[PATCH 2 of 2] addremove: add --full/-f to force rematching of all removed files (status ! or R)

Peter Arrenbrecht peter.arrenbrecht at gmail.com
Wed Apr 2 14:38:02 CDT 2008


# HG changeset patch
# User Peter Arrenbrecht <peter.arrenbrecht at gmail.com>
# Date 1207165043 -7200
# Node ID b007e781b89191603950acfb228fe0d4de97d382
# Parent  e43616661358fa319579c0d9db6d50d6a1d69d18
addremove: add --full/-f to force rematching of all removed files (status ! or R)

With -s the addremove command only checks files with status ! (missing)
against files with status ? (new).  Use the -f option with -s to force
(re)checking of all deleted files (status ! or R) against all new files
(status ? or A).  This is especially helpful if you forgot -s or set
the similarity too high.

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -267,31 +267,51 @@
         if bestname:
             yield bestname, a, bestscore
 
-def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
+def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None, full=None):
     if dry_run is None:
         dry_run = opts.get('dry_run')
     if similarity is None:
         similarity = float(opts.get('similarity') or 0)
-    add, remove = [], []
+    if full is None:
+        full = opts.get('full')
+    newfiles, deletedfiles = [], []
+    sources, targets = [], []
     mapping = {}
+    detectingrenames = (similarity > 0)
     for src, abs, rel, exact in walk(repo, pats, opts):
         target = repo.wjoin(abs)
-        if src == 'f' and abs not in repo.dirstate:
-            add.append(abs)
-            mapping[abs] = rel, exact
-            if repo.ui.verbose or not exact:
-                repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
-        if repo.dirstate[abs] != 'r' and (not util.lexists(target)
-            or (os.path.isdir(target) and not os.path.islink(target))):
-            remove.append(abs)
-            mapping[abs] = rel, exact
-            if repo.ui.verbose or not exact:
-                repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
+        if src == 'f':
+            isrecorded = abs in repo.dirstate
+            issource = False
+            if not isrecorded:
+                newfiles.append(abs)
+                if repo.ui.verbose or not exact:
+                    repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
+                issource = detectingrenames
+            elif detectingrenames and full:
+                issource = repo.dirstate[abs] == 'a'
+            if issource:
+                targets.append(abs)
+                mapping[abs] = rel, exact
+        if (not util.lexists(target) or
+                (os.path.isdir(target) and not os.path.islink(target))):
+            isrecorded = repo.dirstate[abs] == 'r'
+            istarget = False
+            if not isrecorded:
+                deletedfiles.append(abs)
+                if repo.ui.verbose or not exact:
+                    repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
+                istarget = detectingrenames
+            elif full:
+                istarget = detectingrenames
+            if istarget:
+                sources.append(abs)
+                mapping[abs] = rel, exact
     if not dry_run:
-        repo.remove(remove)
-        repo.add(add)
+        repo.remove(deletedfiles)
+        repo.add(newfiles)
     if similarity > 0:
-        for old, new, score in findrenames(repo, add, remove, similarity):
+        for old, new, score in findrenames(repo, targets, sources, similarity):
             oldrel, oldexact = mapping[old]
             newrel, newexact = mapping[new]
             if repo.ui.verbose or not oldexact or not newexact:
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -58,6 +58,12 @@
     those similar enough as renames.  This option takes a percentage
     between 0 (disabled) and 100 (files must be identical) as its
     parameter.  Detecting renamed files this way can be expensive.
+
+    With -s this command normally only checks files with status ! (missing)
+    against files with status ? (new).  Use the -f option with -s to force
+    (re)checking of all deleted files (status ! or R) against all new files
+    (status ? or A).  This is especially helpful if you forgot -s or set
+    the similarity too high.
     """
     try:
         sim = float(opts.get('similarity') or 0)
@@ -2892,7 +2898,9 @@
     "addremove":
         (addremove,
          [('s', 'similarity', '',
-           _('guess renamed files by similarity (0<=s<=100)')),
+           _('guess renamed files (status !) by similarity (0<=s<=100)')),
+          ('f', 'full', None,
+           _('make -s check all removed files (status R or !)')),
          ] + walkopts + dryrunopts,
          _('hg addremove [OPTION]... [FILE]...')),
     "^annotate|blame":
diff --git a/tests/test-addremove-similar b/tests/test-addremove-similar
--- a/tests/test-addremove-similar
+++ b/tests/test-addremove-similar
@@ -50,4 +50,37 @@
 hg addremove -s -1
 hg addremove -s 1e6
 
+cd ..
+
+echo % --full option
+
+hg init rep3; cd rep3
+python -c 'for x in range(50): print x' > a
+# make a1 a closer match that won't be considered because it hasn't gone
+cp a a1
+echo "One more" >> a1
+hg add a a1; hg ci -m a
+mv a b
+echo "One more" >> b
+
+# so here we forget -s
+hg stat -C
+hg addrem
+hg stat -C
+
+# and try again with it, but it doesn't capture already recorded removals
+hg addrem -s 90
+hg stat -C
+
+# so we use the --full option
+hg addrem -fs 90
+hg stat -C
+
+# if we place another copy there, it gets recorded as a second target
+python -c 'for x in range(50): print x' > c
+hg addrem -s 90 --full
+hg stat -C
+
+cd ..
+
 true
diff --git a/tests/test-addremove-similar.out b/tests/test-addremove-similar.out
--- a/tests/test-addremove-similar.out
+++ b/tests/test-addremove-similar.out
@@ -20,3 +20,24 @@
 abort: similarity must be a number
 abort: similarity must be between 0 and 100
 abort: similarity must be between 0 and 100
+% --full option
+! a
+? b
+adding b
+removing a
+A b
+R a
+A b
+R a
+recording removal of a as rename to b (96% similar)
+A b
+  a
+R a
+adding c
+recording removal of a as rename to b (96% similar)
+recording removal of a as rename to c (100% similar)
+A b
+  a
+A c
+  a
+R a


More information about the Mercurial-devel mailing list