1#!/bin/sh
2#
3# Copyright (c) 2006 Shawn Pearce
4#
5
6test_description='Test git update-ref and basic ref logging'
7GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
8export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
9
10. ./test-lib.sh
11
12Z=$ZERO_OID
13
14m=refs/heads/main
15n_dir=refs/heads/gu
16n=$n_dir/fixes
17outside=refs/foo
18bare=bare-repo
19
20create_test_commits ()
21{
22	prfx="$1"
23	for name in A B C D E F
24	do
25		test_tick &&
26		T=$(git write-tree) &&
27		sha1=$(echo $name | git commit-tree $T) &&
28		eval $prfx$name=$sha1
29	done
30}
31
32test_expect_success setup '
33	git checkout --orphan main &&
34	create_test_commits "" &&
35	mkdir $bare &&
36	cd $bare &&
37	git init --bare -b main &&
38	create_test_commits "bare" &&
39	cd -
40'
41
42test_expect_success "create $m" '
43	git update-ref $m $A &&
44	test $A = $(git show-ref -s --verify $m)
45'
46test_expect_success "create $m with oldvalue verification" '
47	git update-ref $m $B $A &&
48	test $B = $(git show-ref -s --verify $m)
49'
50test_expect_success "fail to delete $m with stale ref" '
51	test_must_fail git update-ref -d $m $A &&
52	test $B = "$(git show-ref -s --verify $m)"
53'
54test_expect_success "delete $m" '
55	test_when_finished "git update-ref -d $m" &&
56	git update-ref -d $m $B &&
57	test_must_fail git show-ref --verify -q $m
58'
59
60test_expect_success "delete $m without oldvalue verification" '
61	test_when_finished "git update-ref -d $m" &&
62	git update-ref $m $A &&
63	test $A = $(git show-ref -s --verify $m) &&
64	git update-ref -d $m &&
65	test_must_fail git show-ref --verify -q $m
66'
67
68test_expect_success "fail to create $n" '
69	test_when_finished "rm -f .git/$n_dir" &&
70	touch .git/$n_dir &&
71	test_must_fail git update-ref $n $A
72'
73
74test_expect_success "create $m (by HEAD)" '
75	git update-ref HEAD $A &&
76	test $A = $(git show-ref -s --verify $m)
77'
78test_expect_success "create $m (by HEAD) with oldvalue verification" '
79	git update-ref HEAD $B $A &&
80	test $B = $(git show-ref -s --verify $m)
81'
82test_expect_success "fail to delete $m (by HEAD) with stale ref" '
83	test_must_fail git update-ref -d HEAD $A &&
84	test $B = $(git show-ref -s --verify $m)
85'
86test_expect_success "delete $m (by HEAD)" '
87	test_when_finished "git update-ref -d $m" &&
88	git update-ref -d HEAD $B &&
89	test_must_fail git show-ref --verify -q $m
90'
91
92test_expect_success "deleting current branch adds message to HEAD's log" '
93	test_when_finished "git update-ref -d $m" &&
94	git update-ref $m $A &&
95	git symbolic-ref HEAD $m &&
96	git update-ref -m delete-$m -d $m &&
97	test_must_fail git show-ref --verify -q $m &&
98	grep "delete-$m$" .git/logs/HEAD
99'
100
101test_expect_success "deleting by HEAD adds message to HEAD's log" '
102	test_when_finished "git update-ref -d $m" &&
103	git update-ref $m $A &&
104	git symbolic-ref HEAD $m &&
105	git update-ref -m delete-by-head -d HEAD &&
106	test_must_fail git show-ref --verify -q $m &&
107	grep "delete-by-head$" .git/logs/HEAD
108'
109
110test_expect_success 'update-ref does not create reflogs by default' '
111	test_when_finished "git update-ref -d $outside" &&
112	git update-ref $outside $A &&
113	git rev-parse $A >expect &&
114	git rev-parse $outside >actual &&
115	test_cmp expect actual &&
116	test_must_fail git reflog exists $outside
117'
118
119test_expect_success 'update-ref creates reflogs with --create-reflog' '
120	test_when_finished "git update-ref -d $outside" &&
121	git update-ref --create-reflog $outside $A &&
122	git rev-parse $A >expect &&
123	git rev-parse $outside >actual &&
124	test_cmp expect actual &&
125	git reflog exists $outside
126'
127
128test_expect_success 'creates no reflog in bare repository' '
129	git -C $bare update-ref $m $bareA &&
130	git -C $bare rev-parse $bareA >expect &&
131	git -C $bare rev-parse $m >actual &&
132	test_cmp expect actual &&
133	test_must_fail git -C $bare reflog exists $m
134'
135
136test_expect_success 'core.logAllRefUpdates=true creates reflog in bare repository' '
137	test_when_finished "git -C $bare config --unset core.logAllRefUpdates && \
138		rm $bare/logs/$m" &&
139	git -C $bare config core.logAllRefUpdates true &&
140	git -C $bare update-ref $m $bareB &&
141	git -C $bare rev-parse $bareB >expect &&
142	git -C $bare rev-parse $m >actual &&
143	test_cmp expect actual &&
144	git -C $bare reflog exists $m
145'
146
147test_expect_success 'core.logAllRefUpdates=true does not create reflog by default' '
148	test_config core.logAllRefUpdates true &&
149	test_when_finished "git update-ref -d $outside" &&
150	git update-ref $outside $A &&
151	git rev-parse $A >expect &&
152	git rev-parse $outside >actual &&
153	test_cmp expect actual &&
154	test_must_fail git reflog exists $outside
155'
156
157test_expect_success 'core.logAllRefUpdates=always creates reflog by default' '
158	test_config core.logAllRefUpdates always &&
159	test_when_finished "git update-ref -d $outside" &&
160	git update-ref $outside $A &&
161	git rev-parse $A >expect &&
162	git rev-parse $outside >actual &&
163	test_cmp expect actual &&
164	git reflog exists $outside
165'
166
167test_expect_success 'core.logAllRefUpdates=always creates reflog for ORIG_HEAD' '
168	test_config core.logAllRefUpdates always &&
169	git update-ref ORIG_HEAD $A &&
170	git reflog exists ORIG_HEAD
171'
172
173test_expect_success '--no-create-reflog overrides core.logAllRefUpdates=always' '
174	test_config core.logAllRefUpdates true &&
175	test_when_finished "git update-ref -d $outside" &&
176	git update-ref --no-create-reflog $outside $A &&
177	git rev-parse $A >expect &&
178	git rev-parse $outside >actual &&
179	test_cmp expect actual &&
180	test_must_fail git reflog exists $outside
181'
182
183test_expect_success "create $m (by HEAD)" '
184	git update-ref HEAD $A &&
185	test $A = $(git show-ref -s --verify $m)
186'
187test_expect_success 'pack refs' '
188	git pack-refs --all
189'
190test_expect_success "move $m (by HEAD)" '
191	git update-ref HEAD $B $A &&
192	test $B = $(git show-ref -s --verify $m)
193'
194test_expect_success "delete $m (by HEAD) should remove both packed and loose $m" '
195	test_when_finished "git update-ref -d $m" &&
196	git update-ref -d HEAD $B &&
197	! grep "$m" .git/packed-refs &&
198	test_must_fail git show-ref --verify -q $m
199'
200
201test_expect_success 'delete symref without dereference' '
202	test_when_finished "git update-ref -d $m" &&
203	echo foo >foo.c &&
204	git add foo.c &&
205	git commit -m foo &&
206	git symbolic-ref SYMREF $m &&
207	git update-ref --no-deref -d SYMREF &&
208	git show-ref --verify -q $m &&
209	test_must_fail git show-ref --verify -q SYMREF &&
210	test_must_fail git symbolic-ref SYMREF
211'
212
213test_expect_success 'delete symref without dereference when the referred ref is packed' '
214	test_when_finished "git update-ref -d $m" &&
215	echo foo >foo.c &&
216	git add foo.c &&
217	git commit -m foo &&
218	git symbolic-ref SYMREF $m &&
219	git pack-refs --all &&
220	git update-ref --no-deref -d SYMREF &&
221	git show-ref --verify -q $m &&
222	test_must_fail git show-ref --verify -q SYMREF &&
223	test_must_fail git symbolic-ref SYMREF
224'
225
226test_expect_success 'update-ref -d is not confused by self-reference' '
227	git symbolic-ref refs/heads/self refs/heads/self &&
228	test_when_finished "rm -f .git/refs/heads/self" &&
229	test_path_is_file .git/refs/heads/self &&
230	test_must_fail git update-ref -d refs/heads/self &&
231	test_path_is_file .git/refs/heads/self
232'
233
234test_expect_success 'update-ref --no-deref -d can delete self-reference' '
235	git symbolic-ref refs/heads/self refs/heads/self &&
236	test_when_finished "rm -f .git/refs/heads/self" &&
237	test_path_is_file .git/refs/heads/self &&
238	git update-ref --no-deref -d refs/heads/self &&
239	test_must_fail git show-ref --verify -q refs/heads/self
240'
241
242test_expect_success 'update-ref --no-deref -d can delete reference to bad ref' '
243	>.git/refs/heads/bad &&
244	test_when_finished "rm -f .git/refs/heads/bad" &&
245	git symbolic-ref refs/heads/ref-to-bad refs/heads/bad &&
246	test_when_finished "git update-ref -d refs/heads/ref-to-bad" &&
247	test_path_is_file .git/refs/heads/ref-to-bad &&
248	git update-ref --no-deref -d refs/heads/ref-to-bad &&
249	test_must_fail git show-ref --verify -q refs/heads/ref-to-bad
250'
251
252test_expect_success '(not) create HEAD with old sha1' '
253	test_must_fail git update-ref HEAD $A $B
254'
255test_expect_success "(not) prior created .git/$m" '
256	test_when_finished "git update-ref -d $m" &&
257	test_must_fail git show-ref --verify -q $m
258'
259
260test_expect_success 'create HEAD' '
261	git update-ref HEAD $A
262'
263test_expect_success '(not) change HEAD with wrong SHA1' '
264	test_must_fail git update-ref HEAD $B $Z
265'
266test_expect_success "(not) changed .git/$m" '
267	test_when_finished "git update-ref -d $m" &&
268	! test $B = $(git show-ref -s --verify $m)
269'
270
271rm -f .git/logs/refs/heads/main
272test_expect_success "create $m (logged by touch)" '
273	test_config core.logAllRefUpdates false &&
274	GIT_COMMITTER_DATE="2005-05-26 23:30" \
275	git update-ref --create-reflog HEAD $A -m "Initial Creation" &&
276	test $A = $(git show-ref -s --verify $m)
277'
278test_expect_success "update $m (logged by touch)" '
279	test_config core.logAllRefUpdates false &&
280	GIT_COMMITTER_DATE="2005-05-26 23:31" \
281	git update-ref HEAD $B $A -m "Switch" &&
282	test $B = $(git show-ref -s --verify $m)
283'
284test_expect_success "set $m (logged by touch)" '
285	test_config core.logAllRefUpdates false &&
286	GIT_COMMITTER_DATE="2005-05-26 23:41" \
287	git update-ref HEAD $A &&
288	test $A = $(git show-ref -s --verify $m)
289'
290
291test_expect_success 'empty directory removal' '
292	git branch d1/d2/r1 HEAD &&
293	git branch d1/r2 HEAD &&
294	test_path_is_file .git/refs/heads/d1/d2/r1 &&
295	test_path_is_file .git/logs/refs/heads/d1/d2/r1 &&
296	git branch -d d1/d2/r1 &&
297	test_must_fail git show-ref --verify -q refs/heads/d1/d2 &&
298	test_must_fail git show-ref --verify -q logs/refs/heads/d1/d2 &&
299	test_path_is_file .git/refs/heads/d1/r2 &&
300	test_path_is_file .git/logs/refs/heads/d1/r2
301'
302
303test_expect_success 'symref empty directory removal' '
304	git branch e1/e2/r1 HEAD &&
305	git branch e1/r2 HEAD &&
306	git checkout e1/e2/r1 &&
307	test_when_finished "git checkout main" &&
308	test_path_is_file .git/refs/heads/e1/e2/r1 &&
309	test_path_is_file .git/logs/refs/heads/e1/e2/r1 &&
310	git update-ref -d HEAD &&
311	test_must_fail git show-ref --verify -q refs/heads/e1/e2 &&
312	test_must_fail git show-ref --verify -q logs/refs/heads/e1/e2 &&
313	test_path_is_file .git/refs/heads/e1/r2 &&
314	test_path_is_file .git/logs/refs/heads/e1/r2 &&
315	test_path_is_file .git/logs/HEAD
316'
317
318cat >expect <<EOF
319$Z $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000	Initial Creation
320$A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150260 +0000	Switch
321$B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150860 +0000
322EOF
323test_expect_success "verifying $m's log (logged by touch)" '
324	test_when_finished "rm -rf .git/$m .git/logs expect" &&
325	test_cmp expect .git/logs/$m
326'
327
328test_expect_success "create $m (logged by config)" '
329	test_config core.logAllRefUpdates true &&
330	GIT_COMMITTER_DATE="2005-05-26 23:32" \
331	git update-ref HEAD $A -m "Initial Creation" &&
332	test $A = $(git show-ref -s --verify $m)
333'
334test_expect_success "update $m (logged by config)" '
335	test_config core.logAllRefUpdates true &&
336	GIT_COMMITTER_DATE="2005-05-26 23:33" \
337	git update-ref HEAD $B $A -m "Switch" &&
338	test $B = $(git show-ref -s --verify $m)
339'
340test_expect_success "set $m (logged by config)" '
341	test_config core.logAllRefUpdates true &&
342	GIT_COMMITTER_DATE="2005-05-26 23:43" \
343	git update-ref HEAD $A &&
344	test $A = $(git show-ref -s --verify $m)
345'
346
347cat >expect <<EOF
348$Z $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 +0000	Initial Creation
349$A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 +0000	Switch
350$B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 +0000
351EOF
352test_expect_success "verifying $m's log (logged by config)" '
353	test_when_finished "rm -f .git/$m .git/logs/$m expect" &&
354	test_cmp expect .git/logs/$m
355'
356
357test_expect_success 'set up for querying the reflog' '
358	git update-ref $m $D &&
359	cat >.git/logs/$m <<-EOF
360	$Z $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
361	$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500
362	$A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
363	$F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
364	$Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500
365	EOF
366'
367
368ed="Thu, 26 May 2005 18:32:00 -0500"
369gd="Thu, 26 May 2005 18:33:00 -0500"
370ld="Thu, 26 May 2005 18:43:00 -0500"
371test_expect_success 'Query "main@{May 25 2005}" (before history)' '
372	test_when_finished "rm -f o e" &&
373	git rev-parse --verify "main@{May 25 2005}" >o 2>e &&
374	echo "$C" >expect &&
375	test_cmp expect o &&
376	echo "warning: log for '\''main'\'' only goes back to $ed" >expect &&
377	test_cmp expect e
378'
379test_expect_success 'Query main@{2005-05-25} (before history)' '
380	test_when_finished "rm -f o e" &&
381	git rev-parse --verify main@{2005-05-25} >o 2>e &&
382	echo "$C" >expect &&
383	test_cmp expect o &&
384	echo "warning: log for '\''main'\'' only goes back to $ed" >expect &&
385	test_cmp expect e
386'
387test_expect_success 'Query "main@{May 26 2005 23:31:59}" (1 second before history)' '
388	test_when_finished "rm -f o e" &&
389	git rev-parse --verify "main@{May 26 2005 23:31:59}" >o 2>e &&
390	echo "$C" >expect &&
391	test_cmp expect o &&
392	echo "warning: log for '\''main'\'' only goes back to $ed" >expect &&
393	test_cmp expect e
394'
395test_expect_success 'Query "main@{May 26 2005 23:32:00}" (exactly history start)' '
396	test_when_finished "rm -f o e" &&
397	git rev-parse --verify "main@{May 26 2005 23:32:00}" >o 2>e &&
398	echo "$C" >expect &&
399	test_cmp expect o &&
400	test_must_be_empty e
401'
402test_expect_success 'Query "main@{May 26 2005 23:32:30}" (first non-creation change)' '
403	test_when_finished "rm -f o e" &&
404	git rev-parse --verify "main@{May 26 2005 23:32:30}" >o 2>e &&
405	echo "$A" >expect &&
406	test_cmp expect o &&
407	test_must_be_empty e
408'
409test_expect_success 'Query "main@{2005-05-26 23:33:01}" (middle of history with gap)' '
410	test_when_finished "rm -f o e" &&
411	git rev-parse --verify "main@{2005-05-26 23:33:01}" >o 2>e &&
412	echo "$B" >expect &&
413	test_cmp expect o &&
414	test_i18ngrep -F "warning: log for ref $m has gap after $gd" e
415'
416test_expect_success 'Query "main@{2005-05-26 23:38:00}" (middle of history)' '
417	test_when_finished "rm -f o e" &&
418	git rev-parse --verify "main@{2005-05-26 23:38:00}" >o 2>e &&
419	echo "$Z" >expect &&
420	test_cmp expect o &&
421	test_must_be_empty e
422'
423test_expect_success 'Query "main@{2005-05-26 23:43:00}" (exact end of history)' '
424	test_when_finished "rm -f o e" &&
425	git rev-parse --verify "main@{2005-05-26 23:43:00}" >o 2>e &&
426	echo "$E" >expect &&
427	test_cmp expect o &&
428	test_must_be_empty e
429'
430test_expect_success 'Query "main@{2005-05-28}" (past end of history)' '
431	test_when_finished "rm -f o e" &&
432	git rev-parse --verify "main@{2005-05-28}" >o 2>e &&
433	echo "$D" >expect &&
434	test_cmp expect o &&
435	test_i18ngrep -F "warning: log for ref $m unexpectedly ended on $ld" e
436'
437
438rm -f .git/$m .git/logs/$m expect
439
440test_expect_success 'creating initial files' '
441	test_when_finished rm -f M &&
442	echo TEST >F &&
443	git add F &&
444	GIT_AUTHOR_DATE="2005-05-26 23:30" \
445	GIT_COMMITTER_DATE="2005-05-26 23:30" git commit -m add -a &&
446	h_TEST=$(git rev-parse --verify HEAD) &&
447	echo The other day this did not work. >M &&
448	echo And then Bob told me how to fix it. >>M &&
449	echo OTHER >F &&
450	GIT_AUTHOR_DATE="2005-05-26 23:41" \
451	GIT_COMMITTER_DATE="2005-05-26 23:41" git commit -F M -a &&
452	h_OTHER=$(git rev-parse --verify HEAD) &&
453	GIT_AUTHOR_DATE="2005-05-26 23:44" \
454	GIT_COMMITTER_DATE="2005-05-26 23:44" git commit --amend &&
455	h_FIXED=$(git rev-parse --verify HEAD) &&
456	echo Merged initial commit and a later commit. >M &&
457	echo $h_TEST >.git/MERGE_HEAD &&
458	GIT_AUTHOR_DATE="2005-05-26 23:45" \
459	GIT_COMMITTER_DATE="2005-05-26 23:45" git commit -F M &&
460	h_MERGED=$(git rev-parse --verify HEAD)
461'
462
463cat >expect <<EOF
464$Z $h_TEST $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000	commit (initial): add
465$h_TEST $h_OTHER $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150860 +0000	commit: The other day this did not work.
466$h_OTHER $h_FIXED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151040 +0000	commit (amend): The other day this did not work.
467$h_FIXED $h_MERGED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151100 +0000	commit (merge): Merged initial commit and a later commit.
468EOF
469test_expect_success 'git commit logged updates' '
470	test_cmp expect .git/logs/$m
471'
472unset h_TEST h_OTHER h_FIXED h_MERGED
473
474test_expect_success 'git cat-file blob main:F (expect OTHER)' '
475	test OTHER = $(git cat-file blob main:F)
476'
477test_expect_success 'git cat-file blob main@{2005-05-26 23:30}:F (expect TEST)' '
478	test TEST = $(git cat-file blob "main@{2005-05-26 23:30}:F")
479'
480test_expect_success 'git cat-file blob main@{2005-05-26 23:42}:F (expect OTHER)' '
481	test OTHER = $(git cat-file blob "main@{2005-05-26 23:42}:F")
482'
483
484# Test adding and deleting pseudorefs
485
486test_expect_success 'given old value for missing pseudoref, do not create' '
487	test_must_fail git update-ref PSEUDOREF $A $B 2>err &&
488	test_must_fail git rev-parse PSEUDOREF &&
489	test_i18ngrep "unable to resolve reference" err
490'
491
492test_expect_success 'create pseudoref' '
493	git update-ref PSEUDOREF $A &&
494	test $A = $(git rev-parse PSEUDOREF)
495'
496
497test_expect_success 'overwrite pseudoref with no old value given' '
498	git update-ref PSEUDOREF $B &&
499	test $B = $(git rev-parse PSEUDOREF)
500'
501
502test_expect_success 'overwrite pseudoref with correct old value' '
503	git update-ref PSEUDOREF $C $B &&
504	test $C = $(git rev-parse PSEUDOREF)
505'
506
507test_expect_success 'do not overwrite pseudoref with wrong old value' '
508	test_must_fail git update-ref PSEUDOREF $D $E 2>err &&
509	test $C = $(git rev-parse PSEUDOREF) &&
510	test_i18ngrep "cannot lock ref.*expected" err
511'
512
513test_expect_success 'delete pseudoref' '
514	git update-ref -d PSEUDOREF &&
515	test_must_fail git rev-parse PSEUDOREF
516'
517
518test_expect_success 'do not delete pseudoref with wrong old value' '
519	git update-ref PSEUDOREF $A &&
520	test_must_fail git update-ref -d PSEUDOREF $B 2>err &&
521	test $A = $(git rev-parse PSEUDOREF) &&
522	test_i18ngrep "cannot lock ref.*expected" err
523'
524
525test_expect_success 'delete pseudoref with correct old value' '
526	git update-ref -d PSEUDOREF $A &&
527	test_must_fail git rev-parse PSEUDOREF
528'
529
530test_expect_success 'create pseudoref with old OID zero' '
531	git update-ref PSEUDOREF $A $Z &&
532	test $A = $(git rev-parse PSEUDOREF)
533'
534
535test_expect_success 'do not overwrite pseudoref with old OID zero' '
536	test_when_finished git update-ref -d PSEUDOREF &&
537	test_must_fail git update-ref PSEUDOREF $B $Z 2>err &&
538	test $A = $(git rev-parse PSEUDOREF) &&
539	test_i18ngrep "already exists" err
540'
541
542# Test --stdin
543
544a=refs/heads/a
545b=refs/heads/b
546c=refs/heads/c
547E='""'
548F='%s\0'
549pws='path with space'
550
551test_expect_success 'stdin test setup' '
552	echo "$pws" >"$pws" &&
553	git add -- "$pws" &&
554	git commit -m "$pws"
555'
556
557test_expect_success '-z fails without --stdin' '
558	test_must_fail git update-ref -z $m $m $m 2>err &&
559	test_i18ngrep "usage: git update-ref" err
560'
561
562test_expect_success 'stdin works with no input' '
563	>stdin &&
564	git update-ref --stdin <stdin &&
565	git rev-parse --verify -q $m
566'
567
568test_expect_success 'stdin fails on empty line' '
569	echo "" >stdin &&
570	test_must_fail git update-ref --stdin <stdin 2>err &&
571	grep "fatal: empty command in input" err
572'
573
574test_expect_success 'stdin fails on only whitespace' '
575	echo " " >stdin &&
576	test_must_fail git update-ref --stdin <stdin 2>err &&
577	grep "fatal: whitespace before command:  " err
578'
579
580test_expect_success 'stdin fails on leading whitespace' '
581	echo " create $a $m" >stdin &&
582	test_must_fail git update-ref --stdin <stdin 2>err &&
583	grep "fatal: whitespace before command:  create $a $m" err
584'
585
586test_expect_success 'stdin fails on unknown command' '
587	echo "unknown $a" >stdin &&
588	test_must_fail git update-ref --stdin <stdin 2>err &&
589	grep "fatal: unknown command: unknown $a" err
590'
591
592test_expect_success 'stdin fails on unbalanced quotes' '
593	echo "create $a \"main" >stdin &&
594	test_must_fail git update-ref --stdin <stdin 2>err &&
595	grep "fatal: badly quoted argument: \\\"main" err
596'
597
598test_expect_success 'stdin fails on invalid escape' '
599	echo "create $a \"ma\zn\"" >stdin &&
600	test_must_fail git update-ref --stdin <stdin 2>err &&
601	grep "fatal: badly quoted argument: \\\"ma\\\\zn\\\"" err
602'
603
604test_expect_success 'stdin fails on junk after quoted argument' '
605	echo "create \"$a\"main" >stdin &&
606	test_must_fail git update-ref --stdin <stdin 2>err &&
607	grep "fatal: unexpected character after quoted argument: \\\"$a\\\"main" err
608'
609
610test_expect_success 'stdin fails create with no ref' '
611	echo "create " >stdin &&
612	test_must_fail git update-ref --stdin <stdin 2>err &&
613	grep "fatal: create: missing <ref>" err
614'
615
616test_expect_success 'stdin fails create with no new value' '
617	echo "create $a" >stdin &&
618	test_must_fail git update-ref --stdin <stdin 2>err &&
619	grep "fatal: create $a: missing <newvalue>" err
620'
621
622test_expect_success 'stdin fails create with too many arguments' '
623	echo "create $a $m $m" >stdin &&
624	test_must_fail git update-ref --stdin <stdin 2>err &&
625	grep "fatal: create $a: extra input:  $m" err
626'
627
628test_expect_success 'stdin fails update with no ref' '
629	echo "update " >stdin &&
630	test_must_fail git update-ref --stdin <stdin 2>err &&
631	grep "fatal: update: missing <ref>" err
632'
633
634test_expect_success 'stdin fails update with no new value' '
635	echo "update $a" >stdin &&
636	test_must_fail git update-ref --stdin <stdin 2>err &&
637	grep "fatal: update $a: missing <newvalue>" err
638'
639
640test_expect_success 'stdin fails update with too many arguments' '
641	echo "update $a $m $m $m" >stdin &&
642	test_must_fail git update-ref --stdin <stdin 2>err &&
643	grep "fatal: update $a: extra input:  $m" err
644'
645
646test_expect_success 'stdin fails delete with no ref' '
647	echo "delete " >stdin &&
648	test_must_fail git update-ref --stdin <stdin 2>err &&
649	grep "fatal: delete: missing <ref>" err
650'
651
652test_expect_success 'stdin fails delete with too many arguments' '
653	echo "delete $a $m $m" >stdin &&
654	test_must_fail git update-ref --stdin <stdin 2>err &&
655	grep "fatal: delete $a: extra input:  $m" err
656'
657
658test_expect_success 'stdin fails verify with too many arguments' '
659	echo "verify $a $m $m" >stdin &&
660	test_must_fail git update-ref --stdin <stdin 2>err &&
661	grep "fatal: verify $a: extra input:  $m" err
662'
663
664test_expect_success 'stdin fails option with unknown name' '
665	echo "option unknown" >stdin &&
666	test_must_fail git update-ref --stdin <stdin 2>err &&
667	grep "fatal: option unknown: unknown" err
668'
669
670test_expect_success 'stdin fails with duplicate refs' '
671	cat >stdin <<-EOF &&
672	create $a $m
673	create $b $m
674	create $a $m
675	EOF
676	test_must_fail git update-ref --stdin <stdin 2>err &&
677	test_i18ngrep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err
678'
679
680test_expect_success 'stdin create ref works' '
681	echo "create $a $m" >stdin &&
682	git update-ref --stdin <stdin &&
683	git rev-parse $m >expect &&
684	git rev-parse $a >actual &&
685	test_cmp expect actual
686'
687
688test_expect_success 'stdin does not create reflogs by default' '
689	test_when_finished "git update-ref -d $outside" &&
690	echo "create $outside $m" >stdin &&
691	git update-ref --stdin <stdin &&
692	git rev-parse $m >expect &&
693	git rev-parse $outside >actual &&
694	test_cmp expect actual &&
695	test_must_fail git reflog exists $outside
696'
697
698test_expect_success 'stdin creates reflogs with --create-reflog' '
699	test_when_finished "git update-ref -d $outside" &&
700	echo "create $outside $m" >stdin &&
701	git update-ref --create-reflog --stdin <stdin &&
702	git rev-parse $m >expect &&
703	git rev-parse $outside >actual &&
704	test_cmp expect actual &&
705	git reflog exists $outside
706'
707
708test_expect_success 'stdin succeeds with quoted argument' '
709	git update-ref -d $a &&
710	echo "create $a \"$m\"" >stdin &&
711	git update-ref --stdin <stdin &&
712	git rev-parse $m >expect &&
713	git rev-parse $a >actual &&
714	test_cmp expect actual
715'
716
717test_expect_success 'stdin succeeds with escaped character' '
718	git update-ref -d $a &&
719	echo "create $a \"ma\\151n\"" >stdin &&
720	git update-ref --stdin <stdin &&
721	git rev-parse $m >expect &&
722	git rev-parse $a >actual &&
723	test_cmp expect actual
724'
725
726test_expect_success 'stdin update ref creates with zero old value' '
727	echo "update $b $m $Z" >stdin &&
728	git update-ref --stdin <stdin &&
729	git rev-parse $m >expect &&
730	git rev-parse $b >actual &&
731	test_cmp expect actual &&
732	git update-ref -d $b
733'
734
735test_expect_success 'stdin update ref creates with empty old value' '
736	echo "update $b $m $E" >stdin &&
737	git update-ref --stdin <stdin &&
738	git rev-parse $m >expect &&
739	git rev-parse $b >actual &&
740	test_cmp expect actual
741'
742
743test_expect_success 'stdin create ref works with path with space to blob' '
744	echo "create refs/blobs/pws \"$m:$pws\"" >stdin &&
745	git update-ref --stdin <stdin &&
746	git rev-parse "$m:$pws" >expect &&
747	git rev-parse refs/blobs/pws >actual &&
748	test_cmp expect actual &&
749	git update-ref -d refs/blobs/pws
750'
751
752test_expect_success 'stdin update ref fails with wrong old value' '
753	echo "update $c $m $m~1" >stdin &&
754	test_must_fail git update-ref --stdin <stdin 2>err &&
755	grep "fatal: cannot lock ref '"'"'$c'"'"'" err &&
756	test_must_fail git rev-parse --verify -q $c
757'
758
759test_expect_success 'stdin update ref fails with bad old value' '
760	echo "update $c $m does-not-exist" >stdin &&
761	test_must_fail git update-ref --stdin <stdin 2>err &&
762	grep "fatal: update $c: invalid <oldvalue>: does-not-exist" err &&
763	test_must_fail git rev-parse --verify -q $c
764'
765
766test_expect_success 'stdin create ref fails with bad new value' '
767	echo "create $c does-not-exist" >stdin &&
768	test_must_fail git update-ref --stdin <stdin 2>err &&
769	grep "fatal: create $c: invalid <newvalue>: does-not-exist" err &&
770	test_must_fail git rev-parse --verify -q $c
771'
772
773test_expect_success 'stdin create ref fails with zero new value' '
774	echo "create $c " >stdin &&
775	test_must_fail git update-ref --stdin <stdin 2>err &&
776	grep "fatal: create $c: zero <newvalue>" err &&
777	test_must_fail git rev-parse --verify -q $c
778'
779
780test_expect_success 'stdin update ref works with right old value' '
781	echo "update $b $m~1 $m" >stdin &&
782	git update-ref --stdin <stdin &&
783	git rev-parse $m~1 >expect &&
784	git rev-parse $b >actual &&
785	test_cmp expect actual
786'
787
788test_expect_success 'stdin delete ref fails with wrong old value' '
789	echo "delete $a $m~1" >stdin &&
790	test_must_fail git update-ref --stdin <stdin 2>err &&
791	grep "fatal: cannot lock ref '"'"'$a'"'"'" err &&
792	git rev-parse $m >expect &&
793	git rev-parse $a >actual &&
794	test_cmp expect actual
795'
796
797test_expect_success 'stdin delete ref fails with zero old value' '
798	echo "delete $a " >stdin &&
799	test_must_fail git update-ref --stdin <stdin 2>err &&
800	grep "fatal: delete $a: zero <oldvalue>" err &&
801	git rev-parse $m >expect &&
802	git rev-parse $a >actual &&
803	test_cmp expect actual
804'
805
806test_expect_success 'stdin update symref works option no-deref' '
807	git symbolic-ref TESTSYMREF $b &&
808	cat >stdin <<-EOF &&
809	option no-deref
810	update TESTSYMREF $a $b
811	EOF
812	git update-ref --stdin <stdin &&
813	git rev-parse TESTSYMREF >expect &&
814	git rev-parse $a >actual &&
815	test_cmp expect actual &&
816	git rev-parse $m~1 >expect &&
817	git rev-parse $b >actual &&
818	test_cmp expect actual
819'
820
821test_expect_success 'stdin delete symref works option no-deref' '
822	git symbolic-ref TESTSYMREF $b &&
823	cat >stdin <<-EOF &&
824	option no-deref
825	delete TESTSYMREF $b
826	EOF
827	git update-ref --stdin <stdin &&
828	test_must_fail git rev-parse --verify -q TESTSYMREF &&
829	git rev-parse $m~1 >expect &&
830	git rev-parse $b >actual &&
831	test_cmp expect actual
832'
833
834test_expect_success 'stdin update symref works flag --no-deref' '
835	git symbolic-ref TESTSYMREFONE $b &&
836	git symbolic-ref TESTSYMREFTWO $b &&
837	cat >stdin <<-EOF &&
838	update TESTSYMREFONE $a $b
839	update TESTSYMREFTWO $a $b
840	EOF
841	git update-ref --no-deref --stdin <stdin &&
842	git rev-parse TESTSYMREFONE TESTSYMREFTWO >expect &&
843	git rev-parse $a $a >actual &&
844	test_cmp expect actual &&
845	git rev-parse $m~1 >expect &&
846	git rev-parse $b >actual &&
847	test_cmp expect actual
848'
849
850test_expect_success 'stdin delete symref works flag --no-deref' '
851	git symbolic-ref TESTSYMREFONE $b &&
852	git symbolic-ref TESTSYMREFTWO $b &&
853	cat >stdin <<-EOF &&
854	delete TESTSYMREFONE $b
855	delete TESTSYMREFTWO $b
856	EOF
857	git update-ref --no-deref --stdin <stdin &&
858	test_must_fail git rev-parse --verify -q TESTSYMREFONE &&
859	test_must_fail git rev-parse --verify -q TESTSYMREFTWO &&
860	git rev-parse $m~1 >expect &&
861	git rev-parse $b >actual &&
862	test_cmp expect actual
863'
864
865test_expect_success 'stdin delete ref works with right old value' '
866	echo "delete $b $m~1" >stdin &&
867	git update-ref --stdin <stdin &&
868	test_must_fail git rev-parse --verify -q $b
869'
870
871test_expect_success 'stdin update/create/verify combination works' '
872	cat >stdin <<-EOF &&
873	update $a $m
874	create $b $m
875	verify $c
876	EOF
877	git update-ref --stdin <stdin &&
878	git rev-parse $m >expect &&
879	git rev-parse $a >actual &&
880	test_cmp expect actual &&
881	git rev-parse $b >actual &&
882	test_cmp expect actual &&
883	test_must_fail git rev-parse --verify -q $c
884'
885
886test_expect_success 'stdin verify succeeds for correct value' '
887	git rev-parse $m >expect &&
888	echo "verify $m $m" >stdin &&
889	git update-ref --stdin <stdin &&
890	git rev-parse $m >actual &&
891	test_cmp expect actual
892'
893
894test_expect_success 'stdin verify succeeds for missing reference' '
895	echo "verify refs/heads/missing $Z" >stdin &&
896	git update-ref --stdin <stdin &&
897	test_must_fail git rev-parse --verify -q refs/heads/missing
898'
899
900test_expect_success 'stdin verify treats no value as missing' '
901	echo "verify refs/heads/missing" >stdin &&
902	git update-ref --stdin <stdin &&
903	test_must_fail git rev-parse --verify -q refs/heads/missing
904'
905
906test_expect_success 'stdin verify fails for wrong value' '
907	git rev-parse $m >expect &&
908	echo "verify $m $m~1" >stdin &&
909	test_must_fail git update-ref --stdin <stdin &&
910	git rev-parse $m >actual &&
911	test_cmp expect actual
912'
913
914test_expect_success 'stdin verify fails for mistaken null value' '
915	git rev-parse $m >expect &&
916	echo "verify $m $Z" >stdin &&
917	test_must_fail git update-ref --stdin <stdin &&
918	git rev-parse $m >actual &&
919	test_cmp expect actual
920'
921
922test_expect_success 'stdin verify fails for mistaken empty value' '
923	M=$(git rev-parse $m) &&
924	test_when_finished "git update-ref $m $M" &&
925	git rev-parse $m >expect &&
926	echo "verify $m" >stdin &&
927	test_must_fail git update-ref --stdin <stdin &&
928	git rev-parse $m >actual &&
929	test_cmp expect actual
930'
931
932test_expect_success 'stdin update refs works with identity updates' '
933	cat >stdin <<-EOF &&
934	update $a $m $m
935	update $b $m $m
936	update $c $Z $E
937	EOF
938	git update-ref --stdin <stdin &&
939	git rev-parse $m >expect &&
940	git rev-parse $a >actual &&
941	test_cmp expect actual &&
942	git rev-parse $b >actual &&
943	test_cmp expect actual &&
944	test_must_fail git rev-parse --verify -q $c
945'
946
947test_expect_success 'stdin update refs fails with wrong old value' '
948	git update-ref $c $m &&
949	cat >stdin <<-EOF &&
950	update $a $m $m
951	update $b $m $m
952	update $c  ''
953	EOF
954	test_must_fail git update-ref --stdin <stdin 2>err &&
955	grep "fatal: cannot lock ref '"'"'$c'"'"'" err &&
956	git rev-parse $m >expect &&
957	git rev-parse $a >actual &&
958	test_cmp expect actual &&
959	git rev-parse $b >actual &&
960	test_cmp expect actual &&
961	git rev-parse $c >actual &&
962	test_cmp expect actual
963'
964
965test_expect_success 'stdin delete refs works with packed and loose refs' '
966	git pack-refs --all &&
967	git update-ref $c $m~1 &&
968	cat >stdin <<-EOF &&
969	delete $a $m
970	update $b $Z $m
971	update $c $E $m~1
972	EOF
973	git update-ref --stdin <stdin &&
974	test_must_fail git rev-parse --verify -q $a &&
975	test_must_fail git rev-parse --verify -q $b &&
976	test_must_fail git rev-parse --verify -q $c
977'
978
979test_expect_success 'stdin -z works on empty input' '
980	>stdin &&
981	git update-ref -z --stdin <stdin &&
982	git rev-parse --verify -q $m
983'
984
985test_expect_success 'stdin -z fails on empty line' '
986	echo "" >stdin &&
987	test_must_fail git update-ref -z --stdin <stdin 2>err &&
988	grep "fatal: whitespace before command: " err
989'
990
991test_expect_success 'stdin -z fails on empty command' '
992	printf $F "" >stdin &&
993	test_must_fail git update-ref -z --stdin <stdin 2>err &&
994	grep "fatal: empty command in input" err
995'
996
997test_expect_success 'stdin -z fails on only whitespace' '
998	printf $F " " >stdin &&
999	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1000	grep "fatal: whitespace before command:  " err
1001'
1002
1003test_expect_success 'stdin -z fails on leading whitespace' '
1004	printf $F " create $a" "$m" >stdin &&
1005	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1006	grep "fatal: whitespace before command:  create $a" err
1007'
1008
1009test_expect_success 'stdin -z fails on unknown command' '
1010	printf $F "unknown $a" >stdin &&
1011	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1012	grep "fatal: unknown command: unknown $a" err
1013'
1014
1015test_expect_success 'stdin -z fails create with no ref' '
1016	printf $F "create " >stdin &&
1017	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1018	grep "fatal: create: missing <ref>" err
1019'
1020
1021test_expect_success 'stdin -z fails create with no new value' '
1022	printf $F "create $a" >stdin &&
1023	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1024	grep "fatal: create $a: unexpected end of input when reading <newvalue>" err
1025'
1026
1027test_expect_success 'stdin -z fails create with too many arguments' '
1028	printf $F "create $a" "$m" "$m" >stdin &&
1029	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1030	grep "fatal: unknown command: $m" err
1031'
1032
1033test_expect_success 'stdin -z fails update with no ref' '
1034	printf $F "update " >stdin &&
1035	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1036	grep "fatal: update: missing <ref>" err
1037'
1038
1039test_expect_success 'stdin -z fails update with too few args' '
1040	printf $F "update $a" "$m" >stdin &&
1041	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1042	grep "fatal: update $a: unexpected end of input when reading <oldvalue>" err
1043'
1044
1045test_expect_success 'stdin -z emits warning with empty new value' '
1046	git update-ref $a $m &&
1047	printf $F "update $a" "" "" >stdin &&
1048	git update-ref -z --stdin <stdin 2>err &&
1049	grep "warning: update $a: missing <newvalue>, treating as zero" err &&
1050	test_must_fail git rev-parse --verify -q $a
1051'
1052
1053test_expect_success 'stdin -z fails update with no new value' '
1054	printf $F "update $a" >stdin &&
1055	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1056	grep "fatal: update $a: unexpected end of input when reading <newvalue>" err
1057'
1058
1059test_expect_success 'stdin -z fails update with no old value' '
1060	printf $F "update $a" "$m" >stdin &&
1061	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1062	grep "fatal: update $a: unexpected end of input when reading <oldvalue>" err
1063'
1064
1065test_expect_success 'stdin -z fails update with too many arguments' '
1066	printf $F "update $a" "$m" "$m" "$m" >stdin &&
1067	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1068	grep "fatal: unknown command: $m" err
1069'
1070
1071test_expect_success 'stdin -z fails delete with no ref' '
1072	printf $F "delete " >stdin &&
1073	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1074	grep "fatal: delete: missing <ref>" err
1075'
1076
1077test_expect_success 'stdin -z fails delete with no old value' '
1078	printf $F "delete $a" >stdin &&
1079	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1080	grep "fatal: delete $a: unexpected end of input when reading <oldvalue>" err
1081'
1082
1083test_expect_success 'stdin -z fails delete with too many arguments' '
1084	printf $F "delete $a" "$m" "$m" >stdin &&
1085	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1086	grep "fatal: unknown command: $m" err
1087'
1088
1089test_expect_success 'stdin -z fails verify with too many arguments' '
1090	printf $F "verify $a" "$m" "$m" >stdin &&
1091	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1092	grep "fatal: unknown command: $m" err
1093'
1094
1095test_expect_success 'stdin -z fails verify with no old value' '
1096	printf $F "verify $a" >stdin &&
1097	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1098	grep "fatal: verify $a: unexpected end of input when reading <oldvalue>" err
1099'
1100
1101test_expect_success 'stdin -z fails option with unknown name' '
1102	printf $F "option unknown" >stdin &&
1103	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1104	grep "fatal: option unknown: unknown" err
1105'
1106
1107test_expect_success 'stdin -z fails with duplicate refs' '
1108	printf $F "create $a" "$m" "create $b" "$m" "create $a" "$m" >stdin &&
1109	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1110	test_i18ngrep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err
1111'
1112
1113test_expect_success 'stdin -z create ref works' '
1114	printf $F "create $a" "$m" >stdin &&
1115	git update-ref -z --stdin <stdin &&
1116	git rev-parse $m >expect &&
1117	git rev-parse $a >actual &&
1118	test_cmp expect actual
1119'
1120
1121test_expect_success 'stdin -z update ref creates with zero old value' '
1122	printf $F "update $b" "$m" "$Z" >stdin &&
1123	git update-ref -z --stdin <stdin &&
1124	git rev-parse $m >expect &&
1125	git rev-parse $b >actual &&
1126	test_cmp expect actual &&
1127	git update-ref -d $b
1128'
1129
1130test_expect_success 'stdin -z update ref creates with empty old value' '
1131	printf $F "update $b" "$m" "" >stdin &&
1132	git update-ref -z --stdin <stdin &&
1133	git rev-parse $m >expect &&
1134	git rev-parse $b >actual &&
1135	test_cmp expect actual
1136'
1137
1138test_expect_success 'stdin -z create ref works with path with space to blob' '
1139	printf $F "create refs/blobs/pws" "$m:$pws" >stdin &&
1140	git update-ref -z --stdin <stdin &&
1141	git rev-parse "$m:$pws" >expect &&
1142	git rev-parse refs/blobs/pws >actual &&
1143	test_cmp expect actual &&
1144	git update-ref -d refs/blobs/pws
1145'
1146
1147test_expect_success 'stdin -z update ref fails with wrong old value' '
1148	printf $F "update $c" "$m" "$m~1" >stdin &&
1149	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1150	grep "fatal: cannot lock ref '"'"'$c'"'"'" err &&
1151	test_must_fail git rev-parse --verify -q $c
1152'
1153
1154test_expect_success 'stdin -z update ref fails with bad old value' '
1155	printf $F "update $c" "$m" "does-not-exist" >stdin &&
1156	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1157	grep "fatal: update $c: invalid <oldvalue>: does-not-exist" err &&
1158	test_must_fail git rev-parse --verify -q $c
1159'
1160
1161test_expect_success 'stdin -z create ref fails when ref exists' '
1162	git update-ref $c $m &&
1163	git rev-parse "$c" >expect &&
1164	printf $F "create $c" "$m~1" >stdin &&
1165	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1166	grep "fatal: cannot lock ref '"'"'$c'"'"'" err &&
1167	git rev-parse "$c" >actual &&
1168	test_cmp expect actual
1169'
1170
1171test_expect_success 'stdin -z create ref fails with bad new value' '
1172	git update-ref -d "$c" &&
1173	printf $F "create $c" "does-not-exist" >stdin &&
1174	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1175	grep "fatal: create $c: invalid <newvalue>: does-not-exist" err &&
1176	test_must_fail git rev-parse --verify -q $c
1177'
1178
1179test_expect_success 'stdin -z create ref fails with empty new value' '
1180	printf $F "create $c" "" >stdin &&
1181	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1182	grep "fatal: create $c: missing <newvalue>" err &&
1183	test_must_fail git rev-parse --verify -q $c
1184'
1185
1186test_expect_success 'stdin -z update ref works with right old value' '
1187	printf $F "update $b" "$m~1" "$m" >stdin &&
1188	git update-ref -z --stdin <stdin &&
1189	git rev-parse $m~1 >expect &&
1190	git rev-parse $b >actual &&
1191	test_cmp expect actual
1192'
1193
1194test_expect_success 'stdin -z delete ref fails with wrong old value' '
1195	printf $F "delete $a" "$m~1" >stdin &&
1196	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1197	grep "fatal: cannot lock ref '"'"'$a'"'"'" err &&
1198	git rev-parse $m >expect &&
1199	git rev-parse $a >actual &&
1200	test_cmp expect actual
1201'
1202
1203test_expect_success 'stdin -z delete ref fails with zero old value' '
1204	printf $F "delete $a" "$Z" >stdin &&
1205	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1206	grep "fatal: delete $a: zero <oldvalue>" err &&
1207	git rev-parse $m >expect &&
1208	git rev-parse $a >actual &&
1209	test_cmp expect actual
1210'
1211
1212test_expect_success 'stdin -z update symref works option no-deref' '
1213	git symbolic-ref TESTSYMREF $b &&
1214	printf $F "option no-deref" "update TESTSYMREF" "$a" "$b" >stdin &&
1215	git update-ref -z --stdin <stdin &&
1216	git rev-parse TESTSYMREF >expect &&
1217	git rev-parse $a >actual &&
1218	test_cmp expect actual &&
1219	git rev-parse $m~1 >expect &&
1220	git rev-parse $b >actual &&
1221	test_cmp expect actual
1222'
1223
1224test_expect_success 'stdin -z delete symref works option no-deref' '
1225	git symbolic-ref TESTSYMREF $b &&
1226	printf $F "option no-deref" "delete TESTSYMREF" "$b" >stdin &&
1227	git update-ref -z --stdin <stdin &&
1228	test_must_fail git rev-parse --verify -q TESTSYMREF &&
1229	git rev-parse $m~1 >expect &&
1230	git rev-parse $b >actual &&
1231	test_cmp expect actual
1232'
1233
1234test_expect_success 'stdin -z delete ref works with right old value' '
1235	printf $F "delete $b" "$m~1" >stdin &&
1236	git update-ref -z --stdin <stdin &&
1237	test_must_fail git rev-parse --verify -q $b
1238'
1239
1240test_expect_success 'stdin -z update/create/verify combination works' '
1241	printf $F "update $a" "$m" "" "create $b" "$m" "verify $c" "" >stdin &&
1242	git update-ref -z --stdin <stdin &&
1243	git rev-parse $m >expect &&
1244	git rev-parse $a >actual &&
1245	test_cmp expect actual &&
1246	git rev-parse $b >actual &&
1247	test_cmp expect actual &&
1248	test_must_fail git rev-parse --verify -q $c
1249'
1250
1251test_expect_success 'stdin -z verify succeeds for correct value' '
1252	git rev-parse $m >expect &&
1253	printf $F "verify $m" "$m" >stdin &&
1254	git update-ref -z --stdin <stdin &&
1255	git rev-parse $m >actual &&
1256	test_cmp expect actual
1257'
1258
1259test_expect_success 'stdin -z verify succeeds for missing reference' '
1260	printf $F "verify refs/heads/missing" "$Z" >stdin &&
1261	git update-ref -z --stdin <stdin &&
1262	test_must_fail git rev-parse --verify -q refs/heads/missing
1263'
1264
1265test_expect_success 'stdin -z verify treats no value as missing' '
1266	printf $F "verify refs/heads/missing" "" >stdin &&
1267	git update-ref -z --stdin <stdin &&
1268	test_must_fail git rev-parse --verify -q refs/heads/missing
1269'
1270
1271test_expect_success 'stdin -z verify fails for wrong value' '
1272	git rev-parse $m >expect &&
1273	printf $F "verify $m" "$m~1" >stdin &&
1274	test_must_fail git update-ref -z --stdin <stdin &&
1275	git rev-parse $m >actual &&
1276	test_cmp expect actual
1277'
1278
1279test_expect_success 'stdin -z verify fails for mistaken null value' '
1280	git rev-parse $m >expect &&
1281	printf $F "verify $m" "$Z" >stdin &&
1282	test_must_fail git update-ref -z --stdin <stdin &&
1283	git rev-parse $m >actual &&
1284	test_cmp expect actual
1285'
1286
1287test_expect_success 'stdin -z verify fails for mistaken empty value' '
1288	M=$(git rev-parse $m) &&
1289	test_when_finished "git update-ref $m $M" &&
1290	git rev-parse $m >expect &&
1291	printf $F "verify $m" "" >stdin &&
1292	test_must_fail git update-ref -z --stdin <stdin &&
1293	git rev-parse $m >actual &&
1294	test_cmp expect actual
1295'
1296
1297test_expect_success 'stdin -z update refs works with identity updates' '
1298	printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$Z" "" >stdin &&
1299	git update-ref -z --stdin <stdin &&
1300	git rev-parse $m >expect &&
1301	git rev-parse $a >actual &&
1302	test_cmp expect actual &&
1303	git rev-parse $b >actual &&
1304	test_cmp expect actual &&
1305	test_must_fail git rev-parse --verify -q $c
1306'
1307
1308test_expect_success 'stdin -z update refs fails with wrong old value' '
1309	git update-ref $c $m &&
1310	printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$m" "$Z" >stdin &&
1311	test_must_fail git update-ref -z --stdin <stdin 2>err &&
1312	grep "fatal: cannot lock ref '"'"'$c'"'"'" err &&
1313	git rev-parse $m >expect &&
1314	git rev-parse $a >actual &&
1315	test_cmp expect actual &&
1316	git rev-parse $b >actual &&
1317	test_cmp expect actual &&
1318	git rev-parse $c >actual &&
1319	test_cmp expect actual
1320'
1321
1322test_expect_success 'stdin -z delete refs works with packed and loose refs' '
1323	git pack-refs --all &&
1324	git update-ref $c $m~1 &&
1325	printf $F "delete $a" "$m" "update $b" "$Z" "$m" "update $c" "" "$m~1" >stdin &&
1326	git update-ref -z --stdin <stdin &&
1327	test_must_fail git rev-parse --verify -q $a &&
1328	test_must_fail git rev-parse --verify -q $b &&
1329	test_must_fail git rev-parse --verify -q $c
1330'
1331
1332test_expect_success 'fails with duplicate HEAD update' '
1333	git branch target1 $A &&
1334	git checkout target1 &&
1335	cat >stdin <<-EOF &&
1336	update refs/heads/target1 $C
1337	option no-deref
1338	update HEAD $B
1339	EOF
1340	test_must_fail git update-ref --stdin <stdin 2>err &&
1341	test_i18ngrep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err &&
1342	echo "refs/heads/target1" >expect &&
1343	git symbolic-ref HEAD >actual &&
1344	test_cmp expect actual &&
1345	echo "$A" >expect &&
1346	git rev-parse refs/heads/target1 >actual &&
1347	test_cmp expect actual
1348'
1349
1350test_expect_success 'fails with duplicate ref update via symref' '
1351	git branch target2 $A &&
1352	git symbolic-ref refs/heads/symref2 refs/heads/target2 &&
1353	cat >stdin <<-EOF &&
1354	update refs/heads/target2 $C
1355	update refs/heads/symref2 $B
1356	EOF
1357	test_must_fail git update-ref --stdin <stdin 2>err &&
1358	test_i18ngrep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err &&
1359	echo "refs/heads/target2" >expect &&
1360	git symbolic-ref refs/heads/symref2 >actual &&
1361	test_cmp expect actual &&
1362	echo "$A" >expect &&
1363	git rev-parse refs/heads/target2 >actual &&
1364	test_cmp expect actual
1365'
1366
1367test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches does not burst open file limit' '
1368(
1369	for i in $(test_seq 33)
1370	do
1371		echo "create refs/heads/$i HEAD"
1372	done >large_input &&
1373	run_with_limited_open_files git update-ref --stdin <large_input &&
1374	git rev-parse --verify -q refs/heads/33
1375)
1376'
1377
1378test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction deleting branches does not burst open file limit' '
1379(
1380	for i in $(test_seq 33)
1381	do
1382		echo "delete refs/heads/$i HEAD"
1383	done >large_input &&
1384	run_with_limited_open_files git update-ref --stdin <large_input &&
1385	test_must_fail git rev-parse --verify -q refs/heads/33
1386)
1387'
1388
1389test_expect_success 'handle per-worktree refs in refs/bisect' '
1390	git commit --allow-empty -m "initial commit" &&
1391	git worktree add -b branch worktree &&
1392	(
1393		cd worktree &&
1394		git commit --allow-empty -m "test commit"  &&
1395		git for-each-ref >for-each-ref.out &&
1396		! grep refs/bisect for-each-ref.out &&
1397		git update-ref refs/bisect/something HEAD &&
1398		git rev-parse refs/bisect/something >../worktree-head &&
1399		git for-each-ref | grep refs/bisect/something
1400	) &&
1401	git show-ref >actual &&
1402	! grep 'refs/bisect' actual &&
1403	test_must_fail git rev-parse refs/bisect/something &&
1404	git update-ref refs/bisect/something HEAD &&
1405	git rev-parse refs/bisect/something >main-head &&
1406	! test_cmp main-head worktree-head
1407'
1408
1409test_expect_success 'transaction handles empty commit' '
1410	cat >stdin <<-EOF &&
1411	start
1412	prepare
1413	commit
1414	EOF
1415	git update-ref --stdin <stdin >actual &&
1416	printf "%s: ok\n" start prepare commit >expect &&
1417	test_cmp expect actual
1418'
1419
1420test_expect_success 'transaction handles empty commit with missing prepare' '
1421	cat >stdin <<-EOF &&
1422	start
1423	commit
1424	EOF
1425	git update-ref --stdin <stdin >actual &&
1426	printf "%s: ok\n" start commit >expect &&
1427	test_cmp expect actual
1428'
1429
1430test_expect_success 'transaction handles sole commit' '
1431	cat >stdin <<-EOF &&
1432	commit
1433	EOF
1434	git update-ref --stdin <stdin >actual &&
1435	printf "%s: ok\n" commit >expect &&
1436	test_cmp expect actual
1437'
1438
1439test_expect_success 'transaction handles empty abort' '
1440	cat >stdin <<-EOF &&
1441	start
1442	prepare
1443	abort
1444	EOF
1445	git update-ref --stdin <stdin >actual &&
1446	printf "%s: ok\n" start prepare abort >expect &&
1447	test_cmp expect actual
1448'
1449
1450test_expect_success 'transaction exits on multiple aborts' '
1451	cat >stdin <<-EOF &&
1452	abort
1453	abort
1454	EOF
1455	test_must_fail git update-ref --stdin <stdin >actual 2>err &&
1456	printf "%s: ok\n" abort >expect &&
1457	test_cmp expect actual &&
1458	grep "fatal: transaction is closed" err
1459'
1460
1461test_expect_success 'transaction exits on start after prepare' '
1462	cat >stdin <<-EOF &&
1463	prepare
1464	start
1465	EOF
1466	test_must_fail git update-ref --stdin <stdin 2>err >actual &&
1467	printf "%s: ok\n" prepare >expect &&
1468	test_cmp expect actual &&
1469	grep "fatal: prepared transactions can only be closed" err
1470'
1471
1472test_expect_success 'transaction handles empty abort with missing prepare' '
1473	cat >stdin <<-EOF &&
1474	start
1475	abort
1476	EOF
1477	git update-ref --stdin <stdin >actual &&
1478	printf "%s: ok\n" start abort >expect &&
1479	test_cmp expect actual
1480'
1481
1482test_expect_success 'transaction handles sole abort' '
1483	cat >stdin <<-EOF &&
1484	abort
1485	EOF
1486	git update-ref --stdin <stdin >actual &&
1487	printf "%s: ok\n" abort >expect &&
1488	test_cmp expect actual
1489'
1490
1491test_expect_success 'transaction can handle commit' '
1492	cat >stdin <<-EOF &&
1493	start
1494	create $a HEAD
1495	commit
1496	EOF
1497	git update-ref --stdin <stdin >actual &&
1498	printf "%s: ok\n" start commit >expect &&
1499	test_cmp expect actual &&
1500	git rev-parse HEAD >expect &&
1501	git rev-parse $a >actual &&
1502	test_cmp expect actual
1503'
1504
1505test_expect_success 'transaction can handle abort' '
1506	cat >stdin <<-EOF &&
1507	start
1508	create $b HEAD
1509	abort
1510	EOF
1511	git update-ref --stdin <stdin >actual &&
1512	printf "%s: ok\n" start abort >expect &&
1513	test_cmp expect actual &&
1514	test_must_fail git show-ref --verify -q $b
1515'
1516
1517test_expect_success 'transaction aborts by default' '
1518	cat >stdin <<-EOF &&
1519	start
1520	create $b HEAD
1521	EOF
1522	git update-ref --stdin <stdin >actual &&
1523	printf "%s: ok\n" start >expect &&
1524	test_cmp expect actual &&
1525	test_must_fail git show-ref --verify -q $b
1526'
1527
1528test_expect_success 'transaction with prepare aborts by default' '
1529	cat >stdin <<-EOF &&
1530	start
1531	create $b HEAD
1532	prepare
1533	EOF
1534	git update-ref --stdin <stdin >actual &&
1535	printf "%s: ok\n" start prepare >expect &&
1536	test_cmp expect actual &&
1537	test_must_fail git show-ref --verify -q $b
1538'
1539
1540test_expect_success 'transaction can commit multiple times' '
1541	cat >stdin <<-EOF &&
1542	start
1543	create refs/heads/branch-1 $A
1544	commit
1545	start
1546	create refs/heads/branch-2 $B
1547	commit
1548	EOF
1549	git update-ref --stdin <stdin >actual &&
1550	printf "%s: ok\n" start commit start commit >expect &&
1551	test_cmp expect actual &&
1552	echo "$A" >expect &&
1553	git rev-parse refs/heads/branch-1 >actual &&
1554	test_cmp expect actual &&
1555	echo "$B" >expect &&
1556	git rev-parse refs/heads/branch-2 >actual &&
1557	test_cmp expect actual
1558'
1559
1560test_expect_success 'transaction can create and delete' '
1561	cat >stdin <<-EOF &&
1562	start
1563	create refs/heads/create-and-delete $A
1564	commit
1565	start
1566	delete refs/heads/create-and-delete $A
1567	commit
1568	EOF
1569	git update-ref --stdin <stdin >actual &&
1570	printf "%s: ok\n" start commit start commit >expect &&
1571	test_must_fail git show-ref --verify refs/heads/create-and-delete
1572'
1573
1574test_expect_success 'transaction can commit after abort' '
1575	cat >stdin <<-EOF &&
1576	start
1577	create refs/heads/abort $A
1578	abort
1579	start
1580	create refs/heads/abort $A
1581	commit
1582	EOF
1583	git update-ref --stdin <stdin >actual &&
1584	printf "%s: ok\n" start abort start commit >expect &&
1585	echo "$A" >expect &&
1586	git rev-parse refs/heads/abort >actual &&
1587	test_cmp expect actual
1588'
1589
1590test_expect_success 'transaction cannot restart ongoing transaction' '
1591	cat >stdin <<-EOF &&
1592	start
1593	create refs/heads/restart $A
1594	start
1595	commit
1596	EOF
1597	test_must_fail git update-ref --stdin <stdin >actual &&
1598	test_must_fail git show-ref --verify refs/heads/restart
1599'
1600
1601test_expect_success PIPE 'transaction flushes status updates' '
1602	mkfifo in out &&
1603	(git update-ref --stdin <in >out &) &&
1604
1605	exec 9>in &&
1606	exec 8<out &&
1607	test_when_finished "exec 9>&-" &&
1608	test_when_finished "exec 8<&-" &&
1609
1610	echo "start" >&9 &&
1611	echo "start: ok" >expected &&
1612	read line <&8 &&
1613	echo "$line" >actual &&
1614	test_cmp expected actual &&
1615
1616	echo "create refs/heads/flush $A" >&9 &&
1617
1618	echo prepare >&9 &&
1619	echo "prepare: ok" >expected &&
1620	read line <&8 &&
1621	echo "$line" >actual &&
1622	test_cmp expected actual &&
1623
1624	# This must now fail given that we have locked the ref.
1625	test_must_fail git update-ref refs/heads/flush $B 2>stderr &&
1626	grep "fatal: update_ref failed for ref ${SQ}refs/heads/flush${SQ}: cannot lock ref" stderr &&
1627
1628	echo commit >&9 &&
1629	echo "commit: ok" >expected &&
1630	read line <&8 &&
1631	echo "$line" >actual &&
1632	test_cmp expected actual
1633'
1634
1635test_expect_success 'directory not created deleting packed ref' '
1636	git branch d1/d2/r1 HEAD &&
1637	git pack-refs --all &&
1638	test_path_is_missing .git/refs/heads/d1/d2 &&
1639	git update-ref -d refs/heads/d1/d2/r1 &&
1640	test_path_is_missing .git/refs/heads/d1/d2 &&
1641	test_path_is_missing .git/refs/heads/d1
1642'
1643
1644test_done
1645