From 922496562b82d79e9c4138b69299801274b7bf1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 19 May 2016 15:21:26 +0200 Subject: [PATCH 1/3] tree: use testrepo2 for the tree updater tests This gives us trees with subdirectories, which the new test needs. --- tests/object/tree/update.c | 47 ++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/tests/object/tree/update.c b/tests/object/tree/update.c index 210a504748b..92704caadf7 100644 --- a/tests/object/tree/update.c +++ b/tests/object/tree/update.c @@ -5,12 +5,12 @@ static git_repository *g_repo; void test_object_tree_update__initialize(void) { - g_repo = cl_git_sandbox_init("testrepo"); + g_repo = cl_git_sandbox_init("testrepo2"); } void test_object_tree_update__cleanup(void) { - cl_git_sandbox_cleanup(); + cl_git_sandbox_cleanup(); } void test_object_tree_update__remove_blob(void) @@ -24,7 +24,36 @@ void test_object_tree_update__remove_blob(void) { GIT_TREE_UPDATE_REMOVE, {{0}}, GIT_FILEMODE_BLOB /* ignored */, path}, }; - cl_git_pass(git_oid_fromstr(&base_id, "45dd856fdd4d89b884c340ba0e047752d9b085d6")); + cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); + cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); + + /* Create it with an index */ + cl_git_pass(git_index_new(&idx)); + cl_git_pass(git_index_read_tree(idx, base_tree)); + cl_git_pass(git_index_remove(idx, path, 0)); + cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo)); + git_index_free(idx); + + /* Perform the same operation via the tree updater */ + cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 1, updates)); + + cl_assert_equal_oid(&tree_index_id, &tree_updater_id); + + git_tree_free(base_tree); +} + +void test_object_tree_update__remove_blob_deeper(void) +{ + git_oid tree_index_id, tree_updater_id, base_id; + git_tree *base_tree; + git_index *idx; + const char *path = "subdir/README"; + + git_tree_update updates[] = { + { GIT_TREE_UPDATE_REMOVE, {{0}}, GIT_FILEMODE_BLOB /* ignored */, path}, + }; + + cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); /* Create it with an index */ @@ -54,7 +83,7 @@ void test_object_tree_update__replace_blob(void) { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, path}, }; - cl_git_pass(git_oid_fromstr(&base_id, "45dd856fdd4d89b884c340ba0e047752d9b085d6")); + cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); /* Create it with an index */ @@ -62,7 +91,7 @@ void test_object_tree_update__replace_blob(void) cl_git_pass(git_index_read_tree(idx, base_tree)); entry.path = path; - cl_git_pass(git_oid_fromstr(&entry.id, "3697d64be941a53d4ae8f6a271e4e3fa56b022cc")); + cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92")); entry.mode = GIT_FILEMODE_BLOB; cl_git_pass(git_index_add(idx, &entry)); @@ -70,7 +99,7 @@ void test_object_tree_update__replace_blob(void) git_index_free(idx); /* Perform the same operation via the tree updater */ - cl_git_pass(git_oid_fromstr(&updates[0].id, "3697d64be941a53d4ae8f6a271e4e3fa56b022cc")); + cl_git_pass(git_oid_fromstr(&updates[0].id, "fa49b077972391ad58037050f2a75f74e3671e92")); cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 1, updates)); cl_assert_equal_oid(&tree_index_id, &tree_updater_id); @@ -97,14 +126,14 @@ void test_object_tree_update__add_blobs(void) { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[2]}, }; - cl_git_pass(git_oid_fromstr(&base_id, "45dd856fdd4d89b884c340ba0e047752d9b085d6")); + cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); entry.mode = GIT_FILEMODE_BLOB; - cl_git_pass(git_oid_fromstr(&entry.id, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")); + cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92")); for (i = 0; i < 3; i++) { - cl_git_pass(git_oid_fromstr(&updates[i].id, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")); + cl_git_pass(git_oid_fromstr(&updates[i].id, "fa49b077972391ad58037050f2a75f74e3671e92")); } for (i = 0; i < 2; i++) { From 6ee08d2cd0671d42e4148988863a6a40fbe721cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 19 May 2016 15:22:02 +0200 Subject: [PATCH 2/3] tree: use the basename for the entry removal When we want to remove the file, use the basename as the name of the entry to remove, instead of the full one, which includes the directories we've inserted into the stack. --- src/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tree.c b/src/tree.c index af293d26489..c5a13eaa1a2 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1230,7 +1230,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli break; } case GIT_TREE_UPDATE_REMOVE: - error = git_treebuilder_remove(git_array_last(stack)->bld, update->path); + error = git_treebuilder_remove(git_array_last(stack)->bld, git_path_basename(update->path)); break; default: giterr_set(GITERR_TREE, "unkown action for update"); From 534123053633c05faff3a2de8cadd7291596bb21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 19 May 2016 15:29:53 +0200 Subject: [PATCH 3/3] tree: plug leaks in the tree updater --- src/tree.c | 14 +++++++++++--- tests/object/tree/update.c | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/tree.c b/src/tree.c index c5a13eaa1a2..4a9051cf821 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1216,22 +1216,29 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli { /* Make sure we're replacing something of the same type */ tree_stack_entry *last = git_array_last(stack); - const char *basename = git_path_basename(update->path); + char *basename = git_path_basename(update->path); const git_tree_entry *e = git_treebuilder_get(last->bld, basename); if (e && git_tree_entry_type(e) != git_object__type_from_filemode(update->filemode)) { + git__free(basename); giterr_set(GITERR_TREE, "Cannot replace '%s' with '%s' at '%s'", git_object_type2string(git_tree_entry_type(e)), git_object_type2string(git_object__type_from_filemode(update->filemode)), update->path); - return -1; + error = -1; + goto cleanup; } error = git_treebuilder_insert(NULL, last->bld, basename, &update->id, update->filemode); + git__free(basename); break; } case GIT_TREE_UPDATE_REMOVE: - error = git_treebuilder_remove(git_array_last(stack)->bld, git_path_basename(update->path)); + { + char *basename = git_path_basename(update->path); + error = git_treebuilder_remove(git_array_last(stack)->bld, basename); + git__free(basename); break; + } default: giterr_set(GITERR_TREE, "unkown action for update"); error = -1; @@ -1275,6 +1282,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli } } + git_buf_free(&component); git_array_clear(stack); git_vector_free(&entries); return error; diff --git a/tests/object/tree/update.c b/tests/object/tree/update.c index 92704caadf7..32e029a6d51 100644 --- a/tests/object/tree/update.c +++ b/tests/object/tree/update.c @@ -127,7 +127,6 @@ void test_object_tree_update__add_blobs(void) }; cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); - cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); entry.mode = GIT_FILEMODE_BLOB; cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92")); @@ -161,6 +160,8 @@ void test_object_tree_update__add_blobs(void) cl_assert_equal_oid(&tree_index_id, &tree_updater_id); } + + git_tree_free(base_tree); } void test_object_tree_update__add_conflict(void)