Like .gitattributes, we would like to make sure that
.gitignore files are handled consistently whether read from
the index or from the filesystem. We can do so by using
O_NOFOLLOW when opening the files.

Signed-off-by: Jeff King <p...@peff.net>
---
 dir.c              |  9 +++++++--
 t/t0008-ignores.sh | 29 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/dir.c b/dir.c
index 4fa1ca109..cf3fde005 100644
--- a/dir.c
+++ b/dir.c
@@ -693,6 +693,7 @@ static void invalidate_directory(struct untracked_cache *uc,
 
 /* Flags for add_excludes() */
 #define EXCLUDE_CHECK_INDEX (1<<0)
+#define EXCLUDE_NOFOLLOW (1<<1)
 
 /*
  * Given a file with name "fname", read it (either from disk, or from
@@ -713,7 +714,11 @@ static int add_excludes(const char *fname, const char 
*base, int baselen,
        size_t size = 0;
        char *buf, *entry;
 
-       fd = open(fname, O_RDONLY);
+       if (flags & EXCLUDE_NOFOLLOW)
+               fd = open_nofollow(fname, O_RDONLY);
+       else
+               fd = open(fname, O_RDONLY);
+
        if (fd < 0 || fstat(fd, &st) < 0) {
                if (errno != ENOENT)
                        warn_on_inaccessible(fname);
@@ -1130,7 +1135,7 @@ static void prep_exclude(struct dir_struct *dir, const 
char *base, int baselen)
                        strbuf_addstr(&sb, dir->exclude_per_dir);
                        el->src = strbuf_detach(&sb, NULL);
                        add_excludes(el->src, el->src, stk->baselen, el,
-                                    EXCLUDE_CHECK_INDEX,
+                                    EXCLUDE_CHECK_INDEX | EXCLUDE_NOFOLLOW,
                                     untracked ? &sha1_stat : NULL);
                }
                /*
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index d27f438bf..7348b8e6a 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -841,4 +841,33 @@ test_expect_success 'info/exclude trumps 
core.excludesfile' '
        test_cmp expect actual
 '
 
+test_expect_success SYMLINKS 'set up ignore file for symlink tests' '
+       echo "*" >ignore
+'
+
+test_expect_success SYMLINKS 'symlinks respected in core.excludesFile' '
+       test_when_finished "rm symlink" &&
+       ln -s ignore symlink &&
+       test_config core.excludesFile "$(pwd)/symlink" &&
+       echo file >expect &&
+       git check-ignore file >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success SYMLINKS 'symlinks respected in info/exclude' '
+       test_when_finished "rm .git/info/exclude" &&
+       ln -sf ../../ignore .git/info/exclude &&
+       echo file >expect &&
+       git check-ignore file >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success SYMLINKS 'symlinks not respected in-tree' '
+       test_when_finished "rm .gitignore" &&
+       ln -sf ignore .gitignore &&
+       >expect &&
+       test_must_fail git check-ignore file >actual &&
+       test_cmp expect actual
+'
+
 test_done
-- 
2.11.0.rc0.258.gf434c15

Reply via email to