patch: turn patch.diff() into a generator
authorDirkjan Ochtman <dirkjan@ochtman.nl>
Mon, 03 Nov 2008 16:48:23 +0100
changeset 7308 b6f5490effbf
parent 7307 56380212d630
child 7309 e74a9173c2d7
patch: turn patch.diff() into a generator This should even be a little faster than passing in an fp argument.
hgext/churn.py
hgext/hgk.py
hgext/keyword.py
hgext/mq.py
hgext/notify.py
hgext/record.py
hgext/transplant.py
mercurial/cmdutil.py
mercurial/commands.py
mercurial/patch.py
--- a/hgext/churn.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/hgext/churn.py	Mon Nov 03 16:48:23 2008 +0100
@@ -44,9 +44,7 @@
 
 def changedlines(ui, repo, ctx1, ctx2):
     lines = 0
-    ui.pushbuffer()
-    patch.diff(repo, ctx1.node(), ctx2.node())
-    diff = ui.popbuffer()
+    diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node()))
     for l in diff.split('\n'):
         if (l.startswith("+") and not l.startswith("+++ ") or
             l.startswith("-") and not l.startswith("--- ")):
--- a/hgext/hgk.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/hgext/hgk.py	Mon Nov 03 16:48:23 2008 +0100
@@ -92,8 +92,10 @@
             if opts['pretty']:
                 catcommit(ui, repo, node2, "")
             m = cmdutil.match(repo, files)
-            patch.diff(repo, node1, node2, match=m,
-                       opts=patch.diffopts(ui, {'git': True}))
+            chunks = patch.diff(repo, node1, node2, match=m,
+                                opts=patch.diffopts(ui, {'git': True}))
+            for chunk in chunks:
+                repo.ui.write(chunk)
         else:
             __difftree(repo, node1, node2, files=files)
         if not opts['stdin']:
--- a/hgext/keyword.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/hgext/keyword.py	Mon Nov 03 16:48:23 2008 +0100
@@ -501,15 +501,15 @@
         # shrink keywords read from working dir
         self.lines = kwt.shrinklines(self.fname, self.lines)
 
-    def kw_diff(orig, repo, node1=None, node2=None, match=None,
-                fp=None, changes=None, opts=None):
+    def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
+                opts=None):
         '''Monkeypatch patch.diff to avoid expansion except when
         comparing against working dir.'''
         if node2 is not None:
             kwt.matcher = util.never
         elif node1 is not None and node1 != repo['.'].node():
             kwt.restrict = True
-        orig(repo, node1, node2, match, fp, changes, opts)
+        return orig(repo, node1, node2, match, changes, opts)
 
     def kwweb_skip(orig, web, req, tmpl):
         '''Wraps webcommands.x turning off keyword expansion.'''
--- a/hgext/mq.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/hgext/mq.py	Mon Nov 03 16:48:23 2008 +0100
@@ -321,7 +321,10 @@
     def printdiff(self, repo, node1, node2=None, files=None,
                   fp=None, changes=None, opts={}):
         m = cmdutil.match(repo, files, opts)
-        patch.diff(repo, node1, node2, m, fp, changes, self.diffopts())
+        chunks = patch.diff(repo, node1, node2, m, changes, self.diffopts())
+        write = fp is None and repo.ui.write or fp.write
+        for chunk in chunks:
+            write(chunk)
 
     def mergeone(self, repo, mergeq, head, patch, rev):
         # first try just applying the patch
@@ -697,8 +700,10 @@
                         diffopts = self.diffopts()
                         if opts.get('git'): diffopts.git = True
                         parent = self.qparents(repo, n)
-                        patch.diff(repo, node1=parent, node2=n, fp=p,
-                                   match=match, opts=diffopts)
+                        chunks = patch.diff(repo, node1=parent, node2=n,
+                                            match=match, opts=diffopts)
+                        for chunk in chunks:
+                            p.write(chunk)
                     p.close()
                     wlock = None
                     r = self.qrepo()
@@ -1139,8 +1144,10 @@
                 a = util.unique(aa)
                 c = [filter(matchfn, l) for l in (m, a, r)]
                 match = cmdutil.matchfiles(repo, util.unique(c[0] + c[1] + c[2]))
-                patch.diff(repo, patchparent, match=match,
-                           fp=patchf, changes=c, opts=self.diffopts())
+                chunks = patch.diff(repo, patchparent, match=match,
+                                    changes=c, opts=self.diffopts())
+                for chunk in chunks:
+                    patchf.write(chunk)
                 patchf.close()
 
                 repo.dirstate.setparents(*cparents)
--- a/hgext/notify.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/hgext/notify.py	Mon Nov 03 16:48:23 2008 +0100
@@ -238,9 +238,8 @@
         maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
         prev = self.repo.changelog.parents(node)[0]
 
