@@ -59,7 +59,8 @@ static int verbosity, deepen_relative, set_upstream;
5959static int progress = -1 ;
6060static int enable_auto_gc = 1 ;
6161static int tags = TAGS_DEFAULT , unshallow , update_shallow , deepen ;
62- static int max_children = 1 ;
62+ static int max_jobs = -1 , submodule_fetch_jobs_config = -1 ;
63+ static int fetch_parallel_config = 1 ;
6364static enum transport_family family ;
6465static const char * depth ;
6566static const char * deepen_since ;
@@ -101,13 +102,20 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
101102 }
102103
103104 if (!strcmp (k , "submodule.fetchjobs" )) {
104- max_children = parse_submodule_fetchjobs (k , v );
105+ submodule_fetch_jobs_config = parse_submodule_fetchjobs (k , v );
105106 return 0 ;
106107 } else if (!strcmp (k , "fetch.recursesubmodules" )) {
107108 recurse_submodules = parse_fetch_recurse_submodules_arg (k , v );
108109 return 0 ;
109110 }
110111
112+ if (!strcmp (k , "fetch.parallel" )) {
113+ fetch_parallel_config = git_config_int (k , v );
114+ if (fetch_parallel_config < 0 )
115+ die (_ ("fetch.parallel cannot be negative" ));
116+ return 0 ;
117+ }
118+
111119 return git_default_config (k , v , cb );
112120}
113121
@@ -141,7 +149,7 @@ static struct option builtin_fetch_options[] = {
141149 N_ ("fetch all tags and associated objects" ), TAGS_SET ),
142150 OPT_SET_INT ('n' , NULL , & tags ,
143151 N_ ("do not fetch all tags (--no-tags)" ), TAGS_UNSET ),
144- OPT_INTEGER ('j' , "jobs" , & max_children ,
152+ OPT_INTEGER ('j' , "jobs" , & max_jobs ,
145153 N_ ("number of submodules fetched in parallel" )),
146154 OPT_BOOL ('p' , "prune" , & prune ,
147155 N_ ("prune remote-tracking branches no longer on remote" )),
@@ -1513,7 +1521,62 @@ static void add_options_to_argv(struct argv_array *argv)
15131521
15141522}
15151523
1516- static int fetch_multiple (struct string_list * list )
1524+ /* Fetch multiple remotes in parallel */
1525+
1526+ struct parallel_fetch_state {
1527+ const char * * argv ;
1528+ struct string_list * remotes ;
1529+ int next , result ;
1530+ };
1531+
1532+ static int fetch_next_remote (struct child_process * cp , struct strbuf * out ,
1533+ void * cb , void * * task_cb )
1534+ {
1535+ struct parallel_fetch_state * state = cb ;
1536+ char * remote ;
1537+
1538+ if (state -> next < 0 || state -> next >= state -> remotes -> nr )
1539+ return 0 ;
1540+
1541+ remote = state -> remotes -> items [state -> next ++ ].string ;
1542+ * task_cb = remote ;
1543+
1544+ argv_array_pushv (& cp -> args , state -> argv );
1545+ argv_array_push (& cp -> args , remote );
1546+ cp -> git_cmd = 1 ;
1547+
1548+ if (verbosity >= 0 )
1549+ printf (_ ("Fetching %s\n" ), remote );
1550+
1551+ return 1 ;
1552+ }
1553+
1554+ static int fetch_failed_to_start (struct strbuf * out , void * cb , void * task_cb )
1555+ {
1556+ struct parallel_fetch_state * state = cb ;
1557+ const char * remote = task_cb ;
1558+
1559+ state -> result = error (_ ("Could not fetch %s" ), remote );
1560+
1561+ return 0 ;
1562+ }
1563+
1564+ static int fetch_finished (int result , struct strbuf * out ,
1565+ void * cb , void * task_cb )
1566+ {
1567+ struct parallel_fetch_state * state = cb ;
1568+ const char * remote = task_cb ;
1569+
1570+ if (result ) {
1571+ strbuf_addf (out , _ ("could not fetch '%s' (exit code: %d)\n" ),
1572+ remote , result );
1573+ state -> result = -1 ;
1574+ }
1575+
1576+ return 0 ;
1577+ }
1578+
1579+ static int fetch_multiple (struct string_list * list , int max_children )
15171580{
15181581 int i , result = 0 ;
15191582 struct argv_array argv = ARGV_ARRAY_INIT ;
@@ -1527,20 +1590,34 @@ static int fetch_multiple(struct string_list *list)
15271590 argv_array_pushl (& argv , "fetch" , "--append" , "--no-auto-gc" , NULL );
15281591 add_options_to_argv (& argv );
15291592
1530- for (i = 0 ; i < list -> nr ; i ++ ) {
1531- const char * name = list -> items [i ].string ;
1532- argv_array_push (& argv , name );
1533- if (verbosity >= 0 )
1534- printf (_ ("Fetching %s\n" ), name );
1535- if (run_command_v_opt (argv .argv , RUN_GIT_CMD )) {
1536- error (_ ("Could not fetch %s" ), name );
1537- result = 1 ;
1593+ if (max_children != 1 && list -> nr != 1 ) {
1594+ struct parallel_fetch_state state = { argv .argv , list , 0 , 0 };
1595+
1596+ argv_array_push (& argv , "--end-of-options" );
1597+ result = run_processes_parallel_tr2 (max_children ,
1598+ & fetch_next_remote ,
1599+ & fetch_failed_to_start ,
1600+ & fetch_finished ,
1601+ & state ,
1602+ "fetch" , "parallel/fetch" );
1603+
1604+ if (!result )
1605+ result = state .result ;
1606+ } else
1607+ for (i = 0 ; i < list -> nr ; i ++ ) {
1608+ const char * name = list -> items [i ].string ;
1609+ argv_array_push (& argv , name );
1610+ if (verbosity >= 0 )
1611+ printf (_ ("Fetching %s\n" ), name );
1612+ if (run_command_v_opt (argv .argv , RUN_GIT_CMD )) {
1613+ error (_ ("Could not fetch %s" ), name );
1614+ result = 1 ;
1615+ }
1616+ argv_array_pop (& argv );
15381617 }
1539- argv_array_pop (& argv );
1540- }
15411618
15421619 argv_array_clear (& argv );
1543- return result ;
1620+ return !! result ;
15441621}
15451622
15461623/*
@@ -1673,7 +1750,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
16731750 for (i = 1 ; i < argc ; i ++ )
16741751 strbuf_addf (& default_rla , " %s" , argv [i ]);
16751752
1676- fetch_config_from_gitmodules (& max_children , & recurse_submodules );
1753+ fetch_config_from_gitmodules (& submodule_fetch_jobs_config ,
1754+ & recurse_submodules );
16771755 git_config (git_fetch_config , NULL );
16781756
16791757 argc = parse_options (argc , argv , prefix ,
@@ -1739,15 +1817,27 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
17391817 fetch_one_setup_partial (remote );
17401818 result = fetch_one (remote , argc , argv , prune_tags_ok );
17411819 } else {
1820+ int max_children = max_jobs ;
1821+
17421822 if (filter_options .choice )
17431823 die (_ ("--filter can only be used with the remote "
17441824 "configured in extensions.partialclone" ));
1825+
1826+ if (max_children < 0 )
1827+ max_children = fetch_parallel_config ;
1828+
17451829 /* TODO should this also die if we have a previous partial-clone? */
1746- result = fetch_multiple (& list );
1830+ result = fetch_multiple (& list , max_children );
17471831 }
17481832
17491833 if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF )) {
17501834 struct argv_array options = ARGV_ARRAY_INIT ;
1835+ int max_children = max_jobs ;
1836+
1837+ if (max_children < 0 )
1838+ max_children = submodule_fetch_jobs_config ;
1839+ if (max_children < 0 )
1840+ max_children = fetch_parallel_config ;
17511841
17521842 add_options_to_argv (& options );
17531843 result = fetch_populated_submodules (the_repository ,
0 commit comments