Merge pull request #3808 from ethomson/read_index_fixes `git_index_read_index` fixes
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
diff --git a/src/index.c b/src/index.c
index 31cb27d..20ab6a1 100644
--- a/src/index.c
+++ b/src/index.c
@@ -2968,6 +2968,8 @@ int git_index_read_index(
*remove_entry = NULL;
int diff;
+ error = 0;
+
if (old_entry && new_entry)
diff = git_index_entry_cmp(old_entry, new_entry);
else if (!old_entry && new_entry)
@@ -2985,7 +2987,8 @@ int git_index_read_index(
/* Path and stage are equal, if the OID is equal, keep it to
* keep the stat cache data.
*/
- if (git_oid_equal(&old_entry->id, &new_entry->id)) {
+ if (git_oid_equal(&old_entry->id, &new_entry->id) &&
+ old_entry->mode == new_entry->mode) {
add_entry = (git_index_entry *)old_entry;
} else {
dup_entry = (git_index_entry *)new_entry;
@@ -2996,8 +2999,17 @@ int git_index_read_index(
if (dup_entry) {
if ((error = index_entry_dup_nocache(&add_entry, index, dup_entry)) < 0)
goto done;
+
+ index_entry_adjust_namemask(add_entry,
+ ((struct entry_internal *)add_entry)->pathlen);
}
+ /* invalidate this path in the tree cache if this is new (to
+ * invalidate the parent trees)
+ */
+ if (dup_entry && !remove_entry && index->tree)
+ git_tree_cache_invalidate_path(index->tree, dup_entry->path);
+
if (add_entry) {
if ((error = git_vector_insert(&new_entries, add_entry)) == 0)
INSERT_IN_MAP_EX(index, new_entries_map, add_entry, error);
diff --git a/tests/index/read_index.c b/tests/index/read_index.c
index 82a771d..6d14bc9 100644
--- a/tests/index/read_index.c
+++ b/tests/index/read_index.c
@@ -71,3 +71,58 @@ void test_index_read_index__maintains_stat_cache(void)
}
}
}
+
+static bool roundtrip_with_read_index(const char *tree_idstr)
+{
+ git_oid tree_id, new_tree_id;
+ git_tree *tree;
+ git_index *tree_index;
+
+ cl_git_pass(git_oid_fromstr(&tree_id, tree_idstr));
+ cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
+ cl_git_pass(git_index_new(&tree_index));
+ cl_git_pass(git_index_read_tree(tree_index, tree));
+ cl_git_pass(git_index_read_index(_index, tree_index));
+ cl_git_pass(git_index_write_tree(&new_tree_id, _index));
+
+ git_tree_free(tree);
+ git_index_free(tree_index);
+
+ return git_oid_equal(&tree_id, &new_tree_id);
+}
+
+void test_index_read_index__produces_treesame_indexes(void)
+{
+ roundtrip_with_read_index("53fc32d17276939fc79ed05badaef2db09990016");
+ roundtrip_with_read_index("944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
+ roundtrip_with_read_index("1810dff58d8a660512d4832e740f692884338ccd");
+ roundtrip_with_read_index("d52a8fe84ceedf260afe4f0287bbfca04a117e83");
+ roundtrip_with_read_index("c36d8ea75da8cb510fcb0c408c1d7e53f9a99dbe");
+ roundtrip_with_read_index("7b2417a23b63e1fdde88c80e14b33247c6e5785a");
+ roundtrip_with_read_index("f82a8eb4cb20e88d1030fd10d89286215a715396");
+ roundtrip_with_read_index("fd093bff70906175335656e6ce6ae05783708765");
+ roundtrip_with_read_index("ae90f12eea699729ed24555e40b9fd669da12a12");
+}
+
+void test_index_read_index__read_and_writes(void)
+{
+ git_oid tree_id, new_tree_id;
+ git_tree *tree;
+ git_index *tree_index, *new_index;
+
+ cl_git_pass(git_oid_fromstr(&tree_id, "ae90f12eea699729ed24555e40b9fd669da12a12"));
+ cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
+ cl_git_pass(git_index_new(&tree_index));
+ cl_git_pass(git_index_read_tree(tree_index, tree));
+ cl_git_pass(git_index_read_index(_index, tree_index));
+ cl_git_pass(git_index_write(_index));
+
+ cl_git_pass(git_index_open(&new_index, git_index_path(_index)));
+ cl_git_pass(git_index_write_tree_to(&new_tree_id, new_index, _repo));
+
+ cl_assert_equal_oid(&tree_id, &new_tree_id);
+
+ git_tree_free(tree);
+ git_index_free(tree_index);
+ git_index_free(new_index);
+}
diff --git a/tests/rebase/inmemory.c b/tests/rebase/inmemory.c
index 7ce865b..367d6b3 100644
--- a/tests/rebase/inmemory.c
+++ b/tests/rebase/inmemory.c
@@ -165,3 +165,46 @@ void test_rebase_inmemory__no_common_ancestor(void)
git_reference_free(upstream_ref);
git_rebase_free(rebase);
}
+
+void test_rebase_inmemory__with_directories(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ git_annotated_commit *branch_head, *upstream_head;
+ git_rebase_operation *rebase_operation;
+ git_oid commit_id, tree_id;
+ git_commit *commit;
+ git_rebase_options opts = GIT_REBASE_OPTIONS_INIT;
+
+ opts.inmemory = true;
+
+ git_oid_fromstr(&tree_id, "a4d6d9c3d57308fd8e320cf2525bae8f1adafa57");
+
+ cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/deep_gravy"));
+ cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
+
+ cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
+ cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
+
+ cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &opts));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase));
+
+ cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
+ cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit));
+
+ git_commit_free(commit);
+ git_annotated_commit_free(branch_head);
+ git_annotated_commit_free(upstream_head);
+ git_reference_free(branch_ref);
+ git_reference_free(upstream_ref);
+ git_rebase_free(rebase);
+}
diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c
index 74507e2..0f06ed1 100644
--- a/tests/rebase/merge.c
+++ b/tests/rebase/merge.c
@@ -750,3 +750,42 @@ void test_rebase_merge__custom_merge_options(void)
git_rebase_free(rebase);
}
+void test_rebase_merge__with_directories(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ git_annotated_commit *branch_head, *upstream_head;
+ git_rebase_operation *rebase_operation;
+ git_oid commit_id, tree_id;
+ git_commit *commit;
+
+ git_oid_fromstr(&tree_id, "a4d6d9c3d57308fd8e320cf2525bae8f1adafa57");
+
+ cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/deep_gravy"));
+ cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
+
+ cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
+ cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
+
+ cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase));
+
+ cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
+ cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit));
+
+ git_commit_free(commit);
+ git_annotated_commit_free(branch_head);
+ git_annotated_commit_free(upstream_head);
+ git_reference_free(branch_ref);
+ git_reference_free(upstream_ref);
+ git_rebase_free(rebase);
+}
diff --git a/tests/resources/rebase/.gitted/objects/1d/83f106355e4309a293e42ad2a2c4b8bdbe77ae b/tests/resources/rebase/.gitted/objects/1d/83f106355e4309a293e42ad2a2c4b8bdbe77ae
new file mode 100644
index 0000000..6230fdf
Binary files /dev/null and b/tests/resources/rebase/.gitted/objects/1d/83f106355e4309a293e42ad2a2c4b8bdbe77ae differ
diff --git a/tests/resources/rebase/.gitted/objects/5a/72bf3bf964fdb176ffa4587312e69e2039695a b/tests/resources/rebase/.gitted/objects/5a/72bf3bf964fdb176ffa4587312e69e2039695a
new file mode 100644
index 0000000..80eb921
Binary files /dev/null and b/tests/resources/rebase/.gitted/objects/5a/72bf3bf964fdb176ffa4587312e69e2039695a differ
diff --git a/tests/resources/rebase/.gitted/objects/77/0f14546ee2563a26c52afa5cc4139a96e5d360 b/tests/resources/rebase/.gitted/objects/77/0f14546ee2563a26c52afa5cc4139a96e5d360
new file mode 100644
index 0000000..6091d54
Binary files /dev/null and b/tests/resources/rebase/.gitted/objects/77/0f14546ee2563a26c52afa5cc4139a96e5d360 differ
diff --git a/tests/resources/rebase/.gitted/objects/91/4f3c604d1098847b7fe275f659ee329878153f b/tests/resources/rebase/.gitted/objects/91/4f3c604d1098847b7fe275f659ee329878153f
new file mode 100644
index 0000000..726bf91
Binary files /dev/null and b/tests/resources/rebase/.gitted/objects/91/4f3c604d1098847b7fe275f659ee329878153f differ
diff --git a/tests/resources/rebase/.gitted/objects/d9/c5185186d95d233dc007c1927cb3bdd6cde35b b/tests/resources/rebase/.gitted/objects/d9/c5185186d95d233dc007c1927cb3bdd6cde35b
new file mode 100644
index 0000000..3c340db
Binary files /dev/null and b/tests/resources/rebase/.gitted/objects/d9/c5185186d95d233dc007c1927cb3bdd6cde35b differ
diff --git a/tests/resources/rebase/.gitted/refs/heads/deep_gravy b/tests/resources/rebase/.gitted/refs/heads/deep_gravy
new file mode 100644
index 0000000..efbe5f0
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/deep_gravy
@@ -0,0 +1 @@
+d9c5185186d95d233dc007c1927cb3bdd6cde35b