Skip to content

Commit ad6abc1

Browse files
committed
Merge branch 'ps/receive-pack-shallow-optim' into next
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()`
2 parents bfae23a + bb5da75 commit ad6abc1

5 files changed

Lines changed: 63 additions & 13 deletions

File tree

commit.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,35 @@ const char *commit_type = "commit";
4242
struct commit *lookup_commit_reference_gently(struct repository *r,
4343
const struct object_id *oid, int quiet)
4444
{
45-
struct object *obj = deref_tag(r,
46-
parse_object(r, oid),
47-
NULL, 0);
45+
const struct object_id *maybe_peeled;
46+
struct object_id peeled_oid;
47+
struct commit *commit;
48+
enum object_type type;
4849

49-
if (!obj)
50+
switch (peel_object_ext(r, oid, &peeled_oid, 0, &type)) {
51+
case PEEL_NON_TAG:
52+
maybe_peeled = oid;
53+
break;
54+
case PEEL_PEELED:
55+
maybe_peeled = &peeled_oid;
56+
break;
57+
default:
5058
return NULL;
51-
return object_as_type(obj, OBJ_COMMIT, quiet);
59+
}
60+
61+
if (type != OBJ_COMMIT) {
62+
if (!quiet)
63+
error(_("object %s is a %s, not a %s"),
64+
oid_to_hex(oid), type_name(type),
65+
type_name(OBJ_COMMIT));
66+
return NULL;
67+
}
68+
69+
commit = lookup_commit(r, maybe_peeled);
70+
if (!commit || repo_parse_commit_gently(r, commit, quiet) < 0)
71+
return NULL;
72+
73+
return commit;
5274
}
5375

5476
struct commit *lookup_commit_reference(struct repository *r, const struct object_id *oid)

commit.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,26 @@ static inline int repo_parse_commit(struct repository *r, struct commit *item)
103103
return repo_parse_commit_gently(r, item, 0);
104104
}
105105

106+
void unparse_commit(struct repository *r, const struct object_id *oid);
107+
106108
static inline int repo_parse_commit_no_graph(struct repository *r,
107109
struct commit *commit)
108110
{
111+
/*
112+
* When the commit has been parsed but its tree wasn't populated then
113+
* this is an indicator that it has been parsed via the commit-graph.
114+
* We cannot read the tree via the commit-graph, as we're explicitly
115+
* told not to use it. We thus have to first un-parse the object so
116+
* that we can re-parse it without the graph.
117+
*/
118+
if (commit->object.parsed && !commit->maybe_tree)
119+
unparse_commit(r, &commit->object.oid);
120+
109121
return repo_parse_commit_internal(r, commit, 0, 0);
110122
}
111123

112124
void parse_commit_or_die(struct commit *item);
113125

114-
void unparse_commit(struct repository *r, const struct object_id *oid);
115-
116126
struct buffer_slab;
117127
struct buffer_slab *allocate_commit_buffer_slab(void);
118128
void free_commit_buffer_slab(struct buffer_slab *bs);

contrib/coccinelle/commit.cocci

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ expression s;
2626
// repo_get_commit_tree() on the LHS.
2727
@@
2828
identifier f != { repo_get_commit_tree, get_commit_tree_in_graph_one,
29-
load_tree_for_commit, set_commit_tree };
29+
load_tree_for_commit, set_commit_tree, repo_parse_commit_no_graph };
3030
expression c;
3131
@@
3232
f(...) {<...

object.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,11 @@ struct object *lookup_object_by_type(struct repository *r,
207207
}
208208
}
209209

210-
enum peel_status peel_object(struct repository *r,
211-
const struct object_id *name,
212-
struct object_id *oid,
213-
unsigned flags)
210+
enum peel_status peel_object_ext(struct repository *r,
211+
const struct object_id *name,
212+
struct object_id *oid,
213+
unsigned flags,
214+
enum object_type *typep)
214215
{
215216
struct object *o = lookup_unknown_object(r, name);
216217

@@ -220,8 +221,10 @@ enum peel_status peel_object(struct repository *r,
220221
return PEEL_INVALID;
221222
}
222223

223-
if (o->type != OBJ_TAG)
224+
if (o->type != OBJ_TAG) {
225+
*typep = o->type;
224226
return PEEL_NON_TAG;
227+
}
225228

226229
while (o && o->type == OBJ_TAG) {
227230
o = parse_object(r, &o->oid);
@@ -241,9 +244,19 @@ enum peel_status peel_object(struct repository *r,
241244
return PEEL_INVALID;
242245

243246
oidcpy(oid, &o->oid);
247+
*typep = o->type;
244248
return PEEL_PEELED;
245249
}
246250

251+
enum peel_status peel_object(struct repository *r,
252+
const struct object_id *name,
253+
struct object_id *oid,
254+
unsigned flags)
255+
{
256+
enum object_type dummy;
257+
return peel_object_ext(r, name, oid, flags, &dummy);
258+
}
259+
247260
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)
248261
{
249262
struct object *obj;

object.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ enum peel_status peel_object(struct repository *r,
309309
const struct object_id *name,
310310
struct object_id *oid,
311311
unsigned flags);
312+
enum peel_status peel_object_ext(struct repository *r,
313+
const struct object_id *name,
314+
struct object_id *oid,
315+
unsigned flags,
316+
enum object_type *typep);
312317

313318
struct object_list *object_list_insert(struct object *item,
314319
struct object_list **list_p);

0 commit comments

Comments
 (0)