@@ -2009,6 +2009,20 @@ struct submodule_update_clone {
2009
2009
.max_jobs = 1, \
2010
2010
}
2011
2011
2012
+ struct update_data {
2013
+ const char * recursive_prefix ;
2014
+ const char * sm_path ;
2015
+ const char * displaypath ;
2016
+ struct object_id oid ;
2017
+ struct object_id suboid ;
2018
+ struct submodule_update_strategy update_strategy ;
2019
+ int depth ;
2020
+ unsigned int force : 1 ;
2021
+ unsigned int quiet : 1 ;
2022
+ unsigned int nofetch : 1 ;
2023
+ unsigned int just_cloned : 1 ;
2024
+ };
2025
+ #define UPDATE_DATA_INIT { .update_strategy = SUBMODULE_UPDATE_STRATEGY_INIT }
2012
2026
2013
2027
static void next_submodule_warn_missing (struct submodule_update_clone * suc ,
2014
2028
struct strbuf * out , const char * displaypath )
@@ -2262,6 +2276,181 @@ static int git_update_clone_config(const char *var, const char *value,
2262
2276
return 0 ;
2263
2277
}
2264
2278
2279
+ static int is_tip_reachable (const char * path , struct object_id * oid )
2280
+ {
2281
+ struct child_process cp = CHILD_PROCESS_INIT ;
2282
+ struct strbuf rev = STRBUF_INIT ;
2283
+ char * hex = oid_to_hex (oid );
2284
+
2285
+ cp .git_cmd = 1 ;
2286
+ cp .dir = xstrdup (path );
2287
+ cp .no_stderr = 1 ;
2288
+ strvec_pushl (& cp .args , "rev-list" , "-n" , "1" , hex , "--not" , "--all" , NULL );
2289
+
2290
+ prepare_submodule_repo_env (& cp .env_array );
2291
+
2292
+ if (capture_command (& cp , & rev , GIT_MAX_HEXSZ + 1 ) || rev .len )
2293
+ return 0 ;
2294
+
2295
+ return 1 ;
2296
+ }
2297
+
2298
+ static int fetch_in_submodule (const char * module_path , int depth , int quiet , struct object_id * oid )
2299
+ {
2300
+ struct child_process cp = CHILD_PROCESS_INIT ;
2301
+
2302
+ prepare_submodule_repo_env (& cp .env_array );
2303
+ cp .git_cmd = 1 ;
2304
+ cp .dir = xstrdup (module_path );
2305
+
2306
+ strvec_push (& cp .args , "fetch" );
2307
+ if (quiet )
2308
+ strvec_push (& cp .args , "--quiet" );
2309
+ if (depth )
2310
+ strvec_pushf (& cp .args , "--depth=%d" , depth );
2311
+ if (oid ) {
2312
+ char * hex = oid_to_hex (oid );
2313
+ char * remote = get_default_remote ();
2314
+ strvec_pushl (& cp .args , remote , hex , NULL );
2315
+ }
2316
+
2317
+ return run_command (& cp );
2318
+ }
2319
+
2320
+ static int run_update_command (struct update_data * ud , int subforce )
2321
+ {
2322
+ struct strvec args = STRVEC_INIT ;
2323
+ struct strvec child_env = STRVEC_INIT ;
2324
+ char * oid = oid_to_hex (& ud -> oid );
2325
+ int must_die_on_failure = 0 ;
2326
+ int git_cmd ;
2327
+
2328
+ switch (ud -> update_strategy .type ) {
2329
+ case SM_UPDATE_CHECKOUT :
2330
+ git_cmd = 1 ;
2331
+ strvec_pushl (& args , "checkout" , "-q" , NULL );
2332
+ if (subforce )
2333
+ strvec_push (& args , "-f" );
2334
+ break ;
2335
+ case SM_UPDATE_REBASE :
2336
+ git_cmd = 1 ;
2337
+ strvec_push (& args , "rebase" );
2338
+ if (ud -> quiet )
2339
+ strvec_push (& args , "--quiet" );
2340
+ must_die_on_failure = 1 ;
2341
+ break ;
2342
+ case SM_UPDATE_MERGE :
2343
+ git_cmd = 1 ;
2344
+ strvec_push (& args , "merge" );
2345
+ if (ud -> quiet )
2346
+ strvec_push (& args , "--quiet" );
2347
+ must_die_on_failure = 1 ;
2348
+ break ;
2349
+ case SM_UPDATE_COMMAND :
2350
+ git_cmd = 0 ;
2351
+ strvec_push (& args , ud -> update_strategy .command );
2352
+ must_die_on_failure = 1 ;
2353
+ break ;
2354
+ default :
2355
+ BUG ("unexpected update strategy type: %s" ,
2356
+ submodule_strategy_to_string (& ud -> update_strategy ));
2357
+ }
2358
+ strvec_push (& args , oid );
2359
+
2360
+ prepare_submodule_repo_env (& child_env );
2361
+ if (run_command_v_opt_cd_env (args .v , git_cmd ? RUN_GIT_CMD : RUN_USING_SHELL ,
2362
+ ud -> sm_path , child_env .v )) {
2363
+ switch (ud -> update_strategy .type ) {
2364
+ case SM_UPDATE_CHECKOUT :
2365
+ printf (_ ("Unable to checkout '%s' in submodule path '%s'" ),
2366
+ oid , ud -> displaypath );
2367
+ break ;
2368
+ case SM_UPDATE_REBASE :
2369
+ printf (_ ("Unable to rebase '%s' in submodule path '%s'" ),
2370
+ oid , ud -> displaypath );
2371
+ break ;
2372
+ case SM_UPDATE_MERGE :
2373
+ printf (_ ("Unable to merge '%s' in submodule path '%s'" ),
2374
+ oid , ud -> displaypath );
2375
+ break ;
2376
+ case SM_UPDATE_COMMAND :
2377
+ printf (_ ("Execution of '%s %s' failed in submodule path '%s'" ),
2378
+ ud -> update_strategy .command , oid , ud -> displaypath );
2379
+ break ;
2380
+ default :
2381
+ BUG ("unexpected update strategy type: %s" ,
2382
+ submodule_strategy_to_string (& ud -> update_strategy ));
2383
+ }
2384
+ /*
2385
+ * NEEDSWORK: We are currently printing to stdout with error
2386
+ * return so that the shell caller handles the error output
2387
+ * properly. Once we start handling the error messages within
2388
+ * C, we should use die() instead.
2389
+ */
2390
+ if (must_die_on_failure )
2391
+ return 2 ;
2392
+ /*
2393
+ * This signifies to the caller in shell that the command
2394
+ * failed without dying
2395
+ */
2396
+ return 1 ;
2397
+ }
2398
+
2399
+ switch (ud -> update_strategy .type ) {
2400
+ case SM_UPDATE_CHECKOUT :
2401
+ printf (_ ("Submodule path '%s': checked out '%s'\n" ),
2402
+ ud -> displaypath , oid );
2403
+ break ;
2404
+ case SM_UPDATE_REBASE :
2405
+ printf (_ ("Submodule path '%s': rebased into '%s'\n" ),
2406
+ ud -> displaypath , oid );
2407
+ break ;
2408
+ case SM_UPDATE_MERGE :
2409
+ printf (_ ("Submodule path '%s': merged in '%s'\n" ),
2410
+ ud -> displaypath , oid );
2411
+ break ;
2412
+ case SM_UPDATE_COMMAND :
2413
+ printf (_ ("Submodule path '%s': '%s %s'\n" ),
2414
+ ud -> displaypath , ud -> update_strategy .command , oid );
2415
+ break ;
2416
+ default :
2417
+ BUG ("unexpected update strategy type: %s" ,
2418
+ submodule_strategy_to_string (& ud -> update_strategy ));
2419
+ }
2420
+
2421
+ return 0 ;
2422
+ }
2423
+
2424
+ static int do_run_update_procedure (struct update_data * ud )
2425
+ {
2426
+ int subforce = is_null_oid (& ud -> suboid ) || ud -> force ;
2427
+
2428
+ if (!ud -> nofetch ) {
2429
+ /*
2430
+ * Run fetch only if `oid` isn't present or it
2431
+ * is not reachable from a ref.
2432
+ */
2433
+ if (!is_tip_reachable (ud -> sm_path , & ud -> oid ) &&
2434
+ fetch_in_submodule (ud -> sm_path , ud -> depth , ud -> quiet , NULL ) &&
2435
+ !ud -> quiet )
2436
+ fprintf_ln (stderr ,
2437
+ _ ("Unable to fetch in submodule path '%s'; "
2438
+ "trying to directly fetch %s:" ),
2439
+ ud -> displaypath , oid_to_hex (& ud -> oid ));
2440
+ /*
2441
+ * Now we tried the usual fetch, but `oid` may
2442
+ * not be reachable from any of the refs.
2443
+ */
2444
+ if (!is_tip_reachable (ud -> sm_path , & ud -> oid ) &&
2445
+ fetch_in_submodule (ud -> sm_path , ud -> depth , ud -> quiet , & ud -> oid ))
2446
+ die (_ ("Fetched in submodule path '%s', but it did not "
2447
+ "contain %s. Direct fetching of that commit failed." ),
2448
+ ud -> displaypath , oid_to_hex (& ud -> oid ));
2449
+ }
2450
+
2451
+ return run_update_command (ud , subforce );
2452
+ }
2453
+
2265
2454
static void update_submodule (struct update_clone_data * ucd )
2266
2455
{
2267
2456
fprintf (stdout , "dummy %s %d\t%s\n" ,
@@ -2359,6 +2548,73 @@ static int update_clone(int argc, const char **argv, const char *prefix)
2359
2548
return update_submodules (& suc );
2360
2549
}
2361
2550
2551
+ static int run_update_procedure (int argc , const char * * argv , const char * prefix )
2552
+ {
2553
+ int force = 0 , quiet = 0 , nofetch = 0 , just_cloned = 0 ;
2554
+ char * prefixed_path , * update = NULL ;
2555
+ struct update_data update_data = UPDATE_DATA_INIT ;
2556
+
2557
+ struct option options [] = {
2558
+ OPT__QUIET (& quiet , N_ ("suppress output for update by rebase or merge" )),
2559
+ OPT__FORCE (& force , N_ ("force checkout updates" ), 0 ),
2560
+ OPT_BOOL ('N' , "no-fetch" , & nofetch ,
2561
+ N_ ("don't fetch new objects from the remote site" )),
2562
+ OPT_BOOL (0 , "just-cloned" , & just_cloned ,
2563
+ N_ ("overrides update mode in case the repository is a fresh clone" )),
2564
+ OPT_INTEGER (0 , "depth" , & update_data .depth , N_ ("depth for shallow fetch" )),
2565
+ OPT_STRING (0 , "prefix" , & prefix ,
2566
+ N_ ("path" ),
2567
+ N_ ("path into the working tree" )),
2568
+ OPT_STRING (0 , "update" , & update ,
2569
+ N_ ("string" ),
2570
+ N_ ("rebase, merge, checkout or none" )),
2571
+ OPT_STRING (0 , "recursive-prefix" , & update_data .recursive_prefix , N_ ("path" ),
2572
+ N_ ("path into the working tree, across nested "
2573
+ "submodule boundaries" )),
2574
+ OPT_CALLBACK_F (0 , "oid" , & update_data .oid , N_ ("sha1" ),
2575
+ N_ ("SHA1 expected by superproject" ), PARSE_OPT_NONEG ,
2576
+ parse_opt_object_id ),
2577
+ OPT_CALLBACK_F (0 , "suboid" , & update_data .suboid , N_ ("subsha1" ),
2578
+ N_ ("SHA1 of submodule's HEAD" ), PARSE_OPT_NONEG ,
2579
+ parse_opt_object_id ),
2580
+ OPT_END ()
2581
+ };
2582
+
2583
+ const char * const usage [] = {
2584
+ N_ ("git submodule--helper run-update-procedure [<options>] <path>" ),
2585
+ NULL
2586
+ };
2587
+
2588
+ argc = parse_options (argc , argv , prefix , options , usage , 0 );
2589
+
2590
+ if (argc != 1 )
2591
+ usage_with_options (usage , options );
2592
+
2593
+ update_data .force = !!force ;
2594
+ update_data .quiet = !!quiet ;
2595
+ update_data .nofetch = !!nofetch ;
2596
+ update_data .just_cloned = !!just_cloned ;
2597
+ update_data .sm_path = argv [0 ];
2598
+
2599
+ if (update_data .recursive_prefix )
2600
+ prefixed_path = xstrfmt ("%s%s" , update_data .recursive_prefix , update_data .sm_path );
2601
+ else
2602
+ prefixed_path = xstrdup (update_data .sm_path );
2603
+
2604
+ update_data .displaypath = get_submodule_displaypath (prefixed_path , prefix );
2605
+
2606
+ determine_submodule_update_strategy (the_repository , update_data .just_cloned ,
2607
+ update_data .sm_path , update ,
2608
+ & update_data .update_strategy );
2609
+
2610
+ free (prefixed_path );
2611
+
2612
+ if (!oideq (& update_data .oid , & update_data .suboid ) || update_data .force )
2613
+ return do_run_update_procedure (& update_data );
2614
+
2615
+ return 3 ;
2616
+ }
2617
+
2362
2618
static int resolve_relative_path (int argc , const char * * argv , const char * prefix )
2363
2619
{
2364
2620
struct strbuf sb = STRBUF_INIT ;
@@ -3098,6 +3354,7 @@ static struct cmd_struct commands[] = {
3098
3354
{"add" , module_add , SUPPORT_SUPER_PREFIX },
3099
3355
{"update-module-mode" , module_update_module_mode , 0 },
3100
3356
{"update-clone" , update_clone , 0 },
3357
+ {"run-update-procedure" , run_update_procedure , 0 },
3101
3358
{"ensure-core-worktree" , ensure_core_worktree , 0 },
3102
3359
{"relative-path" , resolve_relative_path , 0 },
3103
3360
{"resolve-relative-url-test" , resolve_relative_url_test , 0 },
0 commit comments