mirror of
https://github.com/git/git
synced 2024-11-04 16:17:49 +00:00
Merge branch 'jk/log-follow-with-non-literal-pathspec'
"git [-c log.follow=true] log [--follow] ':(glob)f**'" used to barf. * jk/log-follow-with-non-literal-pathspec: diff: detect pathspec magic not supported by --follow diff: factor out --follow pathspec check pathspec: factor out magic-to-name function
This commit is contained in:
commit
de00f4b7f3
6 changed files with 70 additions and 10 deletions
|
@ -866,7 +866,7 @@ static void log_setup_revisions_tweak(struct rev_info *rev,
|
|||
struct setup_revision_opt *opt)
|
||||
{
|
||||
if (rev->diffopt.flags.default_follow_renames &&
|
||||
rev->prune_data.nr == 1)
|
||||
diff_check_follow_pathspec(&rev->prune_data, 0))
|
||||
rev->diffopt.flags.follow_renames = 1;
|
||||
|
||||
if (rev->first_parent_only)
|
||||
|
|
29
diff.c
29
diff.c
|
@ -4751,6 +4751,31 @@ unsigned diff_filter_bit(char status)
|
|||
return filter_bit[(int) status];
|
||||
}
|
||||
|
||||
int diff_check_follow_pathspec(struct pathspec *ps, int die_on_error)
|
||||
{
|
||||
unsigned forbidden_magic;
|
||||
|
||||
if (ps->nr != 1) {
|
||||
if (die_on_error)
|
||||
die(_("--follow requires exactly one pathspec"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
forbidden_magic = ps->items[0].magic & ~(PATHSPEC_FROMTOP |
|
||||
PATHSPEC_LITERAL);
|
||||
if (forbidden_magic) {
|
||||
if (die_on_error) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
pathspec_magic_names(forbidden_magic, &sb);
|
||||
die(_("pathspec magic not supported by --follow: %s"),
|
||||
sb.buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void diff_setup_done(struct diff_options *options)
|
||||
{
|
||||
unsigned check_mask = DIFF_FORMAT_NAME |
|
||||
|
@ -4858,8 +4883,8 @@ void diff_setup_done(struct diff_options *options)
|
|||
|
||||
options->diff_path_counter = 0;
|
||||
|
||||
if (options->flags.follow_renames && options->pathspec.nr != 1)
|
||||
die(_("--follow requires exactly one pathspec"));
|
||||
if (options->flags.follow_renames)
|
||||
diff_check_follow_pathspec(&options->pathspec, 1);
|
||||
|
||||
if (!options->use_color || external_diff())
|
||||
options->color_moved = 0;
|
||||
|
|
7
diff.h
7
diff.h
|
@ -539,6 +539,13 @@ void repo_diff_setup(struct repository *, struct diff_options *);
|
|||
struct option *add_diff_options(const struct option *, struct diff_options *);
|
||||
int diff_opt_parse(struct diff_options *, const char **, int, const char *);
|
||||
void diff_setup_done(struct diff_options *);
|
||||
|
||||
/*
|
||||
* Returns true if the pathspec can work with --follow mode. If die_on_error is
|
||||
* set, die() with a specific error message rather than returning false.
|
||||
*/
|
||||
int diff_check_follow_pathspec(struct pathspec *ps, int die_on_error);
|
||||
|
||||
int git_config_rename(const char *var, const char *value);
|
||||
|
||||
#define DIFF_DETECT_RENAME 1
|
||||
|
|
19
pathspec.c
19
pathspec.c
|
@ -531,24 +531,29 @@ static int pathspec_item_cmp(const void *a_, const void *b_)
|
|||
return strcmp(a->match, b->match);
|
||||
}
|
||||
|
||||
static void NORETURN unsupported_magic(const char *pattern,
|
||||
unsigned magic)
|
||||
void pathspec_magic_names(unsigned magic, struct strbuf *out)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) {
|
||||
const struct pathspec_magic *m = pathspec_magic + i;
|
||||
if (!(magic & m->bit))
|
||||
continue;
|
||||
if (sb.len)
|
||||
strbuf_addstr(&sb, ", ");
|
||||
if (out->len)
|
||||
strbuf_addstr(out, ", ");
|
||||
|
||||
if (m->mnemonic)
|
||||
strbuf_addf(&sb, _("'%s' (mnemonic: '%c')"),
|
||||
strbuf_addf(out, _("'%s' (mnemonic: '%c')"),
|
||||
m->name, m->mnemonic);
|
||||
else
|
||||
strbuf_addf(&sb, "'%s'", m->name);
|
||||
strbuf_addf(out, "'%s'", m->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void NORETURN unsupported_magic(const char *pattern,
|
||||
unsigned magic)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
pathspec_magic_names(magic, &sb);
|
||||
/*
|
||||
* We may want to substitute "this command" with a command
|
||||
* name. E.g. when "git add -p" or "git add -i" dies when running
|
||||
|
|
|
@ -130,6 +130,14 @@ void parse_pathspec_file(struct pathspec *pathspec,
|
|||
void copy_pathspec(struct pathspec *dst, const struct pathspec *src);
|
||||
void clear_pathspec(struct pathspec *);
|
||||
|
||||
/*
|
||||
* Add a human-readable string to "out" representing the PATHSPEC_* flags set
|
||||
* in "magic". The result is suitable for error messages, but not for
|
||||
* parsing as pathspec magic itself (you get 'icase' with quotes, not
|
||||
* :(icase)).
|
||||
*/
|
||||
void pathspec_magic_names(unsigned magic, struct strbuf *out);
|
||||
|
||||
static inline int ps_strncmp(const struct pathspec_item *item,
|
||||
const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
|
|
|
@ -187,6 +187,21 @@ test_expect_success 'git config log.follow does not die with no paths' '
|
|||
git log --
|
||||
'
|
||||
|
||||
test_expect_success 'git log --follow rejects unsupported pathspec magic' '
|
||||
test_must_fail git log --follow ":(top,glob,icase)ichi" 2>stderr &&
|
||||
# check full error message; we want to be sure we mention both
|
||||
# of the rejected types (glob,icase), but not the allowed one (top)
|
||||
echo "fatal: pathspec magic not supported by --follow: ${SQ}glob${SQ}, ${SQ}icase${SQ}" >expect &&
|
||||
test_cmp expect stderr
|
||||
'
|
||||
|
||||
test_expect_success 'log.follow disabled with unsupported pathspec magic' '
|
||||
test_config log.follow true &&
|
||||
git log --format=%s ":(glob,icase)ichi" >actual &&
|
||||
echo third >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'git config log.follow is overridden by --no-follow' '
|
||||
test_config log.follow true &&
|
||||
git log --no-follow --pretty="format:%s" ichi >actual &&
|
||||
|
|
Loading…
Reference in a new issue