Merge branch 'gc/resolve-alternate-symlinks'

Resolve symbolic links when processing the locations of alternate
object stores, since failing to do so can lead to confusing and buggy
behavior.

* gc/resolve-alternate-symlinks:
  object-file: use real paths when adding alternates
This commit is contained in:
Junio C Hamano 2022-11-29 10:41:05 +09:00
commit f32996d99a
2 changed files with 29 additions and 13 deletions

View file

@ -508,7 +508,9 @@ static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry,
{ {
struct object_directory *ent; struct object_directory *ent;
struct strbuf pathbuf = STRBUF_INIT; struct strbuf pathbuf = STRBUF_INIT;
struct strbuf tmp = STRBUF_INIT;
khiter_t pos; khiter_t pos;
int ret = -1;
if (!is_absolute_path(entry->buf) && relative_base) { if (!is_absolute_path(entry->buf) && relative_base) {
strbuf_realpath(&pathbuf, relative_base, 1); strbuf_realpath(&pathbuf, relative_base, 1);
@ -516,12 +518,12 @@ static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry,
} }
strbuf_addbuf(&pathbuf, entry); strbuf_addbuf(&pathbuf, entry);
if (strbuf_normalize_path(&pathbuf) < 0 && relative_base) { if (!strbuf_realpath(&tmp, pathbuf.buf, 0)) {
error(_("unable to normalize alternate object path: %s"), error(_("unable to normalize alternate object path: %s"),
pathbuf.buf); pathbuf.buf);
strbuf_release(&pathbuf); goto error;
return -1;
} }
strbuf_swap(&pathbuf, &tmp);
/* /*
* The trailing slash after the directory name is given by * The trailing slash after the directory name is given by
@ -530,10 +532,8 @@ static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry,
while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/') while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
strbuf_setlen(&pathbuf, pathbuf.len - 1); strbuf_setlen(&pathbuf, pathbuf.len - 1);
if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos)) { if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos))
strbuf_release(&pathbuf); goto error;
return -1;
}
CALLOC_ARRAY(ent, 1); CALLOC_ARRAY(ent, 1);
/* pathbuf.buf is already in r->objects->odb_by_path */ /* pathbuf.buf is already in r->objects->odb_by_path */
@ -548,8 +548,11 @@ static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry,
/* recursively add alternates */ /* recursively add alternates */
read_info_alternates(r, ent->path, depth + 1); read_info_alternates(r, ent->path, depth + 1);
ret = 0;
return 0; error:
strbuf_release(&tmp);
strbuf_release(&pathbuf);
return ret;
} }
static const char *parse_alt_odb_entry(const char *string, static const char *parse_alt_odb_entry(const char *string,
@ -596,10 +599,7 @@ static void link_alt_odb_entries(struct repository *r, const char *alt,
return; return;
} }
strbuf_add_absolute_path(&objdirbuf, r->objects->odb->path); strbuf_realpath(&objdirbuf, r->objects->odb->path, 1);
if (strbuf_normalize_path(&objdirbuf) < 0)
die(_("unable to normalize object directory: %s"),
objdirbuf.buf);
while (*alt) { while (*alt) {
alt = parse_alt_odb_entry(alt, sep, &entry); alt = parse_alt_odb_entry(alt, sep, &entry);

View file

@ -90,6 +90,22 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '
test_has_duplicate_object false test_has_duplicate_object false
' '
test_expect_success SYMLINKS '--local keeps packs when alternate is objectdir ' '
test_when_finished "rm -rf repo" &&
git init repo &&
test_commit -C repo A &&
(
cd repo &&
git repack -a &&
ls .git/objects/pack/*.pack >../expect &&
ln -s objects .git/alt_objects &&
echo "$(pwd)/.git/alt_objects" >.git/objects/info/alternates &&
git repack -a -d -l &&
ls .git/objects/pack/*.pack >../actual
) &&
test_cmp expect actual
'
test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' ' test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
mkdir alt_objects/pack && mkdir alt_objects/pack &&
mv .git/objects/pack/* alt_objects/pack && mv .git/objects/pack/* alt_objects/pack &&