changeset 2042:a514c7509fa9

small changes to revert command. fix bug 93: work with files that are in target manifest but not dirstate.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Mon, 03 Apr 2006 10:02:09 -0700
parents 077a2da7f1de
children 968f036f93a4 74d3f5336b66
files mercurial/commands.py mercurial/dirstate.py mercurial/localrepo.py tests/test-confused-revert.out tests/test-revert tests/test-revert-unknown.out tests/test-revert.out
diffstat 7 files changed, 72 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py	Mon Apr 03 14:56:00 2006 +0200
+++ b/mercurial/commands.py	Mon Apr 03 10:02:09 2006 -0700
@@ -48,7 +48,7 @@
     exact = dict(zip(files, files))
     def walk():
         for src, fn in repo.walk(node=node, files=files, match=matchfn,
-                                 badmatch=None):
+                                 badmatch=badmatch):
             yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
     return files, matchfn, walk()
 
@@ -2349,11 +2349,27 @@
 
     wlock = repo.wlock()
 
-    entries = []
+    # need all matching names in dirstate and manifest of target rev,
+    # so have to walk both. do not print errors if files exist in one
+    # but not other.
+
     names = {}
+    target_only = {}
+
+    # walk dirstate.
+
     for src, abs, rel, exact in walk(repo, pats, opts, badmatch=mf.has_key):
-        names[abs] = True
-        entries.append((abs, rel, exact))
+        names[abs] = (rel, exact)
+        if src == 'b':
+            target_only[abs] = True
+
+    # walk target manifest.
+
+    for src, abs, rel, exact in walk(repo, pats, opts, node=node,
+                                     badmatch=names.has_key):
+        if abs in names: continue
+        names[abs] = (rel, exact)
+        target_only[abs] = True
 
     changes = repo.changes(match=names.has_key, wlock=wlock)
     modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
@@ -2377,9 +2393,14 @@
         (removed, undelete, None, False, False),
         (deleted, revert, remove, False, False),
         (unknown, add, None, True, False),
+        (target_only, add, None, False, False),
         )
 
-    for abs, rel, exact in entries:
+    entries = names.items()
+    entries.sort()
+
+    for abs, (rel, exact) in entries:
+        in_mf = abs in mf
         def handle(xlist, dobackup):
             xlist[0].append(abs)
             if dobackup and not opts['no_backup'] and os.path.exists(rel):
@@ -2393,7 +2414,7 @@
         for table, hitlist, misslist, backuphit, backupmiss in disptable:
             if abs not in table: continue
             # file has changed in dirstate
-            if abs in mf:
+            if in_mf:
                 handle(hitlist, backuphit)
             elif misslist is not None:
                 handle(misslist, backupmiss)
@@ -2405,8 +2426,8 @@
             if node == parent:
                 if exact: ui.warn(_('no changes needed to %s\n' % rel))
                 continue
-            if abs not in mf:
-                remove[0].append(abs)
+            if not in_mf:
+                handle(remove, False)
         update[abs] = True
 
     repo.dirstate.forget(forget[0])
--- a/mercurial/dirstate.py	Mon Apr 03 14:56:00 2006 +0200
+++ b/mercurial/dirstate.py	Mon Apr 03 10:02:09 2006 -0700
@@ -294,7 +294,8 @@
                 kind))
         return False
 
-    def statwalk(self, files=None, match=util.always, dc=None, ignored=False):
+    def statwalk(self, files=None, match=util.always, dc=None, ignored=False,
+                 badmatch=None):
         self.lazyread()
 
         # walk all files by default
@@ -311,11 +312,12 @@
                 return False
             return match(file_)
 
-        return self.walkhelper(files=files, statmatch=statmatch, dc=dc)
+        return self.walkhelper(files=files, statmatch=statmatch, dc=dc,
+                               badmatch=badmatch)
 
-    def walk(self, files=None, match=util.always, dc=None):
+    def walk(self, files=None, match=util.always, dc=None, badmatch=None):
         # filter out the stat
