[PATCH] Warn in case user tries to add files which would otherwise be ignored

Jesse Glick Jesse.Glick at Sun.COM
Fri Feb 22 11:21:42 CST 2008


# HG changeset patch
# User Jesse Glick <jesse.glick at sun.com>
# Date 1203700484 18000
# Node ID a15692d29c9f3216b629b7d67e8bcc842ff88c40
# Parent  554715e584e6d9a4275fffd9065d9330511eafc4
Warn in case user tries to add files which would otherwise be ignored.

While sometimes you really meant to do this, often you did not. For
example, if '/build$' is ignored and you have

module/
module/src/
[...]
module/build/
module/build/generated-file

and you run 'hg add module' then all is good. But if a novice user
runs 'hg add module/*' then generated-file is added with no warning!

While you can of course 'hg rem' the bogus file later if you discover
it, this is an unpleasant surprise. In addition, this interacts badly
with Issue988; if a build script routinely deletes the whole 'build'
subdir, even if the discoverer of the bad file does delete it, it can
be silently resurrected during a merge, and be hard to kill.

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -254,7 +254,8 @@ def findrenames(repo, added=None, remove
         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,
+              fromcommit=False):
     if dry_run is None:
         dry_run = opts.get('dry_run')
     if similarity is None:
@@ -266,8 +267,17 @@ def addremove(repo, pats=[], opts={}, dr
         if src == 'f' and abs not in repo.dirstate:
             add.append(abs)
             mapping[abs] = rel, exact
+            name = (pats and rel) or abs
             if repo.ui.verbose or not exact:
-                repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
+                repo.ui.status(_('adding %s\n') % name)
+            if repo.dirstate._dirignore(abs):
+                repo.ui.warn(_('warning: adding ignorable file %s\n') % name)
+                if fromcommit:
+                    repo.ui.warn(_("(use 'hg remove %s' to delete the file)\n")
+                                 % name)
+                else:
+                    repo.ui.warn(_("(use 'hg revert %s' to unadd the file)\n")
+                                 % name)
         if repo.dirstate[abs] != 'r' and (not util.lexists(target)
             or (os.path.isdir(target) and not os.path.islink(target))):
             remove.append(abs)
@@ -1123,7 +1133,7 @@ def commit(ui, repo, commitfunc, pats, o
     # extract addremove carefully -- this function can be called from a command
     # that doesn't support addremove
     if opts.get('addremove'):
-        addremove(repo, pats, opts)
+        addremove(repo, pats, opts, fromcommit=True)
 
     fns, match, anypats = matchpats(repo, pats, opts)
     if pats:
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -31,14 +31,21 @@ def add(ui, repo, *pats, **opts):
     names = []
     for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
                                              badmatch=util.always):
+        def warnignored():
+            if repo.dirstate._dirignore(abs):
+                repo.ui.warn(_('warning: adding ignorable file %s\n'
+                               "(use 'hg revert %s' to unadd the file)\n")
+                             % (rel, rel))
         if exact:
             if ui.verbose:
                 ui.status(_('adding %s\n') % rel)
             names.append(abs)
             exacts[abs] = 1
+            warnignored()
         elif abs not in repo.dirstate:
             ui.status(_('adding %s\n') % rel)
             names.append(abs)
+            warnignored()
     if not opts.get('dry_run'):
         rejected = repo.add(names)
         rejected = [p for p in rejected if p in exacts]
diff --git a/tests/test-add b/tests/test-add
--- a/tests/test-add
+++ b/tests/test-add
@@ -46,3 +46,18 @@ hg add d c && echo "unexpected addition 
 hg add d c && echo "unexpected addition of missing file"
 hg st
 
+echo % checking adding of ignorable files
+hg init ignoretest
+cd ignoretest
+echo '^build$' > .hgignore
+echo '^trash$' >> .hgignore
+hg add .hgignore
+echo trash > trash
+hg add trash
+hg st
+mkdir build
+echo trash > build/trash
+hg add build
+hg st
+hg add build/trash
+hg st
diff --git a/tests/test-add.out b/tests/test-add.out
--- a/tests/test-add.out
+++ b/tests/test-add.out
@@ -36,3 +36,15 @@ M a
 M a
 A c
 ? a.orig
+% checking adding of ignorable files
+warning: adding ignorable file trash
+(use 'hg revert trash' to unadd the file)
+A .hgignore
+A trash
+A .hgignore
+A trash
+warning: adding ignorable file build/trash
+(use 'hg revert build/trash' to unadd the file)
+A .hgignore
+A build/trash
+A trash
diff --git a/tests/test-addremove b/tests/test-addremove
--- a/tests/test-addremove
+++ b/tests/test-addremove
@@ -24,3 +24,21 @@ echo d > d
 echo d > d
 hg addremove -s 50
 hg commit -mb
+
+echo % checking adding of ignorable files
+hg init ignoretest
+cd ignoretest
+echo '^build$' > .hgignore
+echo '^trash$' >> .hgignore
+hg add .hgignore
+echo trash > trash
+hg addrem trash
+hg st
+mkdir build
+echo trash > build/trash
+hg addrem
+hg st
+hg addrem build
+hg st
+hg addrem build/trash
+hg st
diff --git a/tests/test-addremove.out b/tests/test-addremove.out
--- a/tests/test-addremove.out
+++ b/tests/test-addremove.out
@@ -13,3 +13,17 @@ removing a
 removing a
 removing c
 recording removal of a as rename to b (100% similar)
+% checking adding of ignorable files
+warning: adding ignorable file trash
+(use 'hg revert trash' to unadd the file)
+A .hgignore
+A trash
+A .hgignore
+A trash
+A .hgignore
+A trash
+warning: adding ignorable file build/trash
+(use 'hg revert build/trash' to unadd the file)
+A .hgignore
+A build/trash
+A trash
diff --git a/tests/test-revert.out b/tests/test-revert.out
--- a/tests/test-revert.out
+++ b/tests/test-revert.out
@@ -78,6 +78,14 @@ I ignoreddir/file
 I ignoreddir/file
 I ignoreddir/removed
 I removed
+warning: adding ignorable file ignored
+(use 'hg remove ignored' to delete the file)
+warning: adding ignorable file ignoreddir/file
+(use 'hg remove ignoreddir/file' to delete the file)
+warning: adding ignorable file ignoreddir/removed
+(use 'hg remove ignoreddir/removed' to delete the file)
+warning: adding ignorable file removed
+(use 'hg remove removed' to delete the file)
 %% should revert ignored* and undelete *removed
 reverting ignored
 reverting ignoreddir/file


More information about the Mercurial-devel mailing list