dir: allow a BOM at the beginning of exclude files
authorCarlos Martín Nieto <cmn@elego.de>
Thu, 16 Apr 2015 14:05:12 +0000 (16:05 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 16 Apr 2015 17:17:04 +0000 (10:17 -0700)
Some text editors like Notepad or LibreOffice write an UTF-8 BOM in
order to indicate that the file is Unicode text rather than whatever the
current locale would indicate.

If someone uses such an editor to edit a gitignore file, we are left
with those three bytes at the beginning of the file. If we do not skip
them, we will attempt to match a filename with the BOM as prefix, which
won't match the files the user is expecting.

Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
dir.c
t/t7061-wtstatus-ignore.sh
diff --git a/dir.c b/dir.c
index 3f7a0256b61552c6c3f80f710bd042b697d79da9..10c1f903efc5ddff840782bae7a115b895a068a8 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -538,6 +538,7 @@ int add_excludes_from_file_to_list(const char *fname,
        struct stat st;
        int fd, i, lineno = 1;
        size_t size = 0;
+       static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf";
        char *buf, *entry;
 
        fd = open(fname, O_RDONLY);
@@ -574,7 +575,12 @@ int add_excludes_from_file_to_list(const char *fname,
        }
 
        el->filebuf = buf;
-       entry = buf;
+
+       if (size >= 3 && !memcmp(buf, utf8_bom, 3))
+               entry = buf + 3;
+       else
+               entry = buf;
+
        for (i = 0; i < size; i++) {
                if (buf[i] == '\n') {
                        if (entry != buf + i && entry[0] != '#') {
index 460789b4d85241eb51c0c1a5a1f4be7d4a0d7154..cdc0747bf01b0598a2e864073887896162815019 100755 (executable)
@@ -20,6 +20,15 @@ test_expect_success 'status untracked directory with --ignored' '
        test_cmp expected actual
 '
 
+test_expect_success 'same with gitignore starting with BOM' '
+       printf "\357\273\277ignored\n" >.gitignore &&
+       mkdir -p untracked &&
+       : >untracked/ignored &&
+       : >untracked/uncommitted &&
+       git status --porcelain --ignored >actual &&
+       test_cmp expected actual
+'
+
 cat >expected <<\EOF
 ?? .gitignore
 ?? actual