Merge branch 'ma/config-advice-markup-fix'
[git] / t / t6120-describe.sh
1 #!/bin/sh
2
3 test_description='test describe'
4
5 #  o---o-----o----o----o-------o----x
6 #       \   D,R   e           /
7 #        \---o-------------o-'
8 #         \  B            /
9 #          `-o----o----o-'
10 #                 A    c
11 #
12 # First parent of a merge commit is on the same line, second parent below.
13
14 . ./test-lib.sh
15
16 check_describe () {
17         expect="$1"
18         shift
19         describe_opts="$@"
20         test_expect_success "describe $describe_opts" '
21         R=$(git describe $describe_opts 2>err.actual) &&
22         case "$R" in
23         $expect)        echo happy ;;
24         *)      echo "Oops - $R is not $expect" &&
25                 false ;;
26         esac
27         '
28 }
29
30 test_expect_success setup '
31
32         test_tick &&
33         echo one >file && git add file && git commit -m initial &&
34         one=$(git rev-parse HEAD) &&
35
36         git describe --always HEAD &&
37
38         test_tick &&
39         echo two >file && git add file && git commit -m second &&
40         two=$(git rev-parse HEAD) &&
41
42         test_tick &&
43         echo three >file && git add file && git commit -m third &&
44
45         test_tick &&
46         echo A >file && git add file && git commit -m A &&
47         test_tick &&
48         git tag -a -m A A &&
49
50         test_tick &&
51         echo c >file && git add file && git commit -m c &&
52         test_tick &&
53         git tag c &&
54
55         git reset --hard $two &&
56         test_tick &&
57         echo B >side && git add side && git commit -m B &&
58         test_tick &&
59         git tag -a -m B B &&
60
61         test_tick &&
62         git merge -m Merged c &&
63         merged=$(git rev-parse HEAD) &&
64
65         git reset --hard $two &&
66         test_tick &&
67         echo D >another && git add another && git commit -m D &&
68         test_tick &&
69         git tag -a -m D D &&
70         test_tick &&
71         git tag -a -m R R &&
72
73         test_tick &&
74         echo DD >another && git commit -a -m another &&
75
76         test_tick &&
77         git tag e &&
78
79         test_tick &&
80         echo DDD >another && git commit -a -m "yet another" &&
81
82         test_tick &&
83         git merge -m Merged $merged &&
84
85         test_tick &&
86         echo X >file && echo X >side && git add file side &&
87         git commit -m x
88
89 '
90
91 check_describe A-* HEAD
92 check_describe A-* HEAD^
93 check_describe R-* HEAD^^
94 check_describe A-* HEAD^^2
95 check_describe B HEAD^^2^
96 check_describe R-* HEAD^^^
97
98 check_describe c-* --tags HEAD
99 check_describe c-* --tags HEAD^
100 check_describe e-* --tags HEAD^^
101 check_describe c-* --tags HEAD^^2
102 check_describe B --tags HEAD^^2^
103 check_describe e --tags HEAD^^^
104
105 check_describe heads/master --all HEAD
106 check_describe tags/c-* --all HEAD^
107 check_describe tags/e --all HEAD^^^
108
109 check_describe B-0-* --long HEAD^^2^
110 check_describe A-3-* --long HEAD^^2
111
112 check_describe c-7-* --tags
113 check_describe e-3-* --first-parent --tags
114
115 test_expect_success 'describe --contains defaults to HEAD without commit-ish' '
116         echo "A^0" >expect &&
117         git checkout A &&
118         test_when_finished "git checkout -" &&
119         git describe --contains >actual &&
120         test_cmp expect actual
121 '
122
123 check_describe tags/A --all A^0
124 test_expect_success 'no warning was displayed for A' '
125         test_must_be_empty err.actual
126 '
127
128 test_expect_success 'rename tag A to Q locally' '
129         mv .git/refs/tags/A .git/refs/tags/Q
130 '
131 cat - >err.expect <<EOF
132 warning: tag 'A' is really 'Q' here
133 EOF
134 check_describe A-* HEAD
135 test_expect_success 'warning was displayed for Q' '
136         test_i18ncmp err.expect err.actual
137 '
138 test_expect_success 'rename tag Q back to A' '
139         mv .git/refs/tags/Q .git/refs/tags/A
140 '
141
142 test_expect_success 'pack tag refs' 'git pack-refs'
143 check_describe A-* HEAD
144
145 test_expect_success 'describe works from outside repo using --git-dir' '
146         git clone --bare "$TRASH_DIRECTORY" "$TRASH_DIRECTORY/bare" &&
147         git --git-dir "$TRASH_DIRECTORY/bare" describe >out &&
148         grep -E "^A-[1-9][0-9]?-g[0-9a-f]+$" out
149 '
150
151 check_describe "A-*[0-9a-f]" --dirty
152
153 test_expect_success 'describe --dirty with --work-tree' '
154         (
155                 cd "$TEST_DIRECTORY" &&
156                 git --git-dir "$TRASH_DIRECTORY/.git" --work-tree "$TRASH_DIRECTORY" describe --dirty >"$TRASH_DIRECTORY/out"
157         ) &&
158         grep -E "^A-[1-9][0-9]?-g[0-9a-f]+$" out
159 '
160
161 test_expect_success 'set-up dirty work tree' '
162         echo >>file
163 '
164
165 check_describe "A-*[0-9a-f]-dirty" --dirty
166
167 test_expect_success 'describe --dirty with --work-tree (dirty)' '
168         (
169                 cd "$TEST_DIRECTORY" &&
170                 git --git-dir "$TRASH_DIRECTORY/.git" --work-tree "$TRASH_DIRECTORY" describe --dirty >"$TRASH_DIRECTORY/out"
171         ) &&
172         grep -E "^A-[1-9][0-9]?-g[0-9a-f]+-dirty$" out
173 '
174
175 check_describe "A-*[0-9a-f].mod" --dirty=.mod
176
177 test_expect_success 'describe --dirty=.mod with --work-tree (dirty)' '
178         (
179                 cd "$TEST_DIRECTORY" &&
180                 git --git-dir "$TRASH_DIRECTORY/.git" --work-tree "$TRASH_DIRECTORY" describe --dirty=.mod >"$TRASH_DIRECTORY/out"
181         ) &&
182         grep -E "^A-[1-9][0-9]?-g[0-9a-f]+.mod$" out
183 '
184
185 test_expect_success 'describe --dirty HEAD' '
186         test_must_fail git describe --dirty HEAD
187 '
188
189 test_expect_success 'set-up matching pattern tests' '
190         git tag -a -m test-annotated test-annotated &&
191         echo >>file &&
192         test_tick &&
193         git commit -a -m "one more" &&
194         git tag test1-lightweight &&
195         echo >>file &&
196         test_tick &&
197         git commit -a -m "yet another" &&
198         git tag test2-lightweight &&
199         echo >>file &&
200         test_tick &&
201         git commit -a -m "even more"
202
203 '
204
205 check_describe "test-annotated-*" --match="test-*"
206
207 check_describe "test1-lightweight-*" --tags --match="test1-*"
208
209 check_describe "test2-lightweight-*" --tags --match="test2-*"
210
211 check_describe "test2-lightweight-*" --long --tags --match="test2-*" HEAD^
212
213 check_describe "test2-lightweight-*" --long --tags --match="test1-*" --match="test2-*" HEAD^
214
215 check_describe "test2-lightweight-*" --long --tags --match="test1-*" --no-match --match="test2-*" HEAD^
216
217 check_describe "test1-lightweight-*" --long --tags --match="test1-*" --match="test3-*" HEAD
218
219 check_describe "test1-lightweight-*" --long --tags --match="test3-*" --match="test1-*" HEAD
220
221 test_expect_success 'set-up branches' '
222         git branch branch_A A &&
223         git branch branch_C c &&
224         git update-ref refs/remotes/origin/remote_branch_A "A^{commit}" &&
225         git update-ref refs/remotes/origin/remote_branch_C "c^{commit}" &&
226         git update-ref refs/original/original_branch_A test-annotated~2
227 '
228
229 check_describe "heads/branch_A*" --all --match="branch_*" --exclude="branch_C" HEAD
230
231 check_describe "remotes/origin/remote_branch_A*" --all --match="origin/remote_branch_*" --exclude="origin/remote_branch_C" HEAD
232
233 check_describe "original/original_branch_A*" --all test-annotated~1
234
235 test_expect_success '--match does not work for other types' '
236         test_must_fail git describe --all --match="*original_branch_*" test-annotated~1
237 '
238
239 test_expect_success '--exclude does not work for other types' '
240         R=$(git describe --all --exclude="any_pattern_even_not_matching" test-annotated~1) &&
241         case "$R" in
242         *original_branch_A*) echo "fail: Found unknown reference $R with --exclude"
243                 false;;
244         *) echo ok: Found some known type;;
245         esac
246 '
247
248 test_expect_success 'name-rev with exact tags' '
249         echo A >expect &&
250         tag_object=$(git rev-parse refs/tags/A) &&
251         git name-rev --tags --name-only $tag_object >actual &&
252         test_cmp expect actual &&
253
254         echo "A^0" >expect &&
255         tagged_commit=$(git rev-parse "refs/tags/A^0") &&
256         git name-rev --tags --name-only $tagged_commit >actual &&
257         test_cmp expect actual
258 '
259
260 test_expect_success 'name-rev --all' '
261         >expect.unsorted &&
262         for rev in $(git rev-list --all)
263         do
264                 git name-rev $rev >>expect.unsorted
265         done &&
266         sort <expect.unsorted >expect &&
267         git name-rev --all >actual.unsorted &&
268         sort <actual.unsorted >actual &&
269         test_cmp expect actual
270 '
271
272 test_expect_success 'name-rev --stdin' '
273         >expect.unsorted &&
274         for rev in $(git rev-list --all)
275         do
276                 name=$(git name-rev --name-only $rev) &&
277                 echo "$rev ($name)" >>expect.unsorted
278         done &&
279         sort <expect.unsorted >expect &&
280         git rev-list --all | git name-rev --stdin >actual.unsorted &&
281         sort <actual.unsorted >actual &&
282         test_cmp expect actual
283 '
284
285 test_expect_success 'describe --contains with the exact tags' '
286         echo "A^0" >expect &&
287         tag_object=$(git rev-parse refs/tags/A) &&
288         git describe --contains $tag_object >actual &&
289         test_cmp expect actual &&
290
291         echo "A^0" >expect &&
292         tagged_commit=$(git rev-parse "refs/tags/A^0") &&
293         git describe --contains $tagged_commit >actual &&
294         test_cmp expect actual
295 '
296
297 test_expect_success 'describe --contains and --match' '
298         echo "A^0" >expect &&
299         tagged_commit=$(git rev-parse "refs/tags/A^0") &&
300         test_must_fail git describe --contains --match="B" $tagged_commit &&
301         git describe --contains --match="B" --match="A" $tagged_commit >actual &&
302         test_cmp expect actual
303 '
304
305 test_expect_success 'describe --exclude' '
306         echo "c~1" >expect &&
307         tagged_commit=$(git rev-parse "refs/tags/A^0") &&
308         test_must_fail git describe --contains --match="B" $tagged_commit &&
309         git describe --contains --match="?" --exclude="A" $tagged_commit >actual &&
310         test_cmp expect actual
311 '
312
313 test_expect_success 'describe --contains and --no-match' '
314         echo "A^0" >expect &&
315         tagged_commit=$(git rev-parse "refs/tags/A^0") &&
316         git describe --contains --match="B" --no-match $tagged_commit >actual &&
317         test_cmp expect actual
318 '
319
320 test_expect_success 'setup and absorb a submodule' '
321         test_create_repo sub1 &&
322         test_commit -C sub1 initial &&
323         git submodule add ./sub1 &&
324         git submodule absorbgitdirs &&
325         git commit -a -m "add submodule" &&
326         git describe --dirty >expect &&
327         git describe --broken >out &&
328         test_cmp expect out
329 '
330
331 test_expect_success 'describe chokes on severely broken submodules' '
332         mv .git/modules/sub1/ .git/modules/sub_moved &&
333         test_must_fail git describe --dirty
334 '
335
336 test_expect_success 'describe ignoring a broken submodule' '
337         git describe --broken >out &&
338         grep broken out
339 '
340
341 test_expect_success 'describe with --work-tree ignoring a broken submodule' '
342         (
343                 cd "$TEST_DIRECTORY" &&
344                 git --git-dir "$TRASH_DIRECTORY/.git" --work-tree "$TRASH_DIRECTORY" describe --broken >"$TRASH_DIRECTORY/out"
345         ) &&
346         test_when_finished "mv .git/modules/sub_moved .git/modules/sub1" &&
347         grep broken out
348 '
349
350 test_expect_success 'describe a blob at a directly tagged commit' '
351         echo "make it a unique blob" >file &&
352         git add file && git commit -m "content in file" &&
353         git tag -a -m "latest annotated tag" unique-file &&
354         git describe HEAD:file >actual &&
355         echo "unique-file:file" >expect &&
356         test_cmp expect actual
357 '
358
359 test_expect_success 'describe a blob with its first introduction' '
360         git commit --allow-empty -m "empty commit" &&
361         git rm file &&
362         git commit -m "delete blob" &&
363         git revert HEAD &&
364         git commit --allow-empty -m "empty commit" &&
365         git describe HEAD:file >actual &&
366         echo "unique-file:file" >expect &&
367         test_cmp expect actual
368 '
369
370 test_expect_success 'describe directly tagged blob' '
371         git tag test-blob unique-file:file &&
372         git describe test-blob >actual &&
373         echo "unique-file:file" >expect &&
374         # suboptimal: we rather want to see "test-blob"
375         test_cmp expect actual
376 '
377
378 test_expect_success 'describe tag object' '
379         git tag test-blob-1 -a -m msg unique-file:file &&
380         test_must_fail git describe test-blob-1 2>actual &&
381         test_i18ngrep "fatal: test-blob-1 is neither a commit nor blob" actual
382 '
383
384 test_expect_success ULIMIT_STACK_SIZE 'name-rev works in a deep repo' '
385         i=1 &&
386         while test $i -lt 8000
387         do
388                 echo "commit refs/heads/master
389 committer A U Thor <author@example.com> $((1000000000 + $i * 100)) +0200
390 data <<EOF
391 commit #$i
392 EOF"
393                 test $i = 1 && echo "from refs/heads/master^0"
394                 i=$(($i + 1))
395         done | git fast-import &&
396         git checkout master &&
397         git tag far-far-away HEAD^ &&
398         echo "HEAD~4000 tags/far-far-away~3999" >expect &&
399         git name-rev HEAD~4000 >actual &&
400         test_cmp expect actual &&
401         run_with_limited_stack git name-rev HEAD~4000 >actual &&
402         test_cmp expect actual
403 '
404
405 test_expect_success ULIMIT_STACK_SIZE 'describe works in a deep repo' '
406         git tag -f far-far-away HEAD~7999 &&
407         echo "far-far-away" >expect &&
408         git describe --tags --abbrev=0 HEAD~4000 >actual &&
409         test_cmp expect actual &&
410         run_with_limited_stack git describe --tags --abbrev=0 HEAD~4000 >actual &&
411         test_cmp expect actual
412 '
413
414 check_describe tags/A --all A
415 check_describe tags/c --all c
416 check_describe heads/branch_A --all --match='branch_*' branch_A
417
418 test_expect_success 'describe complains about tree object' '
419         test_must_fail git describe HEAD^{tree}
420 '
421
422 test_expect_success 'describe complains about missing object' '
423         test_must_fail git describe $ZERO_OID
424 '
425
426 test_expect_success 'name-rev a rev shortly after epoch' '
427         test_when_finished "git checkout master" &&
428
429         git checkout --orphan no-timestamp-underflow &&
430         # Any date closer to epoch than the CUTOFF_DATE_SLOP constant
431         # in builtin/name-rev.c.
432         GIT_COMMITTER_DATE="@1234 +0000" \
433         git commit -m "committer date shortly after epoch" &&
434         old_commit_oid=$(git rev-parse HEAD) &&
435
436         echo "$old_commit_oid no-timestamp-underflow" >expect &&
437         git name-rev $old_commit_oid >actual &&
438         test_cmp expect actual
439 '
440
441 # A--------------master
442 #  \            /
443 #   \----------M2
444 #    \        /
445 #     \---M1-C
446 #      \ /
447 #       B
448 test_expect_success 'name-rev covers all conditions while looking at parents' '
449         git init repo &&
450         (
451                 cd repo &&
452
453                 echo A >file &&
454                 git add file &&
455                 git commit -m A &&
456                 A=$(git rev-parse HEAD) &&
457
458                 git checkout --detach &&
459                 echo B >file &&
460                 git commit -m B file &&
461                 B=$(git rev-parse HEAD) &&
462
463                 git checkout $A &&
464                 git merge --no-ff $B &&  # M1
465
466                 echo C >file &&
467                 git commit -m C file &&
468
469                 git checkout $A &&
470                 git merge --no-ff HEAD@{1} && # M2
471
472                 git checkout master &&
473                 git merge --no-ff HEAD@{1} &&
474
475                 echo "$B master^2^2~1^2" >expect &&
476                 git name-rev $B >actual &&
477
478                 test_cmp expect actual
479         )
480 '
481
482 test_done