Commit ebeb56f0 by Edward Thomson Committed by GitHub

Merge pull request #3711 from joshtriplett/git_repository_discover_default

Add GIT_REPOSITORY_OPEN_FROM_ENV flag to respect $GIT_* environment vars
parents e4218450 2b80260e
......@@ -3,6 +3,13 @@ v0.24 + 1
### Changes or improvements
* Fix repository discovery with `git_repository_discover` and
`git_repository_open_ext` to match git's handling of a ceiling
directory at the current directory. git only checks ceiling
directories when its search ascends to a parent directory. A ceiling
directory matching the starting directory will not prevent git from
finding a repository in the starting directory or a parent directory.
### API additions
* `git_commit_create_buffer()` creates a commit and writes it into a
......@@ -13,6 +20,25 @@ v0.24 + 1
writing into a stream. Useful when you do not know the final size or
want to copy the contents from another stream.
* New flags for `git_repository_open_ext`:
* `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.
### API removals
* `git_blob_create_fromchunks()` has been removed in favour of
......
......@@ -95,11 +95,29 @@ 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;
/**
......@@ -110,7 +128,8 @@ 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.
* inside the working directory of the repository. May be NULL if
* flags is GIT_REPOSITORY_OPEN_FROM_ENV.
* @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
......
......@@ -359,7 +359,8 @@ static int find_repo(
git_buf path = GIT_BUF_INIT;
struct stat st;
dev_t initial_device = 0;
bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0);
int min_iterations;
bool in_dot_git;
int ceiling_offset;
git_buf_free(repo_path);
......@@ -367,13 +368,30 @@ static int find_repo(
if ((error = git_path_prettify(&path, start_path, NULL)) < 0)
return error;
ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
/* 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;
}
if (!try_with_dot_git &&
(error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
return error;
while (!error && (min_iterations || !(path.ptr[ceiling_offset] == 0 ||
(flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))) {
if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
if (!in_dot_git)
if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
break;
in_dot_git = !in_dot_git;
}
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)
......@@ -414,17 +432,10 @@ static int find_repo(
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;
/* 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);
}
if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
......@@ -480,6 +491,172 @@ 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,
......@@ -492,6 +669,9 @@ 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;
......
......@@ -118,12 +118,22 @@ void test_repo_discover__0(void)
cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER_SUB);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
/* this must pass as ceiling_directories cannot prevent the current
* working directory to be checked */
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path);
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
//this must pass as ceiling_directories cannot predent the current
//working directory to be checked
cl_git_pass(git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
ensure_repository_discover(SUB_REPOSITORY_FOLDER, ceiling_dirs, &sub_repository_path);
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
......
......@@ -3,12 +3,42 @@
#include "sysdir.h"
#include <ctype.h>
static void clear_git_env(void)
{
cl_setenv("GIT_DIR", NULL);
cl_setenv("GIT_CEILING_DIRECTORIES", NULL);
cl_setenv("GIT_INDEX_FILE", NULL);
cl_setenv("GIT_NAMESPACE", NULL);
cl_setenv("GIT_OBJECT_DIRECTORY", NULL);
cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL);
cl_setenv("GIT_WORK_TREE", NULL);
cl_setenv("GIT_COMMON_DIR", NULL);
}
static git_buf cwd_backup_buf = GIT_BUF_INIT;
void test_repo_open__initialize(void)
{
if (!git_buf_is_allocated(&cwd_backup_buf))
cl_git_pass(git_path_prettify_dir(&cwd_backup_buf, ".", NULL));
clear_git_env();
}
void test_repo_open__cleanup(void)
{
cl_git_sandbox_cleanup();
if (git_path_isdir("alternate"))
git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES);
if (git_path_isdir("attr"))
git_futils_rmdir_r("attr", NULL, GIT_RMDIR_REMOVE_FILES);
if (git_path_isdir("testrepo.git"))
git_futils_rmdir_r("testrepo.git", NULL, GIT_RMDIR_REMOVE_FILES);
if (git_path_isdir("peeled.git"))
git_futils_rmdir_r("peeled.git", NULL, GIT_RMDIR_REMOVE_FILES);
cl_must_pass(p_chdir(git_buf_cstr(&cwd_backup_buf)));
clear_git_env();
}
void test_repo_open__bare_empty_repo(void)
......@@ -196,8 +226,9 @@ void test_repo_open__failures(void)
&repo, "attr/sub", GIT_REPOSITORY_OPEN_NO_SEARCH, NULL));
/* fail with ceiling too low */
cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
cl_git_fail(git_repository_open_ext(&repo, "attr/sub", 0, ceiling.ptr));
cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
cl_git_fail(git_repository_open_ext(&repo, "attr/sub/sub", 0, ceiling.ptr));
/* fail with no repo */
cl_git_pass(p_mkdir("alternate", 0777));
......@@ -205,6 +236,12 @@ void test_repo_open__failures(void)
cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL));
cl_git_fail(git_repository_open_ext(&repo, "alternate/.git", 0, NULL));
/* fail with no searching and no appending .git */
cl_git_fail(git_repository_open_ext(
&repo, "attr",
GIT_REPOSITORY_OPEN_NO_SEARCH | GIT_REPOSITORY_OPEN_NO_DOTGIT,
NULL));
git_buf_free(&ceiling);
}
......@@ -394,3 +431,231 @@ void test_repo_open__force_bare(void)
cl_assert(git_repository_is_bare(barerepo));
git_repository_free(barerepo);
}
static int GIT_FORMAT_PRINTF(2, 3) cl_setenv_printf(const char *name, const char *fmt, ...)
{
int ret;
va_list args;
git_buf buf = GIT_BUF_INIT;
va_start(args, fmt);
cl_git_pass(git_buf_vprintf(&buf, fmt, args));
va_end(args);
ret = cl_setenv(name, git_buf_cstr(&buf));
git_buf_free(&buf);
return ret;
}
/* Helper functions for test_repo_open__env, passing through the file and line
* from the caller rather than those of the helper. The expression strings
* distinguish between the possible failures within the helper. */
static void env_pass_(const char *path, const char *file, int line)
{
git_repository *repo;
cl_git_pass_(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line);
cl_git_pass_(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line);
cl_assert_at_line(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0, file, line);
cl_assert_at_line(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0, file, line);
cl_assert_at_line(!git_repository_is_bare(repo), file, line);
git_repository_free(repo);
}
#define env_pass(path) env_pass_((path), __FILE__, __LINE__)
#define cl_git_fail_at_line(expr, file, line) clar__assert((expr) < 0, file, line, "Expected function call to fail: " #expr, NULL, 1)
static void env_fail_(const char *path, const char *file, int line)
{
git_repository *repo;
cl_git_fail_at_line(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line);
cl_git_fail_at_line(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line);
}
#define env_fail(path) env_fail_((path), __FILE__, __LINE__)
static void env_cd_(
const char *path,
void (*passfail_)(const char *, const char *, int),
const char *file, int line)
{
git_buf cwd_buf = GIT_BUF_INIT;
cl_git_pass(git_path_prettify_dir(&cwd_buf, ".", NULL));
cl_must_pass(p_chdir(path));
passfail_(NULL, file, line);
cl_must_pass(p_chdir(git_buf_cstr(&cwd_buf)));
}
#define env_cd_pass(path) env_cd_((path), env_pass_, __FILE__, __LINE__)
#define env_cd_fail(path) env_cd_((path), env_fail_, __FILE__, __LINE__)
static void env_check_objects_(bool a, bool t, bool p, const char *file, int line)
{
git_repository *repo;
git_oid oid_a, oid_t, oid_p;
git_object *object;
cl_git_pass(git_oid_fromstr(&oid_a, "45141a79a77842c59a63229403220a4e4be74e3d"));
cl_git_pass(git_oid_fromstr(&oid_t, "1385f264afb75a56a5bec74243be9b367ba4ca08"));
cl_git_pass(git_oid_fromstr(&oid_p, "0df1a5865c8abfc09f1f2182e6a31be550e99f07"));
cl_git_pass_(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line);
if (a) {
cl_git_pass_(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line);
git_object_free(object);
} else
cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line);
if (t) {
cl_git_pass_(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line);
git_object_free(object);
} else
cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line);
if (p) {
cl_git_pass_(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line);
git_object_free(object);
} else
cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line);
git_repository_free(repo);
}
#define env_check_objects(a, t, t2) env_check_objects_((a), (t), (t2), __FILE__, __LINE__)
void test_repo_open__env(void)
{
git_repository *repo = NULL;
git_buf repo_dir_buf = GIT_BUF_INIT;
const char *repo_dir = NULL;
git_index *index = NULL;
const char *t_obj = "testrepo.git/objects";
const char *p_obj = "peeled.git/objects";
cl_fixture_sandbox("attr");
cl_fixture_sandbox("testrepo.git");
cl_fixture_sandbox("peeled.git");
cl_git_pass(p_rename("attr/.gitted", "attr/.git"));
cl_git_pass(git_path_prettify_dir(&repo_dir_buf, "attr", NULL));
repo_dir = git_buf_cstr(&repo_dir_buf);
/* GIT_DIR that doesn't exist */
cl_setenv("GIT_DIR", "does-not-exist");
env_fail(NULL);
/* Explicit start_path overrides GIT_DIR */
env_pass("attr");
env_pass("attr/.git");
env_pass("attr/sub");
env_pass("attr/sub/sub");
/* GIT_DIR with relative paths */
cl_setenv("GIT_DIR", "attr/.git");
env_pass(NULL);
cl_setenv("GIT_DIR", "attr");
env_fail(NULL);
cl_setenv("GIT_DIR", "attr/sub");
env_fail(NULL);
cl_setenv("GIT_DIR", "attr/sub/sub");
env_fail(NULL);
/* GIT_DIR with absolute paths */
cl_setenv_printf("GIT_DIR", "%s/.git", repo_dir);
env_pass(NULL);
cl_setenv("GIT_DIR", repo_dir);
env_fail(NULL);
cl_setenv_printf("GIT_DIR", "%s/sub", repo_dir);
env_fail(NULL);
cl_setenv_printf("GIT_DIR", "%s/sub/sub", repo_dir);
env_fail(NULL);
cl_setenv("GIT_DIR", NULL);
/* Searching from the current directory */
env_cd_pass("attr");
env_cd_pass("attr/.git");
env_cd_pass("attr/sub");
env_cd_pass("attr/sub/sub");
/* A ceiling directory blocks searches from ascending into that
* directory, but doesn't block the start_path itself. */
cl_setenv("GIT_CEILING_DIRECTORIES", repo_dir);
env_cd_pass("attr");
env_cd_fail("attr/sub");
env_cd_fail("attr/sub/sub");
cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s/sub", repo_dir);
env_cd_pass("attr");
env_cd_pass("attr/sub");
env_cd_fail("attr/sub/sub");
/* Multiple ceiling directories */
cl_setenv_printf("GIT_CEILING_DIRECTORIES", "123%c%s/sub%cabc",
GIT_PATH_LIST_SEPARATOR, repo_dir, GIT_PATH_LIST_SEPARATOR);
env_cd_pass("attr");
env_cd_pass("attr/sub");
env_cd_fail("attr/sub/sub");
cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s%c%s/sub",
repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir);
env_cd_pass("attr");
env_cd_fail("attr/sub");
env_cd_fail("attr/sub/sub");
cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s/sub%c%s",
repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir);
env_cd_pass("attr");
env_cd_fail("attr/sub");
env_cd_fail("attr/sub/sub");
cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s%c%s/sub/sub",
repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir);
env_cd_pass("attr");
env_cd_fail("attr/sub");
env_cd_fail("attr/sub/sub");
cl_setenv("GIT_CEILING_DIRECTORIES", NULL);
/* Index files */
cl_setenv("GIT_INDEX_FILE", cl_fixture("gitgit.index"));
cl_git_pass(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL));
cl_git_pass(git_repository_index(&index, repo));
cl_assert_equal_s(git_index_path(index), cl_fixture("gitgit.index"));
cl_assert_equal_i(git_index_entrycount(index), 1437);
git_index_free(index);
git_repository_free(repo);
cl_setenv("GIT_INDEX_FILE", NULL);
/* Namespaces */
cl_setenv("GIT_NAMESPACE", "some-namespace");
cl_git_pass(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL));
cl_assert_equal_s(git_repository_get_namespace(repo), "some-namespace");
git_repository_free(repo);
cl_setenv("GIT_NAMESPACE", NULL);
/* Object directories and alternates */
env_check_objects(true, false, false);
cl_setenv("GIT_OBJECT_DIRECTORY", t_obj);
env_check_objects(false, true, false);
cl_setenv("GIT_OBJECT_DIRECTORY", NULL);
cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", t_obj);
env_check_objects(true, true, false);
cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL);
cl_setenv("GIT_OBJECT_DIRECTORY", p_obj);
env_check_objects(false, false, true);
cl_setenv("GIT_OBJECT_DIRECTORY", NULL);
cl_setenv("GIT_OBJECT_DIRECTORY", t_obj);
cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", p_obj);
env_check_objects(false, true, true);
cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL);
cl_setenv("GIT_OBJECT_DIRECTORY", NULL);
cl_setenv_printf("GIT_ALTERNATE_OBJECT_DIRECTORIES",
"%s%c%s", t_obj, GIT_PATH_LIST_SEPARATOR, p_obj);
env_check_objects(true, true, true);
cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL);
cl_setenv_printf("GIT_ALTERNATE_OBJECT_DIRECTORIES",
"%s%c%s", p_obj, GIT_PATH_LIST_SEPARATOR, t_obj);
env_check_objects(true, true, true);
cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL);
cl_fixture_cleanup("peeled.git");
cl_fixture_cleanup("testrepo.git");
cl_fixture_cleanup("attr");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment