Skip to content

Commit ac8bbc1

Browse files
committed
Merge branch 'sg/commit-graph-cleanups' into pu
Code cleanup. * sg/commit-graph-cleanups: commit-graph: simplify write_commit_graph_file() #2 commit-graph: simplify write_commit_graph_file() #1 commit-graph: simplify parse_commit_graph() #2 commit-graph: simplify parse_commit_graph() #1 commit-graph: clean up #includes diff.h: drop diff_tree_oid() & friends' return value commit-slab: add a function to deep free entries on the slab commit-graph-format.txt: all multi-byte numbers are in network byte order commit-graph: fix parsing the Chunk Lookup table tree-walk.c: don't match submodule entries for 'submod/anything'
2 parents 8f3417b + 7fbfe07 commit ac8bbc1

13 files changed

+117
-108
lines changed

Documentation/technical/commit-graph-format.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ the body into "chunks" and provide a binary lookup table at the beginning
3232
of the body. The header includes certain values, such as number of chunks
3333
and hash type.
3434

35-
All 4-byte numbers are in network order.
35+
All multi-byte numbers are in network byte order.
3636

3737
HEADER:
3838

commit-graph.c

Lines changed: 48 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
#include "cache.h"
2-
#include "config.h"
3-
#include "dir.h"
41
#include "git-compat-util.h"
2+
#include "config.h"
53
#include "lockfile.h"
64
#include "pack.h"
75
#include "packfile.h"
@@ -230,8 +228,7 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
230228
const unsigned char *data, *chunk_lookup;
231229
uint32_t i;
232230
struct commit_graph *graph;
233-
uint64_t last_chunk_offset;
234-
uint32_t last_chunk_id;
231+
uint64_t next_chunk_offset;
235232
uint32_t graph_signature;
236233
unsigned char graph_version, hash_version;
237234

@@ -271,24 +268,26 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
271268
graph->data = graph_map;
272269
graph->data_len = graph_size;
273270

