Code

Merge branch 'ks/blame-worktree-textconv-cached'
[git.git] / builtin / notes.c
index b5385238eada5b05351c3587483f92824f7ca68d..4d5556e2cb5bccaf0100d9f5019e1a1c493e35e7 100644 (file)
@@ -31,6 +31,7 @@ static const char * const git_notes_usage[] = {
        "git notes merge --abort [-v | -q]",
        "git notes [--ref <notes_ref>] remove [<object>]",
        "git notes [--ref <notes_ref>] prune [-n | -v]",
+       "git notes [--ref <notes_ref>] get-ref",
        NULL
 };
 
@@ -82,6 +83,11 @@ static const char * const git_notes_prune_usage[] = {
        NULL
 };
 
+static const char * const git_notes_get_ref_usage[] = {
+       "git notes get-ref",
+       NULL
+};
+
 static const char note_template[] =
        "\n"
        "#\n"
@@ -324,6 +330,8 @@ combine_notes_fn parse_combine_notes_fn(const char *v)
                return combine_notes_ignore;
        else if (!strcasecmp(v, "concatenate"))
                return combine_notes_concatenate;
+       else if (!strcasecmp(v, "cat_sort_uniq"))
+               return combine_notes_cat_sort_uniq;
        else
                return NULL;
 }
@@ -541,7 +549,7 @@ static int add(int argc, const char **argv, const char *prefix)
                { OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
                        "reuse specified note object", PARSE_OPT_NONEG,
                        parse_reuse_arg},
-               OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
+               OPT__FORCE(&force, "replace existing notes"),
                OPT_END()
        };
 
