+69
-1
index c1d7c672f4..2c583ed0cc 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
int recurse_submodules;
int parallel;
int submodule_fetch_jobs;
+ int submodule_errors;
};
+/* really private - use accessors below to parse and format */
+static const char *submodule_error_name[] = {
+ [SUBMODULE_ERRORS_FAIL] = "fail",
+ [SUBMODULE_ERRORS_WARN] = "warn",
+};
+
+static const char *submodule_error(unsigned num)
+{
+ if (ARRAY_SIZE(submodule_error_name) <= num)
+ BUG("invalid submodule errors mode %u", num);
+ return submodule_error_name[num];
+}
+
+static int parse_submodule_error(const char *name)
+{
+ for (unsigned num = 0; num < ARRAY_SIZE(submodule_error_name); num++)
+ if (!strcmp(submodule_error_name[num], name))
+ return num;
+ return -1;
+}
+
static int git_fetch_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
return 0;
}
+ if (!strcmp(k, "fetch.submoduleerrors")) {
+ int mode;
+
+ if (!v)
+ return config_error_nonbool(k);
+ mode = parse_submodule_error(v);
+ if (mode < 0)
+ die(_("invalid value for '%s': '%s'"),
+ "fetch.submoduleErrors", v);
+ fetch_config->submodule_errors = mode;
+ return 0;
+ }
+
if (!strcmp(k, "fetch.parallel")) {
fetch_config->parallel = git_config_int(k, v, ctx->kvi);
if (fetch_config->parallel < 0)
strvec_push(argv, "--no-recurse-submodules");
else if (config->recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
strvec_push(argv, "--recurse-submodules=on-demand");
+ if (config->submodule_errors != -1)
+ strvec_pushf(argv, "--submodule-errors=%s",
+ submodule_error(config->submodule_errors));
if (tags == TAGS_SET)
strvec_push(argv, "--tags");
else if (tags == TAGS_UNSET)
return exit_code;
}
+static int option_parse_submodule_errors(const struct option *opt,
+ const char *arg, int unset)
+{
+ int *v = opt->value;
+ int mode;
+
+ if (unset) {
+ *v = SUBMODULE_ERRORS_FAIL;
+ return 0;
+ }
+ mode = parse_submodule_error(arg);
+ if (mode < 0)
+ die(_("invalid value for '%s': '%s'"), "--submodule-errors", arg);
+ *v = mode;
+ return 0;
+}
+
int cmd_fetch(int argc,
const char **argv,
const char *prefix,
.recurse_submodules = RECURSE_SUBMODULES_DEFAULT,
.parallel = 1,
.submodule_fetch_jobs = -1,
+ .submodule_errors = -1, /* unset */
};
const char *submodule_prefix = "";
const char *bundle_uri;
int max_jobs = -1;
int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT;
int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
+ int submodule_errors_cli = -1; /* -1: not set on command line */
int fetch_write_commit_graph = -1;
int stdin_refspecs = 0;
int negotiate_only = 0;
OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules_cli, N_("on-demand"),
N_("control recursive fetching of submodules"),
PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
+ OPT_CALLBACK_F(0, "submodule-errors", &submodule_errors_cli,
+ N_("(fail|warn)"),
+ N_("control how submodule fetch errors are handled"),
+ 0, option_parse_submodule_errors),
OPT_BOOL(0, "dry-run", &dry_run,
N_("dry run")),
OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")),
if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT)
config.recurse_submodules = recurse_submodules_cli;
+ if (submodule_errors_cli != -1)
+ config.submodule_errors = submodule_errors_cli;
+
if (negotiate_only) {
switch (recurse_submodules_cli) {
case RECURSE_SUBMODULES_OFF:
if (!result && remote && (config.recurse_submodules != RECURSE_SUBMODULES_OFF)) {
struct strvec options = STRVEC_INIT;
int max_children = max_jobs;
+ int submodule_errors = config.submodule_errors;
if (max_children < 0)
max_children = config.submodule_fetch_jobs;
if (max_children < 0)
max_children = config.parallel;
+ if (submodule_errors < 0)
+ submodule_errors = SUBMODULE_ERRORS_FAIL;
add_options_to_argv(&options, &config);
trace2_region_enter_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix);
config.recurse_submodules,
recurse_submodules_default,
verbosity < 0,
- max_children);
+ max_children,
+ submodule_errors);
trace2_region_leave_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix);
strvec_clear(&options);
}
+6
-2
index 8bcef68a42..da4ace751f 100644
--- a/submodule.c
+++ b/submodule.c
int oid_fetch_tasks_nr, oid_fetch_tasks_alloc;
struct strbuf submodules_with_errors;
+ int submodule_errors;
};
#define SPF_INIT { \
.args = STRVEC_INIT, \
static void record_fetch_error(struct submodule_parallel_fetch *spf,
const char *name)
{
- spf->result = 1;
+ if (spf->submodule_errors == SUBMODULE_ERRORS_FAIL)
+ spf->result = 1;
strbuf_addf(&spf->submodules_with_errors, "\t%s\n", name);
}
const struct strvec *options,
const char *prefix, int command_line_option,
int default_option,
- int quiet, int max_parallel_jobs)
+ int quiet, int max_parallel_jobs,
+ int submodule_errors)
{
struct submodule_parallel_fetch spf = SPF_INIT;
const struct run_process_parallel_opts opts = {
spf.default_option = default_option;
spf.quiet = quiet;
spf.prefix = prefix;
+ spf.submodule_errors = submodule_errors;
if (!r->worktree)
goto out;
+6
-1
index b10e16e6c0..c80b687d2a 100644
--- a/submodule.h
+++ b/submodule.h
*/
const struct submodule *submodule_from_ce(const struct cache_entry *ce);
void check_for_new_submodule_commits(struct object_id *oid);
+/* Values for the submodule_errors parameter of fetch_submodules(). */
+#define SUBMODULE_ERRORS_FAIL 0 /* submodule fetch errors are fatal (default) */
+#define SUBMODULE_ERRORS_WARN 1 /* submodule fetch errors are non-fatal warnings */
+
int fetch_submodules(struct repository *r,
const struct strvec *options,
const char *prefix,
int command_line_option,
int default_option,
- int quiet, int max_parallel_jobs);
+ int quiet, int max_parallel_jobs,
+ int submodule_errors);
unsigned is_submodule_modified(const char *path, int ignore_untracked);
int submodule_uses_gitfile(const char *path);