git
/
notes-utils.c
200 строк · 5.4 Кб
1#define USE_THE_REPOSITORY_VARIABLE2
3#include "git-compat-util.h"4#include "config.h"5#include "commit.h"6#include "environment.h"7#include "gettext.h"8#include "refs.h"9#include "notes-utils.h"10#include "strbuf.h"11
12void create_notes_commit(struct repository *r,13struct notes_tree *t,14const struct commit_list *parents,15const char *msg, size_t msg_len,16struct object_id *result_oid)17{
18struct commit_list *parents_to_free = NULL;19struct object_id tree_oid;20
21assert(t->initialized);22
23if (write_notes_tree(t, &tree_oid))24die("Failed to write notes tree to database");25
26if (!parents) {27/* Deduce parent commit from t->ref */28struct object_id parent_oid;29if (!refs_read_ref(get_main_ref_store(the_repository), t->ref, &parent_oid)) {30struct commit *parent = lookup_commit(r, &parent_oid);31if (repo_parse_commit(r, parent))32die("Failed to find/parse commit %s", t->ref);33commit_list_insert(parent, &parents_to_free);34parents = parents_to_free;35}36/* else: t->ref points to nothing, assume root/orphan commit */37}38
39if (commit_tree(msg, msg_len, &tree_oid, parents, result_oid, NULL,40NULL))41die("Failed to commit notes tree to database");42
43free_commit_list(parents_to_free);44}
45
46void commit_notes(struct repository *r, struct notes_tree *t, const char *msg)47{
48struct strbuf buf = STRBUF_INIT;49struct object_id commit_oid;50
51if (!t)52t = &default_notes_tree;53if (!t->initialized || !t->update_ref || !*t->update_ref)54die(_("Cannot commit uninitialized/unreferenced notes tree"));55if (!t->dirty)56return; /* don't have to commit an unchanged tree */57
58/* Prepare commit message and reflog message */59strbuf_addstr(&buf, msg);60strbuf_complete_line(&buf);61
62create_notes_commit(r, t, NULL, buf.buf, buf.len, &commit_oid);63strbuf_insertstr(&buf, 0, "notes: ");64refs_update_ref(get_main_ref_store(the_repository), buf.buf,65t->update_ref, &commit_oid, NULL, 0,66UPDATE_REFS_DIE_ON_ERR);67
68strbuf_release(&buf);69}
70
71int parse_notes_merge_strategy(const char *v, enum notes_merge_strategy *s)72{
73if (!strcmp(v, "manual"))74*s = NOTES_MERGE_RESOLVE_MANUAL;75else if (!strcmp(v, "ours"))76*s = NOTES_MERGE_RESOLVE_OURS;77else if (!strcmp(v, "theirs"))78*s = NOTES_MERGE_RESOLVE_THEIRS;79else if (!strcmp(v, "union"))80*s = NOTES_MERGE_RESOLVE_UNION;81else if (!strcmp(v, "cat_sort_uniq"))82*s = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ;83else84return -1;85
86return 0;87}
88
89static combine_notes_fn parse_combine_notes_fn(const char *v)90{
91if (!strcasecmp(v, "overwrite"))92return combine_notes_overwrite;93else if (!strcasecmp(v, "ignore"))94return combine_notes_ignore;95else if (!strcasecmp(v, "concatenate"))96return combine_notes_concatenate;97else if (!strcasecmp(v, "cat_sort_uniq"))98return combine_notes_cat_sort_uniq;99else100return NULL;101}
102
103static int notes_rewrite_config(const char *k, const char *v,104const struct config_context *ctx UNUSED,105void *cb)106{
107struct notes_rewrite_cfg *c = cb;108if (starts_with(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {109c->enabled = git_config_bool(k, v);110return 0;111} else if (!c->mode_from_env && !strcmp(k, "notes.rewritemode")) {112if (!v)113return config_error_nonbool(k);114c->combine = parse_combine_notes_fn(v);115if (!c->combine) {116error(_("Bad notes.rewriteMode value: '%s'"), v);117return 1;118}119return 0;120} else if (!c->refs_from_env && !strcmp(k, "notes.rewriteref")) {121if (!v)122return config_error_nonbool(k);123/* note that a refs/ prefix is implied in the124* underlying for_each_glob_ref */
125if (starts_with(v, "refs/notes/"))126string_list_add_refs_by_glob(c->refs, v);127else128warning(_("Refusing to rewrite notes in %s"129" (outside of refs/notes/)"), v);130return 0;131}132
133return 0;134}
135
136
137struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)138{
139struct notes_rewrite_cfg *c = xmalloc(sizeof(struct notes_rewrite_cfg));140const char *rewrite_mode_env = getenv(GIT_NOTES_REWRITE_MODE_ENVIRONMENT);141const char *rewrite_refs_env = getenv(GIT_NOTES_REWRITE_REF_ENVIRONMENT);142c->cmd = cmd;143c->enabled = 1;144c->combine = combine_notes_concatenate;145CALLOC_ARRAY(c->refs, 1);146c->refs->strdup_strings = 1;147c->refs_from_env = 0;148c->mode_from_env = 0;149if (rewrite_mode_env) {150c->mode_from_env = 1;151c->combine = parse_combine_notes_fn(rewrite_mode_env);152if (!c->combine)153/*154* TRANSLATORS: The first %s is the name of
155* the environment variable, the second %s is
156* its value.
157*/
158error(_("Bad %s value: '%s'"), GIT_NOTES_REWRITE_MODE_ENVIRONMENT,159rewrite_mode_env);160}161if (rewrite_refs_env) {162c->refs_from_env = 1;163string_list_add_refs_from_colon_sep(c->refs, rewrite_refs_env);164}165git_config(notes_rewrite_config, c);166if (!c->enabled || !c->refs->nr) {167string_list_clear(c->refs, 0);168free(c->refs);169free(c);170return NULL;171}172c->trees = load_notes_trees(c->refs, NOTES_INIT_WRITABLE);173string_list_clear(c->refs, 0);174free(c->refs);175return c;176}
177
178int copy_note_for_rewrite(struct notes_rewrite_cfg *c,179const struct object_id *from_obj, const struct object_id *to_obj)180{
181int ret = 0;182int i;183for (i = 0; c->trees[i]; i++)184ret = copy_note(c->trees[i], from_obj, to_obj, 1, c->combine) || ret;185return ret;186}
187
188void finish_copy_notes_for_rewrite(struct repository *r,189struct notes_rewrite_cfg *c,190const char *msg)191{
192int i;193for (i = 0; c->trees[i]; i++) {194commit_notes(r, c->trees[i], msg);195free_notes(c->trees[i]);196free(c->trees[i]);197}198free(c->trees);199free(c);200}
201