void init_display_notes(struct display_notes_opt *opt) { char *display_ref_env; int load_config_refs = 0; display_notes_refs.strdup_strings = 1; assert(!display_notes_trees); if (!opt || opt->use_default_notes > 0 || (opt->use_default_notes == -1 && !opt->extra_notes_refs.nr)) { string_list_append(&display_notes_refs, default_notes_ref()); display_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT); if (display_ref_env) { string_list_add_refs_from_colon_sep(&display_notes_refs, display_ref_env); load_config_refs = 0; } else load_config_refs = 1; } git_config(notes_display_config, &load_config_refs); if (opt) { struct string_list_item *item; for_each_string_list_item(item, &opt->extra_notes_refs) string_list_add_refs_by_glob(&display_notes_refs, item->string); } display_notes_trees = load_notes_trees(&display_notes_refs, 0); string_list_clear(&display_notes_refs, 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; }
void init_notes(struct notes_tree *t, const char *notes_ref, combine_notes_fn combine_notes, int flags) { struct object_id oid, object_oid; unsigned mode; struct leaf_node root_tree; if (!t) t = &default_notes_tree; assert(!t->initialized); if (!notes_ref) notes_ref = default_notes_ref(); if (!combine_notes) combine_notes = combine_notes_concatenate; t->root = (struct int_node *) xcalloc(1, sizeof(struct int_node)); t->first_non_note = NULL; t->prev_non_note = NULL; t->ref = xstrdup_or_null(notes_ref); t->update_ref = (flags & NOTES_INIT_WRITABLE) ? t->ref : NULL; t->combine_notes = combine_notes; t->initialized = 1; t->dirty = 0; if (flags & NOTES_INIT_EMPTY || !notes_ref || get_oid_treeish(notes_ref, &object_oid)) return; if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, &object_oid)) die("Cannot use notes ref %s", notes_ref); if (get_tree_entry(&object_oid, "", &oid, &mode)) die("Failed to read notes tree referenced by %s (%s)", notes_ref, oid_to_hex(&object_oid)); oidclr(&root_tree.key_oid); oidcpy(&root_tree.val_oid, &oid); load_subtree(t, &root_tree, t->root, 0); }
void init_notes(struct notes_tree *t, const char *notes_ref, combine_notes_fn combine_notes, int flags) { unsigned char sha1[20], object_sha1[20]; unsigned mode; struct leaf_node root_tree; if (!t) t = &default_notes_tree; assert(!t->initialized); if (!notes_ref) notes_ref = default_notes_ref(); if (!combine_notes) combine_notes = combine_notes_concatenate; t->root = (struct int_node *) xcalloc(1, sizeof(struct int_node)); t->first_non_note = NULL; t->prev_non_note = NULL; t->ref = xstrdup_or_null(notes_ref); t->combine_notes = combine_notes; t->initialized = 1; t->dirty = 0; if (flags & NOTES_INIT_EMPTY || !notes_ref || read_ref(notes_ref, object_sha1)) return; if (get_tree_entry(object_sha1, "", sha1, &mode)) die("Failed to read notes tree referenced by %s (%s)", notes_ref, sha1_to_hex(object_sha1)); hashclr(root_tree.key_sha1); hashcpy(root_tree.val_sha1, sha1); load_subtree(t, &root_tree, t->root, 0); }
static int merge(int argc, const char **argv, const char *prefix) { struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT; unsigned char result_sha1[20]; struct notes_tree *t; struct notes_merge_options o; int do_merge = 0, do_commit = 0, do_abort = 0; int verbosity = 0, result; const char *strategy = NULL; struct option options[] = { OPT_GROUP(N_("General options")), OPT__VERBOSITY(&verbosity), OPT_GROUP(N_("Merge options")), OPT_STRING('s', "strategy", &strategy, N_("strategy"), N_("resolve notes conflicts using the given strategy " "(manual/ours/theirs/union/cat_sort_uniq)")), OPT_GROUP(N_("Committing unmerged notes")), { OPTION_SET_INT, 0, "commit", &do_commit, NULL, N_("finalize notes merge by committing unmerged notes"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1}, OPT_GROUP(N_("Aborting notes merge resolution")), { OPTION_SET_INT, 0, "abort", &do_abort, NULL, N_("abort notes merge"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1}, OPT_END() }; argc = parse_options(argc, argv, prefix, options, git_notes_merge_usage, 0); if (strategy || do_commit + do_abort == 0) do_merge = 1; if (do_merge + do_commit + do_abort != 1) { error("cannot mix --commit, --abort or -s/--strategy"); usage_with_options(git_notes_merge_usage, options); } if (do_merge && argc != 1) { error("Must specify a notes ref to merge"); usage_with_options(git_notes_merge_usage, options); } else if (!do_merge && argc) { error("too many parameters"); usage_with_options(git_notes_merge_usage, options); } init_notes_merge_options(&o); o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT; if (do_abort) return merge_abort(&o); if (do_commit) return merge_commit(&o); o.local_ref = default_notes_ref(); strbuf_addstr(&remote_ref, argv[0]); expand_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; t = init_notes_check("merge"); if (strategy) { if (parse_notes_merge_strategy(strategy, &o.strategy)) { error("Unknown -s/--strategy: %s", strategy); usage_with_options(git_notes_merge_usage, options); } } else { struct strbuf merge_key = STRBUF_INIT; const char *short_ref = NULL; if (!skip_prefix(o.local_ref, "refs/notes/", &short_ref)) die("BUG: local ref %s is outside of refs/notes/", o.local_ref); strbuf_addf(&merge_key, "notes.%s.mergeStrategy", short_ref); if (git_config_get_notes_strategy(merge_key.buf, &o.strategy)) git_config_get_notes_strategy("notes.mergeStrategy", &o.strategy); strbuf_release(&merge_key); } strbuf_addf(&msg, "notes: Merged notes from %s into %s", remote_ref.buf, default_notes_ref()); strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */ result = notes_merge(&o, t, result_sha1); if (result >= 0) /* Merge resulted (trivially) in result_sha1 */ /* Update default notes ref with new commit */ update_ref(msg.buf, default_notes_ref(), result_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); else { /* Merge has unresolved conflicts */ char *existing; /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ existing = find_shared_symref("NOTES_MERGE_REF", default_notes_ref()); if (existing) die(_("A notes merge into %s is already in-progress at %s"), default_notes_ref(), existing); if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) die("Failed to store link to current notes ref (%s)", default_notes_ref()); printf("Automatic notes merge failed. Fix conflicts in %s and " "commit the result with 'git notes merge --commit', or " "abort the merge with 'git notes merge --abort'.\n", git_path(NOTES_MERGE_WORKTREE)); } free_notes(t); strbuf_release(&remote_ref); strbuf_release(&msg); return result < 0; /* return non-zero on conflicts */ }
static int merge(int argc, const char **argv, const char *prefix) { struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT; unsigned char result_sha1[20]; struct notes_tree *t; struct notes_merge_options o; int do_merge = 0, do_commit = 0, do_abort = 0; int verbosity = 0, result; const char *strategy = NULL; struct option options[] = { OPT_GROUP("General options"), OPT__VERBOSITY(&verbosity), OPT_GROUP("Merge options"), OPT_STRING('s', "strategy", &strategy, "strategy", "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", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, OPT_GROUP("Aborting notes merge resolution"), { OPTION_BOOLEAN, 0, "abort", &do_abort, NULL, "abort notes merge", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, OPT_END() }; argc = parse_options(argc, argv, prefix, options, git_notes_merge_usage, 0); if (strategy || do_commit + do_abort == 0) do_merge = 1; if (do_merge + do_commit + do_abort != 1) { error("cannot mix --commit, --abort or -s/--strategy"); usage_with_options(git_notes_merge_usage, options); } if (do_merge && argc != 1) { error("Must specify a notes ref to merge"); usage_with_options(git_notes_merge_usage, options); } else if (!do_merge && argc) { error("too many parameters"); usage_with_options(git_notes_merge_usage, options); } init_notes_merge_options(&o); o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT; if (do_abort) return merge_abort(&o); if (do_commit) return merge_commit(&o); o.local_ref = default_notes_ref(); strbuf_addstr(&remote_ref, argv[0]); expand_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; if (strategy) { if (!strcmp(strategy, "manual")) o.strategy = NOTES_MERGE_RESOLVE_MANUAL; else if (!strcmp(strategy, "ours")) o.strategy = NOTES_MERGE_RESOLVE_OURS; else if (!strcmp(strategy, "theirs")) 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); } } t = init_notes_check("merge"); strbuf_addf(&msg, "notes: Merged notes from %s into %s", remote_ref.buf, default_notes_ref()); strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */ result = notes_merge(&o, t, result_sha1); if (result >= 0) /* Merge resulted (trivially) in result_sha1 */ /* Update default notes ref with new commit */ update_ref(msg.buf, default_notes_ref(), result_sha1, NULL, 0, DIE_ON_ERR); else { /* Merge has unresolved conflicts */ /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL, 0, DIE_ON_ERR); /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) die("Failed to store link to current notes ref (%s)", default_notes_ref()); printf("Automatic notes merge failed. Fix conflicts in %s and " "commit the result with 'git notes merge --commit', or " "abort the merge with 'git notes merge --abort'.\n", git_path(NOTES_MERGE_WORKTREE)); } free_notes(t); strbuf_release(&remote_ref); strbuf_release(&msg); return result < 0; /* return non-zero on conflicts */ }