diff options
-rw-r--r-- | src/repository.c | 2 | ||||
-rw-r--r-- | src/tree.c | 7 | ||||
-rw-r--r-- | tests/object/tree/update.c | 57 | ||||
-rw-r--r-- | tests/repo/discover.c | 160 |
4 files changed, 167 insertions, 59 deletions
diff --git a/src/repository.c b/src/repository.c index 7bdcefd40..5c4442360 100644 --- a/src/repository.c +++ b/src/repository.c @@ -410,7 +410,7 @@ static int find_repo( break; } } - else if (S_ISREG(st.st_mode)) { + else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) { error = read_gitfile(&repo_link, path.ptr); if (error < 0) break; diff --git a/src/tree.c b/src/tree.c index e338acca0..9655ad739 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1164,8 +1164,8 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli goto cleanup; for (i = 0; i < nupdates; i++) { - const git_tree_update *last_update = i == 0 ? NULL : &updates[i-1]; - const git_tree_update *update = &updates[i]; + const git_tree_update *last_update = i == 0 ? NULL : git_vector_get(&entries, i-1); + const git_tree_update *update = git_vector_get(&entries, i); size_t common_prefix = 0, steps_up, j; const char *path; @@ -1200,6 +1200,9 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli last = git_array_last(stack); entry = last->tree ? git_tree_entry_byname(last->tree, component.ptr) : NULL; + if (!entry) + entry = treebuilder_get(last->bld, component.ptr); + if (entry && git_tree_entry_type(entry) != GIT_OBJ_TREE) { giterr_set(GITERR_TREE, "D/F conflict when updating tree"); error = -1; diff --git a/tests/object/tree/update.c b/tests/object/tree/update.c index 54c4335f5..b76e8612a 100644 --- a/tests/object/tree/update.c +++ b/tests/object/tree/update.c @@ -196,6 +196,63 @@ void test_object_tree_update__add_blobs(void) git_tree_free(base_tree); } +void test_object_tree_update__add_blobs_unsorted(void) +{ + git_oid tree_index_id, tree_updater_id, base_id; + git_tree *base_tree; + git_index *idx; + git_index_entry entry = { {0} }; + int i; + const char *paths[] = { + "some/deep/path", + "a/path/elsewhere", + "some/other/path", + }; + + git_tree_update updates[] = { + { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[0]}, + { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[1]}, + { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[2]}, + }; + + cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); + + entry.mode = GIT_FILEMODE_BLOB; + cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92")); + + for (i = 0; i < 3; i++) { + cl_git_pass(git_oid_fromstr(&updates[i].id, "fa49b077972391ad58037050f2a75f74e3671e92")); + } + + for (i = 0; i < 2; i++) { + int j; + + /* Create it with an index */ + cl_git_pass(git_index_new(&idx)); + + base_tree = NULL; + if (i == 1) { + cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); + cl_git_pass(git_index_read_tree(idx, base_tree)); + } + + for (j = 0; j < 3; j++) { + entry.path = paths[j]; + cl_git_pass(git_index_add(idx, &entry)); + } + + cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo)); + git_index_free(idx); + + /* Perform the same operations via the tree updater */ + cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 3, updates)); + + cl_assert_equal_oid(&tree_index_id, &tree_updater_id); + } + + git_tree_free(base_tree); +} + void test_object_tree_update__add_conflict(void) { int i; diff --git a/tests/repo/discover.c b/tests/repo/discover.c index 358daee9f..48aa27581 100644 --- a/tests/repo/discover.c +++ b/tests/repo/discover.c @@ -9,6 +9,7 @@ #define SUB_REPOSITORY_FOLDER_NAME "sub_repo" #define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME +#define SUB_REPOSITORY_GITDIR SUB_REPOSITORY_FOLDER "/.git" #define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub" #define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub" #define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub" @@ -24,20 +25,26 @@ #define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo" static void ensure_repository_discover(const char *start_path, - const char *ceiling_dirs, - git_buf *expected_path) + const char *ceiling_dirs, + const char *expected_path) { - git_buf found_path = GIT_BUF_INIT; + git_buf found_path = GIT_BUF_INIT, resolved = GIT_BUF_INIT; + + git_buf_attach(&resolved, p_realpath(expected_path, NULL), 0); + cl_assert(resolved.size > 0); + cl_git_pass(git_path_to_dir(&resolved)); cl_git_pass(git_repository_discover(&found_path, start_path, 0, ceiling_dirs)); - //across_fs is always 0 as we can't automate the filesystem change tests - cl_assert_equal_s(found_path.ptr, expected_path->ptr); + + cl_assert_equal_s(found_path.ptr, resolved.ptr); + + git_buf_free(&resolved); git_buf_free(&found_path); } static void write_file(const char *path, const char *content) { git_file file; - int error; + int error; if (git_path_exists(path)) { cl_git_pass(p_unlink(path)); @@ -68,42 +75,30 @@ static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path) cl_assert(git_buf_oom(ceiling_dirs) == 0); } -void test_repo_discover__0(void) +static git_buf discovered; +static git_buf ceiling_dirs; + +void test_repo_discover__initialize(void) { - // test discover git_repository *repo; - git_buf ceiling_dirs_buf = GIT_BUF_INIT, repository_path = GIT_BUF_INIT, - sub_repository_path = GIT_BUF_INIT, found_path = GIT_BUF_INIT; - const char *ceiling_dirs; const mode_t mode = 0777; - git_futils_mkdir_r(DISCOVER_FOLDER, mode); - append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER); - ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs)); + git_buf_init(&discovered, 0); + git_buf_init(&ceiling_dirs, 0); + append_ceiling_dir(&ceiling_dirs, TEMP_REPO_FOLDER); cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1)); - cl_git_pass(git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs)); git_repository_free(repo); cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0)); cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode)); - cl_git_pass(git_repository_discover(&sub_repository_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); - cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode)); - ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, &sub_repository_path); cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, mode)); write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../"); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path); cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, mode)); write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:"); @@ -113,41 +108,94 @@ void test_repo_discover__0(void) write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n"); cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, mode)); write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist"); - cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs)); - cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs)); - cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs)); - append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER_SUB); - ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); + git_repository_free(repo); +} + +void test_repo_discover__cleanup(void) +{ + git_buf_free(&discovered); + git_buf_free(&ceiling_dirs); + cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES)); +} + +void test_repo_discover__discovering_repo_with_exact_path_succeeds(void) +{ + cl_git_pass(git_repository_discover(&discovered, DISCOVER_FOLDER, 0, ceiling_dirs.ptr)); + cl_git_pass(git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs.ptr)); +} + +void test_repo_discover__discovering_nonexistent_dir_fails(void) +{ + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, DISCOVER_FOLDER "-nonexistent", 0, NULL)); +} + +void test_repo_discover__discovering_repo_with_subdirectory_succeeds(void) +{ + ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); +} + +void test_repo_discover__discovering_repository_with_alternative_gitdir_succeeds(void) +{ + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs.ptr, DISCOVER_FOLDER); +} + +void test_repo_discover__discovering_repository_with_malformed_alternative_gitdir_fails(void) +{ + cl_git_fail(git_repository_discover(&discovered, ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs.ptr)); + cl_git_fail(git_repository_discover(&discovered, ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs.ptr)); + cl_git_fail(git_repository_discover(&discovered, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs.ptr)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs.ptr)); +} + +void test_repo_discover__discovering_repository_with_ceiling(void) +{ + append_ceiling_dir(&ceiling_dirs, SUB_REPOSITORY_FOLDER_SUB); /* this must pass as ceiling_directories cannot prevent the current * working directory to be checked */ - ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs)); - - append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER); - ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); - - //this must pass as ceiling_directories cannot predent the current - //working directory to be checked - ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs)); - - //.gitfile redirection should not be affected by ceiling directories - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path); + ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); - cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES)); - git_repository_free(repo); - git_buf_free(&ceiling_dirs_buf); - git_buf_free(&repository_path); - git_buf_free(&sub_repository_path); + ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs.ptr)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs.ptr)); +} + +void test_repo_discover__other_ceiling(void) +{ + append_ceiling_dir(&ceiling_dirs, SUB_REPOSITORY_FOLDER); + + /* this must pass as ceiling_directories cannot predent the current + * working directory to be checked */ + ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs.ptr)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs.ptr)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs.ptr)); } +void test_repo_discover__ceiling_should_not_affect_gitdir_redirection(void) +{ + append_ceiling_dir(&ceiling_dirs, SUB_REPOSITORY_FOLDER); + + /* gitfile redirection should not be affected by ceiling directories */ + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs.ptr, DISCOVER_FOLDER); +} + +void test_repo_discover__discovery_starting_at_file_succeeds(void) +{ + int fd; + + cl_assert((fd = p_creat(SUB_REPOSITORY_FOLDER "/file", 0600)) >= 0); + cl_assert(p_close(fd) == 0); + + ensure_repository_discover(SUB_REPOSITORY_FOLDER "/file", ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); +} |