274-
last_chunk_id = 0;
275-
last_chunk_offset = 8;
271+
if (graph_size < GRAPH_HEADER_SIZE +
272+
(graph->num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH +
273+
GRAPH_FANOUT_SIZE + the_hash_algo->rawsz) {
274+
error(_("commit-graph file is too small to hold %u chunks"),
275+
graph->num_chunks);
276+
free(graph);
277+
return NULL;
278+
}
279+
276280
chunk_lookup = data + 8;
281+
next_chunk_offset = get_be64(chunk_lookup + 4);
277282
for (i = 0; i < graph->num_chunks; i++) {
278283
uint32_t chunk_id;
279-
uint64_t chunk_offset;
284+
uint64_t chunk_offset = next_chunk_offset;
280285
int chunk_repeated = 0;
281286

282-
if (data + graph_size - chunk_lookup <
283-
GRAPH_CHUNKLOOKUP_WIDTH) {
284-
error(_("commit-graph chunk lookup table entry missing; file may be incomplete"));
285-
goto free_and_return;
286-
}
287-
288287
chunk_id = get_be32(chunk_lookup + 0);
289-
chunk_offset = get_be64(chunk_lookup + 4);
290288

291289
chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH;
290+
next_chunk_offset = get_be64(chunk_lookup + 4);
292291

293292
if (chunk_offset > graph_size - the_hash_algo->rawsz) {
294293
error(_("commit-graph improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32),
@@ -307,8 +306,11 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
307306
case GRAPH_CHUNKID_OIDLOOKUP:
308307
if (graph->chunk_oid_lookup)
309308
chunk_repeated = 1;
310-
else
309+
else {
311310
graph->chunk_oid_lookup = data + chunk_offset;
311+
graph->num_commits = (next_chunk_offset - chunk_offset)
312+
/ graph->hash_len;
313+
}
312314
break;
313315

314316
case GRAPH_CHUNKID_DATA:
@@ -362,15 +364,6 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
362364
error(_("commit-graph chunk id %08x appears multiple times"), chunk_id);
363365
goto free_and_return;
364366
}
365-
366-
if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP)
367-
{
368-
graph->num_commits = (chunk_offset - last_chunk_offset)
369-
/ graph->hash_len;
370-
}
371-
372-
last_chunk_id = chunk_id;
373-
last_chunk_offset = chunk_offset;
374367
}
375368

376369
if (graph->chunk_bloom_indexes && graph->chunk_bloom_data) {
@@ -1535,17 +1528,22 @@ static int write_graph_chunk_base(struct hashfile *f,
15351528
return 0;
15361529
}
15371530

1531+
struct chunk_info {
1532+
uint32_t id;
1533+
uint64_t size;
1534+
};
1535+
15381536
static int write_commit_graph_file(struct write_commit_graph_context *ctx)
15391537
{
15401538
uint32_t i;
15411539
int fd;
15421540
struct hashfile *f;
15431541
struct lock_file lk = LOCK_INIT;
1544-
uint32_t chunk_ids[MAX_NUM_CHUNKS + 1];
1545-
uint64_t chunk_offsets[MAX_NUM_CHUNKS + 1];
1542+
struct chunk_info chunks[MAX_NUM_CHUNKS + 1];
15461543
const unsigned hashsz = the_hash_algo->rawsz;
15471544
struct strbuf progress_title = STRBUF_INIT;
15481545
int num_chunks = 3;
1546+
uint64_t chunk_offset;
15491547
struct object_id file_hash;
15501548
const struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
15511549

@@ -1593,51 +1591,34 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
15931591
f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
15941592
}
15951593

1596-
chunk_ids[0] = GRAPH_CHUNKID_OIDFANOUT;
1597-
chunk_ids[1] = GRAPH_CHUNKID_OIDLOOKUP;
1598-
chunk_ids[2] = GRAPH_CHUNKID_DATA;
1594+
chunks[0].id = GRAPH_CHUNKID_OIDFANOUT;
1595+
chunks[0].size = GRAPH_FANOUT_SIZE;
1596+
chunks[1].id = GRAPH_CHUNKID_OIDLOOKUP;
1597+
chunks[1].size = hashsz * ctx->commits.nr;
1598+
chunks[2].id = GRAPH_CHUNKID_DATA;
1599+
chunks[2].size = (hashsz + 16) * ctx->commits.nr;
15991600
if (ctx->num_extra_edges) {
1600-
chunk_ids[num_chunks] = GRAPH_CHUNKID_EXTRAEDGES;
1601+
chunks[num_chunks].id = GRAPH_CHUNKID_EXTRAEDGES;
1602+
chunks[num_chunks].size = 4 * ctx->num_extra_edges;
16011603
num_chunks++;
16021604
}
16031605
if (ctx->changed_paths) {
1604-
chunk_ids[num_chunks] = GRAPH_CHUNKID_BLOOMINDEXES;
1606+
chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMINDEXES;
1607+
chunks[num_chunks].size = sizeof(uint32_t) * ctx->commits.nr;
16051608
num_chunks++;
1606-
chunk_ids[num_chunks] = GRAPH_CHUNKID_BLOOMDATA;
1609+
chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMDATA;
1610+
chunks[num_chunks].size = sizeof(uint32_t) * 3
1611+
+ ctx->total_bloom_filter_data_size;
16071612
num_chunks++;
16081613
}
16091614
if (ctx->num_commit_graphs_after > 1) {
1610-
chunk_ids[num_chunks] = GRAPH_CHUNKID_BASE;
1615+
chunks[num_chunks].id = GRAPH_CHUNKID_BASE;
1616+
chunks[num_chunks].size = hashsz * (ctx->num_commit_graphs_after - 1);
16111617
num_chunks++;
16121618
}
16131619

1614-
chunk_ids[num_chunks] = 0;
1615-
1616-
chunk_offsets[0] = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
1617-
chunk_offsets[1] = chunk_offsets[0] + GRAPH_FANOUT_SIZE;
1618-
chunk_offsets[2] = chunk_offsets[1] + hashsz * ctx->commits.nr;
1619-
chunk_offsets[3] = chunk_offsets[2] + (hashsz + 16) * ctx->commits.nr;
1620-
1621-
num_chunks = 3;
1622-
if (ctx->num_extra_edges) {
1623-
chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
1624-
4 * ctx->num_extra_edges;
1625-
num_chunks++;
1626-
}
1627-
if (ctx->changed_paths) {
1628-
chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
1629-
sizeof(uint32_t) * ctx->commits.nr;
1630-
num_chunks++;
1631-
1632-
chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
1633-
sizeof(uint32_t) * 3 + ctx->total_bloom_filter_data_size;
1634-
num_chunks++;
1635-
}
1636-
if (ctx->num_commit_graphs_after > 1) {
1637-
chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
1638-
hashsz * (ctx->num_commit_graphs_after - 1);
1639-
num_chunks++;
1640-
}
1620+
chunks[num_chunks].id = 0;
1621+
chunks[num_chunks].size = 0;
16411622

16421623
hashwrite_be32(f, GRAPH_SIGNATURE);
16431624

@@ -1646,13 +1627,16 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
16461627
hashwrite_u8(f, num_chunks);
16471628
hashwrite_u8(f, ctx->num_commit_graphs_after - 1);
16481629

1630+
chunk_offset = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
16491631
for (i = 0; i <= num_chunks; i++) {
16501632
uint32_t chunk_write[3];
16511633

1652-
chunk_write[0] = htonl(chunk_ids[i]);
1653-
chunk_write[1] = htonl(chunk_offsets[i] >> 32);
1654-
chunk_write[2] = htonl(chunk_offsets[i] & 0xffffffff);
1634+
chunk_write[0] = htonl(chunks[i].id);
1635+
chunk_write[1] = htonl(chunk_offset >> 32);
1636+
chunk_write[2] = htonl(chunk_offset & 0xffffffff);
16551637
hashwrite(f, chunk_write, 12);
1638+
1639+
chunk_offset += chunks[i].size;
16561640
}
16571641

16581642
if (ctx->report_progress) {

commit-graph.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
#define COMMIT_GRAPH_H
33

44
#include "git-compat-util.h"
5-
#include "repository.h"
6-
#include "string-list.h"
7-
#include "cache.h"
85
#include "object-store.h"
96
#include "oidset.h"
107

@@ -23,6 +20,9 @@ void git_test_write_commit_graph_or_die(void);
2320

2421
struct commit;
2522
struct bloom_filter_settings;
23+
struct repository;
24+
struct raw_object_store;
25+
struct string_list;
2626

2727
char *get_commit_graph_filename(struct object_directory *odb);
2828
int open_commit_graph(const char *graph_file, int *fd, struct stat *st);

commit-slab-decl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct slabname { \
3232
void init_ ##slabname## _with_stride(struct slabname *s, unsigned stride); \
3333
void init_ ##slabname(struct slabname *s); \
3434
void clear_ ##slabname(struct slabname *s); \
35+
void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *ptr)); \
3536
elemtype *slabname## _at_peek(struct slabname *s, const struct commit *c, int add_if_missing); \
3637
elemtype *slabname## _at(struct slabname *s, const struct commit *c); \
3738
elemtype *slabname## _peek(struct slabname *s, const struct commit *c)

commit-slab-impl.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ scope void clear_ ##slabname(struct slabname *s) \
3838
FREE_AND_NULL(s->slab); \
3939
} \
4040
\
41+
scope void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *)) \
42+
{ \
43+
unsigned int i; \
44+
for (i = 0; i < s->slab_count; i++) { \
45+
unsigned int j; \
46+
if (!s->slab[i]) \
47+
continue; \
48+
for (j = 0; j < s->slab_size; j++) \
49+
free_fn(&s->slab[i][j * s->stride]); \
50+
} \
51+
clear_ ##slabname(s); \
52+
} \
53+
\
4154
scope elemtype *slabname## _at_peek(struct slabname *s, \
4255
const struct commit *c, \
4356
int add_if_missing) \

