3 test_description
='git fetch output format'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 TEST_PASSES_SANITIZE_LEAK
=true
11 test_expect_success
'fetch with invalid output format configuration' '
12 test_when_finished "rm -rf clone" &&
15 test_must_fail git -C clone -c fetch.output fetch origin 2>actual.err &&
17 error: missing value for ${SQ}fetch.output${SQ}
18 fatal: unable to parse ${SQ}fetch.output${SQ} from command-line config
20 test_cmp expect actual.err &&
22 test_must_fail git -C clone -c fetch.output= fetch origin 2>actual.err &&
24 fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}${SQ}
26 test_cmp expect actual.err &&
28 test_must_fail git -C clone -c fetch.output=garbage fetch origin 2>actual.err &&
30 fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}garbage${SQ}
32 test_cmp expect actual.err
35 test_expect_success
'fetch aligned output' '
36 git clone . full-output &&
37 test_commit looooooooooooong-tag &&
40 git -c fetch.output=full fetch origin >actual 2>&1 &&
41 grep -e "->" actual | cut -c 22- >../actual
43 cat >expect <<-\EOF &&
45 looooooooooooong-tag -> looooooooooooong-tag
47 test_cmp expect actual
50 test_expect_success
'fetch compact output' '
51 git clone . compact &&
52 test_commit extraaa &&
55 git -c fetch.output=compact fetch origin >actual 2>&1 &&
56 grep -e "->" actual | cut -c 22- >../actual
58 cat >expect <<-\EOF &&
62 test_cmp expect actual
65 test_expect_success
'setup for fetch porcelain output' '
66 # Set up a bunch of references that we can use to demonstrate different
67 # kinds of flag symbols in the output format.
68 test_commit commit-for-porcelain-output &&
69 MAIN_OLD=$(git rev-parse HEAD) &&
70 git branch "fast-forward" &&
71 git branch "deleted-branch" &&
72 git checkout -b force-updated &&
73 test_commit --no-tag force-update-old &&
74 FORCE_UPDATED_OLD=$(git rev-parse HEAD) &&
77 # Backup to preseed.git
78 git clone --mirror . preseed.git &&
80 # Continue changing our local references.
81 git branch new-branch &&
82 git branch -d deleted-branch &&
83 git checkout fast-forward &&
84 test_commit --no-tag fast-forward-new &&
85 FAST_FORWARD_NEW=$(git rev-parse HEAD) &&
86 git checkout force-updated &&
87 git reset --hard HEAD~ &&
88 test_commit --no-tag force-update-new &&
89 FORCE_UPDATED_NEW=$(git rev-parse HEAD)
92 for opt
in "" "--atomic"
94 test_expect_success
"fetch porcelain output ${opt:+(atomic)}" '
95 test_when_finished "rm -rf porcelain" &&
97 # Clone and pre-seed the repositories. We fetch references into two
98 # namespaces so that we can test that rejected and force-updated
99 # references are reported properly.
100 refspecs="refs/heads/*:refs/unforced/* +refs/heads/*:refs/forced/*" &&
101 git clone preseed.git porcelain &&
102 git -C porcelain fetch origin $opt $refspecs &&
104 cat >expect <<-EOF &&
105 - $MAIN_OLD $ZERO_OID refs/forced/deleted-branch
106 - $MAIN_OLD $ZERO_OID refs/unforced/deleted-branch
107 $MAIN_OLD $FAST_FORWARD_NEW refs/unforced/fast-forward
108 ! $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/unforced/force-updated
109 * $ZERO_OID $MAIN_OLD refs/unforced/new-branch
110 $MAIN_OLD $FAST_FORWARD_NEW refs/forced/fast-forward
111 + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/forced/force-updated
112 * $ZERO_OID $MAIN_OLD refs/forced/new-branch
113 $MAIN_OLD $FAST_FORWARD_NEW refs/remotes/origin/fast-forward
114 + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/remotes/origin/force-updated
115 * $ZERO_OID $MAIN_OLD refs/remotes/origin/new-branch
118 # Change the URL of the repository to fetch different references.
119 git -C porcelain remote set-url origin .. &&
121 # Execute a dry-run fetch first. We do this to assert that the dry-run
122 # and non-dry-run fetches produces the same output. Execution of the
123 # fetch is expected to fail as we have a rejected reference update.
124 test_must_fail git -C porcelain fetch $opt \
125 --porcelain --dry-run --prune origin $refspecs >actual &&
126 test_cmp expect actual &&
128 # And now we perform a non-dry-run fetch.
129 test_must_fail git -C porcelain fetch $opt \
130 --porcelain --prune origin $refspecs >actual 2>stderr &&
131 test_cmp expect actual &&
132 test_must_be_empty stderr
136 test_expect_success
'fetch porcelain with multiple remotes' '
137 test_when_finished "rm -rf porcelain" &&
139 git switch --create multiple-remotes &&
140 git clone . porcelain &&
141 git -C porcelain remote add second-remote "$PWD" &&
142 git -C porcelain fetch second-remote &&
144 test_commit --no-tag multi-commit &&
145 old_commit=$(git rev-parse HEAD~) &&
146 new_commit=$(git rev-parse HEAD) &&
148 cat >expect <<-EOF &&
149 $old_commit $new_commit refs/remotes/origin/multiple-remotes
150 $old_commit $new_commit refs/remotes/second-remote/multiple-remotes
153 git -C porcelain fetch --porcelain --all >actual 2>stderr &&
154 test_cmp expect actual &&
155 test_must_be_empty stderr
158 test_expect_success
'fetch porcelain refuses to work with submodules' '
159 test_when_finished "rm -rf porcelain" &&
161 cat >expect <<-EOF &&
162 fatal: options ${SQ}--porcelain${SQ} and ${SQ}--recurse-submodules${SQ} cannot be used together
165 git init porcelain &&
166 test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=yes 2>stderr &&
167 test_cmp expect stderr &&
169 test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=on-demand 2>stderr &&
170 test_cmp expect stderr
173 test_expect_success
'fetch porcelain overrides fetch.output config' '
174 test_when_finished "rm -rf porcelain" &&
176 git switch --create config-override &&
177 git clone . porcelain &&
178 test_commit new-commit &&
179 old_commit=$(git rev-parse HEAD~) &&
180 new_commit=$(git rev-parse HEAD) &&
182 cat >expect <<-EOF &&
183 $old_commit $new_commit refs/remotes/origin/config-override
184 * $ZERO_OID $new_commit refs/tags/new-commit
187 git -C porcelain -c fetch.output=compact fetch --porcelain >stdout 2>stderr &&
188 test_must_be_empty stderr &&
189 test_cmp expect stdout
192 test_expect_success
'fetch --no-porcelain overrides previous --porcelain' '
193 test_when_finished "rm -rf no-porcelain" &&
195 git switch --create no-porcelain &&
196 git clone . no-porcelain &&
197 test_commit --no-tag no-porcelain &&
198 old_commit=$(git rev-parse --short HEAD~) &&
199 new_commit=$(git rev-parse --short HEAD) &&
201 cat >expect <<-EOF &&
202 From $(test-tool path-utils real_path .)/.
203 $old_commit..$new_commit no-porcelain -> origin/no-porcelain
206 git -C no-porcelain fetch --porcelain --no-porcelain >stdout 2>stderr &&
207 test_cmp expect stderr &&
208 test_must_be_empty stdout
211 test_expect_success
'fetch output with HEAD' '
212 test_when_finished "rm -rf head" &&
215 git -C head fetch --dry-run origin HEAD >actual.out 2>actual.err &&
216 cat >expect <<-EOF &&
217 From $(test-tool path-utils real_path .)/.
218 * branch HEAD -> FETCH_HEAD
220 test_must_be_empty actual.out &&
221 test_cmp expect actual.err &&
223 git -C head fetch origin HEAD >actual.out 2>actual.err &&
224 test_must_be_empty actual.out &&
225 test_cmp expect actual.err &&
227 git -C head fetch --dry-run origin HEAD:foo >actual.out 2>actual.err &&
228 cat >expect <<-EOF &&
229 From $(test-tool path-utils real_path .)/.
230 * [new ref] HEAD -> foo
232 test_must_be_empty actual.out &&
233 test_cmp expect actual.err &&
235 git -C head fetch origin HEAD:foo >actual.out 2>actual.err &&
236 test_must_be_empty actual.out &&
237 test_cmp expect actual.err
240 test_expect_success
'fetch porcelain output with HEAD' '
241 test_when_finished "rm -rf head" &&
243 COMMIT_ID=$(git rev-parse HEAD) &&
245 git -C head fetch --porcelain --dry-run origin HEAD >actual &&
246 cat >expect <<-EOF &&
247 * $ZERO_OID $COMMIT_ID FETCH_HEAD
249 test_cmp expect actual &&
251 git -C head fetch --porcelain origin HEAD >actual &&
252 test_cmp expect actual &&
254 git -C head fetch --porcelain --dry-run origin HEAD:foo >actual &&
255 cat >expect <<-EOF &&
256 * $ZERO_OID $COMMIT_ID refs/heads/foo
258 test_cmp expect actual &&
260 git -C head fetch --porcelain origin HEAD:foo >actual &&
261 test_cmp expect actual
264 test_expect_success
'fetch output with object ID' '
265 test_when_finished "rm -rf object-id" &&
266 git clone . object-id &&
267 commit=$(git rev-parse HEAD) &&
269 git -C object-id fetch --dry-run origin $commit:object-id >actual.out 2>actual.err &&
270 cat >expect <<-EOF &&
271 From $(test-tool path-utils real_path .)/.
272 * [new ref] $commit -> object-id
274 test_must_be_empty actual.out &&
275 test_cmp expect actual.err &&
277 git -C object-id fetch origin $commit:object-id >actual.out 2>actual.err &&
278 test_must_be_empty actual.out &&
279 test_cmp expect actual.err
282 test_expect_success
'--no-show-forced-updates' '
283 mkdir forced-updates &&
290 git clone forced-updates forced-update-clone &&
291 git clone forced-updates no-forced-update-clone &&
292 git -C forced-updates reset --hard HEAD~1 &&
294 cd forced-update-clone &&
295 git fetch --show-forced-updates origin 2>output &&
296 test_grep "(forced update)" output
299 cd no-forced-update-clone &&
300 git fetch --no-show-forced-updates origin 2>output &&
301 test_grep ! "(forced update)" output