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