Patchwork [6,of,9] export: serialize revisions to be exported per destination file

login
register
mail settings
Submitter Yuya Nishihara
Date April 12, 2018, 4:17 p.m.
Message ID <724b281e9d9b9ebd91d5.1523549829@mimosa>
Download mbox | patch
Permalink /patch/30812/
State Accepted
Headers show

Comments

Yuya Nishihara - April 12, 2018, 4:17 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1523538535 -32400
#      Thu Apr 12 22:08:55 2018 +0900
# Node ID 724b281e9d9b9ebd91d5ab12482f93a25efb1259
# Parent  97ed426f12977158a72a81e64514aa69a735766b
export: serialize revisions to be exported per destination file

Prepares for porting to the formatter API, where we can't simply append
to existing files because JSON can't be streamed for example.

The modemap hack is removed since cmdutil.export() was the only user.
I also made the destination filename printed only once.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1014,7 +1014,7 @@  class _unclosablefile(object):
     def __exit__(self, exc_type, exc_value, exc_tb):
         pass
 
-def makefileobj(ctx, pat, mode='wb', modemap=None, **props):
+def makefileobj(ctx, pat, mode='wb', **props):
     writable = mode not in ('r', 'rb')
 
     if isstdiofilename(pat):
@@ -1025,10 +1025,6 @@  def makefileobj(ctx, pat, mode='wb', mod
             fp = repo.ui.fin
         return _unclosablefile(fp)
     fn = makefilename(ctx, pat, **props)
-    if modemap is not None:
-        mode = modemap.get(fn, mode)
-        if mode == 'wb':
-            modemap[fn] = 'ab'
     return open(fn, mode)
 
 def openrevlog(repo, cmd, file_, opts):
@@ -1579,18 +1575,23 @@  def _exportfntemplate(repo, revs, fntemp
     """Export changesets to possibly multiple files"""
     total = len(revs)
     revwidth = max(len(str(rev)) for rev in revs)
-    filemode = {}
+    filemap = util.sortdict()  # filename: [(seqno, rev), ...]
 
     for seqno, rev in enumerate(revs, 1):
         ctx = repo[rev]
-        fo = makefileobj(ctx, fntemplate, mode='wb', modemap=filemode,
-                         total=total, seqno=seqno, revwidth=revwidth)
-        dest = fo.name
-        def write(s, **kw):
-            fo.write(s)
-        repo.ui.note("%s\n" % dest)
-        _exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts)
-        fo.close()
+        dest = makefilename(ctx, fntemplate,
+                            total=total, seqno=seqno, revwidth=revwidth)
+        filemap.setdefault(dest, []).append((seqno, rev))
+
+    for dest in filemap:
+        with open(dest, 'wb') as fo:
+            repo.ui.note("%s\n" % dest)
+            def write(s, **kw):
+                fo.write(s)
+            for seqno, rev in filemap[dest]:
+                ctx = repo[rev]
+                _exportsingle(repo, ctx, match, switch_parent, seqno, write,
+                              diffopts)
 
 def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False,
            opts=None, match=None):