D3174: cmdutil: refactor I/O for exporting
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Fri Apr 6 22:10:49 UTC 2018
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
Using generators for feeding chunks into I/O is more flexible than
passing a file object or write function around.
This commit refactors the patch exporting code to emit a series a data
chunks instead of doing push-based I/O. As a side-effect, we could now
obtain the patch representation of a changeset without having to use
a file object. Yay!
Code around the management of the file handles has also been cleaned up
a bit.
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D3174
AFFECTED FILES
mercurial/cmdutil.py
CHANGE DETAILS
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1526,7 +1526,7 @@
# it is given two arguments (sequencenumber, changectx)
extraexportmap = {}
-def _exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts):
+def _exportsingle(repo, ctx, match, switch_parent, seqno, diffopts):
node = scmutil.binnode(ctx)
parents = [p.node() for p in ctx.parents() if p]
branch = ctx.branch()
@@ -1538,26 +1538,26 @@
else:
prev = nullid
- write("# HG changeset patch\n")
- write("# User %s\n" % ctx.user())
- write("# Date %d %d\n" % ctx.date())
- write("# %s\n" % dateutil.datestr(ctx.date()))
+ yield "# HG changeset patch\n", None
+ yield "# User %s\n" % ctx.user(), None
+ yield "# Date %d %d\n" % ctx.date(), None
+ yield "# %s\n" % dateutil.datestr(ctx.date()), None
if branch and branch != 'default':
- write("# Branch %s\n" % branch)
- write("# Node ID %s\n" % hex(node))
- write("# Parent %s\n" % hex(prev))
+ yield "# Branch %s\n" % branch, None
+ yield "# Node ID %s\n" % hex(node), None
+ yield "# Parent %s\n" % hex(prev), None
if len(parents) > 1:
- write("# Parent %s\n" % hex(parents[1]))
+ yield "# Parent %s\n" % hex(parents[1]), None
for headerid in extraexport:
header = extraexportmap[headerid](seqno, ctx)
if header is not None:
- write('# %s\n' % header)
- write(ctx.description().rstrip())
- write("\n\n")
+ yield '# %s\n' % header, None
+ yield ctx.description().rstrip(), None
+ yield "\n\n", None
for chunk, label in patch.diffui(repo, prev, node, match, opts=diffopts):
- write(chunk, label=label)
+ yield chunk, label
def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False,
opts=None, match=None):
@@ -1590,30 +1590,40 @@
revwidth = max(len(str(rev)) for rev in revs)
filemode = {}
- write = None
dest = '<unnamed>'
if fp:
+ allfp = fp
dest = getattr(fp, 'name', dest)
- def write(s, **kw):
- fp.write(s)
+ supportslabel = False
elif not fntemplate:
- write = repo.ui.write
+ allfp = repo.ui
+ supportslabel = True
+ else:
+ allfp = None
+ supportslabel = False
+
+ def doexport(ctx, fp, dest):
+ if not dest.startswith('<'):
+ repo.ui.note('%s\n' % dest)
+
+ for s, label in _exportsingle(repo, ctx, match, switch_parent, seqno,
+ opts):
+ if supportslabel and label:
+ fp.write(s, label=label)
+ else:
+ fp.write(s)
for seqno, rev in enumerate(revs, 1):
ctx = repo[rev]
- fo = None
- if not fp and fntemplate:
- fo = makefileobj(ctx, fntemplate, mode='wb', modemap=filemode,
- total=total, seqno=seqno, revwidth=revwidth)
- dest = fo.name
- def write(s, **kw):
- fo.write(s)
- if not dest.startswith('<'):
- repo.ui.note("%s\n" % dest)
- _exportsingle(
- repo, ctx, match, switch_parent, seqno, write, opts)
- if fo is not None:
- fo.close()
+
+ if not allfp:
+ assert fntemplate
+
+ with makefileobj(ctx, fntemplate, mode='wb', modemap=filemode,
+ total=total, seqno=seqno, revwidth=revwidth) as fp:
+ doexport(ctx, fp, fp.name)
+ else:
+ doexport(ctx, allfp, dest)
def showmarker(fm, marker, index=None):
"""utility function to display obsolescence marker in a readable way
To: indygreg, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list