Skip to content

Commit 18952a1

Browse files
jltoblergitster
authored andcommitted
builtin/repo: find commit with most parents
Complex merge events may produce an octopus merge where the resulting merge commit has more than two parents. While iterating through objects in the repository for git-repo-structure, identify the commit with the most parents and display it in the output. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent e00bb8c commit 18952a1

2 files changed

Lines changed: 123 additions & 73 deletions

File tree

builtin/repo.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#define USE_THE_REPOSITORY_VARIABLE
22

33
#include "builtin.h"
4+
#include "commit.h"
45
#include "environment.h"
56
#include "hash.h"
67
#include "hex.h"
@@ -208,6 +209,8 @@ struct largest_objects {
208209
struct object_data commit_size;
209210
struct object_data tree_size;
210211
struct object_data blob_size;
212+
213+
struct object_data parent_count;
211214
};
212215

213216
struct ref_stats {
@@ -318,6 +321,27 @@ static void stats_table_count_addf(struct stats_table *table, size_t value,
318321
va_end(ap);
319322
}
320323

324+
static void stats_table_object_count_addf(struct stats_table *table,
325+
struct object_id *oid, size_t value,
326+
const char *format, ...)
327+
{
328+
struct stats_table_entry *entry;
329+
va_list ap;
330+
331+
CALLOC_ARRAY(entry, 1);
332+
humanise_count(value, &entry->value, &entry->unit);
333+
334+
/*
335+
* A NULL OID should not have a table annotation.
336+
*/
337+
if (!is_null_oid(oid))
338+
entry->oid = oid;
339+
340+
va_start(ap, format);
341+
stats_table_vaddf(table, entry, format, ap);
342+
va_end(ap);
343+
}
344+
321345
static void stats_table_size_addf(struct stats_table *table, size_t value,
322346
const char *format, ...)
323347
{
@@ -425,6 +449,10 @@ static void stats_table_setup_structure(struct stats_table *table,
425449
&objects->largest.commit_size.oid,
426450
objects->largest.commit_size.value,
427451
" * %s", _("Maximum size"));
452+
stats_table_object_count_addf(table,
453+
&objects->largest.parent_count.oid,
454+
objects->largest.parent_count.value,
455+
" * %s", _("Maximum parents"));
428456
stats_table_addf(table, " * %s", _("Trees"));
429457
stats_table_object_size_addf(table,
430458
&objects->largest.tree_size.oid,
@@ -595,6 +623,9 @@ static void structure_keyvalue_print(struct repo_structure *stats,
595623
print_object_data("objects.tags.max_size", key_delim,
596624
&stats->objects.largest.tag_size, value_delim);
597625

626+
print_object_data("objects.commits.max_parents", key_delim,
627+
&stats->objects.largest.parent_count, value_delim);
628+
598629
fflush(stdout);
599630
}
600631

@@ -682,16 +713,24 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
682713
for (size_t i = 0; i < oids->nr; i++) {
683714
struct object_info oi = OBJECT_INFO_INIT;
684715
unsigned long inflated;
716+
struct commit *commit;
717+
struct object *obj;
718+
void *content;
685719
off_t disk;
720+
int eaten;
686721

687722
oi.sizep = &inflated;
688723
oi.disk_sizep = &disk;
724+
oi.contentp = &content;
689725

690726
if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
691727
OBJECT_INFO_SKIP_FETCH_OBJECT |
692728
OBJECT_INFO_QUICK) < 0)
693729
continue;
694730

731+
obj = parse_object_buffer(the_repository, &oids->oid[i], type,
732+
inflated, content, &eaten);
733+
695734
switch (type) {
696735
case OBJ_TAG:
697736
stats->type_counts.tags++;
@@ -701,11 +740,14 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
701740
inflated);
702741
break;
703742
case OBJ_COMMIT:
743+
commit = object_as_type(obj, OBJ_COMMIT, 0);
704744
stats->type_counts.commits++;
705745
stats->inflated_sizes.commits += inflated;
706746
stats->disk_sizes.commits += disk;
707747
check_largest(&stats->largest.commit_size, &oids->oid[i],
708748
inflated);
749+
check_largest(&stats->largest.parent_count, &oids->oid[i],
750+
commit_list_count(commit->parents));
709751
break;
710752
case OBJ_TREE:
711753
stats->type_counts.trees++;
@@ -724,6 +766,9 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
724766
default:
725767
BUG("invalid object type");
726768
}
769+
770+
if (!eaten)
771+
free(content);
727772
}
728773

