Skip to content

Commit 1aaaa8c

Browse files
committed
Merge branch 'sb/submodule-update-in-c' into pu
"git submodule update" is getting rewritten piece-by-piece into C. It seems to pass its own self-tests standalone, but seems to break horribly when merged to 'pu'. * sb/submodule-update-in-c: submodule--helper: introduce new update-module-mode helper builtin/submodule--helper: factor out method to update a single submodule builtin/submodule--helper: store update_clone information in a struct builtin/submodule--helper: factor out submodule updating git-submodule.sh: rename unused variables git-submodule.sh: align error reporting for update mode to use path
2 parents 997c844 + e5803d0 commit 1aaaa8c

File tree

2 files changed

+122
-52
lines changed

2 files changed

+122
-52
lines changed

Diff for: builtin/submodule--helper.c

+118-34
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,72 @@ static int module_clone(int argc, const char **argv, const char *prefix)
14461446
return 0;
14471447
}
14481448

1449+
static void determine_submodule_update_strategy(struct repository *r,
1450+
int just_cloned,
1451+
const char *path,
1452+
const char *update,
1453+
struct submodule_update_strategy *out)
1454+
{
1455+
const struct submodule *sub = submodule_from_path(r, &null_oid, path);
1456+
char *key;
1457+
const char *val;
1458+
1459+
key = xstrfmt("submodule.%s.update", sub->name);
1460+
1461+
if (update) {
1462+
trace_printf("parsing update");
1463+
if (parse_submodule_update_strategy(update, out) < 0)
1464+
die(_("Invalid update mode '%s' for submodule path '%s'"),
1465+
update, path);
1466+
} else if (!repo_config_get_string_const(r, key, &val)) {
1467+
if (parse_submodule_update_strategy(val, out) < 0)
1468+
die(_("Invalid update mode '%s' configured for submodule path '%s'"),
1469+
val, path);
1470+
} else if (sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
1471+
trace_printf("loaded thing");
1472+
out->type = sub->update_strategy.type;
1473+
out->command = sub->update_strategy.command;
1474+
} else
1475+
out->type = SM_UPDATE_CHECKOUT;
1476+
1477+
if (just_cloned &&
1478+
(out->type == SM_UPDATE_MERGE ||
1479+
out->type == SM_UPDATE_REBASE ||
1480+
out->type == SM_UPDATE_NONE))
1481+
out->type = SM_UPDATE_CHECKOUT;
1482+
1483+
free(key);
1484+
}
1485+
1486+
static int module_update_module_mode(int argc, const char **argv, const char *prefix)
1487+
{
1488+
const char *path, *update = NULL;
1489+
int just_cloned;
1490+
struct submodule_update_strategy update_strategy = { .type = SM_UPDATE_CHECKOUT };
1491+
1492+
if (argc < 3 || argc > 4)
1493+
die("submodule--helper update-module-clone expects <just-cloned> <path> [<update>]");
1494+
1495+
just_cloned = git_config_int("just_cloned", argv[1]);
1496+
path = argv[2];
1497+
1498+
if (argc == 4)
1499+
update = argv[3];
1500+
1501+
determine_submodule_update_strategy(the_repository,
1502+
just_cloned, path, update,
1503+
&update_strategy);
1504+
fputs(submodule_strategy_to_string(&update_strategy), stdout);
1505+
1506+
return 0;
1507+
}
1508+
1509+
struct update_clone_data {
1510+
const struct submodule *sub;
1511+
struct object_id oid;
1512+
unsigned just_cloned;
1513+
};
1514+
14491515
struct submodule_update_clone {
14501516
/* index into 'list', the list of submodules to look into for cloning */
14511517
int current;
@@ -1465,20 +1531,23 @@ struct submodule_update_clone {
14651531
const char *recursive_prefix;
14661532
const char *prefix;
14671533

1468-
/* Machine-readable status lines to be consumed by git-submodule.sh */
1469-
struct string_list projectlines;
1534+
/* to be consumed by git-submodule.sh */
1535+
struct update_clone_data *update_clone;
1536+
int update_clone_nr; int update_clone_alloc;
14701537

14711538
/* If we want to stop as fast as possible and return an error */
14721539
unsigned quickstop : 1;
14731540

14741541
/* failed clones to be retried again */
14751542
const struct cache_entry **failed_clones;
14761543
int failed_clones_nr, failed_clones_alloc;
1544+
1545+
int max_jobs;
14771546
};
14781547
#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
14791548
SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \
14801549
NULL, NULL, NULL, \
1481-
STRING_LIST_INIT_DUP, 0, NULL, 0, 0}
1550+
NULL, 0, 0, 0, NULL, 0, 0, 0}
14821551

