# HG changeset patch
# User Maxim Dounin <mdounin@mdounin.ru>
# Date 2008-05-07 10:32:00
# Node ID 7f0dd352fb4dde3e37fbb9dde23f7c82128d91c5
# Parent  05a682c8907df20962c31a8adfcd9433d39dd034

addremove: correctly handle intermediate symlinks

This fixes problems mentioned in issue660 comments (unrelated to original
issue) where directory was renamed, and symlink was added instead.
In such situation addremove wasn't able to correctly detect that old files
no longer here, but tried to add symlink (and failed due collision with
old files).

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -274,14 +274,20 @@ def addremove(repo, pats=[], opts={}, dr
         similarity = float(opts.get('similarity') or 0)
     add, remove = [], []
     mapping = {}
+    audit_path = util.path_auditor(repo.root)
     for src, abs, rel, exact in walk(repo, pats, opts):
         target = repo.wjoin(abs)
-        if src == 'f' and abs not in repo.dirstate:
+        good = True
+        try:
+            audit_path(abs)
+        except:
+            good = False
+        if src == 'f' and good 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)
+        if repo.dirstate[abs] != 'r' and (not good or not util.lexists(target)
             or (os.path.isdir(target) and not os.path.islink(target))):
             remove.append(abs)
             mapping[abs] = rel, exact
diff --git a/tests/test-symlink-addremove b/tests/test-symlink-addremove
new file mode 100755
--- /dev/null
+++ b/tests/test-symlink-addremove
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+"$TESTDIR/hghave" symlink || exit 80
+
+hg init a
+cd a
+
+echo '% directory moved and symlinked'
+mkdir foo
+touch foo/a
+hg ci -Ama
+mv foo bar
+ln -s bar foo
+echo '% now addremove should remove old files'
+hg addremove
diff --git a/tests/test-symlink-addremove.out b/tests/test-symlink-addremove.out
new file mode 100644
--- /dev/null
+++ b/tests/test-symlink-addremove.out
@@ -0,0 +1,6 @@
+% directory moved and symlinked
+adding foo/a
+% now addremove should remove old files
+adding bar/a
+adding foo
+removing foo/a