729774
object_count = get_total_object_values(&stats->type_counts);

t/t1901-repo-structure.sh

Lines changed: 78 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -27,41 +27,42 @@ test_expect_success 'empty repository' '
2727
(
2828
cd repo &&
2929
cat >expect <<-\EOF &&
30-
| Repository structure | Value |
31-
| ------------------------ | ------ |
32-
| * References | |
33-
| * Count | 0 |
34-
| * Branches | 0 |
35-
| * Tags | 0 |
36-
| * Remotes | 0 |
37-
| * Others | 0 |
38-
| | |
39-
| * Reachable objects | |
40-
| * Count | 0 |
41-
| * Commits | 0 |
42-
| * Trees | 0 |
43-
| * Blobs | 0 |
44-
| * Tags | 0 |
45-
| * Inflated size | 0 B |
46-
| * Commits | 0 B |
47-
| * Trees | 0 B |
48-
| * Blobs | 0 B |
49-
| * Tags | 0 B |
50-
| * Disk size | 0 B |
51-
| * Commits | 0 B |
52-
| * Trees | 0 B |
53-
| * Blobs | 0 B |
54-
| * Tags | 0 B |
55-
| | |
56-
| * Largest objects | |
57-
| * Commits | |
58-
| * Maximum size | 0 B |
59-
| * Trees | |
60-
| * Maximum size | 0 B |
61-
| * Blobs | |
62-
| * Maximum size | 0 B |
63-
| * Tags | |
64-
| * Maximum size | 0 B |
30+
| Repository structure | Value |
31+
| ------------------------- | ------ |
32+
| * References | |
33+
| * Count | 0 |
34+
| * Branches | 0 |
35+
| * Tags | 0 |
36+
| * Remotes | 0 |
37+
| * Others | 0 |
38+
| | |
39+
| * Reachable objects | |
40+
| * Count | 0 |
41+
| * Commits | 0 |
42+
| * Trees | 0 |
43+
| * Blobs | 0 |
44+
| * Tags | 0 |
45+
| * Inflated size | 0 B |
46+
| * Commits | 0 B |
47+
| * Trees | 0 B |
48+
| * Blobs | 0 B |
49+
| * Tags | 0 B |
50+
| * Disk size | 0 B |
51+
| * Commits | 0 B |
52+
| * Trees | 0 B |
53+
| * Blobs | 0 B |
54+
| * Tags | 0 B |
55+
| | |
56+
| * Largest objects | |
57+
| * Commits | |
58+
| * Maximum size | 0 B |
59+
| * Maximum parents | 0 |
60+
| * Trees | |
61+
| * Maximum size | 0 B |
62+
| * Blobs | |
63+
| * Maximum size | 0 B |
64+
| * Tags | |
65+
| * Maximum size | 0 B |
6566
EOF
6667
6768
git repo structure >out 2>err &&
@@ -89,46 +90,48 @@ test_expect_success SHA1 'repository with references and objects' '
8990
# git-rev-list(1) --disk-usage=human option printing the full
9091
# "byte/bytes" unit string instead of just "B".
9192
cat >expect <<-EOF &&
92-
| Repository structure | Value |
93-
| ------------------------ | ---------- |
94-
| * References | |
95-
| * Count | 4 |
96-
| * Branches | 1 |
97-
| * Tags | 1 |
98-
| * Remotes | 1 |
99-
| * Others | 1 |
100-
| | |
101-
| * Reachable objects | |
102-
| * Count | 3.02 k |
103-
| * Commits | 1.01 k |
104-
| * Trees | 1.01 k |
105-
| * Blobs | 1.01 k |
106-
| * Tags | 1 |
107-
| * Inflated size | 16.03 MiB |
108-
| * Commits | 217.92 KiB |
109-
| * Trees | 15.81 MiB |
110-
| * Blobs | 11.68 KiB |
111-
| * Tags | 132 B |
112-
| * Disk size | $(object_type_disk_usage all true) |
113-
| * Commits | $(object_type_disk_usage commit true) |
114-
| * Trees | $(object_type_disk_usage tree true) |
115-
| * Blobs | $(object_type_disk_usage blob true) |
116-
| * Tags | $(object_type_disk_usage tag) B |
117-
| | |
118-
| * Largest objects | |
119-
| * Commits | |
120-
| * Maximum size [1] | 223 B |
121-
| * Trees | |
122-
| * Maximum size [2] | 32.29 KiB |
123-
| * Blobs | |
124-
| * Maximum size [3] | 13 B |
125-
| * Tags | |
126-
| * Maximum size [4] | 132 B |
93+
| Repository structure | Value |
94+
| ------------------------- | ---------- |
95+
| * References | |
96+
| * Count | 4 |
97+
| * Branches | 1 |
98+
| * Tags | 1 |
99+
| * Remotes | 1 |
100+
| * Others | 1 |
101+
| | |
102+
| * Reachable objects | |
103+
| * Count | 3.02 k |
104+
| * Commits | 1.01 k |
105+
| * Trees | 1.01 k |
106+
| * Blobs | 1.01 k |
107+
| * Tags | 1 |
108+
| * Inflated size | 16.03 MiB |
109+
| * Commits | 217.92 KiB |
110+
| * Trees | 15.81 MiB |
111+
| * Blobs | 11.68 KiB |
112+
| * Tags | 132 B |
113+
| * Disk size | $(object_type_disk_usage all true) |
114+
| * Commits | $(object_type_disk_usage commit true) |
115+
| * Trees | $(object_type_disk_usage tree true) |
116+
| * Blobs | $(object_type_disk_usage blob true) |
117+
| * Tags | $(object_type_disk_usage tag) B |
118+
| | |
119+
| * Largest objects | |
120+
| * Commits | |
121+
| * Maximum size [1] | 223 B |
122+
| * Maximum parents [2] | 1 |
123+
| * Trees | |
124+
| * Maximum size [3] | 32.29 KiB |
125+
| * Blobs | |
126+
| * Maximum size [4] | 13 B |
127+
| * Tags | |
128+
| * Maximum size [5] | 132 B |
127129
128130
[1] 0dc91eb18580102a3a216c8bfecedeba2b9f9b9a
129-
[2] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
130-
[3] 97d808e45116bf02103490294d3d46dad7a2ac62
131-
[4] 4dae4f5954f5e6feb3577cfb1b181daa3fd3afd2
131+
[2] 0dc91eb18580102a3a216c8bfecedeba2b9f9b9a
132+
[3] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
133+
[4] 97d808e45116bf02103490294d3d46dad7a2ac62
134+
[5] 4dae4f5954f5e6feb3577cfb1b181daa3fd3afd2
132135
EOF
133136
134137
git repo structure >out 2>err &&
@@ -171,6 +174,8 @@ test_expect_success SHA1 'keyvalue and nul format' '
171174
objects.blobs.max_size_oid=eaeeedced46482bd4281fda5a5f05ce24854151f
172175
objects.tags.max_size=132
173176
objects.tags.max_size_oid=1ee0f2b16ea37d895dbe9dbd76cd2ac70446176c
177+
objects.commits.max_parents=1
178+
objects.commits.max_parents_oid=de3508174b5c2ace6993da67cae9be9069e2df39
174179
EOF
175180
176181
git repo structure --format=keyvalue >out 2>err &&

0 commit comments

Comments
 (0)