Skip to content

Commit 0525ed4

Browse files
t1901: extend structure metric coverage and portability
Expand t1901 to cover additional structure metrics emitted by git repo structure, including maxima and aggregate keyvalue/nul checks. The test now validates both human-oriented table content and machine-readable fields for the extended metric set. Also make expectations more portable across hash algorithms and platforms by avoiding brittle assumptions. This includes wc output quirks on BSD/macOS and hash-format- sensitive expectations. Signed-off-by: Eslam reda ragheb <eslam.reda.div@gmail.com>
1 parent fd18f28 commit 0525ed4

1 file changed

Lines changed: 187 additions & 63 deletions

File tree

t/t1901-repo-structure.sh

Lines changed: 187 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
24181
test_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

Comments
 (0)