]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'hs/rebase-not-in-progress' into HEAD
authorJunio C Hamano <gitster@pobox.com>
Fri, 1 Mar 2024 22:38:56 +0000 (14:38 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 1 Mar 2024 22:38:56 +0000 (14:38 -0800)
Error message update.

* hs/rebase-not-in-progress:
  rebase: make warning less passive aggressive

1  2 
builtin/rebase.c

diff --combined builtin/rebase.c
index 5b086f651a6fce7d97132da8ff36c80f00648db1,7acb7f3559c7642500c709ac89e651ea3c35085d..6ead9465a42c6d3c6ff7a547bb42ed9dd919dd90
@@@ -6,21 -6,18 +6,21 @@@
  
  #define USE_THE_INDEX_VARIABLE
  #include "builtin.h"
 +#include "abspath.h"
 +#include "environment.h"
 +#include "gettext.h"
 +#include "hex.h"
  #include "run-command.h"
 -#include "exec-cmd.h"
  #include "strvec.h"
  #include "dir.h"
 -#include "packfile.h"
  #include "refs.h"
 -#include "quote.h"
  #include "config.h"
 -#include "cache-tree.h"
  #include "unpack-trees.h"
  #include "lockfile.h"
 +#include "object-file.h"
 +#include "object-name.h"
  #include "parse-options.h"
 +#include "path.h"
  #include "commit.h"
  #include "diff.h"
  #include "wt-status.h"
@@@ -31,7 -28,6 +31,7 @@@
  #include "sequencer.h"
  #include "rebase-interactive.h"
  #include "reset.h"
 +#include "trace2.h"
  #include "hook.h"
  
  static char const * const builtin_rebase_usage[] = {
@@@ -120,15 -116,13 +120,15 @@@ struct rebase_options 
        struct string_list exec;
        int allow_empty_message;
        int rebase_merges, rebase_cousins;
 -      char *strategy, *strategy_opts;
 +      char *strategy;
 +      struct string_list strategy_opts;
        struct strbuf git_format_patch_opt;
        int reschedule_failed_exec;
        int reapply_cherry_picks;
        int fork_point;
        int update_refs;
        int config_autosquash;
 +      int config_rebase_merges;
        int config_update_refs;
  };
  
                .reapply_cherry_picks = -1,             \
                .allow_empty_message = 1,               \
                .autosquash = -1,                       \
 -              .config_autosquash = -1,                \
 +              .rebase_merges = -1,                    \
 +              .config_rebase_merges = -1,             \
                .update_refs = -1,                      \
                .config_update_refs = -1,               \
 +              .strategy_opts = STRING_LIST_INIT_NODUP,\
        }
  
  static struct replay_opts get_replay_opts(const struct rebase_options *opts)
                replay.default_strategy = NULL;
        }
  
 -      if (opts->strategy_opts)
 -              parse_strategy_opts(&replay, opts->strategy_opts);
 +      for (size_t i = 0; i < opts->strategy_opts.nr; i++)
 +              strvec_push(&replay.xopts, opts->strategy_opts.items[i].string);
  
        if (opts->squash_onto) {
                oidcpy(&replay.squash_onto, opts->squash_onto);
@@@ -204,7 -196,7 +204,7 @@@ static int edit_todo_file(unsigned flag
        if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
                return error_errno(_("could not read '%s'."), todo_file);
  
 -      strbuf_stripspace(&todo_list.buf, 1);
 +      strbuf_stripspace(&todo_list.buf, comment_line_char);
        res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags);
        if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file,
                                            NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS)))
@@@ -226,15 -218,13 +226,15 @@@ static int get_revision_ranges(struct c
        *revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
                             oid_to_hex(orig_head));
  
 -      shorthead = find_unique_abbrev(orig_head, DEFAULT_ABBREV);
 +      shorthead = repo_find_unique_abbrev(the_repository, orig_head,
 +                                          DEFAULT_ABBREV);
  
        if (upstream) {
                const char *shortrev;
  
 -              shortrev = find_unique_abbrev(&base_rev->object.oid,
 -                                            DEFAULT_ABBREV);
 +              shortrev = repo_find_unique_abbrev(the_repository,
 +                                                 &base_rev->object.oid,
 +                                                 DEFAULT_ABBREV);
  
                *shortrevisions = xstrfmt("%s..%s", shortrev, shorthead);
        } else
