2424#include "notes-utils.h"
2525#include "worktree.h"
2626
27+ static char * separator = NULL ;
2728static const char * const git_notes_usage [] = {
2829 N_ ("git notes [--ref <notes-ref>] [list [<object>]]" ),
29- N_ ("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
30+ N_ ("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--separator=<paragraph-break>] [- m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
3031 N_ ("git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>" ),
31- N_ ("git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
32+ N_ ("git notes [--ref <notes-ref>] append [--allow-empty] [--separator=<paragraph-break>] [- m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
3233 N_ ("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]" ),
3334 N_ ("git notes [--ref <notes-ref>] show [<object>]" ),
3435 N_ ("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>" ),
@@ -96,11 +97,19 @@ static const char * const git_notes_get_ref_usage[] = {
9697static const char note_template [] =
9798 N_ ("Write/edit the notes for the following object:" );
9899
100+ struct note_msg {
101+ int stripspace ;
102+ struct strbuf buf ;
103+ };
104+
99105struct note_data {
100106 int given ;
101107 int use_editor ;
102108 char * edit_path ;
103109 struct strbuf buf ;
110+ struct note_msg * * messages ;
111+ size_t msg_nr ;
112+ size_t msg_alloc ;
104113};
105114
106115static void free_note_data (struct note_data * d )
@@ -110,6 +119,13 @@ static void free_note_data(struct note_data *d)
110119 free (d -> edit_path );
111120 }
112121 strbuf_release (& d -> buf );
122+
123+ while (d -> msg_nr ) {
124+ -- d -> msg_nr ;
125+ strbuf_release (& d -> messages [d -> msg_nr ]-> buf );
126+ free (d -> messages [d -> msg_nr ]);
127+ }
128+ free (d -> messages );
113129}
114130
115131static int list_each_note (const struct object_id * object_oid ,
@@ -209,71 +225,109 @@ static void write_note_data(struct note_data *d, struct object_id *oid)
209225 }
210226}
211227
228+ static void insert_separator (struct strbuf * message , size_t pos )
229+ {
230+ if (!separator )
231+ strbuf_insertstr (message , pos , "\n" );
232+ else if (separator [strlen (separator ) - 1 ] == '\n' )
233+ strbuf_insertstr (message , pos , separator );
234+ else
235+ strbuf_insertf (message , pos , "%s%s" , separator , "\n" );
236+ }
237+
238+ /* Consume messages and append them into d->buf, then free them */
239+ static void concat_messages (struct note_data * d )
240+ {
241+ struct strbuf msg = STRBUF_INIT ;
242+
243+ size_t i ;
244+ for (i = 0 ; i < d -> msg_nr ; i ++ ) {
245+ if (d -> buf .len )
246+ insert_separator (& d -> buf , d -> buf .len );
247+ strbuf_add (& msg , d -> messages [i ]-> buf .buf , d -> messages [i ]-> buf .len );
248+ strbuf_addbuf (& d -> buf , & msg );
249+ if (d -> messages [i ]-> stripspace )
250+ strbuf_stripspace (& d -> buf , 0 );
251+ strbuf_reset (& msg );
252+ strbuf_release (& d -> messages [i ]-> buf );
253+ free (d -> messages [i ]);
254+ }
255+ strbuf_release (& msg );
256+ free (d -> messages );
257+ }
258+
212259static int parse_msg_arg (const struct option * opt , const char * arg , int unset )
213260{
214261 struct note_data * d = opt -> value ;
262+ struct note_msg * msg = xmalloc (sizeof (* msg ));
215263
216264 BUG_ON_OPT_NEG (unset );
217265
218- if (d -> buf .len )
219- strbuf_addch (& d -> buf , '\n' );
220- strbuf_addstr (& d -> buf , arg );
221- strbuf_stripspace (& d -> buf , 0 );
222-
223- d -> given = 1 ;
266+ strbuf_init (& msg -> buf , strlen (arg ));
267+ strbuf_addstr (& msg -> buf , arg );
268+ ALLOC_GROW_BY (d -> messages , d -> msg_nr , 1 , d -> msg_alloc );
269+ d -> messages [d -> msg_nr - 1 ] = msg ;
270+ msg -> stripspace = 1 ;
224271 return 0 ;
225272}
226273
227274static int parse_file_arg (const struct option * opt , const char * arg , int unset )
228275{
229276 struct note_data * d = opt -> value ;
277+ struct note_msg * msg = xmalloc (sizeof (* msg ));
230278
231279 BUG_ON_OPT_NEG (unset );
232280
233- if (d -> buf .len )
234- strbuf_addch (& d -> buf , '\n' );
281+ strbuf_init (& msg -> buf , 0 );
235282 if (!strcmp (arg , "-" )) {
236- if (strbuf_read (& d -> buf , 0 , 1024 ) < 0 )
283+ if (strbuf_read (& msg -> buf , 0 , 1024 ) < 0 )
237284 die_errno (_ ("cannot read '%s'" ), arg );
238- } else if (strbuf_read_file (& d -> buf , arg , 1024 ) < 0 )
285+ } else if (strbuf_read_file (& msg -> buf , arg , 1024 ) < 0 )
239286 die_errno (_ ("could not open or read '%s'" ), arg );
240- strbuf_stripspace (& d -> buf , 0 );
241287
242- d -> given = 1 ;
288+ ALLOC_GROW_BY (d -> messages , d -> msg_nr , 1 , d -> msg_alloc );
289+ d -> messages [d -> msg_nr - 1 ] = msg ;
290+ msg -> stripspace = 1 ;
243291 return 0 ;
244292}
245293
246294static int parse_reuse_arg (const struct option * opt , const char * arg , int unset )
247295{
248296 struct note_data * d = opt -> value ;
249- char * buf ;
297+ struct note_msg * msg = xmalloc (sizeof (* msg ));
298+ char * value ;
250299 struct object_id object ;
251300 enum object_type type ;
252301 unsigned long len ;
253302
254303 BUG_ON_OPT_NEG (unset );
255304
256- if (d -> buf .len )
257- strbuf_addch (& d -> buf , '\n' );
258-
305+ strbuf_init (& msg -> buf , 0 );
259306 if (get_oid (arg , & object ))
260307 die (_ ("failed to resolve '%s' as a valid ref." ), arg );
261- if (!(buf = read_object_file (& object , & type , & len )))
308+ if (!(value = read_object_file (& object , & type , & len )))
262309 die (_ ("failed to read object '%s'." ), arg );
263310 if (type != OBJ_BLOB ) {
264- free (buf );
311+ strbuf_release (& msg -> buf );
312+ free (value );
313+ free (msg );
265314 die (_ ("cannot read note data from non-blob object '%s'." ), arg );
266315 }
267- strbuf_add (& d -> buf , buf , len );
268- free (buf );
269316
270- d -> given = 1 ;
317+ strbuf_add (& msg -> buf , value , len );
318+ free (value );
319+
320+ msg -> buf .len = len ;
321+ ALLOC_GROW_BY (d -> messages , d -> msg_nr , 1 , d -> msg_alloc );
322+ d -> messages [d -> msg_nr - 1 ] = msg ;
323+ msg -> stripspace = 0 ;
271324 return 0 ;
272325}
273326
274327static int parse_reedit_arg (const struct option * opt , const char * arg , int unset )
275328{
276329 struct note_data * d = opt -> value ;
330+
277331 BUG_ON_OPT_NEG (unset );
278332 d -> use_editor = 1 ;
279333 return parse_reuse_arg (opt , arg , unset );
@@ -402,6 +456,7 @@ static int add(int argc, const char **argv, const char *prefix)
402456 struct object_id object , new_note ;
403457 const struct object_id * note ;
404458 struct note_data d = { .buf = STRBUF_INIT };
459+
405460 struct option options [] = {
406461 OPT_CALLBACK_F ('m' , "message" , & d , N_ ("message" ),
407462 N_ ("note contents as a string" ), PARSE_OPT_NONEG ,
@@ -418,6 +473,8 @@ static int add(int argc, const char **argv, const char *prefix)
418473 OPT_BOOL (0 , "allow-empty" , & allow_empty ,
419474 N_ ("allow storing empty note" )),
420475 OPT__FORCE (& force , N_ ("replace existing notes" ), PARSE_OPT_NOCOMPLETE ),
476+ OPT_STRING (0 , "separator" , & separator , N_ ("separator" ),
477+ N_ ("insert <paragraph-break> between paragraphs" )),
421478 OPT_END ()
422479 };
423480
@@ -429,6 +486,10 @@ static int add(int argc, const char **argv, const char *prefix)
429486 usage_with_options (git_notes_add_usage , options );
430487 }
431488
489+ if (d .msg_nr )
490+ concat_messages (& d );
491+ d .given = !!d .buf .len ;
492+
432493 object_ref = argc > 1 ? argv [1 ] : "HEAD" ;
433494
434495 if (get_oid (object_ref , & object ))
@@ -568,6 +629,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
568629 char * logmsg ;
569630 const char * const * usage ;
570631 struct note_data d = { .buf = STRBUF_INIT };
632+
571633 struct option options [] = {
572634 OPT_CALLBACK_F ('m' , "message" , & d , N_ ("message" ),
573635 N_ ("note contents as a string" ), PARSE_OPT_NONEG ,
@@ -583,6 +645,8 @@ static int append_edit(int argc, const char **argv, const char *prefix)
583645 parse_reuse_arg ),
584646 OPT_BOOL (0 , "allow-empty" , & allow_empty ,
585647 N_ ("allow storing empty note" )),
648+ OPT_STRING (0 , "separator" , & separator , N_ ("separator" ),
649+ N_ ("insert <paragraph-break> between paragraphs" )),
586650 OPT_END ()
587651 };
588652 int edit = !strcmp (argv [0 ], "edit" );
@@ -596,6 +660,10 @@ static int append_edit(int argc, const char **argv, const char *prefix)
596660 usage_with_options (usage , options );
597661 }
598662
663+ if (d .msg_nr )
664+ concat_messages (& d );
665+ d .given = !!d .buf .len ;
666+
599667 if (d .given && edit )
600668 fprintf (stderr , _ ("The -m/-F/-c/-C options have been deprecated "
601669 "for the 'edit' subcommand.\n"
@@ -615,13 +683,17 @@ static int append_edit(int argc, const char **argv, const char *prefix)
615683 /* Append buf to previous note contents */
616684 unsigned long size ;
617685 enum object_type type ;
686+ struct strbuf buf = STRBUF_INIT ;
618687 char * prev_buf = read_object_file (note , & type , & size );
619688
620- if (d .buf .len && prev_buf && size )
621- strbuf_insertstr (& d .buf , 0 , "\n" );
622689 if (prev_buf && size )
623- strbuf_insert (& d .buf , 0 , prev_buf , size );
690+ strbuf_add (& buf , prev_buf , size );
691+ if (d .buf .len && prev_buf && size )
692+ insert_separator (& buf , buf .len );
693+ strbuf_insert (& d .buf , 0 , buf .buf , buf .len );
694+
624695 free (prev_buf );
696+ strbuf_release (& buf );
625697 }
626698
627699 if (d .buf .len || allow_empty ) {
0 commit comments