Blob


1 #!/bin/sh
2 #
3 # Copyright (c) 2019 Stefan Sperling <stsp@openbsd.org>
4 #
5 # Permission to use, copy, modify, and distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 . ./common.sh
19 blame_cmp() {
20 local testroot="$1"
21 local file="$2"
22 local xfail="$3"
24 (cd $testroot/wt && got blame "$file" | cut -d ' ' -f 2 \
25 > $testroot/${file}.blame.got)
26 (cd $testroot/repo && git reset --hard master > /dev/null)
27 (cd $testroot/repo && git blame "$file" | cut -d ' ' -f 1 \
28 > $testroot/${file}.blame.git)
30 cmp -s $testroot/${file}.blame.git $testroot/${file}.blame.got
31 ret=$?
32 if [ $ret -ne 0 -a "$xfail" = "" ]; then
33 diff -u $testroot/${file}.blame.git $testroot/${file}.blame.got
34 return 1
35 fi
36 return "$ret"
37 }
39 test_blame_basic() {
40 local testroot=`test_init blame_basic`
42 got checkout $testroot/repo $testroot/wt > /dev/null
43 ret=$?
44 if [ $ret -ne 0 ]; then
45 test_done "$testroot" "$ret"
46 return 1
47 fi
49 echo 1 > $testroot/wt/alpha
50 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
51 local commit1=`git_show_head $testroot/repo`
53 echo 2 >> $testroot/wt/alpha
54 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
55 local commit2=`git_show_head $testroot/repo`
57 echo 3 >> $testroot/wt/alpha
58 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
59 local commit3=`git_show_head $testroot/repo`
60 local author_time=`git_show_author_time $testroot/repo`
62 (cd $testroot/wt && got blame alpha > $testroot/stdout)
64 local short_commit1=`trim_obj_id 32 $commit1`
65 local short_commit2=`trim_obj_id 32 $commit2`
66 local short_commit3=`trim_obj_id 32 $commit3`
68 d=`date -u -r $author_time +"%G-%m-%d"`
69 echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
70 echo "2) $short_commit2 $d $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
71 echo "3) $short_commit3 $d $GOT_AUTHOR_8 3" >> $testroot/stdout.expected
73 cmp -s $testroot/stdout.expected $testroot/stdout
74 ret=$?
75 if [ $ret -ne 0 ]; then
76 diff -u $testroot/stdout.expected $testroot/stdout
77 test_done "$testroot" "$ret"
78 return 1
79 fi
81 blame_cmp "$testroot" "alpha"
82 ret=$?
83 test_done "$testroot" "$ret"
84 }
86 test_blame_tag() {
87 local testroot=`test_init blame_tag`
88 local tag=1.0.0
90 got checkout $testroot/repo $testroot/wt > /dev/null
91 ret=$?
92 if [ $ret -ne 0 ]; then
93 test_done "$testroot" "$ret"
94 return 1
95 fi
96 echo 1 > $testroot/wt/alpha
97 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
98 local commit1=`git_show_head $testroot/repo`
100 echo 2 >> $testroot/wt/alpha
101 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
102 local commit2=`git_show_head $testroot/repo`
104 (cd $testroot/repo && git tag -a -m "test" $tag)
106 echo 3 >> $testroot/wt/alpha
107 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
108 local commit3=`git_show_head $testroot/repo`
109 local author_time=`git_show_author_time $testroot/repo`
111 (cd $testroot/wt && got blame -c $tag alpha > $testroot/stdout)
113 local short_commit1=`trim_obj_id 32 $commit1`
114 local short_commit2=`trim_obj_id 32 $commit2`
116 d=`date -u -r $author_time +"%G-%m-%d"`
117 echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
118 echo "2) $short_commit2 $d $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
120 cmp -s $testroot/stdout.expected $testroot/stdout
121 ret=$?
122 if [ $ret -ne 0 ]; then
123 diff -u $testroot/stdout.expected $testroot/stdout
124 test_done "$testroot" "$ret"
125 return 1
126 fi
128 blame_cmp "$testroot" "alpha"
129 ret=$?
130 test_done "$testroot" "$ret"
133 test_blame_file_single_line() {
134 local testroot=`test_init blame_file_single_line`
136 got checkout $testroot/repo $testroot/wt > /dev/null
137 ret=$?
138 if [ $ret -ne 0 ]; then
139 test_done "$testroot" "$ret"
140 return 1
141 fi
143 echo 1 > $testroot/wt/alpha
144 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
145 local commit1=`git_show_head $testroot/repo`
146 local author_time=`git_show_author_time $testroot/repo`
148 (cd $testroot/wt && got blame alpha > $testroot/stdout)
150 local short_commit1=`trim_obj_id 32 $commit1`
152 d=`date -u -r $author_time +"%G-%m-%d"`
153 echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
155 cmp -s $testroot/stdout.expected $testroot/stdout
156 ret=$?
157 if [ $ret -ne 0 ]; then
158 diff -u $testroot/stdout.expected $testroot/stdout
159 test_done "$testroot" "$ret"
160 return 1
161 fi
163 blame_cmp "$testroot" "alpha"
164 ret=$?
165 test_done "$testroot" "$ret"
168 test_blame_file_single_line_no_newline() {
169 local testroot=`test_init blame_file_single_line_no_newline`
171 got checkout $testroot/repo $testroot/wt > /dev/null
172 ret=$?
173 if [ $ret -ne 0 ]; then
174 test_done "$testroot" "$ret"
175 return 1
176 fi
178 echo -n 1 > $testroot/wt/alpha
179 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
180 local commit1=`git_show_head $testroot/repo`
181 local author_time=`git_show_author_time $testroot/repo`
183 (cd $testroot/wt && got blame alpha > $testroot/stdout)
185 local short_commit1=`trim_obj_id 32 $commit1`
187 d=`date -u -r $author_time +"%G-%m-%d"`
188 echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
190 cmp -s $testroot/stdout.expected $testroot/stdout
191 ret=$?
192 if [ $ret -ne 0 ]; then
193 diff -u $testroot/stdout.expected $testroot/stdout
194 fi
195 test_done "$testroot" "$ret"
198 test_blame_all_lines_replaced() {
199 local testroot=`test_init blame_all_lines_replaced`
201 got checkout $testroot/repo $testroot/wt > /dev/null
202 ret=$?
203 if [ $ret -ne 0 ]; then
204 test_done "$testroot" "$ret"
205 return 1
206 fi
208 jot 8 > $testroot/wt/alpha
209 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
210 local commit1=`git_show_head $testroot/repo`
211 local short_commit1=`trim_obj_id 32 $commit1`
212 local author_time=`git_show_author_time $testroot/repo`
214 (cd $testroot/wt && got blame alpha > $testroot/stdout)
216 d=`date -u -r $author_time +"%G-%m-%d"`
217 echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
218 echo "2) $short_commit1 $d $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
219 echo "3) $short_commit1 $d $GOT_AUTHOR_8 3" >> $testroot/stdout.expected
220 echo "4) $short_commit1 $d $GOT_AUTHOR_8 4" >> $testroot/stdout.expected
221 echo "5) $short_commit1 $d $GOT_AUTHOR_8 5" >> $testroot/stdout.expected
222 echo "6) $short_commit1 $d $GOT_AUTHOR_8 6" >> $testroot/stdout.expected
223 echo "7) $short_commit1 $d $GOT_AUTHOR_8 7" >> $testroot/stdout.expected
224 echo "8) $short_commit1 $d $GOT_AUTHOR_8 8" >> $testroot/stdout.expected
226 cmp -s $testroot/stdout.expected $testroot/stdout
227 ret=$?
228 if [ $ret -ne 0 ]; then
229 diff -u $testroot/stdout.expected $testroot/stdout
230 fi
231 test_done "$testroot" "$ret"
235 test_blame_lines_shifted_up() {
236 local testroot=`test_init blame_lines_shifted_up`
238 got checkout $testroot/repo $testroot/wt > /dev/null
239 ret=$?
240 if [ $ret -ne 0 ]; then
241 test_done "$testroot" "$ret"
242 return 1
243 fi
245 jot 8 > $testroot/wt/alpha
246 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
247 local commit1=`git_show_head $testroot/repo`
248 local short_commit1=`trim_obj_id 32 $commit1`
249 local author_time=`git_show_author_time $testroot/repo`
251 ed -s $testroot/wt/alpha <<-\EOF
252 g/^[345]$/d
254 EOF
255 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
256 local commit2=`git_show_head $testroot/repo`
257 local short_commit2=`trim_obj_id 32 $commit2`
259 jot 2 > $testroot/wt/alpha
260 echo foo >> $testroot/wt/alpha
261 echo bar >> $testroot/wt/alpha
262 echo baz >> $testroot/wt/alpha
263 jot 8 6 8 1 >> $testroot/wt/alpha
264 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
265 local commit3=`git_show_head $testroot/repo`
266 local short_commit3=`trim_obj_id 32 $commit3`
267 local author_time=`git_show_author_time $testroot/repo`
269 (cd $testroot/wt && got blame alpha > $testroot/stdout)
271 d=`date -u -r $author_time +"%G-%m-%d"`
272 echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
273 echo "2) $short_commit1 $d $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
274 echo "3) $short_commit3 $d $GOT_AUTHOR_8 foo" >> $testroot/stdout.expected
275 echo "4) $short_commit3 $d $GOT_AUTHOR_8 bar" >> $testroot/stdout.expected
276 echo "5) $short_commit3 $d $GOT_AUTHOR_8 baz" >> $testroot/stdout.expected
277 echo "6) $short_commit1 $d $GOT_AUTHOR_8 6" >> $testroot/stdout.expected
278 echo "7) $short_commit1 $d $GOT_AUTHOR_8 7" >> $testroot/stdout.expected
279 echo "8) $short_commit1 $d $GOT_AUTHOR_8 8" >> $testroot/stdout.expected
281 cmp -s $testroot/stdout.expected $testroot/stdout
282 ret=$?
283 if [ $ret -ne 0 ]; then
284 diff -u $testroot/stdout.expected $testroot/stdout
285 test_done "$testroot" "$ret"
286 return 1
287 fi
289 blame_cmp "$testroot" "alpha"
290 ret=$?
291 test_done "$testroot" "$ret"
294 test_blame_lines_shifted_down() {
295 local testroot=`test_init blame_lines_shifted_down`
297 got checkout $testroot/repo $testroot/wt > /dev/null
298 ret=$?
299 if [ $ret -ne 0 ]; then
300 test_done "$testroot" "$ret"
301 return 1
302 fi
304 jot 8 > $testroot/wt/alpha
305 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
306 local commit1=`git_show_head $testroot/repo`
307 local short_commit1=`trim_obj_id 32 $commit1`
308 local author_time=`git_show_author_time $testroot/repo`
310 ed -s $testroot/wt/alpha <<-\EOF
311 g/^8$/d
313 EOF
314 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
315 local commit2=`git_show_head $testroot/repo`
316 local short_commit2=`trim_obj_id 32 $commit2`
318 jot 2 > $testroot/wt/alpha
319 echo foo >> $testroot/wt/alpha
320 echo bar >> $testroot/wt/alpha
321 echo baz >> $testroot/wt/alpha
322 jot 8 3 8 1 >> $testroot/wt/alpha
323 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
324 local commit3=`git_show_head $testroot/repo`
325 local short_commit3=`trim_obj_id 32 $commit3`
326 local author_time=`git_show_author_time $testroot/repo`
328 (cd $testroot/wt && got blame alpha > $testroot/stdout)
330 d=`date -u -r $author_time +"%G-%m-%d"`
331 echo "01) $short_commit1 $d $GOT_AUTHOR_8 1" \
332 > $testroot/stdout.expected
333 echo "02) $short_commit1 $d $GOT_AUTHOR_8 2" \
334 >> $testroot/stdout.expected
335 echo "03) $short_commit3 $d $GOT_AUTHOR_8 foo" \
336 >> $testroot/stdout.expected
337 echo "04) $short_commit3 $d $GOT_AUTHOR_8 bar" \
338 >> $testroot/stdout.expected
339 echo "05) $short_commit3 $d $GOT_AUTHOR_8 baz" \
340 >> $testroot/stdout.expected
341 echo "06) $short_commit1 $d $GOT_AUTHOR_8 3" \
342 >> $testroot/stdout.expected
343 echo "07) $short_commit1 $d $GOT_AUTHOR_8 4" \
344 >> $testroot/stdout.expected
345 echo "08) $short_commit1 $d $GOT_AUTHOR_8 5" \
346 >> $testroot/stdout.expected
347 echo "09) $short_commit1 $d $GOT_AUTHOR_8 6" \
348 >> $testroot/stdout.expected
349 echo "10) $short_commit1 $d $GOT_AUTHOR_8 7" \
350 >> $testroot/stdout.expected
351 echo "11) $short_commit3 $d $GOT_AUTHOR_8 8" \
352 >> $testroot/stdout.expected
354 cmp -s $testroot/stdout.expected $testroot/stdout
355 ret=$?
356 if [ $ret -ne 0 ]; then
357 diff -u $testroot/stdout.expected $testroot/stdout
358 test_done "$testroot" "$ret"
359 return 1
360 fi
362 blame_cmp "$testroot" "alpha"
363 ret=$?
364 test_done "$testroot" "$ret"
367 test_blame_commit_subsumed() {
368 local testroot=`test_init blame_commit_subsumed`
370 got checkout $testroot/repo $testroot/wt > /dev/null
371 ret=$?
372 if [ $ret -ne 0 ]; then
373 test_done "$testroot" "$ret"
374 return 1
375 fi
377 cat > $testroot/wt/alpha <<EOF
378 SUBDIRS = ext modules codedocs docs
380 if WITH_PDNS_SERVER
381 SUBDIRS += pdns
382 endif
384 EXTRA_DIST =
385 INSTALL
386 NOTICE
387 README
388 .version
389 build-aux/gen-version
390 codedocs/doxygen.conf
391 contrib/powerdns.solaris.init.d
392 pdns/named.conf.parsertest
393 regression-tests/zones/unit.test
395 ACLOCAL_AMFLAGS = -I m4
397 dvi: # do nothing to build dvi
398 EOF
399 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
400 local commit1=`git_show_head $testroot/repo`
401 local short_commit1=`trim_obj_id 32 $commit1`
402 local author_time1=`git_show_author_time $testroot/repo`
403 local d1=`date -u -r $author_time1 +"%G-%m-%d"`
405 cat > $testroot/wt/alpha <<EOF
406 SUBDIRS = ext modules codedocs docs
408 SUBDIRS += pdns
410 EXTRA_DIST =
411 INSTALL
412 NOTICE
413 README
414 .version
415 build-aux/gen-version
416 codedocs/doxygen.conf
417 contrib/powerdns.solaris.init.d
418 pdns/named.conf.parsertest
419 regression-tests/zones/unit.test
421 ACLOCAL_AMFLAGS = -I m4
423 dvi: # do nothing to build dvi
424 EOF
425 # all changes in this commit will be subsumed by later commits
426 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
427 local commit2=`git_show_head $testroot/repo`
428 local short_commit2=`trim_obj_id 32 $commit2`
429 local author_time2=`git_show_author_time $testroot/repo`
430 local d2=`date -u -r $author_time2 +"%G-%m-%d"`
432 cat > $testroot/wt/alpha <<EOF
433 SUBDIRS = ext modules pdns codedocs docs
435 EXTRA_DIST =
436 INSTALL
437 NOTICE
438 README
439 .version
440 build-aux/gen-version
441 codedocs/doxygen.conf
442 contrib/powerdns.solaris.init.d
443 pdns/named.conf.parsertest
444 regression-tests/zones/unit.test
446 ACLOCAL_AMFLAGS = -I m4
448 dvi: # do nothing to build dvi
449 EOF
450 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
451 local commit3=`git_show_head $testroot/repo`
452 local short_commit3=`trim_obj_id 32 $commit3`
453 local author_time3=`git_show_author_time $testroot/repo`
454 local d3=`date -u -r $author_time3 +"%G-%m-%d"`
456 cat > $testroot/wt/alpha <<EOF
457 SUBDIRS = ext modules pdns codedocs docs
459 EXTRA_DIST =
460 INSTALL
461 NOTICE
462 README
463 COPYING
464 codedocs/doxygen.conf
465 contrib/powerdns.solaris.init.d
466 pdns/named.conf.parsertest
467 regression-tests/zones/unit.test
468 builder-support/gen-version
470 ACLOCAL_AMFLAGS = -I m4
472 dvi: # do nothing to build dvi
473 EOF
474 (cd $testroot/wt && got commit -m "change 4" > /dev/null)
475 local commit4=`git_show_head $testroot/repo`
476 local short_commit4=`trim_obj_id 32 $commit4`
477 local author_time4=`git_show_author_time $testroot/repo`
478 local d4=`date -u -r $author_time4 +"%G-%m-%d"`
480 (cd $testroot/wt && got blame alpha > $testroot/stdout)
482 echo -n "01) $short_commit3 $d3 $GOT_AUTHOR_8 " \
483 > $testroot/stdout.expected
484 echo "SUBDIRS = ext modules pdns codedocs docs" \
485 >> $testroot/stdout.expected
486 echo "02) $short_commit1 $d1 $GOT_AUTHOR_8 " \
487 >> $testroot/stdout.expected
488 echo -n "03) $short_commit1 $d1 $GOT_AUTHOR_8 " \
489 >> $testroot/stdout.expected
490 echo 'EXTRA_DIST =' >> $testroot/stdout.expected
491 echo -n "04) $short_commit1 $d1 $GOT_AUTHOR_8 " \
492 >> $testroot/stdout.expected
493 printf "\tINSTALL\n" >> $testroot/stdout.expected
494 echo -n "05) $short_commit1 $d1 $GOT_AUTHOR_8 " \
495 >> $testroot/stdout.expected
496 printf "\tNOTICE\n" >> $testroot/stdout.expected
497 echo -n "06) $short_commit1 $d1 $GOT_AUTHOR_8 " \
498 >> $testroot/stdout.expected
499 printf "\tREADME\n" >> $testroot/stdout.expected
500 echo -n "07) $short_commit4 $d4 $GOT_AUTHOR_8 " \
501 >> $testroot/stdout.expected
502 printf "\tCOPYING\n" >> $testroot/stdout.expected
503 echo -n "08) $short_commit1 $d1 $GOT_AUTHOR_8 " \
504 >> $testroot/stdout.expected
505 printf "\tcodedocs/doxygen.conf\n" >> $testroot/stdout.expected
506 echo -n "09) $short_commit1 $d1 $GOT_AUTHOR_8 " \
507 >> $testroot/stdout.expected
508 printf "\tcontrib/powerdns.solaris.init.d\n" \
509 >> $testroot/stdout.expected
510 echo -n "10) $short_commit1 $d1 $GOT_AUTHOR_8 " \
511 >> $testroot/stdout.expected
512 printf "\tpdns/named.conf.parsertest\n" >> $testroot/stdout.expected
513 echo -n "11) $short_commit1 $d1 $GOT_AUTHOR_8 " \
514 >> $testroot/stdout.expected
515 printf "\tregression-tests/zones/unit.test\n" \
516 >> $testroot/stdout.expected
517 echo -n "12) $short_commit4 $d4 $GOT_AUTHOR_8 " \
518 >> $testroot/stdout.expected
519 printf "\tbuilder-support/gen-version\n" >> $testroot/stdout.expected
520 echo "13) $short_commit1 $d1 $GOT_AUTHOR_8 " \
521 >> $testroot/stdout.expected
522 echo -n "14) $short_commit1 $d1 $GOT_AUTHOR_8 " \
523 >> $testroot/stdout.expected
524 echo "ACLOCAL_AMFLAGS = -I m4" \
525 >> $testroot/stdout.expected
526 echo "15) $short_commit1 $d1 $GOT_AUTHOR_8 " \
527 >> $testroot/stdout.expected
528 echo -n "16) $short_commit1 $d1 $GOT_AUTHOR_8 " \
529 >> $testroot/stdout.expected
530 echo "dvi: # do nothing to build dvi" \
531 >> $testroot/stdout.expected
533 cmp -s $testroot/stdout.expected $testroot/stdout
534 ret=$?
535 if [ $ret -ne 0 ]; then
536 diff -u $testroot/stdout.expected $testroot/stdout
537 test_done "$testroot" "$ret"
538 return 1
539 fi
541 blame_cmp "$testroot" "alpha"
542 ret=$?
543 test_done "$testroot" "$ret"
546 test_blame_blame_h() {
547 local testroot=`test_init blame_blame_h`
549 got checkout $testroot/repo $testroot/wt > /dev/null
550 ret=$?
551 if [ $ret -ne 0 ]; then
552 test_done "$testroot" "$ret"
553 return 1
554 fi
556 cat > $testroot/wt/got_blame.h <<EOF
557 /*
558 * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
560 * Permission to use, copy, modify, and distribute this software for any
561 * purpose with or without fee is hereby granted, provided that the above
562 * copyright notice and this permission notice appear in all copies.
564 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
565 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
566 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
567 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
568 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
569 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
570 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
571 */
573 const struct got_error *got_blame(const char *, struct got_object_id *,
574 struct got_repository *, FILE *);
575 EOF
576 (cd $testroot/wt && got add got_blame.h > /dev/null)
577 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
579 cat > $testroot/wt/blame-2.patch <<EOF
580 diff 63581804340e880bf611c6a4a59eda26c503799f 84451b3ef755f3226d0d79af367632e5f3a830e7
581 blob - b53ca469a18871cc2f6af334dab25028599c6488
582 blob + c787aadf05e2afab61bd34976f7349912252e6da
583 --- got_blame.h
584 +++ got_blame.h
585 @@ -14,5 +14,22 @@
586 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
587 */
589 +/*
590 + * Write an annotated version of a file at a given in-repository path,
591 + * as found in the commit specified by ID, to the specified output file.
592 + */
593 const struct got_error *got_blame(const char *, struct got_object_id *,
594 struct got_repository *, FILE *);
596 +/*
597 + * Like got_blame() but instead of generating an output file invoke
598 + * a callback whenever an annotation has been computed for a line.
599 + *
600 + * The callback receives the provided void * argument, the total number
601 + * of lines of the annotated file, a line number, and the ID of the commit
602 + * which last changed this line.
603 + */
604 +const struct got_error *got_blame_incremental(const char *,
605 + struct got_object_id *, struct got_repository *,
606 + const struct got_error *(*cb)(void *, int, int, struct got_object_id *),
607 + void *);
608 EOF
609 (cd $testroot/wt && patch < blame-2.patch > /dev/null)
610 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
612 cat > $testroot/wt/blame-3.patch <<EOF
613 diff 75b7a700d9d14ef8eb902961255212acbedef164 d68a0a7de13af722c55099582019c03240e13320
614 blob - c787aadf05e2afab61bd34976f7349912252e6da
615 blob + 5255d076c915accf159940978b821d06803ff2f8
616 --- got_blame.h
617 +++ got_blame.h
618 @@ -28,6 +28,15 @@ const struct got_error *got_blame(const char *, struct
619 * The callback receives the provided void * argument, the total number
620 * of lines of the annotated file, a line number, and the ID of the commit
621 * which last changed this line.
622 + *
623 + * The callback is invoked for each commit as history is traversed.
624 + * If no changes to the file were made in a commit, line number -1 and
625 + * commit ID NULL will be reported.
626 + *
627 + * If the callback returns GOT_ERR_ITER_COMPLETED, the blame operation
628 + * will be aborted and this function returns NULL.
629 + * If the callback returns any other error, the blame operation will be
630 + * aborted and the callback's error is returned from this function.
631 */
632 const struct got_error *got_blame_incremental(const char *,
633 struct got_object_id *, struct got_repository *,
634 EOF
635 (cd $testroot/wt && patch < blame-3.patch > /dev/null)
636 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
638 cat > $testroot/wt/blame-4.patch <<EOF
639 diff 3f60a8ef49086101685260fcb829f578cdf6d320 3bf198ba335fa30c8d16efb5c8e496200ac99c05
640 blob - 5255d076c915accf159940978b821d06803ff2f8
641 blob + 39623c468e733ee08abb50eafe29202b2b0a04ef
642 --- got_blame.h
643 +++ got_blame.h
644 @@ -30,8 +30,8 @@ const struct got_error *got_blame(const char *, struct
645 * which last changed this line.
647 * The callback is invoked for each commit as history is traversed.
648 - * If no changes to the file were made in a commit, line number -1 and
649 - * commit ID NULL will be reported.
650 + * If no changes to the file were made in a commit, line number -1 will
651 + * be reported.
653 * If the callback returns GOT_ERR_ITER_COMPLETED, the blame operation
654 * will be aborted and this function returns NULL.
655 EOF
656 (cd $testroot/wt && patch < blame-4.patch > /dev/null)
657 (cd $testroot/wt && got commit -m "change 4" > /dev/null)
659 cat > $testroot/wt/blame-5.patch <<EOF
660 diff 28315671b93d195163b0468fcb3879e29b25759c e27a7222faaa171dcb086ea0b566dc7bebb74a0b
661 blob - 39623c468e733ee08abb50eafe29202b2b0a04ef
662 blob + 6075cadbd177e1802679c7353515bf4ceebb51d0
663 --- got_blame.h
664 +++ got_blame.h
665 @@ -15,14 +15,7 @@
666 */
668 /*
669 - * Write an annotated version of a file at a given in-repository path,
670 - * as found in the commit specified by ID, to the specified output file.
671 - */
672 -const struct got_error *got_blame(const char *, struct got_object_id *,
673 - struct got_repository *, FILE *);
675 -/*
676 - * Like got_blame() but instead of generating an output file invoke
677 + * Blame the blob at the specified path in the specified commit and invoke
678 * a callback whenever an annotation has been computed for a line.
680 * The callback receives the provided void * argument, the total number
681 EOF
682 (cd $testroot/wt && patch < blame-5.patch > /dev/null)
683 (cd $testroot/wt && got commit -m "change 5" > /dev/null)
685 blame_cmp "$testroot" "got_blame.h"
686 ret=$?
687 test_done "$testroot" "$ret"
690 test_blame_added_on_branch() {
691 local testroot=`test_init blame_added_on_branch`
693 got branch -r $testroot/repo -c master newbranch
694 ret=$?
695 if [ $ret -ne 0 ]; then
696 test_done "$testroot" "$ret"
697 return 1
698 fi
700 got checkout -b newbranch $testroot/repo $testroot/wt > /dev/null
701 ret=$?
702 if [ $ret -ne 0 ]; then
703 test_done "$testroot" "$ret"
704 return 1
705 fi
707 echo 1 > $testroot/wt/new
708 (cd $testroot/wt && got add new > /dev/null)
709 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
710 local commit1=`git_show_branch_head $testroot/repo newbranch`
712 echo 2 >> $testroot/wt/new
713 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
714 local commit2=`git_show_branch_head $testroot/repo newbranch`
716 echo 3 >> $testroot/wt/new
717 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
718 local commit3=`git_show_branch_head $testroot/repo newbranch`
719 local author_time=`git_show_author_time $testroot/repo`
721 (cd $testroot/wt && got blame new > $testroot/stdout)
723 local short_commit1=`trim_obj_id 32 $commit1`
724 local short_commit2=`trim_obj_id 32 $commit2`
725 local short_commit3=`trim_obj_id 32 $commit3`
727 d=`date -u -r $author_time +"%G-%m-%d"`
728 echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
729 echo "2) $short_commit2 $d $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
730 echo "3) $short_commit3 $d $GOT_AUTHOR_8 3" >> $testroot/stdout.expected
732 cmp -s $testroot/stdout.expected $testroot/stdout
733 ret=$?
734 if [ $ret -ne 0 ]; then
735 diff -u $testroot/stdout.expected $testroot/stdout
736 fi
737 test_done "$testroot" "$ret"
740 test_blame_submodule() {
741 local testroot=`test_init blame_submodule`
742 local commit_id0=`git_show_head $testroot/repo`
743 local author_time=`git_show_author_time $testroot/repo`
745 make_single_file_repo $testroot/repo2 foo
747 (cd $testroot/repo && git -c protocol.file.allow=always \
748 submodule -q add ../repo2)
749 (cd $testroot/repo && git commit -q -m 'adding submodule')
751 # Attempt a (nonsensical) blame of a submodule.
752 got blame -r $testroot/repo repo2 \
753 > $testroot/stdout 2> $testroot/stderr
754 ret=$?
755 if [ $ret -eq 0 ]; then
756 echo "blame command succeeded unexpectedly" >&2
757 test_done "$testroot" "1"
758 return 1
759 fi
760 local submodule_id=$(got tree -r $testroot/repo -i | \
761 grep 'repo2\$$' | cut -d ' ' -f1)
762 echo "got: object $submodule_id not found" > $testroot/stderr.expected
764 cmp -s $testroot/stderr.expected $testroot/stderr
765 ret=$?
766 if [ $ret -ne 0 ]; then
767 diff -u $testroot/stderr.expected $testroot/stderr
768 fi
769 test_done "$testroot" "$ret"
772 test_blame_symlink() {
773 local testroot=`test_init blame_symlink`
774 local commit_id0=`git_show_head $testroot/repo`
775 local short_commit0=`trim_obj_id 32 $commit_id0`
777 (cd $testroot/repo && ln -s alpha alpha.link)
778 (cd $testroot/repo && ln -s epsilon epsilon.link)
779 (cd $testroot/repo && ln -s /etc/passwd passwd.link)
780 (cd $testroot/repo && ln -s ../beta epsilon/beta.link)
781 (cd $testroot/repo && ln -s nonexistent nonexistent.link)
782 (cd $testroot/repo && git add .)
783 git_commit $testroot/repo -m "add symlinks"
785 local commit_id1=`git_show_head $testroot/repo`
786 local short_commit1=`trim_obj_id 32 $commit_id1`
787 local author_time=`git_show_author_time $testroot/repo`
789 # got blame dereferences symlink to a regular file
790 got blame -r $testroot/repo alpha.link > $testroot/stdout
791 ret=$?
792 if [ $ret -ne 0 ]; then
793 echo "blame command failed unexpectedly" >&2
794 test_done "$testroot" "$ret"
795 return 1
796 fi
798 d=`date -u -r $author_time +"%G-%m-%d"`
799 echo "1) $short_commit0 $d $GOT_AUTHOR_8 alpha" \
800 > $testroot/stdout.expected
802 cmp -s $testroot/stdout.expected $testroot/stdout
803 ret=$?
804 if [ $ret -ne 0 -a "$xfail" = "" ]; then
805 diff -u $testroot/stdout.expected $testroot/stdout
806 test_done "$testroot" "1"
807 return 1
808 fi
810 # got blame dereferences symlink with relative path
811 got blame -r $testroot/repo epsilon/beta.link > $testroot/stdout
812 ret=$?
813 if [ $ret -ne 0 ]; then
814 echo "blame command failed unexpectedly" >&2
815 test_done "$testroot" "$ret"
816 return 1
817 fi
819 d=`date -u -r $author_time +"%G-%m-%d"`
820 echo "1) $short_commit0 $d $GOT_AUTHOR_8 beta" \
821 > $testroot/stdout.expected
823 cmp -s $testroot/stdout.expected $testroot/stdout
824 ret=$?
825 if [ $ret -ne 0 -a "$xfail" = "" ]; then
826 diff -u $testroot/stdout.expected $testroot/stdout
827 test_done "$testroot" "1"
828 return 1
829 fi
831 got blame -r $testroot/repo epsilon.link > $testroot/stdout \
832 2> $testroot/stderr
833 ret=$?
834 if [ $ret -eq 0 ]; then
835 echo "blame command succeeded unexpectedly" >&2
836 test_done "$testroot" "1"
837 return 1
838 fi
840 # blame dereferences symlink to a directory
841 echo "got: /epsilon: wrong type of object" > $testroot/stderr.expected
842 cmp -s $testroot/stderr.expected $testroot/stderr
843 ret=$?
844 if [ $ret -ne 0 ]; then
845 diff -u $testroot/stderr.expected $testroot/stderr
846 test_done "$testroot" "1"
847 return 1
848 fi
850 # got blame fails if symlink target does not exist in repo
851 got blame -r $testroot/repo passwd.link > $testroot/stdout \
852 2> $testroot/stderr
853 ret=$?
854 if [ $ret -eq 0 ]; then
855 echo "blame command succeeded unexpectedly" >&2
856 test_done "$testroot" "1"
857 return 1
858 fi
860 echo "got: /etc/passwd: no such entry found in tree" \
861 > $testroot/stderr.expected
862 cmp -s $testroot/stderr.expected $testroot/stderr
863 ret=$?
864 if [ $ret -ne 0 ]; then
865 diff -u $testroot/stderr.expected $testroot/stderr
866 test_done "$testroot" "1"
867 return 1
868 fi
870 got blame -r $testroot/repo nonexistent.link > $testroot/stdout \
871 2> $testroot/stderr
872 ret=$?
873 if [ $ret -eq 0 ]; then
874 echo "blame command succeeded unexpectedly" >&2
875 test_done "$testroot" "1"
876 return 1
877 fi
879 echo "got: /nonexistent: no such entry found in tree" \
880 > $testroot/stderr.expected
881 cmp -s $testroot/stderr.expected $testroot/stderr
882 ret=$?
883 if [ $ret -ne 0 ]; then
884 diff -u $testroot/stderr.expected $testroot/stderr
885 test_done "$testroot" "1"
886 return 1
887 fi
889 test_done "$testroot" "$ret"
892 test_blame_lines_shifted_skip() {
893 local testroot=`test_init blame_lines_shifted_skip`
895 got checkout $testroot/repo $testroot/wt > /dev/null
896 ret=$?
897 if [ $ret -ne 0 ]; then
898 test_done "$testroot" "$ret"
899 return 1
900 fi
902 cat > $testroot/wt/alpha <<EOF
907 EOF
908 (cd $testroot/wt && got commit -m "change 1" > /dev/null)
909 local commit1=`git_show_head $testroot/repo`
910 local short_commit1=`trim_obj_id 32 $commit1`
911 local author_time1=`git_show_author_time $testroot/repo`
913 cat > $testroot/wt/alpha <<EOF
920 EOF
921 (cd $testroot/wt && got commit -m "change 2" > /dev/null)
922 local commit2=`git_show_head $testroot/repo`
923 local short_commit2=`trim_obj_id 32 $commit2`
924 local author_time2=`git_show_author_time $testroot/repo`
926 cat > $testroot/wt/alpha <<EOF
934 EOF
935 (cd $testroot/wt && got commit -m "change 3" > /dev/null)
936 local commit3=`git_show_head $testroot/repo`
937 local short_commit3=`trim_obj_id 32 $commit3`
938 local author_time3=`git_show_author_time $testroot/repo`
940 cat > $testroot/wt/alpha <<EOF
947 EOF
948 (cd $testroot/wt && got commit -m "change 4" > /dev/null)
949 local commit4=`git_show_head $testroot/repo`
950 local short_commit4=`trim_obj_id 32 $commit4`
951 local author_time4=`git_show_author_time $testroot/repo`
953 cat > $testroot/wt/alpha <<EOF
961 EOF
962 (cd $testroot/wt && got commit -m "change 5" > /dev/null)
963 local commit5=`git_show_head $testroot/repo`
964 local short_commit5=`trim_obj_id 32 $commit5`
965 local author_time5=`git_show_author_time $testroot/repo`
967 (cd $testroot/wt && got blame alpha > $testroot/stdout)
969 d1=`date -u -r $author_time1 +"%G-%m-%d"`
970 d2=`date -u -r $author_time2 +"%G-%m-%d"`
971 d4=`date -u -r $author_time4 +"%G-%m-%d"`
972 d5=`date -u -r $author_time5 +"%G-%m-%d"`
973 echo "1) $short_commit5 $d5 $GOT_AUTHOR_8 X" > $testroot/stdout.expected
974 echo "2) $short_commit1 $d1 $GOT_AUTHOR_8 A" >> $testroot/stdout.expected
975 echo "3) $short_commit1 $d1 $GOT_AUTHOR_8 B" >> $testroot/stdout.expected
976 echo "4) $short_commit1 $d1 $GOT_AUTHOR_8 C" >> $testroot/stdout.expected
977 echo "5) $short_commit2 $d2 $GOT_AUTHOR_8 P" >> $testroot/stdout.expected
978 echo "6) $short_commit4 $d4 $GOT_AUTHOR_8 Y" >> $testroot/stdout.expected
979 echo "7) $short_commit2 $d5 $GOT_AUTHOR_8 Q" >> $testroot/stdout.expected
981 cmp -s $testroot/stdout.expected $testroot/stdout
982 ret=$?
983 if [ $ret -ne 0 ]; then
984 diff -u $testroot/stdout.expected $testroot/stdout
985 test_done "$testroot" "$ret"
986 return 1
987 fi
989 blame_cmp "$testroot" "alpha"
990 ret=$?
991 test_done "$testroot" "$ret"
994 test_parseargs "$@"
995 run_test test_blame_basic
996 run_test test_blame_tag
997 run_test test_blame_file_single_line
998 run_test test_blame_file_single_line_no_newline
999 run_test test_blame_all_lines_replaced
1000 run_test test_blame_lines_shifted_up
1001 run_test test_blame_lines_shifted_down
1002 run_test test_blame_commit_subsumed
1003 run_test test_blame_blame_h
1004 run_test test_blame_added_on_branch
1005 run_test test_blame_submodule
1006 run_test test_blame_symlink
1007 run_test test_blame_lines_shifted_skip