When appending to a given notes object and the appended note is not empty too, we will insert a blank line at first which separates the existing note and the appended one, which as the separator. Sometimes, we want to use a specified <separator> as the separator. For example, if we specify as: * --separator='------': we will insert "------\n" as the separator, because user do not provide the line break char at last, we will add the trailing '\n' compatibly. * --separator='------\n': we will insert as-is because it contains the line break at last. * not specified --separator option: will use '\n' as the separator when do appending and this is the default behavour. * --separator='': we specify an empty separator which has the same behavour with --separator='\n' and or not specified the option. In addition, if a user specifies multple "-m" with "--separator", the separator should be inserted between the messages too, so we use OPT_STRING_LIST instead of OPT_CALLBACK_F to parse "-m" option, make sure the option value of "--separator" been parsed already when we need it. Signed-off-by: Teng Long <dyroneteng@xxxxxxxxx> --- Documentation/git-notes.txt | 12 ++++++-- builtin/notes.c | 31 +++++++++++++++++--- t/t3301-notes.sh | 58 +++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index efbc10f0..5abe6092 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -11,7 +11,7 @@ SYNOPSIS 'git notes' [list [<object>]] 'git notes' add [-f] [--allow-empty] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>] 'git notes' copy [-f] ( --stdin | <from-object> [<to-object>] ) -'git notes' append [--allow-empty] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>] +'git notes' append [--allow-empty] [--separator] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>] 'git notes' edit [--allow-empty] [<object>] 'git notes' show [<object>] 'git notes' merge [-v | -q] [-s <strategy> ] <notes-ref> @@ -86,7 +86,9 @@ the command can read the input given to the `post-rewrite` hook.) append:: Append to the notes of an existing object (defaults to HEAD). - Creates a new notes object if needed. + Creates a new notes object if needed. If the note and the + message are not empty, "\n" will be inserted between them. + Use the `--separator` option to insert other delimiters. edit:: Edit the notes for a given object (defaults to HEAD). @@ -159,6 +161,12 @@ OPTIONS Allow an empty note object to be stored. The default behavior is to automatically remove empty notes. +--separator <separator>:: + The '<separator>' inserted between the note and message + by 'append', "\n" by default. A custom separator can be + provided, if it doesn't end in a "\n", one will be added + implicitly . + --ref <ref>:: Manipulate the notes tree in <ref>. This overrides `GIT_NOTES_REF` and the "core.notesRef" configuration. The ref diff --git a/builtin/notes.c b/builtin/notes.c index 553ae2bd..524976fe 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -24,6 +24,7 @@ #include "notes-utils.h" #include "worktree.h" +static char *separator = NULL; static const char * const git_notes_usage[] = { N_("git notes [--ref <notes-ref>] [list [<object>]]"), N_("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"), @@ -209,6 +210,16 @@ static void write_note_data(struct note_data *d, struct object_id *oid) } } +static void insert_separator(struct strbuf *message, size_t pos) +{ + if (!separator) + strbuf_insertstr(message, pos, "\n"); + else if (separator[strlen(separator) - 1] == '\n') + strbuf_insertstr(message, pos, separator); + else + strbuf_insertf(message, pos, "%s%s", separator, "\n"); +} + static int parse_msg_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; @@ -567,11 +578,12 @@ static int append_edit(int argc, const char **argv, const char *prefix) const struct object_id *note; char *logmsg; const char * const *usage; + size_t message_idx; struct note_data d = { .buf = STRBUF_INIT }; + struct string_list message = STRING_LIST_INIT_DUP; struct option options[] = { - OPT_CALLBACK_F('m', "message", &d, N_("message"), - N_("note contents as a string"), PARSE_OPT_NONEG, - parse_msg_arg), + OPT_STRING_LIST('m', "message", &message, N_("message"), + N_("note contents as a string")), OPT_CALLBACK_F('F', "file", &d, N_("file"), N_("note contents in a file"), PARSE_OPT_NONEG, parse_file_arg), @@ -583,6 +595,8 @@ static int append_edit(int argc, const char **argv, const char *prefix) parse_reuse_arg), OPT_BOOL(0, "allow-empty", &allow_empty, N_("allow storing empty note")), + OPT_STRING(0, "separator", &separator, N_("separator"), + N_("insert <separator> as separator before appending a message")), OPT_END() }; int edit = !strcmp(argv[0], "edit"); @@ -596,6 +610,15 @@ static int append_edit(int argc, const char **argv, const char *prefix) usage_with_options(usage, options); } + for (message_idx = 0; message_idx < message.nr; message_idx++) { + if (d.buf.len) + insert_separator(&d.buf, d.buf.len); + strbuf_insertstr(&d.buf, d.buf.len, + message.items[message_idx].string); + strbuf_stripspace(&d.buf, 0); + d.given = 1; + } + if (d.given && edit) fprintf(stderr, _("The -m/-F/-c/-C options have been deprecated " "for the 'edit' subcommand.\n" @@ -618,7 +641,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) char *prev_buf = read_object_file(note, &type, &size); if (d.buf.len && prev_buf && size) - strbuf_insertstr(&d.buf, 0, "\n"); + insert_separator(&d.buf, 0); if (prev_buf && size) strbuf_insert(&d.buf, 0, prev_buf, size); free(prev_buf); diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 3288aaec..fe00497b 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -521,6 +521,64 @@ test_expect_success 'listing non-existing notes fails' ' test_must_be_empty actual ' +test_expect_success 'append: specify an empty separator' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separatoro with line break' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------$LF" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator without line break' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator with multiple messages' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + ------- + notes-3 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------" -m "notes-2" -m "notes-3" && + git notes show >actual && + test_cmp expect actual +' + test_expect_success 'append to existing note with "git notes append"' ' cat >expect <<-EOF && Initial set of notes -- 2.39.2.459.g31d98a8e.dirty