Merge branch 'jk/unused-params-final-batch'
authorJunio C Hamano <gitster@pobox.com>
Thu, 13 Jun 2019 20:19:34 +0000 (13:19 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 13 Jun 2019 20:19:34 +0000 (13:19 -0700)
* jk/unused-params-final-batch:
  verify-commit: simplify parameters to run_gpg_verify()
  show-branch: drop unused parameter from show_independent()
  rev-list: drop unused void pointer from finish_commit()
  remove_all_fetch_refspecs(): drop unused "remote" parameter
  receive-pack: drop unused "commands" from prepare_shallow_update()
  pack-objects: drop unused rev_info parameters
  name-rev: drop unused parameters from is_better_name()
  mktree: drop unused length parameter
  wt-status: drop unused status parameter
  read-cache: drop unused parameter from threaded load
  clone: drop dest parameter from copy_alternates()
  submodule: drop unused prefix parameter from some functions
  builtin: consistently pass cmd_* prefix to parse_options
  cmd_{read,write}_tree: rename "unused" variable that is used

1  2 
builtin/clone.c
builtin/pack-objects.c
builtin/rebase.c
builtin/submodule--helper.c
read-cache.c
wt-status.c

diff --combined builtin/clone.c
@@@ -99,7 -99,10 +99,7 @@@ static struct option builtin_clone_opti
                    N_("don't use local hardlinks, always copy")),
        OPT_BOOL('s', "shared", &option_shared,
                    N_("setup as shared repository")),
 -      { OPTION_CALLBACK, 0, "recursive", &option_recurse_submodules,
 -        N_("pathspec"), N_("initialize submodules in the clone"),
 -        PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, recurse_submodules_cb,
 -        (intptr_t)"." },
 +      OPT_ALIAS(0, "recursive", "recurse-submodules"),
        { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
          N_("pathspec"), N_("initialize submodules in the clone"),
          PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
@@@ -354,8 -357,7 +354,7 @@@ static void setup_reference(void
                             add_one_reference, &required);
  }
  