commit-slab.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@
4747
*
4848
* Call this function before the slab falls out of scope to avoid
4949
* leaking memory.
50+
*
51+
* - void deep_clear_indegree(struct indegree *, void (*free_fn)(int*))
52+
*
53+
* Empties the slab, similar to clear_indegree(), but in addition it
54+
* calls the given 'free_fn' for each slab entry to release any
55+
* additional memory that might be owned by the entry (but not the
56+
* entry itself!).
57+
* Note that 'free_fn' might be called even for entries for which no
58+
* indegree_at() call has been made; in this case 'free_fn' is invoked
59+
* with a pointer to a zero-initialized location.
5060
*/
5161

5262
#define define_commit_slab(slabname, elemtype) \

diff.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -431,11 +431,11 @@ struct combine_diff_path *diff_tree_paths(
431431
struct combine_diff_path *p, const struct object_id *oid,
432432
const struct object_id **parents_oid, int nparent,
433433
struct strbuf *base, struct diff_options *opt);
434-
int diff_tree_oid(const struct object_id *old_oid,
435-
const struct object_id *new_oid,
436-
const char *base, struct diff_options *opt);
437-
int diff_root_tree_oid(const struct object_id *new_oid, const char *base,
438-
struct diff_options *opt);
434+
void diff_tree_oid(const struct object_id *old_oid,
435+
const struct object_id *new_oid,
436+
const char *base, struct diff_options *opt);
437+
void diff_root_tree_oid(const struct object_id *new_oid, const char *base,
438+
struct diff_options *opt);
439439

