diff options
author | Thomas Rast <trast@student.ethz.ch> | 2010-03-12 18:04:32 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2010-03-12 21:55:39 -0800 |
commit | 6956f858f6237d426fa422949033e3c558104802 (patch) | |
tree | 3b01ce43e51c2cd319db79446568116bbc2a8630 /builtin-notes.c | |
parent | notes: implement 'git notes copy --stdin' (diff) | |
download | tgif-6956f858f6237d426fa422949033e3c558104802.tar.xz |
notes: implement helpers needed for note copying during rewrite
Implement helper functions to load the rewriting config, and to
actually copy the notes. Also document the config.
Secondly, also implement an undocumented --for-rewrite=<cmd> option to
'git notes copy' which is used like --stdin, but also puts the
configuration for <cmd> into effect. It will be needed to support the
copying in git-rebase.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Acked-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin-notes.c')
-rw-r--r-- | builtin-notes.c | 139 |
1 files changed, 131 insertions, 8 deletions
diff --git a/builtin-notes.c b/builtin-notes.c index daeb14e1d9..026cfd32a8 100644 --- a/builtin-notes.c +++ b/builtin-notes.c @@ -16,6 +16,7 @@ #include "exec_cmd.h" #include "run-command.h" #include "parse-options.h" +#include "string-list.h" static const char * const git_notes_usage[] = { "git notes [list [<object>]]", @@ -278,14 +279,121 @@ int commit_notes(struct notes_tree *t, const char *msg) return 0; } -int notes_copy_from_stdin(int force) + +combine_notes_fn *parse_combine_notes_fn(const char *v) +{ + if (!strcasecmp(v, "overwrite")) + return combine_notes_overwrite; + else if (!strcasecmp(v, "ignore")) + return combine_notes_ignore; + else if (!strcasecmp(v, "concatenate")) + return combine_notes_concatenate; + else + return NULL; +} + +static int notes_rewrite_config(const char *k, const char *v, void *cb) +{ + struct notes_rewrite_cfg *c = cb; + if (!prefixcmp(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) { + c->enabled = git_config_bool(k, v); + return 0; + } else if (!c->mode_from_env && !strcmp(k, "notes.rewritemode")) { + if (!v) + config_error_nonbool(k); + c->combine = parse_combine_notes_fn(v); + if (!c->combine) { + error("Bad notes.rewriteMode value: '%s'", v); + return 1; + } + return 0; + } else if (!c->refs_from_env && !strcmp(k, "notes.rewriteref")) { + /* note that a refs/ prefix is implied in the + * underlying for_each_glob_ref */ + if (!prefixcmp(v, "refs/notes/")) + string_list_add_refs_by_glob(c->refs, v); + else + warning("Refusing to rewrite notes in %s" + " (outside of refs/notes/)", v); + return 0; + } + + return 0; +} + + +struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd) +{ + struct notes_rewrite_cfg *c = xmalloc(sizeof(struct notes_rewrite_cfg)); + const char *rewrite_mode_env = getenv(GIT_NOTES_REWRITE_MODE_ENVIRONMENT); + const char *rewrite_refs_env = getenv(GIT_NOTES_REWRITE_REF_ENVIRONMENT); + c->cmd = cmd; + c->enabled = 1; + c->combine = combine_notes_concatenate; + c->refs = xcalloc(1, sizeof(struct string_list)); + c->refs->strdup_strings = 1; + c->refs_from_env = 0; + c->mode_from_env = 0; + if (rewrite_mode_env) { + c->mode_from_env = 1; + c->combine = parse_combine_notes_fn(rewrite_mode_env); + if (!c->combine) + error("Bad " GIT_NOTES_REWRITE_MODE_ENVIRONMENT + " value: '%s'", rewrite_mode_env); + } + if (rewrite_refs_env) { + c->refs_from_env = 1; + string_list_add_refs_from_colon_sep(c->refs, rewrite_refs_env); + } + git_config(notes_rewrite_config, c); + if (!c->enabled || !c->refs->nr) { + string_list_clear(c->refs, 0); + free(c->refs); + free(c); + return NULL; + } + c->trees = load_notes_trees(c->refs); + string_list_clear(c->refs, 0); + free(c->refs); + return c; +} + +int copy_note_for_rewrite(struct notes_rewrite_cfg *c, + const unsigned char *from_obj, const unsigned char *to_obj) +{ + int ret = 0; + int i; + for (i = 0; c->trees[i]; i++) + ret = copy_note(c->trees[i], from_obj, to_obj, 1, c->combine) || ret; + return ret; +} + +void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c) +{ + int i; + for (i = 0; c->trees[i]; i++) { + commit_notes(c->trees[i], "Notes added by 'git notes copy'"); + free_notes(c->trees[i]); + } + free(c->trees); + free(c); +} + +int notes_copy_from_stdin(int force, const char *rewrite_cmd) { struct strbuf buf = STRBUF_INIT; + struct notes_rewrite_cfg *c = NULL; struct notes_tree *t; int ret = 0; - init_notes(NULL, NULL, NULL, 0); - t = &default_notes_tree; + if (rewrite_cmd) { + c = init_copy_notes_for_rewrite(rewrite_cmd); + if (!c) + return 0; + } else { + init_notes(NULL, NULL, NULL, 0); + t = &default_notes_tree; + } while (strbuf_getline(&buf, stdin, '\n') != EOF) { unsigned char from_obj[20], to_obj[20]; @@ -302,7 +410,11 @@ int notes_copy_from_stdin(int force) if (get_sha1(split[1]->buf, to_obj)) die("Failed to resolve '%s' as a valid ref.", split[1]->buf); - err = copy_note(t, from_obj, to_obj, force, combine_notes_overwrite); + if (rewrite_cmd) + err = copy_note_for_rewrite(c, from_obj, to_obj); + else + err = copy_note(t, from_obj, to_obj, force, + combine_notes_overwrite); if (err) { error("Failed to copy notes from '%s' to '%s'", @@ -313,8 +425,12 @@ int notes_copy_from_stdin(int force) strbuf_list_free(split); } - commit_notes(t, "Notes added by 'git notes copy'"); - free_notes(t); + if (!rewrite_cmd) { + commit_notes(t, "Notes added by 'git notes copy'"); + free_notes(t); + } else { + finish_copy_notes_for_rewrite(c); + } return ret; } @@ -330,6 +446,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix) remove = 0, prune = 0, force = 0, from_stdin = 0; int given_object = 0, i = 1, retval = 0; struct msg_arg msg = { 0, 0, STRBUF_INIT }; + const char *rewrite_cmd = NULL; struct option options[] = { OPT_GROUP("Notes options"), OPT_CALLBACK('m', "message", &msg, "MSG", @@ -342,6 +459,8 @@ int cmd_notes(int argc, const char **argv, const char *prefix) "reuse specified note object", parse_reuse_arg), OPT_BOOLEAN('f', "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 --stdin)"), OPT_END() }; @@ -390,6 +509,10 @@ int cmd_notes(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_usage, options); } + if (!copy && rewrite_cmd) { + error("cannot use --for-rewrite with %s subcommand.", argv[0]); + usage_with_options(git_notes_usage, options); + } if (!copy && from_stdin) { error("cannot use --stdin with %s subcommand.", argv[0]); usage_with_options(git_notes_usage, options); @@ -397,12 +520,12 @@ int cmd_notes(int argc, const char **argv, const char *prefix) if (copy) { const char *from_ref; - if (from_stdin) { + if (from_stdin || rewrite_cmd) { if (argc > 1) { error("too many parameters"); usage_with_options(git_notes_usage, options); } else { - return notes_copy_from_stdin(force); + return notes_copy_from_stdin(force, rewrite_cmd); } } if (argc < 3) { |