interpret-trailers: add options for actions
Allow using non-default values for trailers without having to set them up in .gitconfig first. For example, if you have the following configuration trailer.signed-off-by.where = end you may use "--where before" when a patch author forgets his Signed-off-by and provides it in a separate email. Likewise for --if-exists and --if-missing Reverting to the behavior specified by .gitconfig is done with --no-where, --no-if-exists and --no-if-missing. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
51166b8754
commit
0ea5292e6b
@ -80,6 +80,29 @@ OPTIONS
|
|||||||
trailer to the input messages. See the description of this
|
trailer to the input messages. See the description of this
|
||||||
command.
|
command.
|
||||||
|
|
||||||
|
--where <placement>::
|
||||||
|
--no-where::
|
||||||
|
Specify where all new trailers will be added. A setting
|
||||||
|
provided with '--where' overrides all configuration variables
|
||||||
|
and applies to all '--trailer' options until the next occurrence of
|
||||||
|
'--where' or '--no-where'.
|
||||||
|
|
||||||
|
--if-exists <action>::
|
||||||
|
--no-if-exists::
|
||||||
|
Specify what action will be performed when there is already at
|
||||||
|
least one trailer with the same <token> in the message. A setting
|
||||||
|
provided with '--if-exists' overrides all configuration variables
|
||||||
|
and applies to all '--trailer' options until the next occurrence of
|
||||||
|
'--if-exists' or '--no-if-exists'.
|
||||||
|
|
||||||
|
--if-missing <action>::
|
||||||
|
--no-if-missing::
|
||||||
|
Specify what action will be performed when there is no other
|
||||||
|
trailer with the same <token> in the message. A setting
|
||||||
|
provided with '--if-missing' overrides all configuration variables
|
||||||
|
and applies to all '--trailer' options until the next occurrence of
|
||||||
|
'--if-missing' or '--no-if-missing'.
|
||||||
|
|
||||||
CONFIGURATION VARIABLES
|
CONFIGURATION VARIABLES
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -16,6 +16,28 @@ static const char * const git_interpret_trailers_usage[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum trailer_where where;
|
||||||
|
static enum trailer_if_exists if_exists;
|
||||||
|
static enum trailer_if_missing if_missing;
|
||||||
|
|
||||||
|
static int option_parse_where(const struct option *opt,
|
||||||
|
const char *arg, int unset)
|
||||||
|
{
|
||||||
|
return trailer_set_where(&where, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int option_parse_if_exists(const struct option *opt,
|
||||||
|
const char *arg, int unset)
|
||||||
|
{
|
||||||
|
return trailer_set_if_exists(&if_exists, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int option_parse_if_missing(const struct option *opt,
|
||||||
|
const char *arg, int unset)
|
||||||
|
{
|
||||||
|
return trailer_set_if_missing(&if_missing, arg);
|
||||||
|
}
|
||||||
|
|
||||||
static void new_trailers_clear(struct list_head *trailers)
|
static void new_trailers_clear(struct list_head *trailers)
|
||||||
{
|
{
|
||||||
struct list_head *pos, *tmp;
|
struct list_head *pos, *tmp;
|
||||||
@ -44,6 +66,9 @@ static int option_parse_trailer(const struct option *opt,
|
|||||||
|
|
||||||
item = xmalloc(sizeof(*item));
|
item = xmalloc(sizeof(*item));
|
||||||
item->text = arg;
|
item->text = arg;
|
||||||
|
item->where = where;
|
||||||
|
item->if_exists = if_exists;
|
||||||
|
item->if_missing = if_missing;
|
||||||
list_add_tail(&item->list, trailers);
|
list_add_tail(&item->list, trailers);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -58,6 +83,13 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
|
|||||||
OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")),
|
OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")),
|
||||||
OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")),
|
OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")),
|
||||||
|
|
||||||
|
OPT_CALLBACK(0, "where", NULL, N_("action"),
|
||||||
|
N_("where to place the new trailer"), option_parse_where),
|
||||||
|
OPT_CALLBACK(0, "if-exists", NULL, N_("action"),
|
||||||
|
N_("action if trailer already exists"), option_parse_if_exists),
|
||||||
|
OPT_CALLBACK(0, "if-missing", NULL, N_("action"),
|
||||||
|
N_("action if trailer is missing"), option_parse_if_missing),
|
||||||
|
|
||||||
OPT_CALLBACK(0, "trailer", &trailers, N_("trailer"),
|
OPT_CALLBACK(0, "trailer", &trailers, N_("trailer"),
|
||||||
N_("trailer(s) to add"), option_parse_trailer),
|
N_("trailer(s) to add"), option_parse_trailer),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
|
@ -681,6 +681,36 @@ test_expect_success 'using "where = before"' '
|
|||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'overriding configuration with "--where after"' '
|
||||||
|
git config trailer.ack.where "before" &&
|
||||||
|
cat complex_message_body >expected &&
|
||||||
|
sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
|
||||||
|
Fixes: Z
|
||||||
|
Acked-by= Z
|
||||||
|
Acked-by= Peff
|
||||||
|
Reviewed-by: Z
|
||||||
|
Signed-off-by: Z
|
||||||
|
EOF
|
||||||
|
git interpret-trailers --where after --trailer "ack: Peff" \
|
||||||
|
complex_message >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'using "where = before" with "--no-where"' '
|
||||||
|
cat complex_message_body >expected &&
|
||||||
|
sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
|
||||||
|
Bug #42
|
||||||
|
Fixes: Z
|
||||||
|
Acked-by= Peff
|
||||||
|
Acked-by= Z
|
||||||
|
Reviewed-by: Z
|
||||||
|
Signed-off-by: Z
|
||||||
|
EOF
|
||||||
|
git interpret-trailers --where after --no-where --trailer "ack: Peff" \
|
||||||
|
--trailer "bug: 42" complex_message >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'using "where = after"' '
|
test_expect_success 'using "where = after"' '
|
||||||
git config trailer.ack.where "after" &&
|
git config trailer.ack.where "after" &&
|
||||||
cat complex_message_body >expected &&
|
cat complex_message_body >expected &&
|
||||||
@ -947,6 +977,23 @@ test_expect_success 'using "ifExists = add" with "where = after"' '
|
|||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'overriding configuration with "--if-exists replace"' '
|
||||||
|
git config trailer.fix.key "Fixes: " &&
|
||||||
|
git config trailer.fix.ifExists "add" &&
|
||||||
|
cat complex_message_body >expected &&
|
||||||
|
sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
|
||||||
|
Bug #42
|
||||||
|
Acked-by= Z
|
||||||
|
Reviewed-by:
|
||||||
|
Signed-off-by: Z
|
||||||
|
Fixes: 22
|
||||||
|
EOF
|
||||||
|
git interpret-trailers --if-exists replace --trailer "review:" \
|
||||||
|
--trailer "fix=53" --trailer "fix=22" --trailer "bug: 42" \
|
||||||
|
<complex_message >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'using "ifExists = replace"' '
|
test_expect_success 'using "ifExists = replace"' '
|
||||||
git config trailer.fix.key "Fixes: " &&
|
git config trailer.fix.key "Fixes: " &&
|
||||||
git config trailer.fix.ifExists "replace" &&
|
git config trailer.fix.ifExists "replace" &&
|
||||||
@ -1026,6 +1073,25 @@ test_expect_success 'the default is "ifMissing = add"' '
|
|||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'overriding configuration with "--if-missing doNothing"' '
|
||||||
|
git config trailer.ifmissing "add" &&
|
||||||
|
cat complex_message_body >expected &&
|
||||||
|
sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
|
||||||
|
Fixes: Z
|
||||||
|
Acked-by= Z
|
||||||
|
Acked-by= Junio
|
||||||
|
Acked-by= Peff
|
||||||
|
Reviewed-by:
|
||||||
|
Signed-off-by: Z
|
||||||
|
EOF
|
||||||
|
git interpret-trailers --if-missing doNothing \
|
||||||
|
--trailer "review:" --trailer "fix=53" \
|
||||||
|
--trailer "cc=Linus" --trailer "ack: Junio" \
|
||||||
|
--trailer "fix=22" --trailer "bug: 42" --trailer "ack: Peff" \
|
||||||
|
<complex_message >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'when default "ifMissing" is "doNothing"' '
|
test_expect_success 'when default "ifMissing" is "doNothing"' '
|
||||||
git config trailer.ifmissing "doNothing" &&
|
git config trailer.ifmissing "doNothing" &&
|
||||||
cat complex_message_body >expected &&
|
cat complex_message_body >expected &&
|
||||||
|
34
trailer.c
34
trailer.c
@ -295,6 +295,9 @@ static void apply_arg_if_exists(struct trailer_item *in_tok,
|
|||||||
else
|
else
|
||||||
free_arg_item(arg_tok);
|
free_arg_item(arg_tok);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
die("BUG: trailer.c: unhandled value %d",
|
||||||
|
arg_tok->conf.if_exists);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +319,10 @@ static void apply_arg_if_missing(struct list_head *head,
|
|||||||
list_add_tail(&to_add->list, head);
|
list_add_tail(&to_add->list, head);
|
||||||
else
|
else
|
||||||
list_add(&to_add->list, head);
|
list_add(&to_add->list, head);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
die("BUG: trailer.c: unhandled value %d",
|
||||||
|
arg_tok->conf.if_missing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +377,9 @@ static void process_trailers_lists(struct list_head *head,
|
|||||||
|
|
||||||
int trailer_set_where(enum trailer_where *item, const char *value)
|
int trailer_set_where(enum trailer_where *item, const char *value)
|
||||||
{
|
{
|
||||||
if (!strcasecmp("after", value))
|
if (!value)
|
||||||
|
*item = WHERE_DEFAULT;
|
||||||
|
else if (!strcasecmp("after", value))
|
||||||
*item = WHERE_AFTER;
|
*item = WHERE_AFTER;
|
||||||
else if (!strcasecmp("before", value))
|
else if (!strcasecmp("before", value))
|
||||||
*item = WHERE_BEFORE;
|
*item = WHERE_BEFORE;
|
||||||
@ -385,7 +394,9 @@ int trailer_set_where(enum trailer_where *item, const char *value)
|
|||||||
|
|
||||||
int trailer_set_if_exists(enum trailer_if_exists *item, const char *value)
|
int trailer_set_if_exists(enum trailer_if_exists *item, const char *value)
|
||||||
{
|
{
|
||||||
if (!strcasecmp("addIfDifferent", value))
|
if (!value)
|
||||||
|
*item = EXISTS_DEFAULT;
|
||||||
|
else if (!strcasecmp("addIfDifferent", value))
|
||||||
*item = EXISTS_ADD_IF_DIFFERENT;
|
*item = EXISTS_ADD_IF_DIFFERENT;
|
||||||
else if (!strcasecmp("addIfDifferentNeighbor", value))
|
else if (!strcasecmp("addIfDifferentNeighbor", value))
|
||||||
*item = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
|
*item = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
|
||||||
@ -402,7 +413,9 @@ int trailer_set_if_exists(enum trailer_if_exists *item, const char *value)
|
|||||||
|
|
||||||
int trailer_set_if_missing(enum trailer_if_missing *item, const char *value)
|
int trailer_set_if_missing(enum trailer_if_missing *item, const char *value)
|
||||||
{
|
{
|
||||||
if (!strcasecmp("doNothing", value))
|
if (!value)
|
||||||
|
*item = MISSING_DEFAULT;
|
||||||
|
else if (!strcasecmp("doNothing", value))
|
||||||
*item = MISSING_DO_NOTHING;
|
*item = MISSING_DO_NOTHING;
|
||||||
else if (!strcasecmp("add", value))
|
else if (!strcasecmp("add", value))
|
||||||
*item = MISSING_ADD;
|
*item = MISSING_ADD;
|
||||||
@ -659,12 +672,21 @@ static struct trailer_item *add_trailer_item(struct list_head *head, char *tok,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void add_arg_item(struct list_head *arg_head, char *tok, char *val,
|
static void add_arg_item(struct list_head *arg_head, char *tok, char *val,
|
||||||
const struct conf_info *conf)
|
const struct conf_info *conf,
|
||||||
|
const struct new_trailer_item *new_trailer_item)
|
||||||
{
|
{
|
||||||
struct arg_item *new = xcalloc(sizeof(*new), 1);
|
struct arg_item *new = xcalloc(sizeof(*new), 1);
|
||||||
new->token = tok;
|
new->token = tok;
|
||||||
new->value = val;
|
new->value = val;
|
||||||
duplicate_conf(&new->conf, conf);
|
duplicate_conf(&new->conf, conf);
|
||||||
|
if (new_trailer_item) {
|
||||||
|
if (new_trailer_item->where != WHERE_DEFAULT)
|
||||||
|
new->conf.where = new_trailer_item->where;
|
||||||
|
if (new_trailer_item->if_exists != EXISTS_DEFAULT)
|
||||||
|
new->conf.if_exists = new_trailer_item->if_exists;
|
||||||
|
if (new_trailer_item->if_missing != MISSING_DEFAULT)
|
||||||
|
new->conf.if_missing = new_trailer_item->if_missing;
|
||||||
|
}
|
||||||
list_add_tail(&new->list, arg_head);
|
list_add_tail(&new->list, arg_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +712,7 @@ static void process_command_line_args(struct list_head *arg_head,
|
|||||||
add_arg_item(arg_head,
|
add_arg_item(arg_head,
|
||||||
xstrdup(token_from_item(item, NULL)),
|
xstrdup(token_from_item(item, NULL)),
|
||||||
xstrdup(""),
|
xstrdup(""),
|
||||||
&item->conf);
|
&item->conf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an arg item for each trailer on the command line */
|
/* Add an arg item for each trailer on the command line */
|
||||||
@ -712,7 +734,7 @@ static void process_command_line_args(struct list_head *arg_head,
|
|||||||
add_arg_item(arg_head,
|
add_arg_item(arg_head,
|
||||||
strbuf_detach(&tok, NULL),
|
strbuf_detach(&tok, NULL),
|
||||||
strbuf_detach(&val, NULL),
|
strbuf_detach(&val, NULL),
|
||||||
conf);
|
conf, tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,14 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
enum trailer_where {
|
enum trailer_where {
|
||||||
|
WHERE_DEFAULT,
|
||||||
WHERE_END,
|
WHERE_END,
|
||||||
WHERE_AFTER,
|
WHERE_AFTER,
|
||||||
WHERE_BEFORE,
|
WHERE_BEFORE,
|
||||||
WHERE_START
|
WHERE_START
|
||||||
};
|
};
|
||||||
enum trailer_if_exists {
|
enum trailer_if_exists {
|
||||||
|
EXISTS_DEFAULT,
|
||||||
EXISTS_ADD_IF_DIFFERENT_NEIGHBOR,
|
EXISTS_ADD_IF_DIFFERENT_NEIGHBOR,
|
||||||
EXISTS_ADD_IF_DIFFERENT,
|
EXISTS_ADD_IF_DIFFERENT,
|
||||||
EXISTS_ADD,
|
EXISTS_ADD,
|
||||||
@ -17,6 +19,7 @@ enum trailer_if_exists {
|
|||||||
EXISTS_DO_NOTHING
|
EXISTS_DO_NOTHING
|
||||||
};
|
};
|
||||||
enum trailer_if_missing {
|
enum trailer_if_missing {
|
||||||
|
MISSING_DEFAULT,
|
||||||
MISSING_ADD,
|
MISSING_ADD,
|
||||||
MISSING_DO_NOTHING
|
MISSING_DO_NOTHING
|
||||||
};
|
};
|
||||||
@ -54,6 +57,10 @@ struct new_trailer_item {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
|
||||||
const char *text;
|
const char *text;
|
||||||
|
|
||||||
|
enum trailer_where where;
|
||||||
|
enum trailer_if_exists if_exists;
|
||||||
|
enum trailer_if_missing if_missing;
|
||||||
};
|
};
|
||||||
|
|
||||||
void process_trailers(const char *file, int in_place, int trim_empty,
|
void process_trailers(const char *file, int in_place, int trim_empty,
|
||||||
|
Reference in New Issue
Block a user