зеркало из https://github.com/microsoft/git.git
interpret-trailers: add an option to show only the trailers
In theory it's easy for any reader who wants to parse trailers to do so. But there are a lot of subtle corner cases around what counts as a trailer, when the trailer block begins and ends, etc. Since interpret-trailers already has our parsing logic, let's let callers ask it to just output the trailers. They still have to parse the "key: value" lines, but at least they can ignore all of the other corner cases. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
8abc89800c
Коммит
56c493ed1b
|
@ -80,6 +80,9 @@ OPTIONS
|
||||||
trailer to the input messages. See the description of this
|
trailer to the input messages. See the description of this
|
||||||
command.
|
command.
|
||||||
|
|
||||||
|
--only-trailers::
|
||||||
|
Output only the trailers, not any other parts of the input.
|
||||||
|
|
||||||
CONFIGURATION VARIABLES
|
CONFIGURATION VARIABLES
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
|
OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
|
||||||
OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
|
OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
|
||||||
|
OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
|
||||||
OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"),
|
OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"),
|
||||||
N_("trailer(s) to add")),
|
N_("trailer(s) to add")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
|
|
|
@ -1275,4 +1275,43 @@ test_expect_success 'with cut line' '
|
||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'only trailers' '
|
||||||
|
git config trailer.sign.command "echo config-value" &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
existing: existing-value
|
||||||
|
sign: config-value
|
||||||
|
added: added-value
|
||||||
|
EOF
|
||||||
|
git interpret-trailers \
|
||||||
|
--trailer added:added-value \
|
||||||
|
--only-trailers >actual <<-\EOF &&
|
||||||
|
my subject
|
||||||
|
|
||||||
|
my body
|
||||||
|
|
||||||
|
existing: existing-value
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'only-trailers omits non-trailer in middle of block' '
|
||||||
|
git config trailer.sign.command "echo config-value" &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
Signed-off-by: nobody <nobody@nowhere>
|
||||||
|
Signed-off-by: somebody <somebody@somewhere>
|
||||||
|
sign: config-value
|
||||||
|
EOF
|
||||||
|
git interpret-trailers --only-trailers >actual <<-\EOF &&
|
||||||
|
subject
|
||||||
|
|
||||||
|
it is important that the trailers below are signed-off-by
|
||||||
|
so that they meet the "25% trailers Git knows about" heuristic
|
||||||
|
|
||||||
|
Signed-off-by: nobody <nobody@nowhere>
|
||||||
|
this is not a trailer
|
||||||
|
Signed-off-by: somebody <somebody@somewhere>
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
23
trailer.c
23
trailer.c
|
@ -163,13 +163,15 @@ static void print_tok_val(FILE *outfile, const char *tok, const char *val)
|
||||||
fprintf(outfile, "%s%c %s\n", tok, separators[0], val);
|
fprintf(outfile, "%s%c %s\n", tok, separators[0], val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_all(FILE *outfile, struct list_head *head, int trim_empty)
|
static void print_all(FILE *outfile, struct list_head *head,
|
||||||
|
const struct process_trailer_options *opts)
|
||||||
{
|
{
|
||||||
struct list_head *pos;
|
struct list_head *pos;
|
||||||
struct trailer_item *item;
|
struct trailer_item *item;
|
||||||
list_for_each(pos, head) {
|
list_for_each(pos, head) {
|
||||||
item = list_entry(pos, struct trailer_item, list);
|
item = list_entry(pos, struct trailer_item, list);
|
||||||
if (!trim_empty || strlen(item->value) > 0)
|
if ((!opts->trim_empty || strlen(item->value) > 0) &&
|
||||||
|
(!opts->only_trailers || item->token))
|
||||||
print_tok_val(outfile, item->token, item->value);
|
print_tok_val(outfile, item->token, item->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -886,7 +888,8 @@ static int ends_with_blank_line(const char *buf, size_t len)
|
||||||
|
|
||||||
static int process_input_file(FILE *outfile,
|
static int process_input_file(FILE *outfile,
|
||||||
const char *str,
|
const char *str,
|
||||||
struct list_head *head)
|
struct list_head *head,
|
||||||
|
const struct process_trailer_options *opts)
|
||||||
{
|
{
|
||||||
struct trailer_info info;
|
struct trailer_info info;
|
||||||
struct strbuf tok = STRBUF_INIT;
|
struct strbuf tok = STRBUF_INIT;
|
||||||
|
@ -896,9 +899,10 @@ static int process_input_file(FILE *outfile,
|
||||||
trailer_info_get(&info, str);
|
trailer_info_get(&info, str);
|
||||||
|
|
||||||
/* Print lines before the trailers as is */
|
/* Print lines before the trailers as is */
|
||||||
fwrite(str, 1, info.trailer_start - str, outfile);
|
if (!opts->only_trailers)
|
||||||
|
fwrite(str, 1, info.trailer_start - str, outfile);
|
||||||
|
|
||||||
if (!info.blank_line_before_trailer)
|
if (!opts->only_trailers && !info.blank_line_before_trailer)
|
||||||
fprintf(outfile, "\n");
|
fprintf(outfile, "\n");
|
||||||
|
|
||||||
for (i = 0; i < info.trailer_nr; i++) {
|
for (i = 0; i < info.trailer_nr; i++) {
|
||||||
|
@ -913,7 +917,7 @@ static int process_input_file(FILE *outfile,
|
||||||
add_trailer_item(head,
|
add_trailer_item(head,
|
||||||
strbuf_detach(&tok, NULL),
|
strbuf_detach(&tok, NULL),
|
||||||
strbuf_detach(&val, NULL));
|
strbuf_detach(&val, NULL));
|
||||||
} else {
|
} else if (!opts->only_trailers) {
|
||||||
strbuf_addstr(&val, trailer);
|
strbuf_addstr(&val, trailer);
|
||||||
strbuf_strip_suffix(&val, "\n");
|
strbuf_strip_suffix(&val, "\n");
|
||||||
add_trailer_item(head,
|
add_trailer_item(head,
|
||||||
|
@ -985,18 +989,19 @@ void process_trailers(const char *file,
|
||||||
outfile = create_in_place_tempfile(file);
|
outfile = create_in_place_tempfile(file);
|
||||||
|
|
||||||
/* Print the lines before the trailers */
|
/* Print the lines before the trailers */
|
||||||
trailer_end = process_input_file(outfile, sb.buf, &head);
|
trailer_end = process_input_file(outfile, sb.buf, &head, opts);
|
||||||
|
|
||||||
process_command_line_args(&arg_head, trailers);
|
process_command_line_args(&arg_head, trailers);
|
||||||
|
|
||||||
process_trailers_lists(&head, &arg_head);
|
process_trailers_lists(&head, &arg_head);
|
||||||
|
|
||||||
print_all(outfile, &head, opts->trim_empty);
|
print_all(outfile, &head, opts);
|
||||||
|
|
||||||
free_all(&head);
|
free_all(&head);
|
||||||
|
|
||||||
/* Print the lines after the trailers as is */
|
/* Print the lines after the trailers as is */
|
||||||
fwrite(sb.buf + trailer_end, 1, sb.len - trailer_end, outfile);
|
if (!opts->only_trailers)
|
||||||
|
fwrite(sb.buf + trailer_end, 1, sb.len - trailer_end, outfile);
|
||||||
|
|
||||||
if (opts->in_place)
|
if (opts->in_place)
|
||||||
if (rename_tempfile(&trailers_tempfile, file))
|
if (rename_tempfile(&trailers_tempfile, file))
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct trailer_info {
|
||||||
struct process_trailer_options {
|
struct process_trailer_options {
|
||||||
int in_place;
|
int in_place;
|
||||||
int trim_empty;
|
int trim_empty;
|
||||||
|
int only_trailers;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PROCESS_TRAILER_OPTIONS_INIT {0}
|
#define PROCESS_TRAILER_OPTIONS_INIT {0}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче