export: enable formatter support (API)
authorYuya Nishihara <yuya@tcha.org>
Thu, 12 Apr 2018 23:13:55 +0900
changeset 37604 daafaff4e5be
parent 37603 678d760c71ff
child 37605 74e1362585c0
export: enable formatter support (API) This change is basically the same as "hg cat". A formatter object is created by caller. .. api:: ``cmdutil.export()`` takes a formatter as an argument.
hgext/extdiff.py
mercurial/cmdutil.py
mercurial/commands.py
tests/test-completion.t
tests/test-export.t
--- a/hgext/extdiff.py	Thu Apr 12 22:59:49 2018 +0900
+++ b/hgext/extdiff.py	Thu Apr 12 23:13:55 2018 +0900
@@ -82,6 +82,7 @@
     cmdutil,
     error,
     filemerge,
+    formatter,
     pycompat,
     registrar,
     scmutil,
@@ -267,9 +268,11 @@
                 label2 = common_file + rev2
         else:
             template = 'hg-%h.patch'
-            cmdutil.export(repo, [repo[node1a].rev(), repo[node2].rev()],
-                           fntemplate=repo.vfs.reljoin(tmproot, template),
-                           match=matcher)
+            with formatter.nullformatter(ui, 'extdiff', {}) as fm:
+                cmdutil.export(repo, [repo[node1a].rev(), repo[node2].rev()],
+                               fm,
+                               fntemplate=repo.vfs.reljoin(tmproot, template),
+                               match=matcher)
             label1a = cmdutil.makefilename(repo[node1a], template)
             label2 = cmdutil.makefilename(repo[node2], template)
             dir1a = repo.vfs.reljoin(tmproot, label1a)
--- a/mercurial/cmdutil.py	Thu Apr 12 22:59:49 2018 +0900
+++ b/mercurial/cmdutil.py	Thu Apr 12 23:13:55 2018 +0900
@@ -1565,24 +1565,17 @@
         # TODO: make it structured?
         fm.data(diff=b''.join(chunkiter))
 
-def _exportfile(repo, revs, fp, switch_parent, diffopts, match):
+def _exportfile(repo, revs, fm, dest, switch_parent, diffopts, match):
     """Export changesets to stdout or a single file"""
-    dest = '<unnamed>'
-    if fp:
-        dest = getattr(fp, 'name', dest)
-        fm = formatter.formatter(repo.ui, fp, 'export', {})
-    else:
-        fm = repo.ui.formatter('export', {})
-
     for seqno, rev in enumerate(revs, 1):
         ctx = repo[rev]
         if not dest.startswith('<'):
             repo.ui.note("%s\n" % dest)
         fm.startitem()
         _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts)
-    fm.end()
-
-def _exportfntemplate(repo, revs, fntemplate, switch_parent, diffopts, match):
+
+def _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, diffopts,
+                      match):
     """Export changesets to possibly multiple files"""
     total = len(revs)
     revwidth = max(len(str(rev)) for rev in revs)
@@ -1595,7 +1588,7 @@
         filemap.setdefault(dest, []).append((seqno, rev))
 
     for dest in filemap:
-        with formatter.openformatter(repo.ui, dest, 'export', {}) as fm:
+        with formatter.maybereopen(basefm, dest) as fm:
             repo.ui.note("%s\n" % dest)
             for seqno, rev in filemap[dest]:
                 fm.startitem()
@@ -1603,13 +1596,14 @@
                 _exportsingle(repo, ctx, fm, match, switch_parent, seqno,
                               diffopts)
 
-def export(repo, revs, fntemplate='hg-%h.patch', switch_parent=False,
+def export(repo, revs, basefm, fntemplate='hg-%h.patch', switch_parent=False,
            opts=None, match=None):
     '''export changesets as hg patches
 
     Args:
       repo: The repository from which we're exporting revisions.
       revs: A list of revisions to export as revision numbers.
+      basefm: A formatter to which patches should be written.
       fntemplate: An optional string to use for generating patch file names.
       switch_parent: If True, show diffs against second parent when not nullid.
                      Default is false, which always shows diff against p1.
@@ -1624,16 +1618,19 @@
       destinations:
         fntemplate specified: Each rev is written to a unique file named using
                             the given template.
-        Otherwise: All revs written to repo.ui.write()
+        Otherwise: All revs will be written to basefm.
     '''
     if not fntemplate:
-        _exportfile(repo, revs, None, switch_parent, opts, match)
+        _exportfile(repo, revs, basefm, '<unnamed>', switch_parent, opts, match)
     else:
-        _exportfntemplate(repo, revs, fntemplate, switch_parent, opts, match)
+        _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, opts,
+                          match)
 
 def exportfile(repo, revs, fp, switch_parent=False, opts=None, match=None):
     """Export changesets to the given file stream"""
-    _exportfile(repo, revs, fp, switch_parent, opts, match)
+    dest = getattr(fp, 'name', '<unnamed>')
+    with formatter.formatter(repo.ui, fp, 'export', {}) as fm:
+        _exportfile(repo, revs, fm, dest, switch_parent, opts, match)
 
 def showmarker(fm, marker, index=None):
     """utility function to display obsolescence marker in a readable way
--- a/mercurial/commands.py	Thu Apr 12 22:59:49 2018 +0900
+++ b/mercurial/commands.py	Thu Apr 12 23:13:55 2018 +0900
@@ -1894,7 +1894,7 @@
      _('print output to file with formatted name'), _('FORMAT')),
     ('', 'switch-parent', None, _('diff against the second parent')),
     ('r', 'rev', [], _('revisions to export'), _('REV')),
-    ] + diffopts,
+    ] + diffopts + formatteropts,
     _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
 def export(ui, repo, *changesets, **opts):
     """dump the header and diffs for one or more changesets
@@ -1976,11 +1976,15 @@
     if cmdutil.isstdiofilename(fntemplate):
         fntemplate = ''
 
-    if not fntemplate:
+    if fntemplate:
+        fm = formatter.nullformatter(ui, 'export', opts)
+    else:
         ui.pager('export')
-    cmdutil.export(repo, revs, fntemplate=fntemplate,
-                 switch_parent=opts.get('switch_parent'),
-                 opts=patch.diffallopts(ui, opts))
+        fm = ui.formatter('export', opts)
+    with fm:
+        cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
+                       switch_parent=opts.get('switch_parent'),
+                       opts=patch.diffallopts(ui, opts))
 
 @command('files',
     [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
--- a/tests/test-completion.t	Thu Apr 12 22:59:49 2018 +0900
+++ b/tests/test-completion.t	Thu Apr 12 23:13:55 2018 +0900
@@ -231,7 +231,7 @@
   clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
   commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
   diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
-  export: output, switch-parent, rev, text, git, binary, nodates
+  export: output, switch-parent, rev, text, git, binary, nodates, template
   forget: include, exclude, dry-run
   init: ssh, remotecmd, insecure
   log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
--- a/tests/test-export.t	Thu Apr 12 22:59:49 2018 +0900
+++ b/tests/test-export.t	Thu Apr 12 23:13:55 2018 +0900
@@ -159,6 +159,85 @@
   +foo-wdir
   $ hg revert -q foo
 
+Templated output to stdout:
+
+  $ hg export -Tjson 0
+  [
+   {
+    "branch": "default",
+    "date": [0.0, 0],
+    "desc": "foo-0",
+    "diff": "diff -r 000000000000 -r 871558de6af2 foo\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/foo\tThu Jan 01 00:00:00 1970 +0000\n@@ -0,0 +1,1 @@\n+foo-0\n",
+    "node": "871558de6af2e8c244222f8eea69b782c94ce3df",
+    "parents": [],
+    "user": "test"
+   }
+  ]
+
+Templated output to single file:
+
+  $ hg export -Tjson 0:1 -o out.json
+  $ cat out.json
+  [
+   {
+    "branch": "default",
+    "date": [0.0, 0],
+    "desc": "foo-0",
+    "diff": "diff -r 000000000000 -r 871558de6af2 foo\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/foo\tThu Jan 01 00:00:00 1970 +0000\n@@ -0,0 +1,1 @@\n+foo-0\n",
+    "node": "871558de6af2e8c244222f8eea69b782c94ce3df",
+    "parents": [],
+    "user": "test"
+   },
+   {
+    "branch": "default",
+    "date": [0.0, 0],
+    "desc": "foo-1",
+    "diff": "diff -r 871558de6af2 -r d1c9656e973c foo\n--- a/foo\tThu Jan 01 00:00:00 1970 +0000\n+++ b/foo\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +1,2 @@\n foo-0\n+foo-1\n",
+    "node": "d1c9656e973cfb5aebd5499bbd2cb350e3b12266",
+    "parents": ["871558de6af2e8c244222f8eea69b782c94ce3df"],
+    "user": "test"
+   }
+  ]
+
+Templated output to multiple files:
+
+  $ hg export -Tjson 0:1 -o 'out-{rev}.json'
+  $ cat out-0.json
+  [
+   {
+    "branch": "default",
+    "date": [0.0, 0],
+    "desc": "foo-0",
+    "diff": "diff -r 000000000000 -r 871558de6af2 foo\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/foo\tThu Jan 01 00:00:00 1970 +0000\n@@ -0,0 +1,1 @@\n+foo-0\n",
+    "node": "871558de6af2e8c244222f8eea69b782c94ce3df",
+    "parents": [],
+    "user": "test"
+   }
+  ]
+  $ cat out-1.json
+  [
+   {
+    "branch": "default",
+    "date": [0.0, 0],
+    "desc": "foo-1",
+    "diff": "diff -r 871558de6af2 -r d1c9656e973c foo\n--- a/foo\tThu Jan 01 00:00:00 1970 +0000\n+++ b/foo\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +1,2 @@\n foo-0\n+foo-1\n",
+    "node": "d1c9656e973cfb5aebd5499bbd2cb350e3b12266",
+    "parents": ["871558de6af2e8c244222f8eea69b782c94ce3df"],
+    "user": "test"
+   }
+  ]
+
+Template keywrods:
+
+  $ hg export 0 -T '# {node|shortest}\n\n{diff}'
+  # 8715
+  
+  diff -r 000000000000 -r 871558de6af2 foo
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +foo-0
+
 No filename should be printed if stdout is specified explicitly:
 
   $ hg export -v 1 -o -