-        self.ui.pushbuffer()
-        patch.diff(self.repo, prev, ref, opts=patch.diffopts(self.ui))
-        difflines = self.ui.popbuffer().splitlines()
+        chunks = patch.diff(self.repo, prev, ref, opts=patch.diffopts(self.ui))
+        difflines = ''.join(chunks).splitlines()
 
         if self.ui.configbool('notify', 'diffstat', True):
             s = patch.diffstat(difflines)
--- a/hgext/record.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/hgext/record.py	Mon Nov 03 16:48:23 2008 +0100
@@ -413,9 +413,10 @@
             modified, added, removed = changes
             match = cmdutil.matchfiles(repo, modified + added + removed)
         diffopts = mdiff.diffopts(git=True, nodates=True)
+        chunks = patch.diff(repo, repo.dirstate.parents()[0], match=match,
+                            changes=changes, opts=diffopts)
         fp = cStringIO.StringIO()
-        patch.diff(repo, repo.dirstate.parents()[0], match=match,
-                   changes=changes, opts=diffopts, fp=fp)
+        fp.write(''.join(chunks))
         fp.seek(0)
 
         # 1. filter patch, so we have intending-to apply subset of it
--- a/hgext/transplant.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/hgext/transplant.py	Mon Nov 03 16:48:23 2008 +0100
@@ -138,7 +138,9 @@
                 else:
                     fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-')
                     fp = os.fdopen(fd, 'w')
-                    patch.diff(source, parents[0], node, fp=fp, opts=diffopts)
+                    gen = patch.diff(source, parents[0], node, opts=diffopts)
+                    for chunk in gen:
+                        fp.write(chunk)
                     fp.close()
 
                 del revmap[rev]
@@ -405,7 +407,8 @@
                 action = None
             elif action == 'p':
                 parent = repo.changelog.parents(node)[0]
-                patch.diff(repo, parent, node)
+                for chunk in patch.diff(repo, parent, node):
+                    repo.ui.write(chunk)
                 action = None
             elif action not in ('y', 'n', 'm', 'c', 'q'):
                 ui.write('no such option\n')
--- a/mercurial/cmdutil.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/mercurial/cmdutil.py	Mon Nov 03 16:48:23 2008 +0100
@@ -673,8 +673,10 @@
     def showpatch(self, node):
         if self.patch:
             prev = self.repo.changelog.parents(node)[0]
-            patch.diff(self.repo, prev, node, match=self.patch, fp=self.ui,
-                       opts=patch.diffopts(self.ui))
+            chunks = patch.diff(self.repo, prev, node, match=self.patch,
+                                opts=patch.diffopts(self.ui))
+            for chunk in chunks:
+                self.ui.write(chunk)
             self.ui.write("\n")
 
     def _meaningful_parentrevs(self, log, rev):
--- a/mercurial/commands.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/mercurial/commands.py	Mon Nov 03 16:48:23 2008 +0100
@@ -1010,7 +1010,9 @@
     node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
 
     m = cmdutil.match(repo, pats, opts)
-    patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
+    it = patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
+    for chunk in it:
+        repo.ui.write(chunk)
 
 def export(ui, repo, *changesets, **opts):
     """dump the header and diffs for one or more changesets
--- a/mercurial/patch.py	Mon Nov 03 16:31:47 2008 +0100
+++ b/mercurial/patch.py	Mon Nov 03 16:48:23 2008 +0100
@@ -1169,9 +1169,8 @@
         header.append('old mode %s\n' % omode)
         header.append('new mode %s\n' % nmode)
 
-def diff(repo, node1=None, node2=None, match=None,
-         fp=None, changes=None, opts=None):
-    '''print diff of changes to files between two nodes, or node and
+def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None):
+    '''yields diff of changes to files between two nodes, or node and
     working directory.
 
     if node1 is None, use first dirstate parent instead.
@@ -1182,8 +1181,6 @@
 
     if opts is None:
         opts = mdiff.defaultopts
-    if fp is None:
-        fp = repo.ui
 
     if not node1:
         node1 = repo.dirstate.parents()[0]
@@ -1274,9 +1271,10 @@
                                     # ctx2 date may be dynamic
                                     tn, util.datestr(ctx2.date()),
                                     a, b, r, opts=opts)
-            if text or len(header) > 1:
-                fp.write(''.join(header))
-            fp.write(text)
+            if header and (text or len(header) > 1):
+                yield ''.join(header)
+            if text:
+                yield text
 
 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
            opts=None):
@@ -1312,7 +1310,8 @@
         fp.write(ctx.description().rstrip())
         fp.write("\n\n")
 
-        diff(repo, prev, node, fp=fp, opts=opts)
+        for chunk in diff(repo, prev, node, opts=opts):
+            fp.write(chunk)
         if fp not in (sys.stdout, repo.ui):
             fp.close()