Skip to content

Commit 39c6fca

Browse files
committed
Add GIT_REPOSITORY_OPEN_NO_DOTGIT flag to avoid appending /.git
GIT_REPOSITORY_OPEN_NO_SEARCH does not search up through parent directories, but still tries the specified path both directly and with /.git appended. GIT_REPOSITORY_OPEN_BARE avoids appending /.git, but opens the repository in bare mode even if it has a working directory. To support the semantics git uses when given $GIT_DIR in the environment, provide a new GIT_REPOSITORY_OPEN_NO_DOTGIT flag to not try appending /.git.
1 parent ed57713 commit 39c6fca

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

include/git2/repository.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,15 @@ GIT_EXTERN(int) git_repository_discover(
9595
* * GIT_REPOSITORY_OPEN_BARE - Open repository as a bare repo regardless
9696
* of core.bare config, and defer loading config file for faster setup.
9797
* Unlike `git_repository_open_bare`, this can follow gitlinks.
98+
* * GIT_REPOSITORY_OPEN_NO_DOTGIT - Do not check for a repository by
99+
* appending /.git to the start_path; only open the repository if
100+
* start_path itself points to the git directory.
98101
*/
99102
typedef enum {
100103
GIT_REPOSITORY_OPEN_NO_SEARCH = (1 << 0),
101104
GIT_REPOSITORY_OPEN_CROSS_FS = (1 << 1),
102105
GIT_REPOSITORY_OPEN_BARE = (1 << 2),
106+
GIT_REPOSITORY_OPEN_NO_DOTGIT = (1 << 3),
103107
} git_repository_open_flag_t;
104108

105109
/**

src/repository.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,12 @@ static int find_repo(
370370

371371
/* in_dot_git toggles each loop:
372372
* /a/b/c/.git, /a/b/c, /a/b/.git, /a/b, /a/.git, /a
373-
* With GIT_REPOSITORY_OPEN_BARE, we assume we started with /a/b/c.git
374-
* and don't append .git the first time through.
373+
* With GIT_REPOSITORY_OPEN_BARE or GIT_REPOSITORY_OPEN_NO_DOTGIT, we
374+
* assume we started with /a/b/c.git and don't append .git the first
375+
* time through.
375376
* min_iterations indicates the number of iterations left before going
376377
* further counts as a search. */
377-
if (flags & GIT_REPOSITORY_OPEN_BARE) {
378+
if (flags & (GIT_REPOSITORY_OPEN_BARE | GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
378379
in_dot_git = true;
379380
min_iterations = 1;
380381
} else {
@@ -384,10 +385,12 @@ static int find_repo(
384385

385386
while (!error && (min_iterations || !(path.ptr[ceiling_offset] == 0 ||
386387
(flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))) {
387-
if (!in_dot_git)
388-
if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
389-
break;
390-
in_dot_git = !in_dot_git;
388+
if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
389+
if (!in_dot_git)
390+
if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
391+
break;
392+
in_dot_git = !in_dot_git;
393+
}
391394

392395
if (p_stat(path.ptr, &st) == 0) {
393396
/* check that we have not crossed device boundaries */

tests/repo/open.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ void test_repo_open__failures(void)
206206
cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL));
207207
cl_git_fail(git_repository_open_ext(&repo, "alternate/.git", 0, NULL));
208208

209+
/* fail with no searching and no appending .git */
210+
cl_git_fail(git_repository_open_ext(
211+
&repo, "attr",
212+
GIT_REPOSITORY_OPEN_NO_SEARCH | GIT_REPOSITORY_OPEN_NO_DOTGIT,
213+
NULL));
214+
209215
git_buf_free(&ceiling);
210216
}
211217

0 commit comments

Comments
 (0)