Preserve tree filemode in index during checkout Don't try to determine whether the system supports file modes when putting the tree data in the index during checkout. The tree's mode is canonical and did not come from stat(2) in the first place.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
diff --git a/src/checkout.c b/src/checkout.c
index cfb0e72..9629290 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -1217,8 +1217,7 @@ static int checkout_update_index(
memset(&entry, 0, sizeof(entry));
entry.path = (char *)file->path; /* cast to prevent warning */
- git_index_entry__init_from_stat(
- &entry, st, !(git_index_caps(data->index) & GIT_INDEXCAP_NO_FILEMODE));
+ git_index_entry__init_from_stat(&entry, st, true);
git_oid_cpy(&entry.oid, &file->oid);
return git_index_add(data->index, &entry);
diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c
index f0699fd..047c9ed 100644
--- a/tests/checkout/tree.c
+++ b/tests/checkout/tree.c
@@ -925,3 +925,26 @@ void test_checkout_tree__fails_when_conflicts_exist_in_index(void)
git_object_free(obj);
}
+
+void test_checkout_tree__filemode_preserved_in_index(void)
+{
+ git_oid executable_oid;
+ git_commit *commit;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ git_index *index;
+ const git_index_entry *entry;
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ cl_git_pass(git_oid_fromstr(&executable_oid, "afe4393b2b2a965f06acf2ca9658eaa01e0cd6b6"));
+ cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid));
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+
+ cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts));
+ cl_assert(entry = git_index_get_bypath(index, "executable.txt", 0));
+ cl_assert_equal_i(0100755, entry->mode);
+
+ git_commit_free(commit);
+ git_index_free(index);
+}
diff --git a/tests/resources/testrepo/.gitted/objects/1d/d0968be3ff95fcaecb6fa4245662db9fdc4568 b/tests/resources/testrepo/.gitted/objects/1d/d0968be3ff95fcaecb6fa4245662db9fdc4568
new file mode 100644
index 0000000..97c6b2c
Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/1d/d0968be3ff95fcaecb6fa4245662db9fdc4568 differ
diff --git a/tests/resources/testrepo/.gitted/objects/af/e4393b2b2a965f06acf2ca9658eaa01e0cd6b6 b/tests/resources/testrepo/.gitted/objects/af/e4393b2b2a965f06acf2ca9658eaa01e0cd6b6
new file mode 100644
index 0000000..6948f1b
Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/af/e4393b2b2a965f06acf2ca9658eaa01e0cd6b6 differ
diff --git a/tests/resources/testrepo/.gitted/objects/ce/054d4c5e3c83522aed8bc061987b46b7ede3be b/tests/resources/testrepo/.gitted/objects/ce/054d4c5e3c83522aed8bc061987b46b7ede3be
new file mode 100644
index 0000000..4910e4c
Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/ce/054d4c5e3c83522aed8bc061987b46b7ede3be differ