@@ -249,6 +249,257 @@ static int module_clone(int argc, const char **argv, const char *prefix)
249249 return 0 ;
250250}
251251
252+ struct submodule_update_clone {
253+ /* index into 'list', the list of submodules to look into for cloning */
254+ int current ;
255+ struct module_list list ;
256+ unsigned warn_if_uninitialized : 1 ;
257+
258+ /* update parameter passed via commandline */
259+ struct submodule_update_strategy update ;
260+
261+ /* configuration parameters which are passed on to the children */
262+ int quiet ;
263+ const char * reference ;
264+ const char * depth ;
265+ const char * recursive_prefix ;
266+ const char * prefix ;
267+
268+ /* Machine-readable status lines to be consumed by git-submodule.sh */
269+ struct string_list projectlines ;
270+
271+ /* If we want to stop as fast as possible and return an error */
272+ unsigned quickstop : 1 ;
273+ };
274+ #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
275+ SUBMODULE_UPDATE_STRATEGY_INIT, 0, NULL, NULL, NULL, NULL, \
276+ STRING_LIST_INIT_DUP, 0}
277+
278+ /**
279+ * Determine whether 'ce' needs to be cloned. If so, prepare the 'child' to
280+ * run the clone. Returns 1 if 'ce' needs to be cloned, 0 otherwise.
281+ */
282+ static int prepare_to_clone_next_submodule (const struct cache_entry * ce ,
283+ struct child_process * child ,
284+ struct submodule_update_clone * suc ,
285+ struct strbuf * out )
286+ {
287+ const struct submodule * sub = NULL ;
288+ struct strbuf displaypath_sb = STRBUF_INIT ;
289+ struct strbuf sb = STRBUF_INIT ;
290+ const char * displaypath = NULL ;
291+ char * url = NULL ;
292+ int needs_cloning = 0 ;
293+
294+ if (ce_stage (ce )) {
295+ if (suc -> recursive_prefix )
296+ strbuf_addf (& sb , "%s/%s" , suc -> recursive_prefix , ce -> name );
297+ else
298+ strbuf_addf (& sb , "%s" , ce -> name );
299+ strbuf_addf (out , _ ("Skipping unmerged submodule %s" ), sb .buf );
300+ strbuf_addch (out , '\n' );
301+ goto cleanup ;
302+ }
303+
304+ sub = submodule_from_path (null_sha1 , ce -> name );
305+
306+ if (suc -> recursive_prefix )
307+ displaypath = relative_path (suc -> recursive_prefix ,
308+ ce -> name , & displaypath_sb );
309+ else
310+ displaypath = ce -> name ;
311+
312+ if (suc -> update .type == SM_UPDATE_NONE
313+ || (suc -> update .type == SM_UPDATE_UNSPECIFIED
314+ && sub -> update_strategy .type == SM_UPDATE_NONE )) {
315+ strbuf_addf (out , _ ("Skipping submodule '%s'" ), displaypath );
316+ strbuf_addch (out , '\n' );
317+ goto cleanup ;
318+ }
319+
320+ /*
321+ * Looking up the url in .git/config.
322+ * We must not fall back to .gitmodules as we only want
323+ * to process configured submodules.
324+ */
325+ strbuf_reset (& sb );
326+ strbuf_addf (& sb , "submodule.%s.url" , sub -> name );
327+ git_config_get_string (sb .buf , & url );
328+ if (!url ) {
329+ /*
330+ * Only mention uninitialized submodules when their
331+ * path have been specified
332+ */
333+ if (suc -> warn_if_uninitialized ) {
334+ strbuf_addf (out ,
335+ _ ("Submodule path '%s' not initialized" ),
336+ displaypath );
337+ strbuf_addch (out , '\n' );
338+ strbuf_addstr (out ,
339+ _ ("Maybe you want to use 'update --init'?" ));
340+ strbuf_addch (out , '\n' );
341+ }
342+ goto cleanup ;
343+ }
344+
345+ strbuf_reset (& sb );
346+ strbuf_addf (& sb , "%s/.git" , ce -> name );
347+ needs_cloning = !file_exists (sb .buf );
348+
349+ strbuf_reset (& sb );
350+ strbuf_addf (& sb , "%06o %s %d %d\t%s\n" , ce -> ce_mode ,
351+ sha1_to_hex (ce -> sha1 ), ce_stage (ce ),
352+ needs_cloning , ce -> name );
353+ string_list_append (& suc -> projectlines , sb .buf );
354+
355+ if (!needs_cloning )
356+ goto cleanup ;
357+
358+ child -> git_cmd = 1 ;
359+ child -> no_stdin = 1 ;
360+ child -> stdout_to_stderr = 1 ;
361+ child -> err = -1 ;
362+ argv_array_push (& child -> args , "submodule--helper" );
363+ argv_array_push (& child -> args , "clone" );
364+ if (suc -> quiet )
365+ argv_array_push (& child -> args , "--quiet" );
366+ if (suc -> prefix )
367+ argv_array_pushl (& child -> args , "--prefix" , suc -> prefix , NULL );
368+ argv_array_pushl (& child -> args , "--path" , sub -> path , NULL );
369+ argv_array_pushl (& child -> args , "--name" , sub -> name , NULL );
370+ argv_array_pushl (& child -> args , "--url" , url , NULL );
371+ if (suc -> reference )
372+ argv_array_push (& child -> args , suc -> reference );
373+ if (suc -> depth )
374+ argv_array_push (& child -> args , suc -> depth );
375+
376+ cleanup :
377+ free (url );
378+ strbuf_reset (& displaypath_sb );
379+ strbuf_reset (& sb );
380+
381+ return needs_cloning ;
382+ }
383+
384+ static int update_clone_get_next_task (struct child_process * child ,
385+ struct strbuf * err ,
386+ void * suc_cb ,
387+ void * * void_task_cb )
388+ {
389+ struct submodule_update_clone * suc = suc_cb ;
390+
391+ for (; suc -> current < suc -> list .nr ; suc -> current ++ ) {
392+ const struct cache_entry * ce = suc -> list .entries [suc -> current ];
393+ if (prepare_to_clone_next_submodule (ce , child , suc , err )) {
394+ suc -> current ++ ;
395+ return 1 ;
396+ }
397+ }
398+ return 0 ;
399+ }
400+
401+ static int update_clone_start_failure (struct strbuf * err ,
402+ void * suc_cb ,
403+ void * void_task_cb )
404+ {
405+ struct submodule_update_clone * suc = suc_cb ;
406+ suc -> quickstop = 1 ;
407+ return 1 ;
408+ }
409+
410+ static int update_clone_task_finished (int result ,
411+ struct strbuf * err ,
412+ void * suc_cb ,
413+ void * void_task_cb )
414+ {
415+ struct submodule_update_clone * suc = suc_cb ;
416+
417+ if (!result )
418+ return 0 ;
419+
420+ suc -> quickstop = 1 ;
421+ return 1 ;
422+ }
423+
424+ static int update_clone (int argc , const char * * argv , const char * prefix )
425+ {
426+ const char * update = NULL ;
427+ int max_jobs = -1 ;
428+ struct string_list_item * item ;
429+ struct pathspec pathspec ;
430+ struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT ;
431+
432+ struct option module_update_clone_options [] = {
433+ OPT_STRING (0 , "prefix" , & prefix ,
434+ N_ ("path" ),
435+ N_ ("path into the working tree" )),
436+ OPT_STRING (0 , "recursive-prefix" , & suc .recursive_prefix ,
437+ N_ ("path" ),
438+ N_ ("path into the working tree, across nested "
439+ "submodule boundaries" )),
440+ OPT_STRING (0 , "update" , & update ,
441+ N_ ("string" ),
442+ N_ ("rebase, merge, checkout or none" )),
443+ OPT_STRING (0 , "reference" , & suc .reference , N_ ("repo" ),
444+ N_ ("reference repository" )),
445+ OPT_STRING (0 , "depth" , & suc .depth , "<depth>" ,
446+ N_ ("Create a shallow clone truncated to the "
447+ "specified number of revisions" )),
448+ OPT_INTEGER ('j' , "jobs" , & max_jobs ,
449+ N_ ("parallel jobs" )),
450+ OPT__QUIET (& suc .quiet , N_ ("don't print cloning progress" )),
451+ OPT_END ()
452+ };
453+
454+ const char * const git_submodule_helper_usage [] = {
455+ N_ ("git submodule--helper update_clone [--prefix=<path>] [<path>...]" ),
456+ NULL
457+ };
458+ suc .prefix = prefix ;
459+
460+ argc = parse_options (argc , argv , prefix , module_update_clone_options ,
461+ git_submodule_helper_usage , 0 );
462+
463+ if (update )
464+ if (parse_submodule_update_strategy (update , & suc .update ) < 0 )
465+ die (_ ("bad value for update parameter" ));
466+
467+ if (module_list_compute (argc , argv , prefix , & pathspec , & suc .list ) < 0 )
468+ return 1 ;
469+
470+ if (pathspec .nr )
471+ suc .warn_if_uninitialized = 1 ;
472+
473+ /* Overlay the parsed .gitmodules file with .git/config */
474+ gitmodules_config ();
475+ git_config (submodule_config , NULL );
476+
477+ if (max_jobs < 0 )
478+ max_jobs = parallel_submodules ();
479+
480+ run_processes_parallel (max_jobs ,
481+ update_clone_get_next_task ,
482+ update_clone_start_failure ,
483+ update_clone_task_finished ,
484+ & suc );
485+
486+ /*
487+ * We saved the output and put it out all at once now.
488+ * That means:
489+ * - the listener does not have to interleave their (checkout)
490+ * work with our fetching. The writes involved in a
491+ * checkout involve more straightforward sequential I/O.
492+ * - the listener can avoid doing any work if fetching failed.
493+ */
494+ if (suc .quickstop )
495+ return 1 ;
496+
497+ for_each_string_list_item (item , & suc .projectlines )
498+ utf8_fprintf (stdout , "%s" , item -> string );
499+
500+ return 0 ;
501+ }
502+
252503struct cmd_struct {
253504 const char * cmd ;
254505 int (* fn )(int , const char * * , const char * );
@@ -258,19 +509,20 @@ static struct cmd_struct commands[] = {
258509 {"list" , module_list },
259510 {"name" , module_name },
260511 {"clone" , module_clone },
512+ {"update-clone" , update_clone }
261513};
262514
263515int cmd_submodule__helper (int argc , const char * * argv , const char * prefix )
264516{
265517 int i ;
266518 if (argc < 2 )
267- die (_ ("fatal: submodule--helper subcommand must be "
519+ die (_ ("submodule--helper subcommand must be "
268520 "called with a subcommand" ));
269521
270522 for (i = 0 ; i < ARRAY_SIZE (commands ); i ++ )
271523 if (!strcmp (argv [1 ], commands [i ].cmd ))
272524 return commands [i ].fn (argc - 1 , argv + 1 , prefix );
273525
274- die (_ ("fatal: '%s' is not a valid submodule--helper "
526+ die (_ ("'%s' is not a valid submodule--helper "
275527 "subcommand" ), argv [1 ]);
276528}
0 commit comments