Skip to content

Commit

Permalink
Revert to use the libgit2 source code at 'e4218450'
Browse files Browse the repository at this point in the history
The tests in ‘tests/repository.R’ failed with the libgit2 source
code at 'd824346'

Signed-off-by: Stefan Widgren <stefan.widgren@gmail.com>
  • Loading branch information
stewid committed Jul 2, 2016
1 parent d3d2db8 commit 7b0f435
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 244 deletions.
2 changes: 1 addition & 1 deletion R/libgit2.r
Expand Up @@ -47,7 +47,7 @@ libgit2_version <- function() {
##' @export
##' @examples
##' libgit2_sha()
libgit2_sha <- function() "d8243465be6ae4c3d0482ec262da58276f3a4e58"
libgit2_sha <- function() "e4218450338cf6757077f63bac570ea77f655eff"

##' Set the SSL certificate-authority locations
##'
Expand Down
21 changes: 1 addition & 20 deletions src/libgit2/include/git2/repository.h
Expand Up @@ -95,29 +95,11 @@ GIT_EXTERN(int) git_repository_discover(
* * 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.
* * GIT_REPOSITORY_OPEN_NO_DOTGIT - Do not check for a repository by
* appending /.git to the start_path; only open the repository if
* start_path itself points to the git directory.
* * GIT_REPOSITORY_OPEN_FROM_ENV - Find and open a git repository,
* respecting the environment variables used by the git command-line
* tools. If set, `git_repository_open_ext` will ignore the other
* flags and the `ceiling_dirs` argument, and will allow a NULL `path`
* to use `GIT_DIR` or search from the current directory. The search
* for a repository will respect $GIT_CEILING_DIRECTORIES and
* $GIT_DISCOVERY_ACROSS_FILESYSTEM. The opened repository will
* respect $GIT_INDEX_FILE, $GIT_NAMESPACE, $GIT_OBJECT_DIRECTORY, and
* $GIT_ALTERNATE_OBJECT_DIRECTORIES. In the future, this flag will
* also cause `git_repository_open_ext` to respect $GIT_WORK_TREE and
* $GIT_COMMON_DIR; currently, `git_repository_open_ext` with this
* flag will error out if either $GIT_WORK_TREE or $GIT_COMMON_DIR is
* set.
*/
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_NO_DOTGIT = (1 << 3),
GIT_REPOSITORY_OPEN_FROM_ENV = (1 << 4),
} git_repository_open_flag_t;

/**
Expand All @@ -128,8 +110,7 @@ typedef enum {
* see if a repo at this path could be opened.
* @param path Path to open as git repository. If the flags
* permit "searching", then this can be a path to a subdirectory
* inside the working directory of the repository. May be NULL if
* flags is GIT_REPOSITORY_OPEN_FROM_ENV.
* inside the working directory of the repository.
* @param flags A combination of the GIT_REPOSITORY_OPEN flags above.
* @param ceiling_dirs A GIT_PATH_LIST_SEPARATOR delimited list of path
* prefixes at which the search for a containing repository should
Expand Down
258 changes: 35 additions & 223 deletions src/libgit2/src/repository.c
Expand Up @@ -357,50 +357,29 @@ static int find_repo(
{
int error;
git_buf path = GIT_BUF_INIT;
git_buf repo_link = GIT_BUF_INIT;
struct stat st;
dev_t initial_device = 0;
int min_iterations;
bool in_dot_git;
bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0);
int ceiling_offset;

git_buf_free(repo_path);

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

/* 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 or GIT_REPOSITORY_OPEN_NO_DOTGIT, we
* assume we started with /a/b/c.git 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 | GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
in_dot_git = true;
min_iterations = 1;
} else {
in_dot_git = false;
min_iterations = 2;
}
ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);

for (;;) {
if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
if (!in_dot_git) {
error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
if (error < 0)
break;
}
in_dot_git = !in_dot_git;
}
if (!try_with_dot_git &&
(error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
return error;

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)
initial_device = st.st_dev;
else if (st.st_dev != initial_device &&
!(flags & GIT_REPOSITORY_OPEN_CROSS_FS))
(flags & GIT_REPOSITORY_OPEN_CROSS_FS) == 0)
break;

if (S_ISDIR(st.st_mode)) {
Expand All @@ -411,37 +390,41 @@ static int find_repo(
}
}
else if (S_ISREG(st.st_mode)) {
error = read_gitfile(&repo_link, path.ptr);
if (error < 0)
break;
if (valid_repository_path(&repo_link)) {
git_buf_swap(repo_path, &repo_link);
git_buf repo_link = GIT_BUF_INIT;

if (!(error = read_gitfile(&repo_link, path.ptr))) {
if (valid_repository_path(&repo_link)) {
git_buf_swap(repo_path, &repo_link);

if (link_path)
error = git_buf_put(link_path,
path.ptr, path.size);
}

if (link_path)
error = git_buf_put(link_path, path.ptr, path.size);
git_buf_free(&repo_link);
break;
}
break;
git_buf_free(&repo_link);
}
}

/* Move up one directory. If we're in_dot_git, we'll search the
* parent itself next. If we're !in_dot_git, we'll search .git
* in the parent directory next (added at the top of the loop). */
/* move up one directory level */
if (git_path_dirname_r(&path, path.ptr) < 0) {
error = -1;
break;
}

/* 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);

/* Check if we should stop searching here. */
if (min_iterations == 0
&& (path.ptr[ceiling_offset] == 0
|| (flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))
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;
}

if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
Expand All @@ -455,16 +438,14 @@ static int find_repo(
return -1;
}

/* If we didn't find the repository, and we don't have any other error
* to report, report that. */
git_buf_free(&path);

if (!git_buf_len(repo_path) && !error) {
giterr_set(GITERR_REPOSITORY,
"Could not find repository from '%s'", start_path);
error = GIT_ENOTFOUND;
}

git_buf_free(&path);
git_buf_free(&repo_link);
return error;
}

