# HG changeset patch # User Vadim Gelfer # Date 1144083729 25200 # Node ID a514c7509fa99d963dc7ca5d9a713bd8c88ff2c6 # Parent 077a2da7f1ded39ac8452e10797290fbdfb773fc small changes to revert command. fix bug 93: work with files that are in target manifest but not dirstate. diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -48,7 +48,7 @@ def makewalk(repo, pats, opts, node=None 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 @@ def revert(ui, repo, *pats, **opts): 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 @@ def revert(ui, repo, *pats, **opts): (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 @@ def revert(ui, repo, *pats, **opts): 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 @@ def revert(ui, repo, *pats, **opts): 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]) diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -294,7 +294,8 @@ class dirstate(object): 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 @@ class dirstate(object): 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 @@ class dirstate(object): # 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 @@ class dirstate(object): 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])) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -498,7 +498,7 @@ class localrepository(object): 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, diff --git a/tests/test-confused-revert.out b/tests/test-confused-revert.out --- a/tests/test-confused-revert.out +++ b/tests/test-confused-revert.out @@ -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 @@ A b R a ? b.orig reverting... +undeleting a forgetting b -undeleting a %%% should show b unknown and a marked modified (merged) ? b ? b.orig diff --git a/tests/test-revert b/tests/test-revert --- a/tests/test-revert +++ b/tests/test-revert @@ -37,7 +37,21 @@ hg revert a 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 diff --git a/tests/test-revert-unknown.out b/tests/test-revert-unknown.out --- a/tests/test-revert-unknown.out +++ b/tests/test-revert-unknown.out @@ -1,5 +1,6 @@ %% Should show unknown ? unknown +removing b %% Should show unknown and b removed R b ? unknown diff --git a/tests/test-revert.out b/tests/test-revert.out --- a/tests/test-revert.out +++ b/tests/test-revert.out @@ -37,4 +37,15 @@ no changes needed to a %% 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