[PATCH 2 of 2] rollback: only restore dirstate (et. al.) when appropriate
Greg Ward
greg-hg at gerg.ca
Thu Sep 15 21:22:10 CDT 2011
# HG changeset patch
# User Greg Ward <greg at gerg.ca>
# Date 1316139696 14400
# Node ID b33ba776a9977a4b1460eebb5acd9dc954da03c5
# Parent 23fe96275fabc99c33f61da305f81948ea5c61df
rollback: only restore dirstate (et. al.) when appropriate.
If the working dir parent is not one of the changesets slated for
destruction, then this rollback should not affect the working dir:
that means do not restore dirstate, branch, or bookmarks.
This is very preliminary, just posted for initial review. Some tests
still fail.
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -769,33 +769,49 @@
def _rollback(self, dryrun):
try:
- args = self.opener.read("undo.desc").splitlines()
- if len(args) >= 3 and self.ui.verbose:
- desc = _("repository tip rolled back to revision %s"
- " (undo %s: %s)\n") % (
- int(args[0]) - 1, args[1], args[2])
+ args = self.opener.read('undo.desc').splitlines()
+ if len(args) >= 3:
+ (oldlen, desc, detail) = args
elif len(args) >= 2:
- desc = _("repository tip rolled back to revision %s"
- " (undo %s)\n") % (
- int(args[0]) - 1, args[1])
+ (oldlen, desc) = args
+ detail = None
+ oldlen = int(oldlen)
+ oldtip = oldlen - 1
+ doomed = range(oldlen, len(self))
+
+ if detail and self.ui.verbose:
+ msg = (_('repository tip rolled back to revision %s'
+ ' (undo %s: %s)\n')
+ % (oldtip, desc, detail))
+ else:
+ msg = (_('repository tip rolled back to revision %s'
+ ' (undo %s)\n')
+ % (oldtip, desc))
except IOError:
- desc = _("rolling back unknown transaction\n")
- self.ui.status(desc)
+ doomed = None # not enough info
+ msg = _('rolling back unknown transaction\n')
+ self.ui.status(msg)
if dryrun:
return 0
+
+ parents = map(self.changelog.rev, self.dirstate.parents())
+ affectswdir = (doomed is not None and
+ (parents[0] in doomed or parents[1] in doomed))
transaction.rollback(self.sopener, self.sjoin("undo"),
self.ui.warn)
- util.rename(self.join("undo.dirstate"), self.join("dirstate"))
- if os.path.exists(self.join('undo.bookmarks')):
- util.rename(self.join('undo.bookmarks'),
- self.join('bookmarks'))
- try:
- branch = self.opener.read("undo.branch")
- self.dirstate.setbranch(branch)
- except IOError:
- self.ui.warn(_("named branch could not be reset, "
- "current branch is still: %s\n")
- % self.dirstate.branch())
+ if affectswdir:
+ util.rename(self.join('undo.dirstate'), self.join('dirstate'))
+ if os.path.exists(self.join('undo.bookmarks')):
+ util.rename(self.join('undo.bookmarks'),
+ self.join('bookmarks'))
+ try:
+ branch = self.opener.read('undo.branch')
+ self.dirstate.setbranch(branch)
+ except IOError:
+ self.ui.warn(_('named branch could not be reset, '
+ 'current branch is still: %s\n')
+ % self.dirstate.branch())
+
self.invalidate()
self.dirstate.invalidate()
self.destroyed()
diff --git a/tests/test-rollback.t b/tests/test-rollback.t
--- a/tests/test-rollback.t
+++ b/tests/test-rollback.t
@@ -64,6 +64,37 @@
$ hg branch
test
+do not restore dirstate, branch when we don't need to
+ $ hg log --template '{rev} {branch} {desc|firstline}\n'
+ 0 default add a again
+ $ hg status
+ M a
+ $ hg commit -m'modify a again'
+ $ echo b > b
+ $ hg commit -Am'add b'
+ adding b
+ $ hg log --template '{rev} {branch} {desc|firstline}\n'
+ 2 test add b
+ 1 test modify a again
+ 0 default add a again
+ $ hg update default
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ cat .hg/undo.branch ; echo
+ test
+ $ hg rollback
+ repository tip rolled back to revision 1 (undo commit)
+ working directory now based on revision 0
+ $ hg id -n
+ 0
+ $ hg branch
+ default
+
+# commented out because this bug is still there: I don't want anyone
+# to think that this is desirable behaviour!
+#oops: file b is irretrievably lost (issue 2998)
+# $ hg status
+# $ find . -name b -o -name 'b.[id]'
+
rollback by pretxncommit saves commit message (issue 1635)
$ echo a >> a
@@ -102,12 +133,12 @@
adding changesets
adding manifests
adding file changes
- added 2 changesets with 2 changes to 1 files
+ added 3 changesets with 2 changes to 1 files (+1 heads)
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd u
$ hg id default
- 8902593132ae
+ 068774709090
now rollback and observe that 'hg serve' reloads the repository and
presents the correct tip changeset:
More information about the Mercurial-devel
mailing list