Expand Down Expand Up @@ -499,172 +480,6 @@ int git_repository_open_bare(
return 0;
}

static int _git_repository_open_ext_from_env(
git_repository **out,
const char *start_path)
{
git_repository *repo = NULL;
git_index *index = NULL;
git_odb *odb = NULL;
git_buf dir_buf = GIT_BUF_INIT;
git_buf ceiling_dirs_buf = GIT_BUF_INIT;
git_buf across_fs_buf = GIT_BUF_INIT;
git_buf index_file_buf = GIT_BUF_INIT;
git_buf namespace_buf = GIT_BUF_INIT;
git_buf object_dir_buf = GIT_BUF_INIT;
git_buf alts_buf = GIT_BUF_INIT;
git_buf work_tree_buf = GIT_BUF_INIT;
git_buf common_dir_buf = GIT_BUF_INIT;
const char *ceiling_dirs = NULL;
unsigned flags = 0;
int error;

if (!start_path) {
error = git__getenv(&dir_buf, "GIT_DIR");
if (error == GIT_ENOTFOUND) {
giterr_clear();
start_path = ".";
} else if (error < 0)
goto error;
else {
start_path = git_buf_cstr(&dir_buf);
flags |= GIT_REPOSITORY_OPEN_NO_SEARCH;
flags |= GIT_REPOSITORY_OPEN_NO_DOTGIT;
}
}

error = git__getenv(&ceiling_dirs_buf, "GIT_CEILING_DIRECTORIES");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;
else
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);

error = git__getenv(&across_fs_buf, "GIT_DISCOVERY_ACROSS_FILESYSTEM");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;
else {
int across_fs = 0;
error = git_config_parse_bool(&across_fs, git_buf_cstr(&across_fs_buf));
if (error < 0)
goto error;
if (across_fs)
flags |= GIT_REPOSITORY_OPEN_CROSS_FS;
}

error = git__getenv(&index_file_buf, "GIT_INDEX_FILE");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;
else {
error = git_index_open(&index, git_buf_cstr(&index_file_buf));
if (error < 0)
goto error;
}

error = git__getenv(&namespace_buf, "GIT_NAMESPACE");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;

error = git__getenv(&object_dir_buf, "GIT_OBJECT_DIRECTORY");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;
else {
error = git_odb_open(&odb, git_buf_cstr(&object_dir_buf));
if (error < 0)
goto error;
}

error = git__getenv(&work_tree_buf, "GIT_WORK_TREE");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;
else {
giterr_set(GITERR_INVALID, "GIT_WORK_TREE unimplemented");
error = GIT_ERROR;
goto error;
}

error = git__getenv(&work_tree_buf, "GIT_COMMON_DIR");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;
else {
giterr_set(GITERR_INVALID, "GIT_COMMON_DIR unimplemented");
error = GIT_ERROR;
goto error;
}

error = git_repository_open_ext(&repo, start_path, flags, ceiling_dirs);
if (error < 0)
goto error;

if (odb)
git_repository_set_odb(repo, odb);

error = git__getenv(&alts_buf, "GIT_ALTERNATE_OBJECT_DIRECTORIES");
if (error == GIT_ENOTFOUND)
giterr_clear();
else if (error < 0)
goto error;
else {
const char *end;
char *alt, *sep;
if (!odb) {
error = git_repository_odb(&odb, repo);
if (error < 0)
goto error;
}

end = git_buf_cstr(&alts_buf) + git_buf_len(&alts_buf);
for (sep = alt = alts_buf.ptr; sep != end; alt = sep+1) {
for (sep = alt; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++)
;
if (*sep)
*sep = '\0';
error = git_odb_add_disk_alternate(odb, alt);
if (error < 0)
goto error;
}
}

error = git_repository_set_namespace(repo, git_buf_cstr(&namespace_buf));
if (error < 0)
goto error;

git_repository_set_index(repo, index);

if (out) {
*out = repo;
goto success;
}
error:
git_repository_free(repo);
success:
git_odb_free(odb);
git_index_free(index);
git_buf_free(&common_dir_buf);
git_buf_free(&work_tree_buf);
git_buf_free(&alts_buf);
git_buf_free(&object_dir_buf);
git_buf_free(&namespace_buf);
git_buf_free(&index_file_buf);
git_buf_free(&across_fs_buf);
git_buf_free(&ceiling_dirs_buf);
git_buf_free(&dir_buf);
return error;
}

int git_repository_open_ext(
git_repository **repo_ptr,
const char *start_path,
Expand All @@ -677,9 +492,6 @@ int git_repository_open_ext(
git_repository *repo;
git_config *config = NULL;

if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
return _git_repository_open_ext_from_env(repo_ptr, start_path);

if (repo_ptr)
*repo_ptr = NULL;

Expand Down

0 comments on commit 7b0f435

Please sign in to comment.