aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2026-03-02 17:06:53 -0800
committerJunio C Hamano <gitster@pobox.com>2026-03-02 17:06:53 -0800
commit13763ecf7d92be72beff75c59163c5448d9e085e (patch)
tree936c5d97e77cefb1f0da9b2aae1054b1433bc690
parent34113149cfde760b6b791939c6d8d87d27ca2767 (diff)
parentbb5da75d6116c35924a04a418ef4c3182663d0a2 (diff)
downloadgit-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.c32
-rw-r--r--commit.h14
-rw-r--r--contrib/coccinelle/commit.cocci2
-rw-r--r--object.c23
-rw-r--r--object.h5
5 files changed, 63 insertions, 13 deletions
diff --git a/commit.c b/commit.c
index d16ae73345..0ffdd6679e 100644
--- a/commit.c
+++ b/commit.c
@@ -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)
diff --git a/commit.h b/commit.h
index 1635de418b..f2f39e1a89 100644
--- a/commit.h
+++ b/commit.h
@@ -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(...) {<...
diff --git a/object.c b/object.c
index 4669b8d65e..99b6df3780 100644
--- a/object.c
+++ b/object.c
@@ -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;
diff --git a/object.h b/object.h
index dfe7a1f0ea..d814647ebe 100644
--- a/object.h
+++ b/object.h
@@ -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);