Skip to content

Commit a133c40

Browse files
pcloudsgitster
authored andcommitted
commit.cocci: refactor code, avoid double rewrite
"maybe" pointer in 'struct commit' is tricky because it can be lazily initialized to take advantage of commit-graph if available. This makes it not safe to access directly. This leads to a rule in commit.cocci to rewrite 'x->maybe_tree' to 'get_commit_tree(x)'. But that rule alone could lead to incorrectly rewrite assignments, e.g. from x->maybe_tree = yes to get_commit_tree(x) = yes Because of this we have a second rule to revert this effect. Szeder found out that we could do better by performing the assignment rewrite rule first, then the remaining is read-only access and handled by the current first rule. For this to work, we need to transform "x->maybe_tree = y" to something that does NOT contain "x->maybe_tree" to avoid the original first rule. This is where set_commit_tree() comes in. Helped-by: SZEDER Gábor <[email protected]> Helped-by: Johannes Schindelin <[email protected]> Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7fdff47 commit a133c40

File tree

4 files changed

+33
-12
lines changed

4 files changed

+33
-12
lines changed

commit-graph.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,11 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g,
343343
item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
344344
}
345345

346+
static inline void set_commit_tree(struct commit *c, struct tree *t)
347+
{
348+
c->maybe_tree = t;
349+
}
350+
346351
static int fill_commit_in_graph(struct repository *r,
347352
struct commit *item,
348353
struct commit_graph *g, uint32_t pos)
@@ -356,7 +361,7 @@ static int fill_commit_in_graph(struct repository *r,
356361
item->object.parsed = 1;
357362
item->graph_pos = pos;
358363

359-
item->maybe_tree = NULL;
364+
set_commit_tree(item, NULL);
360365

361366
date_high = get_be32(commit_data + g->hash_len + 8) & 0x3;
362367
date_low = get_be32(commit_data + g->hash_len + 12);
@@ -442,7 +447,7 @@ static struct tree *load_tree_for_commit(struct repository *r,
442447
GRAPH_DATA_WIDTH * (c->graph_pos);
443448

444449
hashcpy(oid.hash, commit_data);
445-
c->maybe_tree = lookup_tree(r, &oid);
450+
set_commit_tree(c, lookup_tree(r, &oid));
446451

447452
return c->maybe_tree;
448453
}

commit.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@ void free_commit_buffer(struct parsed_object_pool *pool, struct commit *commit)
340340
}
341341
}
342342

343+
static inline void set_commit_tree(struct commit *c, struct tree *t)
344+
{
345+
c->maybe_tree = t;
346+
}
347+
343348
struct tree *get_commit_tree(const struct commit *commit)
344349
{
345350
if (commit->maybe_tree || !commit->object.parsed)
@@ -358,7 +363,7 @@ struct object_id *get_commit_tree_oid(const struct commit *commit)
358363

359364
void release_commit_memory(struct parsed_object_pool *pool, struct commit *c)
360365
{
361-
c->maybe_tree = NULL;
366+
set_commit_tree(c, NULL);
362367
c->index = 0;
363368
free_commit_buffer(pool, c);
364369
free_commit_list(c->parents);
@@ -406,7 +411,7 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
406411
if (get_oid_hex(bufptr + 5, &parent) < 0)
407412
return error("bad tree pointer in commit %s",
408413
oid_to_hex(&item->object.oid));
409-
item->maybe_tree = lookup_tree(r, &parent);
414+
set_commit_tree(item, lookup_tree(r, &parent));
410415
bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */
411416
pptr = &item->parents;
412417

contrib/coccinelle/commit.cocci

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,25 @@ expression c;
1010
- c->maybe_tree->object.oid.hash
1111
+ get_commit_tree_oid(c)->hash
1212

13-
// These excluded functions must access c->maybe_tree direcly.
1413
@@
15-
identifier f !~ "^(get_commit_tree|get_commit_tree_in_graph_one|load_tree_for_commit)$";
14+
identifier f !~ "^set_commit_tree$";
1615
expression c;
16+
expression s;
1717
@@
1818
f(...) {<...
19-
- c->maybe_tree
20-
+ get_commit_tree(c)
19+
- c->maybe_tree = s
20+
+ set_commit_tree(c, s)
2121
...>}
2222

23+
// These excluded functions must access c->maybe_tree direcly.
24+
// Note that if c->maybe_tree is written somewhere outside of these
25+
// functions, then the recommended transformation will be bogus with
26+
// get_commit_tree() on the LHS.
2327
@@
28+
identifier f !~ "^(get_commit_tree|get_commit_tree_in_graph_one|load_tree_for_commit|set_commit_tree)$";
2429
expression c;
25-
expression s;
2630
@@
27-
- get_commit_tree(c) = s
28-
+ c->maybe_tree = s
31+
f(...) {<...
32+
- c->maybe_tree
33+
+ get_commit_tree(c)
34+
...>}

merge-recursive.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,19 @@ static struct tree *shift_tree_object(struct repository *repo,
163163
return lookup_tree(repo, &shifted);
164164
}
165165

166+
static inline void set_commit_tree(struct commit *c, struct tree *t)
167+
{
168+
c->maybe_tree = t;
169+
}
170+
166171
static struct commit *make_virtual_commit(struct repository *repo,
167172
struct tree *tree,
168173
const char *comment)
169174
{
170175
struct commit *commit = alloc_commit_node(repo);
171176

172177
set_merge_remote_desc(commit, comment, (struct object *)commit);
173-
commit->maybe_tree = tree;
178+
set_commit_tree(commit, tree);
174179
commit->object.parsed = 1;
175180
return commit;
176181
}

0 commit comments

Comments
 (0)