comparison tests/test-log-linerange.t @ 34857:84c6b9384d6a

log: add -L/--line-range option to follow file history by line range We add an experimental -L/--line-range option to 'hg log' taking file patterns along with a line range using the (new) FILE,FROMLINE-TOLINE syntax where FILE may be a pattern (matching exactly one file). The resulting history is similar to what the "followlines" revset except that, if --patch is specified, only diff hunks within specified line range are shown. Basically, this brings the CLI on par with what currently only exists in hgweb through line selection in "file" and "annotate" views resulting in a file log with filtered patch to only display followed line range. The option may be specified multiple times and can be combined with --rev and regular file patterns to further restrict revisions. Usage of this option requires --follow; revisions are shown in descending order and renames are followed. Only the --graph option is currently not supported. The UI is the result of a consensus from review feedback at: https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-October/106749.html The implementation spreads between commands.log() and cmdutil module. In commands.log(), the main loop may now use a "hunksfilter" factory (similar to "filematcher") that, for a given "rev", produces a filtering function for diff hunks for a given file context object. The logic to build revisions from -L/--line-range options lives in cmdutil.getloglinerangerevs() which produces "revs", "filematcher" and "hunksfilter" information. Revisions obtained by following files' line range are filtered if they do not match the revset specified by --rev option. If regular FILE arguments are passed along with -L options, both filematchers are combined into a new matcher. .. feature:: Add an experimental -L/--line-range FILE,FROMLINE-TOLINE option to 'hg log' command to follow the history of files by line range. In combination with -p/--patch option, only diff hunks within specified line range will be displayed. Feedback, especially on UX aspects, is welcome.
author Denis Laxalde <denis.laxalde@logilab.fr>
date Tue, 17 Oct 2017 21:15:31 +0200
parents
children 4554649a6ea4
comparison
equal deleted inserted replaced
34856:890afefa7296 34857:84c6b9384d6a
1 $ cat >> $HGRCPATH << EOF
2 > [diff]
3 > git = true
4 > EOF
5
6 $ hg init
7 $ cat > foo << EOF
8 > 0
9 > 1
10 > 2
11 > 3
12 > 4
13 > EOF
14 $ hg ci -Am init
15 adding foo
16 $ cat > foo << EOF
17 > 0
18 > 0
19 > 0
20 > 0
21 > 1
22 > 2
23 > 3
24 > 4
25 > EOF
26 $ hg ci -m 'more 0'
27 $ sed 's/2/2+/' foo > foo.new
28 $ mv foo.new foo
29 $ cat > bar << EOF
30 > a
31 > b
32 > c
33 > d
34 > e
35 > EOF
36 $ hg add bar
37 $ hg ci -Am "2 -> 2+; added bar"
38 $ cat >> foo << EOF
39 > 5
40 > 6
41 > 7
42 > 8
43 > 9
44 > 10
45 > 11
46 > EOF
47 $ hg ci -m "to 11"
48
49 Add some changes with two diff hunks
50
51 $ sed 's/^1$/ 1/' foo > foo.new
52 $ mv foo.new foo
53 $ sed 's/^11$/11+/' foo > foo.new
54 $ mv foo.new foo
55 $ hg ci -m '11 -> 11+; leading space before "1"'
56 (make sure there are two hunks in "foo")
57 $ hg diff -c .
58 diff --git a/foo b/foo
59 --- a/foo
60 +++ b/foo
61 @@ -2,7 +2,7 @@
62 0
63 0
64 0
65 -1
66 + 1
67 2+
68 3
69 4
70 @@ -12,4 +12,4 @@
71 8
72 9
73 10
74 -11
75 +11+
76 $ sed 's/3/3+/' foo > foo.new
77 $ mv foo.new foo
78 $ sed 's/^11+$/11-/' foo > foo.new
79 $ mv foo.new foo
80 $ sed 's/a/a+/' bar > bar.new
81 $ mv bar.new bar
82 $ hg ci -m 'foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+'
83 (make sure there are two hunks in "foo")
84 $ hg diff -c . foo
85 diff --git a/foo b/foo
86 --- a/foo
87 +++ b/foo
88 @@ -4,7 +4,7 @@
89 0
90 1
91 2+
92 -3
93 +3+
94 4
95 5
96 6
97 @@ -12,4 +12,4 @@
98 8
99 9
100 10
101 -11+
102 +11-
103
104 $ hg log -f -L foo,5-7 -p
105 changeset: 5:cfdf972b3971
106 tag: tip
107 user: test
108 date: Thu Jan 01 00:00:00 1970 +0000
109 summary: foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
110
111 diff --git a/foo b/foo
112 --- a/foo
113 +++ b/foo
114 @@ -4,7 +4,7 @@
115 0
116 1
117 2+
118 -3
119 +3+
120 4
121 5
122 6
123
124 changeset: 4:eaec41c1a0c9
125 user: test
126 date: Thu Jan 01 00:00:00 1970 +0000
127 summary: 11 -> 11+; leading space before "1"
128
129 diff --git a/foo b/foo
130 --- a/foo
131 +++ b/foo
132 @@ -2,7 +2,7 @@
133 0
134 0
135 0
136 -1
137 + 1
138 2+
139 3
140 4
141
142 changeset: 2:63a884426fd0
143 user: test
144 date: Thu Jan 01 00:00:00 1970 +0000
145 summary: 2 -> 2+; added bar
146
147 diff --git a/foo b/foo
148 --- a/foo
149 +++ b/foo
150 @@ -3,6 +3,6 @@
151 0
152 0
153 1
154 -2
155 +2+
156 3
157 4
158
159 changeset: 0:5ae1f82b9a00
160 user: test
161 date: Thu Jan 01 00:00:00 1970 +0000
162 summary: init
163
164 diff --git a/foo b/foo
165 new file mode 100644
166 --- /dev/null
167 +++ b/foo
168 @@ -0,0 +1,5 @@
169 +0
170 +1
171 +2
172 +3
173 +4
174
175
176 With --template.
177
178 $ hg log -f -L foo,5-7 -T '{rev}:{node|short} {desc|firstline}\n'
179 5:cfdf972b3971 foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
180 4:eaec41c1a0c9 11 -> 11+; leading space before "1"
181 2:63a884426fd0 2 -> 2+; added bar
182 0:5ae1f82b9a00 init
183 $ hg log -f -L foo,5-7 -T json
184 [
185 {
186 "rev": 5,
187 "node": "cfdf972b3971a2a59638bf9583c0debbffee5404",
188 "branch": "default",
189 "phase": "draft",
190 "user": "test",
191 "date": [0, 0],
192 "desc": "foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+",
193 "bookmarks": [],
194 "tags": ["tip"],
195 "parents": ["eaec41c1a0c9ad0a5e999611d0149d171beffb8c"]
196 },
197 {
198 "rev": 4,
199 "node": "eaec41c1a0c9ad0a5e999611d0149d171beffb8c",
200 "branch": "default",
201 "phase": "draft",
202 "user": "test",
203 "date": [0, 0],
204 "desc": "11 -> 11+; leading space before \"1\"",
205 "bookmarks": [],
206 "tags": [],
207 "parents": ["730a61fbaecf426c17c2c66bc42d195b5d5b0ba8"]
208 },
209 {
210 "rev": 2,
211 "node": "63a884426fd0b277fcd55895bbb2f230434576eb",
212 "branch": "default",
213 "phase": "draft",
214 "user": "test",
215 "date": [0, 0],
216 "desc": "2 -> 2+; added bar",
217 "bookmarks": [],
218 "tags": [],
219 "parents": ["29a1e7c6b80024f63f310a2d71de979e9d2996d7"]
220 },
221 {
222 "rev": 0,
223 "node": "5ae1f82b9a000ff1e0967d0dac1c58b9d796e1b4",
224 "branch": "default",
225 "phase": "draft",
226 "user": "test",
227 "date": [0, 0],
228 "desc": "init",
229 "bookmarks": [],
230 "tags": [],
231 "parents": ["0000000000000000000000000000000000000000"]
232 }
233 ]
234
235 With some white-space diff option, respective revisions are skipped.
236
237 $ hg log -f -L foo,5-7 -p --config diff.ignorews=true
238 changeset: 5:cfdf972b3971
239 tag: tip
240 user: test
241 date: Thu Jan 01 00:00:00 1970 +0000
242 summary: foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
243
244 diff --git a/foo b/foo
245 --- a/foo
246 +++ b/foo
247 @@ -4,7 +4,7 @@
248 0
249 1
250 2+
251 -3
252 +3+
253 4
254 5
255 6
256
257 changeset: 2:63a884426fd0
258 user: test
259 date: Thu Jan 01 00:00:00 1970 +0000
260 summary: 2 -> 2+; added bar
261
262 diff --git a/foo b/foo
263 --- a/foo
264 +++ b/foo
265 @@ -3,6 +3,6 @@
266 0
267 0
268 1
269 -2
270 +2+
271 3
272 4
273
274 changeset: 0:5ae1f82b9a00
275 user: test
276 date: Thu Jan 01 00:00:00 1970 +0000
277 summary: init
278
279 diff --git a/foo b/foo
280 new file mode 100644
281 --- /dev/null
282 +++ b/foo
283 @@ -0,0 +1,5 @@
284 +0
285 +1
286 +2
287 +3
288 +4
289
290
291 Regular file patterns are allowed with -L and their diff shows all lines.
292
293 $ hg log -f -L foo,5-7 -p bar
294 changeset: 5:cfdf972b3971
295 tag: tip
296 user: test
297 date: Thu Jan 01 00:00:00 1970 +0000
298 summary: foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
299
300 diff --git a/bar b/bar
301 --- a/bar
302 +++ b/bar
303 @@ -1,4 +1,4 @@
304 -a
305 +a+
306 b
307 c
308 d
309 diff --git a/foo b/foo
310 --- a/foo
311 +++ b/foo
312 @@ -4,7 +4,7 @@
313 0
314 1
315 2+
316 -3
317 +3+
318 4
319 5
320 6
321
322 changeset: 2:63a884426fd0
323 user: test
324 date: Thu Jan 01 00:00:00 1970 +0000
325 summary: 2 -> 2+; added bar
326
327 diff --git a/bar b/bar
328 new file mode 100644
329 --- /dev/null
330 +++ b/bar
331 @@ -0,0 +1,5 @@
332 +a
333 +b
334 +c
335 +d
336 +e
337 diff --git a/foo b/foo
338 --- a/foo
339 +++ b/foo
340 @@ -3,6 +3,6 @@
341 0
342 0
343 1
344 -2
345 +2+
346 3
347 4
348
349
350 Option --rev acts as a restriction.
351
352 $ hg log -f -L foo,5-7 -p -r 'desc(2)'
353 changeset: 2:63a884426fd0
354 user: test
355 date: Thu Jan 01 00:00:00 1970 +0000
356 summary: 2 -> 2+; added bar
357
358 diff --git a/foo b/foo
359 --- a/foo
360 +++ b/foo
361 @@ -3,6 +3,6 @@
362 0
363 0
364 1
365 -2
366 +2+
367 3
368 4
369
370 changeset: 0:5ae1f82b9a00
371 user: test
372 date: Thu Jan 01 00:00:00 1970 +0000
373 summary: init
374
375 diff --git a/foo b/foo
376 new file mode 100644
377 --- /dev/null
378 +++ b/foo
379 @@ -0,0 +1,5 @@
380 +0
381 +1
382 +2
383 +3
384 +4
385
386
387 With several -L patterns, changes touching any files in their respective line
388 range are show.
389
390 $ hg log -f -L foo,5-7 -L bar,1-2 -p
391 changeset: 5:cfdf972b3971
392 tag: tip
393 user: test
394 date: Thu Jan 01 00:00:00 1970 +0000
395 summary: foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
396
397 diff --git a/bar b/bar
398 --- a/bar
399 +++ b/bar
400 @@ -1,4 +1,4 @@
401 -a
402 +a+
403 b
404 c
405 d
406 diff --git a/foo b/foo
407 --- a/foo
408 +++ b/foo
409 @@ -4,7 +4,7 @@
410 0
411 1
412 2+
413 -3
414 +3+
415 4
416 5
417 6
418
419 changeset: 4:eaec41c1a0c9
420 user: test
421 date: Thu Jan 01 00:00:00 1970 +0000
422 summary: 11 -> 11+; leading space before "1"
423
424 diff --git a/foo b/foo
425 --- a/foo
426 +++ b/foo
427 @@ -2,7 +2,7 @@
428 0
429 0
430 0
431 -1
432 + 1
433 2+
434 3
435 4
436
437 changeset: 2:63a884426fd0
438 user: test
439 date: Thu Jan 01 00:00:00 1970 +0000
440 summary: 2 -> 2+; added bar
441
442 diff --git a/bar b/bar
443 new file mode 100644
444 --- /dev/null
445 +++ b/bar
446 @@ -0,0 +1,5 @@
447 +a
448 +b
449 +c
450 +d
451 +e
452 diff --git a/foo b/foo
453 --- a/foo
454 +++ b/foo
455 @@ -3,6 +3,6 @@
456 0
457 0
458 1
459 -2
460 +2+
461 3
462 4
463
464 changeset: 0:5ae1f82b9a00
465 user: test
466 date: Thu Jan 01 00:00:00 1970 +0000
467 summary: init
468
469 diff --git a/foo b/foo
470 new file mode 100644
471 --- /dev/null
472 +++ b/foo
473 @@ -0,0 +1,5 @@
474 +0
475 +1
476 +2
477 +3
478 +4
479
480
481 Multiple -L options with the same file yields changes touching any of
482 specified line ranges.
483
484 $ hg log -f -L foo,5-7 -L foo,14-15 -p
485 changeset: 5:cfdf972b3971
486 tag: tip
487 user: test
488 date: Thu Jan 01 00:00:00 1970 +0000
489 summary: foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
490
491 diff --git a/foo b/foo
492 --- a/foo
493 +++ b/foo
494 @@ -4,7 +4,7 @@
495 0
496 1
497 2+
498 -3
499 +3+
500 4
501 5
502 6
503 @@ -12,4 +12,4 @@
504 8
505 9
506 10
507 -11+
508 +11-
509
510 changeset: 4:eaec41c1a0c9
511 user: test
512 date: Thu Jan 01 00:00:00 1970 +0000
513 summary: 11 -> 11+; leading space before "1"
514
515 diff --git a/foo b/foo
516 --- a/foo
517 +++ b/foo
518 @@ -2,7 +2,7 @@
519 0
520 0
521 0
522 -1
523 + 1
524 2+
525 3
526 4
527 @@ -12,4 +12,4 @@
528 8
529 9
530 10
531 -11
532 +11+
533
534 changeset: 3:730a61fbaecf
535 user: test
536 date: Thu Jan 01 00:00:00 1970 +0000
537 summary: to 11
538
539 diff --git a/foo b/foo
540 --- a/foo
541 +++ b/foo
542 @@ -6,3 +6,10 @@
543 2+
544 3
545 4
546 +5
547 +6
548 +7
549 +8
550 +9
551 +10
552 +11
553
554 changeset: 2:63a884426fd0
555 user: test
556 date: Thu Jan 01 00:00:00 1970 +0000
557 summary: 2 -> 2+; added bar
558
559 diff --git a/foo b/foo
560 --- a/foo
561 +++ b/foo
562 @@ -3,6 +3,6 @@
563 0
564 0
565 1
566 -2
567 +2+
568 3
569 4
570
571 changeset: 0:5ae1f82b9a00
572 user: test
573 date: Thu Jan 01 00:00:00 1970 +0000
574 summary: init
575
576 diff --git a/foo b/foo
577 new file mode 100644
578 --- /dev/null
579 +++ b/foo
580 @@ -0,0 +1,5 @@
581 +0
582 +1
583 +2
584 +3
585 +4
586
587
588 A file with a comma in its name.
589
590 $ cat > ba,z << EOF
591 > q
592 > w
593 > e
594 > r
595 > t
596 > y
597 > EOF
598 $ hg ci -Am 'querty'
599 adding ba,z
600 $ cat >> ba,z << EOF
601 > u
602 > i
603 > o
604 > p
605 > EOF
606 $ hg ci -m 'more keys'
607 $ cat > ba,z << EOF
608 > a
609 > z
610 > e
611 > r
612 > t
613 > y
614 > u
615 > i
616 > o
617 > p
618 > EOF
619 $ hg ci -m 'azerty'
620 $ hg log -f -L ba,z,1-2 -p
621 changeset: 8:52373265138b
622 tag: tip
623 user: test
624 date: Thu Jan 01 00:00:00 1970 +0000
625 summary: azerty
626
627 diff --git a/ba,z b/ba,z
628 --- a/ba,z
629 +++ b/ba,z
630 @@ -1,5 +1,5 @@
631 -q
632 -w
633 +a
634 +z
635 e
636 r
637 t
638
639 changeset: 6:96ba8850f316
640 user: test
641 date: Thu Jan 01 00:00:00 1970 +0000
642 summary: querty
643
644 diff --git a/ba,z b/ba,z
645 new file mode 100644
646 --- /dev/null
647 +++ b/ba,z
648 @@ -0,0 +1,6 @@
649 +q
650 +w
651 +e
652 +r
653 +t
654 +y
655
656
657 Exact prefix kinds work in -L options.
658
659 $ mkdir dir
660 $ cd dir
661 $ hg log -f -L path:foo,5-7 -p
662 changeset: 5:cfdf972b3971
663 user: test
664 date: Thu Jan 01 00:00:00 1970 +0000
665 summary: foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
666
667 diff --git a/foo b/foo
668 --- a/foo
669 +++ b/foo
670 @@ -4,7 +4,7 @@
671 0
672 1
673 2+
674 -3
675 +3+
676 4
677 5
678 6
679
680 changeset: 4:eaec41c1a0c9
681 user: test
682 date: Thu Jan 01 00:00:00 1970 +0000
683 summary: 11 -> 11+; leading space before "1"
684
685 diff --git a/foo b/foo
686 --- a/foo
687 +++ b/foo
688 @@ -2,7 +2,7 @@
689 0
690 0
691 0
692 -1
693 + 1
694 2+
695 3
696 4
697
698 changeset: 2:63a884426fd0
699 user: test
700 date: Thu Jan 01 00:00:00 1970 +0000
701 summary: 2 -> 2+; added bar
702
703 diff --git a/foo b/foo
704 --- a/foo
705 +++ b/foo
706 @@ -3,6 +3,6 @@
707 0
708 0
709 1
710 -2
711 +2+
712 3
713 4
714
715 changeset: 0:5ae1f82b9a00
716 user: test
717 date: Thu Jan 01 00:00:00 1970 +0000
718 summary: init
719
720 diff --git a/foo b/foo
721 new file mode 100644
722 --- /dev/null
723 +++ b/foo
724 @@ -0,0 +1,5 @@
725 +0
726 +1
727 +2
728 +3
729 +4
730
731
732 Renames are followed.
733
734 $ hg mv ../foo baz
735 $ sed 's/1/1+/' baz > baz.new
736 $ mv baz.new baz
737 $ hg ci -m 'foo -> dir/baz; 1-1+'
738 $ hg diff -c .
739 diff --git a/foo b/dir/baz
740 rename from foo
741 rename to dir/baz
742 --- a/foo
743 +++ b/dir/baz
744 @@ -2,7 +2,7 @@
745 0
746 0
747 0
748 - 1
749 + 1+
750 2+
751 3+
752 4
753 @@ -11,5 +11,5 @@
754 7
755 8
756 9
757 -10
758 -11-
759 +1+0
760 +1+1-
761 $ hg log -f -L relpath:baz,5-7 -p
762 changeset: 9:6af29c3a778f
763 tag: tip
764 user: test
765 date: Thu Jan 01 00:00:00 1970 +0000
766 summary: foo -> dir/baz; 1-1+
767
768 diff --git a/foo b/dir/baz
769 copy from foo
770 copy to dir/baz
771 --- a/foo
772 +++ b/dir/baz
773 @@ -2,7 +2,7 @@
774 0
775 0
776 0
777 - 1
778 + 1+
779 2+
780 3+
781 4
782
783 changeset: 5:cfdf972b3971
784 user: test
785 date: Thu Jan 01 00:00:00 1970 +0000
786 summary: foo: 3 -> 3+ and 11+ -> 11-; bar: a -> a+
787
788 diff --git a/foo b/foo
789 --- a/foo
790 +++ b/foo
791 @@ -4,7 +4,7 @@
792 0
793 1
794 2+
795 -3
796 +3+
797 4
798 5
799 6
800
801 changeset: 4:eaec41c1a0c9
802 user: test
803 date: Thu Jan 01 00:00:00 1970 +0000
804 summary: 11 -> 11+; leading space before "1"
805
806 diff --git a/foo b/foo
807 --- a/foo
808 +++ b/foo
809 @@ -2,7 +2,7 @@
810 0
811 0
812 0
813 -1
814 + 1
815 2+
816 3
817 4
818
819 changeset: 2:63a884426fd0
820 user: test
821 date: Thu Jan 01 00:00:00 1970 +0000
822 summary: 2 -> 2+; added bar
823
824 diff --git a/foo b/foo
825 --- a/foo
826 +++ b/foo
827 @@ -3,6 +3,6 @@
828 0
829 0
830 1
831 -2
832 +2+
833 3
834 4
835
836 changeset: 0:5ae1f82b9a00
837 user: test
838 date: Thu Jan 01 00:00:00 1970 +0000
839 summary: init
840
841 diff --git a/foo b/foo
842 new file mode 100644
843 --- /dev/null
844 +++ b/foo
845 @@ -0,0 +1,5 @@
846 +0
847 +1
848 +2
849 +3
850 +4
851
852 Option --follow is required.
853
854 $ hg log -L foo,5-7
855 abort: --line-range requires --follow
856 [255]
857
858 Non-exact pattern kinds are not allowed.
859
860 $ cd ..
861 $ hg log -f -L glob:*a*,1-2
862 hg: parse error: line range pattern 'glob:*a*' must match exactly one file
863 [255]
864
865 Graph log does work yet.
866
867 $ hg log -f -L dir/baz,5-7 --graph
868 abort: graph not supported with line range patterns
869 [255]