- static void copy_alternates(struct strbuf *src, struct strbuf *dst,
-                           const char *src_repo)
+ static void copy_alternates(struct strbuf *src, const char *src_repo)
  {
        /*
         * Read from the source objects/info/alternates file
@@@ -436,7 -438,7 +435,7 @@@ static void copy_or_link_directory(stru
  
                /* Files that cannot be copied bit-for-bit... */
                if (!strcmp(src->buf + src_baselen, "/info/alternates")) {
-                       copy_alternates(src, dest, src_repo);
+                       copy_alternates(src, src_repo);
                        continue;
                }
  
@@@ -657,8 -659,7 +656,8 @@@ static void update_remote_refs(const st
                               const char *branch_top,
                               const char *msg,
                               struct transport *transport,
 -                             int check_connectivity)
 +                             int check_connectivity,
 +                             int check_refs_only)
  {
        const struct ref *rm = mapped_refs;
  
  
                opt.transport = transport;
                opt.progress = transport->progress;
 +              opt.check_refs_only = !!check_refs_only;
  
                if (check_connected(iterate_ref_map, &rm, &opt))
                        die(_("remote did not send all necessary objects"));
@@@ -1229,7 -1229,7 +1228,7 @@@ int cmd_clone(int argc, const char **ar
  
        update_remote_refs(refs, mapped_refs, remote_head_points_at,
                           branch_top.buf, reflog_msg.buf, transport,
 -                         !is_local);
 +                         !is_local, filter_options.choice);
  
        update_head(our_head_points_at, remote_head, reflog_msg.buf);
  
diff --combined builtin/pack-objects.c
@@@ -97,7 -97,7 +97,7 @@@ static off_t reuse_packfile_offset
  static int use_bitmap_index_default = 1;
  static int use_bitmap_index = -1;
  static int write_bitmap_index;
 -static uint16_t write_bitmap_options;
 +static uint16_t write_bitmap_options = BITMAP_OPT_HASH_CACHE;
  
  static int exclude_promisor_objects;
  
@@@ -1080,7 -1080,7 +1080,7 @@@ static int want_object_in_pack(const st
  
        for (m = get_multi_pack_index(the_repository); m; m = m->next) {
                struct pack_entry e;
 -              if (fill_midx_entry(oid, &e, m)) {
 +              if (fill_midx_entry(the_repository, oid, &e, m)) {
                        struct packed_git *p = e.p;
                        off_t offset;
  
@@@ -2899,7 -2899,7 +2899,7 @@@ static int ofscmp(const void *a_, cons
                return oidcmp(&a->object->oid, &b->object->oid);
  }
  
- static void add_objects_in_unpacked_packs(struct rev_info *revs)
+ static void add_objects_in_unpacked_packs(void)
  {
        struct packed_git *p;
        struct in_pack in_pack;
@@@ -3011,7 -3011,7 +3011,7 @@@ static int loosened_object_can_be_disca
        return 1;
  }
  
- static void loosen_unused_packed_objects(struct rev_info *revs)
+ static void loosen_unused_packed_objects(void)
  {
        struct packed_git *p;
        uint32_t i;
@@@ -3158,11 -3158,11 +3158,11 @@@ static void get_object_list(int ac, con
        }
  
        if (keep_unreachable)
-               add_objects_in_unpacked_packs(&revs);
+               add_objects_in_unpacked_packs();
        if (pack_loose_unreachable)
                add_unreachable_loose_objects();
        if (unpack_unreachable)
-               loosen_unused_packed_objects(&revs);
+               loosen_unused_packed_objects();
  
        oid_array_clear(&recent_objects);
  }
diff --combined builtin/rebase.c
@@@ -25,8 -25,6 +25,8 @@@
  #include "commit-reach.h"
  #include "rerere.h"
  #include "branch.h"
 +#include "sequencer.h"
 +#include "rebase-interactive.h"
  
  static char const * const builtin_rebase_usage[] = {
        N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
@@@ -37,8 -35,6 +37,8 @@@
        NULL
  };
  
 +static GIT_PATH_FUNC(path_squash_onto, "rebase-merge/squash-onto")
 +static GIT_PATH_FUNC(path_interactive, "rebase-merge/interactive")
  static GIT_PATH_FUNC(apply_dir, "rebase-apply")
  static GIT_PATH_FUNC(merge_dir, "rebase-merge")
  
@@@ -90,437 -86,6 +90,437 @@@ struct rebase_options 
        int use_legacy_rebase;
  };
  
-       argc = parse_options(argc, argv, NULL, options,
 +#define REBASE_OPTIONS_INIT {                         \
 +              .type = REBASE_UNSPECIFIED,             \
 +              .flags = REBASE_NO_QUIET,               \
 +              .git_am_opts = ARGV_ARRAY_INIT,         \
 +              .git_format_patch_opt = STRBUF_INIT     \
 +      }
 +
 +static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 +{
 +      struct replay_opts replay = REPLAY_OPTS_INIT;
 +
 +      replay.action = REPLAY_INTERACTIVE_REBASE;
 +      sequencer_init_config(&replay);
 +
 +      replay.signoff = opts->signoff;
 +      replay.allow_ff = !(opts->flags & REBASE_FORCE);
 +      if (opts->allow_rerere_autoupdate)
 +              replay.allow_rerere_auto = opts->allow_rerere_autoupdate;
 +      replay.allow_empty = 1;
 +      replay.allow_empty_message = opts->allow_empty_message;
 +      replay.verbose = opts->flags & REBASE_VERBOSE;
 +      replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 +      replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 +      replay.strategy = opts->strategy;
 +      if (opts->strategy_opts)
 +              parse_strategy_opts(&replay, opts->strategy_opts);
 +
 +      return replay;
 +}
 +
 +enum action {
 +      ACTION_NONE = 0,
 +      ACTION_CONTINUE,
 +      ACTION_SKIP,
 +      ACTION_ABORT,
 +      ACTION_QUIT,
 +      ACTION_EDIT_TODO,
 +      ACTION_SHOW_CURRENT_PATCH,
 +      ACTION_SHORTEN_OIDS,
 +      ACTION_EXPAND_OIDS,
 +      ACTION_CHECK_TODO_LIST,
 +      ACTION_REARRANGE_SQUASH,
 +      ACTION_ADD_EXEC
 +};
 +
 +static const char *action_names[] = { "undefined",
 +                                    "continue",
 +                                    "skip",
 +                                    "abort",
 +                                    "quit",
 +                                    "edit_todo",
 +                                    "show_current_patch" };
 +
 +static int add_exec_commands(struct string_list *commands)
 +{
 +      const char *todo_file = rebase_path_todo();
 +      struct todo_list todo_list = TODO_LIST_INIT;
 +      int res;
 +
 +      if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
 +              return error_errno(_("could not read '%s'."), todo_file);
 +
 +      if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
 +                                      &todo_list)) {
 +              todo_list_release(&todo_list);
 +              return error(_("unusable todo list: '%s'"), todo_file);
 +      }
 +
 +      todo_list_add_exec_commands(&todo_list, commands);
 +      res = todo_list_write_to_file(the_repository, &todo_list,
 +                                    todo_file, NULL, NULL, -1, 0);
 +      todo_list_release(&todo_list);
 +
 +      if (res)
 +              return error_errno(_("could not write '%s'."), todo_file);
 +      return 0;
 +}
 +
 +static int rearrange_squash_in_todo_file(void)
 +{
 +      const char *todo_file = rebase_path_todo();
 +      struct todo_list todo_list = TODO_LIST_INIT;
 +      int res = 0;
 +
 +      if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
 +              return error_errno(_("could not read '%s'."), todo_file);
 +      if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
 +                                      &todo_list)) {
 +              todo_list_release(&todo_list);
 +              return error(_("unusable todo list: '%s'"), todo_file);
 +      }
 +
 +      res = todo_list_rearrange_squash(&todo_list);
 +      if (!res)
 +              res = todo_list_write_to_file(the_repository, &todo_list,
 +                                            todo_file, NULL, NULL, -1, 0);
 +
 +      todo_list_release(&todo_list);
 +
 +      if (res)
 +              return error_errno(_("could not write '%s'."), todo_file);
 +      return 0;
 +}
 +
 +static int transform_todo_file(unsigned flags)
 +{
 +      const char *todo_file = rebase_path_todo();
 +      struct todo_list todo_list = TODO_LIST_INIT;
 +      int res;
 +
 +      if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
 +              return error_errno(_("could not read '%s'."), todo_file);
 +
 +      if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
 +                                      &todo_list)) {
 +              todo_list_release(&todo_list);
 +              return error(_("unusable todo list: '%s'"), todo_file);
 +      }
 +
 +      res = todo_list_write_to_file(the_repository, &todo_list, todo_file,
 +                                    NULL, NULL, -1, flags);
 +      todo_list_release(&todo_list);
 +
 +      if (res)
 +              return error_errno(_("could not write '%s'."), todo_file);
 +      return 0;
 +}
 +
 +static int edit_todo_file(unsigned flags)
 +{
 +      const char *todo_file = rebase_path_todo();
 +      struct todo_list todo_list = TODO_LIST_INIT,
 +              new_todo = TODO_LIST_INIT;
 +      int res = 0;
 +
 +      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);
 +      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)))
 +              res = error_errno(_("could not write '%s'"), todo_file);
 +
 +      todo_list_release(&todo_list);
 +      todo_list_release(&new_todo);
 +
 +      return res;
 +}
 +
 +static int get_revision_ranges(struct commit *upstream, struct commit *onto,
 +                             const char **head_hash,
 +                             char **revisions, char **shortrevisions)
 +{
 +      struct commit *base_rev = upstream ? upstream : onto;
 +      const char *shorthead;
 +      struct object_id orig_head;
 +
 +      if (get_oid("HEAD", &orig_head))
 +              return error(_("no HEAD?"));
 +
 +      *head_hash = find_unique_abbrev(&orig_head, GIT_MAX_HEXSZ);
 +      *revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
 +                                                 *head_hash);
 +
 +      shorthead = find_unique_abbrev(&orig_head, DEFAULT_ABBREV);
 +
 +      if (upstream) {
 +              const char *shortrev;
 +
 +              shortrev = find_unique_abbrev(&base_rev->object.oid,
 +                                            DEFAULT_ABBREV);
 +
 +              *shortrevisions = xstrfmt("%s..%s", shortrev, shorthead);
 +      } else
 +              *shortrevisions = xstrdup(shorthead);
 +
 +      return 0;
 +}
 +
 +static int init_basic_state(struct replay_opts *opts, const char *head_name,
 +                          struct commit *onto, const char *orig_head)
 +{
 +      FILE *interactive;
 +
 +      if (!is_directory(merge_dir()) && mkdir_in_gitdir(merge_dir()))
 +              return error_errno(_("could not create temporary %s"), merge_dir());
 +
 +      delete_reflog("REBASE_HEAD");
 +
 +      interactive = fopen(path_interactive(), "w");
 +      if (!interactive)
 +              return error_errno(_("could not mark as interactive"));
 +      fclose(interactive);
 +
 +      return write_basic_state(opts, head_name, onto, orig_head);
 +}
 +
 +static void split_exec_commands(const char *cmd, struct string_list *commands)
 +{
 +      if (cmd && *cmd) {
 +              string_list_split(commands, cmd, '\n', -1);
 +
 +              /* rebase.c adds a new line to cmd after every command,
 +               * so here the last command is always empty */
 +              string_list_remove_empty_items(commands, 0);
 +      }
 +}
 +
 +static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
 +{
 +      int ret;
 +      const char *head_hash = NULL;
 +      char *revisions = NULL, *shortrevisions = NULL;
 +      struct argv_array make_script_args = ARGV_ARRAY_INIT;
 +      struct todo_list todo_list = TODO_LIST_INIT;
 +      struct replay_opts replay = get_replay_opts(opts);
 +      struct string_list commands = STRING_LIST_INIT_DUP;
 +
 +      if (prepare_branch_to_be_rebased(the_repository, &replay,
 +                                       opts->switch_to))
 +              return -1;
 +
 +      if (get_revision_ranges(opts->upstream, opts->onto, &head_hash,
 +                              &revisions, &shortrevisions))
 +              return -1;
 +
 +      if (init_basic_state(&replay,
 +                           opts->head_name ? opts->head_name : "detached HEAD",
 +                           opts->onto, head_hash)) {
 +              free(revisions);
 +              free(shortrevisions);
 +
 +              return -1;
 +      }
 +
 +      if (!opts->upstream && opts->squash_onto)
 +              write_file(path_squash_onto(), "%s\n",
 +                         oid_to_hex(opts->squash_onto));
 +
 +      argv_array_pushl(&make_script_args, "", revisions, NULL);
 +      if (opts->restrict_revision)
 +              argv_array_push(&make_script_args,
 +                              oid_to_hex(&opts->restrict_revision->object.oid));
 +
 +      ret = sequencer_make_script(the_repository, &todo_list.buf,
 +                                  make_script_args.argc, make_script_args.argv,
 +                                  flags);
 +
 +      if (ret)
 +              error(_("could not generate todo list"));
 +      else {
 +              discard_cache();
 +              if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
 +                                              &todo_list))
 +                      BUG("unusable todo list");
 +
 +              split_exec_commands(opts->cmd, &commands);
 +              ret = complete_action(the_repository, &replay, flags,
 +                      shortrevisions, opts->onto_name, opts->onto, head_hash,
 +                      &commands, opts->autosquash, &todo_list);
 +      }
 +
 +      string_list_clear(&commands, 0);
 +      free(revisions);
 +      free(shortrevisions);
 +      todo_list_release(&todo_list);
 +      argv_array_clear(&make_script_args);
 +
 +      return ret;
 +}
 +
 +static int run_rebase_interactive(struct rebase_options *opts,
 +                                enum action command)
 +{
 +      unsigned flags = 0;
 +      int abbreviate_commands = 0, ret = 0;
 +
 +      git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
 +
 +      flags |= opts->keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
 +      flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
 +      flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
 +      flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
 +      flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
 +
 +      switch (command) {
 +      case ACTION_NONE: {
 +              if (!opts->onto && !opts->upstream)
 +                      die(_("a base commit must be provided with --upstream or --onto"));
 +
 +              ret = do_interactive_rebase(opts, flags);
 +              break;
 +      }
 +      case ACTION_SKIP: {
 +              struct string_list merge_rr = STRING_LIST_INIT_DUP;
 +
 +              rerere_clear(the_repository, &merge_rr);
 +      }
 +              /* fallthrough */
 +      case ACTION_CONTINUE: {
 +              struct replay_opts replay_opts = get_replay_opts(opts);
 +
 +              ret = sequencer_continue(the_repository, &replay_opts);
 +              break;
 +      }
 +      case ACTION_EDIT_TODO:
 +              ret = edit_todo_file(flags);
 +              break;
 +      case ACTION_SHOW_CURRENT_PATCH: {
 +              struct child_process cmd = CHILD_PROCESS_INIT;
 +
 +              cmd.git_cmd = 1;
 +              argv_array_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
 +              ret = run_command(&cmd);
 +
 +              break;
 +      }
 +      case ACTION_SHORTEN_OIDS:
 +      case ACTION_EXPAND_OIDS:
 +              ret = transform_todo_file(flags);
 +              break;
 +      case ACTION_CHECK_TODO_LIST:
 +              ret = check_todo_list_from_file(the_repository);
 +              break;
 +      case ACTION_REARRANGE_SQUASH:
 +              ret = rearrange_squash_in_todo_file();
 +              break;
 +      case ACTION_ADD_EXEC: {
 +              struct string_list commands = STRING_LIST_INIT_DUP;
 +
 +              split_exec_commands(opts->cmd, &commands);
 +              ret = add_exec_commands(&commands);
 +              string_list_clear(&commands, 0);
 +              break;
 +      }
 +      default:
 +              BUG("invalid command '%d'", command);
 +      }
 +
 +      return ret;
 +}
 +
 +static const char * const builtin_rebase_interactive_usage[] = {
 +      N_("git rebase--interactive [<options>]"),
 +      NULL
 +};
 +
 +int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 +{
 +      struct rebase_options opts = REBASE_OPTIONS_INIT;
 +      struct object_id squash_onto = null_oid;
 +      enum action command = ACTION_NONE;
 +      struct option options[] = {
 +              OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"),
 +                         REBASE_FORCE),
 +              OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")),
 +              OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message,
 +                       N_("allow commits with empty messages")),
 +              OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")),
 +              OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins,
 +                       N_("keep original branch points of cousins")),
 +              OPT_BOOL(0, "autosquash", &opts.autosquash,
 +                       N_("move commits that begin with squash!/fixup!")),
 +              OPT_BOOL(0, "signoff", &opts.signoff, N_("sign commits")),
 +              OPT_BIT('v', "verbose", &opts.flags,
 +                      N_("display a diffstat of what changed upstream"),
 +                      REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
 +              OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
 +                          ACTION_CONTINUE),
 +              OPT_CMDMODE(0, "skip", &command, N_("skip commit"), ACTION_SKIP),
 +              OPT_CMDMODE(0, "edit-todo", &command, N_("edit the todo list"),
 +                          ACTION_EDIT_TODO),
 +              OPT_CMDMODE(0, "show-current-patch", &command, N_("show the current patch"),
 +                          ACTION_SHOW_CURRENT_PATCH),
 +              OPT_CMDMODE(0, "shorten-ids", &command,
 +                      N_("shorten commit ids in the todo list"), ACTION_SHORTEN_OIDS),
 +              OPT_CMDMODE(0, "expand-ids", &command,
 +                      N_("expand commit ids in the todo list"), ACTION_EXPAND_OIDS),
 +              OPT_CMDMODE(0, "check-todo-list", &command,
 +                      N_("check the todo list"), ACTION_CHECK_TODO_LIST),
 +              OPT_CMDMODE(0, "rearrange-squash", &command,
 +                      N_("rearrange fixup/squash lines"), ACTION_REARRANGE_SQUASH),
 +              OPT_CMDMODE(0, "add-exec-commands", &command,
 +                      N_("insert exec commands in todo list"), ACTION_ADD_EXEC),
 +              { OPTION_CALLBACK, 0, "onto", &opts.onto, N_("onto"), N_("onto"),
 +                PARSE_OPT_NONEG, parse_opt_commit, 0 },
 +              { OPTION_CALLBACK, 0, "restrict-revision", &opts.restrict_revision,
 +                N_("restrict-revision"), N_("restrict revision"),
 +                PARSE_OPT_NONEG, parse_opt_commit, 0 },
 +              { OPTION_CALLBACK, 0, "squash-onto", &squash_onto, N_("squash-onto"),
 +                N_("squash onto"), PARSE_OPT_NONEG, parse_opt_object_id, 0 },
 +              { OPTION_CALLBACK, 0, "upstream", &opts.upstream, N_("upstream"),
 +                N_("the upstream commit"), PARSE_OPT_NONEG, parse_opt_commit,
 +                0 },
 +              OPT_STRING(0, "head-name", &opts.head_name, N_("head-name"), N_("head name")),
 +              { OPTION_STRING, 'S', "gpg-sign", &opts.gpg_sign_opt, N_("key-id"),
 +                      N_("GPG-sign commits"),
 +                      PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 +              OPT_STRING(0, "strategy", &opts.strategy, N_("strategy"),
 +                         N_("rebase strategy")),
 +              OPT_STRING(0, "strategy-opts", &opts.strategy_opts, N_("strategy-opts"),
 +                         N_("strategy options")),
 +              OPT_STRING(0, "switch-to", &opts.switch_to, N_("switch-to"),
 +                         N_("the branch or commit to checkout")),
 +              OPT_STRING(0, "onto-name", &opts.onto_name, N_("onto-name"), N_("onto name")),
 +              OPT_STRING(0, "cmd", &opts.cmd, N_("cmd"), N_("the command to run")),
 +              OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_autoupdate),
 +              OPT_BOOL(0, "reschedule-failed-exec", &opts.reschedule_failed_exec,
 +                       N_("automatically re-schedule any `exec` that fails")),
 +              OPT_END()
 +      };
 +
 +      opts.rebase_cousins = -1;
 +
 +      if (argc == 1)
 +              usage_with_options(builtin_rebase_interactive_usage, options);
 +