14831552

14841553
static void next_submodule_warn_missing(struct submodule_update_clone *suc,
@@ -1572,11 +1641,12 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
15721641
strbuf_addf(&sb, "%s/.git", ce->name);
15731642
needs_cloning = !file_exists(sb.buf);
15741643

1575-
strbuf_reset(&sb);
1576-
strbuf_addf(&sb, "%06o %s %d %d\t%s\n", ce->ce_mode,
1577-
oid_to_hex(&ce->oid), ce_stage(ce),
1578-
needs_cloning, ce->name);
1579-
string_list_append(&suc->projectlines, sb.buf);
1644+
ALLOC_GROW(suc->update_clone, suc->update_clone_nr + 1,
1645+
suc->update_clone_alloc);
1646+
oidcpy(&suc->update_clone[suc->update_clone_nr].oid, &ce->oid);
1647+
suc->update_clone[suc->update_clone_nr].just_cloned = needs_cloning;
1648+
suc->update_clone[suc->update_clone_nr].sub = sub;
1649+
suc->update_clone_nr++;
15801650

15811651
if (!needs_cloning)
15821652
goto cleanup;
@@ -1717,11 +1787,44 @@ static int git_update_clone_config(const char *var, const char *value,
17171787
return 0;
17181788
}
17191789

1790+
static void update_submodule(struct update_clone_data *ucd)
1791+
{
1792+
fprintf(stdout, "dummy %s %d\t%s\n",
1793+
oid_to_hex(&ucd->oid),
1794+
ucd->just_cloned,
1795+
ucd->sub->path);
1796+
}
1797+
1798+
static int update_submodules(struct submodule_update_clone *suc)
1799+
{
1800+
int i;
1801+
1802+
run_processes_parallel(suc->max_jobs,
1803+
update_clone_get_next_task,
1804+
update_clone_start_failure,
1805+
update_clone_task_finished,
1806+
suc);
1807+
1808+
/*
1809+
* We saved the output and put it out all at once now.
1810+
* That means:
1811+
* - the listener does not have to interleave their (checkout)
1812+
* work with our fetching. The writes involved in a
1813+
* checkout involve more straightforward sequential I/O.
1814+
* - the listener can avoid doing any work if fetching failed.
1815+
*/
1816+
if (suc->quickstop)
1817+
return 1;
1818+
1819+
for (i = 0; i < suc->update_clone_nr; i++)
1820+
update_submodule(&suc->update_clone[i]);
1821+
1822+
return 0;
1823+
}
1824+
17201825
static int update_clone(int argc, const char **argv, const char *prefix)
17211826
{
17221827
const char *update = NULL;
1723-
int max_jobs = 1;
1724-
struct string_list_item *item;
17251828
struct pathspec pathspec;
17261829
struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
17271830

@@ -1743,7 +1846,7 @@ static int update_clone(int argc, const char **argv, const char *prefix)
17431846
OPT_STRING(0, "depth", &suc.depth, "<depth>",
17441847
N_("Create a shallow clone truncated to the "
17451848
"specified number of revisions")),
1746-
OPT_INTEGER('j', "jobs", &max_jobs,
1849+
OPT_INTEGER('j', "jobs", &suc.max_jobs,
17471850
N_("parallel jobs")),
17481851
OPT_BOOL(0, "recommend-shallow", &suc.recommend_shallow,
17491852
N_("whether the initial clone should follow the shallow recommendation")),
@@ -1759,8 +1862,8 @@ static int update_clone(int argc, const char **argv, const char *prefix)
17591862
};
17601863
suc.prefix = prefix;
17611864

1762-
update_clone_config_from_gitmodules(&max_jobs);
1763-
git_config(git_update_clone_config, &max_jobs);
1865+
update_clone_config_from_gitmodules(&suc.max_jobs);
1866+
git_config(git_update_clone_config, &suc.max_jobs);
17641867

17651868
argc = parse_options(argc, argv, prefix, module_update_clone_options,
17661869
git_submodule_helper_usage, 0);
@@ -1775,27 +1878,7 @@ static int update_clone(int argc, const char **argv, const char *prefix)
17751878
if (pathspec.nr)
17761879
suc.warn_if_uninitialized = 1;
17771880

1778-
run_processes_parallel(max_jobs,
1779-
update_clone_get_next_task,
1780-
update_clone_start_failure,
1781-
update_clone_task_finished,
1782-
&suc);
1783-
1784-
/*
1785-
* We saved the output and put it out all at once now.
1786-
* That means:
1787-
* - the listener does not have to interleave their (checkout)
1788-
* work with our fetching. The writes involved in a
1789-
* checkout involve more straightforward sequential I/O.
1790-
* - the listener can avoid doing any work if fetching failed.
1791-
*/
1792-
if (suc.quickstop)
1793-
return 1;
1794-
1795-
for_each_string_list_item(item, &suc.projectlines)
1796-
fprintf(stdout, "%s", item->string);
1797-
1798-
return 0;
1881+
return update_submodules(&suc);
17991882
}
18001883

18011884
static int resolve_relative_path(int argc, const char **argv, const char *prefix)
@@ -2041,6 +2124,7 @@ static struct cmd_struct commands[] = {
20412124
{"list", module_list, 0},
20422125
{"name", module_name, 0},
20432126
{"clone", module_clone, 0},
2127+
{"update-module-mode", module_update_module_mode, 0},
20442128
{"update-clone", update_clone, 0},
20452129
{"connect-gitdir-workingtree", connect_gitdir_workingtree, 0},
20462130
{"relative-path", resolve_relative_path, 0},

Diff for: git-submodule.sh

+4-18
Original file line numberDiff line numberDiff line change
@@ -531,31 +531,17 @@ cmd_update()
531531
"$@" || echo "#unmatched" $?
532532
} | {
533533
err=
534-
while read -r mode sha1 stage just_cloned sm_path
534+
while read -r quickabort sha1 just_cloned sm_path
535535
do
536-
die_if_unmatched "$mode" "$sha1"
536+
die_if_unmatched "$quickabort" "$sha1"
537537

538-
name=$(git submodule--helper name "$sm_path") || exit
539-
if ! test -z "$update"
540-
then
541-
update_module=$update
542-
else
543-
update_module=$(git config submodule."$name".update)
544-
if test -z "$update_module"
545-
then
546-
update_module="checkout"
547-
fi
548-
fi
538+
update_module=$(git submodule--helper update-module-mode $just_cloned "$sm_path" $update)
549539

550540
displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
551541

552542
if test $just_cloned -eq 1
553543
then
554544
subsha1=
555-
case "$update_module" in
556-
merge | rebase | none)
557-
update_module=checkout ;;
558-
esac
559545
else
560546
subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
561547
git rev-parse --verify HEAD) ||
@@ -632,7 +618,7 @@ cmd_update()
632618
must_die_on_failure=yes
633619
;;
634620
*)
635-
die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
621+
die "$(eval_gettext "Invalid update mode '$update_module' for submodule path '$path'")"
636622
esac
637623

638624
if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")

0 commit comments

Comments
 (0)