@@@ -371,6 -361,20 +371,6 @@@ static int run_sequencer_rebase(struct 
        return ret;
  }
  
 -static void imply_merge(struct rebase_options *opts, const char *option);
 -static int parse_opt_keep_empty(const struct option *opt, const char *arg,
 -                              int unset)
 -{
 -      struct rebase_options *opts = opt->value;
 -
 -      BUG_ON_OPT_ARG(arg);
 -
 -      imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty");
 -      opts->keep_empty = !unset;
 -      opts->type = REBASE_MERGE;
 -      return 0;
 -}
 -
  static int is_merge(struct rebase_options *opts)
  {
        return opts->type == REBASE_MERGE;
@@@ -478,6 -482,24 +478,6 @@@ static int read_basic_state(struct reba
                opts->gpg_sign_opt = xstrdup(buf.buf);
        }
  
 -      if (file_exists(state_dir_path("strategy", opts))) {
 -              strbuf_reset(&buf);
 -              if (!read_oneliner(&buf, state_dir_path("strategy", opts),
 -                                 READ_ONELINER_WARN_MISSING))
 -                      return -1;
 -              free(opts->strategy);
 -              opts->strategy = xstrdup(buf.buf);
 -      }
 -
 -      if (file_exists(state_dir_path("strategy_opts", opts))) {
 -              strbuf_reset(&buf);
 -              if (!read_oneliner(&buf, state_dir_path("strategy_opts", opts),
 -                                 READ_ONELINER_WARN_MISSING))
 -                      return -1;
 -              free(opts->strategy_opts);
 -              opts->strategy_opts = xstrdup(buf.buf);
 -      }
 -
        strbuf_release(&buf);
  
        return 0;
@@@ -495,6 -517,12 +495,6 @@@ static int rebase_write_basic_state(str
                write_file(state_dir_path("quiet", opts), "%s", "");
        if (opts->flags & REBASE_VERBOSE)
                write_file(state_dir_path("verbose", opts), "%s", "");
 -      if (opts->strategy)
 -              write_file(state_dir_path("strategy", opts), "%s",
 -                         opts->strategy);
 -      if (opts->strategy_opts)
 -              write_file(state_dir_path("strategy_opts", opts), "%s",
 -                         opts->strategy_opts);
        if (opts->allow_rerere_autoupdate > 0)
                write_file(state_dir_path("allow_rerere_autoupdate", opts),
                           "-%s-rerere-autoupdate",
@@@ -515,7 -543,7 +515,7 @@@ static int finish_rebase(struct rebase_
        int ret = 0;
  
        delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
 -      unlink(git_path_auto_merge(the_repository));
 +      delete_ref(NULL, "AUTO_MERGE", NULL, REF_NO_DEREF);
        apply_autostash(state_dir_path("autostash", opts));
        /*
         * We ignore errors in 'git maintenance run --auto', since the
@@@ -578,6 -606,7 +578,6 @@@ static int run_am(struct rebase_option
  {
        struct child_process am = CHILD_PROCESS_INIT;
        struct child_process format_patch = CHILD_PROCESS_INIT;
 -      struct strbuf revisions = STRBUF_INIT;
        int status;
        char *rebased_patches;
  
                return run_command(&am);
        }
  
 -      strbuf_addf(&revisions, "%s...%s",
 -                  oid_to_hex(opts->root ?
 -                             /* this is now equivalent to !opts->upstream */
 -                             &opts->onto->object.oid :
 -                             &opts->upstream->object.oid),
 -                  oid_to_hex(&opts->orig_head->object.oid));
 -
        rebased_patches = xstrdup(git_path("rebased-patches"));
        format_patch.out = open(rebased_patches,
                                O_WRONLY | O_CREAT | O_TRUNC, 0666);
        format_patch.git_cmd = 1;
        strvec_pushl(&format_patch.args, "format-patch", "-k", "--stdout",
                     "--full-index", "--cherry-pick", "--right-only",
 -                   "--src-prefix=a/", "--dst-prefix=b/", "--no-renames",
 +                   "--default-prefix", "--no-renames",
                     "--no-cover-letter", "--pretty=mboxrd", "--topo-order",
                     "--no-base", NULL);
        if (opts->git_format_patch_opt.len)
                strvec_split(&format_patch.args,
                             opts->git_format_patch_opt.buf);
 -      strvec_push(&format_patch.args, revisions.buf);
 +      strvec_pushf(&format_patch.args, "%s...%s",
 +                   oid_to_hex(opts->root ?
 +                              /* this is now equivalent to !opts->upstream */
 +                              &opts->onto->object.oid :
 +                              &opts->upstream->object.oid),
 +                   oid_to_hex(&opts->orig_head->object.oid));
        if (opts->restrict_revision)
                strvec_pushf(&format_patch.args, "^%s",
                             oid_to_hex(&opts->restrict_revision->object.oid));
                        "As a result, git cannot rebase them."),
                      opts->revisions);
  
 -              strbuf_release(&revisions);
                return status;
        }
 -      strbuf_release(&revisions);
  
        am.in = open(rebased_patches, O_RDONLY);
        if (am.in < 0) {
@@@ -701,8 -734,10 +701,8 @@@ static int run_specific_rebase(struct r
        if (opts->type == REBASE_MERGE) {
                /* Run sequencer-based rebase */
                setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1);
 -              if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
 +              if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT))
                        setenv("GIT_SEQUENCE_EDITOR", ":", 1);
 -                      opts->autosquash = 0;
 -              }
                if (opts->gpg_sign_opt) {
                        /* remove the leading "-S" */
                        char *tmp = xstrdup(opts->gpg_sign_opt + 2);
        return status ? -1 : 0;
  }
  
 -static int rebase_config(const char *var, const char *value, void *data)
 +static void parse_rebase_merges_value(struct rebase_options *options, const char *value)
 +{
 +      if (!strcmp("no-rebase-cousins", value))
 +              options->rebase_cousins = 0;
 +      else if (!strcmp("rebase-cousins", value))
 +              options->rebase_cousins = 1;
 +      else
 +              die(_("Unknown rebase-merges mode: %s"), value);
 +}
 +
 +static int rebase_config(const char *var, const char *value,
 +                       const struct config_context *ctx, void *data)
  {
        struct rebase_options *opts = data;
  
                return 0;
        }
  
 +      if (!strcmp(var, "rebase.rebasemerges")) {
 +              opts->config_rebase_merges = git_parse_maybe_bool(value);
 +              if (opts->config_rebase_merges < 0) {
 +                      opts->config_rebase_merges = 1;
 +                      parse_rebase_merges_value(opts, value);
 +              } else {
 +                      opts->rebase_cousins = 0;
 +              }
 +              return 0;
 +      }
 +
        if (!strcmp(var, "rebase.updaterefs")) {
                opts->config_update_refs = git_config_bool(var, value);
                return 0;
                return git_config_string(&opts->default_backend, var, value);
        }
  
 -      return git_default_config(var, value, data);
 +      return git_default_config(var, value, ctx, data);
  }
  
  static int checkout_up_to_date(struct rebase_options *options)
  static int is_linear_history(struct commit *from, struct commit *to)
  {
        while (to && to != from) {
 -              parse_commit(to);
 +              repo_parse_commit(the_repository, to);
                if (!to->parents)
                        return 1;
                if (to->parents->next)
@@@ -867,7 -880,7 +867,7 @@@ static int can_fast_forward(struct comm
        if (!upstream)
                goto done;
  
 -      merge_bases = get_merge_bases(upstream, head);
 +      merge_bases = repo_get_merge_bases(the_repository, upstream, head);
        if (!merge_bases || merge_bases->next)
                goto done;
  
@@@ -886,8 -899,7 +886,8 @@@ static void fill_branch_base(struct reb
  {
        struct commit_list *merge_bases = NULL;
  
 -      merge_bases = get_merge_bases(options->onto, options->orig_head);
 +      merge_bases = repo_get_merge_bases(the_repository, options->onto,
 +                                         options->orig_head);
        if (!merge_bases || merge_bases->next)
                oidcpy(branch_base, null_oid());
        else
@@@ -957,18 -969,6 +957,18 @@@ static enum empty_type parse_empty_valu
        die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value);
  }
  
 +static int parse_opt_keep_empty(const struct option *opt, const char *arg,
 +                              int unset)
 +{
 +      struct rebase_options *opts = opt->value;
 +
 +      BUG_ON_OPT_ARG(arg);
 +
 +      imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty");
 +      opts->keep_empty = !unset;
 +      return 0;
 +}
 +
  static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
  {
        struct rebase_options *options = opt->value;
        return 0;
  }
  
 +static int parse_opt_rebase_merges(const struct option *opt, const char *arg, int unset)
 +{
 +      struct rebase_options *options = opt->value;
 +
 +      options->rebase_merges = !unset;
 +      options->rebase_cousins = 0;
 +
 +      if (arg) {
 +              if (!*arg) {
 +                      warning(_("--rebase-merges with an empty string "
 +                                "argument is deprecated and will stop "
 +                                "working in a future version of Git. Use "
 +                                "--rebase-merges without an argument "
 +                                "instead, which does the same thing."));
 +                      return 0;
 +              }
 +              parse_rebase_merges_value(options, arg);
 +      }
 +
 +      return 0;
 +}
 +
  static void NORETURN error_on_missing_default_upstream(void)
  {
        struct branch *current_branch = branch_get(NULL);
@@@ -1057,6 -1035,8 +1057,6 @@@ int cmd_rebase(int argc, const char **a
        struct object_id branch_base;
        int ignore_whitespace = 0;
        const char *gpg_sign = NULL;
 -      const char *rebase_merges = NULL;
 -      struct string_list strategy_options = STRING_LIST_INIT_NODUP;
        struct object_id squash_onto;
        char *squash_onto_name = NULL;
        char *keep_base_onto_name = NULL;
                                 "instead of ignoring them"),
                              1, PARSE_OPT_HIDDEN),
                OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
 -              OPT_CALLBACK_F(0, "empty", &options, "{drop,keep,ask}",
 +              OPT_CALLBACK_F(0, "empty", &options, "(drop|keep|ask)",
                               N_("how to handle commits that become empty"),
                               PARSE_OPT_NONEG, parse_opt_empty),
                OPT_CALLBACK_F('k', "keep-empty", &options, NULL,
                           &options.allow_empty_message,
                           N_("allow rebasing commits with empty messages"),
                           PARSE_OPT_HIDDEN),
 -              {OPTION_STRING, 'r', "rebase-merges", &rebase_merges,
 -                      N_("mode"),
 +              OPT_CALLBACK_F('r', "rebase-merges", &options, N_("mode"),
                        N_("try to rebase merges instead of skipping them"),
 -                      PARSE_OPT_OPTARG, NULL, (intptr_t)""},
 +                      PARSE_OPT_OPTARG, parse_opt_rebase_merges),
                OPT_BOOL(0, "fork-point", &options.fork_point,
                         N_("use 'merge-base --fork-point' to refine upstream")),
                OPT_STRING('s', "strategy", &options.strategy,
                           N_("strategy"), N_("use the given merge strategy")),
 -              OPT_STRING_LIST('X', "strategy-option", &strategy_options,
 +              OPT_STRING_LIST('X', "strategy-option", &options.strategy_opts,
                                N_("option"),
                                N_("pass the argument through to the merge "
                                   "strategy")),
                die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
  
        if (options.action != ACTION_NONE && !in_progress)
-               die(_("No rebase in progress?"));
+               die(_("no rebase in progress"));
  
        if (options.action == ACTION_EDIT_TODO && !is_merge(&options))
                die(_("The --edit-todo action can only be used during "
                int fd;
  
                /* Sanity check */
 -              if (get_oid("HEAD", &head))
 +              if (repo_get_oid(the_repository, "HEAD", &head))
                        die(_("Cannot read HEAD"));
  
                fd = repo_hold_locked_index(the_repository, &lock_file, 0);
        if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
            (options.action != ACTION_NONE) ||
            (options.exec.nr > 0) ||
 -          (options.autosquash == -1 && options.config_autosquash == 1) ||
            options.autosquash == 1) {
                allow_preemptive_ff = 0;
        }
        if (options.exec.nr)
                imply_merge(&options, "--exec");
  
 -      if (rebase_merges) {
 -              if (!*rebase_merges)
 -                      ; /* default mode; do nothing */
 -              else if (!strcmp("rebase-cousins", rebase_merges))
 -                      options.rebase_cousins = 1;
 -              else if (strcmp("no-rebase-cousins", rebase_merges))
 -                      die(_("Unknown mode: %s"), rebase_merges);
 -              options.rebase_merges = 1;
 -              imply_merge(&options, "--rebase-merges");
 -      }
 -
        if (options.type == REBASE_APPLY) {
                if (ignore_whitespace)
                        strvec_push(&options.git_am_opts,
        } else {
                /* REBASE_MERGE */
                if (ignore_whitespace) {
 -                      string_list_append(&strategy_options,
 +                      string_list_append(&options.strategy_opts,
                                           "ignore-space-change");
                }
        }
  
 -      if (strategy_options.nr) {
 -              int i;
 -
 -              if (!options.strategy)
 -                      options.strategy = "ort";
 -
 -              strbuf_reset(&buf);
 -              for (i = 0; i < strategy_options.nr; i++)
 -                      strbuf_addf(&buf, " --%s",
 -                                  strategy_options.items[i].string);
 -              options.strategy_opts = xstrdup(buf.buf);
 -      }
 +      if (options.strategy_opts.nr && !options.strategy)
 +              options.strategy = "ort";
  
        if (options.strategy) {
                options.strategy = xstrdup(options.strategy);
 -              switch (options.type) {
 -              case REBASE_APPLY:
 -                      die(_("--strategy requires --merge or --interactive"));
 -              case REBASE_MERGE:
 -                      /* compatible */
 -                      break;
 -              case REBASE_UNSPECIFIED:
 -                      options.type = REBASE_MERGE;
 -                      break;
 -              default:
 -                      BUG("unhandled rebase type (%d)", options.type);
 -              }
 +              imply_merge(&options, "--strategy");
        }
  
 -      if (options.type == REBASE_MERGE)
 -              imply_merge(&options, "--merge");
 -
        if (options.root && !options.onto_name)
                imply_merge(&options, "--root without --onto");
  
                        if (is_merge(&options))
                                die(_("apply options and merge options "
                                          "cannot be used together"));
 -                      else if (options.autosquash == -1 && options.config_autosquash == 1)
 -                              die(_("apply options are incompatible with rebase.autosquash.  Consider adding --no-autosquash"));
 +                      else if (options.rebase_merges == -1 && options.config_rebase_merges == 1)
 +                              die(_("apply options are incompatible with rebase.rebaseMerges.  Consider adding --no-rebase-merges"));
                        else if (options.update_refs == -1 && options.config_update_refs == 1)
                                die(_("apply options are incompatible with rebase.updateRefs.  Consider adding --no-update-refs"));
                        else
        options.update_refs = (options.update_refs >= 0) ? options.update_refs :
                             ((options.config_update_refs >= 0) ? options.config_update_refs : 0);
  
 -      if (options.autosquash == 1)
 +      if (options.rebase_merges == 1)
 +              imply_merge(&options, "--rebase-merges");
 +      options.rebase_merges = (options.rebase_merges >= 0) ? options.rebase_merges :
 +                              ((options.config_rebase_merges >= 0) ? options.config_rebase_merges : 0);
 +
 +      if (options.autosquash == 1) {
                imply_merge(&options, "--autosquash");
 -      options.autosquash = (options.autosquash >= 0) ? options.autosquash :
 -                           ((options.config_autosquash >= 0) ? options.config_autosquash : 0);
 +      } else if (options.autosquash == -1) {
 +              options.autosquash =
 +                      options.config_autosquash &&
 +                      (options.flags & REBASE_INTERACTIVE_EXPLICIT);
 +      }
  
        if (options.type == REBASE_UNSPECIFIED) {
                if (!strcmp(options.default_backend, "merge"))
 -                      imply_merge(&options, "--merge");
 +                      options.type = REBASE_MERGE;
                else if (!strcmp(options.default_backend, "apply"))
                        options.type = REBASE_APPLY;
                else
        } else if (!options.onto_name)
                options.onto_name = options.upstream_name;
        if (strstr(options.onto_name, "...")) {
 -              if (get_oid_mb(options.onto_name, &branch_base) < 0) {
 +              if (repo_get_oid_mb(the_repository, options.onto_name, &branch_base) < 0) {
                        if (keep_base)
                                die(_("'%s': need exactly one merge base with branch"),
                                    options.upstream_name);
                }
  
                /* We want color (if set), but no pager */
 -              diff_setup(&opts);
 -              opts.stat_width = -1; /* use full terminal width */
 -              opts.stat_graph_width = -1; /* respect statGraphWidth config */
 +              repo_diff_setup(the_repository, &opts);
 +              init_diffstat_widths(&opts);
                opts.output_format |=
                        DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
                opts.detect_rename = DIFF_DETECT_RENAME;
@@@ -1840,9 -1850,10 +1840,9 @@@ cleanup
        free(options.gpg_sign_opt);
        string_list_clear(&options.exec, 0);
        free(options.strategy);
 -      free(options.strategy_opts);
 +      string_list_clear(&options.strategy_opts, 0);
        strbuf_release(&options.git_format_patch_opt);
        free(squash_onto_name);
        free(keep_base_onto_name);
 -      string_list_clear(&strategy_options, 0);
        return !!ret;
  }