Merge branch 'sb/object-store-grafts'
[git] / builtin / notes.c
1 /*
2  * Builtin "git notes"
3  *
4  * Copyright (c) 2010 Johan Herland <johan@herland.net>
5  *
6  * Based on git-notes.sh by Johannes Schindelin,
7  * and builtin/tag.c by Kristian Høgsberg and Carlos Rica.
8  */
9
10 #include "cache.h"
11 #include "config.h"
12 #include "builtin.h"
13 #include "notes.h"
14 #include "object-store.h"
15 #include "blob.h"
16 #include "pretty.h"
17 #include "refs.h"
18 #include "exec-cmd.h"
19 #include "run-command.h"
20 #include "parse-options.h"
21 #include "string-list.h"
22 #include "notes-merge.h"
23 #include "notes-utils.h"
24 #include "worktree.h"
25
26 static const char * const git_notes_usage[] = {
27         N_("git notes [--ref <notes-ref>] [list [<object>]]"),
28         N_("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"),
29         N_("git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>"),
30         N_("git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"),
31         N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"),
32         N_("git notes [--ref <notes-ref>] show [<object>]"),
33         N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"),
34         N_("git notes merge --commit [-v | -q]"),
35         N_("git notes merge --abort [-v | -q]"),
36         N_("git notes [--ref <notes-ref>] remove [<object>...]"),
37         N_("git notes [--ref <notes-ref>] prune [-n] [-v]"),
38         N_("git notes [--ref <notes-ref>] get-ref"),
39         NULL
40 };
41
42 static const char * const git_notes_list_usage[] = {
43         N_("git notes [list [<object>]]"),
44         NULL
45 };
46
47 static const char * const git_notes_add_usage[] = {
48         N_("git notes add [<options>] [<object>]"),
49         NULL
50 };
51
52 static const char * const git_notes_copy_usage[] = {
53         N_("git notes copy [<options>] <from-object> <to-object>"),
54         N_("git notes copy --stdin [<from-object> <to-object>]..."),
55         NULL
56 };
57
58 static const char * const git_notes_append_usage[] = {
59         N_("git notes append [<options>] [<object>]"),
60         NULL
61 };
62
63 static const char * const git_notes_edit_usage[] = {
64         N_("git notes edit [<object>]"),
65         NULL
66 };
67
68 static const char * const git_notes_show_usage[] = {
69         N_("git notes show [<object>]"),
70         NULL
71 };
72
73 static const char * const git_notes_merge_usage[] = {
74         N_("git notes merge [<options>] <notes-ref>"),
75         N_("git notes merge --commit [<options>]"),
76         N_("git notes merge --abort [<options>]"),
77         NULL
78 };
79
80 static const char * const git_notes_remove_usage[] = {
81         N_("git notes remove [<object>]"),
82         NULL
83 };
84
85 static const char * const git_notes_prune_usage[] = {
86         N_("git notes prune [<options>]"),
87         NULL
88 };
89
90 static const char * const git_notes_get_ref_usage[] = {
91         N_("git notes get-ref"),
92         NULL
93 };
94
95 static const char note_template[] =
96         N_("Write/edit the notes for the following object:");
97
98 struct note_data {
99         int given;
100         int use_editor;
101         char *edit_path;
102         struct strbuf buf;
103 };
104
105 static void free_note_data(struct note_data *d)
106 {
107         if (d->edit_path) {
108                 unlink_or_warn(d->edit_path);
109                 free(d->edit_path);
110         }
111         strbuf_release(&d->buf);
112 }
113
114 static int list_each_note(const struct object_id *object_oid,
115                 const struct object_id *note_oid, char *note_path,
116                 void *cb_data)
117 {
118         printf("%s %s\n", oid_to_hex(note_oid), oid_to_hex(object_oid));
119         return 0;
120 }
121
122 static void copy_obj_to_fd(int fd, const struct object_id *oid)
123 {
124         unsigned long size;
125         enum object_type type;
126         char *buf = read_object_file(oid, &type, &size);
127         if (buf) {
128                 if (size)
129                         write_or_die(fd, buf, size);
130                 free(buf);
131         }
132 }
133
134 static void write_commented_object(int fd, const struct object_id *object)
135 {
136         const char *show_args[5] =
137                 {"show", "--stat", "--no-notes", oid_to_hex(object), NULL};
138         struct child_process show = CHILD_PROCESS_INIT;
139         struct strbuf buf = STRBUF_INIT;
140         struct strbuf cbuf = STRBUF_INIT;
141
142         /* Invoke "git show --stat --no-notes $object" */
143         show.argv = show_args;
144         show.no_stdin = 1;
145         show.out = -1;
146         show.err = 0;
147         show.git_cmd = 1;
148         if (start_command(&show))
149                 die(_("unable to start 'show' for object '%s'"),
150                     oid_to_hex(object));
151
152         if (strbuf_read(&buf, show.out, 0) < 0)
153                 die_errno(_("could not read 'show' output"));
154         strbuf_add_commented_lines(&cbuf, buf.buf, buf.len);
155         write_or_die(fd, cbuf.buf, cbuf.len);
156
157         strbuf_release(&cbuf);
158         strbuf_release(&buf);
159
160         if (finish_command(&show))
161                 die(_("failed to finish 'show' for object '%s'"),
162                     oid_to_hex(object));
163 }
164
165 static void prepare_note_data(const struct object_id *object, struct note_data *d,
166                 const struct object_id *old_note)
167 {
168         if (d->use_editor || !d->given) {
169                 int fd;
170                 struct strbuf buf = STRBUF_INIT;
171
172                 /* write the template message before editing: */
173                 d->edit_path = git_pathdup("NOTES_EDITMSG");
174                 fd = open(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
175                 if (fd < 0)
176                         die_errno(_("could not create file '%s'"), d->edit_path);
177
178                 if (d->given)
179                         write_or_die(fd, d->buf.buf, d->buf.len);
180                 else if (old_note)
181                         copy_obj_to_fd(fd, old_note);
182
183                 strbuf_addch(&buf, '\n');
184                 strbuf_add_commented_lines(&buf, "\n", strlen("\n"));
185                 strbuf_add_commented_lines(&buf, _(note_template), strlen(_(note_template)));
186                 strbuf_addch(&buf, '\n');
187                 write_or_die(fd, buf.buf, buf.len);
188
189                 write_commented_object(fd, object);
190
191                 close(fd);
192                 strbuf_release(&buf);
193                 strbuf_reset(&d->buf);
194
195                 if (launch_editor(d->edit_path, &d->buf, NULL)) {
196                         die(_("please supply the note contents using either -m or -F option"));
197                 }
198                 strbuf_stripspace(&d->buf, 1);
199         }
200 }
201
202 static void write_note_data(struct note_data *d, struct object_id *oid)
203 {
204         if (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) {
205                 error(_("unable to write note object"));
206                 if (d->edit_path)
207                         error(_("the note contents have been left in %s"),
208                                 d->edit_path);
209                 exit(128);
210         }
211 }
212
213 static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
214 {
215         struct note_data *d = opt->value;
216
217         strbuf_grow(&d->buf, strlen(arg) + 2);
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;
224         return 0;
225 }
226
227 static int parse_file_arg(const struct option *opt, const char *arg, int unset)
228 {
229         struct note_data *d = opt->value;
230
231         if (d->buf.len)
232                 strbuf_addch(&d->buf, '\n');
233         if (!strcmp(arg, "-")) {
234                 if (strbuf_read(&d->buf, 0, 1024) < 0)
235                         die_errno(_("cannot read '%s'"), arg);
236         } else if (strbuf_read_file(&d->buf, arg, 1024) < 0)
237                 die_errno(_("could not open or read '%s'"), arg);
238         strbuf_stripspace(&d->buf, 0);
239
240         d->given = 1;
241         return 0;
242 }
243
244 static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
245 {
246         struct note_data *d = opt->value;
247         char *buf;
248         struct object_id object;
249         enum object_type type;
250         unsigned long len;
251
252         if (d->buf.len)
253                 strbuf_addch(&d->buf, '\n');
254
255         if (get_oid(arg, &object))
256                 die(_("failed to resolve '%s' as a valid ref."), arg);
257         if (!(buf = read_object_file(&object, &type, &len))) {
258                 free(buf);
259                 die(_("failed to read object '%s'."), arg);
260         }
261         if (type != OBJ_BLOB) {
262                 free(buf);
263                 die(_("cannot read note data from non-blob object '%s'."), arg);
264         }
265         strbuf_add(&d->buf, buf, len);
266         free(buf);
267
268         d->given = 1;
269         return 0;
270 }
271
272 static int parse_reedit_arg(const struct option *opt, const char *arg, int unset)
273 {
274         struct note_data *d = opt->value;
275         d->use_editor = 1;
276         return parse_reuse_arg(opt, arg, unset);
277 }
278
279 static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
280 {
281         struct strbuf buf = STRBUF_INIT;
282         struct notes_rewrite_cfg *c = NULL;
283         struct notes_tree *t = NULL;
284         int ret = 0;
285         const char *msg = "Notes added by 'git notes copy'";
286
287         if (rewrite_cmd) {
288                 c = init_copy_notes_for_rewrite(rewrite_cmd);
289                 if (!c)
290                         return 0;
291         } else {
292                 init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE);
293                 t = &default_notes_tree;
294         }
295
296         while (strbuf_getline_lf(&buf, stdin) != EOF) {
297                 struct object_id from_obj, to_obj;
298                 struct strbuf **split;
299                 int err;
300
301                 split = strbuf_split(&buf, ' ');
302                 if (!split[0] || !split[1])
303                         die(_("malformed input line: '%s'."), buf.buf);
304                 strbuf_rtrim(split[0]);
305                 strbuf_rtrim(split[1]);
306                 if (get_oid(split[0]->buf, &from_obj))
307                         die(_("failed to resolve '%s' as a valid ref."), split[0]->buf);
308                 if (get_oid(split[1]->buf, &to_obj))
309                         die(_("failed to resolve '%s' as a valid ref."), split[1]->buf);
310
311                 if (rewrite_cmd)
312                         err = copy_note_for_rewrite(c, &from_obj, &to_obj);
313                 else
314                         err = copy_note(t, &from_obj, &to_obj, force,
315                                         combine_notes_overwrite);
316
317                 if (err) {
318                         error(_("failed to copy notes from '%s' to '%s'"),
319                               split[0]->buf, split[1]->buf);
320                         ret = 1;
321                 }
322
323                 strbuf_list_free(split);
324         }
325
326         if (!rewrite_cmd) {
327                 commit_notes(t, msg);
328                 free_notes(t);
329         } else {
330                 finish_copy_notes_for_rewrite(c, msg);
331         }
332         strbuf_release(&buf);
333         return ret;
334 }
335
336 static struct notes_tree *init_notes_check(const char *subcommand,
337                                            int flags)
338 {
339         struct notes_tree *t;
340         const char *ref;
341         init_notes(NULL, NULL, NULL, flags);
342         t = &default_notes_tree;
343
344         ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref;
345         if (!starts_with(ref, "refs/notes/"))
346                 /*
347                  * TRANSLATORS: the first %s will be replaced by a git
348                  * notes command: 'add', 'merge', 'remove', etc.
349                  */
350                 die(_("refusing to %s notes in %s (outside of refs/notes/)"),
351                     subcommand, ref);
352         return t;
353 }
354
355 static int list(int argc, const char **argv, const char *prefix)
356 {
357         struct notes_tree *t;
358         struct object_id object;
359         const struct object_id *note;
360         int retval = -1;
361         struct option options[] = {
362                 OPT_END()
363         };
364
365         if (argc)
366                 argc = parse_options(argc, argv, prefix, options,
367                                      git_notes_list_usage, 0);
368
369         if (1 < argc) {
370                 error(_("too many parameters"));
371                 usage_with_options(git_notes_list_usage, options);
372         }
373
374         t = init_notes_check("list", 0);
375         if (argc) {
376                 if (get_oid(argv[0], &object))
377                         die(_("failed to resolve '%s' as a valid ref."), argv[0]);
378                 note = get_note(t, &object);
379                 if (note) {
380                         puts(oid_to_hex(note));
381                         retval = 0;
382                 } else
383                         retval = error(_("no note found for object %s."),
384                                        oid_to_hex(&object));
385         } else
386                 retval = for_each_note(t, 0, list_each_note, NULL);
387
388         free_notes(t);
389         return retval;
390 }
391
392 static int append_edit(int argc, const char **argv, const char *prefix);
393
394 static int add(int argc, const char **argv, const char *prefix)
395 {
396         int force = 0, allow_empty = 0;
397         const char *object_ref;
398         struct notes_tree *t;
399         struct object_id object, new_note;
400         const struct object_id *note;
401         struct note_data d = { 0, 0, NULL, STRBUF_INIT };
402         struct option options[] = {
403                 { OPTION_CALLBACK, 'm', "message", &d, N_("message"),
404                         N_("note contents as a string"), PARSE_OPT_NONEG,
405                         parse_msg_arg},
406                 { OPTION_CALLBACK, 'F', "file", &d, N_("file"),
407                         N_("note contents in a file"), PARSE_OPT_NONEG,
408                         parse_file_arg},
409                 { OPTION_CALLBACK, 'c', "reedit-message", &d, N_("object"),
410                         N_("reuse and edit specified note object"), PARSE_OPT_NONEG,
411                         parse_reedit_arg},
412                 { OPTION_CALLBACK, 'C', "reuse-message", &d, N_("object"),
413                         N_("reuse specified note object"), PARSE_OPT_NONEG,
414                         parse_reuse_arg},
415                 OPT_BOOL(0, "allow-empty", &allow_empty,
416                         N_("allow storing empty note")),
417                 OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE),
418                 OPT_END()
419         };
420
421         argc = parse_options(argc, argv, prefix, options, git_notes_add_usage,
422                              PARSE_OPT_KEEP_ARGV0);
423
424         if (2 < argc) {
425                 error(_("too many parameters"));
426                 usage_with_options(git_notes_add_usage, options);
427         }
428
429         object_ref = argc > 1 ? argv[1] : "HEAD";
430
431         if (get_oid(object_ref, &object))
432                 die(_("failed to resolve '%s' as a valid ref."), object_ref);
433
434         t = init_notes_check("add", NOTES_INIT_WRITABLE);
435         note = get_note(t, &object);
436
437         if (note) {
438                 if (!force) {
439                         free_notes(t);
440                         if (d.given) {
441                                 free_note_data(&d);
442                                 return error(_("Cannot add notes. "
443                                         "Found existing notes for object %s. "
444                                         "Use '-f' to overwrite existing notes"),
445                                         oid_to_hex(&object));
446                         }
447                         /*
448                          * Redirect to "edit" subcommand.
449                          *
450                          * We only end up here if none of -m/-F/-c/-C or -f are
451                          * given. The original args are therefore still in
452                          * argv[0-1].
453                          */
454                         argv[0] = "edit";
455                         return append_edit(argc, argv, prefix);
456                 }
457                 fprintf(stderr, _("Overwriting existing notes for object %s\n"),
458                         oid_to_hex(&object));
459         }
460
461         prepare_note_data(&object, &d, note);
462         if (d.buf.len || allow_empty) {
463                 write_note_data(&d, &new_note);
464                 if (add_note(t, &object, &new_note, combine_notes_overwrite))
465                         BUG("combine_notes_overwrite failed");
466                 commit_notes(t, "Notes added by 'git notes add'");
467         } else {
468                 fprintf(stderr, _("Removing note for object %s\n"),
469                         oid_to_hex(&object));
470                 remove_note(t, object.hash);
471                 commit_notes(t, "Notes removed by 'git notes add'");
472         }
473
474         free_note_data(&d);
475         free_notes(t);
476         return 0;
477 }
478
479 static int copy(int argc, const char **argv, const char *prefix)
480 {
481         int retval = 0, force = 0, from_stdin = 0;
482         const struct object_id *from_note, *note;
483         const char *object_ref;
484         struct object_id object, from_obj;
485         struct notes_tree *t;
486         const char *rewrite_cmd = NULL;
487         struct option options[] = {
488                 OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE),
489                 OPT_BOOL(0, "stdin", &from_stdin, N_("read objects from stdin")),
490                 OPT_STRING(0, "for-rewrite", &rewrite_cmd, N_("command"),
491                            N_("load rewriting config for <command> (implies "
492                               "--stdin)")),
493                 OPT_END()
494         };
495
496         argc = parse_options(argc, argv, prefix, options, git_notes_copy_usage,
497                              0);
498
499         if (from_stdin || rewrite_cmd) {
500                 if (argc) {
501                         error(_("too many parameters"));
502                         usage_with_options(git_notes_copy_usage, options);
503                 } else {
504                         return notes_copy_from_stdin(force, rewrite_cmd);
505                 }
506         }
507
508         if (argc < 2) {
509                 error(_("too few parameters"));
510                 usage_with_options(git_notes_copy_usage, options);
511         }
512         if (2 < argc) {
513                 error(_("too many parameters"));
514                 usage_with_options(git_notes_copy_usage, options);
515         }
516
517         if (get_oid(argv[0], &from_obj))
518                 die(_("failed to resolve '%s' as a valid ref."), argv[0]);
519
520         object_ref = 1 < argc ? argv[1] : "HEAD";
521
522         if (get_oid(object_ref, &object))
523                 die(_("failed to resolve '%s' as a valid ref."), object_ref);
524
525         t = init_notes_check("copy", NOTES_INIT_WRITABLE);
526         note = get_note(t, &object);
527
528         if (note) {
529                 if (!force) {
530                         retval = error(_("Cannot copy notes. Found existing "
531                                        "notes for object %s. Use '-f' to "
532                                        "overwrite existing notes"),
533                                        oid_to_hex(&object));
534                         goto out;
535                 }
536                 fprintf(stderr, _("Overwriting existing notes for object %s\n"),
537                         oid_to_hex(&object));
538         }
539
540         from_note = get_note(t, &from_obj);
541         if (!from_note) {
542                 retval = error(_("missing notes on source object %s. Cannot "
543                                "copy."), oid_to_hex(&from_obj));
544                 goto out;
545         }
546
547         if (add_note(t, &object, from_note, combine_notes_overwrite))
548                 BUG("combine_notes_overwrite failed");
549         commit_notes(t, "Notes added by 'git notes copy'");
550 out:
551         free_notes(t);
552         return retval;
553 }
554
555 static int append_edit(int argc, const char **argv, const char *prefix)
556 {
557         int allow_empty = 0;
558         const char *object_ref;
559         struct notes_tree *t;
560         struct object_id object, new_note;
561         const struct object_id *note;
562         char *logmsg;
563         const char * const *usage;
564         struct note_data d = { 0, 0, NULL, STRBUF_INIT };
565         struct option options[] = {
566                 { OPTION_CALLBACK, 'm', "message", &d, N_("message"),
567                         N_("note contents as a string"), PARSE_OPT_NONEG,
568                         parse_msg_arg},
569                 { OPTION_CALLBACK, 'F', "file", &d, N_("file"),
570                         N_("note contents in a file"), PARSE_OPT_NONEG,
571                         parse_file_arg},
572                 { OPTION_CALLBACK, 'c', "reedit-message", &d, N_("object"),
573                         N_("reuse and edit specified note object"), PARSE_OPT_NONEG,
574                         parse_reedit_arg},
575                 { OPTION_CALLBACK, 'C', "reuse-message", &d, N_("object"),
576                         N_("reuse specified note object"), PARSE_OPT_NONEG,
577                         parse_reuse_arg},
578                 OPT_BOOL(0, "allow-empty", &allow_empty,
579                         N_("allow storing empty note")),
580                 OPT_END()
581         };
582         int edit = !strcmp(argv[0], "edit");
583
584         usage = edit ? git_notes_edit_usage : git_notes_append_usage;
585         argc = parse_options(argc, argv, prefix, options, usage,
586                              PARSE_OPT_KEEP_ARGV0);
587
588         if (2 < argc) {
589                 error(_("too many parameters"));
590                 usage_with_options(usage, options);
591         }
592
593         if (d.given && edit)
594                 fprintf(stderr, _("The -m/-F/-c/-C options have been deprecated "
595                         "for the 'edit' subcommand.\n"
596                         "Please use 'git notes add -f -m/-F/-c/-C' instead.\n"));
597
598         object_ref = 1 < argc ? argv[1] : "HEAD";
599
600         if (get_oid(object_ref, &object))
601                 die(_("failed to resolve '%s' as a valid ref."), object_ref);
602
603         t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
604         note = get_note(t, &object);
605
606         prepare_note_data(&object, &d, edit && note ? note : NULL);
607
608         if (note && !edit) {
609                 /* Append buf to previous note contents */
610                 unsigned long size;
611                 enum object_type type;
612                 char *prev_buf = read_object_file(note, &type, &size);
613
614                 strbuf_grow(&d.buf, size + 1);
615                 if (d.buf.len && prev_buf && size)
616                         strbuf_insert(&d.buf, 0, "\n", 1);
617                 if (prev_buf && size)
618                         strbuf_insert(&d.buf, 0, prev_buf, size);
619                 free(prev_buf);
620         }
621
622         if (d.buf.len || allow_empty) {
623                 write_note_data(&d, &new_note);
624                 if (add_note(t, &object, &new_note, combine_notes_overwrite))
625                         BUG("combine_notes_overwrite failed");
626                 logmsg = xstrfmt("Notes added by 'git notes %s'", argv[0]);
627         } else {
628                 fprintf(stderr, _("Removing note for object %s\n"),
629                         oid_to_hex(&object));
630                 remove_note(t, object.hash);
631                 logmsg = xstrfmt("Notes removed by 'git notes %s'", argv[0]);
632         }
633         commit_notes(t, logmsg);
634
635         free(logmsg);
636         free_note_data(&d);
637         free_notes(t);
638         return 0;
639 }
640
641 static int show(int argc, const char **argv, const char *prefix)
642 {
643         const char *object_ref;
644         struct notes_tree *t;
645         struct object_id object;
646         const struct object_id *note;
647         int retval;
648         struct option options[] = {
649                 OPT_END()
650         };
651
652         argc = parse_options(argc, argv, prefix, options, git_notes_show_usage,
653                              0);
654
655         if (1 < argc) {
656                 error(_("too many parameters"));
657                 usage_with_options(git_notes_show_usage, options);
658         }
659
660         object_ref = argc ? argv[0] : "HEAD";
661
662         if (get_oid(object_ref, &object))
663                 die(_("failed to resolve '%s' as a valid ref."), object_ref);
664
665         t = init_notes_check("show", 0);
666         note = get_note(t, &object);
667
668         if (!note)
669                 retval = error(_("no note found for object %s."),
670                                oid_to_hex(&object));
671         else {
672                 const char *show_args[3] = {"show", oid_to_hex(note), NULL};
673                 retval = execv_git_cmd(show_args);
674         }
675         free_notes(t);
676         return retval;
677 }
678
679 static int merge_abort(struct notes_merge_options *o)
680 {
681         int ret = 0;
682
683         /*
684          * Remove .git/NOTES_MERGE_PARTIAL and .git/NOTES_MERGE_REF, and call
685          * notes_merge_abort() to remove .git/NOTES_MERGE_WORKTREE.
686          */
687
688         if (delete_ref(NULL, "NOTES_MERGE_PARTIAL", NULL, 0))
689                 ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL"));
690         if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NO_DEREF))
691                 ret += error(_("failed to delete ref NOTES_MERGE_REF"));
692         if (notes_merge_abort(o))
693                 ret += error(_("failed to remove 'git notes merge' worktree"));
694         return ret;
695 }
696
697 static int merge_commit(struct notes_merge_options *o)
698 {
699         struct strbuf msg = STRBUF_INIT;
700         struct object_id oid, parent_oid;
701         struct notes_tree *t;
702         struct commit *partial;
703         struct pretty_print_context pretty_ctx;
704         void *local_ref_to_free;
705         int ret;
706
707         /*
708          * Read partial merge result from .git/NOTES_MERGE_PARTIAL,
709          * and target notes ref from .git/NOTES_MERGE_REF.
710          */
711
712         if (get_oid("NOTES_MERGE_PARTIAL", &oid))
713                 die(_("failed to read ref NOTES_MERGE_PARTIAL"));
714         else if (!(partial = lookup_commit_reference(&oid)))
715                 die(_("could not find commit from NOTES_MERGE_PARTIAL."));
716         else if (parse_commit(partial))
717                 die(_("could not parse commit from NOTES_MERGE_PARTIAL."));
718
719         if (partial->parents)
720                 oidcpy(&parent_oid, &partial->parents->item->object.oid);
721         else
722                 oidclr(&parent_oid);
723
724         t = xcalloc(1, sizeof(struct notes_tree));
725         init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
726
727         o->local_ref = local_ref_to_free =
728                 resolve_refdup("NOTES_MERGE_REF", 0, &oid, NULL);
729         if (!o->local_ref)
730                 die(_("failed to resolve NOTES_MERGE_REF"));
731
732         if (notes_merge_commit(o, t, partial, &oid))
733                 die(_("failed to finalize notes merge"));
734
735         /* Reuse existing commit message in reflog message */
736         memset(&pretty_ctx, 0, sizeof(pretty_ctx));
737         format_commit_message(partial, "%s", &msg, &pretty_ctx);
738         strbuf_trim(&msg);
739         strbuf_insert(&msg, 0, "notes: ", 7);
740         update_ref(msg.buf, o->local_ref, &oid,
741                    is_null_oid(&parent_oid) ? NULL : &parent_oid,
742                    0, UPDATE_REFS_DIE_ON_ERR);
743
744         free_notes(t);
745         strbuf_release(&msg);
746         ret = merge_abort(o);
747         free(local_ref_to_free);
748         return ret;
749 }
750
751 static int git_config_get_notes_strategy(const char *key,
752                                          enum notes_merge_strategy *strategy)
753 {
754         char *value;
755
756         if (git_config_get_string(key, &value))
757                 return 1;
758         if (parse_notes_merge_strategy(value, strategy))
759                 git_die_config(key, _("unknown notes merge strategy %s"), value);
760
761         free(value);
762         return 0;
763 }
764
765 static int merge(int argc, const char **argv, const char *prefix)
766 {
767         struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT;
768         struct object_id result_oid;
769         struct notes_tree *t;
770         struct notes_merge_options o;
771         int do_merge = 0, do_commit = 0, do_abort = 0;
772         int verbosity = 0, result;
773         const char *strategy = NULL;
774         struct option options[] = {
775                 OPT_GROUP(N_("General options")),
776                 OPT__VERBOSITY(&verbosity),
777                 OPT_GROUP(N_("Merge options")),
778                 OPT_STRING('s', "strategy", &strategy, N_("strategy"),
779                            N_("resolve notes conflicts using the given strategy "
780                               "(manual/ours/theirs/union/cat_sort_uniq)")),
781                 OPT_GROUP(N_("Committing unmerged notes")),
782                 OPT_SET_INT_F(0, "commit", &do_commit,
783                               N_("finalize notes merge by committing unmerged notes"),
784                               1, PARSE_OPT_NONEG),
785                 OPT_GROUP(N_("Aborting notes merge resolution")),
786                 OPT_SET_INT_F(0, "abort", &do_abort,
787                               N_("abort notes merge"),
788                               1, PARSE_OPT_NONEG),
789                 OPT_END()
790         };
791
792         argc = parse_options(argc, argv, prefix, options,
793                              git_notes_merge_usage, 0);
794
795         if (strategy || do_commit + do_abort == 0)
796                 do_merge = 1;
797         if (do_merge + do_commit + do_abort != 1) {
798                 error(_("cannot mix --commit, --abort or -s/--strategy"));
799                 usage_with_options(git_notes_merge_usage, options);
800         }
801
802         if (do_merge && argc != 1) {
803                 error(_("must specify a notes ref to merge"));
804                 usage_with_options(git_notes_merge_usage, options);
805         } else if (!do_merge && argc) {
806                 error(_("too many parameters"));
807                 usage_with_options(git_notes_merge_usage, options);
808         }
809
810         init_notes_merge_options(&o);
811         o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT;
812
813         if (do_abort)
814                 return merge_abort(&o);
815         if (do_commit)
816                 return merge_commit(&o);
817
818         o.local_ref = default_notes_ref();
819         strbuf_addstr(&remote_ref, argv[0]);
820         expand_loose_notes_ref(&remote_ref);
821         o.remote_ref = remote_ref.buf;
822
823         t = init_notes_check("merge", NOTES_INIT_WRITABLE);
824
825         if (strategy) {
826                 if (parse_notes_merge_strategy(strategy, &o.strategy)) {
827                         error(_("unknown -s/--strategy: %s"), strategy);
828                         usage_with_options(git_notes_merge_usage, options);
829                 }
830         } else {
831                 struct strbuf merge_key = STRBUF_INIT;
832                 const char *short_ref = NULL;
833
834                 if (!skip_prefix(o.local_ref, "refs/notes/", &short_ref))
835                         BUG("local ref %s is outside of refs/notes/",
836                             o.local_ref);
837
838                 strbuf_addf(&merge_key, "notes.%s.mergeStrategy", short_ref);
839
840                 if (git_config_get_notes_strategy(merge_key.buf, &o.strategy))
841                         git_config_get_notes_strategy("notes.mergeStrategy", &o.strategy);
842
843                 strbuf_release(&merge_key);
844         }
845
846         strbuf_addf(&msg, "notes: Merged notes from %s into %s",
847                     remote_ref.buf, default_notes_ref());
848         strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */
849
850         result = notes_merge(&o, t, &result_oid);
851
852         if (result >= 0) /* Merge resulted (trivially) in result_oid */
853                 /* Update default notes ref with new commit */
854                 update_ref(msg.buf, default_notes_ref(), &result_oid, NULL, 0,
855                            UPDATE_REFS_DIE_ON_ERR);
856         else { /* Merge has unresolved conflicts */
857                 const struct worktree *wt;
858                 /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
859                 update_ref(msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL,
860                            0, UPDATE_REFS_DIE_ON_ERR);
861                 /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
862                 wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
863                 if (wt)
864                         die(_("a notes merge into %s is already in-progress at %s"),
865                             default_notes_ref(), wt->path);
866                 if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
867                         die(_("failed to store link to current notes ref (%s)"),
868                             default_notes_ref());
869                 fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s "
870                                   "and commit the result with 'git notes merge --commit', "
871                                   "or abort the merge with 'git notes merge --abort'.\n"),
872                         git_path(NOTES_MERGE_WORKTREE));
873         }
874
875         free_notes(t);
876         strbuf_release(&remote_ref);
877         strbuf_release(&msg);
878         return result < 0; /* return non-zero on conflicts */
879 }
880
881 #define IGNORE_MISSING 1
882
883 static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag)
884 {
885         int status;
886         struct object_id oid;
887         if (get_oid(name, &oid))
888                 return error(_("Failed to resolve '%s' as a valid ref."), name);
889         status = remove_note(t, oid.hash);
890         if (status)
891                 fprintf(stderr, _("Object %s has no note\n"), name);
892         else
893                 fprintf(stderr, _("Removing note for object %s\n"), name);
894         return (flag & IGNORE_MISSING) ? 0 : status;
895 }
896
897 static int remove_cmd(int argc, const char **argv, const char *prefix)
898 {
899         unsigned flag = 0;
900         int from_stdin = 0;
901         struct option options[] = {
902                 OPT_BIT(0, "ignore-missing", &flag,
903                         N_("attempt to remove non-existent note is not an error"),
904                         IGNORE_MISSING),
905                 OPT_BOOL(0, "stdin", &from_stdin,
906                             N_("read object names from the standard input")),
907                 OPT_END()
908         };
909         struct notes_tree *t;
910         int retval = 0;
911
912         argc = parse_options(argc, argv, prefix, options,
913                              git_notes_remove_usage, 0);
914
915         t = init_notes_check("remove", NOTES_INIT_WRITABLE);
916
917         if (!argc && !from_stdin) {
918                 retval = remove_one_note(t, "HEAD", flag);
919         } else {
920                 while (*argv) {
921                         retval |= remove_one_note(t, *argv, flag);
922                         argv++;
923                 }
924         }
925         if (from_stdin) {
926                 struct strbuf sb = STRBUF_INIT;
927                 while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
928                         strbuf_rtrim(&sb);
929                         retval |= remove_one_note(t, sb.buf, flag);
930                 }
931                 strbuf_release(&sb);
932         }
933         if (!retval)
934                 commit_notes(t, "Notes removed by 'git notes remove'");
935         free_notes(t);
936         return retval;
937 }
938
939 static int prune(int argc, const char **argv, const char *prefix)
940 {
941         struct notes_tree *t;
942         int show_only = 0, verbose = 0;
943         struct option options[] = {
944                 OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
945                 OPT__VERBOSE(&verbose, N_("report pruned notes")),
946                 OPT_END()
947         };
948
949         argc = parse_options(argc, argv, prefix, options, git_notes_prune_usage,
950                              0);
951
952         if (argc) {
953                 error(_("too many parameters"));
954                 usage_with_options(git_notes_prune_usage, options);
955         }
956
957         t = init_notes_check("prune", NOTES_INIT_WRITABLE);
958
959         prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) |
960                 (show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) );
961         if (!show_only)
962                 commit_notes(t, "Notes removed by 'git notes prune'");
963         free_notes(t);
964         return 0;
965 }
966
967 static int get_ref(int argc, const char **argv, const char *prefix)
968 {
969         struct option options[] = { OPT_END() };
970         argc = parse_options(argc, argv, prefix, options,
971                              git_notes_get_ref_usage, 0);
972
973         if (argc) {
974                 error(_("too many parameters"));
975                 usage_with_options(git_notes_get_ref_usage, options);
976         }
977
978         puts(default_notes_ref());
979         return 0;
980 }
981
982 int cmd_notes(int argc, const char **argv, const char *prefix)
983 {
984         int result;
985         const char *override_notes_ref = NULL;
986         struct option options[] = {
987                 OPT_STRING(0, "ref", &override_notes_ref, N_("notes-ref"),
988                            N_("use notes from <notes-ref>")),
989                 OPT_END()
990         };
991
992         git_config(git_default_config, NULL);
993         argc = parse_options(argc, argv, prefix, options, git_notes_usage,
994                              PARSE_OPT_STOP_AT_NON_OPTION);
995
996         if (override_notes_ref) {
997                 struct strbuf sb = STRBUF_INIT;
998                 strbuf_addstr(&sb, override_notes_ref);
999                 expand_notes_ref(&sb);
1000                 setenv("GIT_NOTES_REF", sb.buf, 1);
1001                 strbuf_release(&sb);
1002         }
1003
1004         if (argc < 1 || !strcmp(argv[0], "list"))
1005                 result = list(argc, argv, prefix);
1006         else if (!strcmp(argv[0], "add"))
1007                 result = add(argc, argv, prefix);
1008         else if (!strcmp(argv[0], "copy"))
1009                 result = copy(argc, argv, prefix);
1010         else if (!strcmp(argv[0], "append") || !strcmp(argv[0], "edit"))
1011                 result = append_edit(argc, argv, prefix);
1012         else if (!strcmp(argv[0], "show"))
1013                 result = show(argc, argv, prefix);
1014         else if (!strcmp(argv[0], "merge"))
1015                 result = merge(argc, argv, prefix);
1016         else if (!strcmp(argv[0], "remove"))
1017                 result = remove_cmd(argc, argv, prefix);
1018         else if (!strcmp(argv[0], "prune"))
1019                 result = prune(argc, argv, prefix);
1020         else if (!strcmp(argv[0], "get-ref"))
1021                 result = get_ref(argc, argv, prefix);
1022         else {
1023                 result = error(_("unknown subcommand: %s"), argv[0]);
1024                 usage_with_options(git_notes_usage, options);
1025         }
1026
1027         return result ? 1 : 0;
1028 }