Raw
1 #!/bin/sh
2
3 test_description='git blame corner cases'
4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
6
7 . ./test-lib.sh
8
9 pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/'
10
11 test_expect_success setup '
12 echo A A A A A >one &&
13 echo B B B B B >two &&
14 echo C C C C C >tres &&
15 echo ABC >mouse &&
16 test_write_lines 1 2 3 4 5 6 7 8 9 >nine_lines &&
17 test_write_lines 1 2 3 4 5 6 7 8 9 a >ten_lines &&
18 git add one two tres mouse nine_lines ten_lines &&
19 test_tick &&
20 GIT_AUTHOR_NAME=Initial git commit -m Initial &&
21
22 cat one >uno &&
23 mv two dos &&
24 cat one >>tres &&
25 echo DEF >>mouse &&
26 git add uno dos tres mouse &&
27 test_tick &&
28 GIT_AUTHOR_NAME=Second git commit -a -m Second &&
29
30 echo GHIJK >>mouse &&
31 git add mouse &&
32 test_tick &&
33 GIT_AUTHOR_NAME=Third git commit -m Third &&
34
35 cat mouse >cow &&
36 git add cow &&
37 test_tick &&
38 GIT_AUTHOR_NAME=Fourth git commit -m Fourth &&
39
40 cat >cow <<-\EOF &&
41 ABC
42 DEF
43 XXXX
44 GHIJK
45 EOF
46 git add cow &&
47 test_tick &&
48 GIT_AUTHOR_NAME=Fifth git commit -m Fifth
49 '
50
51 test_expect_success 'straight copy without -C' '
52 git blame uno >actual &&
53 test_grep Second actual
54 '
55
56 test_expect_success 'straight move without -C' '
57 git blame dos >actual &&
58 test_grep Initial actual
59 '
60
61 test_expect_success 'straight copy with -C' '
62 git blame -C1 uno >actual &&
63 test_grep Second actual
64 '
65
66 test_expect_success 'straight move with -C' '
67 git blame -C1 dos >actual &&
68 test_grep Initial actual
69 '
70
71 test_expect_success 'straight copy with -C -C' '
72 git blame -C -C1 uno >actual &&
73 test_grep Initial actual
74 '
75
76 test_expect_success 'straight move with -C -C' '
77 git blame -C -C1 dos >actual &&
78 test_grep Initial actual
79 '
80
81 test_expect_success 'append without -C' '
82 git blame -L2 tres >actual &&
83 test_grep Second actual
84 '
85
86 test_expect_success 'append with -C' '
87 git blame -L2 -C1 tres >actual &&
88 test_grep Second actual
89 '
90
91 test_expect_success 'append with -C -C' '
92 git blame -L2 -C -C1 tres >actual &&
93 test_grep Second actual
94 '
95
96 test_expect_success 'append with -C -C -C' '
97 git blame -L2 -C -C -C1 tres >actual &&
98 test_grep Initial actual
99 '
100
101 test_expect_success 'blame wholesale copy' '
102 git blame -f -C -C1 HEAD^ -- cow >actual &&
103 sed -e "$pick_fc" actual >current &&
104 cat >expected <<-\EOF &&
105 mouse-Initial
106 mouse-Second
107 mouse-Third
108 EOF
109 test_cmp expected current
110 '
111
112 test_expect_success 'blame wholesale copy and more' '
113 git blame -f -C -C1 HEAD -- cow >actual &&
114 sed -e "$pick_fc" actual >current &&
115 cat >expected <<-\EOF &&
116 mouse-Initial
117 mouse-Second
118 cow-Fifth
119 mouse-Third
120 EOF
121 test_cmp expected current
122 '
123
124 test_expect_success 'blame wholesale copy and more in the index' '
125 cat >horse <<-\EOF &&
126 ABC
127 DEF
128 XXXX
129 YYYY
130 GHIJK
131 EOF
132 git add horse &&
133 test_when_finished "git rm -f horse" &&
134 git blame -f -C -C1 -- horse >actual &&
135 sed -e "$pick_fc" actual >current &&
136 cat >expected <<-\EOF &&
137 mouse-Initial
138 mouse-Second
139 cow-Fifth
140 horse-Not
141 mouse-Third
142 EOF
143 test_cmp expected current
144 '
145
146 test_expect_success 'blame during cherry-pick with file rename conflict' '
147 test_when_finished "git reset --hard && git checkout main" &&
148 git checkout HEAD~3 &&
149 echo MOUSE >> mouse &&
150 git mv mouse rodent &&
151 git add rodent &&
152 GIT_AUTHOR_NAME=Rodent git commit -m "rodent" &&
153 git checkout --detach main &&
154 (git cherry-pick HEAD@{1} || test $? -eq 1) &&
155 git show HEAD@{1}:rodent > rodent &&
156 git add rodent &&
157 git blame -f -C -C1 rodent >actual &&
158 sed -e "$pick_fc" actual >current &&
159 cat >expected <<-\EOF &&
160 mouse-Initial
161 mouse-Second
162 rodent-Not
163 EOF
164 test_cmp expected current
165 '
166
167 test_expect_success 'blame path that used to be a directory' '
168 mkdir path &&
169 echo A A A A A >path/file &&
170 echo B B B B B >path/elif &&
171 git add path &&
172 test_tick &&
173 git commit -m "path was a directory" &&
174 rm -fr path &&
175 echo A A A A A >path &&
176 git add path &&
177 test_tick &&
178 git commit -m "path is a regular file" &&
179 git blame HEAD^.. -- path
180 '
181
182 test_expect_success 'blame to a commit with no author name' '
183 TREE=$(git rev-parse HEAD:) &&
184 cat >badcommit <<EOF &&
185 tree $TREE
186 author <noname> 1234567890 +0000
187 committer David Reiss <dreiss@facebook.com> 1234567890 +0000
188
189 some message
190 EOF
191 COMMIT=$(git hash-object --literally -t commit -w badcommit) &&
192 git --no-pager blame $COMMIT -- uno >/dev/null
193 '
194
195 test_expect_success 'blame -L with invalid start' '
196 test_must_fail git blame -L5 tres 2>errors &&
197 test_grep "has only 2 lines" errors
198 '
199
200 test_expect_success 'blame -L with invalid end' '
201 git blame -L1,5 tres >out &&
202 test_line_count = 2 out
203 '
204
205 test_expect_success 'blame parses <end> part of -L' '
206 git blame -L1,1 tres >out &&
207 test_line_count = 1 out
208 '
209
210 test_expect_success 'blame -Ln,-(n+1)' '
211 git blame -L3,-4 nine_lines >out &&
212 test_line_count = 3 out
213 '
214
215 test_expect_success 'indent of line numbers, nine lines' '
216 git blame nine_lines >actual &&
217 test $(grep -c " " actual) = 0
218 '
219
220 test_expect_success 'indent of line numbers, ten lines' '
221 git blame ten_lines >actual &&
222 test $(grep -c " " actual) = 9
223 '
224
225 test_expect_success 'setup file with CRLF newlines' '
226 git config core.autocrlf false &&
227 printf "testcase\n" >crlffile &&
228 git add crlffile &&
229 git commit -m testcase &&
230 printf "testcase\r\n" >crlffile
231 '
232
233 test_expect_success 'blame file with CRLF core.autocrlf true' '
234 git config core.autocrlf true &&
235 git blame crlffile >actual &&
236 test_grep "A U Thor" actual
237 '
238
239 test_expect_success 'blame file with CRLF attributes text' '
240 git config core.autocrlf false &&
241 echo "crlffile text" >.gitattributes &&
242 git blame crlffile >actual &&
243 test_grep "A U Thor" actual
244 '
245
246 test_expect_success 'blame file with CRLF core.autocrlf=true' '
247 git config core.autocrlf false &&
248 printf "testcase\r\n" >crlfinrepo &&
249 >.gitattributes &&
250 git add crlfinrepo &&
251 git commit -m "add crlfinrepo" &&
252 git config core.autocrlf true &&
253 mv crlfinrepo tmp &&
254 git checkout crlfinrepo &&
255 rm tmp &&
256 git blame crlfinrepo >actual &&
257 test_grep "A U Thor" actual
258 '
259
260 test_expect_success 'setup coalesce tests' '
261 cat >giraffe <<-\EOF &&
262 ABC
263 DEF
264 EOF
265 git add giraffe &&
266 git commit -m "original file" &&
267 orig=$(git rev-parse HEAD) &&
268
269 cat >giraffe <<-\EOF &&
270 ABC
271 SPLIT
272 DEF
273 EOF
274 git add giraffe &&
275 git commit -m "interior SPLIT line" &&
276 split=$(git rev-parse HEAD) &&
277
278 cat >giraffe <<-\EOF &&
279 ABC
280 DEF
281 EOF
282 git add giraffe &&
283 git commit -m "same contents as original" &&
284 final=$(git rev-parse HEAD)
285 '
286
287 test_expect_success 'blame coalesce' '
288 cat >expect <<-EOF &&
289 $orig 1 1 2
290 $orig 2 2
291 EOF
292 git blame --porcelain $final giraffe >actual.raw &&
293 grep "^$orig" actual.raw >actual &&
294 test_cmp expect actual
295 '
296
297 test_expect_success 'blame does not coalesce non-adjacent result lines' '
298 cat >expect <<-EOF &&
299 $orig 1) ABC
300 $orig 3) DEF
301 EOF
302 git blame --no-abbrev -s -L1,1 -L3,3 $split giraffe >actual &&
303 test_cmp expect actual
304 '
305
306 test_done