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