3 test_description
='git fetch output format'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10 test_expect_success
'fetch with invalid output format configuration' '
11 test_when_finished "rm -rf clone" &&
14 test_must_fail git -C clone -c fetch.output fetch origin 2>actual.err &&
16 error: missing value for ${SQ}fetch.output${SQ}
17 fatal: unable to parse ${SQ}fetch.output${SQ} from command-line config
19 test_cmp expect actual.err &&
21 test_must_fail git -C clone -c fetch.output= fetch origin 2>actual.err &&
23 fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}${SQ}
25 test_cmp expect actual.err &&
27 test_must_fail git -C clone -c fetch.output=garbage fetch origin 2>actual.err &&
29 fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}garbage${SQ}
31 test_cmp expect actual.err
34 test_expect_success
'fetch aligned output' '
35 git clone . full-output &&
36 test_commit looooooooooooong-tag &&
39 git -c fetch.output=full fetch origin >actual 2>&1 &&
40 grep -e "->" actual | cut -c 22- >../actual
42 cat >expect <<-\EOF &&
44 looooooooooooong-tag -> looooooooooooong-tag
46 test_cmp expect actual
49 test_expect_success
'fetch compact output' '
50 git clone . compact &&
51 test_commit extraaa &&
54 git -c fetch.output=compact fetch origin >actual 2>&1 &&
55 grep -e "->" actual | cut -c 22- >../actual
57 cat >expect <<-\EOF &&
61 test_cmp expect actual
64 test_expect_success
'setup for fetch porcelain output' '
65 # Set up a bunch of references that we can use to demonstrate different
66 # kinds of flag symbols in the output format.
67 test_commit commit-for-porcelain-output &&
68 MAIN_OLD=$(git rev-parse HEAD) &&
69 git branch "fast-forward" &&
70 git branch "deleted-branch" &&
71 git checkout -b force-updated &&
72 test_commit --no-tag force-update-old &&
73 FORCE_UPDATED_OLD=$(git rev-parse HEAD) &&
76 # Backup to preseed.git
77 git clone --mirror . preseed.git &&
79 # Continue changing our local references.
80 git branch new-branch &&
81 git branch -d deleted-branch &&
82 git checkout fast-forward &&
83 test_commit --no-tag fast-forward-new &&
84 FAST_FORWARD_NEW=$(git rev-parse HEAD) &&
85 git checkout force-updated &&
86 git reset --hard HEAD~ &&
87 test_commit --no-tag force-update-new &&
88 FORCE_UPDATED_NEW=$(git rev-parse HEAD)
91 for opt
in "" "--atomic"
93 test_expect_success
"fetch porcelain output ${opt:+(atomic)}" '
94 test_when_finished "rm -rf porcelain" &&
96 # Clone and pre-seed the repositories. We fetch references into two
97 # namespaces so that we can test that rejected and force-updated
98 # references are reported properly.
99 refspecs="refs/heads/*:refs/unforced/* +refs/heads/*:refs/forced/*" &&
100 git clone preseed.git porcelain &&
101 git -C porcelain fetch origin $opt $refspecs &&
103 cat >expect <<-EOF &&
104 - $MAIN_OLD $ZERO_OID refs/forced/deleted-branch
105 - $MAIN_OLD $ZERO_OID refs/unforced/deleted-branch
106 $MAIN_OLD $FAST_FORWARD_NEW refs/unforced/fast-forward
107 ! $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/unforced/force-updated
108 * $ZERO_OID $MAIN_OLD refs/unforced/new-branch
109 $MAIN_OLD $FAST_FORWARD_NEW refs/forced/fast-forward
110 + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/forced/force-updated
111 * $ZERO_OID $MAIN_OLD refs/forced/new-branch
112 $MAIN_OLD $FAST_FORWARD_NEW refs/remotes/origin/fast-forward
113 + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/remotes/origin/force-updated
114 * $ZERO_OID $MAIN_OLD refs/remotes/origin/new-branch
117 # Change the URL of the repository to fetch different references.
118 git -C porcelain remote set-url origin .. &&
120 # Execute a dry-run fetch first. We do this to assert that the dry-run
121 # and non-dry-run fetches produces the same output. Execution of the
122 # fetch is expected to fail as we have a rejected reference update.
123 test_must_fail git -C porcelain fetch $opt \
124 --porcelain --dry-run --prune origin $refspecs >actual &&
125 test_cmp expect actual &&
127 # And now we perform a non-dry-run fetch.
128 test_must_fail git -C porcelain fetch $opt \
129 --porcelain --prune origin $refspecs >actual 2>stderr &&
130 test_cmp expect actual &&
131 test_must_be_empty stderr
135 test_expect_success
'fetch porcelain with multiple remotes' '
136 test_when_finished "rm -rf porcelain" &&
138 git switch --create multiple-remotes &&
139 git clone . porcelain &&
140 git -C porcelain remote add second-remote "$PWD" &&
141 git -C porcelain fetch second-remote &&
143 test_commit --no-tag multi-commit &&
144 old_commit=$(git rev-parse HEAD~) &&
145 new_commit=$(git rev-parse HEAD) &&
147 cat >expect <<-EOF &&
148 $old_commit $new_commit refs/remotes/origin/multiple-remotes
149 $old_commit $new_commit refs/remotes/second-remote/multiple-remotes
152 git -C porcelain fetch --porcelain --all >actual 2>stderr &&
153 test_cmp expect actual &&
154 test_must_be_empty stderr
157 test_expect_success
'fetch porcelain refuses to work with submodules' '
158 test_when_finished "rm -rf porcelain" &&
160 cat >expect <<-EOF &&
161 fatal: options ${SQ}--porcelain${SQ} and ${SQ}--recurse-submodules${SQ} cannot be used together
164 git init porcelain &&
165 test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=yes 2>stderr &&
166 test_cmp expect stderr &&
168 test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=on-demand 2>stderr &&
169 test_cmp expect stderr
172 test_expect_success
'fetch porcelain overrides fetch.output config' '
173 test_when_finished "rm -rf porcelain" &&
175 git switch --create config-override &&
176 git clone . porcelain &&
177 test_commit new-commit &&
178 old_commit=$(git rev-parse HEAD~) &&
179 new_commit=$(git rev-parse HEAD) &&
181 cat >expect <<-EOF &&
182 $old_commit $new_commit refs/remotes/origin/config-override
183 * $ZERO_OID $new_commit refs/tags/new-commit
186 git -C porcelain -c fetch.output=compact fetch --porcelain >stdout 2>stderr &&
187 test_must_be_empty stderr &&
188 test_cmp expect stdout
191 test_expect_success
'fetch --no-porcelain overrides previous --porcelain' '
192 test_when_finished "rm -rf no-porcelain" &&
194 git switch --create no-porcelain &&
195 git clone . no-porcelain &&
196 test_commit --no-tag no-porcelain &&
197 old_commit=$(git rev-parse --short HEAD~) &&
198 new_commit=$(git rev-parse --short HEAD) &&
200 cat >expect <<-EOF &&
201 From $(test-tool path-utils real_path .)/.
202 $old_commit..$new_commit no-porcelain -> origin/no-porcelain
205 git -C no-porcelain fetch --porcelain --no-porcelain >stdout 2>stderr &&
206 test_cmp expect stderr &&
207 test_must_be_empty stdout
210 test_expect_success
'fetch output with HEAD' '
211 test_when_finished "rm -rf head" &&
214 git -C head fetch --dry-run origin HEAD >actual.out 2>actual.err &&
215 cat >expect <<-EOF &&
216 From $(test-tool path-utils real_path .)/.
217 * branch HEAD -> FETCH_HEAD
219 test_must_be_empty actual.out &&
220 test_cmp expect actual.err &&
222 git -C head fetch origin HEAD >actual.out 2>actual.err &&
223 test_must_be_empty actual.out &&
224 test_cmp expect actual.err &&
226 git -C head fetch --dry-run origin HEAD:foo >actual.out 2>actual.err &&
227 cat >expect <<-EOF &&
228 From $(test-tool path-utils real_path .)/.
229 * [new ref] HEAD -> foo
231 test_must_be_empty actual.out &&
232 test_cmp expect actual.err &&
234 git -C head fetch origin HEAD:foo >actual.out 2>actual.err &&
235 test_must_be_empty actual.out &&
236 test_cmp expect actual.err
239 test_expect_success
'fetch porcelain output with HEAD' '
240 test_when_finished "rm -rf head" &&
242 COMMIT_ID=$(git rev-parse HEAD) &&
244 git -C head fetch --porcelain --dry-run origin HEAD >actual &&
245 cat >expect <<-EOF &&
246 * $ZERO_OID $COMMIT_ID FETCH_HEAD
248 test_cmp expect actual &&
250 git -C head fetch --porcelain origin HEAD >actual &&
251 test_cmp expect actual &&
253 git -C head fetch --porcelain --dry-run origin HEAD:foo >actual &&
254 cat >expect <<-EOF &&
255 * $ZERO_OID $COMMIT_ID refs/heads/foo
257 test_cmp expect actual &&
259 git -C head fetch --porcelain origin HEAD:foo >actual &&
260 test_cmp expect actual
263 test_expect_success
'fetch output with object ID' '
264 test_when_finished "rm -rf object-id" &&
265 git clone . object-id &&
266 commit=$(git rev-parse HEAD) &&
268 git -C object-id fetch --dry-run origin $commit:object-id >actual.out 2>actual.err &&
269 cat >expect <<-EOF &&
270 From $(test-tool path-utils real_path .)/.
271 * [new ref] $commit -> object-id
273 test_must_be_empty actual.out &&
274 test_cmp expect actual.err &&
276 git -C object-id fetch origin $commit:object-id >actual.out 2>actual.err &&
277 test_must_be_empty actual.out &&
278 test_cmp expect actual.err
281 test_expect_success
'--no-show-forced-updates' '
282 mkdir forced-updates &&
289 git clone forced-updates forced-update-clone &&
290 git clone forced-updates no-forced-update-clone &&
291 git -C forced-updates reset --hard HEAD~1 &&
293 cd forced-update-clone &&
294 git fetch --show-forced-updates origin 2>output &&
295 test_grep "(forced update)" output
298 cd no-forced-update-clone &&
299 git fetch --no-show-forced-updates origin 2>output &&
300 test_grep ! "(forced update)" output