Skip to content

Commit a39f18a

Browse files
authored
Merge pull request libgit2#3998 from pks-t/pks/repo-discovery
Repository discovery starting from files
2 parents df045ce + 0f31609 commit a39f18a

File tree

2 files changed

+105
-57
lines changed

2 files changed

+105
-57
lines changed

src/repository.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ static int find_repo(
410410
break;
411411
}
412412
}
413-
else if (S_ISREG(st.st_mode)) {
413+
else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
414414
error = read_gitfile(&repo_link, path.ptr);
415415
if (error < 0)
416416
break;

tests/repo/discover.c

Lines changed: 104 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#define SUB_REPOSITORY_FOLDER_NAME "sub_repo"
1111
#define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME
12+
#define SUB_REPOSITORY_GITDIR SUB_REPOSITORY_FOLDER "/.git"
1213
#define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub"
1314
#define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub"
1415
#define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub"
@@ -24,20 +25,26 @@
2425
#define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo"
2526

2627
static void ensure_repository_discover(const char *start_path,
27-
const char *ceiling_dirs,
28-
git_buf *expected_path)
28+
const char *ceiling_dirs,
29+
const char *expected_path)
2930
{
30-
git_buf found_path = GIT_BUF_INIT;
31+
git_buf found_path = GIT_BUF_INIT, resolved = GIT_BUF_INIT;
32+
33+
git_buf_attach(&resolved, p_realpath(expected_path, NULL), 0);
34+
cl_assert(resolved.size > 0);
35+
cl_git_pass(git_path_to_dir(&resolved));
3136
cl_git_pass(git_repository_discover(&found_path, start_path, 0, ceiling_dirs));
32-
//across_fs is always 0 as we can't automate the filesystem change tests
33-
cl_assert_equal_s(found_path.ptr, expected_path->ptr);
37+
38+
cl_assert_equal_s(found_path.ptr, resolved.ptr);
39+
40+
git_buf_free(&resolved);
3441
git_buf_free(&found_path);
3542
}
3643

3744
static void write_file(const char *path, const char *content)
3845
{
3946
git_file file;
40-
int error;
47+
int error;
4148

4249
if (git_path_exists(path)) {
4350
cl_git_pass(p_unlink(path));
@@ -68,42 +75,30 @@ static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path)
6875
cl_assert(git_buf_oom(ceiling_dirs) == 0);
6976
}
7077

71-
void test_repo_discover__0(void)
78+
static git_buf discovered;
79+
static git_buf ceiling_dirs;
80+
81+
void test_repo_discover__initialize(void)
7282
{
73-
// test discover
7483
git_repository *repo;
75-
git_buf ceiling_dirs_buf = GIT_BUF_INIT, repository_path = GIT_BUF_INIT,
76-
sub_repository_path = GIT_BUF_INIT, found_path = GIT_BUF_INIT;
77-
const char *ceiling_dirs;
7884
const mode_t mode = 0777;
79-
8085
git_futils_mkdir_r(DISCOVER_FOLDER, mode);
81-
append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER);
82-
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
8386

84-
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs));
87+
git_buf_init(&discovered, 0);
88+
git_buf_init(&ceiling_dirs, 0);
89+
append_ceiling_dir(&ceiling_dirs, TEMP_REPO_FOLDER);
8590

8691
cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
87-
cl_git_pass(git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs));
8892
git_repository_free(repo);
8993

9094
cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0));
9195
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode));
92-
cl_git_pass(git_repository_discover(&sub_repository_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
93-
9496
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode));
95-
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
96-
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
97-
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, &sub_repository_path);
9897

9998
cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, mode));
10099
write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
101100
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
102101
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../");
103-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path);
104-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
105-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
106-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path);
107102

108103
cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, mode));
109104
write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:");
@@ -113,41 +108,94 @@ void test_repo_discover__0(void)
113108
write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n");
114109
cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, mode));
115110
write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist");
116-
cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
117-
cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
118-
cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
119-
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
120111

