3 test_description='ignore revisions when blaming'
8 # A added line 1 and B added line 2. X makes changes to those lines. Sanity
9 # check that X is blamed for both lines.
10 test_expect_success setup '
11 test_commit A file line1 &&
19 test_write_lines line-one line-two >file &&
25 git blame --line-porcelain file >blame_raw &&
27 grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
28 git rev-parse X >expect &&
29 test_cmp expect actual &&
31 grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
32 git rev-parse X >expect &&
33 test_cmp expect actual
36 # Ignore X, make sure A is blamed for line 1 and B for line 2.
37 test_expect_success ignore_rev_changing_lines '
38 git blame --line-porcelain --ignore-rev X file >blame_raw &&
40 grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
41 git rev-parse A >expect &&
42 test_cmp expect actual &&
44 grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
45 git rev-parse B >expect &&
46 test_cmp expect actual
49 # For ignored revs that have added 'unblamable' lines, attribute those to the
52 # Where Y changes lines 1 and 2, and adds lines 3 and 4. The added lines ought
53 # to have nothing in common with "line-one" or "line-two", to keep any
54 # heuristics from matching them with any lines in the parent.
55 test_expect_success ignore_rev_adding_unblamable_lines '
56 test_write_lines line-one-change line-two-changed y3 y4 >file &&
62 git rev-parse Y >expect &&
63 git blame --line-porcelain file --ignore-rev Y >blame_raw &&
65 grep -E "^[0-9a-f]+ [0-9]+ 3" blame_raw | sed -e "s/ .*//" >actual &&
66 test_cmp expect actual &&
68 grep -E "^[0-9a-f]+ [0-9]+ 4" blame_raw | sed -e "s/ .*//" >actual &&
69 test_cmp expect actual
72 # Ignore X and Y, both in separate files. Lines 1 == A, 2 == B.
73 test_expect_success ignore_revs_from_files '
74 git rev-parse X >ignore_x &&
75 git rev-parse Y >ignore_y &&
76 git blame --line-porcelain file --ignore-revs-file ignore_x --ignore-revs-file ignore_y >blame_raw &&
78 grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
79 git rev-parse A >expect &&
80 test_cmp expect actual &&
82 grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
83 git rev-parse B >expect &&
84 test_cmp expect actual
87 # Ignore X from the config option, Y from a file.
88 test_expect_success ignore_revs_from_configs_and_files '
89 git config --add blame.ignoreRevsFile ignore_x &&
90 git blame --line-porcelain file --ignore-revs-file ignore_y >blame_raw &&
92 grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
93 git rev-parse A >expect &&
94 test_cmp expect actual &&
96 grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
97 git rev-parse B >expect &&
98 test_cmp expect actual
101 # Override blame.ignoreRevsFile (ignore_x) with an empty string. X should be
102 # blamed now for lines 1 and 2, since we are no longer ignoring X.
103 test_expect_success override_ignore_revs_file '
104 git blame --line-porcelain file --ignore-revs-file "" --ignore-revs-file ignore_y >blame_raw &&
105 git rev-parse X >expect &&
107 grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
108 test_cmp expect actual &&
110 grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
111 test_cmp expect actual
113 test_expect_success bad_files_and_revs '
114 test_must_fail git blame file --ignore-rev NOREV 2>err &&
115 test_i18ngrep "cannot find revision NOREV to ignore" err &&
117 test_must_fail git blame file --ignore-revs-file NOFILE 2>err &&
118 test_i18ngrep "could not open.*: NOFILE" err &&
120 echo NOREV >ignore_norev &&
121 test_must_fail git blame file --ignore-revs-file ignore_norev 2>err &&
122 test_i18ngrep "invalid object name: NOREV" err
125 # For ignored revs that have added 'unblamable' lines, mark those lines with a
128 # Lines 3 and 4 are from Y and unblamable. This was set up in
129 # ignore_rev_adding_unblamable_lines.
130 test_expect_success mark_unblamable_lines '
131 git config --add blame.markUnblamableLines true &&
133 git blame --ignore-rev Y file >blame_raw &&
136 sed -n "3p" blame_raw | cut -c1 >actual &&
137 test_cmp expect actual &&
139 sed -n "4p" blame_raw | cut -c1 >actual &&
140 test_cmp expect actual
143 # Commit Z will touch the first two lines. Y touched all four.
145 # The blame output when ignoring Z should be:
150 # We're checking only the first character
151 test_expect_success mark_ignored_lines '
152 git config --add blame.markIgnoredLines true &&
154 test_write_lines line-one-Z line-two-Z y3 y4 >file &&
160 git blame --ignore-rev Z file >blame_raw &&
163 sed -n "1p" blame_raw | cut -c1 >actual &&
164 test_cmp expect actual &&
166 sed -n "2p" blame_raw | cut -c1 >actual &&
167 test_cmp expect actual &&
169 sed -n "3p" blame_raw | cut -c1 >actual &&
170 ! test_cmp expect actual &&
172 sed -n "4p" blame_raw | cut -c1 >actual &&
173 ! test_cmp expect actual
176 # For ignored revs that added 'unblamable' lines and more recent commits changed
177 # the blamable lines, mark the unblamable lines with a
180 # Lines 3 and 4 are from Y and unblamable, as set up in
181 # ignore_rev_adding_unblamable_lines. Z changed lines 1 and 2.
182 test_expect_success mark_unblamable_lines_intermediate '
183 git config --add blame.markUnblamableLines true &&
185 git blame --ignore-rev Y file >blame_raw 2>stderr &&
188 sed -n "3p" blame_raw | cut -c1 >actual &&
189 test_cmp expect actual &&
191 sed -n "4p" blame_raw | cut -c1 >actual &&
192 test_cmp expect actual
195 # The heuristic called by guess_line_blames() tries to find the size of a
196 # blame_entry 'e' in the parent's address space. Those calculations need to
197 # check for negative or zero values for when a blame entry is completely outside
198 # the window of the parent's version of a file.
200 # This happens when one commit adds several lines (commit B below). A later
201 # commit (C) changes one line in the middle of B's change. Commit C gets blamed
202 # for its change, and that breaks up B's change into multiple blame entries.
203 # When processing B, one of the blame_entries is outside A's window (which was
204 # zero - it had no lines added on its side of the diff).
206 # A--B--C, ignore B to test the ignore heuristic's boundary checks.
207 test_expect_success ignored_chunk_negative_parent_size '
211 test_write_lines L1 L2 L7 L8 L9 >file &&
217 test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file &&
223 test_write_lines L1 L2 L3 L4 xxx L6 L7 L8 L9 >file &&
229 git blame file --ignore-rev B >blame_raw
232 # Resetting the repo and creating:
238 # 'A' creates a file. B changes line 1, and C changes line 9. M merges.
239 test_expect_success ignore_merge '
243 test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file &&
249 test_write_lines BB L2 L3 L4 L5 L6 L7 L8 L9 >file &&
255 git reset --hard A &&
256 test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 CC >file &&
263 git blame --line-porcelain file --ignore-rev M >blame_raw &&
265 grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
266 git rev-parse B >expect &&
267 test_cmp expect actual &&
269 grep -E "^[0-9a-f]+ [0-9]+ 9" blame_raw | sed -e "s/ .*//" >actual &&
270 git rev-parse C >expect &&
271 test_cmp expect actual