Commit 4aa36ff2c0fe2e7b29220737c757ffff99e00059

Patrick Steinhardt 2019-05-21T12:18:47

Merge pull request #5075 from libgit2/ethomson/ignore_skip_bom Skip UTF8 BOM in ignore files

diff --git a/src/attr_file.c b/src/attr_file.c
index 8619647..ddd4470 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -10,6 +10,7 @@
 #include "repository.h"
 #include "filebuf.h"
 #include "attrcache.h"
+#include "buf_text.h"
 #include "git2/blob.h"
 #include "git2/tree.h"
 #include "blob.h"
@@ -108,9 +109,12 @@ int git_attr_file__load(
 	int error = 0;
 	git_blob *blob = NULL;
 	git_buf content = GIT_BUF_INIT;
+	const char *content_str;
 	git_attr_file *file;
 	struct stat st;
 	bool nonexistent = false;
+	int bom_offset;
+	git_bom_t bom;
 
 	*out = NULL;
 
@@ -159,13 +163,20 @@ int git_attr_file__load(
 	if ((error = git_attr_file__new(&file, entry, source)) < 0)
 		goto cleanup;
 
+	/* advance over a UTF8 BOM */
+	content_str = git_buf_cstr(&content);
+	bom_offset = git_buf_text_detect_bom(&bom, &content);
+
+	if (bom == GIT_BOM_UTF8)
+		content_str += bom_offset;
+
 	/* store the key of the attr_reader; don't bother with cache
 	 * invalidation during the same attr reader session.
 	 */
 	if (attr_session)
 		file->session_key = attr_session->key;
 
-	if (parser && (error = parser(repo, file, git_buf_cstr(&content))) < 0) {
+	if (parser && (error = parser(repo, file, content_str)) < 0) {
 		git_attr_file__free(file);
 		goto cleanup;
 	}
diff --git a/tests/status/ignore.c b/tests/status/ignore.c
index 4965821..1da9ecf 100644
--- a/tests/status/ignore.c
+++ b/tests/status/ignore.c
@@ -1213,3 +1213,26 @@ void test_status_ignore__unignored_subdirs(void)
 	assert_is_ignored("dir/a.test");
 	refute_is_ignored("dir/subdir/a.test");
 }
+
+void test_status_ignore__skips_bom(void)
+{
+	static const char *test_files[] = {
+		"empty_standard_repo/a.test",
+		"empty_standard_repo/b.test",
+		"empty_standard_repo/c.test",
+		"empty_standard_repo/foo.txt",
+		"empty_standard_repo/bar.txt",
+		NULL
+	};
+
+	make_test_data("empty_standard_repo", test_files);
+	cl_git_mkfile(
+		"empty_standard_repo/.gitignore",
+		"\xEF\xBB\xBF*.test\n");
+
+	assert_is_ignored("a.test");
+	assert_is_ignored("b.test");
+	assert_is_ignored("c.test");
+	refute_is_ignored("foo.txt");
+	refute_is_ignored("bar.txt");
+}