Skip to content

Commit 39487a1

Browse files
taminobgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a26002b commit 39487a1

File tree

4 files changed

+186
-3
lines changed

4 files changed

+186
-3
lines changed

Documentation/config/fetch.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ fetch.pruneTags::
5050
refs. See also `remote.<name>.pruneTags` and the PRUNING
5151
section of linkgit:git-fetch[1].
5252

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+
5359
fetch.output::
5460
Control how ref update status is printed. Valid values are
5561
`full` and `compact`. Default value is `full`. See the

Documentation/fetch-options.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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`.
34

45
-a::
56
--append::

builtin/fetch.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
102102

103103
struct fetch_config {
104104
enum display_format display_format;
105+
int all;
105106
int prune;
106107
int prune_tags;
107108
int show_forced_updates;
@@ -115,6 +116,11 @@ static int git_fetch_config(const char *k, const char *v,
115116
{
116117
struct fetch_config *fetch_config = cb;
117118

119+
if (!strcmp(k, "fetch.all")) {
120+
fetch_config->all = git_config_bool(k, v);
121+
return 0;
122+
}
123+
118124
if (!strcmp(k, "fetch.prune")) {
119125
fetch_config->prune = git_config_bool(k, v);
120126
return 0;
@@ -2132,7 +2138,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
21322138
const char *bundle_uri;
21332139
struct string_list list = STRING_LIST_INIT_DUP;
21342140
struct remote *remote = NULL;
2135-
int all = 0, multiple = 0;
2141+
int all = -1, multiple = 0;
21362142
int result = 0;
21372143
int prune_tags_ok = 1;
21382144
int enable_auto_gc = 1;
@@ -2337,11 +2343,20 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
23372343
fetch_bundle_uri(the_repository, bundle_uri, NULL))
23382344
warning(_("failed to fetch bundles from '%s'"), bundle_uri);
23392345

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+
23402354
if (all) {
23412355
if (argc == 1)
23422356
die(_("fetch --all does not take a repository argument"));
23432357
else if (argc > 1)
23442358
die(_("fetch --all does not make sense with refspecs"));
2359+
23452360
(void) for_each_remote(get_one_remote_for_fetch, &list);
23462361

23472362
/* do not do fetch_multiple() of one */

t/t5514-fetch-multiple.sh

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ setup_repository () {
2424
)
2525
}
2626

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+
2736
test_expect_success setup '
2837
setup_repository one &&
2938
setup_repository two &&
@@ -209,4 +218,156 @@ test_expect_success 'git fetch --multiple --jobs=0 picks a default' '
209218
git fetch --multiple --jobs=0)
210219
'
211220

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+
212373
test_done

0 commit comments

Comments
 (0)