diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2127,51 +2127,74 @@ def remove(ui, repo, *pats, **opts): Schedule the indicated files for removal from the repository. - This only removes files from the current branch, not from the - entire project history. If the files still exist in the working - directory, they will be deleted from it. If invoked with --after, - files are marked as removed, but not actually unlinked unless --force - is also given. Without exact file names, --after will only mark - files as removed if they are no longer in the working directory. + This only removes files from the current branch, not from the entire + project history. -A can be used to remove only files that have already + been deleted, -f can be used to force deletion, and -Af can be used + to remove files from the next revision without deleting them. + + The following table details the behavior of remove for different file + states (columns) and option combinations (rows). The file states are + Added, Clean, Modified and Missing (as reported by hg status). The + actions are Warn, Remove (from branch) and Delete (from disk). + + A C M ! + none W RD W R + -f R RD RD R + -A W W W R + -Af R R R R This command schedules the files to be removed at the next commit. To undo a remove before that, see hg revert. - - Modified files and added files are not removed by default. To - remove them, use the -f/--force option. """ - if not opts['after'] and not pats: + + after, force = opts.get('after'), opts.get('force') + if not pats and not after: raise util.Abort(_('no files specified')) + files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts) - exact = dict.fromkeys(files) mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5] modified, added, removed, deleted, unknown = mardu + remove, forget = [], [] for src, abs, rel, exact in cmdutil.walk(repo, pats, opts): + reason = None - if abs in modified and not opts['force']: - reason = _('is modified (use -f to force removal)') + if abs in removed or abs in unknown: + continue + + # last column + elif abs in deleted: + remove.append(abs) + + # rest of the third row + elif after and not force: + reason = _('still exists (use -f to force removal)') + + # rest of the first column elif abs in added: - if opts['force']: + if not force: + reason = _('has been marked for add (use -f to force removal)') + else: forget.append(abs) - continue - reason = _('has been marked for add (use -f to force removal)') - exact = 1 # force the message - elif abs not in repo.dirstate: - reason = _('is not managed') - elif opts['after'] and not exact and abs not in deleted: - continue - elif abs in removed: - continue + + # rest of the third column + elif abs in modified: + if not force: + reason = _('is modified (use -f to force removal)') + else: + remove.append(abs) + + # rest of the second column + elif not reason: + remove.append(abs) + if reason: - if exact: - ui.warn(_('not removing %s: file %s\n') % (rel, reason)) - else: - if ui.verbose or not exact: - ui.status(_('removing %s\n') % rel) - remove.append(abs) + ui.warn(_('not removing %s: file %s\n') % (rel, reason)) + elif ui.verbose or not exact: + ui.status(_('removing %s\n') % rel) + repo.forget(forget) - repo.remove(remove, unlink=opts['force'] or not opts['after']) + repo.remove(remove, unlink=not after) def rename(ui, repo, *pats, **opts): """rename files; equivalent of copy + remove @@ -3125,8 +3148,9 @@ table = { "recover": (recover, [], _('hg recover')), "^remove|rm": (remove, - [('A', 'after', None, _('record remove without deleting')), - ('f', 'force', None, _('remove file even if modified')), + [('A', 'after', None, _('record delete for missing files')), + ('f', 'force', None, + _('remove (and delete) file even if added or modified')), ] + walkopts, _('hg remove [OPTION]... FILE...')), "rename|mv": diff --git a/tests/test-remove b/tests/test-remove --- a/tests/test-remove +++ b/tests/test-remove @@ -1,45 +1,109 @@ #!/bin/sh +remove() { + hg rm $@ + hg st + ls -R + hg up -C +} + hg init a cd a echo a > foo -hg rm foo + +echo % file not managed +remove foo + hg add foo -hg commit -m 1 -d "1000000 0" -hg remove +hg commit -m1 + +# the table cases + +echo % 00 state added, options none +echo b > bar +hg add bar +remove bar + +echo % 01 state clean, options none +remove foo + +echo % 02 state modified, options none +echo b >> foo +remove foo + +echo % 03 state missing, options none rm foo -hg remove foo -hg revert --all +remove foo + +echo % 10 state added, options -f +echo b > bar +hg add bar +remove -f bar +rm bar + +echo % 11 state clean, options -f +remove -f foo + +echo % 12 state modified, options -f +echo b >> foo +remove -f foo + +echo % 13 state missing, options -f rm foo -hg remove --after -hg commit -m 2 -d "1000000 0" -hg export --nodates 0 -hg export --nodates 1 -hg log -p -r 0 -hg log -p -r 1 +remove -f foo + +echo % 20 state added, options -A +echo b > bar +hg add bar +remove -A bar -echo a > a -hg add a -hg rm a -hg rm -f a -echo b > b -mkdir c -echo d > c/d -hg ci -A -m 3 -d "1000001 0" -echo c >> b -hg rm b -hg rm -f b -hg rm -A c/d -hg st -cat c/d -hg revert c -hg rm -A -hg st -hg rm -A c -hg st -rm c/d -hg rm -A -hg st +echo % 21 state clean, options -A +remove -A foo + +echo % 22 state modified, options -A +echo b >> foo +remove -A foo + +echo % 23 state missing, options -A +rm foo +remove -A foo + +echo % 30 state added, options -Af +echo b > bar +hg add bar +remove -Af bar +rm bar + +echo % 31 state clean, options -Af +remove -Af foo + +echo % 32 state modified, options -Af +echo b >> foo +remove -Af foo -cd .. -hg clone a b +echo % 33 state missing, options -Af +rm foo +remove -Af foo + +# test some directory stuff + +mkdir test +echo a > test/foo +echo b > test/bar +hg ci -Am2 + +echo % dir, options none +rm test/bar +remove test + +echo % dir, options -f +rm test/bar +remove -f test + +echo % dir, options -A +rm test/bar +remove -A test + +echo % dir, options -Af +rm test/bar +remove -Af test diff --git a/tests/test-remove.out b/tests/test-remove.out --- a/tests/test-remove.out +++ b/tests/test-remove.out @@ -1,67 +1,127 @@ -not removing foo: file is not managed -abort: no files specified -undeleting foo -removing foo -# HG changeset patch -# User test -# Date 1000000 0 -# Node ID 8ba83d44753d6259db5ce6524974dd1174e90f47 -# Parent 0000000000000000000000000000000000000000 -1 - -diff -r 000000000000 -r 8ba83d44753d foo ---- /dev/null -+++ b/foo -@@ -0,0 +1,1 @@ -+a -# HG changeset patch -# User test -# Date 1000000 0 -# Node ID a1fce69c50d97881c5c014ab23f580f720c78678 -# Parent 8ba83d44753d6259db5ce6524974dd1174e90f47 -2 - -diff -r 8ba83d44753d -r a1fce69c50d9 foo ---- a/foo -+++ /dev/null -@@ -1,1 +0,0 @@ --a -changeset: 0:8ba83d44753d -user: test -date: Mon Jan 12 13:46:40 1970 +0000 -summary: 1 +% file not managed +? foo +.: +foo +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 00 state added, options none +not removing bar: file has been marked for add (use -f to force removal) +A bar +.: +bar +foo +0 files updated, 0 files merged, 1 files removed, 0 files unresolved +% 01 state clean, options none +R foo +.: +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 02 state modified, options none +not removing foo: file is modified (use -f to force removal) +M foo +.: +foo +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 03 state missing, options none +R foo +.: +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 10 state added, options -f +? bar +.: +bar +foo +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 11 state clean, options -f +R foo +.: +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 12 state modified, options -f +R foo +.: +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 13 state missing, options -f +R foo +.: +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 20 state added, options -A +not removing bar: file still exists (use -f to force removal) +A bar +.: +bar +foo +0 files updated, 0 files merged, 1 files removed, 0 files unresolved +% 21 state clean, options -A +not removing foo: file still exists (use -f to force removal) +.: +foo +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 22 state modified, options -A +not removing foo: file still exists (use -f to force removal) +M foo +.: +foo +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 23 state missing, options -A +R foo +.: +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 30 state added, options -Af +? bar +.: +bar +foo +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 31 state clean, options -Af +R foo +.: +foo +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 32 state modified, options -Af +R foo +.: +foo +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% 33 state missing, options -Af +R foo +.: +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +adding test/bar +adding test/foo +% dir, options none +removing test/foo +removing test/bar +R test/bar +R test/foo +.: +foo +2 files updated, 0 files merged, 0 files removed, 0 files unresolved +% dir, options -f +removing test/foo +removing test/bar +R test/bar +R test/foo +.: +foo +2 files updated, 0 files merged, 0 files removed, 0 files unresolved +% dir, options -A +not removing test/foo: file still exists (use -f to force removal) +removing test/bar +R test/bar +.: +foo +test -diff -r 000000000000 -r 8ba83d44753d foo ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/foo Mon Jan 12 13:46:40 1970 +0000 -@@ -0,0 +1,1 @@ -+a - -changeset: 1:a1fce69c50d9 -tag: tip -user: test -date: Mon Jan 12 13:46:40 1970 +0000 -summary: 2 +./test: +foo +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% dir, options -Af +removing test/foo +removing test/bar +R test/bar +R test/foo +.: +foo +test -diff -r 8ba83d44753d -r a1fce69c50d9 foo ---- a/foo Mon Jan 12 13:46:40 1970 +0000 -+++ /dev/null Thu Jan 01 00:00:00 1970 +0000 -@@ -1,1 +0,0 @@ --a - -not removing a: file has been marked for add (use -f to force removal) -adding a -adding b -adding c/d -not removing b: file is modified (use -f to force removal) -R b -R c/d -d -undeleting c/d -R b -R b -removing c/d -R b -R c/d -updating working directory -3 files updated, 0 files merged, 0 files removed, 0 files unresolved +./test: +foo +2 files updated, 0 files merged, 0 files removed, 0 files unresolved