Skip to content

Commit 10ee2e7

Browse files
committed
fast-import: allow 'from' to reference new commits and tags by oid
During a 'git fast-import' session, newly created objects are written to an in-progress packfile and recorded in fast-import's internal object table. Until a 'checkpoint' command or the end of the session finalizes and indexes that packfile, these objects are not visible to the repository's object database via odb_read_object_peeled(). Commands such as 'ls' (via parse_treeish_dataref() and dereference()) and 'cat-blob' already account for this when given a hex object name: they look up the object in fast-import's internal object table with find_object() first and read it from the in-progress packfile with gfi_unpack_entry() when its '.pack_id' is not MAX_PACK_ID. By contrast, when 'from <committish>' (in a 'commit' or 'reset' command) is given a hex object name instead of a mark or branch name, parse_objectish() parses the hex string into 'b->oid' and calls parse_from_existing(), which unconditionally looks up the object via odb_read_object_peeled(). If the object is a commit or tag created in the current pack cycle, odb_read_object_peeled() returns NULL and fast-import dies with "fatal: not a valid commit: <oid>". Teach parse_from_existing() to look up 'b->oid' with find_object() first, peel any tag objects in the object table using dereference(), and unpack the target commit with gfi_unpack_entry() if it resides in the in-progress packfile, before falling back to odb_read_object_peeled() for objects in the repository's object database.
1 parent 6de20f6 commit 10ee2e7

2 files changed

Lines changed: 58 additions & 4 deletions

File tree

‎builtin/fast-import.c‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ static void fast_import_state_init(struct fast_import_state *state,
292292
state->option = option;
293293
}
294294

295+
static struct object_entry *dereference(struct object_entry *oe,
296+
struct object_id *oid);
297+
295298
static void parse_argv(struct fast_import_state *state);
296299
static void parse_get_mark(struct fast_import_state *state, const char *p);
297300
static void parse_cat_blob(struct fast_import_state *state, const char *p);
@@ -2658,12 +2661,20 @@ static void parse_from_existing(struct branch *b)
26582661
oidclr(&b->branch_tree.versions[1].oid, the_repository->hash_algo);
26592662
} else {
26602663
unsigned long size;
2661-
size_t size_st = 0;
26622664
char *buf;
2665+
struct object_entry *e = find_object(&b->oid);
26632666

2664-
buf = odb_read_object_peeled(the_repository->objects, &b->oid,
2665-
OBJ_COMMIT, &size_st, &b->oid);
2666-
size = cast_size_t_to_ulong(size_st);
2667+
while (e && e->type == OBJ_TAG)
2668+
e = dereference(e, &b->oid);
2669+
2670+
if (e && e->type == OBJ_COMMIT && e->pack_id != MAX_PACK_ID) {
2671+
buf = gfi_unpack_entry(e, &size);
2672+
} else {
2673+
size_t size_st = 0;
2674+
buf = odb_read_object_peeled(the_repository->objects, &b->oid,
2675+
OBJ_COMMIT, &size_st, &b->oid);
2676+
size = cast_size_t_to_ulong(size_st);
2677+
}
26672678
parse_from_commit(b, buf, size);
26682679
free(buf);
26692680
}

‎t/t9300-fast-import.sh‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3938,4 +3938,47 @@ test_expect_success 'Y: rewrite submodules' '
39383938
)
39393939
'
39403940

3941+
test_expect_success 'Y: reference pending tag or commit' '
3942+
test_oid_cache <<-EOF &&
3943+
pending_commit sha1:85b46dd918355ff17b4109ec738723d42f235a04
3944+
pending_commit sha256:17e650f097a4db6fe069c96935360d3ccc9b35c4018728c5f311a4217c2ced3d
3945+
pending_tag sha1:ec6c4db71feb5f66615214dad2324ce030e777a7
3946+
pending_tag sha256:85edc5eac315bc680677b2fc71622bd77476f057eb8dc8ed6a497803a24f1f46
3947+
EOF
3948+
3949+
git init reference-pending &&
3950+
(
3951+
cd reference-pending &&
3952+
git fast-import <<-EOF
3953+
commit refs/heads/main
3954+
committer A U Thor <author@example.com> 1712563200 +0000
3955+
data 14
3956+
commit message
3957+
M 644 inline test file
3958+
data 14
3959+
dummy content
3960+
3961+
tag newtag
3962+
from $(test_oid pending_commit)
3963+
tagger A U Thor <author@example.com> 1712563300 +0000
3964+
data 11
3965+
tag message
3966+
# no emty line after tag data!
3967+
reset refs/heads/other
3968+
from $(test_oid pending_tag)
3969+
3970+
commit refs/heads/further
3971+
committer A U Thor <author@example.com> 1712563400 +0000
3972+
data 21
3973+
what about 2nd commit
3974+
from $(test_oid pending_commit)
3975+
M 644 inline other test file
3976+
data 19
3977+
more dummy content
3978+
3979+
done
3980+
EOF
3981+
)
3982+
'
3983+
39413984
test_done

0 commit comments

Comments
 (0)