Merge with crew-stable
authorPatrick Mezard <pmezard@gmail.com>
Fri, 01 Jan 2010 20:52:05 +0100
changeset 10188 fd6e9c7cd98c
parent 10183 572dd10fa308 (current diff)
parent 10186 296a0b14a686 (diff)
child 10189 e451e599fbcf
Merge with crew-stable
hgext/mq.py
tests/test-mq-merge
--- a/hgext/mq.py	Fri Jan 01 18:46:24 2010 +0100
+++ b/hgext/mq.py	Fri Jan 01 20:52: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,26 @@
         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:
+            diffopts = self.patchopts(diffopts, patchfn)
+        return diffopts
+
+    def patchopts(self, diffopts, *patches):
+        """Return a copy of input diff options with git set to true if
+        referenced patch is a git patch.
+        """
+        diffopts = diffopts.copy()
+        for patchfn in patches:
+            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'):
+                    diffopts.git = True
+                    break
+            patchf.close()
+        return diffopts
 
     def join(self, *p):
         return os.path.join(self.path, *p)
@@ -418,24 +433,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)
@@ -464,11 +479,12 @@
         except:
             raise util.Abort(_("unable to read %s") % patch)
 
+        diffopts = self.patchopts(diffopts, patch)
         patchf = self.opener(patch, "w")
         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 +508,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 +538,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 +773,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 +823,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 +947,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 +1010,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 +1153,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:
@@ -1159,6 +1175,7 @@
             cparents = repo.changelog.parents(top)
             patchparent = self.qparents(repo, top)
             ph = patchheader(self.join(patchfn))
+            diffopts = self.diffopts({'git': opts.get('git')}, patchfn)
             if msg:
                 ph.setmessage(msg)
             if newuser:
@@ -1166,14 +1183,6 @@
             if newdate:
                 ph.setdate(newdate)
 
-            # 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'):
-                    self.diffopts().git = True
-                    break
-            patchf.close()
-
             # only commit new patch when write is complete
             patchf = self.opener(patchfn, 'w', atomictemp=True)
 
@@ -1181,8 +1190,6 @@
             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
@@ -1248,12 +1255,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)
@@ -1332,7 +1339,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:
@@ -1612,9 +1619,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)
@@ -1633,7 +1638,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)
@@ -2065,7 +2070,8 @@
     if opts['edit']:
         message = ui.edit(message, user or ui.username())
 
-    q.refresh(repo, msg=message)
+    diffopts = q.patchopts(q.diffopts(), *patches)
+    q.refresh(repo, msg=message, git=diffopts.git)
     q.delete(repo, patches, opts)
     q.save_dirty()
 
--- a/mercurial/mdiff.py	Fri Jan 01 18:46:24 2010 +0100
+++ b/mercurial/mdiff.py	Fri Jan 01 20:52:05 2010 +0100
@@ -55,6 +55,11 @@
             raise util.Abort(_('diff context lines count must be '
                                'an integer, not %r') % self.context)
 
+    def copy(self, **kwargs):
+        opts = dict((k, getattr(self, k)) for k in self.defaults)
+        opts.update(kwargs)
+        return diffopts(**opts)
+
 defaultopts = diffopts()
 
 def wsclean(opts, text, blank=True):
--- a/tests/test-mq-merge	Fri Jan 01 18:46:24 2010 +0100
+++ b/tests/test-mq-merge	Fri Jan 01 20:52:05 2010 +0100
@@ -56,18 +56,27 @@
 echo % init t2
 hg init t2
 cd t2
+echo '[diff]' > .hg/hgrc
+echo 'nodates = 1' >> .hg/hgrc
 echo a > a
 hg ci -Am init
-echo b >> a
+echo b > a
 hg ci -m changea
 hg up -C 0
+hg cp a aa
 echo c >> a
-hg qnew -f -e patcha
+hg qnew --git -f -e patcha
+echo d >> a
+hg qnew -d '0 0' -f -e patcha2
 echo % create the reference queue
 hg qsave -c -e -n refqueue 2> /dev/null
 hg up -C 1
 echo % merge
-hg qpush -m -n refqueue 2>&1 | \
+HGMERGE=internal:other hg qpush -a -m -n refqueue 2>&1 | \
     sed 's/merging with queue at.*refqueue/merging with queue at refqueue/'
+echo % check patcha is still a git patch
+cat .hg/patches/patcha
+echo % check patcha2 is still a regular patch
+grep git .hg/patches/patcha2 && echo 'git patch found!'
 cd ..
 
--- a/tests/test-mq-merge.out	Fri Jan 01 18:46:24 2010 +0100
+++ b/tests/test-mq-merge.out	Fri Jan 01 20:52:05 2010 +0100
@@ -18,8 +18,35 @@
 adding a
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 % create the reference queue
-1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
 % merge
 merging with queue at refqueue
 applying patcha
-now at: patcha
+patching file a
+Hunk #1 FAILED at 0
+1 out of 1 hunks FAILED -- saving rejects to file a.rej
+patch failed, unable to continue (try -v)
+patch failed, rejects left in working dir
+patch didn't work out, merging patcha
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+0 files updated, 2 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+applying patcha2
+now at: patcha2
+% check patcha is still a git patch
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,1 +1,2 @@
+-b
++a
++c
+diff --git a/a b/aa
+copy from a
+copy to aa
+--- a/a
++++ b/aa
+@@ -1,1 +1,1 @@
+-b
++a
+% check patcha2 is still a regular patch
--- a/tests/test-mq-qfold	Fri Jan 01 18:46:24 2010 +0100
+++ b/tests/test-mq-qfold	Fri Jan 01 20:52:05 2010 +0100
@@ -25,12 +25,35 @@
 hg qpop p1
 hg qdiff | filterdiff
 hg qfold p2
+grep git .hg/patches/p1 && echo 'git patch found!'
 hg qser
 hg qdiff | filterdiff
 echo '% fold with local changes'
 echo d >> a
 hg qfold p3
 hg diff -c . | filterdiff
+hg revert -a --no-backup
+
+echo '% fold git patch into a regular patch, expect git patch'
+echo a >> a
+hg qnew -f regular
+hg cp a aa
+hg qnew --git -f git
+hg qpop
+hg qfold git
+cat .hg/patches/regular
+hg qpop
+hg qdel regular
+
+echo '% fold regular patch into a git patch, expect git patch'
+hg cp a aa
+hg qnew --git -f git
+echo b >> aa
+hg qnew -f regular
+hg qpop
+hg qfold regular
+cat .hg/patches/git
+
 cd ..
 
 
--- a/tests/test-mq-qfold.out	Fri Jan 01 18:46:24 2010 +0100
+++ b/tests/test-mq-qfold.out	Fri Jan 01 20:52:05 2010 +0100
@@ -25,3 +25,40 @@
  a
 +a
 +b
+reverting a
+% fold git patch into a regular patch, expect git patch
+popping git
+now at: regular
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,3 +1,4 @@
+ a
+ a
+ b
++a
+diff --git a/a b/aa
+copy from a
+copy to aa
+--- a/a
++++ b/aa
+@@ -1,3 +1,4 @@
+ a
+ a
+ b
++a
+popping regular
+now at: p1
+% fold regular patch into a git patch, expect git patch
+popping regular
+now at: git
+diff --git a/a b/aa
+copy from a
+copy to aa
+--- a/a
++++ b/aa
+@@ -1,3 +1,4 @@
+ a
+ a
+ b
++b