changeset 14010:d7b4d421b56c

mq: prevent traceback when qfinish patches not in series. When mq status entry referencing a patches that is not in series `hg qfinish -a` used to issue a traceback. This states is inconsistent but might happen regularly when people misuse hg up -mq. This changeset prevent hg from crashing. The faulty entry is finished anyway and a warning is issued.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Mon, 25 Apr 2011 14:03:12 +0200
parents 64de9ca66511
children b69471bdb678
files hgext/mq.py tests/test-mq-qdelete.t
diffstat 2 files changed, 50 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/mq.py	Mon Apr 25 13:03:26 2011 +0300
+++ b/hgext/mq.py	Mon Apr 25 14:03:12 2011 +0200
@@ -737,11 +737,29 @@
                     os.unlink(self.join(p))
 
         if numrevs:
+            qfinished = self.applied[:numrevs]
             del self.applied[:numrevs]
             self.applied_dirty = 1
 
-        for i in sorted([self.find_series(p) for p in patches], reverse=True):
-            del self.full_series[i]
+        unknown = []
+
+        for (i, p) in sorted([(self.find_series(p), p) for p in patches],
+                             reverse=True):
+            if i is not None:
+                del self.full_series[i]
+            else:
+                unknown.append(p)
+
+        if unknown:
+            if numrevs:
+                rev  = dict((entry.name, entry.node) for entry in qfinished)
+                for p in unknown:
+                    msg = _('revision %s refers to unknown patches: %s\n')
+                    self.ui.warn(msg % (short(rev[p]), p))
+            else:
+                msg = _('unknown patches: %s\n')
+                raise util.Abort(''.join(msg % p for p in unknown))
+
         self.parse_series()
         self.series_dirty = 1
 
--- a/tests/test-mq-qdelete.t	Mon Apr 25 13:03:26 2011 +0300
+++ b/tests/test-mq-qdelete.t	Mon Apr 25 14:03:12 2011 +0200
@@ -162,3 +162,33 @@
   adding 3.diff to series file
   $ hg qfinish -a
   no patches applied
+
+
+resilience to inconsistency: qfinish -a with applied patches not in series
+
+  $ hg qser
+  3.diff
+  $ hg qapplied
+  $ hg qpush
+  applying 3.diff
+  patch 3.diff is empty
+  now at: 3.diff
+  $ echo next >>  base
+  $ hg qrefresh -d '1 0'
+  $ echo > .hg/patches/series # remove 3.diff from series to confuse mq
+  $ hg qfinish -a
+  revision c4dd2b624061 refers to unknown patches: 3.diff
+
+more complex state 'both known and unknown patches
+
+  $ echo hip >>  base
+  $ hg qnew -f -d '1 0' -m 4 4.diff
+  $ echo hop >>  base
+  $ hg qnew -f -d '1 0' -m 5 5.diff
+  $ echo > .hg/patches/series # remove 4.diff and 5.diff from series to confuse mq
+  $ echo hup >>  base
+  $ hg qnew -f -d '1 0' -m 6 6.diff
+  $ hg qfinish -a
+  revision 6fdec4b20ec3 refers to unknown patches: 5.diff
+  revision 2ba51db7ba24 refers to unknown patches: 4.diff
+