summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2014-07-31 21:16:40 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2014-07-31 21:16:40 +0200
commitb69256816f2ea27cfa99d906363fc292517b43a4 (patch)
tree8d2432dd34d2201286baeb194c6d3bb328ee25ba
parent28f087c8642ff9c8dd6964e101e6d8539db6281a (diff)
downloadlibgit2-cmn/treebuilder-set-attribute.tar.gz
treebuilder: set the attributes before sorting and insertingcmn/treebuilder-set-attribute
We need to set the attributes before we try to insert it into the vector, as the comparison function needs to know whether the entry is a tree or not.
-rw-r--r--src/tree.c9
-rw-r--r--tests/object/tree/write.c61
2 files changed, 67 insertions, 3 deletions
diff --git a/src/tree.c b/src/tree.c
index b64efe460..4ddb26b2d 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -667,10 +667,16 @@ int git_treebuilder_insert(
entry->removed = 0;
bld->entrycount++;
}
+
+ entry->attr = filemode;
+ git_oid_cpy(&entry->oid, id);
} else {
entry = alloc_entry(filename);
GITERR_CHECK_ALLOC(entry);
+ entry->attr = filemode;
+ git_oid_cpy(&entry->oid, id);
+
if (git_vector_insert_sorted(&bld->entries, entry, NULL) < 0) {
git__free(entry);
return -1;
@@ -679,9 +685,6 @@ int git_treebuilder_insert(
bld->entrycount++;
}
- git_oid_cpy(&entry->oid, id);
- entry->attr = filemode;
-
if (entry_out)
*entry_out = entry;
diff --git a/tests/object/tree/write.c b/tests/object/tree/write.c
index 45356e807..ef7adaf20 100644
--- a/tests/object/tree/write.c
+++ b/tests/object/tree/write.c
@@ -396,3 +396,64 @@ void test_object_tree_write__cruel_paths(void)
git_tree_free(tree);
}
+
+void test_object_tree_write__from_tree_git_sorting(void)
+{
+ git_index *index;
+ git_odb *db;
+ git_treebuilder *bld;
+ git_oid first_tree = {{0}}, second_tree = {{0}}, subtree_id = {{0}}, second_tree_bld = {{0}};
+ git_tree *tree;
+ git_index_entry entry = {{0}};
+ const char *foo = "foo\n";
+ const char *bar = "bar\n";
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+ cl_git_pass(git_index_clear(index));
+ cl_git_pass(git_repository_odb(&db, g_repo));
+
+ cl_git_pass(git_odb_write(&entry.id, db, foo, strlen(foo), GIT_OBJ_BLOB));
+ entry.mode = GIT_FILEMODE_BLOB;
+ entry.path = "foo.txt";
+
+ cl_git_pass(git_index_add(index, &entry));
+ cl_git_pass(git_index_write_tree(&first_tree, index));
+
+ /* Clear the index and re-add so we don't use any tree caches */
+ cl_git_pass(git_index_clear(index));
+ cl_git_pass(git_index_add(index, &entry));
+
+ cl_git_pass(git_odb_write(&entry.id, db, bar, strlen(bar), GIT_OBJ_BLOB));
+ entry.mode = GIT_FILEMODE_BLOB;
+ entry.path = "foo/bar";
+
+ cl_git_pass(git_index_add(index, &entry));
+ cl_git_pass(git_index_write_tree(&second_tree, index));
+
+ /*
+ * The index has now written the tree from scratch. We will
+ * create a builder taking the first tree as a starting point
+ * and create the second tree.
+ */
+
+ cl_git_pass(git_treebuilder_create(&bld, NULL));
+
+ cl_git_pass(git_treebuilder_insert(NULL, bld, "bar", &entry.id, entry.mode));
+ cl_git_pass(git_treebuilder_write(&subtree_id, g_repo, bld));
+ git_treebuilder_free(bld);
+
+ /* assert subtree_id is the same as the one from the index */
+
+ cl_git_pass(git_tree_lookup(&tree, g_repo, &first_tree));
+ cl_git_pass(git_treebuilder_create(&bld, tree));
+
+ cl_git_pass(git_treebuilder_insert(NULL, bld, "foo", &subtree_id, GIT_FILEMODE_TREE));
+ cl_git_pass(git_treebuilder_write(&second_tree_bld, g_repo, bld));
+ git_treebuilder_free(bld);
+
+ cl_assert(!git_oid_cmp(&second_tree, &second_tree_bld));
+
+ git_tree_free(tree);
+ git_odb_free(db);
+ git_index_free(index);
+}