The old version of work-tree support was an unholy mess, barely readable,
and not to the point.

For example, why do you have to provide a worktree, when it is not used?
As in "git status".  Now it works.

Another riddle was: if you can have work trees inside the git dir, why
are some programs complaining that they need a work tree?

IOW it is allowed to call

	$ git --git-dir=../ --work-tree=. bla

when you really want to.  In this case, you are both in the git directory
and in the working tree.  So, programs have to actually test for the right
thing, namely if they are inside a working tree, and not if they are
inside a git directory.

Also, GIT_DIR=../.git should behave the same as if no GIT_DIR was
specified, unless there is a repository in the current working directory.
It does now.

The logic to determine if a repository is bare, or has a work tree
(tertium non datur), is this:

--work-tree=bla overrides GIT_WORK_TREE, which overrides core.bare = true,
which overrides core.worktree, which overrides GIT_DIR/.. when GIT_DIR
ends in /.git, which overrides the directory in which .git/ was found.

In related news, a long standing bug was fixed: when in .git/bla/x.git/,
which is a bare repository, git formerly assumed ../.. to be the
appropriate git dir.  This problem was reported by Shawn Pearce to have
caused much pain, where a colleague mistakenly ran "git init" in "/" a
long time ago, and bare repositories just would not work.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin 2007-08-01 01:30:14 +01:00 коммит произвёл Junio C Hamano
Родитель d7ac12b25d
Коммит e90fdc39b6
10 изменённых файлов: 216 добавлений и 221 удалений

Просмотреть файл