121-
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER_SUB);
122-
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
112+
git_repository_free(repo);
113+
}
114+
115+
void test_repo_discover__cleanup(void)
116+
{
117+
git_buf_free(&discovered);
118+
git_buf_free(&ceiling_dirs);
119+
cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES));
120+
}
121+
122+
void test_repo_discover__discovering_repo_with_exact_path_succeeds(void)
123+
{
124+
cl_git_pass(git_repository_discover(&discovered, DISCOVER_FOLDER, 0, ceiling_dirs.ptr));
125+
cl_git_pass(git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs.ptr));
126+
}
127+
128+
void test_repo_discover__discovering_nonexistent_dir_fails(void)
129+
{
130+
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, DISCOVER_FOLDER "-nonexistent", 0, NULL));
131+
}
132+
133+
void test_repo_discover__discovering_repo_with_subdirectory_succeeds(void)
134+
{
135+
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
136+
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
137+
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
138+
}
139+
140+
void test_repo_discover__discovering_repository_with_alternative_gitdir_succeeds(void)
141+
{
142+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
143+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
144+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
145+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs.ptr, DISCOVER_FOLDER);
146+
}
147+
148+
void test_repo_discover__discovering_repository_with_malformed_alternative_gitdir_fails(void)
149+
{
150+
cl_git_fail(git_repository_discover(&discovered, ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs.ptr));
151+
cl_git_fail(git_repository_discover(&discovered, ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs.ptr));
152+
cl_git_fail(git_repository_discover(&discovered, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs.ptr));
153+
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs.ptr));
154+
}
155+
156+
void test_repo_discover__discovering_repository_with_ceiling(void)
157+
{
158+
append_ceiling_dir(&ceiling_dirs, SUB_REPOSITORY_FOLDER_SUB);
123159

124160
/* this must pass as ceiling_directories cannot prevent the current
125161
* working directory to be checked */
126-
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path);
127-
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
128-
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
129-
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
130-
131-
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
132-
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
133-
134-
//this must pass as ceiling_directories cannot predent the current
135-
//working directory to be checked
136-
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path);
137-
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
138-
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
139-
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
140-
141-
//.gitfile redirection should not be affected by ceiling directories
142-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path);
143-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
144-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
145-
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path);
162+
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
146163

147-
cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES));
148-
git_repository_free(repo);
149-
git_buf_free(&ceiling_dirs_buf);
150-
git_buf_free(&repository_path);
151-
git_buf_free(&sub_repository_path);
164+
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
165+
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs.ptr));
166+
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs.ptr));
167+
}
168+
169+
void test_repo_discover__other_ceiling(void)
170+
{
171+
append_ceiling_dir(&ceiling_dirs, SUB_REPOSITORY_FOLDER);
172+
173+
/* this must pass as ceiling_directories cannot predent the current
174+
* working directory to be checked */
175+
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
176+
177+
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs.ptr));
178+
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs.ptr));
179+
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&discovered, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs.ptr));
152180
}
153181

182+
void test_repo_discover__ceiling_should_not_affect_gitdir_redirection(void)
183+
{
184+
append_ceiling_dir(&ceiling_dirs, SUB_REPOSITORY_FOLDER);
185+
186+
/* gitfile redirection should not be affected by ceiling directories */
187+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
188+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
189+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
190+
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs.ptr, DISCOVER_FOLDER);
191+
}
192+
193+
void test_repo_discover__discovery_starting_at_file_succeeds(void)
194+
{
195+
int fd;
196+
197+
cl_assert((fd = p_creat(SUB_REPOSITORY_FOLDER "/file", 0600)) >= 0);
198+
cl_assert(p_close(fd) == 0);
199+
200+
ensure_repository_discover(SUB_REPOSITORY_FOLDER "/file", ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
201+
}

0 commit comments

Comments
 (0)