@@ -60,7 +60,8 @@ static int verbosity, deepen_relative, set_upstream;
6060static int progress = -1 ;
6161static int enable_auto_gc = 1 ;
6262static int tags = TAGS_DEFAULT , unshallow , update_shallow , deepen ;
63- static int max_children = 1 ;
63+ static int max_jobs = -1 , submodule_fetch_jobs_config = -1 ;
64+ static int fetch_parallel_config = 1 ;
6465static enum transport_family family ;
6566static const char * depth ;
6667static const char * deepen_since ;
@@ -102,13 +103,20 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
102103 }
103104
104105 if (!strcmp (k , "submodule.fetchjobs" )) {
105- max_children = parse_submodule_fetchjobs (k , v );
106+ submodule_fetch_jobs_config = parse_submodule_fetchjobs (k , v );
106107 return 0 ;
107108 } else if (!strcmp (k , "fetch.recursesubmodules" )) {
108109 recurse_submodules = parse_fetch_recurse_submodules_arg (k , v );
109110 return 0 ;
110111 }
111112
113+ if (!strcmp (k , "fetch.parallel" )) {
114+ fetch_parallel_config = git_config_int (k , v );
115+ if (fetch_parallel_config < 0 )
116+ die (_ ("fetch.parallel cannot be negative" ));
117+ return 0 ;
118+ }
119+
112120 return git_default_config (k , v , cb );
113121}
114122
@@ -142,7 +150,7 @@ static struct option builtin_fetch_options[] = {
142150 N_ ("fetch all tags and associated objects" ), TAGS_SET ),
143151 OPT_SET_INT ('n' , NULL , & tags ,
144152 N_ ("do not fetch all tags (--no-tags)" ), TAGS_UNSET ),
145- OPT_INTEGER ('j' , "jobs" , & max_children ,
153+ OPT_INTEGER ('j' , "jobs" , & max_jobs ,
146154 N_ ("number of submodules fetched in parallel" )),
147155 OPT_BOOL ('p' , "prune" , & prune ,
148156 N_ ("prune remote-tracking branches no longer on remote" )),
@@ -1526,7 +1534,62 @@ static void add_options_to_argv(struct argv_array *argv)
15261534
15271535}
15281536
1529- static int fetch_multiple (struct string_list * list )
1537+ /* Fetch multiple remotes in parallel */
1538+
1539+ struct parallel_fetch_state {
1540+ const char * * argv ;
1541+ struct string_list * remotes ;
1542+ int next , result ;
1543+ };
1544+
1545+ static int fetch_next_remote (struct child_process * cp , struct strbuf * out ,
1546+ void * cb , void * * task_cb )
1547+ {
1548+ struct parallel_fetch_state * state = cb ;
1549+ char * remote ;
1550+
1551+ if (state -> next < 0 || state -> next >= state -> remotes -> nr )
1552+ return 0 ;
1553+
1554+ remote = state -> remotes -> items [state -> next ++ ].string ;
1555+ * task_cb = remote ;
1556+
1557+ argv_array_pushv (& cp -> args , state -> argv );
1558+ argv_array_push (& cp -> args , remote );
1559+ cp -> git_cmd = 1 ;
1560+
1561+ if (verbosity >= 0 )
1562+ printf (_ ("Fetching %s\n" ), remote );
1563+
1564+ return 1 ;
1565+ }
1566+
1567+ static int fetch_failed_to_start (struct strbuf * out , void * cb , void * task_cb )
1568+ {
1569+ struct parallel_fetch_state * state = cb ;
1570+ const char * remote = task_cb ;
1571+
1572+ state -> result = error (_ ("Could not fetch %s" ), remote );
1573+
1574+ return 0 ;
1575+ }
1576+
1577+ static int fetch_finished (int result , struct strbuf * out ,
1578+ void * cb , void * task_cb )
1579+ {
1580+ struct parallel_fetch_state * state = cb ;
1581+ const char * remote = task_cb ;
1582+
1583+ if (result ) {
1584+ strbuf_addf (out , _ ("could not fetch '%s' (exit code: %d)\n" ),
1585+ remote , result );
1586+ state -> result = -1 ;
1587+ }
1588+
1589+ return 0 ;
1590+ }
1591+
1592+ static int fetch_multiple (struct string_list * list , int max_children )
15301593{
15311594 int i , result = 0 ;
15321595 struct argv_array argv = ARGV_ARRAY_INIT ;
@@ -1540,20 +1603,34 @@ static int fetch_multiple(struct string_list *list)
15401603 argv_array_pushl (& argv , "fetch" , "--append" , "--no-auto-gc" , NULL );
15411604 add_options_to_argv (& argv );
15421605
1543- for (i = 0 ; i < list -> nr ; i ++ ) {
1544- const char * name = list -> items [i ].string ;
1545- argv_array_push (& argv , name );
1546- if (verbosity >= 0 )
1547- printf (_ ("Fetching %s\n" ), name );
1548- if (run_command_v_opt (argv .argv , RUN_GIT_CMD )) {
1549- error (_ ("Could not fetch %s" ), name );
1550- result = 1 ;
1606+ if (max_children != 1 && list -> nr != 1 ) {
1607+ struct parallel_fetch_state state = { argv .argv , list , 0 , 0 };
1608+
1609+ argv_array_push (& argv , "--end-of-options" );
1610+ result = run_processes_parallel_tr2 (max_children ,
1611+ & fetch_next_remote ,
1612+ & fetch_failed_to_start ,
1613+ & fetch_finished ,
1614+ & state ,
1615+ "fetch" , "parallel/fetch" );
1616+
1617+ if (!result )
1618+ result = state .result ;
1619+ } else
1620+ for (i = 0 ; i < list -> nr ; i ++ ) {
1621+ const char * name = list -> items [i ].string ;
1622+ argv_array_push (& argv , name );
1623+ if (verbosity >= 0 )
1624+ printf (_ ("Fetching %s\n" ), name );
1625+ if (run_command_v_opt (argv .argv , RUN_GIT_CMD )) {
1626+ error (_ ("Could not fetch %s" ), name );
1627+ result = 1 ;
1628+ }
1629+ argv_array_pop (& argv );
15511630 }
1552- argv_array_pop (& argv );
1553- }
15541631
15551632 argv_array_clear (& argv );
1556- return result ;
1633+ return !! result ;
15571634}
15581635
15591636/*
@@ -1690,7 +1767,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
16901767 for (i = 1 ; i < argc ; i ++ )
16911768 strbuf_addf (& default_rla , " %s" , argv [i ]);
16921769
1693- fetch_config_from_gitmodules (& max_children , & recurse_submodules );
1770+ fetch_config_from_gitmodules (& submodule_fetch_jobs_config ,
1771+ & recurse_submodules );
16941772 git_config (git_fetch_config , NULL );
16951773
16961774 argc = parse_options (argc , argv , prefix ,
@@ -1756,15 +1834,27 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
17561834 fetch_one_setup_partial (remote );
17571835 result = fetch_one (remote , argc , argv , prune_tags_ok );
17581836 } else {
1837+ int max_children = max_jobs ;
1838+
17591839 if (filter_options .choice )
17601840 die (_ ("--filter can only be used with the remote "
17611841 "configured in extensions.partialclone" ));
1842+
1843+ if (max_children < 0 )
1844+ max_children = fetch_parallel_config ;
1845+
17621846 /* TODO should this also die if we have a previous partial-clone? */
1763- result = fetch_multiple (& list );
1847+ result = fetch_multiple (& list , max_children );
17641848 }
17651849
17661850 if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF )) {
17671851 struct argv_array options = ARGV_ARRAY_INIT ;
1852+ int max_children = max_jobs ;
1853+
1854+ if (max_children < 0 )
1855+ max_children = submodule_fetch_jobs_config ;
1856+ if (max_children < 0 )
1857+ max_children = fetch_parallel_config ;
17681858
17691859 add_options_to_argv (& options );
17701860 result = fetch_populated_submodules (the_repository ,
0 commit comments