440440
struct combine_diff_path {
441441
struct combine_diff_path *next;

revision.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,9 +791,7 @@ static int rev_compare_tree(struct rev_info *revs,
791791

792792
tree_difference = REV_TREE_SAME;
793793
revs->pruning.flags.has_changes = 0;
794-
if (diff_tree_oid(&t1->object.oid, &t2->object.oid, "",
795-
&revs->pruning) < 0)
796-
return REV_TREE_DIFFERENT;
794+
diff_tree_oid(&t1->object.oid, &t2->object.oid, "", &revs->pruning);
797795

798796
if (!nth_parent)
799797
if (bloom_ret == 1 && tree_difference == REV_TREE_SAME)
@@ -804,17 +802,16 @@ static int rev_compare_tree(struct rev_info *revs,
804802

805803
static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
806804
{
807-
int retval;
808805
struct tree *t1 = get_commit_tree(commit);
809806

810807
if (!t1)
811808
return 0;
812809

813810
tree_difference = REV_TREE_SAME;
814811
revs->pruning.flags.has_changes = 0;
815-
retval = diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
812+
diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
816813

817-
return retval >= 0 && (tree_difference == REV_TREE_SAME);
814+
return tree_difference == REV_TREE_SAME;
818815
}
819816

820817
struct treesame_state {

shallow.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ void rollback_shallow_file(struct repository *r, struct shallow_lock *lk)
110110
* supports a "valid" flag.
111111
*/
112112
define_commit_slab(commit_depth, int *);
113+
static void free_depth_in_slab(int **ptr)
114+
{
115+
FREE_AND_NULL(*ptr);
116+
}
113117
struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
114118
int shallow_flag, int not_shallow_flag)
115119
{
@@ -176,15 +180,7 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
176180
}
177181
}
178182
}
179-
for (i = 0; i < depths.slab_count; i++) {
180-
int j;
181-
182-
if (!depths.slab[i])
183-
continue;
184-
for (j = 0; j < depths.slab_size; j++)
185-
free(depths.slab[i][j]);
186-
}
187-
clear_commit_depth(&depths);
183+
deep_clear_commit_depth(&depths, free_depth_in_slab);
188184

189185
return result;
190186
}

t/t4010-diff-pathspec.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ test_expect_success 'setup submodules' '
125125
test_expect_success 'diff-tree ignores trailing slash on submodule path' '
126126
git diff --name-only HEAD^ HEAD submod >expect &&
127127
git diff --name-only HEAD^ HEAD submod/ >actual &&
128-
test_cmp expect actual
128+
test_cmp expect actual &&
129+
git diff --name-only HEAD^ HEAD -- submod/whatever >actual &&
130+
test_must_be_empty actual
129131
'
130132

131133
test_expect_success 'diff multiple wildcard pathspecs' '

t/t5318-commit-graph.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ test_expect_success 'detect bad hash version' '
529529
'
530530

531531
test_expect_success 'detect low chunk count' '
532-
corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\02" \
532+
corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\01" \
533533
"missing the .* chunk"
534534
'
535535

@@ -615,7 +615,8 @@ test_expect_success 'detect invalid checksum hash' '
615615

616616
test_expect_success 'detect incorrect chunk count' '
617617
corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\377" \
618-
"chunk lookup table entry missing" $GRAPH_CHUNK_LOOKUP_OFFSET
618+
"commit-graph file is too small to hold [0-9]* chunks" \
619+
$GRAPH_CHUNK_LOOKUP_OFFSET
619620
'
620621

621622
test_expect_success 'git fsck (checks commit-graph)' '

0 commit comments

Comments
 (0)