mirror of
https://github.com/git/git
synced 2024-10-30 04:01:21 +00:00
Merge branch 'jn/maint-setup-fix' (early part) into jn/paginate-fix
* 'jn/maint-setup-fix' (early part): Revert "rehabilitate 'git index-pack' inside the object store" setup: do not forget working dir from subdir of gitdir t4111 (apply): refresh index before applying patches to it setup: split off get_device_or_die helper setup: split off a function to handle hitting ceiling in repo search setup: split off code to handle stumbling upon a repository setup: split off a function to checks working dir for .git file setup: split off $GIT_DIR-set case from setup_git_directory_gently tests: try git apply from subdir of toplevel t1501 (rev-parse): clarify
This commit is contained in:
commit
fc196b6890
4 changed files with 550 additions and 258 deletions
|
@ -880,29 +880,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
||||||
char *index_name_buf = NULL, *keep_name_buf = NULL;
|
char *index_name_buf = NULL, *keep_name_buf = NULL;
|
||||||
struct pack_idx_entry **idx_objects;
|
struct pack_idx_entry **idx_objects;
|
||||||
unsigned char pack_sha1[20];
|
unsigned char pack_sha1[20];
|
||||||
|
int nongit;
|
||||||
|
|
||||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||||
usage(index_pack_usage);
|
usage(index_pack_usage);
|
||||||
|
|
||||||
/*
|
prefix = setup_git_directory_gently(&nongit);
|
||||||
* We wish to read the repository's config file if any, and
|
git_config(git_index_pack_config, NULL);
|
||||||
* for that it is necessary to call setup_git_directory_gently().
|
if (prefix && chdir(prefix))
|
||||||
* However if the cwd was inside .git/objects/pack/ then we need
|
die("Cannot come back to cwd");
|
||||||
* to go back there or all the pack name arguments will be wrong.
|
|
||||||
* And in that case we cannot rely on any prefix returned by
|
|
||||||
* setup_git_directory_gently() either.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
char cwd[PATH_MAX+1];
|
|
||||||
int nongit;
|
|
||||||
|
|
||||||
if (!getcwd(cwd, sizeof(cwd)-1))
|
|
||||||
die("Unable to get current working directory");
|
|
||||||
setup_git_directory_gently(&nongit);
|
|
||||||
git_config(git_index_pack_config, NULL);
|
|
||||||
if (chdir(cwd))
|
|
||||||
die("Cannot come back to cwd");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
|
|
171
setup.c
171
setup.c
|
@ -313,6 +313,93 @@ const char *read_gitfile_gently(const char *path)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *setup_explicit_git_dir(const char *gitdirenv,
|
||||||
|
const char *work_tree_env, int *nongit_ok)
|
||||||
|
{
|
||||||
|
static char buffer[1024 + 1];
|
||||||
|
const char *retval;
|
||||||
|
|
||||||
|
if (PATH_MAX - 40 < strlen(gitdirenv))
|
||||||
|
die("'$%s' too big", GIT_DIR_ENVIRONMENT);
|
||||||
|
if (!is_git_directory(gitdirenv)) {
|
||||||
|
if (nongit_ok) {
|
||||||
|
*nongit_ok = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
die("Not a git repository: '%s'", gitdirenv);
|
||||||
|
}
|
||||||
|
if (!work_tree_env) {
|
||||||
|
retval = set_work_tree(gitdirenv);
|
||||||
|
/* config may override worktree */
|
||||||
|
if (check_repository_format_gently(nongit_ok))
|
||||||
|
return NULL;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
if (check_repository_format_gently(nongit_ok))
|
||||||
|
return NULL;
|
||||||
|
retval = get_relative_cwd(buffer, sizeof(buffer) - 1,
|
||||||
|
get_git_work_tree());
|
||||||
|
if (!retval || !*retval)
|
||||||
|
return NULL;
|
||||||
|
set_git_dir(make_absolute_path(gitdirenv));
|
||||||
|
if (chdir(work_tree_env) < 0)
|
||||||
|
die_errno ("Could not chdir to '%s'", work_tree_env);
|
||||||
|
strcat(buffer, "/");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cwd_contains_git_dir(const char **gitfile_dirp)
|
||||||
|
{
|
||||||
|
const char *gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
|
||||||
|
*gitfile_dirp = gitfile_dir;
|
||||||
|
if (gitfile_dir) {
|
||||||
|
if (set_git_dir(gitfile_dir))
|
||||||
|
die("Repository setup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *setup_bare_git_dir(const char *work_tree_env,
|
||||||
|
int offset, int len, char *cwd, int *nongit_ok)
|
||||||
|
{
|
||||||
|
int root_len;
|
||||||
|
|
||||||
|
inside_git_dir = 1;
|
||||||
|
if (!work_tree_env)
|
||||||
|
inside_work_tree = 0;
|
||||||
|
if (offset != len) {
|
||||||
|
if (chdir(cwd))
|
||||||
|
die_errno("Cannot come back to cwd");
|
||||||
|
root_len = offset_1st_component(cwd);
|
||||||
|
cwd[offset > root_len ? offset : root_len] = '\0';
|
||||||
|
set_git_dir(cwd);
|
||||||
|
} else
|
||||||
|
set_git_dir(".");
|
||||||
|
check_repository_format_gently(nongit_ok);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *setup_nongit(const char *cwd, int *nongit_ok)
|
||||||
|
{
|
||||||
|
if (!nongit_ok)
|
||||||
|
die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
|
||||||
|
if (chdir(cwd))
|
||||||
|
die_errno("Cannot come back to cwd");
|
||||||
|
*nongit_ok = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dev_t get_device_or_die(const char *path, const char *prefix)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
if (stat(path, &buf))
|
||||||
|
die_errno("failed to stat '%s%s%s'",
|
||||||
|
prefix ? prefix : "",
|
||||||
|
prefix ? "/" : "", path);
|
||||||
|
return buf.st_dev;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We cannot decide in this function whether we are in the work tree or
|
* 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.
|
* not, since the config can only be read _after_ this function was called.
|
||||||
|
@ -327,7 +414,6 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
||||||
int len, offset, ceil_offset, root_len;
|
int len, offset, ceil_offset, root_len;
|
||||||
dev_t current_device = 0;
|
dev_t current_device = 0;
|
||||||
int one_filesystem = 1;
|
int one_filesystem = 1;
|
||||||
struct stat buf;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let's assume that we are in a git repository.
|
* Let's assume that we are in a git repository.
|
||||||
|
@ -343,38 +429,8 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
||||||
* validation.
|
* validation.
|
||||||
*/
|
*/
|
||||||
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
|
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
|
||||||
if (gitdirenv) {
|
if (gitdirenv)
|
||||||
if (PATH_MAX - 40 < strlen(gitdirenv))
|
return setup_explicit_git_dir(gitdirenv, work_tree_env, nongit_ok);
|
||||||
die("'$%s' too big", GIT_DIR_ENVIRONMENT);
|
|
||||||
if (is_git_directory(gitdirenv)) {
|
|
||||||
static char buffer[1024 + 1];
|
|
||||||
const char *retval;
|
|
||||||
|
|
||||||
if (!work_tree_env) {
|
|
||||||
retval = set_work_tree(gitdirenv);
|
|
||||||
/* config may override worktree */
|
|
||||||
if (check_repository_format_gently(nongit_ok))
|
|
||||||
return NULL;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
if (check_repository_format_gently(nongit_ok))
|
|
||||||
return NULL;
|
|
||||||
retval = get_relative_cwd(buffer, sizeof(buffer) - 1,
|
|
||||||
get_git_work_tree());
|
|
||||||
if (!retval || !*retval)
|
|
||||||
return NULL;
|
|
||||||
set_git_dir(make_absolute_path(gitdirenv));
|
|
||||||
if (chdir(work_tree_env) < 0)
|
|
||||||
die_errno ("Could not chdir to '%s'", work_tree_env);
|
|
||||||
strcat(buffer, "/");
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
if (nongit_ok) {
|
|
||||||
*nongit_ok = 1;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
die("Not a git repository: '%s'", gitdirenv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!getcwd(cwd, sizeof(cwd)-1))
|
if (!getcwd(cwd, sizeof(cwd)-1))
|
||||||
die_errno("Unable to read current working directory");
|
die_errno("Unable to read current working directory");
|
||||||
|
@ -396,49 +452,20 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
||||||
*/
|
*/
|
||||||
offset = len = strlen(cwd);
|
offset = len = strlen(cwd);
|
||||||
one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
|
one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
|
||||||
if (one_filesystem) {
|
if (one_filesystem)
|
||||||
if (stat(".", &buf))
|
current_device = get_device_or_die(".", NULL);
|
||||||
die_errno("failed to stat '.'");
|
|
||||||
current_device = buf.st_dev;
|
|
||||||
}
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
|
if (cwd_contains_git_dir(&gitfile_dir))
|
||||||
if (gitfile_dir) {
|
|
||||||
if (set_git_dir(gitfile_dir))
|
|
||||||
die("Repository setup failed");
|
|
||||||
break;
|
break;
|
||||||
}
|
if (is_git_directory("."))
|
||||||
if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
|
return setup_bare_git_dir(work_tree_env, offset,
|
||||||
break;
|
len, cwd, nongit_ok);
|
||||||
if (is_git_directory(".")) {
|
|
||||||
inside_git_dir = 1;
|
|
||||||
if (!work_tree_env)
|
|
||||||
inside_work_tree = 0;
|
|
||||||
if (offset != len) {
|
|
||||||
root_len = offset_1st_component(cwd);
|
|
||||||
cwd[offset > root_len ? offset : root_len] = '\0';
|
|
||||||
set_git_dir(cwd);
|
|
||||||
} else
|
|
||||||
set_git_dir(".");
|
|
||||||
check_repository_format_gently(nongit_ok);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
while (--offset > ceil_offset && cwd[offset] != '/');
|
while (--offset > ceil_offset && cwd[offset] != '/');
|
||||||
if (offset <= ceil_offset) {
|
if (offset <= ceil_offset)
|
||||||
if (nongit_ok) {
|
return setup_nongit(cwd, nongit_ok);
|
||||||
if (chdir(cwd))
|
|
||||||
die_errno("Cannot come back to cwd");
|
|
||||||
*nongit_ok = 1;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
|
|
||||||
}
|
|
||||||
if (one_filesystem) {
|
if (one_filesystem) {
|
||||||
if (stat("..", &buf)) {
|
dev_t parent_device = get_device_or_die("..", cwd);
|
||||||
cwd[offset] = '\0';
|
if (parent_device != current_device) {
|
||||||
die_errno("failed to stat '%s/..'", cwd);
|
|
||||||
}
|
|
||||||
if (buf.st_dev != current_device) {
|
|
||||||
if (nongit_ok) {
|
if (nongit_ok) {
|
||||||
if (chdir(cwd))
|
if (chdir(cwd))
|
||||||
die_errno("Cannot come back to cwd");
|
die_errno("Cannot come back to cwd");
|
||||||
|
|
|
@ -3,183 +3,320 @@
|
||||||
test_description='test separate work tree'
|
test_description='test separate work tree'
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_rev_parse() {
|
test_expect_success 'setup' '
|
||||||
name=$1
|
EMPTY_TREE=$(git write-tree) &&
|
||||||
shift
|
EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&
|
||||||
|
CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&
|
||||||
|
ZEROES=0000000000000000000000000000000000000000 &&
|
||||||
|
EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") &&
|
||||||
|
CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") &&
|
||||||
|
|
||||||
test_expect_success "$name: is-bare-repository" \
|
mkdir -p work/sub/dir &&
|
||||||
"test '$1' = \"\$(git rev-parse --is-bare-repository)\""
|
mkdir -p work2 &&
|
||||||
shift
|
mv .git repo.git
|
||||||
[ $# -eq 0 ] && return
|
|
||||||
|
|
||||||
test_expect_success "$name: is-inside-git-dir" \
|
|
||||||
"test '$1' = \"\$(git rev-parse --is-inside-git-dir)\""
|
|
||||||
shift
|
|
||||||
[ $# -eq 0 ] && return
|
|
||||||
|
|
||||||
test_expect_success "$name: is-inside-work-tree" \
|
|
||||||
"test '$1' = \"\$(git rev-parse --is-inside-work-tree)\""
|
|
||||||
shift
|
|
||||||
[ $# -eq 0 ] && return
|
|
||||||
|
|
||||||
test_expect_success "$name: prefix" \
|
|
||||||
"test '$1' = \"\$(git rev-parse --show-prefix)\""
|
|
||||||
shift
|
|
||||||
[ $# -eq 0 ] && return
|
|
||||||
}
|
|
||||||
|
|
||||||
EMPTY_TREE=$(git write-tree)
|
|
||||||
mkdir -p work/sub/dir || exit 1
|
|
||||||
mkdir -p work2 || exit 1
|
|
||||||
mv .git repo.git || exit 1
|
|
||||||
|
|
||||||
say "core.worktree = relative path"
|
|
||||||
GIT_DIR=repo.git
|
|
||||||
GIT_CONFIG="$(pwd)"/$GIT_DIR/config
|
|
||||||
export GIT_DIR GIT_CONFIG
|
|
||||||
unset GIT_WORK_TREE
|
|
||||||
git config core.worktree ../work
|
|
||||||
test_rev_parse 'outside' false false false
|
|
||||||
cd work || exit 1
|
|
||||||
GIT_DIR=../repo.git
|
|
||||||
GIT_CONFIG="$(pwd)"/$GIT_DIR/config
|
|
||||||
test_rev_parse 'inside' false false true ''
|
|
||||||
cd sub/dir || exit 1
|
|
||||||
GIT_DIR=../../../repo.git
|
|
||||||
GIT_CONFIG="$(pwd)"/$GIT_DIR/config
|
|
||||||
test_rev_parse 'subdirectory' false false true sub/dir/
|
|
||||||
cd ../../.. || exit 1
|
|
||||||
|
|
||||||
say "core.worktree = absolute path"
|
|
||||||
GIT_DIR=$(pwd)/repo.git
|
|
||||||
GIT_CONFIG=$GIT_DIR/config
|
|
||||||
git config core.worktree "$(pwd)/work"
|
|
||||||
test_rev_parse 'outside' false false false
|
|
||||||
cd work2
|
|
||||||
test_rev_parse 'outside2' false false false
|
|
||||||
cd ../work || exit 1
|
|
||||||
test_rev_parse 'inside' false false true ''
|
|
||||||
cd sub/dir || exit 1
|
|
||||||
test_rev_parse 'subdirectory' false false true sub/dir/
|
|
||||||
cd ../../.. || exit 1
|
|
||||||
|
|
||||||
say "GIT_WORK_TREE=relative path (override core.worktree)"
|
|
||||||
GIT_DIR=$(pwd)/repo.git
|
|
||||||
GIT_CONFIG=$GIT_DIR/config
|
|
||||||
git config core.worktree non-existent
|
|
||||||
GIT_WORK_TREE=work
|
|
||||||
export GIT_WORK_TREE
|
|
||||||
test_rev_parse 'outside' false false false
|
|
||||||
cd work2
|
|
||||||
test_rev_parse 'outside' false false false
|
|
||||||
cd ../work || exit 1
|
|
||||||
GIT_WORK_TREE=.
|
|
||||||
test_rev_parse 'inside' false false true ''
|
|
||||||
cd sub/dir || exit 1
|
|
||||||
GIT_WORK_TREE=../..
|
|
||||||
test_rev_parse 'subdirectory' false false true sub/dir/
|
|
||||||
cd ../../.. || exit 1
|
|
||||||
|
|
||||||
mv work repo.git/work
|
|
||||||
mv work2 repo.git/work2
|
|
||||||
|
|
||||||
say "GIT_WORK_TREE=absolute path, work tree below git dir"
|
|
||||||
GIT_DIR=$(pwd)/repo.git
|
|
||||||
GIT_CONFIG=$GIT_DIR/config
|
|
||||||
GIT_WORK_TREE=$(pwd)/repo.git/work
|
|
||||||
test_rev_parse 'outside' false false false
|
|
||||||
cd repo.git || exit 1
|
|
||||||
test_rev_parse 'in repo.git' false true false
|
|
||||||
cd objects || exit 1
|
|
||||||
test_rev_parse 'in repo.git/objects' false true false
|
|
||||||
cd ../work2 || exit 1
|
|
||||||
test_rev_parse 'in repo.git/work2' false true false
|
|
||||||
cd ../work || exit 1
|
|
||||||
test_rev_parse 'in repo.git/work' false true true ''
|
|
||||||
cd sub/dir || exit 1
|
|
||||||
test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/
|
|
||||||
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' '
|
test_expect_success 'setup: helper for testing rev-parse' '
|
||||||
(cd repo.git/work/sub/dir &&
|
test_rev_parse() {
|
||||||
: > tracked &&
|
echo $1 >expected.bare &&
|
||||||
git --git-dir=../../.. add tracked &&
|
echo $2 >expected.inside-git &&
|
||||||
cd ../../.. &&
|
echo $3 >expected.inside-worktree &&
|
||||||
test sub/dir/tracked = "$(git ls-files)")
|
if test $# -ge 4
|
||||||
|
then
|
||||||
|
echo $4 >expected.prefix
|
||||||
|
fi &&
|
||||||
|
|
||||||
|
git rev-parse --is-bare-repository >actual.bare &&
|
||||||
|
git rev-parse --is-inside-git-dir >actual.inside-git &&
|
||||||
|
git rev-parse --is-inside-work-tree >actual.inside-worktree &&
|
||||||
|
if test $# -ge 4
|
||||||
|
then
|
||||||
|
git rev-parse --show-prefix >actual.prefix
|
||||||
|
fi &&
|
||||||
|
|
||||||
|
test_cmp expected.bare actual.bare &&
|
||||||
|
test_cmp expected.inside-git actual.inside-git &&
|
||||||
|
test_cmp expected.inside-worktree actual.inside-worktree &&
|
||||||
|
if test $# -ge 4
|
||||||
|
then
|
||||||
|
# rev-parse --show-prefix should output
|
||||||
|
# a single newline when at the top of the work tree,
|
||||||
|
# but we test for that separately.
|
||||||
|
test -z "$4" && ! test -s actual.prefix ||
|
||||||
|
test_cmp expected.prefix actual.prefix
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup: core.worktree = relative path' '
|
||||||
|
unset GIT_WORK_TREE;
|
||||||
|
GIT_DIR=repo.git &&
|
||||||
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
||||||
|
export GIT_DIR GIT_CONFIG &&
|
||||||
|
git config core.worktree ../work
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'outside' '
|
||||||
|
test_rev_parse false false false
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'inside work tree' '
|
||||||
|
(
|
||||||
|
cd work &&
|
||||||
|
GIT_DIR=../repo.git &&
|
||||||
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
||||||
|
test_rev_parse false false true ""
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_failure 'empty prefix is actually written out' '
|
||||||
|
echo >expected &&
|
||||||
|
(
|
||||||
|
cd work &&
|
||||||
|
GIT_DIR=../repo.git &&
|
||||||
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
||||||
|
git rev-parse --show-prefix >../actual
|
||||||
|
) &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'subdir of work tree' '
|
||||||
|
(
|
||||||
|
cd work/sub/dir &&
|
||||||
|
GIT_DIR=../../../repo.git &&
|
||||||
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
||||||
|
test_rev_parse false false true sub/dir/
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup: core.worktree = absolute path' '
|
||||||
|
unset GIT_WORK_TREE;
|
||||||
|
GIT_DIR=$(pwd)/repo.git &&
|
||||||
|
GIT_CONFIG=$GIT_DIR/config &&
|
||||||
|
export GIT_DIR GIT_CONFIG &&
|
||||||
|
git config core.worktree "$(pwd)/work"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'outside' '
|
||||||
|
test_rev_parse false false false &&
|
||||||
|
(
|
||||||
|
cd work2 &&
|
||||||
|
test_rev_parse false false false
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'inside work tree' '
|
||||||
|
(
|
||||||
|
cd work &&
|
||||||
|
test_rev_parse false false true ""
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'subdir of work tree' '
|
||||||
|
(
|
||||||
|
cd work/sub/dir &&
|
||||||
|
test_rev_parse false false true sub/dir/
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' '
|
||||||
|
GIT_DIR=$(pwd)/repo.git &&
|
||||||
|
GIT_CONFIG=$GIT_DIR/config &&
|
||||||
|
git config core.worktree non-existent &&
|
||||||
|
GIT_WORK_TREE=work &&
|
||||||
|
export GIT_DIR GIT_CONFIG GIT_WORK_TREE
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'outside' '
|
||||||
|
test_rev_parse false false false &&
|
||||||
|
(
|
||||||
|
cd work2 &&
|
||||||
|
test_rev_parse false false false
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'inside work tree' '
|
||||||
|
(
|
||||||
|
cd work &&
|
||||||
|
GIT_WORK_TREE=. &&
|
||||||
|
test_rev_parse false false true ""
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'subdir of work tree' '
|
||||||
|
(
|
||||||
|
cd work/sub/dir &&
|
||||||
|
GIT_WORK_TREE=../.. &&
|
||||||
|
test_rev_parse false false true sub/dir/
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' '
|
||||||
|
mv work repo.git/work &&
|
||||||
|
mv work2 repo.git/work2 &&
|
||||||
|
GIT_DIR=$(pwd)/repo.git &&
|
||||||
|
GIT_CONFIG=$GIT_DIR/config &&
|
||||||
|
GIT_WORK_TREE=$(pwd)/repo.git/work &&
|
||||||
|
export GIT_DIR GIT_CONFIG GIT_WORK_TREE
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'outside' '
|
||||||
|
echo outside &&
|
||||||
|
test_rev_parse false false false
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'in repo.git' '
|
||||||
|
(
|
||||||
|
cd repo.git &&
|
||||||
|
test_rev_parse false true false
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
cd repo.git/objects &&
|
||||||
|
test_rev_parse false true false
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
cd repo.git/work2 &&
|
||||||
|
test_rev_parse false true false
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'inside work tree' '
|
||||||
|
(
|
||||||
|
cd repo.git/work &&
|
||||||
|
test_rev_parse false true true ""
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'subdir of work tree' '
|
||||||
|
(
|
||||||
|
cd repo.git/work/sub/dir &&
|
||||||
|
test_rev_parse false true true sub/dir/
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'find work tree from repo' '
|
||||||
|
echo sub/dir/untracked >expected &&
|
||||||
|
cat <<-\EOF >repo.git/work/.gitignore &&
|
||||||
|
expected.*
|
||||||
|
actual.*
|
||||||
|
.gitignore
|
||||||
|
EOF
|
||||||
|
>repo.git/work/sub/dir/untracked &&
|
||||||
|
(
|
||||||
|
cd repo.git &&
|
||||||
|
git ls-files --others --exclude-standard >../actual
|
||||||
|
) &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'find work tree from work tree' '
|
||||||
|
echo sub/dir/tracked >expected &&
|
||||||
|
>repo.git/work/sub/dir/tracked &&
|
||||||
|
(
|
||||||
|
cd repo.git/work/sub/dir &&
|
||||||
|
git --git-dir=../../.. add tracked
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
cd repo.git &&
|
||||||
|
git ls-files >../actual
|
||||||
|
) &&
|
||||||
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
|
test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
|
||||||
(cd repo.git/work/sub/dir &&
|
(
|
||||||
GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
|
cd repo.git/work/sub/dir &&
|
||||||
|
GIT_DIR=../../.. &&
|
||||||
|
GIT_WORK_TREE=../.. &&
|
||||||
|
GIT_PAGER= &&
|
||||||
|
export GIT_DIR GIT_WORK_TREE GIT_PAGER &&
|
||||||
|
|
||||||
git diff --exit-code tracked &&
|
git diff --exit-code tracked &&
|
||||||
echo changed > tracked &&
|
echo changed >tracked &&
|
||||||
! GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
|
test_must_fail git diff --exit-code tracked
|
||||||
git diff --exit-code tracked)
|
)
|
||||||
'
|
|
||||||
cat > diff-index-cached.expected <<\EOF
|
|
||||||
:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A sub/dir/tracked
|
|
||||||
EOF
|
|
||||||
cat > diff-index.expected <<\EOF
|
|
||||||
:000000 100644 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 A sub/dir/tracked
|
|
||||||
EOF
|
|
||||||
|
|
||||||
|
|
||||||
test_expect_success 'git diff-index' '
|
|
||||||
GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-index $EMPTY_TREE > result &&
|
|
||||||
test_cmp diff-index.expected result &&
|
|
||||||
GIT_DIR=repo.git git diff-index --cached $EMPTY_TREE > result &&
|
|
||||||
test_cmp diff-index-cached.expected result
|
|
||||||
'
|
|
||||||
cat >diff-files.expected <<\EOF
|
|
||||||
:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M sub/dir/tracked
|
|
||||||
EOF
|
|
||||||
|
|
||||||
test_expect_success 'git diff-files' '
|
|
||||||
GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-files > result &&
|
|
||||||
test_cmp diff-files.expected result
|
|
||||||
'
|
'
|
||||||
|
|
||||||
cat >diff-TREE.expected <<\EOF
|
test_expect_success 'diff-index respects work tree under .git dir' '
|
||||||
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
cat >diff-index-cached.expected <<-EOF &&
|
||||||
new file mode 100644
|
:000000 100644 $ZEROES $EMPTY_BLOB A sub/dir/tracked
|
||||||
index 0000000..5ea2ed4
|
EOF
|
||||||
--- /dev/null
|
cat >diff-index.expected <<-EOF &&
|
||||||
+++ b/sub/dir/tracked
|
:000000 100644 $ZEROES $ZEROES A sub/dir/tracked
|
||||||
@@ -0,0 +1 @@
|
EOF
|
||||||
+changed
|
|
||||||
EOF
|
|
||||||
cat >diff-TREE-cached.expected <<\EOF
|
|
||||||
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..e69de29
|
|
||||||
EOF
|
|
||||||
cat >diff-FILES.expected <<\EOF
|
|
||||||
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
|
||||||
index e69de29..5ea2ed4 100644
|
|
||||||
--- a/sub/dir/tracked
|
|
||||||
+++ b/sub/dir/tracked
|
|
||||||
@@ -0,0 +1 @@
|
|
||||||
+changed
|
|
||||||
EOF
|
|
||||||
|
|
||||||
test_expect_success 'git diff' '
|
(
|
||||||
GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff $EMPTY_TREE > result &&
|
GIT_DIR=repo.git &&
|
||||||
test_cmp diff-TREE.expected result &&
|
GIT_WORK_TREE=repo.git/work &&
|
||||||
GIT_DIR=repo.git git diff --cached $EMPTY_TREE > result &&
|
export GIT_DIR GIT_WORK_TREE &&
|
||||||
test_cmp diff-TREE-cached.expected result &&
|
git diff-index $EMPTY_TREE >diff-index.actual &&
|
||||||
GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff > result &&
|
git diff-index --cached $EMPTY_TREE >diff-index-cached.actual
|
||||||
test_cmp diff-FILES.expected result
|
) &&
|
||||||
|
test_cmp diff-index.expected diff-index.actual &&
|
||||||
|
test_cmp diff-index-cached.expected diff-index-cached.actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'diff-files respects work tree under .git dir' '
|
||||||
|
cat >diff-files.expected <<-EOF &&
|
||||||
|
:100644 100644 $EMPTY_BLOB $ZEROES M sub/dir/tracked
|
||||||
|
EOF
|
||||||
|
|
||||||
|
(
|
||||||
|
GIT_DIR=repo.git &&
|
||||||
|
GIT_WORK_TREE=repo.git/work &&
|
||||||
|
export GIT_DIR GIT_WORK_TREE &&
|
||||||
|
git diff-files >diff-files.actual
|
||||||
|
) &&
|
||||||
|
test_cmp diff-files.expected diff-files.actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git diff respects work tree under .git dir' '
|
||||||
|
cat >diff-TREE.expected <<-EOF &&
|
||||||
|
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..$CHANGED_BLOB7
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sub/dir/tracked
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+changed
|
||||||
|
EOF
|
||||||
|
cat >diff-TREE-cached.expected <<-EOF &&
|
||||||
|
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..$EMPTY_BLOB7
|
||||||
|
EOF
|
||||||
|
cat >diff-FILES.expected <<-EOF &&
|
||||||
|
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
||||||
|
index $EMPTY_BLOB7..$CHANGED_BLOB7 100644
|
||||||
|
--- a/sub/dir/tracked
|
||||||
|
+++ b/sub/dir/tracked
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+changed
|
||||||
|
EOF
|
||||||
|
|
||||||
|
(
|
||||||
|
GIT_DIR=repo.git &&
|
||||||
|
GIT_WORK_TREE=repo.git/work &&
|
||||||
|
export GIT_DIR GIT_WORK_TREE &&
|
||||||
|
git diff $EMPTY_TREE >diff-TREE.actual &&
|
||||||
|
git diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&
|
||||||
|
git diff >diff-FILES.actual
|
||||||
|
) &&
|
||||||
|
test_cmp diff-TREE.expected diff-TREE.actual &&
|
||||||
|
test_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&
|
||||||
|
test_cmp diff-FILES.expected diff-FILES.actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'git grep' '
|
test_expect_success 'git grep' '
|
||||||
(cd repo.git/work/sub &&
|
echo dir/tracked >expected.grep &&
|
||||||
GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked)
|
(
|
||||||
|
cd repo.git/work/sub &&
|
||||||
|
GIT_DIR=../.. &&
|
||||||
|
GIT_WORK_TREE=.. &&
|
||||||
|
export GIT_DIR GIT_WORK_TREE &&
|
||||||
|
git grep -l changed >../../../actual.grep
|
||||||
|
) &&
|
||||||
|
test_cmp expected.grep actual.grep
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'git commit' '
|
test_expect_success 'git commit' '
|
||||||
|
@ -191,14 +328,14 @@ test_expect_success 'git commit' '
|
||||||
|
|
||||||
test_expect_success 'absolute pathspec should fail gracefully' '
|
test_expect_success 'absolute pathspec should fail gracefully' '
|
||||||
(
|
(
|
||||||
cd repo.git || exit 1
|
cd repo.git &&
|
||||||
git config --unset core.worktree
|
test_might_fail git config --unset core.worktree &&
|
||||||
test_must_fail git log HEAD -- /home
|
test_must_fail git log HEAD -- /home
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
|
test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
|
||||||
: > dummy_file
|
>dummy_file
|
||||||
echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
|
echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
|
||||||
git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
|
git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
|
||||||
'
|
'
|
||||||
|
|
142
t/t4111-apply-subdir.sh
Executable file
142
t/t4111-apply-subdir.sh
Executable file
|
@ -0,0 +1,142 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='patching from inconvenient places'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_expect_success 'setup' '
|
||||||
|
cat >patch <<-\EOF &&
|
||||||
|
diff file.orig file
|
||||||
|
--- a/file.orig
|
||||||
|
+++ b/file
|
||||||
|
@@ -1 +1,2 @@
|
||||||
|
1
|
||||||
|
+2
|
||||||
|
EOF
|
||||||
|
patch="$(pwd)/patch" &&
|
||||||
|
|
||||||
|
echo 1 >preimage &&
|
||||||
|
printf "%s\n" 1 2 >postimage &&
|
||||||
|
echo 3 >other &&
|
||||||
|
|
||||||
|
test_tick &&
|
||||||
|
git commit --allow-empty -m basis
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup: subdir' '
|
||||||
|
reset_subdir() {
|
||||||
|
git reset &&
|
||||||
|
mkdir -p sub/dir/b &&
|
||||||
|
mkdir -p objects &&
|
||||||
|
cp "$1" file &&
|
||||||
|
cp "$1" objects/file &&
|
||||||
|
cp "$1" sub/dir/file &&
|
||||||
|
cp "$1" sub/dir/b/file &&
|
||||||
|
git add file sub/dir/file sub/dir/b/file objects/file &&
|
||||||
|
cp "$2" file &&
|
||||||
|
cp "$2" sub/dir/file &&
|
||||||
|
cp "$2" sub/dir/b/file &&
|
||||||
|
cp "$2" objects/file &&
|
||||||
|
test_might_fail git update-index --refresh -q
|
||||||
|
}
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'apply from subdir of toplevel' '
|
||||||
|
cp postimage expected &&
|
||||||
|
reset_subdir other preimage &&
|
||||||
|
(
|
||||||
|
cd sub/dir &&
|
||||||
|
git apply "$patch"
|
||||||
|
) &&
|
||||||
|
test_cmp expected sub/dir/file
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'apply --cached from subdir of toplevel' '
|
||||||
|
cp postimage expected &&
|
||||||
|
cp other expected.working &&
|
||||||
|
reset_subdir preimage other &&
|
||||||
|
(
|
||||||
|
cd sub/dir &&
|
||||||
|
git apply --cached "$patch"
|
||||||
|
) &&
|
||||||
|
git show :sub/dir/file >actual &&
|
||||||
|
test_cmp expected actual &&
|
||||||
|
test_cmp expected.working sub/dir/file
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'apply --index from subdir of toplevel' '
|
||||||
|
cp postimage expected &&
|
||||||
|
reset_subdir preimage other &&
|
||||||
|
(
|
||||||
|
cd sub/dir &&
|
||||||
|
test_must_fail git apply --index "$patch"
|
||||||
|
) &&
|
||||||
|
reset_subdir other preimage &&
|
||||||
|
(
|
||||||
|
cd sub/dir &&
|
||||||
|
test_must_fail git apply --index "$patch"
|
||||||
|
) &&
|
||||||
|
reset_subdir preimage preimage &&
|
||||||
|
(
|
||||||
|
cd sub/dir &&
|
||||||
|
git apply --index "$patch"
|
||||||
|
) &&
|
||||||
|
git show :sub/dir/file >actual &&
|
||||||
|
test_cmp expected actual &&
|
||||||
|
test_cmp expected sub/dir/file
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'apply from .git dir' '
|
||||||
|
cp postimage expected &&
|
||||||
|
cp preimage .git/file &&
|
||||||
|
cp preimage .git/objects/file
|
||||||
|
(
|
||||||
|
cd .git &&
|
||||||
|
git apply "$patch"
|
||||||
|
) &&
|
||||||
|
test_cmp expected .git/file
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'apply from subdir of .git dir' '
|
||||||
|
cp postimage expected &&
|
||||||
|
cp preimage .git/file &&
|
||||||
|
cp preimage .git/objects/file
|
||||||
|
(
|
||||||
|
cd .git/objects &&
|
||||||
|
git apply "$patch"
|
||||||
|
) &&
|
||||||
|
test_cmp expected .git/objects/file
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'apply --cached from .git dir' '
|
||||||
|
cp postimage expected &&
|
||||||
|
cp other expected.working &&
|
||||||
|
cp other .git/file &&
|
||||||
|
reset_subdir preimage other &&
|
||||||
|
(
|
||||||
|
cd .git &&
|
||||||
|
git apply --cached "$patch"
|
||||||
|
) &&
|
||||||
|
git show :file >actual &&
|
||||||
|
test_cmp expected actual &&
|
||||||
|
test_cmp expected.working file &&
|
||||||
|
test_cmp expected.working .git/file
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'apply --cached from subdir of .git dir' '
|
||||||
|
cp postimage expected &&
|
||||||
|
cp preimage expected.subdir &&
|
||||||
|
cp other .git/file &&
|
||||||
|
cp other .git/objects/file &&
|
||||||
|
reset_subdir preimage other &&
|
||||||
|
(
|
||||||
|
cd .git/objects &&
|
||||||
|
git apply --cached "$patch"
|
||||||
|
) &&
|
||||||
|
git show :file >actual &&
|
||||||
|
git show :objects/file >actual.subdir &&
|
||||||
|
test_cmp expected actual &&
|
||||||
|
test_cmp expected.subdir actual.subdir
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in a new issue