Deprecate support for .git/info/grafts
[gitweb.git] / builtin / replace.c
index e57d3d187eddb723f17fbe188dd3fb73838d58a0..a87fca045be831c2e14b0c4977d48f205833bace 100644 (file)
@@ -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
@@ -428,7 +429,7 @@ static int check_mergetags(struct commit *commit, int argc, const char **argv)
        return for_each_mergetag(check_one_mergetag, commit, &mergetag_data);
 }
 
-static int create_graft(int argc, const char **argv, int force)
+static int create_graft(int argc, const char **argv, int force, int gentle)
 {
        struct object_id old_oid, new_oid;
        const char *old_ref = argv[0];
@@ -470,12 +471,49 @@ static int create_graft(int argc, const char **argv, int force)
 
        strbuf_release(&buf);
 
-       if (!oidcmp(&old_oid, &new_oid))
+       if (!oidcmp(&old_oid, &new_oid)) {
+               if (gentle) {
+                       warning("graft for '%s' unnecessary", oid_to_hex(&old_oid));
+                       return 0;
+               }
                return error("new commit is the same as the old one: '%s'", oid_to_hex(&old_oid));
+       }
 
        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, 1))
+                       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 +525,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 +533,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 +556,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);
 
@@ -547,7 +588,13 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
                if (argc < 1)
                        usage_msg_opt("-g needs at least one argument",
                                      git_replace_usage, options);
-               return create_graft(argc, argv, force);
+               return create_graft(argc, argv, force, 0);
+
+       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)