]>
Commit | Line | Data |
---|---|---|
caf3827e JH |
1 | #!/bin/sh |
2 | ||
3 | test_description='git rev-list using object filtering' | |
4 | ||
5 | . ./test-lib.sh | |
6 | ||
7 | # Test the blob:none filter. | |
8 | ||
9 | test_expect_success 'setup r1' ' | |
10 | echo "{print \$1}" >print_1.awk && | |
11 | echo "{print \$2}" >print_2.awk && | |
12 | ||
13 | git init r1 && | |
14 | for n in 1 2 3 4 5 | |
15 | do | |
16 | echo "This is file: $n" > r1/file.$n | |
17 | git -C r1 add file.$n | |
18 | git -C r1 commit -m "$n" | |
19 | done | |
20 | ' | |
21 | ||
22 | test_expect_success 'verify blob:none omits all 5 blobs' ' | |
61de0ff6 MD |
23 | git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \ |
24 | >ls_files_result && | |
25 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
26 | sort >expected && |
27 | ||
8d6ba495 MD |
28 | git -C r1 rev-list --quiet --objects --filter-print-omitted \ |
29 | --filter=blob:none HEAD >revs && | |
61de0ff6 | 30 | awk -f print_1.awk revs | |
bdbc17e8 MD |
31 | sed "s/~//" | |
32 | sort >observed && | |
33 | ||
dcbaa0b3 | 34 | test_cmp expected observed |
caf3827e JH |
35 | ' |
36 | ||
99c9aa95 MD |
37 | test_expect_success 'specify blob explicitly prevents filtering' ' |
38 | file_3=$(git -C r1 ls-files -s file.3 | | |
39 | awk -f print_2.awk) && | |
40 | ||
41 | file_4=$(git -C r1 ls-files -s file.4 | | |
42 | awk -f print_2.awk) && | |
43 | ||
44 | git -C r1 rev-list --objects --filter=blob:none HEAD $file_3 >observed && | |
d9e6d094 MD |
45 | grep "$file_3" observed && |
46 | ! grep "$file_4" observed | |
99c9aa95 MD |
47 | ' |
48 | ||
caf3827e | 49 | test_expect_success 'verify emitted+omitted == all' ' |
8d6ba495 | 50 | git -C r1 rev-list --objects HEAD >revs && |
61de0ff6 | 51 | awk -f print_1.awk revs | |
bdbc17e8 MD |
52 | sort >expected && |
53 | ||
8d6ba495 MD |
54 | git -C r1 rev-list --objects --filter-print-omitted --filter=blob:none \ |
55 | HEAD >revs && | |
61de0ff6 | 56 | awk -f print_1.awk revs | |
bdbc17e8 MD |
57 | sed "s/~//" | |
58 | sort >observed && | |
59 | ||
dcbaa0b3 | 60 | test_cmp expected observed |
caf3827e JH |
61 | ' |
62 | ||
63 | ||
64 | # Test blob:limit=<n>[kmg] filter. | |
65 | # We boundary test around the size parameter. The filter is strictly less than | |
66 | # the value, so size 500 and 1000 should have the same results, but 1001 should | |
67 | # filter more. | |
68 | ||
69 | test_expect_success 'setup r2' ' | |
70 | git init r2 && | |
71 | for n in 1000 10000 | |
72 | do | |
73 | printf "%"$n"s" X > r2/large.$n | |
74 | git -C r2 add large.$n | |
75 | git -C r2 commit -m "$n" | |
76 | done | |
77 | ' | |
78 | ||
79 | test_expect_success 'verify blob:limit=500 omits all blobs' ' | |
61de0ff6 MD |
80 | git -C r2 ls-files -s large.1000 large.10000 >ls_files_result && |
81 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
82 | sort >expected && |
83 | ||
8d6ba495 MD |
84 | git -C r2 rev-list --quiet --objects --filter-print-omitted \ |
85 | --filter=blob:limit=500 HEAD >revs && | |
61de0ff6 | 86 | awk -f print_1.awk revs | |
bdbc17e8 MD |
87 | sed "s/~//" | |
88 | sort >observed && | |
89 | ||
dcbaa0b3 | 90 | test_cmp expected observed |
caf3827e JH |
91 | ' |
92 | ||
93 | test_expect_success 'verify emitted+omitted == all' ' | |
8d6ba495 | 94 | git -C r2 rev-list --objects HEAD >revs && |
61de0ff6 | 95 | awk -f print_1.awk revs | |
bdbc17e8 MD |
96 | sort >expected && |
97 | ||
8d6ba495 MD |
98 | git -C r2 rev-list --objects --filter-print-omitted \ |
99 | --filter=blob:limit=500 HEAD >revs && | |
61de0ff6 | 100 | awk -f print_1.awk revs | |
bdbc17e8 MD |
101 | sed "s/~//" | |
102 | sort >observed && | |
103 | ||
dcbaa0b3 | 104 | test_cmp expected observed |
caf3827e JH |
105 | ' |
106 | ||
107 | test_expect_success 'verify blob:limit=1000' ' | |
61de0ff6 MD |
108 | git -C r2 ls-files -s large.1000 large.10000 >ls_files_result && |
109 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
110 | sort >expected && |
111 | ||
8d6ba495 MD |
112 | git -C r2 rev-list --quiet --objects --filter-print-omitted \ |
113 | --filter=blob:limit=1000 HEAD >revs && | |
61de0ff6 | 114 | awk -f print_1.awk revs | |
bdbc17e8 MD |
115 | sed "s/~//" | |
116 | sort >observed && | |
117 | ||
dcbaa0b3 | 118 | test_cmp expected observed |
caf3827e JH |
119 | ' |
120 | ||
121 | test_expect_success 'verify blob:limit=1001' ' | |
61de0ff6 MD |
122 | git -C r2 ls-files -s large.10000 >ls_files_result && |
123 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
124 | sort >expected && |
125 | ||
8d6ba495 MD |
126 | git -C r2 rev-list --quiet --objects --filter-print-omitted \ |
127 | --filter=blob:limit=1001 HEAD >revs && | |
61de0ff6 | 128 | awk -f print_1.awk revs | |
bdbc17e8 MD |
129 | sed "s/~//" | |
130 | sort >observed && | |
131 | ||
dcbaa0b3 | 132 | test_cmp expected observed |
caf3827e JH |
133 | ' |
134 | ||
135 | test_expect_success 'verify blob:limit=1k' ' | |
61de0ff6 MD |
136 | git -C r2 ls-files -s large.10000 >ls_files_result && |
137 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
138 | sort >expected && |
139 | ||
8d6ba495 MD |
140 | git -C r2 rev-list --quiet --objects --filter-print-omitted \ |
141 | --filter=blob:limit=1k HEAD >revs && | |
61de0ff6 | 142 | awk -f print_1.awk revs | |
bdbc17e8 MD |
143 | sed "s/~//" | |
144 | sort >observed && | |
145 | ||
dcbaa0b3 | 146 | test_cmp expected observed |
caf3827e JH |
147 | ' |
148 | ||
149 | test_expect_success 'verify blob:limit=1m' ' | |
8d6ba495 MD |
150 | git -C r2 rev-list --quiet --objects --filter-print-omitted \ |
151 | --filter=blob:limit=1m HEAD >revs && | |
61de0ff6 | 152 | awk -f print_1.awk revs | |
bdbc17e8 MD |
153 | sed "s/~//" | |
154 | sort >observed && | |
155 | ||
1c5e94f4 | 156 | test_must_be_empty observed |
caf3827e JH |
157 | ' |
158 | ||
159 | # Test sparse:path=<path> filter. | |
160 | # Use a local file containing a sparse-checkout specification to filter | |
161 | # out blobs not required for the corresponding sparse-checkout. We do not | |
162 | # require sparse-checkout to actually be enabled. | |
163 | ||
164 | test_expect_success 'setup r3' ' | |
165 | git init r3 && | |
166 | mkdir r3/dir1 && | |
167 | for n in sparse1 sparse2 | |
168 | do | |
169 | echo "This is file: $n" > r3/$n | |
170 | git -C r3 add $n | |
171 | echo "This is file: dir1/$n" > r3/dir1/$n | |
172 | git -C r3 add dir1/$n | |
173 | done && | |
174 | git -C r3 commit -m "sparse" && | |
175 | echo dir1/ >pattern1 && | |
176 | echo sparse1 >pattern2 | |
177 | ' | |
178 | ||
179 | test_expect_success 'verify sparse:path=pattern1 omits top-level files' ' | |
61de0ff6 MD |
180 | git -C r3 ls-files -s sparse1 sparse2 >ls_files_result && |
181 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
182 | sort >expected && |
183 | ||
8d6ba495 MD |
184 | git -C r3 rev-list --quiet --objects --filter-print-omitted \ |
185 | --filter=sparse:path=../pattern1 HEAD >revs && | |
61de0ff6 | 186 | awk -f print_1.awk revs | |
bdbc17e8 MD |
187 | sed "s/~//" | |
188 | sort >observed && | |
189 | ||
dcbaa0b3 | 190 | test_cmp expected observed |
caf3827e JH |
191 | ' |
192 | ||
193 | test_expect_success 'verify sparse:path=pattern2 omits both sparse2 files' ' | |
61de0ff6 MD |
194 | git -C r3 ls-files -s sparse2 dir1/sparse2 >ls_files_result && |
195 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
196 | sort >expected && |
197 | ||
8d6ba495 MD |
198 | git -C r3 rev-list --quiet --objects --filter-print-omitted \ |
199 | --filter=sparse:path=../pattern2 HEAD >revs && | |
61de0ff6 | 200 | awk -f print_1.awk revs | |
bdbc17e8 MD |
201 | sed "s/~//" | |
202 | sort >observed && | |
203 | ||
dcbaa0b3 | 204 | test_cmp expected observed |
caf3827e JH |
205 | ' |
206 | ||
207 | # Test sparse:oid=<oid-ish> filter. | |
208 | # Like sparse:path, but we get the sparse-checkout specification from | |
209 | # a blob rather than a file on disk. | |
210 | ||
211 | test_expect_success 'setup r3 part 2' ' | |
212 | echo dir1/ >r3/pattern && | |
213 | git -C r3 add pattern && | |
214 | git -C r3 commit -m "pattern" | |
215 | ' | |
216 | ||
217 | test_expect_success 'verify sparse:oid=OID omits top-level files' ' | |
61de0ff6 MD |
218 | git -C r3 ls-files -s pattern sparse1 sparse2 >ls_files_result && |
219 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
220 | sort >expected && |
221 | ||
caf3827e | 222 | oid=$(git -C r3 ls-files -s pattern | awk -f print_2.awk) && |
bdbc17e8 | 223 | |
8d6ba495 MD |
224 | git -C r3 rev-list --quiet --objects --filter-print-omitted \ |
225 | --filter=sparse:oid=$oid HEAD >revs && | |
61de0ff6 | 226 | awk -f print_1.awk revs | |
bdbc17e8 MD |
227 | sed "s/~//" | |
228 | sort >observed && | |
229 | ||
dcbaa0b3 | 230 | test_cmp expected observed |
caf3827e JH |
231 | ' |
232 | ||
233 | test_expect_success 'verify sparse:oid=oid-ish omits top-level files' ' | |
61de0ff6 MD |
234 | git -C r3 ls-files -s pattern sparse1 sparse2 >ls_files_result && |
235 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
236 | sort >expected && |
237 | ||
8d6ba495 MD |
238 | git -C r3 rev-list --quiet --objects --filter-print-omitted \ |
239 | --filter=sparse:oid=master:pattern HEAD >revs && | |
61de0ff6 | 240 | awk -f print_1.awk revs | |
bdbc17e8 MD |
241 | sed "s/~//" | |
242 | sort >observed && | |
243 | ||
dcbaa0b3 | 244 | test_cmp expected observed |
caf3827e JH |
245 | ' |
246 | ||
7c0fe330 MD |
247 | test_expect_success 'rev-list W/ --missing=print and --missing=allow-any for trees' ' |
248 | TREE=$(git -C r3 rev-parse HEAD:dir1) && | |
249 | ||
250 | # Create a spare repo because we will be deleting objects from this one. | |
251 | git clone r3 r3.b && | |
252 | ||
253 | rm r3.b/.git/objects/$(echo $TREE | sed "s|^..|&/|") && | |
254 | ||
255 | git -C r3.b rev-list --quiet --missing=print --objects HEAD \ | |
256 | >missing_objs 2>rev_list_err && | |
257 | echo "?$TREE" >expected && | |
258 | test_cmp expected missing_objs && | |
259 | ||
260 | # do not complain when a missing tree cannot be parsed | |
261 | test_must_be_empty rev_list_err && | |
262 | ||
263 | git -C r3.b rev-list --missing=allow-any --objects HEAD \ | |
264 | >objs 2>rev_list_err && | |
265 | ! grep $TREE objs && | |
266 | test_must_be_empty rev_list_err | |
267 | ' | |
268 | ||
bc5975d2 MD |
269 | # Test tree:0 filter. |
270 | ||
271 | test_expect_success 'verify tree:0 includes trees in "filtered" output' ' | |
272 | git -C r3 rev-list --quiet --objects --filter-print-omitted \ | |
273 | --filter=tree:0 HEAD >revs && | |
274 | ||
275 | awk -f print_1.awk revs | | |
276 | sed s/~// | | |
277 | xargs -n1 git -C r3 cat-file -t >unsorted_filtered_types && | |
278 | ||
279 | sort -u unsorted_filtered_types >filtered_types && | |
d9e6d094 | 280 | test_write_lines blob tree >expected && |
bc5975d2 MD |
281 | test_cmp expected filtered_types |
282 | ' | |
283 | ||
8b10a206 MD |
284 | # Make sure tree:0 does not iterate through any trees. |
285 | ||
8272f260 | 286 | test_expect_success 'verify skipping tree iteration when not collecting omits' ' |
8b10a206 MD |
287 | GIT_TRACE=1 git -C r3 rev-list \ |
288 | --objects --filter=tree:0 HEAD 2>filter_trace && | |
289 | grep "Skipping contents of tree [.][.][.]" filter_trace >actual && | |
290 | # One line for each commit traversed. | |
291 | test_line_count = 2 actual && | |
292 | ||
293 | # Make sure no other trees were considered besides the root. | |
294 | ! grep "Skipping contents of tree [^.]" filter_trace | |
295 | ' | |
296 | ||
c813a7c3 MD |
297 | # Test tree:# filters. |
298 | ||
299 | expect_has () { | |
300 | commit=$1 && | |
301 | name=$2 && | |
302 | ||
303 | hash=$(git -C r3 rev-parse $commit:$name) && | |
304 | grep "^$hash $name$" actual | |
305 | } | |
306 | ||
307 | test_expect_success 'verify tree:1 includes root trees' ' | |
308 | git -C r3 rev-list --objects --filter=tree:1 HEAD >actual && | |
309 | ||
310 | # We should get two root directories and two commits. | |
311 | expect_has HEAD "" && | |
312 | expect_has HEAD~1 "" && | |
313 | test_line_count = 4 actual | |
314 | ' | |
315 | ||
316 | test_expect_success 'verify tree:2 includes root trees and immediate children' ' | |
317 | git -C r3 rev-list --objects --filter=tree:2 HEAD >actual && | |
318 | ||
319 | expect_has HEAD "" && | |
320 | expect_has HEAD~1 "" && | |
321 | expect_has HEAD dir1 && | |
322 | expect_has HEAD pattern && | |
323 | expect_has HEAD sparse1 && | |
324 | expect_has HEAD sparse2 && | |
325 | ||
326 | # There are also 2 commit objects | |
327 | test_line_count = 8 actual | |
328 | ' | |
329 | ||
330 | test_expect_success 'verify tree:3 includes everything expected' ' | |
331 | git -C r3 rev-list --objects --filter=tree:3 HEAD >actual && | |
332 | ||
333 | expect_has HEAD "" && | |
334 | expect_has HEAD~1 "" && | |
335 | expect_has HEAD dir1 && | |
336 | expect_has HEAD dir1/sparse1 && | |
337 | expect_has HEAD dir1/sparse2 && | |
338 | expect_has HEAD pattern && | |
339 | expect_has HEAD sparse1 && | |
340 | expect_has HEAD sparse2 && | |
341 | ||
342 | # There are also 2 commit objects | |
343 | test_line_count = 10 actual | |
344 | ' | |
345 | ||
346 | # Test provisional omit collection logic with a repo that has objects appearing | |
347 | # at multiple depths - first deeper than the filter's threshold, then shallow. | |
348 | ||
349 | test_expect_success 'setup r4' ' | |
350 | git init r4 && | |
351 | ||
352 | echo foo > r4/foo && | |
353 | mkdir r4/subdir && | |
354 | echo bar > r4/subdir/bar && | |
355 | ||
356 | mkdir r4/filt && | |
357 | cp -r r4/foo r4/subdir r4/filt && | |
358 | ||
359 | git -C r4 add foo subdir filt && | |
360 | git -C r4 commit -m "commit msg" | |
361 | ' | |
362 | ||
363 | expect_has_with_different_name () { | |
364 | repo=$1 && | |
365 | name=$2 && | |
366 | ||
367 | hash=$(git -C $repo rev-parse HEAD:$name) && | |
368 | ! grep "^$hash $name$" actual && | |
369 | grep "^$hash " actual && | |
370 | ! grep "~$hash" actual | |
371 | } | |
372 | ||
373 | test_expect_success 'test tree:# filter provisional omit for blob and tree' ' | |
374 | git -C r4 rev-list --objects --filter-print-omitted --filter=tree:2 \ | |
375 | HEAD >actual && | |
376 | expect_has_with_different_name r4 filt/foo && | |
377 | expect_has_with_different_name r4 filt/subdir | |
378 | ' | |
379 | ||
8272f260 MD |
380 | test_expect_success 'verify skipping tree iteration when collecting omits' ' |
381 | GIT_TRACE=1 git -C r4 rev-list --filter-print-omitted \ | |
382 | --objects --filter=tree:0 HEAD 2>filter_trace && | |
383 | grep "^Skipping contents of tree " filter_trace >actual && | |
384 | ||
385 | echo "Skipping contents of tree subdir/..." >expect && | |
386 | test_cmp expect actual | |
387 | ' | |
388 | ||
c813a7c3 MD |
389 | # Test tree:<depth> where a tree is iterated to twice - once where a subentry is |
390 | # too deep to be included, and again where the blob inside it is shallow enough | |
391 | # to be included. This makes sure we don't use LOFR_MARK_SEEN incorrectly (we | |
392 | # can't use it because a tree can be iterated over again at a lower depth). | |
393 | ||
394 | test_expect_success 'tree:<depth> where we iterate over tree at two levels' ' | |
395 | git init r5 && | |
396 | ||
397 | mkdir -p r5/a/subdir/b && | |
398 | echo foo > r5/a/subdir/b/foo && | |
399 | ||
400 | mkdir -p r5/subdir/b && | |
401 | echo foo > r5/subdir/b/foo && | |
402 | ||
403 | git -C r5 add a subdir && | |
404 | git -C r5 commit -m "commit msg" && | |
405 | ||
406 | git -C r5 rev-list --objects --filter=tree:4 HEAD >actual && | |
407 | expect_has_with_different_name r5 a/subdir/b/foo | |
408 | ' | |
409 | ||
410 | test_expect_success 'tree:<depth> which filters out blob but given as arg' ' | |
411 | blob_hash=$(git -C r4 rev-parse HEAD:subdir/bar) && | |
412 | ||
413 | git -C r4 rev-list --objects --filter=tree:1 HEAD $blob_hash >actual && | |
414 | grep ^$blob_hash actual | |
415 | ' | |
416 | ||
caf3827e JH |
417 | # Delete some loose objects and use rev-list, but WITHOUT any filtering. |
418 | # This models previously omitted objects that we did not receive. | |
419 | ||
420 | test_expect_success 'rev-list W/ --missing=print' ' | |
61de0ff6 MD |
421 | git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \ |
422 | >ls_files_result && | |
423 | awk -f print_2.awk ls_files_result | | |
bdbc17e8 MD |
424 | sort >expected && |
425 | ||
caf3827e JH |
426 | for id in `cat expected | sed "s|..|&/|"` |
427 | do | |
428 | rm r1/.git/objects/$id | |
429 | done && | |
bdbc17e8 | 430 | |
8d6ba495 | 431 | git -C r1 rev-list --quiet --missing=print --objects HEAD >revs && |
61de0ff6 | 432 | awk -f print_1.awk revs | |
bdbc17e8 MD |
433 | sed "s/?//" | |
434 | sort >observed && | |
435 | ||
dcbaa0b3 | 436 | test_cmp expected observed |
caf3827e JH |
437 | ' |
438 | ||
439 | test_expect_success 'rev-list W/O --missing fails' ' | |
440 | test_must_fail git -C r1 rev-list --quiet --objects HEAD | |
441 | ' | |
442 | ||
443 | test_expect_success 'rev-list W/ missing=allow-any' ' | |
444 | git -C r1 rev-list --quiet --missing=allow-any --objects HEAD | |
445 | ' | |
446 | ||
87c2d9d3 JS |
447 | # Test expansion of filter specs. |
448 | ||
449 | test_expect_success 'expand blob limit in protocol' ' | |
450 | git -C r2 config --local uploadpack.allowfilter 1 && | |
451 | GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 clone \ | |
452 | --filter=blob:limit=1k "file://$(pwd)/r2" limit && | |
453 | ! grep "blob:limit=1k" trace && | |
454 | grep "blob:limit=1024" trace | |
455 | ' | |
456 | ||
457 | test_expect_success 'expand tree depth limit in protocol' ' | |
458 | GIT_TRACE_PACKET="$(pwd)/tree_trace" git -c protocol.version=2 clone \ | |
459 | --filter=tree:0k "file://$(pwd)/r2" tree && | |
460 | ! grep "tree:0k" tree_trace && | |
461 | grep "tree:0" tree_trace | |
462 | ' | |
463 | ||
caf3827e | 464 | test_done |