Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions src/libgit2/repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,8 +768,14 @@ static int find_repo_traverse(

git_str_clear(&out->gitdir);

if ((error = git_fs_path_prettify(&path, start_path, NULL)) < 0)
return error;
if ((error = git_fs_path_prettify(&path, start_path, NULL)) < 0) {
if (error != GIT_ENOTFOUND)
return error;

git_error_clear();
if ((error = git_str_sets(&path, start_path)) < 0)
goto out;
}

/*
* In each loop we look first for a `.git` dir within the
Expand Down Expand Up @@ -810,7 +816,7 @@ static int find_repo_traverse(

if (S_ISDIR(st.st_mode)) {
if ((error = is_valid_repository_path(&is_valid, &path, &common_link, flags)) < 0)
goto out;
goto out;

if (is_valid) {
if ((error = git_fs_path_to_dir(&path)) < 0 ||
Expand All @@ -821,7 +827,7 @@ static int find_repo_traverse(
goto out;

git_str_swap(&common_link, &out->commondir);

break;
}
} else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
Expand All @@ -831,16 +837,20 @@ static int find_repo_traverse(

if (is_valid) {
git_str_swap(&out->gitdir, &repo_link);

if ((error = git_str_put(&out->gitlink, path.ptr, path.size)) < 0)
goto out;

git_str_swap(&common_link, &out->commondir);
goto out;
git_str_swap(&common_link, &out->commondir);
}
break;
}
}

/*
* Stop searching because relative paths that reach "." cannot be walked up further.
*/
if (min_iterations == 0 && git__strcmp(path.ptr, ".") == 0)
break;
/*
* Move up one directory. If we're in_dot_git, we'll
* search the parent itself next. If we're !in_dot_git,
Expand Down Expand Up @@ -879,6 +889,9 @@ static int find_repo_traverse(
goto out;
}

/* If we found the repository, we need prettify gitdir since prettifying start_path may have failed above due to non existing child folder */
error = git_fs_path_prettify_dir(&out->gitdir, out->gitdir.ptr, NULL);

out:
if (error)
repo_paths_dispose(out);
Expand Down
41 changes: 39 additions & 2 deletions tests/libgit2/repo/discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,20 @@
#define ALTERNATE_MALFORMED_FOLDER2 DISCOVER_FOLDER "/alternate_malformed_repo2"
#define ALTERNATE_MALFORMED_FOLDER3 DISCOVER_FOLDER "/alternate_malformed_repo3"
#define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo"
#define NO_REPOSITORY_FOLDER_SUB TEMP_REPO_FOLDER "no_repo/sub"

static void ensure_repository_discover(const char *start_path,
const char *ceiling_dirs,
const char *expected_path)
{
git_buf found_path = GIT_BUF_INIT;
git_str resolved = GIT_STR_INIT;

git_str_attach(&resolved, p_realpath(expected_path, NULL), 0);
cl_assert(resolved.size > 0);
cl_git_pass(git_fs_path_to_dir(&resolved));
cl_git_pass(git_repository_discover(&found_path, start_path, 1, ceiling_dirs));

cl_assert_equal_s(found_path.ptr, resolved.ptr);

git_str_dispose(&resolved);
Expand Down Expand Up @@ -108,6 +109,7 @@ void test_repo_discover__initialize(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_pass(git_futils_mkdir_r(NO_REPOSITORY_FOLDER_SUB, mode));

git_repository_free(repo);
}
Expand All @@ -133,6 +135,41 @@ 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_nonexistent_subpath_inside_repo_succeeds(void)
{
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB "/missing1/missing2",
ceiling_dirs.ptr,
SUB_REPOSITORY_GITDIR);
}

void test_repo_discover__discovering_nonexistent_branch_without_existing_parent_fails(void)
{
cl_assert_equal_i(
GIT_ENOTFOUND,
git_repository_discover(
&discovered,
TEMP_REPO_FOLDER "missing_parent/missing_child",
0,
NULL));
}

void test_repo_discover__discovering_relative_nonrepo_path_with_dot_ceiling_fails(void)
{
git_str ceiling = GIT_STR_INIT;

append_ceiling_dir(&ceiling, ".");

cl_assert_equal_i(
GIT_ENOTFOUND,
git_repository_discover(
&discovered,
NO_REPOSITORY_FOLDER_SUB "/missing",
0,
ceiling.ptr));

git_str_dispose(&ceiling);
}

void test_repo_discover__discovering_repo_with_subdirectory_succeeds(void)
{
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
Expand Down