mq: pop/refresh: avoid losing revisions not managed by mq
authorAlexis S. L. Carvalho <alexis@cecm.usp.br>
Sun, 03 Feb 2008 21:03:46 -0200
changeset 5980 dcda0c90125c
parent 5979 b4858eb4b58f
child 5981 ca2af0c81c9a
mq: pop/refresh: avoid losing revisions not managed by mq We already disallow committing on top of an mq revision exactly to avoid losing this new revision during a qpop/qrefresh, so this can be seen as an additional safety check. If this is not enough to fix issue844, it should at least prevent it from happening.
hgext/mq.py
tests/test-mq-safety
tests/test-mq-safety.out
--- a/hgext/mq.py	Sun Feb 03 21:03:46 2008 -0200
+++ b/hgext/mq.py	Sun Feb 03 21:03:46 2008 -0200
@@ -861,10 +861,16 @@
             start = info[0]
             rev = revlog.bin(info[1])
 
+            if update:
+                top = self.check_toppatch(repo)
+
+            if repo.changelog.heads(rev) != [revlog.bin(self.applied[-1].rev)]:
+                raise util.Abort("popping would remove a revision not "
+                                 "managed by this patch queue")
+
             # we know there are no local changes, so we can make a simplified
             # form of hg.update.
             if update:
-                top = self.check_toppatch(repo)
                 qp = self.qparents(repo, rev)
                 changes = repo.changelog.read(qp)
                 mmap = repo.manifest.read(changes[0])
@@ -915,6 +921,8 @@
             self.check_toppatch(repo)
             (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
             top = revlog.bin(top)
+            if repo.changelog.heads(top) != [top]:
+                raise util.Abort("cannot refresh a revision with children")
             cparents = repo.changelog.parents(top)
             patchparent = self.qparents(repo, top)
             message, comments, user, date, patchfound = self.readheaders(patchfn)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mq-safety	Sun Feb 03 21:03:46 2008 -0200
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+echo '[extensions]' >> $HGRCPATH
+echo 'hgext.mq =' >> $HGRCPATH
+
+hg init repo
+cd repo
+
+echo foo > foo
+hg ci -qAm 'add a file'
+
+hg qinit
+
+hg qnew foo
+echo foo >> foo
+hg qrefresh -m 'append foo'
+
+hg qnew bar
+echo bar >> foo
+hg qrefresh -m 'append bar'
+
+echo '% try to commit on top of a patch'
+echo quux >> foo
+hg ci -m 'append quux'
+
+# cheat a bit...
+mv .hg/patches .hg/patches2
+hg ci -m 'append quux'
+mv .hg/patches2 .hg/patches
+
+echo '% qpop/qrefresh on the wrong revision'
+hg qpop
+hg qpop -n patches 2>&1 | sed -e 's/\(using patch queue:\).*/\1/'
+hg qrefresh
+
+hg up -C qtip
+echo '% qpop'
+hg qpop
+
+echo '% qrefresh'
+hg qrefresh
+
+echo '% tip:'
+hg tip --template '#rev# #desc#\n'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mq-safety.out	Sun Feb 03 21:03:46 2008 -0200
@@ -0,0 +1,14 @@
+% try to commit on top of a patch
+abort: cannot commit over an applied mq patch
+% qpop/qrefresh on the wrong revision
+abort: working directory revision is not qtip
+using patch queue:
+abort: popping would remove a revision not managed by this patch queue
+abort: working directory revision is not qtip
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% qpop
+abort: popping would remove a revision not managed by this patch queue
+% qrefresh
+abort: cannot refresh a revision with children
+% tip:
+3 append quux