2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
26 #include "test_helpers.h"
29 #include "git2/odb_backend.h"
30 #include "repository.h"
37 git_odb_backend
*new_backend(int position
)
41 b
= git__malloc(sizeof(fake_backend
));
45 memset(b
, 0x0, sizeof(fake_backend
));
46 b
->position
= position
;
47 return (git_odb_backend
*)b
;
50 int test_backend_sorting(git_odb
*odb
)
54 for (i
= 0; i
< odb
->backends
.length
; ++i
) {
55 fake_backend
*internal
= *((fake_backend
**)git_vector_get(&odb
->backends
, i
));
60 if (internal
->position
!= (int)i
)
67 BEGIN_TEST(odb0
, "assure that ODB backends are properly sorted")
69 must_pass(git_odb_new(&odb
));
70 must_pass(git_odb_add_backend(odb
, new_backend(0), 5));
71 must_pass(git_odb_add_backend(odb
, new_backend(2), 3));
72 must_pass(git_odb_add_backend(odb
, new_backend(1), 4));
73 must_pass(git_odb_add_backend(odb
, new_backend(3), 1));
74 must_pass(test_backend_sorting(odb
));
78 BEGIN_TEST(odb1
, "assure that alternate backends are properly sorted")
80 must_pass(git_odb_new(&odb
));
81 must_pass(git_odb_add_backend(odb
, new_backend(0), 5));
82 must_pass(git_odb_add_backend(odb
, new_backend(2), 3));
83 must_pass(git_odb_add_backend(odb
, new_backend(1), 4));
84 must_pass(git_odb_add_backend(odb
, new_backend(3), 1));
85 must_pass(git_odb_add_alternate(odb
, new_backend(4), 5));
86 must_pass(git_odb_add_alternate(odb
, new_backend(6), 3));
87 must_pass(git_odb_add_alternate(odb
, new_backend(5), 4));
88 must_pass(git_odb_add_alternate(odb
, new_backend(7), 1));
89 must_pass(test_backend_sorting(odb
));
94 #define STANDARD_REPOSITORY 0
95 #define BARE_REPOSITORY 1
97 static int ensure_repository_init(
98 const char *working_directory
,
100 const char *expected_path_index
,
101 const char *expected_path_repository
,
102 const char *expected_working_directory
)
104 char path_odb
[GIT_PATH_MAX
];
105 git_repository
*repo
;
107 if (git_futils_isdir(working_directory
) == GIT_SUCCESS
)
110 git_path_join(path_odb
, expected_path_repository
, GIT_OBJECTS_DIR
);
112 if (git_repository_init(&repo
, working_directory
, repository_kind
) < GIT_SUCCESS
)
115 if (repo
->path_workdir
!= NULL
|| expected_working_directory
!= NULL
) {
116 if (git__suffixcmp(repo
->path_workdir
, expected_working_directory
) != 0)
120 if (git__suffixcmp(repo
->path_odb
, path_odb
) != 0)
123 if (git__suffixcmp(repo
->path_repository
, expected_path_repository
) != 0)
126 if (repo
->path_index
!= NULL
|| expected_path_index
!= NULL
) {
127 if (git__suffixcmp(repo
->path_index
, expected_path_index
) != 0)
131 if ((GetFileAttributes(repo
->path_repository
) & FILE_ATTRIBUTE_HIDDEN
) == 0)
135 if (git_repository_is_bare(repo
) == 1)
137 } else if (git_repository_is_bare(repo
) == 0)
140 if (git_repository_is_empty(repo
) == 0)
143 git_repository_free(repo
);
144 git_futils_rmdir_r(working_directory
, 1);
149 git_repository_free(repo
);
150 git_futils_rmdir_r(working_directory
, 1);
154 BEGIN_TEST(init0
, "initialize a standard repo")
155 char path_index
[GIT_PATH_MAX
], path_repository
[GIT_PATH_MAX
];
157 git_path_join(path_repository
, TEMP_REPO_FOLDER
, GIT_DIR
);
158 git_path_join(path_index
, path_repository
, GIT_INDEX_FILE
);
160 must_pass(ensure_repository_init(TEMP_REPO_FOLDER
, STANDARD_REPOSITORY
, path_index
, path_repository
, TEMP_REPO_FOLDER
));
161 must_pass(ensure_repository_init(TEMP_REPO_FOLDER_NS
, STANDARD_REPOSITORY
, path_index
, path_repository
, TEMP_REPO_FOLDER
));
164 BEGIN_TEST(init1
, "initialize a bare repo")
165 char path_repository
[GIT_PATH_MAX
];
167 git_path_join(path_repository
, TEMP_REPO_FOLDER
, "");
169 must_pass(ensure_repository_init(TEMP_REPO_FOLDER
, BARE_REPOSITORY
, NULL
, path_repository
, NULL
));
170 must_pass(ensure_repository_init(TEMP_REPO_FOLDER_NS
, BARE_REPOSITORY
, NULL
, path_repository
, NULL
));
173 BEGIN_TEST(init2
, "Initialize and open a bare repo with a relative path escaping out of the current working directory")
174 char path_repository
[GIT_PATH_MAX
];
175 char current_workdir
[GIT_PATH_MAX
];
176 const int mode
= 0755; /* or 0777 ? */
177 git_repository
* repo
;
179 must_pass(p_getcwd(current_workdir
, sizeof(current_workdir
)));
181 git_path_join(path_repository
, TEMP_REPO_FOLDER
, "a/b/c/");
182 must_pass(git_futils_mkdir_r(path_repository
, mode
));
184 must_pass(chdir(path_repository
));
186 must_pass(git_repository_init(&repo
, "../d/e.git", 1));
187 must_pass(git__suffixcmp(repo
->path_repository
, "/a/b/d/e.git/"));
189 git_repository_free(repo
);
191 must_pass(git_repository_open(&repo
, "../d/e.git"));
193 git_repository_free(repo
);
195 must_pass(chdir(current_workdir
));
196 must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER
, 1));
199 #define EMPTY_BARE_REPOSITORY_FOLDER TEST_RESOURCES "/empty_bare.git/"
201 BEGIN_TEST(open0
, "Open a bare repository that has just been initialized by git")
202 git_repository
*repo
;
204 must_pass(copydir_recurs(EMPTY_BARE_REPOSITORY_FOLDER
, TEMP_REPO_FOLDER
));
205 must_pass(remove_placeholders(TEMP_REPO_FOLDER
, "dummy-marker.txt"));
207 must_pass(git_repository_open(&repo
, TEMP_REPO_FOLDER
));
208 must_be_true(git_repository_path(repo
, GIT_REPO_PATH
) != NULL
);
209 must_be_true(git_repository_path(repo
, GIT_REPO_PATH_WORKDIR
) == NULL
);
211 git_repository_free(repo
);
212 must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER
, 1));
215 #define EMPTY_REPOSITORY_FOLDER TEST_RESOURCES "/empty_standard_repo/.gitted/"
217 BEGIN_TEST(open1
, "Open a standard repository that has just been initialized by git")
218 git_repository
*repo
;
220 must_pass(copydir_recurs(EMPTY_REPOSITORY_FOLDER
, TEST_STD_REPO_FOLDER
));
221 must_pass(remove_placeholders(TEST_STD_REPO_FOLDER
, "dummy-marker.txt"));
223 must_pass(git_repository_open(&repo
, TEST_STD_REPO_FOLDER
));
224 must_be_true(git_repository_path(repo
, GIT_REPO_PATH
) != NULL
);
225 must_be_true(git_repository_path(repo
, GIT_REPO_PATH_WORKDIR
) != NULL
);
227 git_repository_free(repo
);
228 must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER
, 1));
232 BEGIN_TEST(open2
, "Open a bare repository with a relative path escaping out of the current working directory")
233 char new_current_workdir
[GIT_PATH_MAX
];
234 char current_workdir
[GIT_PATH_MAX
];
235 char path_repository
[GIT_PATH_MAX
];
237 const int mode
= 0755; /* or 0777 ? */
238 git_repository
* repo
;
240 /* Setup the repository to open */
241 must_pass(p_getcwd(current_workdir
, sizeof(current_workdir
)));
242 strcpy(path_repository
, current_workdir
);
243 git_path_join_n(path_repository
, 3, path_repository
, TEMP_REPO_FOLDER
, "a/d/e.git");
244 must_pass(copydir_recurs(REPOSITORY_FOLDER
, path_repository
));
246 /* Change the current working directory */
247 git_path_join(new_current_workdir
, TEMP_REPO_FOLDER
, "a/b/c/");
248 must_pass(git_futils_mkdir_r(new_current_workdir
, mode
));
249 must_pass(chdir(new_current_workdir
));
251 must_pass(git_repository_open(&repo
, "../../d/e.git"));
253 git_repository_free(repo
);
255 must_pass(chdir(current_workdir
));
256 must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER
, 1));
259 BEGIN_TEST(empty0
, "test if a repository is empty or not")
261 git_repository
*repo_empty
, *repo_normal
;
263 must_pass(git_repository_open(&repo_normal
, REPOSITORY_FOLDER
));
264 must_be_true(git_repository_is_empty(repo_normal
) == 0);
265 git_repository_free(repo_normal
);
267 must_pass(git_repository_open(&repo_empty
, EMPTY_BARE_REPOSITORY_FOLDER
));
268 must_be_true(git_repository_is_empty(repo_empty
) == 1);
269 git_repository_free(repo_empty
);
272 BEGIN_TEST(detached0
, "test if HEAD is detached")
273 git_repository
*repo
;
277 must_pass(git_repository_open(&repo
, REPOSITORY_FOLDER
));
279 must_be_true(git_repository_head_detached(repo
) == 0);
281 /* detach the HEAD */
282 git_oid_fromstr(&oid
, "c47800c7266a2be04c571c04d5a6614691ea99bd");
283 must_pass(git_reference_create_oid(&ref
, repo
, "HEAD", &oid
, 1));
284 must_be_true(git_repository_head_detached(repo
) == 1);
286 /* take the reop back to it's original state */
287 must_pass(git_reference_create_symbolic(&ref
, repo
, "HEAD", "refs/heads/master", 1));
288 must_be_true(git_repository_head_detached(repo
) == 0);
290 git_repository_free(repo
);
293 BEGIN_TEST(orphan0
, "test if HEAD is orphan")
294 git_repository
*repo
;
297 must_pass(git_repository_open(&repo
, REPOSITORY_FOLDER
));
299 must_be_true(git_repository_head_orphan(repo
) == 0);
302 must_pass(git_reference_create_symbolic(&ref
, repo
, "HEAD", "refs/heads/orphan", 1));
303 must_be_true(git_repository_head_orphan(repo
) == 1);
305 /* take the reop back to it's original state */
306 must_pass(git_reference_create_symbolic(&ref
, repo
, "HEAD", "refs/heads/master", 1));
307 must_be_true(git_repository_head_orphan(repo
) == 0);
309 git_repository_free(repo
);
312 #define DISCOVER_FOLDER TEST_RESOURCES "/discover.git"
314 #define SUB_REPOSITORY_FOLDER_NAME "sub_repo"
315 #define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME
316 #define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub"
317 #define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub"
318 #define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub"
320 #define REPOSITORY_ALTERNATE_FOLDER DISCOVER_FOLDER "/alternate_sub_repo"
321 #define REPOSITORY_ALTERNATE_FOLDER_SUB REPOSITORY_ALTERNATE_FOLDER "/sub"
322 #define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB "/subsub"
323 #define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/subsubsub"
325 #define ALTERNATE_MALFORMED_FOLDER1 DISCOVER_FOLDER "/alternate_malformed_repo1"
326 #define ALTERNATE_MALFORMED_FOLDER2 DISCOVER_FOLDER "/alternate_malformed_repo2"
327 #define ALTERNATE_MALFORMED_FOLDER3 DISCOVER_FOLDER "/alternate_malformed_repo3"
328 #define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo"
330 static int ensure_repository_discover(const char *start_path
, const char *ceiling_dirs
, const char *expected_path
)
333 char found_path
[GIT_PATH_MAX
];
335 error
= git_repository_discover(found_path
, sizeof(found_path
), start_path
, 0, ceiling_dirs
);
336 //across_fs is always 0 as we can't automate the filesystem change tests
338 if (error
< GIT_SUCCESS
)
341 return strcmp(found_path
, expected_path
) ? GIT_ERROR
: GIT_SUCCESS
;
344 static int write_file(const char *path
, const char *content
)
349 if (git_futils_exists(path
) == GIT_SUCCESS
) {
350 error
= p_unlink(path
);
352 if (error
< GIT_SUCCESS
)
356 file
= git_futils_creat_withpath(path
, 0644);
357 if (file
< GIT_SUCCESS
)
360 error
= p_write(file
, content
, strlen(content
) * sizeof(char));
367 //no check is performed on ceiling_dirs length, so be sure it's long enough
368 static int append_ceiling_dir(char *ceiling_dirs
, const char *path
)
370 int len
= strlen(ceiling_dirs
);
373 error
= git_path_prettify_dir(ceiling_dirs
+ len
+ (len
? 1 : 0), path
, NULL
);
374 if (error
< GIT_SUCCESS
)
375 return git__rethrow(error
, "Failed to append ceiling directory.");
378 ceiling_dirs
[len
] = GIT_PATH_LIST_SEPARATOR
;
383 BEGIN_TEST(discover0
, "test discover")
384 git_repository
*repo
;
385 char ceiling_dirs
[GIT_PATH_MAX
* 2] = "";
386 char repository_path
[GIT_PATH_MAX
];
387 char sub_repository_path
[GIT_PATH_MAX
];
388 char found_path
[GIT_PATH_MAX
];
391 must_pass(append_ceiling_dir(ceiling_dirs
,TEST_RESOURCES
));
392 git_futils_mkdir_r(DISCOVER_FOLDER
, mode
);
394 must_be_true(git_repository_discover(repository_path
, sizeof(repository_path
), DISCOVER_FOLDER
, 0, ceiling_dirs
) == GIT_ENOTAREPO
);
396 must_pass(git_repository_init(&repo
, DISCOVER_FOLDER
, 1));
397 must_pass(git_repository_discover(repository_path
, sizeof(repository_path
), DISCOVER_FOLDER
, 0, ceiling_dirs
));
398 git_repository_free(repo
);
400 must_pass(git_repository_init(&repo
, SUB_REPOSITORY_FOLDER
, 0));
401 must_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
, mode
));
402 must_pass(git_repository_discover(sub_repository_path
, sizeof(sub_repository_path
), SUB_REPOSITORY_FOLDER
, 0, ceiling_dirs
));
404 must_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
, mode
));
405 must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB
, ceiling_dirs
, sub_repository_path
));
406 must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB
, ceiling_dirs
, sub_repository_path
));
407 must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
, ceiling_dirs
, sub_repository_path
));
409 must_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
, mode
));
410 must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER
"/" DOT_GIT
, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME
"/" DOT_GIT
));
411 must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB
"/" DOT_GIT
, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME
"/" DOT_GIT
));
412 must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
"/" DOT_GIT
, "gitdir: ../../../../"));
413 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER
, ceiling_dirs
, sub_repository_path
));
414 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB
, ceiling_dirs
, sub_repository_path
));
415 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB
, ceiling_dirs
, sub_repository_path
));
416 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
, ceiling_dirs
, repository_path
));
418 must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1
, mode
));
419 must_pass(write_file(ALTERNATE_MALFORMED_FOLDER1
"/" DOT_GIT
, "Anything but not gitdir:"));
420 must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER2
, mode
));
421 must_pass(write_file(ALTERNATE_MALFORMED_FOLDER2
"/" DOT_GIT
, "gitdir:"));
422 must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER3
, mode
));
423 must_pass(write_file(ALTERNATE_MALFORMED_FOLDER3
"/" DOT_GIT
, "gitdir: \n\n\n"));
424 must_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER
, mode
));
425 must_pass(write_file(ALTERNATE_NOT_FOUND_FOLDER
"/" DOT_GIT
, "gitdir: a_repository_that_surely_does_not_exist"));
426 must_fail(git_repository_discover(found_path
, sizeof(found_path
), ALTERNATE_MALFORMED_FOLDER1
, 0, ceiling_dirs
));
427 must_fail(git_repository_discover(found_path
, sizeof(found_path
), ALTERNATE_MALFORMED_FOLDER2
, 0, ceiling_dirs
));
428 must_fail(git_repository_discover(found_path
, sizeof(found_path
), ALTERNATE_MALFORMED_FOLDER3
, 0, ceiling_dirs
));
429 must_fail(git_repository_discover(found_path
, sizeof(found_path
), ALTERNATE_NOT_FOUND_FOLDER
, 0, ceiling_dirs
));
431 must_pass(append_ceiling_dir(ceiling_dirs
, SUB_REPOSITORY_FOLDER
));
432 //this must pass as ceiling_directories cannot predent the current
433 //working directory to be checked
434 must_pass(git_repository_discover(found_path
, sizeof(found_path
), SUB_REPOSITORY_FOLDER
, 0, ceiling_dirs
));
435 must_fail(git_repository_discover(found_path
, sizeof(found_path
), SUB_REPOSITORY_FOLDER_SUB
, 0, ceiling_dirs
));
436 must_fail(git_repository_discover(found_path
, sizeof(found_path
), SUB_REPOSITORY_FOLDER_SUB_SUB
, 0, ceiling_dirs
));
437 must_fail(git_repository_discover(found_path
, sizeof(found_path
), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB
, 0, ceiling_dirs
));
439 //.gitfile redirection should not be affected by ceiling directories
440 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER
, ceiling_dirs
, sub_repository_path
));
441 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB
, ceiling_dirs
, sub_repository_path
));
442 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB
, ceiling_dirs
, sub_repository_path
));
443 must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB
, ceiling_dirs
, repository_path
));
445 must_pass(git_futils_rmdir_r(DISCOVER_FOLDER
, 1));
446 git_repository_free(repo
);
449 BEGIN_SUITE(repository
)