Skip to content

Commit

Permalink
submodule: allow erroneous values for the fetchRecurseSubmodules option
Browse files Browse the repository at this point in the history
We should not die when reading the submodule config cache since the
user might not be able to get out of that situation when the
configuration is part of the history.

We should handle this condition later when the value is about to be
used.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
hvoigt authored and gitster committed Aug 19, 2015
1 parent 851e18c commit 027771f
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 17 deletions.
1 change: 1 addition & 0 deletions builtin/fetch.c
Expand Up @@ -11,6 +11,7 @@
#include "run-command.h"
#include "parse-options.h"
#include "sigchain.h"
#include "submodule-config.h"
#include "submodule.h"
#include "connected.h"
#include "argv-array.h"
Expand Down
29 changes: 28 additions & 1 deletion submodule-config.c
Expand Up @@ -204,6 +204,30 @@ static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
return submodule;
}

static int parse_fetch_recurse(const char *opt, const char *arg,
int die_on_error)
{
switch (git_config_maybe_bool(opt, arg)) {
case 1:
return RECURSE_SUBMODULES_ON;
case 0:
return RECURSE_SUBMODULES_OFF;
default:
if (!strcmp(arg, "on-demand"))
return RECURSE_SUBMODULES_ON_DEMAND;

if (die_on_error)
die("bad %s argument: %s", opt, arg);
else
return RECURSE_SUBMODULES_ERROR;
}
}

int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
{
return parse_fetch_recurse(opt, arg, 1);
}

static void warn_multiple_config(const unsigned char *commit_sha1,
const char *name, const char *option)
{
Expand Down Expand Up @@ -255,14 +279,17 @@ static int parse_config(const char *var, const char *value, void *data)
submodule->path = strbuf_detach(&path, NULL);
cache_put_path(me->cache, submodule);
} else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
/* when parsing worktree configurations we can die early */
int die_on_error = is_null_sha1(me->gitmodules_sha1);
if (!me->overwrite &&
submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) {
warn_multiple_config(me->commit_sha1, submodule->name,
"fetchrecursesubmodules");
goto release_return;
}

submodule->fetch_recurse = parse_fetch_recurse_submodules_arg(var, value);
submodule->fetch_recurse = parse_fetch_recurse(var, value,
die_on_error);
} else if (!strcmp(item.buf, "ignore")) {
struct strbuf ignore = STRBUF_INIT;
if (!me->overwrite && submodule->ignore != NULL) {
Expand Down
1 change: 1 addition & 0 deletions submodule-config.h
Expand Up @@ -18,6 +18,7 @@ struct submodule {
unsigned char gitmodules_sha1[20];
};

int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
int parse_submodule_config_option(const char *var, const char *value);
const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
const char *name);
Expand Down
15 changes: 0 additions & 15 deletions submodule.c
Expand Up @@ -288,21 +288,6 @@ static void print_submodule_summary(struct rev_info *rev, FILE *f,
strbuf_release(&sb);
}

int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
{
switch (git_config_maybe_bool(opt, arg)) {
case 1:
return RECURSE_SUBMODULES_ON;
case 0:
return RECURSE_SUBMODULES_OFF;
default:
if (!strcmp(arg, "on-demand"))
return RECURSE_SUBMODULES_ON_DEMAND;
/* TODO: remove the die for history parsing here */
die("bad %s argument: %s", opt, arg);
}
}

void show_submodule_summary(FILE *f, const char *path,
const char *line_prefix,
unsigned char one[20], unsigned char two[20],
Expand Down
2 changes: 1 addition & 1 deletion submodule.h
Expand Up @@ -5,6 +5,7 @@ struct diff_options;
struct argv_array;

enum {
RECURSE_SUBMODULES_ERROR = -3,
RECURSE_SUBMODULES_NONE = -2,
RECURSE_SUBMODULES_ON_DEMAND = -1,
RECURSE_SUBMODULES_OFF = 0,
Expand All @@ -21,7 +22,6 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
int submodule_config(const char *var, const char *value, void *cb);
void gitmodules_config(void);
void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
void show_submodule_summary(FILE *f, const char *path,
const char *line_prefix,
unsigned char one[20], unsigned char two[20],
Expand Down
35 changes: 35 additions & 0 deletions t/t7411-submodule-config.sh
Expand Up @@ -115,4 +115,39 @@ test_expect_success 'reading of local configuration' '
)
'

cat >super/expect_fetchrecurse_die.err <<EOF
fatal: bad submodule.submodule.fetchrecursesubmodules argument: blabla
EOF

test_expect_success 'local error in fetchrecursesubmodule dies early' '
(cd super &&
git config submodule.submodule.fetchrecursesubmodules blabla &&
test_must_fail test-submodule-config \
"" b \
"" submodule \
>actual.out 2>actual.err &&
touch expect_fetchrecurse_die.out &&
test_cmp expect_fetchrecurse_die.out actual.out &&
test_cmp expect_fetchrecurse_die.err actual.err &&
git config --unset submodule.submodule.fetchrecursesubmodules
)
'

test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
(cd super &&
git config -f .gitmodules \
submodule.submodule.fetchrecursesubmodules blabla &&
git add .gitmodules &&
git config --unset -f .gitmodules \
submodule.submodule.fetchrecursesubmodules &&
git commit -m "add error in fetchrecursesubmodules" &&
test-submodule-config \
HEAD b \
HEAD submodule \
>actual &&
test_cmp expect_error actual &&
git reset --hard HEAD^
)
'

test_done

0 comments on commit 027771f

Please sign in to comment.