зеркало из 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
|
||||
command.
|
||||
|
||||
--only-trailers::
|
||||
Output only the trailers, not any other parts of the input.
|
||||
|
||||
CONFIGURATION VARIABLES
|
||||
-----------------------
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
|
|||
struct option options[] = {
|
||||
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, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
|
||||
OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"),
|
||||
N_("trailer(s) to add")),
|
||||
OPT_END()
|
||||
|
|
|
@ -1275,4 +1275,43 @@ test_expect_success 'with cut line' '
|
|||
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
|
||||
|
|
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);
|
||||
}
|
||||
|
||||
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 trailer_item *item;
|
||||
list_for_each(pos, head) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -886,7 +888,8 @@ static int ends_with_blank_line(const char *buf, size_t len)
|
|||
|
||||
static int process_input_file(FILE *outfile,
|
||||
const char *str,
|
||||
struct list_head *head)
|
||||
struct list_head *head,
|
||||
const struct process_trailer_options *opts)
|
||||
{
|
||||
struct trailer_info info;
|
||||
struct strbuf tok = STRBUF_INIT;
|
||||
|
@ -896,9 +899,10 @@ static int process_input_file(FILE *outfile,
|
|||
trailer_info_get(&info, str);
|
||||
|
||||
/* 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");
|
||||
|
||||
for (i = 0; i < info.trailer_nr; i++) {
|
||||
|
@ -913,7 +917,7 @@ static int process_input_file(FILE *outfile,
|
|||
add_trailer_item(head,
|
||||
strbuf_detach(&tok, NULL),
|
||||
strbuf_detach(&val, NULL));
|
||||
} else {
|
||||
} else if (!opts->only_trailers) {
|
||||
strbuf_addstr(&val, trailer);
|
||||
strbuf_strip_suffix(&val, "\n");
|
||||
add_trailer_item(head,
|
||||
|
@ -985,18 +989,19 @@ void process_trailers(const char *file,
|
|||
outfile = create_in_place_tempfile(file);
|
||||
|
||||
/* 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_trailers_lists(&head, &arg_head);
|
||||
|
||||
print_all(outfile, &head, opts->trim_empty);
|
||||
print_all(outfile, &head, opts);
|
||||
|
||||
free_all(&head);
|
||||
|
||||
/* 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 (rename_tempfile(&trailers_tempfile, file))
|
||||
|
|
|
@ -25,6 +25,7 @@ struct trailer_info {
|
|||
struct process_trailer_options {
|
||||
int in_place;
|
||||
int trim_empty;
|
||||
int only_trailers;
|
||||
};
|
||||
|
||||
#define PROCESS_TRAILER_OPTIONS_INIT {0}
|
||||
|
|
Загрузка…
Ссылка в новой задаче