improved semantics for remove (
issue438)
- Added files are never deleted (only removed with --force).
- Modified files can only be removed with --force.
- With --after, only deleted files are removed.
- With --after --force, all files are removed but not deleted.
--- a/mercurial/commands.py Fri Mar 21 17:22:47 2008 -0500
+++ b/mercurial/commands.py Sat Mar 22 10:07:49 2008 +0100
@@ -2127,51 +2127,74 @@
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 @@
"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":
--- a/tests/test-remove Fri Mar 21 17:22:47 2008 -0500
+++ b/tests/test-remove Sat Mar 22 10:07:49 2008 +0100
@@ -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
--- a/tests/test-remove.out Fri Mar 21 17:22:47 2008 -0500
+++ b/tests/test-remove.out Sat Mar 22 10:07:49 2008 +0100
@@ -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