-        for src, f, st in self.statwalk(files, match, dc):
+        for src, f, st in self.statwalk(files, match, dc, badmatch=badmatch):
             yield src, f
 
     # walk recursively through the directory tree, finding all files
@@ -330,7 +332,7 @@
     # dc is an optional arg for the current dirstate.  dc is not modified
     # directly by this function, but might be modified by your statmatch call.
     #
-    def walkhelper(self, files, statmatch, dc):
+    def walkhelper(self, files, statmatch, dc, badmatch=None):
         # recursion free walker, faster than os.walk.
         def findfiles(s):
             work = [s]
@@ -379,9 +381,12 @@
                         found = True
                         break
                 if not found:
-                    self.ui.warn('%s: %s\n' % (
-                                 util.pathto(self.getcwd(), ff),
-                                 inst.strerror))
+                    if inst.errno != errno.ENOENT or not badmatch:
+                        self.ui.warn('%s: %s\n' % (
+                            util.pathto(self.getcwd(), ff),
+                            inst.strerror))
+                    elif badmatch and badmatch(ff) and statmatch(ff, None):
+                        yield 'b', ff, None
                 continue
             if stat.S_ISDIR(st.st_mode):
                 cmp1 = (lambda x, y: cmp(x[1], y[1]))
--- a/mercurial/localrepo.py	Mon Apr 03 14:56:00 2006 +0200
+++ b/mercurial/localrepo.py	Mon Apr 03 10:02:09 2006 -0700
@@ -498,7 +498,7 @@
                     self.ui.warn(_('%s: No such file in rev %s\n') % (
                         util.pathto(self.getcwd(), fn), short(node)))
         else:
-            for src, fn in self.dirstate.walk(files, match):
+            for src, fn in self.dirstate.walk(files, match, badmatch=badmatch):
                 yield src, fn
 
     def changes(self, node1=None, node2=None, files=[], match=util.always,
--- a/tests/test-confused-revert.out	Mon Apr 03 14:56:00 2006 +0200
+++ b/tests/test-confused-revert.out	Mon Apr 03 10:02:09 2006 -0700
@@ -2,8 +2,8 @@
 A b
 R a
 reverting...
+undeleting a
 forgetting b
-undeleting a
 %%% should show b unknown and a back to normal
 ? b
 ? b.orig
@@ -15,8 +15,8 @@
 R a
 ? b.orig
 reverting...
+undeleting a
 forgetting b
-undeleting a
 %%% should show b unknown and a marked modified (merged)
 ? b
 ? b.orig
--- a/tests/test-revert	Mon Apr 03 14:56:00 2006 +0200
+++ b/tests/test-revert	Mon Apr 03 10:02:09 2006 -0700
@@ -37,7 +37,21 @@
 echo %% should say file not managed
 echo q > q
 hg revert q
+rm q
 echo %% should say file not found
 hg revert notfound
+hg rm a
+hg commit -m "second" -d "1000000 0"
+echo z > z
+hg add z
+hg st
+echo %% should add a, forget z
+hg revert -r0
+echo %% should forget a
+hg revert -rtip
+rm -f a *.orig
+echo %% should silently add a
+hg revert -r0 a
+hg st a
 
 true
--- a/tests/test-revert-unknown.out	Mon Apr 03 14:56:00 2006 +0200
+++ b/tests/test-revert-unknown.out	Mon Apr 03 10:02:09 2006 -0700
@@ -1,5 +1,6 @@
 %% Should show unknown
 ? unknown
+removing b
 %% Should show unknown and b removed
 R b
 ? unknown
--- a/tests/test-revert.out	Mon Apr 03 14:56:00 2006 +0200
+++ b/tests/test-revert.out	Mon Apr 03 10:02:09 2006 -0700
@@ -37,4 +37,15 @@
 %% should say file not managed
 file not managed: q
 %% should say file not found
-notfound: No such file or directory
+notfound: No such file in rev 095eacd0c0d7
+A z
+? b
+? b.orig
+? e.orig
+%% should add a, forget z
+adding a
+forgetting z
+%% should forget a
+forgetting a
+%% should silently add a
+A a