This option is intended to help with the transition away from the now-deprecated graft file. Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- Documentation/git-replace.txt | 11 +++++-- builtin/replace.c | 59 ++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt index e5c57ae6ef4..4dc0686f7d6 100644 --- a/Documentation/git-replace.txt +++ b/Documentation/git-replace.txt @@ -11,6 +11,7 @@ SYNOPSIS 'git replace' [-f] <object> <replacement> 'git replace' [-f] --edit <object> 'git replace' [-f] --graft <commit> [<parent>...] +'git replace' [-f] --convert-graft-file 'git replace' -d <object>... 'git replace' [--format=<format>] [-l [<pattern>]] @@ -87,9 +88,13 @@ OPTIONS content as <commit> except that its parents will be [<parent>...] instead of <commit>'s parents. A replacement ref is then created to replace <commit> with the newly created - commit. See contrib/convert-grafts-to-replace-refs.sh for an - example script based on this option that can convert grafts to - replace refs. + commit. Use `--convert-graft-file` to convert a + `$GIT_DIR/info/grafts` file use replace refs instead. + +--convert-graft-file:: + Creates graft commits for all entries in `$GIT_DIR/info/grafts` + and deletes that file upon success. The purpose is to help users + with transitioning off of the now-deprecated graft file. -l <pattern>:: --list <pattern>:: diff --git a/builtin/replace.c b/builtin/replace.c index 43264f0998e..4cdc00a96df 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -20,6 +20,7 @@ static const char * const git_replace_usage[] = { N_("git replace [-f] <object> <replacement>"), N_("git replace [-f] --edit <object>"), N_("git replace [-f] --graft <commit> [<parent>...]"), + N_("git replace [-f] --convert-graft-file"), N_("git replace -d <object>..."), N_("git replace [--format=<format>] [-l [<pattern>]]"), NULL @@ -423,6 +424,53 @@ static int create_graft(int argc, const char **argv, int force) return replace_object_oid(old_ref, &old_oid, "replacement", &new_oid, force); } +static int convert_graft_file(int force) +{ + const char *graft_file = get_graft_file(); + FILE *fp = fopen_or_warn(graft_file, "r"); + struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT; + struct argv_array args = ARGV_ARRAY_INIT; + + if (!fp) + return -1; + + while (strbuf_getline(&buf, fp) != EOF) { + int i = 0, j; + + while (i != buf.len) { + char save; + + for (j = i; j < buf.len && !isspace(buf.buf[j]); j++) + ; /* look further */ + save = buf.buf[j]; + buf.buf[j] = '\0'; + argv_array_push(&args, buf.buf + i); + buf.buf[j] = save; + + while (j < buf.len && isspace(buf.buf[j])) + j++; + i = j; + } + + if (create_graft(args.argc, args.argv, force)) + strbuf_addf(&err, "\n\t%s", buf.buf); + + argv_array_clear(&args); + strbuf_reset(&buf); + } + + strbuf_release(&buf); + argv_array_clear(&args); + + if (!err.len) + return unlink_or_warn(graft_file); + + warning(_("could not convert the following graft(s):\n%s"), err.buf); + strbuf_release(&err); + + return -1; +} + int cmd_replace(int argc, const char **argv, const char *prefix) { int force = 0; @@ -434,6 +482,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix) MODE_DELETE, MODE_EDIT, MODE_GRAFT, + MODE_CONVERT_GRAFT_FILE, MODE_REPLACE } cmdmode = MODE_UNSPECIFIED; struct option options[] = { @@ -441,6 +490,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix) OPT_CMDMODE('d', "delete", &cmdmode, N_("delete replace refs"), MODE_DELETE), OPT_CMDMODE('e', "edit", &cmdmode, N_("edit existing object"), MODE_EDIT), OPT_CMDMODE('g', "graft", &cmdmode, N_("change a commit's parents"), MODE_GRAFT), + OPT_CMDMODE(0, "convert-graft-file", &cmdmode, N_("convert existing graft file"), MODE_CONVERT_GRAFT_FILE), OPT_BOOL_F('f', "force", &force, N_("replace the ref if it exists"), PARSE_OPT_NOCOMPLETE), OPT_BOOL(0, "raw", &raw, N_("do not pretty-print contents for --edit")), @@ -463,7 +513,8 @@ int cmd_replace(int argc, const char **argv, const char *prefix) if (force && cmdmode != MODE_REPLACE && cmdmode != MODE_EDIT && - cmdmode != MODE_GRAFT) + cmdmode != MODE_GRAFT && + cmdmode != MODE_CONVERT_GRAFT_FILE) usage_msg_opt("-f only makes sense when writing a replacement", git_replace_usage, options); @@ -496,6 +547,12 @@ int cmd_replace(int argc, const char **argv, const char *prefix) git_replace_usage, options); return create_graft(argc, argv, force); + case MODE_CONVERT_GRAFT_FILE: + if (argc != 0) + usage_msg_opt("--convert-graft-file takes no argument", + git_replace_usage, options); + return !!convert_graft_file(force); + case MODE_LIST: if (argc > 1) usage_msg_opt("only one pattern can be given with -l", -- 2.17.0.windows.1.4.g7e4058d72e3