This option is intended to help with the transition away from the
now-deprecated graft file.

Signed-off-by: Johannes Schindelin <johannes.schinde...@gmx.de>
---
 Documentation/git-replace.txt | 11 ++++++---
 builtin/replace.c             | 44 ++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt
index e5c57ae6ef4..246dc9943c2 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 and 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 e57d3d187ed..35394ec1874 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
@@ -476,6 +477,38 @@ 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) {
+               if (*buf.buf == '#')
+                       continue;
+
+               argv_array_split(&args, buf.buf);
+               if (args.argc && create_graft(args.argc, args.argv, force))
+                       strbuf_addf(&err, "\n\t%s", buf.buf);
+               argv_array_clear(&args);
+       }
+       fclose(fp);
+
+       strbuf_release(&buf);
+
+       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;
@@ -487,6 +520,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[] = {
@@ -494,6 +528,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")),
@@ -516,7 +551,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);
 
@@ -549,6 +585,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.33.gfcbb1fa0445


Reply via email to