diff options
| author | Junio C Hamano <gitster@pobox.com> | 2026-03-02 17:06:53 -0800 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2026-03-02 17:06:53 -0800 |
| commit | 13763ecf7d92be72beff75c59163c5448d9e085e (patch) | |
| tree | 936c5d97e77cefb1f0da9b2aae1054b1433bc690 | |
| parent | 34113149cfde760b6b791939c6d8d87d27ca2767 (diff) | |
| parent | bb5da75d6116c35924a04a418ef4c3182663d0a2 (diff) | |
| download | git-13763ecf7d92be72beff75c59163c5448d9e085e.tar.xz | |
Merge branch 'ps/receive-pack-shallow-optim'
The code to accept shallow "git push" has been optimized.
* ps/receive-pack-shallow-optim:
commit: use commit graph in `lookup_commit_reference_gently()`
commit: make `repo_parse_commit_no_graph()` more robust
commit: avoid parsing non-commits in `lookup_commit_reference_gently()`
| -rw-r--r-- | commit.c | 32 | ||||
| -rw-r--r-- | commit.h | 14 | ||||
| -rw-r--r-- | contrib/coccinelle/commit.cocci | 2 | ||||
| -rw-r--r-- | object.c | 23 | ||||
| -rw-r--r-- | object.h | 5 |
5 files changed, 63 insertions, 13 deletions
@@ -42,13 +42,35 @@ const char *commit_type = "commit"; struct commit *lookup_commit_reference_gently(struct repository *r, const struct object_id *oid, int quiet) { - struct object *obj = deref_tag(r, - parse_object(r, oid), - NULL, 0); + const struct object_id *maybe_peeled; + struct object_id peeled_oid; + struct commit *commit; + enum object_type type; - if (!obj) + switch (peel_object_ext(r, oid, &peeled_oid, 0, &type)) { + case PEEL_NON_TAG: + maybe_peeled = oid; + break; + case PEEL_PEELED: + maybe_peeled = &peeled_oid; + break; + default: return NULL; - return object_as_type(obj, OBJ_COMMIT, quiet); + } + + if (type != OBJ_COMMIT) { + if (!quiet) + error(_("object %s is a %s, not a %s"), + oid_to_hex(oid), type_name(type), + type_name(OBJ_COMMIT)); + return NULL; + } + + commit = lookup_commit(r, maybe_peeled); + if (!commit || repo_parse_commit_gently(r, commit, quiet) < 0) + return NULL; + + return commit; } struct commit *lookup_commit_reference(struct repository *r, const struct object_id *oid) @@ -103,16 +103,26 @@ static inline int repo_parse_commit(struct repository *r, struct commit *item) return repo_parse_commit_gently(r, item, 0); } +void unparse_commit(struct repository *r, const struct object_id *oid); + static inline int repo_parse_commit_no_graph(struct repository *r, struct commit *commit) { + /* + * When the commit has been parsed but its tree wasn't populated then + * this is an indicator that it has been parsed via the commit-graph. + * We cannot read the tree via the commit-graph, as we're explicitly + * told not to use it. We thus have to first un-parse the object so + * that we can re-parse it without the graph. + */ + if (commit->object.parsed && !commit->maybe_tree) + unparse_commit(r, &commit->object.oid); + return repo_parse_commit_internal(r, commit, 0, 0); } void parse_commit_or_die(struct commit *item); -void unparse_commit(struct repository *r, const struct object_id *oid); - struct buffer_slab; struct buffer_slab *allocate_commit_buffer_slab(void); void free_commit_buffer_slab(struct buffer_slab *bs); diff --git a/contrib/coccinelle/commit.cocci b/contrib/coccinelle/commit.cocci index c5284604c5..42725161e9 100644 --- a/contrib/coccinelle/commit.cocci +++ b/contrib/coccinelle/commit.cocci @@ -26,7 +26,7 @@ expression s; // repo_get_commit_tree() on the LHS. @@ identifier f != { repo_get_commit_tree, get_commit_tree_in_graph_one, - load_tree_for_commit, set_commit_tree }; + load_tree_for_commit, set_commit_tree, repo_parse_commit_no_graph }; expression c; @@ f(...) {<... @@ -207,10 +207,11 @@ struct object *lookup_object_by_type(struct repository *r, } } -enum peel_status peel_object(struct repository *r, - const struct object_id *name, - struct object_id *oid, - unsigned flags) +enum peel_status peel_object_ext(struct repository *r, + const struct object_id *name, + struct object_id *oid, + unsigned flags, + enum object_type *typep) { struct object *o = lookup_unknown_object(r, name); @@ -220,8 +221,10 @@ enum peel_status peel_object(struct repository *r, return PEEL_INVALID; } - if (o->type != OBJ_TAG) + if (o->type != OBJ_TAG) { + *typep = o->type; return PEEL_NON_TAG; + } while (o && o->type == OBJ_TAG) { o = parse_object(r, &o->oid); @@ -241,9 +244,19 @@ enum peel_status peel_object(struct repository *r, return PEEL_INVALID; oidcpy(oid, &o->oid); + *typep = o->type; return PEEL_PEELED; } +enum peel_status peel_object(struct repository *r, + const struct object_id *name, + struct object_id *oid, + unsigned flags) +{ + enum object_type dummy; + return peel_object_ext(r, name, oid, flags, &dummy); +} + struct object *parse_object_buffer(struct repository *r, const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p) { struct object *obj; @@ -309,6 +309,11 @@ enum peel_status peel_object(struct repository *r, const struct object_id *name, struct object_id *oid, unsigned flags); +enum peel_status peel_object_ext(struct repository *r, + const struct object_id *name, + struct object_id *oid, + unsigned flags, + enum object_type *typep); struct object_list *object_list_insert(struct object *item, struct object_list **list_p); |
