changeset 10184:8a47347d298b stable

mq: stop caching and sharing diff options Several mq commands mutate the shared options which causes hard to track bugs when multiple calls are combined.
author Patrick Mezard <pmezard@gmail.com>
date Fri, 01 Jan 2010 19:53:05 +0100
parents 83cfa1baf8ad
children 7637fe4f525d
files hgext/mq.py
diffstat 1 files changed, 28 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/mq.py	Fri Jan 01 13:58:30 2010 +0100
+++ b/hgext/mq.py	Fri Jan 01 19:53:05 2010 +0100
@@ -225,7 +225,6 @@
         self.guards_path = "guards"
         self.active_guards = None
         self.guards_dirty = False
-        self._diffopts = None
 
     @util.propertycache
     def applied(self):
@@ -259,10 +258,16 @@
         self.guards_dirty = False
         self.active_guards = None
 
-    def diffopts(self):
-        if self._diffopts is None:
-            self._diffopts = patch.diffopts(self.ui)
-        return self._diffopts
+    def diffopts(self, opts={}, patchfn=None):
+        diffopts = patch.diffopts(self.ui, opts)
+        if patchfn:
+            # if the patch was a git patch, refresh it as a git patch
+            patchf = self.opener(patchfn, 'r')
+            for line in patchf:
+                if line.startswith('diff --git'):
+                    diffopts.git = True
+                    break
+        return diffopts
 
     def join(self, *p):
         return os.path.join(self.path, *p)
@@ -418,24 +423,24 @@
         except OSError, inst:
             self.ui.warn(_('error removing undo: %s\n') % str(inst))
 
-    def printdiff(self, repo, node1, node2=None, files=None,
+    def printdiff(self, repo, diffopts, node1, node2=None, files=None,
                   fp=None, changes=None, opts={}):
         stat = opts.get('stat')
         if stat:
             opts['unified'] = '0'
 
         m = cmdutil.match(repo, files, opts)
-        chunks = patch.diff(repo, node1, node2, m, changes, self.diffopts())
+        chunks = patch.diff(repo, node1, node2, m, changes, diffopts)
         write = fp is None and repo.ui.write or fp.write
         if stat:
             width = self.ui.interactive() and util.termwidth() or 80
             write(patch.diffstat(util.iterlines(chunks), width=width,
-                                 git=self.diffopts().git))
+                                 git=diffopts.git))
         else:
             for chunk in chunks:
                 write(chunk)
 
-    def mergeone(self, repo, mergeq, head, patch, rev):
+    def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
         # first try just applying the patch
         (err, n) = self.apply(repo, [ patch ], update_status=False,
                               strict=True, merge=rev)
@@ -468,7 +473,7 @@
         comments = str(ph)
         if comments:
             patchf.write(comments)
-        self.printdiff(repo, head, n, fp=patchf)
+        self.printdiff(repo, diffopts, head, n, fp=patchf)
         patchf.close()
         self.removeundo(repo)
         return (0, n)
@@ -492,7 +497,7 @@
                 return pp[1]
         return pp[0]
 
-    def mergepatch(self, repo, mergeq, series):
+    def mergepatch(self, repo, mergeq, series, diffopts):
         if len(self.applied) == 0:
             # each of the patches merged in will have two parents.  This
             # can confuse the qrefresh, qdiff, and strip code because it
@@ -522,7 +527,7 @@
                 self.ui.warn(_("patch %s is not applied\n") % patch)
                 return (1, None)
             rev = bin(info[1])
-            (err, head) = self.mergeone(repo, mergeq, head, patch, rev)
+            err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts)
             if head:
                 self.applied.append(statusentry(hex(head), patch))
                 self.applied_dirty = 1
@@ -757,6 +762,7 @@
         date = opts.get('date')
         if date:
             date = util.parsedate(date)
+        diffopts = self.diffopts({'git': opts.get('git')})
         self.check_reserved_name(patchfn)
         if os.path.exists(self.join(patchfn)):
             raise util.Abort(_('patch "%s" already exists') % patchfn)
