Commit 8e60c712acef798a6b3913359f8d9dffcddf7256

Adam Roben 2012-06-07T09:50:19

Fix git_status_file for files that start with a character > 0x7f git_status_file would always return GIT_ENOTFOUND for these files. The underlying bug was that git__strcmp_cb, which is used by git_path_with_stat_cmp to sort entries in the working directory, compares strings based on unsigned chars (this is confirmed by the strcmp(3) manpage), while git__prefixcmp, which is used by workdir_iterator__entry_cmp to search for a path in the working directory, compares strings based on char. So the sort puts this path at the end of the list, while the search expects it to be at the beginning. The fix was simply to make git__prefixcmp compare using unsigned chars, just like strcmp(3). The rest of the change is just adding/updating tests.

diff --git a/src/util.c b/src/util.c
index ce77020..3093cd7 100644
--- a/src/util.c
+++ b/src/util.c
@@ -179,7 +179,7 @@ void git__strtolower(char *str)
 int git__prefixcmp(const char *str, const char *prefix)
 {
 	for (;;) {
-		char p = *(prefix++), s;
+		unsigned char p = *(prefix++), s;
 		if (!p)
 			return 0;
 		if ((s = *(str++)) != p)
diff --git a/tests-clar/diff/iterator.c b/tests-clar/diff/iterator.c
index be29bea..eee8481 100644
--- a/tests-clar/diff/iterator.c
+++ b/tests-clar/diff/iterator.c
@@ -474,13 +474,14 @@ static const char *status_paths[] = {
 	"subdir/current_file",
 	"subdir/modified_file",
 	"subdir/new_file",
+	"\xe8\xbf\x99",
 	NULL
 };
 
 void test_diff_iterator__workdir_1(void)
 {
 	workdir_iterator_test(
-		"status", NULL, NULL, 12, 1, status_paths, "ignored_file");
+		"status", NULL, NULL, 13, 1, status_paths, "ignored_file");
 }
 
 static const char *status_paths_range_0[] = {
@@ -527,13 +528,14 @@ static const char *status_paths_range_4[] = {
 	"subdir/current_file",
 	"subdir/modified_file",
 	"subdir/new_file",
+	"\xe8\xbf\x99",
 	NULL
 };
 
 void test_diff_iterator__workdir_1_ranged_4(void)
 {
 	workdir_iterator_test(
-		"status", "subdir/", NULL, 3, 0, status_paths_range_4, NULL);
+		"status", "subdir/", NULL, 4, 0, status_paths_range_4, NULL);
 }
 
 static const char *status_paths_range_5[] = {
@@ -551,7 +553,7 @@ void test_diff_iterator__workdir_1_ranged_5(void)
 void test_diff_iterator__workdir_1_ranged_empty_0(void)
 {
 	workdir_iterator_test(
-		"status", "z_does_not_exist", NULL,
+		"status", "\xff_does_not_exist", NULL,
 		0, 0, NULL, NULL);
 }
 
diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c
index 1ea1af8..42152f1 100644
--- a/tests-clar/diff/workdir.c
+++ b/tests-clar/diff/workdir.c
@@ -37,12 +37,12 @@ void test_diff_workdir__to_index(void)
 	 * - git diff
 	 * - mv .git .gitted
 	 */
-	cl_assert_equal_i(12, exp.files);
+	cl_assert_equal_i(13, exp.files);
 	cl_assert_equal_i(0, exp.file_adds);
 	cl_assert_equal_i(4, exp.file_dels);
 	cl_assert_equal_i(4, exp.file_mods);
 	cl_assert_equal_i(1, exp.file_ignored);
-	cl_assert_equal_i(3, exp.file_untracked);
+	cl_assert_equal_i(4, exp.file_untracked);
 
 	cl_assert_equal_i(8, exp.hunks);
 
@@ -87,12 +87,12 @@ void test_diff_workdir__to_tree(void)
 	cl_git_pass(git_diff_foreach(
 		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
 
-	cl_assert(exp.files == 13);
+	cl_assert(exp.files == 14);
 	cl_assert(exp.file_adds == 0);
 	cl_assert(exp.file_dels == 4);
 	cl_assert(exp.file_mods == 4);
 	cl_assert(exp.file_ignored == 1);
-	cl_assert(exp.file_untracked == 4);
+	cl_assert(exp.file_untracked == 5);
 
 	/* Since there is no git diff equivalent, let's just assume that the
 	 * text diffs produced by git_diff_foreach are accurate here.  We will
@@ -115,12 +115,12 @@ void test_diff_workdir__to_tree(void)
 	cl_git_pass(git_diff_foreach(
 		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
 
-	cl_assert(exp.files == 14);
+	cl_assert(exp.files == 15);
 	cl_assert(exp.file_adds == 2);
 	cl_assert(exp.file_dels == 5);
 	cl_assert(exp.file_mods == 4);
 	cl_assert(exp.file_ignored == 1);
-	cl_assert(exp.file_untracked == 2);
+	cl_assert(exp.file_untracked == 3);
 
 	cl_assert(exp.hunks == 11);
 
@@ -144,12 +144,12 @@ void test_diff_workdir__to_tree(void)
 	cl_git_pass(git_diff_foreach(
 		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
 
-	cl_assert(exp.files == 15);
+	cl_assert(exp.files == 16);
 	cl_assert(exp.file_adds == 5);
 	cl_assert(exp.file_dels == 4);
 	cl_assert(exp.file_mods == 3);
 	cl_assert(exp.file_ignored == 1);
-	cl_assert(exp.file_untracked == 2);
+	cl_assert(exp.file_untracked == 3);
 
 	cl_assert(exp.hunks == 12);
 
@@ -182,12 +182,12 @@ void test_diff_workdir__to_index_with_pathspec(void)
 	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
 	cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));
 
-	cl_assert_equal_i(12, exp.files);
+	cl_assert_equal_i(13, exp.files);
 	cl_assert_equal_i(0, exp.file_adds);
 	cl_assert_equal_i(4, exp.file_dels);
 	cl_assert_equal_i(4, exp.file_mods);
 	cl_assert_equal_i(1, exp.file_ignored);
-	cl_assert_equal_i(3, exp.file_untracked);
+	cl_assert_equal_i(4, exp.file_untracked);
 
 	git_diff_list_free(diff);
 
diff --git "a/tests-clar/resources/status/\350\277\231" "b/tests-clar/resources/status/\350\277\231"
new file mode 100644
index 0000000..f0ff9a1
--- /dev/null
+++ "b/tests-clar/resources/status/\350\277\231"
@@ -0,0 +1 @@
+This
diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h
index f109717..043b830 100644
--- a/tests-clar/status/status_data.h
+++ b/tests-clar/status/status_data.h
@@ -19,6 +19,8 @@ static const char *entry_paths0[] = {
 	"subdir/deleted_file",
 	"subdir/modified_file",
 	"subdir/new_file",
+
+	"\xe8\xbf\x99",
 };
 
 static const unsigned int entry_statuses0[] = {
@@ -38,9 +40,11 @@ static const unsigned int entry_statuses0[] = {
 	GIT_STATUS_WT_DELETED,
 	GIT_STATUS_WT_MODIFIED,
 	GIT_STATUS_WT_NEW,
+
+	GIT_STATUS_WT_NEW,
 };
 
-static const size_t entry_count0 = 15;
+static const size_t entry_count0 = 16;
 
 /* entries for a copy of tests/resources/status with all content
  * deleted from the working directory
@@ -108,6 +112,7 @@ static const char *entry_paths3[] = {
 	"subdir/current_file",
 	"subdir/deleted_file",
 	"subdir/modified_file",
+	"\xe8\xbf\x99",
 };
 
 static const unsigned int entry_statuses3[] = {
@@ -132,9 +137,10 @@ static const unsigned int entry_statuses3[] = {
 	GIT_STATUS_WT_DELETED,
 	GIT_STATUS_WT_DELETED,
 	GIT_STATUS_WT_DELETED,
+	GIT_STATUS_WT_NEW,
 };
 
-static const size_t entry_count3 = 21;
+static const size_t entry_count3 = 22;
 
 
 /* entries for a copy of tests/resources/status with some mods
@@ -163,7 +169,8 @@ static const char *entry_paths4[] = {
 	"subdir/deleted_file",
 	"subdir/modified_file",
 	"zzz_new_dir/new_file",
-	"zzz_new_file"
+	"zzz_new_file",
+	"\xe8\xbf\x99",
 };
 
 static const unsigned int entry_statuses4[] = {
@@ -189,6 +196,7 @@ static const unsigned int entry_statuses4[] = {
 	GIT_STATUS_WT_DELETED,
 	GIT_STATUS_WT_NEW,
 	GIT_STATUS_WT_NEW,
+	GIT_STATUS_WT_NEW,
 };
 
-static const size_t entry_count4 = 22;
+static const size_t entry_count4 = 23;