@@ -2045,6 +2045,20 @@ struct submodule_update_clone {
2045
2045
.max_jobs = 1, \
2046
2046
}
2047
2047
2048
+ struct update_data {
2049
+ const char * recursive_prefix ;
2050
+ const char * sm_path ;
2051
+ const char * displaypath ;
2052
+ struct object_id oid ;
2053
+ struct object_id suboid ;
2054
+ struct submodule_update_strategy update_strategy ;
2055
+ int depth ;
2056
+ unsigned int force : 1 ;
2057
+ unsigned int quiet : 1 ;
2058
+ unsigned int nofetch : 1 ;
2059
+ unsigned int just_cloned : 1 ;
2060
+ };
2061
+ #define UPDATE_DATA_INIT { .update_strategy = SUBMODULE_UPDATE_STRATEGY_INIT }
2048
2062
2049
2063
static void next_submodule_warn_missing (struct submodule_update_clone * suc ,
2050
2064
struct strbuf * out , const char * displaypath )
@@ -2298,6 +2312,181 @@ static int git_update_clone_config(const char *var, const char *value,
2298
2312
return 0 ;
2299
2313
}
2300
2314
2315
+ static int is_tip_reachable (const char * path , struct object_id * oid )
2316
+ {
2317
+ struct child_process cp = CHILD_PROCESS_INIT ;
2318
+ struct strbuf rev = STRBUF_INIT ;
2319
+ char * hex = oid_to_hex (oid );
2320
+
2321
+ cp .git_cmd = 1 ;
2322
+ cp .dir = xstrdup (path );
2323
+ cp .no_stderr = 1 ;
2324
+ strvec_pushl (& cp .args , "rev-list" , "-n" , "1" , hex , "--not" , "--all" , NULL );
2325
+
2326
+ prepare_submodule_repo_env (& cp .env_array );
2327
+
2328
+ if (capture_command (& cp , & rev , GIT_MAX_HEXSZ + 1 ) || rev .len )
2329
+ return 0 ;
2330
+
2331
+ return 1 ;
2332
+ }
2333
+
2334
+ static int fetch_in_submodule (const char * module_path , int depth , int quiet , struct object_id * oid )
2335
+ {
2336
+ struct child_process cp = CHILD_PROCESS_INIT ;
2337
+
2338
+ prepare_submodule_repo_env (& cp .env_array );
2339
+ cp .git_cmd = 1 ;
2340
+ cp .dir = xstrdup (module_path );
2341
+
2342
+ strvec_push (& cp .args , "fetch" );
2343
+ if (quiet )
2344
+ strvec_push (& cp .args , "--quiet" );
2345
+ if (depth )
2346
+ strvec_pushf (& cp .args , "--depth=%d" , depth );
2347
+ if (oid ) {
2348
+ char * hex = oid_to_hex (oid );
2349
+ char * remote = get_default_remote ();
2350
+ strvec_pushl (& cp .args , remote , hex , NULL );
2351
+ }
2352
+
2353
+ return run_command (& cp );
2354
+ }
2355
+
2356
+ static int run_update_command (struct update_data * ud , int subforce )
2357
+ {
2358
+ struct strvec args = STRVEC_INIT ;
2359
+ struct strvec child_env = STRVEC_INIT ;
2360
+ char * oid = oid_to_hex (& ud -> oid );
2361
+ int must_die_on_failure = 0 ;
2362
+ int git_cmd ;
2363
+
2364
+ switch (ud -> update_strategy .type ) {
2365
+ case SM_UPDATE_CHECKOUT :
2366
+ git_cmd = 1 ;
2367
+ strvec_pushl (& args , "checkout" , "-q" , NULL );
2368
+ if (subforce )
2369
+ strvec_push (& args , "-f" );
2370
+ break ;
2371
+ case SM_UPDATE_REBASE :
2372
+ git_cmd = 1 ;
2373
+ strvec_push (& args , "rebase" );
2374
+ if (ud -> quiet )
2375
+ strvec_push (& args , "--quiet" );
2376
+ must_die_on_failure = 1 ;
2377
+ break ;
2378
+ case SM_UPDATE_MERGE :
2379
+ git_cmd = 1 ;
2380
+ strvec_push (& args , "merge" );
2381
+ if (ud -> quiet )
2382
+ strvec_push (& args , "--quiet" );
2383
+ must_die_on_failure = 1 ;
2384
+ break ;
2385
+ case SM_UPDATE_COMMAND :
2386
+ git_cmd = 0 ;
2387
+ strvec_push (& args , ud -> update_strategy .command );
2388
+ must_die_on_failure = 1 ;
2389
+ break ;
2390
+ default :
2391
+ BUG ("unexpected update strategy type: %s" ,
2392
+ submodule_strategy_to_string (& ud -> update_strategy ));
2393
+ }
2394
+ strvec_push (& args , oid );
2395
+
2396
+ prepare_submodule_repo_env (& child_env );
2397
+ if (run_command_v_opt_cd_env (args .v , git_cmd ? RUN_GIT_CMD : RUN_USING_SHELL ,
2398
+ ud -> sm_path , child_env .v )) {
2399
+ switch (ud -> update_strategy .type ) {
2400
+ case SM_UPDATE_CHECKOUT :
2401
+ printf (_ ("Unable to checkout '%s' in submodule path '%s'" ),
2402
+ oid , ud -> displaypath );
2403
+ break ;
2404
+ case SM_UPDATE_REBASE :
2405
+ printf (_ ("Unable to rebase '%s' in submodule path '%s'" ),
2406
+ oid , ud -> displaypath );
2407
+ break ;
2408
+ case SM_UPDATE_MERGE :
2409
+ printf (_ ("Unable to merge '%s' in submodule path '%s'" ),
2410
+ oid , ud -> displaypath );
2411
+ break ;
2412
+ case SM_UPDATE_COMMAND :
2413
+ printf (_ ("Execution of '%s %s' failed in submodule path '%s'" ),
2414
+ ud -> update_strategy .command , oid , ud -> displaypath );
2415
+ break ;
2416
+ default :
2417
+ BUG ("unexpected update strategy type: %s" ,
2418
+ submodule_strategy_to_string (& ud -> update_strategy ));
2419
+ }
2420
+ /*
2421
+ * NEEDSWORK: We are currently printing to stdout with error
2422
+ * return so that the shell caller handles the error output
2423
+ * properly. Once we start handling the error messages within
2424
+ * C, we should use die() instead.
2425
+ */
2426
+ if (must_die_on_failure )
2427
+ return 2 ;
2428
+ /*
2429
+ * This signifies to the caller in shell that the command
2430
+ * failed without dying
2431
+ */
2432
+ return 1 ;
2433
+ }
2434
+
2435
+ switch (ud -> update_strategy .type ) {
2436
+ case SM_UPDATE_CHECKOUT :
2437
+ printf (_ ("Submodule path '%s': checked out '%s'\n" ),
2438
+ ud -> displaypath , oid );
2439
+ break ;
2440
+ case SM_UPDATE_REBASE :
2441
+ printf (_ ("Submodule path '%s': rebased into '%s'\n" ),
2442
+ ud -> displaypath , oid );
2443
+ break ;
2444
+ case SM_UPDATE_MERGE :
2445
+ printf (_ ("Submodule path '%s': merged in '%s'\n" ),
2446
+ ud -> displaypath , oid );
2447
+ break ;
2448
+ case SM_UPDATE_COMMAND :
2449
+ printf (_ ("Submodule path '%s': '%s %s'\n" ),
2450
+ ud -> displaypath , ud -> update_strategy .command , oid );
2451
+ break ;
2452
+ default :
2453
+ BUG ("unexpected update strategy type: %s" ,
2454
+ submodule_strategy_to_string (& ud -> update_strategy ));
2455
+ }
2456
+
2457
+ return 0 ;
2458
+ }
2459
+
2460
+ static int do_run_update_procedure (struct update_data * ud )
2461
+ {
2462
+ int subforce = is_null_oid (& ud -> suboid ) || ud -> force ;
2463
+
2464
+ if (!ud -> nofetch ) {
2465
+ /*
2466
+ * Run fetch only if `oid` isn't present or it
2467
+ * is not reachable from a ref.
2468
+ */
2469
+ if (!is_tip_reachable (ud -> sm_path , & ud -> oid ) &&
2470
+ fetch_in_submodule (ud -> sm_path , ud -> depth , ud -> quiet , NULL ) &&
2471
+ !ud -> quiet )
2472
+ fprintf_ln (stderr ,
2473
+ _ ("Unable to fetch in submodule path '%s'; "
2474
+ "trying to directly fetch %s:" ),
2475
+ ud -> displaypath , oid_to_hex (& ud -> oid ));
2476
+ /*
2477
+ * Now we tried the usual fetch, but `oid` may
2478
+ * not be reachable from any of the refs.
2479
+ */
2480
+ if (!is_tip_reachable (ud -> sm_path , & ud -> oid ) &&
2481
+ fetch_in_submodule (ud -> sm_path , ud -> depth , ud -> quiet , & ud -> oid ))
2482
+ die (_ ("Fetched in submodule path '%s', but it did not "
2483
+ "contain %s. Direct fetching of that commit failed." ),
2484
+ ud -> displaypath , oid_to_hex (& ud -> oid ));
2485
+ }
2486
+
2487
+ return run_update_command (ud , subforce );
2488
+ }
2489
+
2301
2490
static void update_submodule (struct update_clone_data * ucd )
2302
2491
{
2303
2492
fprintf (stdout , "dummy %s %d\t%s\n" ,
@@ -2395,6 +2584,73 @@ static int update_clone(int argc, const char **argv, const char *prefix)
2395
2584
return update_submodules (& suc );
2396
2585
}
2397
2586
2587
+ static int run_update_procedure (int argc , const char * * argv , const char * prefix )
2588
+ {
2589
+ int force = 0 , quiet = 0 , nofetch = 0 , just_cloned = 0 ;
2590
+ char * prefixed_path , * update = NULL ;
2591
+ struct update_data update_data = UPDATE_DATA_INIT ;
2592
+
2593
+ struct option options [] = {
2594
+ OPT__QUIET (& quiet , N_ ("suppress output for update by rebase or merge" )),
2595
+ OPT__FORCE (& force , N_ ("force checkout updates" ), 0 ),
2596
+ OPT_BOOL ('N' , "no-fetch" , & nofetch ,
2597
+ N_ ("don't fetch new objects from the remote site" )),
2598
+ OPT_BOOL (0 , "just-cloned" , & just_cloned ,
2599
+ N_ ("overrides update mode in case the repository is a fresh clone" )),
2600
+ OPT_INTEGER (0 , "depth" , & update_data .depth , N_ ("depth for shallow fetch" )),
2601
+ OPT_STRING (0 , "prefix" , & prefix ,
2602
+ N_ ("path" ),
2603
+ N_ ("path into the working tree" )),
2604
+ OPT_STRING (0 , "update" , & update ,
2605
+ N_ ("string" ),
2606
+ N_ ("rebase, merge, checkout or none" )),
2607
+ OPT_STRING (0 , "recursive-prefix" , & update_data .recursive_prefix , N_ ("path" ),
2608
+ N_ ("path into the working tree, across nested "
2609
+ "submodule boundaries" )),
2610
+ OPT_CALLBACK_F (0 , "oid" , & update_data .oid , N_ ("sha1" ),
2611
+ N_ ("SHA1 expected by superproject" ), PARSE_OPT_NONEG ,
2612
+ parse_opt_object_id ),
2613
+ OPT_CALLBACK_F (0 , "suboid" , & update_data .suboid , N_ ("subsha1" ),
2614
+ N_ ("SHA1 of submodule's HEAD" ), PARSE_OPT_NONEG ,
2615
+ parse_opt_object_id ),
2616
+ OPT_END ()
2617
+ };
2618
+
2619
+ const char * const usage [] = {
2620
+ N_ ("git submodule--helper run-update-procedure [<options>] <path>" ),
2621
+ NULL
2622
+ };
2623
+
2624
+ argc = parse_options (argc , argv , prefix , options , usage , 0 );
2625
+
2626
+ if (argc != 1 )
2627
+ usage_with_options (usage , options );
2628
+
2629
+ update_data .force = !!force ;
2630
+ update_data .quiet = !!quiet ;
2631
+ update_data .nofetch = !!nofetch ;
2632
+ update_data .just_cloned = !!just_cloned ;
2633
+ update_data .sm_path = argv [0 ];
2634
+
2635
+ if (update_data .recursive_prefix )
2636
+ prefixed_path = xstrfmt ("%s%s" , update_data .recursive_prefix , update_data .sm_path );
2637
+ else
2638
+ prefixed_path = xstrdup (update_data .sm_path );
2639
+
2640
+ update_data .displaypath = get_submodule_displaypath (prefixed_path , prefix );
2641
+
2642
+ determine_submodule_update_strategy (the_repository , update_data .just_cloned ,
2643
+ update_data .sm_path , update ,
2644
+ & update_data .update_strategy );
2645
+
2646
+ free (prefixed_path );
2647
+
2648
+ if (!oideq (& update_data .oid , & update_data .suboid ) || update_data .force )
2649
+ return do_run_update_procedure (& update_data );
2650
+
2651
+ return 3 ;
2652
+ }
2653
+
2398
2654
static int resolve_relative_path (int argc , const char * * argv , const char * prefix )
2399
2655
{
2400
2656
struct strbuf sb = STRBUF_INIT ;
@@ -2951,6 +3207,7 @@ static struct cmd_struct commands[] = {
2951
3207
{"add-clone" , add_clone , 0 },
2952
3208
{"update-module-mode" , module_update_module_mode , 0 },
2953
3209
{"update-clone" , update_clone , 0 },
3210
+ {"run-update-procedure" , run_update_procedure , 0 },
2954
3211
{"ensure-core-worktree" , ensure_core_worktree , 0 },
2955
3212
{"relative-path" , resolve_relative_path , 0 },
2956
3213
{"resolve-relative-url" , resolve_relative_url , 0 },
0 commit comments