++      argc = parse_options(argc, argv, prefix, options,
 +                      builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 +
 +      if (!is_null_oid(&squash_onto))
 +              opts.squash_onto = &squash_onto;
 +
 +      if (opts.rebase_cousins >= 0 && !opts.rebase_merges)
 +              warning(_("--[no-]rebase-cousins has no effect without "
 +                        "--rebase-merges"));
 +
 +      return !!run_rebase_interactive(&opts, command);
 +}
 +
  static int is_interactive(struct rebase_options *opts)
  {
        return opts->type == REBASE_INTERACTIVE ||
@@@ -619,13 -184,14 +619,13 @@@ static int read_basic_state(struct reba
                            &buf))
                        return -1;
                if (!strcmp(buf.buf, "--rerere-autoupdate"))
 -                      opts->allow_rerere_autoupdate = 1;
 +                      opts->allow_rerere_autoupdate = RERERE_AUTOUPDATE;
                else if (!strcmp(buf.buf, "--no-rerere-autoupdate"))
 -                      opts->allow_rerere_autoupdate = 0;
 +                      opts->allow_rerere_autoupdate = RERERE_NOAUTOUPDATE;
                else
                        warning(_("ignoring invalid allow_rerere_autoupdate: "
                                  "'%s'"), buf.buf);
 -      } else
 -              opts->allow_rerere_autoupdate = -1;
 +      }
  
        if (file_exists(state_dir_path("gpg_sign_opt", opts))) {
                strbuf_reset(&buf);
        return 0;
  }
  
 -static int write_basic_state(struct rebase_options *opts)
 +static int rebase_write_basic_state(struct rebase_options *opts)
  {
        write_file(state_dir_path("head-name", opts), "%s",
                   opts->head_name ? opts->head_name : "detached HEAD");
        if (opts->strategy_opts)
                write_file(state_dir_path("strategy_opts", opts), "%s",
                           opts->strategy_opts);
 -      if (opts->allow_rerere_autoupdate >= 0)
 +      if (opts->allow_rerere_autoupdate > 0)
                write_file(state_dir_path("allow_rerere_autoupdate", opts),
                           "-%s-rerere-autoupdate",
 -                         opts->allow_rerere_autoupdate ? "" : "-no");
 +                         opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ?
 +                              "" : "-no");
        if (opts->gpg_sign_opt)
                write_file(state_dir_path("gpg_sign_opt", opts), "%s",
                           opts->gpg_sign_opt);