@@ -597,7 +605,7 @@ static int copy(int argc, const char **argv, const char *prefix)
        struct notes_tree *t;
        const char *rewrite_cmd = NULL;
        struct option options[] = {
-               OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
+               OPT__FORCE(&force, "replace existing notes"),
                OPT_BOOLEAN(0, "stdin", &from_stdin, "read objects from stdin"),
                OPT_STRING(0, "for-rewrite", &rewrite_cmd, "command",
                           "load rewriting config for <command> (implies "
@@ -786,7 +794,7 @@ static int merge_abort(struct notes_merge_options *o)
 static int merge_commit(struct notes_merge_options *o)
 {
        struct strbuf msg = STRBUF_INIT;
-       unsigned char sha1[20];
+       unsigned char sha1[20], parent_sha1[20];
        struct notes_tree *t;
        struct commit *partial;
        struct pretty_print_context pretty_ctx;
@@ -803,6 +811,11 @@ static int merge_commit(struct notes_merge_options *o)
        else if (parse_commit(partial))
                die("Could not parse commit from NOTES_MERGE_PARTIAL.");
 
+       if (partial->parents)
+               hashcpy(parent_sha1, partial->parents->item->object.sha1);
+       else
+               hashclr(parent_sha1);
+
        t = xcalloc(1, sizeof(struct notes_tree));
        init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
 
@@ -818,7 +831,9 @@ static int merge_commit(struct notes_merge_options *o)
        format_commit_message(partial, "%s", &msg, &pretty_ctx);
        strbuf_trim(&msg);
        strbuf_insert(&msg, 0, "notes: ", 7);
-       update_ref(msg.buf, o->local_ref, sha1, NULL, 0, DIE_ON_ERR);
+       update_ref(msg.buf, o->local_ref, sha1,
+                  is_null_sha1(parent_sha1) ? NULL : parent_sha1,
+                  0, DIE_ON_ERR);
 
        free_notes(t);
        strbuf_release(&msg);
@@ -839,8 +854,8 @@ static int merge(int argc, const char **argv, const char *prefix)
                OPT__VERBOSITY(&verbosity),
                OPT_GROUP("Merge options"),
                OPT_STRING('s', "strategy", &strategy, "strategy",
-                          "resolve notes conflicts using the given "
-                          "strategy (manual/ours/theirs/union)"),
+                          "resolve notes conflicts using the given strategy "
+                          "(manual/ours/theirs/union/cat_sort_uniq)"),
                OPT_GROUP("Committing unmerged notes"),
                { OPTION_BOOLEAN, 0, "commit", &do_commit, NULL,
                        "finalize notes merge by committing unmerged notes",
@@ -892,6 +907,8 @@ static int merge(int argc, const char **argv, const char *prefix)
                        o.strategy = NOTES_MERGE_RESOLVE_THEIRS;
                else if (!strcmp(strategy, "union"))
                        o.strategy = NOTES_MERGE_RESOLVE_UNION;
+               else if (!strcmp(strategy, "cat_sort_uniq"))
+                       o.strategy = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ;
                else {
                        error("Unknown -s/--strategy: %s", strategy);
                        usage_with_options(git_notes_merge_usage, options);
@@ -902,7 +919,7 @@ static int merge(int argc, const char **argv, const char *prefix)
 
        strbuf_addf(&msg, "notes: Merged notes from %s into %s",
                    remote_ref.buf, default_notes_ref());
-       o.commit_msg = msg.buf + 7; // skip "notes: " prefix
+       strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */
 
        result = notes_merge(&o, t, result_sha1);
 
@@ -938,6 +955,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
        const char *object_ref;
        struct notes_tree *t;
        unsigned char object[20];
+       int retval;
 
        argc = parse_options(argc, argv, prefix, options,
                             git_notes_remove_usage, 0);
@@ -954,12 +972,17 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
 
        t = init_notes_check("remove");
 
-       fprintf(stderr, "Removing note for object %s\n", sha1_to_hex(object));
-       remove_note(t, object);
+       retval = remove_note(t, object);
+       if (retval)
+               fprintf(stderr, "Object %s has no note\n", sha1_to_hex(object));
+       else {
+               fprintf(stderr, "Removing note for object %s\n",
+                       sha1_to_hex(object));
 
-       commit_notes(t, "Notes removed by 'git notes remove'");
+               commit_notes(t, "Notes removed by 'git notes remove'");
+       }
        free_notes(t);
-       return 0;
+       return retval;
 }
 
 static int prune(int argc, const char **argv, const char *prefix)
@@ -967,9 +990,8 @@ static int prune(int argc, const char **argv, const char *prefix)
        struct notes_tree *t;
        int show_only = 0, verbose = 0;
        struct option options[] = {
-               OPT_BOOLEAN('n', "dry-run", &show_only,
-                           "do not remove, show only"),
-               OPT_BOOLEAN('v', "verbose", &verbose, "report pruned notes"),
+               OPT__DRY_RUN(&show_only, "do not remove, show only"),
+               OPT__VERBOSE(&verbose, "report pruned notes"),
                OPT_END()
        };
 
@@ -991,6 +1013,21 @@ static int prune(int argc, const char **argv, const char *prefix)
        return 0;
 }
 
+static int get_ref(int argc, const char **argv, const char *prefix)
+{
+       struct option options[] = { OPT_END() };
+       argc = parse_options(argc, argv, prefix, options,
+                            git_notes_get_ref_usage, 0);
+
+       if (argc) {
+               error("too many parameters");
+               usage_with_options(git_notes_get_ref_usage, options);
+       }
+
+       puts(default_notes_ref());
+       return 0;
+}
+
 int cmd_notes(int argc, const char **argv, const char *prefix)
 {
        int result;
@@ -1029,6 +1066,8 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
                result = remove_cmd(argc, argv, prefix);
        else if (!strcmp(argv[0], "prune"))
                result = prune(argc, argv, prefix);
+       else if (!strcmp(argv[0], "get-ref"))
+               result = get_ref(argc, argv, prefix);
        else {
                result = error("Unknown subcommand: %s", argv[0]);
                usage_with_options(git_notes_usage, options);