changeset 14256:d04ba50e104d

mq: allow to qpop/push with a dirty working copy (issue2780) It's safe to do so if the sets of changed files in the working copy and patches are disjoint.
author Idan Kamara <idankk86@gmail.com>
date Fri, 06 May 2011 19:55:46 +0300
parents 576256a81cb6
children d035ede73434
files hgext/mq.py tests/test-mq-qpush-exact.t tests/test-mq.t
diffstat 3 files changed, 81 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/mq.py	Fri May 06 19:03:41 2011 +0300
+++ b/hgext/mq.py	Fri May 06 19:55:46 2011 +0300
@@ -844,13 +844,16 @@
                 inclsubs.append(s)
         return inclsubs
 
+    def localchangesfound(self, refresh=True):
+        if refresh:
+            raise util.Abort(_("local changes found, refresh first"))
+        else:
+            raise util.Abort(_("local changes found"))
+
     def check_localchanges(self, repo, force=False, refresh=True):
         m, a, r, d = repo.status()[:4]
         if (m or a or r or d) and not force:
-            if refresh:
-                raise util.Abort(_("local changes found, refresh first"))
-            else:
-                raise util.Abort(_("local changes found"))
+            self.localchangesfound(refresh)
         return m, a, r, d
 
     _reserved = ('series', 'status', 'guards', '.', '..')
@@ -1127,8 +1130,6 @@
             if start == len(self.series):
                 self.ui.warn(_('patch series already fully applied\n'))
                 return 1
-            if not force:
-                self.check_localchanges(repo, refresh=self.applied)
 
             if exact:
                 if move:
@@ -1167,6 +1168,19 @@
                 end = self.series.index(patch, start) + 1
 
             s = self.series[start:end]
+
+            if not force:
+                mm, aa, rr, dd = repo.status()[:4]
+                wcfiles = set(mm + aa + rr + dd)
+                if wcfiles:
+                    for patchname in s:
+                        pf = os.path.join(self.path, patchname)
+                        patchfiles = patchmod.changedfiles(pf, strip=1)
+                        if not wcfiles.isdisjoint(patchfiles):
+                            self.localchangesfound(self.applied)
+            elif mergeq:
+                self.check_localchanges(refresh=self.applied)
+
             all_files = set()
             try:
                 if mergeq:
@@ -1247,9 +1261,6 @@
                         break
                 update = needupdate
 
-            if not force and update:
-                self.check_localchanges(repo)
-
             self.applied_dirty = 1
             end = len(self.applied)
             rev = self.applied[start].node
@@ -1272,6 +1283,12 @@
                 qp = self.qparents(repo, rev)
                 ctx = repo[qp]
                 m, a, r, d = repo.status(qp, top)[:4]
+                parentfiles = set(m + a + r + d)
+                if not force and parentfiles:
+                    mm, aa, rr, dd = repo.status()[:4]
+                    wcfiles = set(mm + aa + rr + dd)
+                    if not wcfiles.isdisjoint(parentfiles):
+                        self.localchangesfound()
                 if d:
                     raise util.Abort(_("deletions found between repo revs"))
                 for f in a:
--- a/tests/test-mq-qpush-exact.t	Fri May 06 19:03:41 2011 +0300
+++ b/tests/test-mq-qpush-exact.t	Fri May 06 19:55:46 2011 +0300
@@ -163,8 +163,12 @@
   $ hg update 1 -q
   $ echo c0 >> f0
   $ hg qpush -e
-  abort: local changes found
-  [255]
+  applying p0
+  now at: p0
+  $ cat f0
+  c0
+  $ hg qpop -aq
+  patch queue now empty
   $ hg qpush -ef
   applying p0
   now at: p0
@@ -178,8 +182,13 @@
   $ hg update 1 -q
   $ echo c0 >> f0
   $ hg qpush -e p1
-  abort: local changes found
-  [255]
+  applying p0
+  applying p1
+  now at: p1
+  $ cat f0
+  c0
+  $ hg qpop -aq
+  patch queue now empty
   $ hg qpush -e p1 -f
   applying p0
   applying p1
--- a/tests/test-mq.t	Fri May 06 19:03:41 2011 +0300
+++ b/tests/test-mq.t	Fri May 06 19:55:46 2011 +0300
@@ -1259,6 +1259,47 @@
   now at: changea
   $ cd ..
 
+test qpop with local changes, issue2780
+
+  $ hg init forcepop
+  $ cd forcepop
+  $ echo 1 > 1
+  $ hg ci -Am 1
+  adding 1
+  $ hg qnew foo
+  $ echo 2 > 2
+  $ hg add
+  adding 2
+
+unrelated changes
+
+  $ hg qpop
+  popping foo
+  patch queue now empty
+
+related changes
+
+  $ hg forget 2
+  $ rm 2
+  $ hg qpush
+  applying foo
+  patch foo is empty
+  now at: foo
+  $ echo 2 >> 1
+  $ hg qrefresh
+  $ echo 2 >> 1
+  $ hg qpop
+  abort: local changes found, refresh first
+  [255]
+  $ hg st
+  M 1
+
+related changes with force
+  $ hg qpop --force
+  popping foo
+  patch queue now empty
+  $ hg st
+  $ cd ..
 
 test qpush with --force, issue1087
 
@@ -1276,16 +1317,9 @@
   $ echo world >> hello.txt
 
 
-qpush should fail, local changes
+apply, should not discard changes with empty patch
 
   $ hg qpush
-  abort: local changes found
-  [255]
-
-
-apply force, should not discard changes with empty patch
-
-  $ hg qpush -f
   applying empty
   patch empty is empty
   now at: empty