9
9
10
10
#include "builtin.h"
11
11
#include "config.h"
12
+ #include "alloc.h"
12
13
#include "editor.h"
13
14
#include "environment.h"
14
15
#include "gettext.h"
30
31
#include "worktree.h"
31
32
#include "write-or-die.h"
32
33
34
+ static const char * separator = "\n" ;
33
35
static const char * const git_notes_usage [] = {
34
36
N_ ("git notes [--ref <notes-ref>] [list [<object>]]" ),
35
- N_ ("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
37
+ N_ ("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [- m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
36
38
N_ ("git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>" ),
37
- N_ ("git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
39
+ N_ ("git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [- m <msg> | -F <file> | (-c | -C) <object>] [<object>]" ),
38
40
N_ ("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]" ),
39
41
N_ ("git notes [--ref <notes-ref>] show [<object>]" ),
40
42
N_ ("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>" ),
@@ -102,11 +104,26 @@ static const char * const git_notes_get_ref_usage[] = {
102
104
static const char note_template [] =
103
105
N_ ("Write/edit the notes for the following object:" );
104
106
107
+ enum notes_stripspace {
108
+ UNSPECIFIED = -1 ,
109
+ NO_STRIPSPACE = 0 ,
110
+ STRIPSPACE = 1 ,
111
+ };
112
+
113
+ struct note_msg {
114
+ enum notes_stripspace stripspace ;
115
+ struct strbuf buf ;
116
+ };
117
+
105
118
struct note_data {
106
119
int given ;
107
120
int use_editor ;
121
+ int stripspace ;
108
122
char * edit_path ;
109
123
struct strbuf buf ;
124
+ struct note_msg * * messages ;
125
+ size_t msg_nr ;
126
+ size_t msg_alloc ;
110
127
};
111
128
112
129
static void free_note_data (struct note_data * d )
@@ -116,6 +133,12 @@ static void free_note_data(struct note_data *d)
116
133
free (d -> edit_path );
117
134
}
118
135
strbuf_release (& d -> buf );
136
+
137
+ while (d -> msg_nr -- ) {
138
+ strbuf_release (& d -> messages [d -> msg_nr ]-> buf );
139
+ free (d -> messages [d -> msg_nr ]);
140
+ }
141
+ free (d -> messages );
119
142
}
120
143
121
144
static int list_each_note (const struct object_id * object_oid ,
@@ -201,7 +224,8 @@ static void prepare_note_data(const struct object_id *object, struct note_data *
201
224
if (launch_editor (d -> edit_path , & d -> buf , NULL )) {
202
225
die (_ ("please supply the note contents using either -m or -F option" ));
203
226
}
204
- strbuf_stripspace (& d -> buf , comment_line_char );
227
+ if (d -> stripspace )
228
+ strbuf_stripspace (& d -> buf , comment_line_char );
205
229
}
206
230
}
207
231
@@ -217,66 +241,102 @@ static void write_note_data(struct note_data *d, struct object_id *oid)
217
241
}
218
242
}
219
243
244
+ static void append_separator (struct strbuf * message )
245
+ {
246
+ size_t sep_len = 0 ;
247
+
248
+ if (!separator )
249
+ return ;
250
+ else if ((sep_len = strlen (separator )) && separator [sep_len - 1 ] == '\n' )
251
+ strbuf_addstr (message , separator );
252
+ else
253
+ strbuf_addf (message , "%s%s" , separator , "\n" );
254
+ }
255
+
256
+ static void concat_messages (struct note_data * d )
257
+ {
258
+ struct strbuf msg = STRBUF_INIT ;
259
+ size_t i ;
260
+
261
+ for (i = 0 ; i < d -> msg_nr ; i ++ ) {
262
+ if (d -> buf .len )
263
+ append_separator (& d -> buf );
264
+ strbuf_add (& msg , d -> messages [i ]-> buf .buf , d -> messages [i ]-> buf .len );
265
+ strbuf_addbuf (& d -> buf , & msg );
266
+ if ((d -> stripspace == UNSPECIFIED &&
267
+ d -> messages [i ]-> stripspace == STRIPSPACE ) ||
268
+ d -> stripspace == STRIPSPACE )
269
+ strbuf_stripspace (& d -> buf , 0 );
270
+ strbuf_reset (& msg );
271
+ }
272
+ strbuf_release (& msg );
273
+ }
274
+
220
275
static int parse_msg_arg (const struct option * opt , const char * arg , int unset )
221
276
{
222
277
struct note_data * d = opt -> value ;
278
+ struct note_msg * msg = xmalloc (sizeof (* msg ));
223
279
224
280
BUG_ON_OPT_NEG (unset );
225
281
226
- strbuf_grow (& d -> buf , strlen (arg ) + 2 );
227
- if (d -> buf .len )
228
- strbuf_addch (& d -> buf , '\n' );
229
- strbuf_addstr (& d -> buf , arg );
230
- strbuf_stripspace (& d -> buf , '\0' );
231
-
232
- d -> given = 1 ;
282
+ strbuf_init (& msg -> buf , strlen (arg ));
283
+ strbuf_addstr (& msg -> buf , arg );
284
+ ALLOC_GROW_BY (d -> messages , d -> msg_nr , 1 , d -> msg_alloc );
285
+ d -> messages [d -> msg_nr - 1 ] = msg ;
286
+ msg -> stripspace = STRIPSPACE ;
233
287
return 0 ;
234
288
}
235
289
236
290
static int parse_file_arg (const struct option * opt , const char * arg , int unset )
237
291
{
238
292
struct note_data * d = opt -> value ;
293
+ struct note_msg * msg = xmalloc (sizeof (* msg ));
239
294
240
295
BUG_ON_OPT_NEG (unset );
241
296
242
- if (d -> buf .len )
243
- strbuf_addch (& d -> buf , '\n' );
297
+ strbuf_init (& msg -> buf , 0 );
244
298
if (!strcmp (arg , "-" )) {
245
- if (strbuf_read (& d -> buf , 0 , 1024 ) < 0 )
299
+ if (strbuf_read (& msg -> buf , 0 , 1024 ) < 0 )
246
300
die_errno (_ ("cannot read '%s'" ), arg );
247
- } else if (strbuf_read_file (& d -> buf , arg , 1024 ) < 0 )
301
+ } else if (strbuf_read_file (& msg -> buf , arg , 1024 ) < 0 )
248
302
die_errno (_ ("could not open or read '%s'" ), arg );
249
- strbuf_stripspace (& d -> buf , '\0' );
250
303
251
- d -> given = 1 ;
304
+ ALLOC_GROW_BY (d -> messages , d -> msg_nr , 1 , d -> msg_alloc );
305
+ d -> messages [d -> msg_nr - 1 ] = msg ;
306
+ msg -> stripspace = STRIPSPACE ;
252
307
return 0 ;
253
308
}
254
309
255
310
static int parse_reuse_arg (const struct option * opt , const char * arg , int unset )
256
311
{
257
312
struct note_data * d = opt -> value ;
258
- char * buf ;
313
+ struct note_msg * msg = xmalloc (sizeof (* msg ));
314
+ char * value ;
259
315
struct object_id object ;
260
316
enum object_type type ;
261
317
unsigned long len ;
262
318
263
319
BUG_ON_OPT_NEG (unset );
264
320
265
- if (d -> buf .len )
266
- strbuf_addch (& d -> buf , '\n' );
267
-
321
+ strbuf_init (& msg -> buf , 0 );
268
322
if (repo_get_oid (the_repository , arg , & object ))
269
323
die (_ ("failed to resolve '%s' as a valid ref." ), arg );
270
- if (!(buf = repo_read_object_file (the_repository , & object , & type , & len )))
324
+ if (!(value = repo_read_object_file (the_repository , & object , & type , & len )))
271
325
die (_ ("failed to read object '%s'." ), arg );
272
326
if (type != OBJ_BLOB ) {
273
- free (buf );
327
+ strbuf_release (& msg -> buf );
328
+ free (value );
329
+ free (msg );
274
330
die (_ ("cannot read note data from non-blob object '%s'." ), arg );
275
331
}
276
- strbuf_add (& d -> buf , buf , len );
277
- free (buf );
278
332
279
- d -> given = 1 ;
333
+ strbuf_add (& msg -> buf , value , len );
334
+ free (value );
335
+
336
+ msg -> buf .len = len ;
337
+ ALLOC_GROW_BY (d -> messages , d -> msg_nr , 1 , d -> msg_alloc );
338
+ d -> messages [d -> msg_nr - 1 ] = msg ;
339
+ msg -> stripspace = NO_STRIPSPACE ;
280
340
return 0 ;
281
341
}
282
342
@@ -288,6 +348,16 @@ static int parse_reedit_arg(const struct option *opt, const char *arg, int unset
288
348
return parse_reuse_arg (opt , arg , unset );
289
349
}
290
350
351
+ static int parse_separator_arg (const struct option * opt , const char * arg ,
352
+ int unset )
353
+ {
354
+ if (unset )
355
+ * (const char * * )opt -> value = NULL ;
356
+ else
357
+ * (const char * * )opt -> value = arg ? arg : "\n" ;
358
+ return 0 ;
359
+ }
360
+
291
361
static int notes_copy_from_stdin (int force , const char * rewrite_cmd )
292
362
{
293
363
struct strbuf buf = STRBUF_INIT ;
@@ -410,7 +480,8 @@ static int add(int argc, const char **argv, const char *prefix)
410
480
struct notes_tree * t ;
411
481
struct object_id object , new_note ;
412
482
const struct object_id * note ;
413
- struct note_data d = { 0 , 0 , NULL , STRBUF_INIT };
483
+ struct note_data d = { .buf = STRBUF_INIT , .stripspace = UNSPECIFIED };
484
+
414
485
struct option options [] = {
415
486
OPT_CALLBACK_F ('m' , "message" , & d , N_ ("message" ),
416
487
N_ ("note contents as a string" ), PARSE_OPT_NONEG ,
@@ -427,6 +498,12 @@ static int add(int argc, const char **argv, const char *prefix)
427
498
OPT_BOOL (0 , "allow-empty" , & allow_empty ,
428
499
N_ ("allow storing empty note" )),
429
500
OPT__FORCE (& force , N_ ("replace existing notes" ), PARSE_OPT_NOCOMPLETE ),
501
+ OPT_CALLBACK_F (0 , "separator" , & separator ,
502
+ N_ ("<paragraph-break>" ),
503
+ N_ ("insert <paragraph-break> between paragraphs" ),
504
+ PARSE_OPT_OPTARG , parse_separator_arg ),
505
+ OPT_BOOL (0 , "stripspace" , & d .stripspace ,
506
+ N_ ("remove unnecessary whitespace" )),
430
507
OPT_END ()
431
508
};
432
509
@@ -438,6 +515,10 @@ static int add(int argc, const char **argv, const char *prefix)
438
515
usage_with_options (git_notes_add_usage , options );
439
516
}
440
517
518
+ if (d .msg_nr )
519
+ concat_messages (& d );
520
+ d .given = !!d .buf .len ;
521
+
441
522
object_ref = argc > 1 ? argv [1 ] : "HEAD" ;
442
523
443
524
if (repo_get_oid (the_repository , object_ref , & object ))
@@ -576,7 +657,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
576
657
const struct object_id * note ;
577
658
char * logmsg ;
578
659
const char * const * usage ;
579
- struct note_data d = { 0 , 0 , NULL , STRBUF_INIT };
660
+ struct note_data d = { . buf = STRBUF_INIT , . stripspace = UNSPECIFIED };
580
661
struct option options [] = {
581
662
OPT_CALLBACK_F ('m' , "message" , & d , N_ ("message" ),
582
663
N_ ("note contents as a string" ), PARSE_OPT_NONEG ,
@@ -592,6 +673,12 @@ static int append_edit(int argc, const char **argv, const char *prefix)
592
673
parse_reuse_arg ),
593
674
OPT_BOOL (0 , "allow-empty" , & allow_empty ,
594
675
N_ ("allow storing empty note" )),
676
+ OPT_CALLBACK_F (0 , "separator" , & separator ,
677
+ N_ ("<paragraph-break>" ),
678
+ N_ ("insert <paragraph-break> between paragraphs" ),
679
+ PARSE_OPT_OPTARG , parse_separator_arg ),
680
+ OPT_BOOL (0 , "stripspace" , & d .stripspace ,
681
+ N_ ("remove unnecessary whitespace" )),
595
682
OPT_END ()
596
683
};
597
684
int edit = !strcmp (argv [0 ], "edit" );
@@ -605,6 +692,10 @@ static int append_edit(int argc, const char **argv, const char *prefix)
605
692
usage_with_options (usage , options );
606
693
}
607
694
695
+ if (d .msg_nr )
696
+ concat_messages (& d );
697
+ d .given = !!d .buf .len ;
698
+
608
699
if (d .given && edit )
609
700
fprintf (stderr , _ ("The -m/-F/-c/-C options have been deprecated "
610
701
"for the 'edit' subcommand.\n"
@@ -624,15 +715,17 @@ static int append_edit(int argc, const char **argv, const char *prefix)
624
715
/* Append buf to previous note contents */
625
716
unsigned long size ;
626
717
enum object_type type ;
627
- char * prev_buf = repo_read_object_file ( the_repository , note ,
628
- & type , & size );
718
+ struct strbuf buf = STRBUF_INIT ;
719
+ char * prev_buf = repo_read_object_file ( the_repository , note , & type , & size );
629
720
630
- strbuf_grow (& d .buf , size + 1 );
631
- if (d .buf .len && prev_buf && size )
632
- strbuf_insertstr (& d .buf , 0 , "\n" );
633
721
if (prev_buf && size )
634
- strbuf_insert (& d .buf , 0 , prev_buf , size );
722
+ strbuf_add (& buf , prev_buf , size );
723
+ if (d .buf .len && prev_buf && size )
724
+ append_separator (& buf );
725
+ strbuf_insert (& d .buf , 0 , buf .buf , buf .len );
726
+
635
727
free (prev_buf );
728
+ strbuf_release (& buf );
636
729
}
637
730
638
731
if (d .buf .len || allow_empty ) {
0 commit comments