16
16
#include "exec_cmd.h"
17
17
#include "run-command.h"
18
18
#include "parse-options.h"
19
+ #include "string-list.h"
19
20
20
21
static const char * const git_notes_usage [] = {
21
22
"git notes [list [<object>]]" ,
@@ -278,14 +279,121 @@ int commit_notes(struct notes_tree *t, const char *msg)
278
279
return 0 ;
279
280
}
280
281
281
- int notes_copy_from_stdin (int force )
282
+
283
+ combine_notes_fn * parse_combine_notes_fn (const char * v )
284
+ {
285
+ if (!strcasecmp (v , "overwrite" ))
286
+ return combine_notes_overwrite ;
287
+ else if (!strcasecmp (v , "ignore" ))
288
+ return combine_notes_ignore ;
289
+ else if (!strcasecmp (v , "concatenate" ))
290
+ return combine_notes_concatenate ;
291
+ else
292
+ return NULL ;
293
+ }
294
+
295
+ static int notes_rewrite_config (const char * k , const char * v , void * cb )
296
+ {
297
+ struct notes_rewrite_cfg * c = cb ;
298
+ if (!prefixcmp (k , "notes.rewrite." ) && !strcmp (k + 14 , c -> cmd )) {
299
+ c -> enabled = git_config_bool (k , v );
300
+ return 0 ;
301
+ } else if (!c -> mode_from_env && !strcmp (k , "notes.rewritemode" )) {
302
+ if (!v )
303
+ config_error_nonbool (k );
304
+ c -> combine = parse_combine_notes_fn (v );
305
+ if (!c -> combine ) {
306
+ error ("Bad notes.rewriteMode value: '%s'" , v );
307
+ return 1 ;
308
+ }
309
+ return 0 ;
310
+ } else if (!c -> refs_from_env && !strcmp (k , "notes.rewriteref" )) {
311
+ /* note that a refs/ prefix is implied in the
312
+ * underlying for_each_glob_ref */
313
+ if (!prefixcmp (v , "refs/notes/" ))
314
+ string_list_add_refs_by_glob (c -> refs , v );
315
+ else
316
+ warning ("Refusing to rewrite notes in %s"
317
+ " (outside of refs/notes/)" , v );
318
+ return 0 ;
319
+ }
320
+
321
+ return 0 ;
322
+ }
323
+
324
+
325
+ struct notes_rewrite_cfg * init_copy_notes_for_rewrite (const char * cmd )
326
+ {
327
+ struct notes_rewrite_cfg * c = xmalloc (sizeof (struct notes_rewrite_cfg ));
328
+ const char * rewrite_mode_env = getenv (GIT_NOTES_REWRITE_MODE_ENVIRONMENT );
329
+ const char * rewrite_refs_env = getenv (GIT_NOTES_REWRITE_REF_ENVIRONMENT );
330
+ c -> cmd = cmd ;
331
+ c -> enabled = 1 ;
332
+ c -> combine = combine_notes_concatenate ;
333
+ c -> refs = xcalloc (1 , sizeof (struct string_list ));
334
+ c -> refs -> strdup_strings = 1 ;
335
+ c -> refs_from_env = 0 ;
336
+ c -> mode_from_env = 0 ;
337
+ if (rewrite_mode_env ) {
338
+ c -> mode_from_env = 1 ;
339
+ c -> combine = parse_combine_notes_fn (rewrite_mode_env );
340
+ if (!c -> combine )
341
+ error ("Bad " GIT_NOTES_REWRITE_MODE_ENVIRONMENT
342
+ " value: '%s'" , rewrite_mode_env );
343
+ }
344
+ if (rewrite_refs_env ) {
345
+ c -> refs_from_env = 1 ;
346
+ string_list_add_refs_from_colon_sep (c -> refs , rewrite_refs_env );
347
+ }
348
+ git_config (notes_rewrite_config , c );
349
+ if (!c -> enabled || !c -> refs -> nr ) {
350
+ string_list_clear (c -> refs , 0 );
351
+ free (c -> refs );
352
+ free (c );
353
+ return NULL ;
354
+ }
355
+ c -> trees = load_notes_trees (c -> refs );
356
+ string_list_clear (c -> refs , 0 );
357
+ free (c -> refs );
358
+ return c ;
359
+ }
360
+
361
+ int copy_note_for_rewrite (struct notes_rewrite_cfg * c ,
362
+ const unsigned char * from_obj , const unsigned char * to_obj )
363
+ {
364
+ int ret = 0 ;
365
+ int i ;
366
+ for (i = 0 ; c -> trees [i ]; i ++ )
367
+ ret = copy_note (c -> trees [i ], from_obj , to_obj , 1 , c -> combine ) || ret ;
368
+ return ret ;
369
+ }
370
+
371
+ void finish_copy_notes_for_rewrite (struct notes_rewrite_cfg * c )
372
+ {
373
+ int i ;
374
+ for (i = 0 ; c -> trees [i ]; i ++ ) {
375
+ commit_notes (c -> trees [i ], "Notes added by 'git notes copy'" );
376
+ free_notes (c -> trees [i ]);
377
+ }
378
+ free (c -> trees );
379
+ free (c );
380
+ }
381
+
382
+ int notes_copy_from_stdin (int force , const char * rewrite_cmd )
282
383
{
283
384
struct strbuf buf = STRBUF_INIT ;
385
+ struct notes_rewrite_cfg * c = NULL ;
284
386
struct notes_tree * t ;
285
387
int ret = 0 ;
286
388
287
- init_notes (NULL , NULL , NULL , 0 );
288
- t = & default_notes_tree ;
389
+ if (rewrite_cmd ) {
390
+ c = init_copy_notes_for_rewrite (rewrite_cmd );
391
+ if (!c )
392
+ return 0 ;
393
+ } else {
394
+ init_notes (NULL , NULL , NULL , 0 );
395
+ t = & default_notes_tree ;
396
+ }
289
397
290
398
while (strbuf_getline (& buf , stdin , '\n' ) != EOF ) {
291
399
unsigned char from_obj [20 ], to_obj [20 ];
@@ -302,7 +410,11 @@ int notes_copy_from_stdin(int force)
302
410
if (get_sha1 (split [1 ]-> buf , to_obj ))
303
411
die ("Failed to resolve '%s' as a valid ref." , split [1 ]-> buf );
304
412
305
- err = copy_note (t , from_obj , to_obj , force , combine_notes_overwrite );
413
+ if (rewrite_cmd )
414
+ err = copy_note_for_rewrite (c , from_obj , to_obj );
415
+ else
416
+ err = copy_note (t , from_obj , to_obj , force ,
417
+ combine_notes_overwrite );
306
418
307
419
if (err ) {
308
420
error ("Failed to copy notes from '%s' to '%s'" ,
@@ -313,8 +425,12 @@ int notes_copy_from_stdin(int force)
313
425
strbuf_list_free (split );
314
426
}
315
427
316
- commit_notes (t , "Notes added by 'git notes copy'" );
317
- free_notes (t );
428
+ if (!rewrite_cmd ) {
429
+ commit_notes (t , "Notes added by 'git notes copy'" );
430
+ free_notes (t );
431
+ } else {
432
+ finish_copy_notes_for_rewrite (c );
433
+ }
318
434
return ret ;
319
435
}
320
436
@@ -330,6 +446,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
330
446
remove = 0 , prune = 0 , force = 0 , from_stdin = 0 ;
331
447
int given_object = 0 , i = 1 , retval = 0 ;
332
448
struct msg_arg msg = { 0 , 0 , STRBUF_INIT };
449
+ const char * rewrite_cmd = NULL ;
333
450
struct option options [] = {
334
451
OPT_GROUP ("Notes options" ),
335
452
OPT_CALLBACK ('m' , "message" , & msg , "MSG" ,
@@ -342,6 +459,8 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
342
459
"reuse specified note object" , parse_reuse_arg ),
343
460
OPT_BOOLEAN ('f' , "force" , & force , "replace existing notes" ),
344
461
OPT_BOOLEAN (0 , "stdin" , & from_stdin , "read objects from stdin" ),
462
+ OPT_STRING (0 , "for-rewrite" , & rewrite_cmd , "command" ,
463
+ "load rewriting config for <command> (implies --stdin)" ),
345
464
OPT_END ()
346
465
};
347
466
@@ -390,19 +509,23 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
390
509
usage_with_options (git_notes_usage , options );
391
510
}
392
511
512
+ if (!copy && rewrite_cmd ) {
513
+ error ("cannot use --for-rewrite with %s subcommand." , argv [0 ]);
514
+ usage_with_options (git_notes_usage , options );
515
+ }
393
516
if (!copy && from_stdin ) {
394
517
error ("cannot use --stdin with %s subcommand." , argv [0 ]);
395
518
usage_with_options (git_notes_usage , options );
396
519
}
397
520
398
521
if (copy ) {
399
522
const char * from_ref ;
400
- if (from_stdin ) {
523
+ if (from_stdin || rewrite_cmd ) {
401
524
if (argc > 1 ) {
402
525
error ("too many parameters" );
403
526
usage_with_options (git_notes_usage , options );
404
527
} else {
405
- return notes_copy_from_stdin (force );
528
+ return notes_copy_from_stdin (force , rewrite_cmd );
406
529
}
407
530
}
408
531
if (argc < 3 ) {
0 commit comments