2045
.max_jobs = 1, \
2046
}
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 }
2062
2063
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
2064
struct strbuf *out, const char *displaypath)
2312
return 0;
2313
}
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
+
2490
static void update_submodule(struct update_clone_data *ucd)
2491
{
2492
fprintf(stdout, "dummy %s %d\t%s\n",
2584
return update_submodules(&suc);
2585
}
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
+
2654
static int resolve_relative_path(int argc, const char **argv, const char *prefix)
2655
{
2656
struct strbuf sb = STRBUF_INIT;
3207
{"add-clone", add_clone, 0},
3208
{"update-module-mode", module_update_module_mode, 0},
3209
{"update-clone", update_clone, 0},
3210
+ {"run-update-procedure", run_update_procedure, 0},
3211
{"ensure-core-worktree", ensure_core_worktree, 0},
3212
{"relative-path", resolve_relative_path, 0},
3213
{"resolve-relative-url", resolve_relative_url, 0},