@@ -806,8 +812,6 @@
                         msg = msg + "\n\n"
                         p.write(msg)
                     if commitfiles:
-                        diffopts = self.diffopts()
-                        if opts.get('git'): diffopts.git = True
                         parent = self.qparents(repo, n)
                         chunks = patch.diff(repo, node1=parent, node2=n,
                                             match=match, opts=diffopts)
@@ -932,6 +936,7 @@
 
     def push(self, repo, patch=None, force=False, list=False,
              mergeq=None, all=False):
+        diffopts = self.diffopts()
         wlock = repo.wlock()
         try:
             if repo.dirstate.parents()[0] not in repo.heads():
@@ -994,7 +999,7 @@
             all_files = {}
             try:
                 if mergeq:
-                    ret = self.mergepatch(repo, mergeq, s)
+                    ret = self.mergepatch(repo, mergeq, s, diffopts)
                 else:
                     ret = self.apply(repo, s, list, all_files=all_files)
             except:
@@ -1137,8 +1142,8 @@
             node1, node2 = None, qp
         else:
             node1, node2 = qp, None
-        self._diffopts = patch.diffopts(self.ui, opts)
-        self.printdiff(repo, node1, node2, files=pats, opts=opts)
+        diffopts = self.diffopts(opts)
+        self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts)
 
     def refresh(self, repo, pats=None, **opts):
         if len(self.applied) == 0:
@@ -1160,14 +1165,7 @@
             patchparent = self.qparents(repo, top)
             ph = patchheader(self.join(patchfn))
 
-            patchf = self.opener(patchfn, 'r')
-
-            # if the patch was a git patch, refresh it as a git patch
-            for line in patchf:
-                if line.startswith('diff --git'):
-                    self.diffopts().git = True
-                    break
-
+            diffopts = self.diffopts({'git': opts.get('git')}, patchfn)
             if msg:
                 ph.setmessage(msg)
             if newuser:
@@ -1178,15 +1176,10 @@
             # only commit new patch when write is complete
             patchf = self.opener(patchfn, 'w', atomictemp=True)
 
-            patchf.seek(0)
-            patchf.truncate()
-
             comments = str(ph)
             if comments:
                 patchf.write(comments)
 
-            if opts.get('git'):
-                self.diffopts().git = True
             tip = repo.changelog.tip()
             if top == tip:
                 # if the top of our patch queue is also the tip, there is an
@@ -1252,12 +1245,12 @@
                 c = [filter(matchfn, l) for l in (m, a, r)]
                 match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2]))
                 chunks = patch.diff(repo, patchparent, match=match,
-                                    changes=c, opts=self.diffopts())
+                                    changes=c, opts=diffopts)
                 for chunk in chunks:
                     patchf.write(chunk)
 
                 try:
-                    if self.diffopts().git:
+                    if diffopts.git:
                         copies = {}
                         for dst in a:
                             src = repo.dirstate.copied(dst)
@@ -1336,7 +1329,7 @@
                                    '(revert --all, qpush to recover)\n'))
                     raise
             else:
-                self.printdiff(repo, patchparent, fp=patchf)
+                self.printdiff(repo, diffopts, patchparent, fp=patchf)
                 patchf.rename()
                 added = repo.status()[1]
                 for a in added:
@@ -1616,9 +1609,7 @@
                                      % rev[0])
                 lastparent = None
 
-            if git:
-                self.diffopts().git = True
-
+            diffopts = self.diffopts({'git': git})
             for r in rev:
                 p1, p2 = repo.changelog.parentrevs(r)
                 n = repo.changelog.node(r)
@@ -1637,7 +1628,7 @@
                 self.full_series.insert(0, patchname)
 
                 patchf = self.opener(patchname, "w")
-                patch.export(repo, [n], fp=patchf, opts=self.diffopts())
+                patch.export(repo, [n], fp=patchf, opts=diffopts)
                 patchf.close()
 
                 se = statusentry(hex(n), patchname)