@ -174,36 +174,7 @@ static void copy_templates(const char *git_dir, int len, const char *template_di
closedir(dir); closedir(dir);
} }
/* static int create_default_files(const char *git_dir, const char *template_path)
* Get the full path to the working tree specified in $GIT_WORK_TREE
* or NULL if no working tree is specified.
*/
static const char *get_work_tree(void)
{
const char *git_work_tree;
char cwd[PATH_MAX];
static char worktree[PATH_MAX];
git_work_tree = getenv(GIT_WORK_TREE_ENVIRONMENT);
if (!git_work_tree)
return NULL;
if (!getcwd(cwd, sizeof(cwd)))
die("Unable to read current working directory");
if (chdir(git_work_tree))
die("Cannot change directory to specified working tree '%s'",
git_work_tree);
if (git_work_tree[0] != '/') {
if (!getcwd(worktree, sizeof(worktree)))
die("Unable to read current working directory");
git_work_tree = worktree;
}
if (chdir(cwd))
die("Cannot come back to cwd");
return git_work_tree;
}
static int create_default_files(const char *git_dir, const char *git_work_tree,
const char *template_path)
{ {
unsigned len = strlen(git_dir); unsigned len = strlen(git_dir);
static char path[PATH_MAX]; static char path[PATH_MAX];
@ -282,16 +253,16 @@ static int create_default_files(const char *git_dir, const char *git_work_tree,
} }
git_config_set("core.filemode", filemode ? "true" : "false"); git_config_set("core.filemode", filemode ? "true" : "false");
if (is_bare_repository() && !git_work_tree) { if (is_bare_repository())
git_config_set("core.bare", "true"); git_config_set("core.bare", "true");
}
else { else {
const char *work_tree = get_git_work_tree();
git_config_set("core.bare", "false"); git_config_set("core.bare", "false");
/* allow template config file to override the default */ /* allow template config file to override the default */
if (log_all_ref_updates == -1) if (log_all_ref_updates == -1)
git_config_set("core.logallrefupdates", "true"); git_config_set("core.logallrefupdates", "true");
if (git_work_tree) if (work_tree != git_work_tree_cfg)
git_config_set("core.worktree", git_work_tree); git_config_set("core.worktree", work_tree);
} }
return reinit; return reinit;
} }
@ -308,7 +279,6 @@ static const char init_db_usage[] =
int cmd_init_db(int argc, const char **argv, const char *prefix) int cmd_init_db(int argc, const char **argv, const char *prefix)
{ {
const char *git_dir; const char *git_dir;
const char *git_work_tree;
const char *sha1_dir; const char *sha1_dir;
const char *template_dir = NULL; const char *template_dir = NULL;
char *path; char *path;
@ -329,7 +299,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
usage(init_db_usage); usage(init_db_usage);
} }
git_work_tree = get_work_tree(); git_work_tree_cfg = xcalloc(PATH_MAX, 1);
if (!getcwd(git_work_tree_cfg, PATH_MAX))
die ("Cannot access current working directory.");
if (access(get_git_work_tree(), X_OK))
die ("Cannot access work tree '%s'", get_git_work_tree());
/* /*
* Set up the default .git directory contents * Set up the default .git directory contents
@ -346,7 +320,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
*/ */
check_repository_format(); check_repository_format();
reinit = create_default_files(git_dir, git_work_tree, template_dir); reinit = create_default_files(git_dir, template_dir);
/* /*
* And set up the object store. * And set up the object store.

Просмотреть файл

@ -469,9 +469,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
break; break;
} }
if (require_work_tree && if (require_work_tree && !is_inside_work_tree()) {
(!is_inside_work_tree() || is_inside_git_dir())) const char *work_tree = get_git_work_tree();
die("This operation must be run in a work tree"); if (!work_tree || chdir(work_tree))
die("This operation must be run in a work tree");
}
pathspec = get_pathspec(prefix, argv + i); pathspec = get_pathspec(prefix, argv + i);

Просмотреть файл

@ -321,6 +321,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
} }
if (!strcmp(arg, "--show-cdup")) { if (!strcmp(arg, "--show-cdup")) {
const char *pfx = prefix; const char *pfx = prefix;
if (!is_inside_work_tree()) {
const char *work_tree =
get_git_work_tree();
if (work_tree)
printf("%s\n", work_tree);
continue;
}
while (pfx) { while (pfx) {
pfx = strchr(pfx, '/'); pfx = strchr(pfx, '/');
if (pfx) { if (pfx) {

Просмотреть файл

@ -208,6 +208,7 @@ enum object_type {
extern int is_bare_repository_cfg; extern int is_bare_repository_cfg;
extern int is_bare_repository(void); extern int is_bare_repository(void);
extern int is_inside_git_dir(void); extern int is_inside_git_dir(void);
extern char *git_work_tree_cfg;
extern int is_inside_work_tree(void); extern int is_inside_work_tree(void);
extern const char *get_git_dir(void); extern const char *get_git_dir(void);
extern char *get_object_directory(void); extern char *get_object_directory(void);
@ -215,6 +216,7 @@ extern char *get_refs_directory(void);
extern char *get_index_file(void); extern char *get_index_file(void);
extern char *get_graft_file(void); extern char *get_graft_file(void);
extern int set_git_dir(const char *path); extern int set_git_dir(const char *path);
extern const char *get_git_work_tree(void);
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"

Просмотреть файл

@ -35,6 +35,10 @@ int pager_in_use;
int pager_use_color = 1; int pager_use_color = 1;
int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */ int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */
/* This is set by setup_git_dir_gently() and/or git_default_config() */
char *git_work_tree_cfg;
static const char *work_tree;
static const char *git_dir; static const char *git_dir;
static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file; static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
@ -62,15 +66,8 @@ static void setup_git_env(void)
int is_bare_repository(void) int is_bare_repository(void)
{ {
const char *dir, *s; /* if core.bare is not 'false', let's see if there is a work tree */
if (0 <= is_bare_repository_cfg) return is_bare_repository_cfg && !get_git_work_tree();
return is_bare_repository_cfg;
dir = get_git_dir();
if (!strcmp(dir, DEFAULT_GIT_DIR_ENVIRONMENT))
return 0;
s = strrchr(dir, '/');
return !s || strcmp(s + 1, DEFAULT_GIT_DIR_ENVIRONMENT);
} }
const char *get_git_dir(void) const char *get_git_dir(void)
@ -80,6 +77,26 @@ const char *get_git_dir(void)
return git_dir; return git_dir;
} }
const char *get_git_work_tree(void)
{
static int initialized = 0;
if (!initialized) {
work_tree = getenv(GIT_WORK_TREE_ENVIRONMENT);
/* core.bare = true overrides implicit and config work tree */
if (!work_tree && is_bare_repository_cfg < 1) {
work_tree = git_work_tree_cfg;
/* make_absolute_path also normalizes the path */
if (work_tree && !is_absolute_path(work_tree))
work_tree = xstrdup(make_absolute_path(git_path(work_tree)));
} else if (work_tree)
work_tree = xstrdup(make_absolute_path(work_tree));
initialized = 1;
if (work_tree)
is_bare_repository_cfg = 0;
}
return work_tree;
}
char *get_object_directory(void) char *get_object_directory(void)
{ {
if (!git_object_dir) if (!git_object_dir)

Просмотреть файл

@ -59,8 +59,7 @@ cd_to_toplevel () {
} }
require_work_tree () { require_work_tree () {
test $(git rev-parse --is-inside-work-tree) = true && test $(git rev-parse --is-inside-work-tree) = true ||
test $(git rev-parse --is-inside-git-dir) = false ||
die "fatal: $0 cannot be used without a working tree." die "fatal: $0 cannot be used without a working tree."
} }

11
git.c
Просмотреть файл

@ -272,9 +272,14 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv)
prefix = setup_git_directory(); prefix = setup_git_directory();
if (p->option & USE_PAGER) if (p->option & USE_PAGER)
setup_pager(); setup_pager();
if ((p->option & NEED_WORK_TREE) && if (p->option & NEED_WORK_TREE) {
(!is_inside_work_tree() || is_inside_git_dir())) const char *work_tree = get_git_work_tree();
die("%s must be run in a work tree", p->cmd); const char *git_dir = get_git_dir();
if (!is_absolute_path(git_dir))
set_git_dir(make_absolute_path(git_dir));
if (!work_tree || chdir(work_tree))
die("%s must be run in a work tree", p->cmd);
}
trace_argv_printf(argv, argc, "trace: built-in: git"); trace_argv_printf(argv, argc, "trace: built-in: git");
status = p->fn(argc, argv, prefix); status = p->fn(argc, argv, prefix);

