git-commit-vandalism/t/t1700-split-index.sh
Johannes Schindelin 098aa86762 rev-parse: fix several options when running in a subdirectory
In addition to making git_path() aware of certain file names that need
to be handled differently e.g. when running in worktrees, the commit
557bd833bb (git_path(): be aware of file relocation in $GIT_DIR,
2014-11-30) also snuck in a new option for `git rev-parse`:
`--git-path`.

On the face of it, there is no obvious bug in that commit's diff: it
faithfully calls git_path() on the argument and prints it out, i.e. `git
rev-parse --git-path <filename>` has the same precise behavior as
calling `git_path("<filename>")` in C.

The problem lies deeper, much deeper. In hindsight (which is always
unfair), implementing the .git/ directory discovery in
`setup_git_directory()` by changing the working directory may have
allowed us to avoid passing around a struct that contains information
about the current repository, but it bought us many, many problems.

In this case, when being called in a subdirectory, `git rev-parse`
changes the working directory to the top-level directory before calling
`git_path()`. In the new working directory, the result is correct. But
in the working directory of the calling script, it is incorrect.

Example: when calling `git rev-parse --git-path HEAD` in, say, the
Documentation/ subdirectory of Git's own source code, the string
`.git/HEAD` is printed.

Side note: that bug is hidden when running in a subdirectory of a
worktree that was added by the `git worktree` command: in that case, the
(correct) absolute path of the `HEAD` file is printed.

In the interest of time, this patch does not go the "correct" route to
introduce a struct with repository information (and removing global
state in the process), instead this patch chooses to detect when the
command was called in a subdirectory and forces the result to be an
absolute path.

While at it, we are also fixing the output of --git-common-dir and
--shared-index-path.

Lastly, please note that we reuse the same strbuf for all of the
relative_path() calls; this avoids frequent allocation (and duplicated
code), and it does not risk memory leaks, for two reasons: 1) the
cmd_rev_parse() function does not return anywhere between the use of
the new strbuf instance and its final release, and 2) git-rev-parse is
one of these "one-shot" programs in Git, i.e. it exits after running
for a very short time, meaning that all allocated memory is released
with the exit() call anyway.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-17 10:21:54 -08:00

220 lines
5.1 KiB
Bash
Executable File

#!/bin/sh
test_description='split index mode tests'
. ./test-lib.sh
# We need total control of index splitting here
sane_unset GIT_TEST_SPLIT_INDEX
test_expect_success 'enable split index' '
git update-index --split-index &&
test-dump-split-index .git/index >actual &&
indexversion=$(test-index-version <.git/index) &&
if test "$indexversion" = "4"
then
own=432ef4b63f32193984f339431fd50ca796493569
base=508851a7f0dfa8691e9f69c7f055865389012491
else
own=8299b0bcd1ac364e5f1d7768efb62fa2da79a339
base=39d890139ee5356c7ef572216cebcd27aa41f9df
fi &&
cat >expect <<EOF &&
own $own
base $base
replacements:
deletions:
EOF
test_cmp expect actual
'
test_expect_success 'add one file' '
: >one &&
git update-index --add one &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 $EMPTY_BLOB 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<EOF &&
base $base
100644 $EMPTY_BLOB 0 one
replacements:
deletions:
EOF
test_cmp expect actual
'
test_expect_success 'disable split index' '
git update-index --no-split-index &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 $EMPTY_BLOB 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
BASE=$(test-dump-split-index .git/index | grep "^own" | sed "s/own/base/") &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<EOF &&
not a split index
EOF
test_cmp expect actual
'
test_expect_success 'enable split index again, "one" now belongs to base index"' '
git update-index --split-index &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 $EMPTY_BLOB 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<EOF &&
$BASE
replacements:
deletions:
EOF
test_cmp expect actual
'
test_expect_success 'modify original file, base index untouched' '
echo modified >one &&
git update-index one &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
q_to_tab >expect <<EOF &&
$BASE
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
replacements: 0
deletions:
EOF
test_cmp expect actual
'
test_expect_success 'add another file, which stays index' '
: >two &&
git update-index --add two &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
100644 $EMPTY_BLOB 0 two
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
q_to_tab >expect <<EOF &&
$BASE
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
100644 $EMPTY_BLOB 0 two
replacements: 0
deletions:
EOF
test_cmp expect actual
'
test_expect_success 'remove file not in base index' '
git update-index --force-remove two &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
q_to_tab >expect <<EOF &&
$BASE
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
replacements: 0
deletions:
EOF
test_cmp expect actual
'
test_expect_success 'remove file in base index' '
git update-index --force-remove one &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<EOF &&
$BASE
replacements:
deletions: 0
EOF
test_cmp expect actual
'
test_expect_success 'add original file back' '
: >one &&
git update-index --add one &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 $EMPTY_BLOB 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<EOF &&
$BASE
100644 $EMPTY_BLOB 0 one
replacements:
deletions: 0
EOF
test_cmp expect actual
'
test_expect_success 'add new file' '
: >two &&
git update-index --add two &&
git ls-files --stage >actual &&
cat >expect <<EOF &&
100644 $EMPTY_BLOB 0 one
100644 $EMPTY_BLOB 0 two
EOF
test_cmp expect actual
'
test_expect_success 'unify index, two files remain' '
git update-index --no-split-index &&
git ls-files --stage >ls-files.actual &&
cat >ls-files.expect <<EOF &&
100644 $EMPTY_BLOB 0 one
100644 $EMPTY_BLOB 0 two
EOF
test_cmp ls-files.expect ls-files.actual &&
test-dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<EOF &&
not a split index
EOF
test_cmp expect actual
'
test_expect_success 'rev-parse --shared-index-path' '
test_create_repo split-index &&
(
cd split-index &&
git update-index --split-index &&
echo .git/sharedindex* >expect &&
git rev-parse --shared-index-path >actual &&
test_cmp expect actual &&
mkdir subdirectory &&
cd subdirectory &&
echo ../.git/sharedindex* >expect &&
git rev-parse --shared-index-path >actual &&
test_cmp expect actual
)
'
test_done