@@@ -1043,9 -608,9 +1043,9 @@@ static int run_am(struct rebase_option
        argv_array_push(&am.args, "--rebasing");
        argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
        argv_array_push(&am.args, "--patch-format=mboxrd");
 -      if (opts->allow_rerere_autoupdate > 0)
 +      if (opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE)
                argv_array_push(&am.args, "--rerere-autoupdate");
 -      else if (opts->allow_rerere_autoupdate == 0)
 +      else if (opts->allow_rerere_autoupdate == RERERE_NOAUTOUPDATE)
                argv_array_push(&am.args, "--no-rerere-autoupdate");
        if (opts->gpg_sign_opt)
                argv_array_push(&am.args, opts->gpg_sign_opt);
        }
  
        if (is_directory(opts->state_dir))
 -              write_basic_state(opts);
 +              rebase_write_basic_state(opts);
  
        return status;
  }
  
 -static int run_specific_rebase(struct rebase_options *opts)
 +static int run_specific_rebase(struct rebase_options *opts, enum action action)
  {
        const char *argv[] = { NULL, NULL };
        struct strbuf script_snippet = STRBUF_INIT, buf = STRBUF_INIT;
  
        if (opts->type == REBASE_INTERACTIVE) {
                /* Run builtin interactive rebase */
 -              struct child_process child = CHILD_PROCESS_INIT;
 -
 -              argv_array_pushf(&child.env_array, "GIT_CHERRY_PICK_HELP=%s",
 -                               resolvemsg);
 +              setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1);
                if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
 -                      argv_array_push(&child.env_array,
 -                                      "GIT_SEQUENCE_EDITOR=:");
 +                      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);
 +                      free(opts->gpg_sign_opt);
 +                      opts->gpg_sign_opt = tmp;
 +              }
  
 -              child.git_cmd = 1;
 -              argv_array_push(&child.args, "rebase--interactive");
 -
 -              if (opts->action)
 -                      argv_array_pushf(&child.args, "--%s", opts->action);
 -              if (opts->keep_empty)
 -                      argv_array_push(&child.args, "--keep-empty");
 -              if (opts->rebase_merges)
 -                      argv_array_push(&child.args, "--rebase-merges");
 -              if (opts->rebase_cousins)
 -                      argv_array_push(&child.args, "--rebase-cousins");
 -              if (opts->autosquash)
 -                      argv_array_push(&child.args, "--autosquash");
 -              if (opts->flags & REBASE_VERBOSE)
 -                      argv_array_push(&child.args, "--verbose");
 -              if (opts->flags & REBASE_FORCE)
 -                      argv_array_push(&child.args, "--no-ff");
 -              if (opts->restrict_revision)
 -                      argv_array_pushf(&child.args,
 -                                       "--restrict-revision=^%s",
 -                                       oid_to_hex(&opts->restrict_revision->object.oid));
 -              if (opts->upstream)
 -                      argv_array_pushf(&child.args, "--upstream=%s",
 -                                       oid_to_hex(&opts->upstream->object.oid));
 -              if (opts->onto)
 -                      argv_array_pushf(&child.args, "--onto=%s",
 -                                       oid_to_hex(&opts->onto->object.oid));
 -              if (opts->squash_onto)
 -                      argv_array_pushf(&child.args, "--squash-onto=%s",
 -                                       oid_to_hex(opts->squash_onto));
 -              if (opts->onto_name)
 -                      argv_array_pushf(&child.args, "--onto-name=%s",
 -                                       opts->onto_name);
 -              argv_array_pushf(&child.args, "--head-name=%s",
 -                               opts->head_name ?
 -                               opts->head_name : "detached HEAD");
 -              if (opts->strategy)
 -                      argv_array_pushf(&child.args, "--strategy=%s",
 -                                       opts->strategy);
 -              if (opts->strategy_opts)
 -                      argv_array_pushf(&child.args, "--strategy-opts=%s",
 -                                       opts->strategy_opts);
 -              if (opts->switch_to)
 -                      argv_array_pushf(&child.args, "--switch-to=%s",
 -                                       opts->switch_to);
 -              if (opts->cmd)
 -                      argv_array_pushf(&child.args, "--cmd=%s", opts->cmd);
 -              if (opts->allow_empty_message)
 -                      argv_array_push(&child.args, "--allow-empty-message");
 -              if (opts->allow_rerere_autoupdate > 0)
 -                      argv_array_push(&child.args, "--rerere-autoupdate");
 -              else if (opts->allow_rerere_autoupdate == 0)
 -                      argv_array_push(&child.args, "--no-rerere-autoupdate");
 -              if (opts->gpg_sign_opt)
 -                      argv_array_push(&child.args, opts->gpg_sign_opt);
 -              if (opts->signoff)
 -                      argv_array_push(&child.args, "--signoff");
 -              if (opts->reschedule_failed_exec)
 -                      argv_array_push(&child.args, "--reschedule-failed-exec");
 -
 -              status = run_command(&child);
 +              status = run_rebase_interactive(opts, action);
                goto finished_rebase;
        }
  
        add_var(&script_snippet, "action", opts->action ? opts->action : "");
        add_var(&script_snippet, "signoff", opts->signoff ? "--signoff" : "");
        add_var(&script_snippet, "allow_rerere_autoupdate",
 -              opts->allow_rerere_autoupdate < 0 ? "" :
                opts->allow_rerere_autoupdate ?
 -              "--rerere-autoupdate" : "--no-rerere-autoupdate");
 +                      opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ?
 +                      "--rerere-autoupdate" : "--no-rerere-autoupdate" : "");
        add_var(&script_snippet, "keep_empty", opts->keep_empty ? "yes" : "");
        add_var(&script_snippet, "autosquash", opts->autosquash ? "t" : "");
        add_var(&script_snippet, "gpg_sign_opt", opts->gpg_sign_opt);
@@@ -1203,7 -826,7 +1203,7 @@@ static int rebase_config(const char *va
                if (git_config_bool(var, value))
                        opts->flags |= REBASE_DIFFSTAT;
                else
 -                      opts->flags &= !REBASE_DIFFSTAT;
 +                      opts->flags &= ~REBASE_DIFFSTAT;
                return 0;
        }
  
@@@ -1368,7 -991,14 +1368,7 @@@ static int check_exec_cmd(const char *c
  
  int cmd_rebase(int argc, const char **argv, const char *prefix)
  {
 -      struct rebase_options options = {
 -              .type = REBASE_UNSPECIFIED,
 -              .flags = REBASE_NO_QUIET,
 -              .git_am_opts = ARGV_ARRAY_INIT,
 -              .allow_rerere_autoupdate  = -1,
 -              .allow_empty_message = 1,
 -              .git_format_patch_opt = STRBUF_INIT,
 -      };
 +      struct rebase_options options = REBASE_OPTIONS_INIT;
        const char *branch_name;
        int ret, flags, total_argc, in_progress = 0;
        int ok_to_skip_pre_rebase = 0;
        struct strbuf revisions = STRBUF_INIT;
        struct strbuf buf = STRBUF_INIT;
        struct object_id merge_base;
 -      enum {
 -              NO_ACTION,
 -              ACTION_CONTINUE,
 -              ACTION_SKIP,
 -              ACTION_ABORT,
 -              ACTION_QUIT,
 -              ACTION_EDIT_TODO,
 -              ACTION_SHOW_CURRENT_PATCH,
 -      } action = NO_ACTION;
 -      static const char *action_names[] = { N_("undefined"),
 -                                            N_("continue"),
 -                                            N_("skip"),
 -                                            N_("abort"),
 -                                            N_("quit"),
 -                                            N_("edit_todo"),
 -                                            N_("show_current_patch"),
 -                                            NULL };
 +      enum action action = ACTION_NONE;
        const char *gpg_sign = NULL;
        struct string_list exec = STRING_LIST_INIT_NODUP;
        const char *rebase_merges = NULL;
                OPT_SET_INT('p', "preserve-merges", &options.type,
                            N_("(DEPRECATED) try to recreate merges instead of "
                               "ignoring them"), REBASE_PRESERVE_MERGES),
 -              OPT_BOOL(0, "rerere-autoupdate",
 -                       &options.allow_rerere_autoupdate,
 -                       N_("allow rerere to update index with resolved "
 -                          "conflict")),
 +              OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
                OPT_BOOL('k', "keep-empty", &options.keep_empty,
                         N_("preserve empty commits during rebase")),
                OPT_BOOL(0, "autosquash", &options.autosquash,
        trace_repo_setup(prefix);
        setup_work_tree();
  
 +      options.allow_empty_message = 1;
        git_config(rebase_config, &options);
  
        if (options.use_legacy_rebase ||
                             builtin_rebase_options,
                             builtin_rebase_usage, 0);
  
 -      if (action != NO_ACTION && total_argc != 2) {
 +      if (action != ACTION_NONE && total_argc != 2) {
                usage_with_options(builtin_rebase_usage,
                                   builtin_rebase_options);
        }
                warning(_("git rebase --preserve-merges is deprecated. "
                          "Use --rebase-merges instead."));
  
 -      if (action != NO_ACTION && !in_progress)
 +      if (action != ACTION_NONE && !in_progress)
                die(_("No rebase in progress?"));
        setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
  
                options.action = "show-current-patch";
                options.dont_finish_rebase = 1;
                goto run_rebase;
 -      case NO_ACTION:
 +      case ACTION_NONE:
                break;
        default:
                BUG("action: %d", action);
        options.revisions = revisions.buf;
  
  run_rebase:
 -      ret = !!run_specific_rebase(&options);
 +      ret = !!run_specific_rebase(&options, action);
  
  cleanup:
        strbuf_release(&revisions);
@@@ -1301,7 -1301,7 +1301,7 @@@ static int add_possible_reference_from_
                                die(_("submodule '%s' cannot add alternate: %s"),
                                    sas->submodule_name, err.buf);
                        case SUBMODULE_ALTERNATE_ERROR_INFO:
 -                              fprintf(stderr, _("submodule '%s' cannot add alternate: %s"),
 +                              fprintf_ln(stderr, _("submodule '%s' cannot add alternate: %s"),
                                        sas->submodule_name, err.buf);
                        case SUBMODULE_ALTERNATE_ERROR_IGNORE:
                                ; /* nothing */
@@@ -2107,8 -2107,7 +2107,7 @@@ static int absorb_git_dirs(int argc, co
                return 1;
  
        for (i = 0; i < list.nr; i++)
-               absorb_git_dir_into_superproject(prefix,
-                               list.entries[i]->name, flags);
+               absorb_git_dir_into_superproject(list.entries[i]->name, flags);
  
        return 0;
  }
diff --combined read-cache.c
@@@ -2037,7 -2037,7 +2037,7 @@@ static void *load_cache_entries_thread(
  }
  
  static unsigned long load_cache_entries_threaded(struct index_state *istate, const char *mmap, size_t mmap_size,
-                       unsigned long src_offset, int nr_threads, struct index_entry_offset_table *ieot)
+                                                int nr_threads, struct index_entry_offset_table *ieot)
  {
        int i, offset, ieot_blocks, ieot_start, err;
        struct load_cache_entries_thread_data *data;
@@@ -2198,7 -2198,7 +2198,7 @@@ int do_read_index(struct index_state *i
                ieot = read_ieot_extension(mmap, mmap_size, extension_offset);
  
        if (ieot) {
-               src_offset += load_cache_entries_threaded(istate, mmap, mmap_size, src_offset, nr_threads, ieot);
+               src_offset += load_cache_entries_threaded(istate, mmap, mmap_size, nr_threads, ieot);
                free(ieot);
        } else {
                src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
@@@ -2326,7 -2326,6 +2326,7 @@@ int discard_index(struct index_state *i
        free_name_hash(istate);
        cache_tree_free(&(istate->cache_tree));
        istate->initialized = 0;
 +      istate->fsmonitor_has_run_once = 0;
        FREE_AND_NULL(istate->cache);
        istate->cache_alloc = 0;
        discard_split_index(istate);
@@@ -3132,7 -3131,7 +3132,7 @@@ static int write_shared_index(struct in
        trace2_region_enter_printf("index", "shared/do_write_index",
                                   the_repository, "%s", (*temp)->filename.buf);
        ret = do_write_index(si->base, *temp, 1);
 -      trace2_region_enter_printf("index", "shared/do_write_index",
 +      trace2_region_leave_printf("index", "shared/do_write_index",
                                   the_repository, "%s", (*temp)->filename.buf);
  
        if (ret)
diff --combined wt-status.c
@@@ -17,7 -17,6 +17,7 @@@
  #include "utf8.h"
  #include "worktree.h"
  #include "lockfile.h"
 +#include "sequencer.h"
  
  static const char cut_line[] =
  "------------------------ >8 ------------------------\n";
@@@ -1215,9 -1214,7 +1215,9 @@@ static void abbrev_sha1_in_line(struct 
        int i;
  
        if (starts_with(line->buf, "exec ") ||
 -          starts_with(line->buf, "x "))
 +          starts_with(line->buf, "x ") ||
 +          starts_with(line->buf, "label ") ||
 +          starts_with(line->buf, "l "))
                return;
  
        split = strbuf_split_max(line, ' ', 3);
@@@ -1389,22 -1386,12 +1389,22 @@@ static void show_rebase_in_progress(str
  static void show_cherry_pick_in_progress(struct wt_status *s,
                                         const char *color)
  {
 -      status_printf_ln(s, color, _("You are currently cherry-picking commit %s."),
 -                      find_unique_abbrev(&s->state.cherry_pick_head_oid, DEFAULT_ABBREV));
 +      if (is_null_oid(&s->state.cherry_pick_head_oid))
 +              status_printf_ln(s, color,
 +                      _("Cherry-pick currently in progress."));
 +      else
 +              status_printf_ln(s, color,
 +                      _("You are currently cherry-picking commit %s."),
 +                      find_unique_abbrev(&s->state.cherry_pick_head_oid,
 +                                         DEFAULT_ABBREV));
 +
        if (s->hints) {
                if (has_unmerged(s))
                        status_printf_ln(s, color,
                                _("  (fix conflicts and run \"git cherry-pick --continue\")"));
 +              else if (is_null_oid(&s->state.cherry_pick_head_oid))
 +                      status_printf_ln(s, color,
 +                              _("  (run \"git cherry-pick --continue\" to continue)"));
                else
                        status_printf_ln(s, color,
                                _("  (all conflicts fixed: run \"git cherry-pick --continue\")"));
  static void show_revert_in_progress(struct wt_status *s,
                                    const char *color)
  {
 -      status_printf_ln(s, color, _("You are currently reverting commit %s."),
 -                       find_unique_abbrev(&s->state.revert_head_oid, DEFAULT_ABBREV));
 +      if (is_null_oid(&s->state.revert_head_oid))
 +              status_printf_ln(s, color,
 +                      _("Revert currently in progress."));
 +      else
 +              status_printf_ln(s, color,
 +                      _("You are currently reverting commit %s."),
 +                      find_unique_abbrev(&s->state.revert_head_oid,
 +                                         DEFAULT_ABBREV));
        if (s->hints) {
                if (has_unmerged(s))
                        status_printf_ln(s, color,
                                _("  (fix conflicts and run \"git revert --continue\")"));
 +              else if (is_null_oid(&s->state.revert_head_oid))
 +                      status_printf_ln(s, color,
 +                              _("  (run \"git revert --continue\" to continue)"));
                else
                        status_printf_ln(s, color,
                                _("  (all conflicts fixed: run \"git revert --continue\")"));
@@@ -1602,7 -1580,6 +1602,7 @@@ void wt_status_get_state(struct reposit
  {
        struct stat st;
        struct object_id oid;
 +      enum replay_action action;
  
        if (!stat(git_path_merge_head(r), &st)) {
                wt_status_check_rebase(NULL, state);
                state->revert_in_progress = 1;
                oidcpy(&state->revert_head_oid, &oid);
        }
 -
 +      if (!sequencer_get_last_command(r, &action)) {
 +              if (action == REPLAY_PICK) {
 +                      state->cherry_pick_in_progress = 1;
 +                      oidcpy(&state->cherry_pick_head_oid, &null_oid);
 +              } else {
 +                      state->revert_in_progress = 1;
 +                      oidcpy(&state->revert_head_oid, &null_oid);
 +              }
 +      }
        if (get_detached_from)
                wt_status_get_detached_from(r, state);
  }
@@@ -2076,9 -2045,7 +2076,7 @@@ static void wt_porcelain_v2_submodule_s
  /*
   * Fix-up changed entries before we print them.
   */
- static void wt_porcelain_v2_fix_up_changed(
-       struct string_list_item *it,
-       struct wt_status *s)
+ static void wt_porcelain_v2_fix_up_changed(struct string_list_item *it)
  {
        struct wt_status_change_data *d = it->util;
  
@@@ -2138,7 -2105,7 +2136,7 @@@ static void wt_porcelain_v2_print_chang
        char submodule_token[5];
        char sep_char, eol_char;
  
-       wt_porcelain_v2_fix_up_changed(it, s);
+       wt_porcelain_v2_fix_up_changed(it);
        wt_porcelain_v2_submodule_state(d, submodule_token);
  
        key[0] = d->index_status ? d->index_status : '.';