279
setup.c
Просмотреть файл

@ -1,4 +1,8 @@
#include "cache.h" #include "cache.h"
#include "dir.h"
static int inside_git_dir = -1;
static int inside_work_tree = -1;
const char *prefix_path(const char *prefix, int len, const char *path) const char *prefix_path(const char *prefix, int len, const char *path)
{ {
@ -170,100 +174,89 @@ static int is_git_directory(const char *suspect)
return 1; return 1;
} }
static int inside_git_dir = -1;
int is_inside_git_dir(void) int is_inside_git_dir(void)
{ {
if (inside_git_dir >= 0) if (inside_git_dir < 0)
return inside_git_dir; inside_git_dir = is_inside_dir(get_git_dir());
die("BUG: is_inside_git_dir called before setup_git_directory"); return inside_git_dir;
} }
static int inside_work_tree = -1;
int is_inside_work_tree(void) int is_inside_work_tree(void)
{ {
if (inside_git_dir >= 0) if (inside_work_tree < 0)
return inside_work_tree; inside_work_tree = is_inside_dir(get_git_work_tree());
die("BUG: is_inside_work_tree called before setup_git_directory"); return inside_work_tree;
} }
static char *gitworktree_config; /*
* If no worktree was given, and we are outside of a default work tree,
static int git_setup_config(const char *var, const char *value) * now is the time to set it.
*
* In other words, if the user calls git with something like
*
* git --git-dir=/some/where/else/.git bla
*
* default to /some/where/else as working directory; if the specified
* git-dir does not end in "/.git", the cwd is used as working directory.
*/
const char *set_work_tree(const char *dir)
{ {
if (!strcmp(var, "core.worktree")) { char dir_buffer[PATH_MAX];
if (gitworktree_config) static char buffer[PATH_MAX + 1], *rel = NULL;
strlcpy(gitworktree_config, value, PATH_MAX); int len, postfix_len = strlen(DEFAULT_GIT_DIR_ENVIRONMENT) + 1;
return 0;
/* strip the variable 'dir' of the postfix "/.git" if it has it */
len = strlen(dir);
if (len > postfix_len && !strcmp(dir + len - postfix_len,
"/" DEFAULT_GIT_DIR_ENVIRONMENT)) {
strncpy(dir_buffer, dir, len - postfix_len);
/* are we inside the default work tree? */
rel = get_relative_cwd(buffer, sizeof(buffer), dir_buffer);
} }
return git_default_config(var, value); /* if rel is set, the cwd is _not_ the current working tree */
if (rel && *rel) {
if (!is_absolute_path(dir))
set_git_dir(make_absolute_path(dir));
dir = dir_buffer;
chdir(dir);
strcat(rel, "/");
inside_git_dir = 0;
} else {
rel = NULL;
dir = getcwd(buffer, sizeof(buffer));
}
git_work_tree_cfg = xstrdup(dir);
inside_work_tree = 1;
return rel;
} }
/*
* We cannot decide in this function whether we are in the work tree or
* not, since the config can only be read _after_ this function was called.
*/
const char *setup_git_directory_gently(int *nongit_ok) const char *setup_git_directory_gently(int *nongit_ok)
{ {
const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
static char cwd[PATH_MAX+1]; static char cwd[PATH_MAX+1];
char worktree[PATH_MAX+1], gitdir[PATH_MAX+1]; const char *gitdirenv;
const char *gitdirenv, *gitworktree; int len, offset;
int wt_rel_gitdir = 0;
/*
* If GIT_DIR is set explicitly, we're not going
* to do any discovery, but we still do repository
* validation.
*/
gitdirenv = getenv(GIT_DIR_ENVIRONMENT); gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
if (!gitdirenv) { if (gitdirenv) {
int len, offset; if (PATH_MAX - 40 < strlen(gitdirenv))
die("'$%s' too big", GIT_DIR_ENVIRONMENT);
if (!getcwd(cwd, sizeof(cwd)-1)) if (is_git_directory(gitdirenv)) {
die("Unable to read current working directory"); if (!work_tree_env)
return set_work_tree(gitdirenv);
offset = len = strlen(cwd);
for (;;) {
if (is_git_directory(".git"))
break;
if (offset == 0) {
offset = -1;
break;
}
chdir("..");
while (cwd[--offset] != '/')
; /* do nothing */
}
if (offset >= 0) {
inside_work_tree = 1;
git_config(git_default_config);
if (offset == len) {
inside_git_dir = 0;
return NULL;
}
cwd[len++] = '/';
cwd[len] = '\0';
inside_git_dir = !prefixcmp(cwd + offset + 1, ".git/");
return cwd + offset + 1;
}
if (chdir(cwd))
die("Cannot come back to cwd");
if (!is_git_directory(".")) {
if (nongit_ok) {
*nongit_ok = 1;
return NULL;
}
die("Not a git repository");
}
setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
if (!gitdirenv)
die("getenv after setenv failed");
}
if (PATH_MAX - 40 < strlen(gitdirenv)) {
if (nongit_ok) {
*nongit_ok = 1;
return NULL; return NULL;
} }
die("$%s too big", GIT_DIR_ENVIRONMENT);
}
if (!is_git_directory(gitdirenv)) {
if (nongit_ok) { if (nongit_ok) {
*nongit_ok = 1; *nongit_ok = 1;
return NULL; return NULL;
@ -273,92 +266,53 @@ const char *setup_git_directory_gently(int *nongit_ok)
if (!getcwd(cwd, sizeof(cwd)-1)) if (!getcwd(cwd, sizeof(cwd)-1))
die("Unable to read current working directory"); die("Unable to read current working directory");
if (chdir(gitdirenv)) {
if (nongit_ok) {
*nongit_ok = 1;
return NULL;
}
die("Cannot change directory to $%s '%s'",
GIT_DIR_ENVIRONMENT, gitdirenv);
}
if (!getcwd(gitdir, sizeof(gitdir)-1))
die("Unable to read current working directory");
if (chdir(cwd))
die("Cannot come back to cwd");
/* /*
* In case there is a work tree we may change the directory, * Test in the following order (relative to the cwd):
* therefore make GIT_DIR an absolute path. * - .git/
* - ./ (bare)
* - ../.git/
* - ../ (bare)
* - ../../.git/
* etc.
*/ */
if (gitdirenv[0] != '/') { offset = len = strlen(cwd);
setenv(GIT_DIR_ENVIRONMENT, gitdir, 1); for (;;) {
gitdirenv = getenv(GIT_DIR_ENVIRONMENT); if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
if (!gitdirenv) break;
die("getenv after setenv failed"); if (is_git_directory(".")) {
if (PATH_MAX - 40 < strlen(gitdirenv)) { inside_git_dir = 1;
if (nongit_ok) { if (!work_tree_env)
*nongit_ok = 1; inside_work_tree = 0;
return NULL; setenv(GIT_DIR_ENVIRONMENT, ".", 1);
}
die("$%s too big after expansion to absolute path",
GIT_DIR_ENVIRONMENT);
}
}
strcat(cwd, "/");
strcat(gitdir, "/");
inside_git_dir = !prefixcmp(cwd, gitdir);
gitworktree = getenv(GIT_WORK_TREE_ENVIRONMENT);
if (!gitworktree) {
gitworktree_config = worktree;
worktree[0] = '\0';
}
git_config(git_setup_config);
if (!gitworktree) {
gitworktree_config = NULL;
if (worktree[0])
gitworktree = worktree;
if (gitworktree && gitworktree[0] != '/')
wt_rel_gitdir = 1;
}
if (wt_rel_gitdir && chdir(gitdirenv))
die("Cannot change directory to $%s '%s'",
GIT_DIR_ENVIRONMENT, gitdirenv);
if (gitworktree && chdir(gitworktree)) {
if (nongit_ok) {
if (wt_rel_gitdir && chdir(cwd))
die("Cannot come back to cwd");
*nongit_ok = 1;
return NULL; return NULL;
} }
if (wt_rel_gitdir) chdir("..");
die("Cannot change directory to working tree '%s'" do {
" from $%s", gitworktree, GIT_DIR_ENVIRONMENT); if (!offset) {
else if (nongit_ok) {
die("Cannot change directory to working tree '%s'", if (chdir(cwd))
gitworktree); die("Cannot come back to cwd");
} *nongit_ok = 1;
if (!getcwd(worktree, sizeof(worktree)-1)) return NULL;
die("Unable to read current working directory"); }
strcat(worktree, "/"); die("Not a git repository");
inside_work_tree = !prefixcmp(cwd, worktree); }
} while (cwd[--offset] != '/');
if (gitworktree && inside_work_tree && !prefixcmp(worktree, gitdir) &&
strcmp(worktree, gitdir)) {
inside_git_dir = 0;
} }
if (!inside_work_tree) { inside_git_dir = 0;
if (chdir(cwd)) if (!work_tree_env)
die("Cannot come back to cwd"); inside_work_tree = 1;
git_work_tree_cfg = xstrndup(cwd, offset);
if (offset == len)
return NULL; return NULL;
}
if (!strcmp(cwd, worktree)) /* Make "offset" point to past the '/', and add a '/' at the end */
return NULL; offset++;
return cwd+strlen(worktree); cwd[len++] = '/';
cwd[len] = 0;
return cwd + offset;
} }
int git_config_perm(const char *var, const char *value) int git_config_perm(const char *var, const char *value)
@ -386,6 +340,16 @@ int check_repository_format_version(const char *var, const char *value)
repository_format_version = git_config_int(var, value); repository_format_version = git_config_int(var, value);
else if (strcmp(var, "core.sharedrepository") == 0) else if (strcmp(var, "core.sharedrepository") == 0)
shared_repository = git_config_perm(var, value); shared_repository = git_config_perm(var, value);
else if (strcmp(var, "core.bare") == 0) {
is_bare_repository_cfg = git_config_bool(var, value);
if (is_bare_repository_cfg == 1)
inside_work_tree = -1;
} else if (strcmp(var, "core.worktree") == 0) {
if (git_work_tree_cfg)
free(git_work_tree_cfg);
git_work_tree_cfg = xstrdup(value);
inside_work_tree = -1;
}
return 0; return 0;
} }
@ -402,5 +366,16 @@ const char *setup_git_directory(void)
{ {
const char *retval = setup_git_directory_gently(NULL); const char *retval = setup_git_directory_gently(NULL);
check_repository_format(); check_repository_format();
/* If the work tree is not the default one, recompute prefix */
if (inside_work_tree < 0) {
static char buffer[PATH_MAX + 1];
char *rel;
if (retval && chdir(retval))
die ("Could not jump back into original cwd");
rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());
return rel && *rel ? strcat(rel, "/") : NULL;
}
return retval; return retval;
} }

Просмотреть файл

@ -31,9 +31,9 @@ test_rev_parse() {
test_rev_parse toplevel false false true '' test_rev_parse toplevel false false true ''
cd .git || exit 1 cd .git || exit 1
test_rev_parse .git/ false true true .git/ test_rev_parse .git/ true true false ''
cd objects || exit 1 cd objects || exit 1
test_rev_parse .git/objects/ false true true .git/objects/ test_rev_parse .git/objects/ true true false ''
cd ../.. || exit 1 cd ../.. || exit 1
mkdir -p sub/dir || exit 1 mkdir -p sub/dir || exit 1
@ -42,7 +42,7 @@ test_rev_parse subdirectory false false true sub/dir/
cd ../.. || exit 1 cd ../.. || exit 1
git config core.bare true git config core.bare true
test_rev_parse 'core.bare = true' true false true test_rev_parse 'core.bare = true' true false false
git config --unset core.bare git config --unset core.bare
test_rev_parse 'core.bare undefined' false false true test_rev_parse 'core.bare undefined' false false true
@ -50,28 +50,28 @@ test_rev_parse 'core.bare undefined' false false true
mkdir work || exit 1 mkdir work || exit 1
cd work || exit 1 cd work || exit 1
export GIT_DIR=../.git export GIT_DIR=../.git
export GIT_CONFIG="$GIT_DIR"/config export GIT_CONFIG="$(pwd)"/../.git/config
git config core.bare false git config core.bare false
test_rev_parse 'GIT_DIR=../.git, core.bare = false' false false true '' test_rev_parse 'GIT_DIR=../.git, core.bare = false' false false true work/
git config core.bare true git config core.bare true
test_rev_parse 'GIT_DIR=../.git, core.bare = true' true false true '' test_rev_parse 'GIT_DIR=../.git, core.bare = true' true false false ''
git config --unset core.bare git config --unset core.bare
test_rev_parse 'GIT_DIR=../.git, core.bare undefined' false false true '' test_rev_parse 'GIT_DIR=../.git, core.bare undefined' false false true work/
mv ../.git ../repo.git || exit 1 mv ../.git ../repo.git || exit 1
export GIT_DIR=../repo.git export GIT_DIR=../repo.git
export GIT_CONFIG="$GIT_DIR"/config export GIT_CONFIG="$(pwd)"/../repo.git/config
git config core.bare false git config core.bare false
test_rev_parse 'GIT_DIR=../repo.git, core.bare = false' false false true '' test_rev_parse 'GIT_DIR=../repo.git, core.bare = false' false false true ''
git config core.bare true git config core.bare true
test_rev_parse 'GIT_DIR=../repo.git, core.bare = true' true false true '' test_rev_parse 'GIT_DIR=../repo.git, core.bare = true' true false false ''
git config --unset core.bare git config --unset core.bare
test_rev_parse 'GIT_DIR=../repo.git, core.bare undefined' true false true '' test_rev_parse 'GIT_DIR=../repo.git, core.bare undefined' false false true ''
test_done test_done

Просмотреть файл

@ -33,17 +33,17 @@ mv .git repo.git || exit 1
say "core.worktree = relative path" say "core.worktree = relative path"
export GIT_DIR=repo.git export GIT_DIR=repo.git
export GIT_CONFIG=$GIT_DIR/config export GIT_CONFIG="$(pwd)"/$GIT_DIR/config
unset GIT_WORK_TREE unset GIT_WORK_TREE
git config core.worktree ../work git config core.worktree ../work
test_rev_parse 'outside' false false false test_rev_parse 'outside' false false false
cd work || exit 1 cd work || exit 1
export GIT_DIR=../repo.git export GIT_DIR=../repo.git
export GIT_CONFIG=$GIT_DIR/config export GIT_CONFIG="$(pwd)"/$GIT_DIR/config
test_rev_parse 'inside' false false true '' test_rev_parse 'inside' false false true ''
cd sub/dir || exit 1 cd sub/dir || exit 1
export GIT_DIR=../../../repo.git export GIT_DIR=../../../repo.git
export GIT_CONFIG=$GIT_DIR/config export GIT_CONFIG="$(pwd)"/$GIT_DIR/config
test_rev_parse 'subdirectory' false false true sub/dir/ test_rev_parse 'subdirectory' false false true sub/dir/
cd ../../.. || exit 1 cd ../../.. || exit 1
@ -84,9 +84,23 @@ test_rev_parse 'in repo.git' false true false
cd objects || exit 1 cd objects || exit 1
test_rev_parse 'in repo.git/objects' false true false test_rev_parse 'in repo.git/objects' false true false
cd ../work || exit 1 cd ../work || exit 1
test_rev_parse 'in repo.git/work' false false true '' test_rev_parse 'in repo.git/work' false true true ''
cd sub/dir || exit 1 cd sub/dir || exit 1
test_rev_parse 'in repo.git/sub/dir' false false true sub/dir/ test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/
cd ../../../.. || exit 1 cd ../../../.. || exit 1
test_expect_success 'repo finds its work tree' '
(cd repo.git &&
: > work/sub/dir/untracked &&
test sub/dir/untracked = "$(git ls-files --others)")
'
test_expect_success 'repo finds its work tree from work tree, too' '
(cd repo.git/work/sub/dir &&
: > tracked &&
git --git-dir=../../.. add tracked &&
cd ../../.. &&
test sub/dir/tracked = "$(git ls-files)")
'
test_done test_done