sha1_file: always allow relative paths to alternates

We recursively expand alternates repositories, so that if A
borrows from B which borrows from C, A can see all objects.

For the root object database, we allow relative paths, so A
can point to B as "../B/objects". However, we currently do
not allow relative paths when recursing, so B must use an
absolute path to reach C.

That is an ancient protection from c2f493a (Transitively
read alternatives, 2006-05-07) that tries to avoid adding
the same alternate through two different paths. Since
5bdf0a8 (sha1_file: normalize alt_odb path before comparing
and storing, 2011-09-07), we use a normalized absolute path
for each alt_odb entry.

This means that in most cases the protection is no longer
necessary; we will detect the duplicate no matter how we got
there (but see below).  And it's a good idea to get rid of
it, as it creates an unnecessary complication when setting
up recursive alternates (B has to know that A is going to
borrow from it and make sure to use an absolute path).

Note that our normalization doesn't actually look at the
filesystem, so it can still be fooled by crossing symbolic
links. But that's also true of absolute paths, so it's not a
good reason to disallow only relative paths (it's
potentially a reason to switch to real_path(), but that's a
separate and non-trivial change).

We adjust the test script here to demonstrate that this now
works, and add new tests to show that the normalization does
indeed suppress duplicates.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2016-10-03 16:36:22 -04:00 committed by Junio C Hamano
parent 5fe849d651
commit 087b6d5840
2 changed files with 23 additions and 8 deletions

View File

@ -354,12 +354,7 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
const char *entry = entries.items[i].string;
if (entry[0] == '\0' || entry[0] == '#')
continue;
if (!is_absolute_path(entry) && depth) {
error("%s: ignoring relative alternate object store %s",
relative_base, entry);
} else {
link_alt_odb_entry(entry, relative_base, depth, objdirbuf.buf);
}
link_alt_odb_entry(entry, relative_base, depth, objdirbuf.buf);
}
string_list_clear(&entries, 0);
free(alt_copy);

View File

@ -95,8 +95,28 @@ test_expect_success 'that relative alternate is possible for current dir' '
git fsck
'
test_expect_success 'that relative alternate is only possible for current dir' '
test_must_fail git -C D fsck
test_expect_success 'that relative alternate is recursive' '
git -C D fsck
'
# we can reach "A" from our new repo both directly, and via "C".
# The deep/subdir is there to make sure we are not doing a stupid
# pure-text comparison of the alternate names.
test_expect_success 'relative duplicates are eliminated' '
mkdir -p deep/subdir &&
git init --bare deep/subdir/duplicate.git &&
cat >deep/subdir/duplicate.git/objects/info/alternates <<-\EOF &&
../../../../C/.git/objects
../../../../A/.git/objects
EOF
cat >expect <<-EOF &&
alternate: $(pwd)/C/.git/objects
alternate: $(pwd)/B/.git/objects
alternate: $(pwd)/A/.git/objects
EOF
git -C deep/subdir/duplicate.git count-objects -v >actual &&
grep ^alternate: actual >actual.alternates &&
test_cmp expect actual.alternates
'
test_done