Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix repository discovery with ceiling_dirs at current directory #3727

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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
42 changes: 25 additions & 17 deletions src/repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,21 +359,36 @@ static int find_repo(
git_buf path = GIT_BUF_INIT;
struct stat st;
dev_t initial_device = 0;
bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0);
int min_iterations;
bool in_dot_git;
int ceiling_offset;

git_buf_free(repo_path);

if ((error = git_path_prettify(&path, start_path, NULL)) < 0)
return error;

ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
/* in_dot_git toggles each loop:
* /a/b/c/.git, /a/b/c, /a/b/.git, /a/b, /a/.git, /a
* With GIT_REPOSITORY_OPEN_BARE, we assume we started with /a/b/c.git
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to assume this? _OPEN_BARE is about avoiding loading things like workdir and config. Anything else should be the same.

Copy link
Contributor Author

@joshtriplett joshtriplett Apr 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the defined and documented behavior of the _OPEN_BARE flag; it already causes the search to not append /.git. I just documented that behavior here in the algorithm.

* and don't append .git the first time through.
* min_iterations indicates the number of iterations left before going
* further counts as a search. */
if (flags & GIT_REPOSITORY_OPEN_BARE) {
in_dot_git = true;
min_iterations = 1;
} else {
in_dot_git = false;
min_iterations = 2;
}

if (!try_with_dot_git &&
(error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
return error;
while (!error && (min_iterations || !(path.ptr[ceiling_offset] == 0 ||
(flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))) {
if (!in_dot_git)
if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
break;
in_dot_git = !in_dot_git;

while (!error && !git_buf_len(repo_path)) {
if (p_stat(path.ptr, &st) == 0) {
/* check that we have not crossed device boundaries */
if (initial_device == 0)
Expand Down Expand Up @@ -414,17 +429,10 @@ static int find_repo(
break;
}

if (try_with_dot_git) {
/* if we tried original dir with and without .git AND either hit
* directory ceiling or NO_SEARCH was requested, then be done.
*/
if (path.ptr[ceiling_offset] == '\0' ||
(flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0)
break;
/* otherwise look first for .git item */
error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
}
try_with_dot_git = !try_with_dot_git;
/* Once we've checked the directory (and .git if applicable),
* find the ceiling for a search. */
if (min_iterations && (--min_iterations == 0))
ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
}

if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
Expand Down
12 changes: 11 additions & 1 deletion tests/repo/discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,22 @@ void test_repo_discover__0(void)
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);

/* 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
cl_git_pass(git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
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));
Expand Down
3 changes: 2 additions & 1 deletion tests/repo/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,9 @@ void test_repo_open__failures(void)
&repo, "attr/sub", GIT_REPOSITORY_OPEN_NO_SEARCH, NULL));

/* fail with ceiling too low */
cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
cl_git_fail(git_repository_open_ext(&repo, "attr/sub", 0, ceiling.ptr));
cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
cl_git_fail(git_repository_open_ext(&repo, "attr/sub/sub", 0, ceiling.ptr));

/* fail with no repo */
cl_git_pass(p_mkdir("alternate", 0777));
Expand Down