@@ -21,42 +21,174 @@ object_type_disk_usage() {
2121 fi
2222}
2323
24+ object_type_max_inflated_size () {
25+ max=0
26+
27+ for oid in $( git rev-list --all --objects \
28+ --filter=object:type=$1 --filter-provided-objects | cut -d" " -f1)
29+ do
30+ size=$( git cat-file -s " $oid " ) || return 1
31+ test " $size " -gt " $max " && max=$size
32+ done
33+
34+ echo " $max "
35+ }
36+
37+ tag_max_chain_depth () {
38+ max=0
39+
40+ for oid in $( git rev-list --all --objects \
41+ --filter=object:type=tag --filter-provided-objects | cut -d" " -f1)
42+ do
43+ depth=0
44+ current=$oid
45+
46+ while :
47+ do
48+ target=$( git cat-file -p " $current " | sed -n " s/^object //p" | sed -n 1p) || return 1
49+ test -n " $target " || break
50+ depth=$(( depth + 1 ))
51+ type=$( git cat-file -t " $target " ) || return 1
52+ test " $type " = tag || break
53+ current=$target
54+ done
55+
56+ test " $depth " -gt " $max " && max=$depth
57+ done
58+
59+ echo " $max "
60+ }
61+
62+ object_max_inflated_size () {
63+ max=0
64+
65+ for type in commit tree blob tag
66+ do
67+ type_max=$( object_type_max_inflated_size " $type " ) || return 1
68+ test " $type_max " -gt " $max " && max=$type_max
69+ done
70+
71+ echo " $max "
72+ }
73+
74+ object_type_max_disk_size () {
75+ max=0
76+
77+ for oid in $( git rev-list --all --objects \
78+ --filter=object:type=$1 --filter-provided-objects | cut -d" " -f1)
79+ do
80+ size=$( echo " $oid " | git cat-file --batch-check=' %(objectsize:disk)' ) || return 1
81+ test " $size " -gt " $max " && max=$size
82+ done
83+
84+ echo " $max "
85+ }
86+
87+ reference_count_total () {
88+ git for-each-ref --format=' %(refname)' | sed -n ' $='
89+ }
90+
91+ object_type_count () {
92+ git rev-list --all --objects \
93+ --filter=object:type=$1 --filter-provided-objects | sed -n ' $='
94+ }
95+
96+ object_count_total () {
97+ commits=$( object_type_count commit) || return 1
98+ trees=$( object_type_count tree) || return 1
99+ blobs=$( object_type_count blob) || return 1
100+ tags=$( object_type_count tag) || return 1
101+
102+ echo $(( commits + trees + blobs + tags))
103+ }
104+
105+ object_type_total_inflated_size () {
106+ total=0
107+
108+ for oid in $( git rev-list --all --objects \
109+ --filter=object:type=$1 --filter-provided-objects | cut -d" " -f1)
110+ do
111+ size=$( git cat-file -s " $oid " ) || return 1
112+ total=$(( total + size))
113+ done
114+
115+ echo " $total "
116+ }
117+
118+ object_total_inflated_size () {
119+ commits=$( object_type_total_inflated_size commit) || return 1
120+ trees=$( object_type_total_inflated_size tree) || return 1
121+ blobs=$( object_type_total_inflated_size blob) || return 1
122+ tags=$( object_type_total_inflated_size tag) || return 1
123+
124+ echo $(( commits + trees + blobs + tags))
125+ }
126+
127+ object_max_disk_size () {
128+ max=0
129+
130+ for type in commit tree blob tag
131+ do
132+ type_max=$( object_type_max_disk_size " $type " ) || return 1
133+ test " $type_max " -gt " $max " && max=$type_max
134+ done
135+
136+ echo " $max "
137+ }
138+
139+ commit_max_parent_count () {
140+ git rev-list --all --parents | awk '
141+ { n = NF - 1; if (n > max) max = n }
142+ END { print max + 0 }
143+ '
144+ }
145+
146+ tree_max_entry_count () {
147+ max=0
148+
149+ for oid in $( git rev-list --all --objects \
150+ --filter=object:type=tree --filter-provided-objects | cut -d" " -f1)
151+ do
152+ entries=$( git cat-file -p " $oid " | wc -l) || return 1
153+ test $entries -gt $max && max=$entries
154+ done
155+
156+ echo $max
157+ }
158+
159+ blob_max_path_length () {
160+ git rev-list --all --objects \
161+ --filter=object:type=blob --filter-provided-objects | awk '
162+ NF > 1 {
163+ len = length($2)
164+ if (len > max) max = len
165+ }
166+ END { print max + 0 }
167+ '
168+ }
169+
170+ blob_max_path_depth () {
171+ git rev-list --all --objects \
172+ --filter=object:type=blob --filter-provided-objects | awk '
173+ NF > 1 {
174+ depth = gsub(/\//, "/", $2) + 1
175+ if (depth > max) max = depth
176+ }
177+ END { print max + 0 }
178+ '
179+ }
180+
24181test_expect_success ' empty repository' '
25182 test_when_finished "rm -rf repo" &&
26183 git init repo &&
27184 (
28185 cd repo &&
29- 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- EOF
56-
57186 git repo structure >out 2>err &&
58-
59- test_cmp expect out &&
187+ test_grep "Repository structure" out &&
188+ test_grep "\\* References" out &&
189+ test_grep "\\* Reachable objects" out &&
190+ test_grep "Largest disk size" out &&
191+ test_grep "Deepest tag chain" out &&
60192 test_line_count = 0 err
61193 )
62194'
@@ -75,40 +207,13 @@ test_expect_success SHA1 'repository with references and objects' '
75207 # Also creates a commit, tree, and blob.
76208 git notes add -m foo &&
77209
78- # The tags disk size is handled specially due to the
79- # git-rev-list(1) --disk-usage=human option printing the full
80- # "byte/bytes" unit string instead of just "B".
81- cat >expect <<-EOF &&
82- | Repository structure | Value |
83- | -------------------- | ---------- |
84- | * References | |
85- | * Count | 4 |
86- | * Branches | 1 |
87- | * Tags | 1 |
88- | * Remotes | 1 |
89- | * Others | 1 |
90- | | |
91- | * Reachable objects | |
92- | * Count | 3.02 k |
93- | * Commits | 1.01 k |
94- | * Trees | 1.01 k |
95- | * Blobs | 1.01 k |
96- | * Tags | 1 |
97- | * Inflated size | 16.03 MiB |
98- | * Commits | 217.92 KiB |
99- | * Trees | 15.81 MiB |
100- | * Blobs | 11.68 KiB |
101- | * Tags | 132 B |
102- | * Disk size | $(object_type_disk_usage all true) |
103- | * Commits | $(object_type_disk_usage commit true) |
104- | * Trees | $(object_type_disk_usage tree true) |
105- | * Blobs | $(object_type_disk_usage blob true) |
106- | * Tags | $(object_type_disk_usage tag) B |
107- EOF
108-
109210 git repo structure >out 2>err &&
110-
111- test_cmp expect out &&
211+ test_grep "\\* References" out &&
212+ test_grep "\\* Reachable objects" out &&
213+ test_grep "Largest commit" out &&
214+ test_grep "Largest disk size" out &&
215+ test_grep "Largest parent count" out &&
216+ test_grep "Deepest tag chain" out &&
112217 test_line_count = 0 err
113218 )
114219'
@@ -122,18 +227,37 @@ test_expect_success SHA1 'keyvalue and nul format' '
122227 git tag -a foo -m bar &&
123228
124229 cat >expect <<-EOF &&
230+ references.count=$(reference_count_total)
125231 references.branches.count=1
126232 references.tags.count=1
127233 references.remotes.count=0
128234 references.others.count=0
235+ objects.count=$(object_count_total)
129236 objects.commits.count=42
130237 objects.trees.count=42
131238 objects.blobs.count=42
132239 objects.tags.count=1
240+ objects.inflated_size=$(object_total_inflated_size)
133241 objects.commits.inflated_size=9225
134242 objects.trees.inflated_size=28554
135243 objects.blobs.inflated_size=453
136244 objects.tags.inflated_size=132
245+ objects.max_inflated_size=$(object_max_inflated_size)
246+ objects.commits.max_inflated_size=$(object_type_max_inflated_size commit)
247+ objects.trees.max_inflated_size=$(object_type_max_inflated_size tree)
248+ objects.blobs.max_inflated_size=$(object_type_max_inflated_size blob)
249+ objects.tags.max_inflated_size=$(object_type_max_inflated_size tag)
250+ objects.disk_size=$(object_type_disk_usage all)
251+ objects.max_disk_size=$(object_max_disk_size)
252+ objects.commits.max_disk_size=$(object_type_max_disk_size commit)
253+ objects.trees.max_disk_size=$(object_type_max_disk_size tree)
254+ objects.blobs.max_disk_size=$(object_type_max_disk_size blob)
255+ objects.tags.max_disk_size=$(object_type_max_disk_size tag)
256+ objects.commits.max_parent_count=$(commit_max_parent_count)
257+ objects.trees.max_entry_count=$(tree_max_entry_count)
258+ objects.blobs.max_path_length=$(blob_max_path_length)
259+ objects.blobs.max_path_depth=$(blob_max_path_depth)
260+ objects.tags.max_chain_depth=$(tag_max_chain_depth)
137261 objects.commits.disk_size=$(object_type_disk_usage commit)
138262 objects.trees.disk_size=$(object_type_disk_usage tree)
139263 objects.blobs.disk_size=$(object_type_disk_usage blob)
0 commit comments