revert added and removed files to their normal state before reverting
add a test for revert
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1824,6 +1824,10 @@ def revert(ui, repo, *names, **opts):
chosen[relname] = 1
return ret
+ (c, a, d, u) = repo.changes()
+ repo.forget(filter(choose, a))
+ repo.undelete(filter(choose, d))
+
r = repo.update(node, False, True, choose, False)
for n in relnames:
if n not in chosen:
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -555,6 +555,30 @@ class localrepository:
else:
self.dirstate.update([f], "r")
+ def undelete(self, list):
+ pl = self.dirstate.parents()
+ if pl[1] != nullid:
+ self.ui.warn("aborting: outstanding uncommitted merges\n")
+ return 1
+ p = pl[0]
+ mn = self.changelog.read(p)[0]
+ mf = self.manifest.readflags(mn)
+ m = self.manifest.read(mn)
+ for f in list:
+ if self.dirstate.state(f) not in "r":
+ self.ui.warn("%s not removed!\n" % f)
+ else:
+ t = self.file(f).read(m[f])
+ try:
+ self.wwrite(f, t)
+ except IOError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ os.makedirs(os.path.dirname(self.wjoin(f)))
+ self.wwrite(f, t)
+ util.set_exec(self.wjoin(f), mf[f])
+ self.dirstate.update([f], "n")
+
def copy(self, source, dest):
p = self.wjoin(dest)
if not os.path.exists(p):
new file mode 100644
--- /dev/null
+++ b/tests/test-revert
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+hg init
+echo 123 > a
+echo 123 > c
+hg add a c
+hg commit -m "first" -d "0 0" a c
+echo 123 > b
+hg status
+echo 12 > c
+hg status
+hg add b
+hg status
+hg rm a
+hg status
+hg revert a
+hg status
+hg revert b
+hg status
+hg revert c
+hg status
+ls
+
+true
new file mode 100644
--- /dev/null
+++ b/tests/test-revert.out
@@ -0,0 +1,16 @@
+? b
+M c
+? b
+M c
+A b
+M c
+A b
+R a
+M c
+A b
+M c
+? b
+? b
+a
+b
+c