fetch: add new config option fetch.all
Introduce a boolean configuration option fetch.all which allows to fetch all available remotes by default. The config option can be overridden by explicitly specifying a remote or by using --no-all. The behavior for --all is unchanged and calling git-fetch with --all and a remote will still result in an error. Additionally, describe the configuration variable in the config documentation and implement new tests to cover the expected behavior. Also add --no-all to the command-line documentation of git-fetch. Signed-off-by: Tamino Bauknecht <dev@tb6.eu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Tamino Bauknecht committed
Jan 8, 2024 at 22:13 UTC
39487a1510fcdbb4124882f531a077dbdfe1ef60
4 files changed
+186
-3
Documentation/config/fetch.txt
+6
@@ -50,6 +50,12 @@ fetch.pruneTags::
50
refs. See also `remote.<name>.pruneTags` and the PRUNING
51
section of linkgit:git-fetch[1].
52
53
+fetch.all::
54
+ If true, fetch will attempt to update all available remotes.
55
+ This behavior can be overridden by passing `--no-all` or by
56
+ explicitly specifying one or more remote(s) to fetch from.
57
+ Defaults to false.
58
+
59
fetch.output::
60
Control how ref update status is printed. Valid values are
61
`full` and `compact`. Default value is `full`. See the
Documentation/fetch-options.txt
+3
-2
@@ -1,5 +1,6 @@
1
---all::
2
- Fetch all remotes.
1
+--[no-]all::
2
+ Fetch all remotes. This overrides the configuration variable
3
+ `fetch.all`.
4
5
-a::
6
--append::
builtin/fetch.c
+16
-1
@@ -102,6 +102,7 @@ static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
102
103
struct fetch_config {
104
enum display_format display_format;
105
+ int all;
106
int prune;
107
int prune_tags;
108
int show_forced_updates;
@@ -115,6 +116,11 @@ static int git_fetch_config(const char *k, const char *v,
116
{
117
struct fetch_config *fetch_config = cb;
118
119
+ if (!strcmp(k, "fetch.all")) {
120
+ fetch_config->all = git_config_bool(k, v);
121
+ return 0;
122
+ }
123
+
124
if (!strcmp(k, "fetch.prune")) {
125
fetch_config->prune = git_config_bool(k, v);
126
return 0;
@@ -2132,7 +2138,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
2138
const char *bundle_uri;
2139
struct string_list list = STRING_LIST_INIT_DUP;
2140
struct remote *remote = NULL;
2135
- int all = 0, multiple = 0;
2141
+ int all = -1, multiple = 0;
2142
int result = 0;
2143
int prune_tags_ok = 1;
2144
int enable_auto_gc = 1;
@@ -2337,11 +2343,20 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
2343
fetch_bundle_uri(the_repository, bundle_uri, NULL))
2344
warning(_("failed to fetch bundles from '%s'"), bundle_uri);
2345
2346
+ if (all < 0) {
2347
+ /*
2348
+ * no --[no-]all given;
2349
+ * only use config option if no remote was explicitly specified
2350
+ */
2351
+ all = (!argc) ? config.all : 0;
2352
+ }
2353
+
2354
if (all) {
2355
if (argc == 1)
2356
die(_("fetch --all does not take a repository argument"));
2357
else if (argc > 1)
2358
die(_("fetch --all does not make sense with refspecs"));
2359
+
2360
(void) for_each_remote(get_one_remote_for_fetch, &list);
2361
2362
/* do not do fetch_multiple() of one */
t/t5514-fetch-multiple.sh
+161
@@ -24,6 +24,15 @@ setup_repository () {
24
)
25
}
26
27
+setup_test_clone () {
28
+ test_dir="$1" &&
29
+ git clone one "$test_dir" &&
30
+ for r in one two three
31
+ do
32
+ git -C "$test_dir" remote add "$r" "../$r" || return 1
33
+ done
34
+}
35
+
36
test_expect_success setup '
37
setup_repository one &&
38
setup_repository two &&
@@ -209,4 +218,156 @@ test_expect_success 'git fetch --multiple --jobs=0 picks a default' '
218
git fetch --multiple --jobs=0)
219
'
220
221
+create_fetch_all_expect () {
222
+ cat >expect <<-\EOF
223
+ one/main
224
+ one/side
225
+ origin/HEAD -> origin/main
226
+ origin/main
227
+ origin/side
228
+ three/another
229
+ three/main
230
+ three/side
231
+ two/another
232
+ two/main
233
+ two/side
234
+ EOF
235
+}
236
+
237
+for fetch_all in true false
238
+do
239
+ test_expect_success "git fetch --all (works with fetch.all = $fetch_all)" '
240
+ test_dir="test_fetch_all_$fetch_all" &&
241
+ setup_test_clone "$test_dir" &&
242
+ (
243
+ cd "$test_dir" &&
244
+ git config fetch.all $fetch_all &&
245
+ git fetch --all &&
246
+ create_fetch_all_expect &&
247
+ git branch -r >actual &&
248
+ test_cmp expect actual
249
+ )
250
+ '
251
+done
252
+
253
+test_expect_success 'git fetch (fetch all remotes with fetch.all = true)' '
254
+ setup_test_clone test9 &&
255
+ (
256
+ cd test9 &&
257
+ git config fetch.all true &&
258
+ git fetch &&
259
+ git branch -r >actual &&
260
+ create_fetch_all_expect &&
261
+ test_cmp expect actual
262
+ )
263
+'
264
+
265
+create_fetch_one_expect () {
266
+ cat >expect <<-\EOF
267
+ one/main
268
+ one/side
269
+ origin/HEAD -> origin/main
270
+ origin/main
271
+ origin/side
272
+ EOF
273
+}
274
+
275
+test_expect_success 'git fetch one (explicit remote overrides fetch.all)' '
276
+ setup_test_clone test10 &&
277
+ (
278
+ cd test10 &&
279
+ git config fetch.all true &&
280
+ git fetch one &&
281
+ create_fetch_one_expect &&
282
+ git branch -r >actual &&
283
+ test_cmp expect actual
284
+ )
285
+'
286
+
287
+create_fetch_two_as_origin_expect () {
288
+ cat >expect <<-\EOF
289
+ origin/HEAD -> origin/main
290
+ origin/another
291
+ origin/main
292
+ origin/side
293
+ EOF
294
+}
295
+
296
+test_expect_success 'git config fetch.all false (fetch only default remote)' '
297
+ setup_test_clone test11 &&
298
+ (
299
+ cd test11 &&
300
+ git config fetch.all false &&
301
+ git remote set-url origin ../two &&
302
+ git fetch &&
303
+ create_fetch_two_as_origin_expect &&
304
+ git branch -r >actual &&
305
+ test_cmp expect actual
306
+ )
307
+'
308
+
309
+for fetch_all in true false
310
+do
311
+ test_expect_success "git fetch --no-all (fetch only default remote with fetch.all = $fetch_all)" '
312
+ test_dir="test_no_all_fetch_all_$fetch_all" &&
313
+ setup_test_clone "$test_dir" &&
314
+ (
315
+ cd "$test_dir" &&
316
+ git config fetch.all $fetch_all &&
317
+ git remote set-url origin ../two &&
318
+ git fetch --no-all &&
319
+ create_fetch_two_as_origin_expect &&
320
+ git branch -r >actual &&
321
+ test_cmp expect actual
322
+ )
323
+ '
324
+done
325
+
326
+test_expect_success 'git fetch --no-all (fetch only default remote without fetch.all)' '
327
+ setup_test_clone test12 &&
328
+ (
329
+ cd test12 &&
330
+ git config --unset-all fetch.all || true &&
331
+ git remote set-url origin ../two &&
332
+ git fetch --no-all &&
333
+ create_fetch_two_as_origin_expect &&
334
+ git branch -r >actual &&
335
+ test_cmp expect actual
336
+ )
337
+'
338
+
339
+test_expect_success 'git fetch --all --no-all (fetch only default remote)' '
340
+ setup_test_clone test13 &&
341
+ (
342
+ cd test13 &&
343
+ git remote set-url origin ../two &&
344
+ git fetch --all --no-all &&
345
+ create_fetch_two_as_origin_expect &&
346
+ git branch -r >actual &&
347
+ test_cmp expect actual
348
+ )
349
+'
350
+
351
+test_expect_success 'git fetch --no-all one (fetch only explicit remote)' '
352
+ setup_test_clone test14 &&
353
+ (
354
+ cd test14 &&
355
+ git fetch --no-all one &&
356
+ create_fetch_one_expect &&
357
+ git branch -r >actual &&
358
+ test_cmp expect actual
359
+ )
360
+'
361
+
362
+test_expect_success 'git fetch --no-all --all (fetch all remotes)' '
363
+ setup_test_clone test15 &&
364
+ (
365
+ cd test15 &&
366
+ git fetch --no-all --all &&
367
+ create_fetch_all_expect &&
368
+ git branch -r >actual &&
369
+ test_cmp expect actual
370
+ )
371
+'
372
+
373
test_done