remove: rewrite to be ~400x faster, bit more friendly
old remove code called localrepo.changes for each file.
was very expensive:
$ hg --time rm arch>/dev/null
Time: real 1066.120 secs (user 1014.450+0.000 sys 18.090+0.000)
new code, same files:
$ hg --time rm arch>/dev/null
Time: real 2.770 secs (user 2.190+0.000 sys 0.580+0.000)
also mention "-f" if not removing files. also allow "-f" to forget
added files.
make test a bit better.
--- a/mercurial/commands.py Thu May 18 21:01:38 2006 +0200
+++ b/mercurial/commands.py Thu May 18 13:48:12 2006 -0700
@@ -2189,34 +2189,42 @@
entire project history. If the files still exist in the working
directory, they will be deleted from it. If invoked with --after,
files that have been manually deleted are marked as removed.
+
+ Modified files and added files are not removed by default. To
+ remove them, use the -f/--force option.
"""
names = []
if not opts['after'] and not pats:
raise util.Abort(_('no files specified'))
- def okaytoremove(abs, rel, exact):
- modified, added, removed, deleted, unknown = repo.changes(files=[abs])
+ files, matchfn, anypats = matchpats(repo, pats, opts)
+ exact = dict.fromkeys(files)
+ mardu = map(dict.fromkeys, repo.changes(files=files, match=matchfn))
+ modified, added, removed, deleted, unknown = mardu
+ remove, forget = [], []
+ for src, abs, rel, exact in walk(repo, pats, opts):
reason = None
- if not deleted and opts['after']:
+ if abs not in deleted and opts['after']:
reason = _('is still present')
- elif modified and not opts['force']:
- reason = _('is modified')
- elif added:
- reason = _('has been marked for add')
- elif unknown:
+ elif abs in modified and not opts['force']:
+ reason = _('is modified (use -f to force removal)')
+ elif abs in added:
+ if opts['force']:
+ forget.append(abs)
+ continue
+ reason = _('has been marked for add (use -f to force removal)')
+ elif abs in unknown:
reason = _('is not managed')
- elif removed:
- return False
+ elif abs in removed:
+ continue
if reason:
if exact:
ui.warn(_('not removing %s: file %s\n') % (rel, reason))
else:
- return True
- for src, abs, rel, exact in walk(repo, pats, opts):
- if okaytoremove(abs, rel, exact):
if ui.verbose or not exact:
ui.status(_('removing %s\n') % rel)
- names.append(abs)
- repo.remove(names, unlink=not opts['after'])
+ remove.append(abs)
+ repo.forget(forget)
+ repo.remove(remove, unlink=not opts['after'])
def rename(ui, repo, *pats, **opts):
"""rename files; equivalent of copy + remove
--- a/tests/test-remove Thu May 18 21:01:38 2006 +0200
+++ b/tests/test-remove Thu May 18 13:48:12 2006 -0700
@@ -3,6 +3,7 @@
hg init a
cd a
echo a > foo
+hg rm foo
hg add foo
hg commit -m 1 -d "1000000 0"
hg remove
@@ -17,5 +18,15 @@
hg log -p -r 0
hg log -p -r 1
+echo a > a
+hg add a
+hg rm a
+hg rm -f a
+echo b > b
+hg ci -A -m 3 -d "1000001 0"
+echo c >> b
+hg rm b
+hg rm -f b
+
cd ..
hg clone a b
--- a/tests/test-remove.out Thu May 18 21:01:38 2006 +0200
+++ b/tests/test-remove.out Thu May 18 13:48:12 2006 -0700
@@ -1,3 +1,4 @@
+not removing foo: file is not managed
abort: no files specified
undeleting foo
removing foo
@@ -50,4 +51,8 @@
-a
-0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+not removing a: file has been marked for add (use -f to force removal)
+adding a
+adding b
+not removing b: file is modified (use -f to force removal)
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved