mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 19:46:59 +00:00
Add BARE option to git_repository_open_ext
This adds a BARE option to git_repository_open_ext which allows a fast open path that still knows how to read gitlinks and to search for the actual .git directory from a subdirectory. `git_repository_open_bare` is still simpler and faster, but having a gitlink aware fast open is very useful for submodules where we want to quickly be able to peek at the HEAD and index data without doing any other meaningful repo operations.
This commit is contained in:
parent
302a04b09c
commit
3fe046cfdb
@ -94,10 +94,14 @@ GIT_EXTERN(int) git_repository_discover(
|
||||
* changes from the `stat` system call). (E.g. Searching in a user's home
|
||||
* directory "/home/user/source/" will not return "/.git/" as the found
|
||||
* repo if "/" is a different filesystem than "/home".)
|
||||
* * GIT_REPOSITORY_OPEN_BARE - Open repository as a bare repo regardless
|
||||
* of core.bare config, and defer loading config file for faster setup.
|
||||
* Unlike `git_repository_open_bare`, this can follow gitlinks.
|
||||
*/
|
||||
typedef enum {
|
||||
GIT_REPOSITORY_OPEN_NO_SEARCH = (1 << 0),
|
||||
GIT_REPOSITORY_OPEN_CROSS_FS = (1 << 1),
|
||||
GIT_REPOSITORY_OPEN_BARE = (1 << 2),
|
||||
} git_repository_open_flag_t;
|
||||
|
||||
/**
|
||||
|
@ -266,7 +266,7 @@ static int find_ceiling_dir_offset(
|
||||
buf[--len] = '\0';
|
||||
|
||||
if (!strncmp(path, buf2, len) &&
|
||||
path[len] == '/' &&
|
||||
(path[len] == '/' || !path[len]) &&
|
||||
len > max_len)
|
||||
{
|
||||
max_len = len;
|
||||
@ -322,17 +322,18 @@ static int find_repo(
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
struct stat st;
|
||||
dev_t initial_device = 0;
|
||||
bool try_with_dot_git = false;
|
||||
bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0);
|
||||
int ceiling_offset;
|
||||
|
||||
git_buf_free(repo_path);
|
||||
|
||||
if ((error = git_path_prettify_dir(&path, start_path, NULL)) < 0)
|
||||
if ((error = git_path_prettify(&path, start_path, NULL)) < 0)
|
||||
return error;
|
||||
|
||||
ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
|
||||
|
||||
if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
|
||||
if (!try_with_dot_git &&
|
||||
(error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
|
||||
return error;
|
||||
|
||||
while (!error && !git_buf_len(repo_path)) {
|
||||
@ -384,7 +385,7 @@ static int find_repo(
|
||||
try_with_dot_git = !try_with_dot_git;
|
||||
}
|
||||
|
||||
if (!error && parent_path != NULL) {
|
||||
if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
|
||||
if (!git_buf_len(repo_path))
|
||||
git_buf_clear(parent_path);
|
||||
else {
|
||||
@ -460,7 +461,9 @@ int git_repository_open_ext(
|
||||
repo->path_repository = git_buf_detach(&path);
|
||||
GITERR_CHECK_ALLOC(repo->path_repository);
|
||||
|
||||
if ((error = load_config_data(repo)) < 0 ||
|
||||
if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
|
||||
repo->is_bare = 1;
|
||||
else if ((error = load_config_data(repo)) < 0 ||
|
||||
(error = load_workdir(repo, &parent)) < 0)
|
||||
{
|
||||
git_repository_free(repo);
|
||||
|
@ -69,14 +69,23 @@ void test_repo_open__open_with_discover(void)
|
||||
cl_fixture_cleanup("attr");
|
||||
}
|
||||
|
||||
static void make_gitlink_dir(const char *dir, const char *linktext)
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
cl_git_pass(git_futils_mkdir(dir, NULL, 0777, GIT_MKDIR_VERIFY_DIR));
|
||||
cl_git_pass(git_buf_joinpath(&path, dir, ".git"));
|
||||
cl_git_rewritefile(path.ptr, linktext);
|
||||
git_buf_free(&path);
|
||||
}
|
||||
|
||||
void test_repo_open__gitlinked(void)
|
||||
{
|
||||
/* need to have both repo dir and workdir set up correctly */
|
||||
git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
|
||||
git_repository *repo2;
|
||||
|
||||
cl_must_pass(p_mkdir("alternate", 0777));
|
||||
cl_git_mkfile("alternate/.git", "gitdir: ../empty_standard_repo/.git");
|
||||
make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git");
|
||||
|
||||
cl_git_pass(git_repository_open(&repo2, "alternate"));
|
||||
|
||||
@ -193,12 +202,11 @@ void test_repo_open__bad_gitlinks(void)
|
||||
|
||||
cl_git_sandbox_init("attr");
|
||||
|
||||
cl_git_pass(p_mkdir("alternate", 0777));
|
||||
cl_git_pass(p_mkdir("invalid", 0777));
|
||||
cl_git_pass(git_futils_mkdir_r("invalid2/.git", NULL, 0777));
|
||||
|
||||
for (scan = bad_links; *scan != NULL; scan++) {
|
||||
cl_git_rewritefile("alternate/.git", *scan);
|
||||
make_gitlink_dir("alternate", *scan);
|
||||
cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL));
|
||||
}
|
||||
|
||||
@ -315,3 +323,52 @@ void test_repo_open__no_config(void)
|
||||
git_repository_free(repo);
|
||||
cl_fixture_cleanup("empty_standard_repo");
|
||||
}
|
||||
|
||||
void test_repo_open__force_bare(void)
|
||||
{
|
||||
/* need to have both repo dir and workdir set up correctly */
|
||||
git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
|
||||
git_repository *barerepo;
|
||||
|
||||
make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git");
|
||||
|
||||
cl_assert(!git_repository_is_bare(repo));
|
||||
|
||||
cl_git_pass(git_repository_open(&barerepo, "alternate"));
|
||||
cl_assert(!git_repository_is_bare(barerepo));
|
||||
git_repository_free(barerepo);
|
||||
|
||||
cl_git_pass(git_repository_open_bare(
|
||||
&barerepo, "empty_standard_repo/.git"));
|
||||
cl_assert(git_repository_is_bare(barerepo));
|
||||
git_repository_free(barerepo);
|
||||
|
||||
cl_git_fail(git_repository_open_bare(&barerepo, "alternate/.git"));
|
||||
|
||||
cl_git_pass(git_repository_open_ext(
|
||||
&barerepo, "alternate/.git", GIT_REPOSITORY_OPEN_BARE, NULL));
|
||||
cl_assert(git_repository_is_bare(barerepo));
|
||||
git_repository_free(barerepo);
|
||||
|
||||
cl_git_pass(p_mkdir("empty_standard_repo/subdir", 0777));
|
||||
cl_git_mkfile("empty_standard_repo/subdir/something.txt", "something");
|
||||
|
||||
cl_git_fail(git_repository_open_bare(
|
||||
&barerepo, "empty_standard_repo/subdir"));
|
||||
|
||||
cl_git_pass(git_repository_open_ext(
|
||||
&barerepo, "empty_standard_repo/subdir", GIT_REPOSITORY_OPEN_BARE, NULL));
|
||||
cl_assert(git_repository_is_bare(barerepo));
|
||||
git_repository_free(barerepo);
|
||||
|
||||
cl_git_pass(p_mkdir("alternate/subdir", 0777));
|
||||
cl_git_pass(p_mkdir("alternate/subdir/sub2", 0777));
|
||||
cl_git_mkfile("alternate/subdir/sub2/something.txt", "something");
|
||||
|
||||
cl_git_fail(git_repository_open_bare(&barerepo, "alternate/subdir/sub2"));
|
||||
|
||||
cl_git_pass(git_repository_open_ext(
|
||||
&barerepo, "alternate/subdir/sub2", GIT_REPOSITORY_OPEN_BARE, NULL));
|
||||
cl_assert(git_repository_is_bare(barerepo));
|
||||
git_repository_free(barerepo);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user