472
return run_command(&cp);
473
}
474
475
+struct submodule_alternate_setup {
476
+ const char *submodule_name;
477
+ enum SUBMODULE_ALTERNATE_ERROR_MODE {
478
+ SUBMODULE_ALTERNATE_ERROR_DIE,
479
+ SUBMODULE_ALTERNATE_ERROR_INFO,
480
+ SUBMODULE_ALTERNATE_ERROR_IGNORE
481
+ } error_mode;
482
+ struct string_list *reference;
483
+};
484
+#define SUBMODULE_ALTERNATE_SETUP_INIT { NULL, \
485
+ SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL }
486
+
487
+static int add_possible_reference_from_superproject(
488
+ struct alternate_object_database *alt, void *sas_cb)
489
+{
490
+ struct submodule_alternate_setup *sas = sas_cb;
491
+
492
+ /* directory name, minus trailing slash */
493
+ size_t namelen = alt->name - alt->base - 1;
494
+ struct strbuf name = STRBUF_INIT;
495
+ strbuf_add(&name, alt->base, namelen);
496
+
497
+ /*
498
+ * If the alternate object store is another repository, try the
499
+ * standard layout with .git/modules/<name>/objects
500
+ */
501
+ if (ends_with(name.buf, ".git/objects")) {
502
+ char *sm_alternate;
503
+ struct strbuf sb = STRBUF_INIT;
504
+ struct strbuf err = STRBUF_INIT;
505
+ strbuf_add(&sb, name.buf, name.len - strlen("objects"));
506
+ /*
507
+ * We need to end the new path with '/' to mark it as a dir,
508
+ * otherwise a submodule name containing '/' will be broken
509
+ * as the last part of a missing submodule reference would
510
+ * be taken as a file name.
511
+ */
512
+ strbuf_addf(&sb, "modules/%s/", sas->submodule_name);
513
+
514
+ sm_alternate = compute_alternate_path(sb.buf, &err);
515
+ if (sm_alternate) {
516
+ string_list_append(sas->reference, xstrdup(sb.buf));
517
+ free(sm_alternate);
518
+ } else {
519
+ switch (sas->error_mode) {
520
+ case SUBMODULE_ALTERNATE_ERROR_DIE:
521
+ die(_("submodule '%s' cannot add alternate: %s"),
522
+ sas->submodule_name, err.buf);
523
+ case SUBMODULE_ALTERNATE_ERROR_INFO:
524
+ fprintf(stderr, _("submodule '%s' cannot add alternate: %s"),
525
+ sas->submodule_name, err.buf);
526
+ case SUBMODULE_ALTERNATE_ERROR_IGNORE:
527
+ ; /* nothing */
528
+ }
529
+ }
530
+ strbuf_release(&sb);
531
+ }
532
+
533
+ strbuf_release(&name);
534
+ return 0;
535
+}
536
+
537
+static void prepare_possible_alternates(const char *sm_name,
538
+ struct string_list *reference)
539
+{
540
+ char *sm_alternate = NULL, *error_strategy = NULL;
541
+ struct submodule_alternate_setup sas = SUBMODULE_ALTERNATE_SETUP_INIT;
542
+
543
+ git_config_get_string("submodule.alternateLocation", &sm_alternate);
544
+ if (!sm_alternate)
545
+ return;
546
+
547
+ git_config_get_string("submodule.alternateErrorStrategy", &error_strategy);
548
+
549
+ if (!error_strategy)
550
+ error_strategy = xstrdup("die");
551
+
552
+ sas.submodule_name = sm_name;
553
+ sas.reference = reference;
554
+ if (!strcmp(error_strategy, "die"))
555
+ sas.error_mode = SUBMODULE_ALTERNATE_ERROR_DIE;
556
+ else if (!strcmp(error_strategy, "info"))
557
+ sas.error_mode = SUBMODULE_ALTERNATE_ERROR_INFO;
558
+ else if (!strcmp(error_strategy, "ignore"))
559
+ sas.error_mode = SUBMODULE_ALTERNATE_ERROR_IGNORE;
560
+ else
561
+ die(_("Value '%s' for submodule.alternateErrorStrategy is not recognized"), error_strategy);
562
+
563
+ if (!strcmp(sm_alternate, "superproject"))
564
+ foreach_alt_odb(add_possible_reference_from_superproject, &sas);
565
+ else if (!strcmp(sm_alternate, "no"))
566
+ ; /* do nothing */
567
+ else
568
+ die(_("Value '%s' for submodule.alternateLocation is not recognized"), sm_alternate);
569
+
570
+ free(sm_alternate);
571
+ free(error_strategy);
572
+}
573
+
574
static int module_clone(int argc, const char **argv, const char *prefix)
575
{
576
const char *name = NULL, *url = NULL, *depth = NULL;
631
if (!file_exists(sm_gitdir)) {
632
if (safe_create_leading_directories_const(sm_gitdir) < 0)
633
die(_("could not create directory '%s'"), sm_gitdir);
634
+
635
+ prepare_possible_alternates(name, &reference);
636
+
637
if (clone_submodule(path, sm_gitdir, url, depth, &reference, quiet))
638
die(_("clone of '%s' into submodule path '%s' failed"),
639
url, path);