Merge branch 'nd/the-index' into md/list-objects-filter-by-depth
authorJunio C Hamano <gitster@pobox.com>
Fri, 28 Dec 2018 18:41:41 +0000 (10:41 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 15 Jan 2019 23:38:29 +0000 (15:38 -0800)
23 files changed:
1  2 
builtin/am.c
builtin/commit.c
builtin/fsck.c
builtin/merge.c
builtin/notes.c
builtin/pack-objects.c
builtin/pull.c
builtin/push.c
builtin/read-tree.c
builtin/rebase.c
builtin/rerere.c
builtin/reset.c
bundle.c
combine-diff.c
diff.c
diffcore-pickaxe.c
grep.c
pack-objects.h
read-cache.c
ref-filter.c
sequencer.c
sequencer.h
wt-status.c
diff --combined builtin/am.c
index 8f27f3375b1e92f2ef026e0a1530ca8b6b3235bf,f0eeec82a9ed499082d2d549e6350bda47138cb2..95370313b66daad8cabcc3b855136e29afb3133f
@@@ -260,6 -260,32 +260,6 @@@ static int read_state_file(struct strbu
        die_errno(_("could not read '%s'"), am_path(state, file));
  }
  
 -/**
 - * Take a series of KEY='VALUE' lines where VALUE part is
 - * sq-quoted, and append <KEY, VALUE> at the end of the string list
 - */
 -static int parse_key_value_squoted(char *buf, struct string_list *list)
 -{
 -      while (*buf) {
 -              struct string_list_item *item;
 -              char *np;
 -              char *cp = strchr(buf, '=');
 -              if (!cp)
 -                      return -1;
 -              np = strchrnul(cp, '\n');
 -              *cp++ = '\0';
 -              item = string_list_append(list, buf);
 -
 -              buf = np + (*np == '\n');
 -              *np = '\0';
 -              cp = sq_dequote(cp);
 -              if (!cp)
 -                      return -1;
 -              item->util = xstrdup(cp);
 -      }
 -      return 0;
 -}
 -
  /**
   * Reads and parses the state directory's "author-script" file, and sets
   * state->author_name, state->author_email and state->author_date accordingly.
   * script, and thus if the file differs from what this function expects, it is
   * better to bail out than to do something that the user does not expect.
   */
 -static int read_author_script(struct am_state *state)
 +static int read_am_author_script(struct am_state *state)
  {
        const char *filename = am_path(state, "author-script");
 -      struct strbuf buf = STRBUF_INIT;
 -      struct string_list kv = STRING_LIST_INIT_DUP;
 -      int retval = -1; /* assume failure */
 -      int fd;
  
        assert(!state->author_name);
        assert(!state->author_email);
        assert(!state->author_date);
  
 -      fd = open(filename, O_RDONLY);
 -      if (fd < 0) {
 -              if (errno == ENOENT)
 -                      return 0;
 -              die_errno(_("could not open '%s' for reading"), filename);
 -      }
 -      strbuf_read(&buf, fd, 0);
 -      close(fd);
 -      if (parse_key_value_squoted(buf.buf, &kv))
 -              goto finish;
 -
 -      if (kv.nr != 3 ||
 -          strcmp(kv.items[0].string, "GIT_AUTHOR_NAME") ||
 -          strcmp(kv.items[1].string, "GIT_AUTHOR_EMAIL") ||
 -          strcmp(kv.items[2].string, "GIT_AUTHOR_DATE"))
 -              goto finish;
 -      state->author_name = kv.items[0].util;
 -      state->author_email = kv.items[1].util;
 -      state->author_date = kv.items[2].util;
 -      retval = 0;
 -finish:
 -      string_list_clear(&kv, !!retval);
 -      strbuf_release(&buf);
 -      return retval;
 +      return read_author_script(filename, &state->author_name,
 +                                &state->author_email, &state->author_date, 1);
  }
  
  /**
@@@ -359,7 -411,7 +359,7 @@@ static void am_load(struct am_state *st
                BUG("state file 'last' does not exist");
        state->last = strtol(sb.buf, NULL, 10);
  
 -      if (read_author_script(state) < 0)
 +      if (read_am_author_script(state) < 0)
                die(_("could not parse author script"));
  
        read_commit_msg(state);
@@@ -1970,7 -2022,7 +1970,7 @@@ static int clean_index(const struct obj
        if (merge_tree(remote_tree))
                return -1;
  
-       remove_branch_state();
+       remove_branch_state(the_repository);
  
        return 0;
  }
  static void am_rerere_clear(void)
  {
        struct string_list merge_rr = STRING_LIST_INIT_DUP;
-       rerere_clear(&merge_rr);
+       rerere_clear(the_repository, &merge_rr);
        string_list_clear(&merge_rr, 1);
  }
  
@@@ -2113,9 -2165,7 +2113,9 @@@ static int parse_opt_patchformat(const 
  {
        int *opt_value = opt->value;
  
 -      if (!strcmp(arg, "mbox"))
 +      if (unset)
 +              *opt_value = PATCH_FORMAT_UNKNOWN;
 +      else if (!strcmp(arg, "mbox"))
                *opt_value = PATCH_FORMAT_MBOX;
        else if (!strcmp(arg, "stgit"))
                *opt_value = PATCH_FORMAT_STGIT;
diff --combined builtin/commit.c
index c021b119bb9df106ab7a860e032ea5dd35529401,91b19202557b5c1a23dbc11a2a447b8e1388a032..004b816635bf1628bfe7697f737a22cbcd27622b
@@@ -161,9 -161,6 +161,9 @@@ static int opt_parse_m(const struct opt
  static int opt_parse_rename_score(const struct option *opt, const char *arg, int unset)
  {
        const char **value = opt->value;
 +
 +      BUG_ON_OPT_NEG(unset);
 +
        if (arg != NULL && *arg == '=')
                arg = arg + 1;
  
@@@ -188,7 -185,7 +188,7 @@@ static void determine_whence(struct wt_
  
  static void status_init_config(struct wt_status *s, config_fn_t fn)
  {
-       wt_status_prepare(s);
+       wt_status_prepare(the_repository, s);
        init_diff_ui_defaults();
        git_config(fn, s);
        determine_whence(s);
@@@ -911,7 -908,8 +911,8 @@@ static int prepare_to_commit(const cha
                        if (ignore_submodule_arg &&
                            !strcmp(ignore_submodule_arg, "all"))
                                flags.ignore_submodules = 1;
-                       committable = index_differs_from(parent, &flags, 1);
+                       committable = index_differs_from(the_repository,
+                                                        parent, &flags, 1);
                }
        }
        strbuf_release(&committer_ident);
@@@ -1338,7 -1336,7 +1339,7 @@@ int cmd_status(int argc, const char **a
                OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")),
                { OPTION_CALLBACK, 'M', "find-renames", &rename_score_arg,
                  N_("n"), N_("detect renames, optionally set similarity index"),
 -                PARSE_OPT_OPTARG, opt_parse_rename_score },
 +                PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_rename_score },
                OPT_END(),
        };
  
        if (status_format != STATUS_FORMAT_PORCELAIN &&
            status_format != STATUS_FORMAT_PORCELAIN_V2)
                progress_flag = REFRESH_PROGRESS;
 -      read_index_preload(&the_index, &s.pathspec, progress_flag);
 +      read_index(&the_index);
        refresh_index(&the_index,
                      REFRESH_QUIET|REFRESH_UNMERGED|progress_flag,
                      &s.pathspec, NULL, NULL);
@@@ -1682,7 -1680,8 +1683,8 @@@ int cmd_commit(int argc, const char **a
                        flags |= SUMMARY_INITIAL_COMMIT;
                if (author_date_is_interesting())
                        flags |= SUMMARY_SHOW_AUTHOR_DATE;
-               print_commit_summary(prefix, &oid, flags);
+               print_commit_summary(the_repository, prefix,
+                                    &oid, flags);
        }
  
        UNLEAK(err);
diff --combined builtin/fsck.c
index 967341e1d3ad9b4c7caba8ba36bc9f2e485c6b02,8ea2823864f7071ec835beec90eb6025a20eaf64..22d9ef92efce95b56bdecc004ad50a788c69111e
@@@ -19,7 -19,6 +19,7 @@@
  #include "packfile.h"
  #include "object-store.h"
  #include "run-command.h"
 +#include "worktree.h"
  
  #define REACHABLE 0x0001
  #define SEEN      0x0002
@@@ -37,6 -36,8 +37,6 @@@ static int check_strict
  static int keep_cache_objects;
  static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT;
  static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT;
 -static struct object_id head_oid;
 -static const char *head_points_at;
  static int errors_found;
  static int write_lost_and_found;
  static int verbose;
@@@ -381,8 -382,7 +381,8 @@@ out
        if (obj->type == OBJ_TREE)
                free_tree_buffer((struct tree *)obj);
        if (obj->type == OBJ_COMMIT)
 -              free_commit_buffer((struct commit *)obj);
 +              free_commit_buffer(the_repository->parsed_objects,
 +                                 (struct commit *)obj);
        return err;
  }
  
@@@ -446,11 -446,7 +446,11 @@@ static int fsck_handle_reflog_ent(struc
  static int fsck_handle_reflog(const char *logname, const struct object_id *oid,
                              int flag, void *cb_data)
  {
 -      for_each_reflog_ent(logname, fsck_handle_reflog_ent, (void *)logname);
 +      struct strbuf refname = STRBUF_INIT;
 +
 +      strbuf_worktree_ref(cb_data, &refname, logname);
 +      for_each_reflog_ent(refname.buf, fsck_handle_reflog_ent, refname.buf);
 +      strbuf_release(&refname);
        return 0;
  }
  
@@@ -488,34 -484,13 +488,34 @@@ static int fsck_handle_ref(const char *
        return 0;
  }
  
 +static int fsck_head_link(const char *head_ref_name,
 +                        const char **head_points_at,
 +                        struct object_id *head_oid);
 +
  static void get_default_heads(void)
  {
 -      if (head_points_at && !is_null_oid(&head_oid))
 -              fsck_handle_ref("HEAD", &head_oid, 0, NULL);
 +      struct worktree **worktrees, **p;
 +      const char *head_points_at;
 +      struct object_id head_oid;
 +
        for_each_rawref(fsck_handle_ref, NULL);
 -      if (include_reflogs)
 -              for_each_reflog(fsck_handle_reflog, NULL);
 +
 +      worktrees = get_worktrees(0);
 +      for (p = worktrees; *p; p++) {
 +              struct worktree *wt = *p;
 +              struct strbuf ref = STRBUF_INIT;
 +
 +              strbuf_worktree_ref(wt, &ref, "HEAD");
 +              fsck_head_link(ref.buf, &head_points_at, &head_oid);
 +              if (head_points_at && !is_null_oid(&head_oid))
 +                      fsck_handle_ref(ref.buf, &head_oid, 0, NULL);
 +              strbuf_release(&ref);
 +
 +              if (include_reflogs)
 +                      refs_for_each_reflog(get_worktree_ref_store(wt),
 +                                           fsck_handle_reflog, wt);
 +      }
 +      free_worktrees(worktrees);
  
        /*
         * Not having any default heads isn't really fatal, but
@@@ -604,36 -579,33 +604,36 @@@ static void fsck_object_dir(const char 
        stop_progress(&progress);
  }
  
 -static int fsck_head_link(void)
 +static int fsck_head_link(const char *head_ref_name,
 +                        const char **head_points_at,
 +                        struct object_id *head_oid)
  {
        int null_is_error = 0;
  
        if (verbose)
 -              fprintf(stderr, "Checking HEAD link\n");
 +              fprintf(stderr, "Checking %s link\n", head_ref_name);
  
 -      head_points_at = resolve_ref_unsafe("HEAD", 0, &head_oid, NULL);
 -      if (!head_points_at) {
 +      *head_points_at = resolve_ref_unsafe(head_ref_name, 0, head_oid, NULL);
 +      if (!*head_points_at) {
                errors_found |= ERROR_REFS;
 -              return error("Invalid HEAD");
 +              return error("Invalid %s", head_ref_name);
        }
 -      if (!strcmp(head_points_at, "HEAD"))
 +      if (!strcmp(*head_points_at, head_ref_name))
                /* detached HEAD */
                null_is_error = 1;
 -      else if (!starts_with(head_points_at, "refs/heads/")) {
 +      else if (!starts_with(*head_points_at, "refs/heads/")) {
                errors_found |= ERROR_REFS;
 -              return error("HEAD points to something strange (%s)",
 -                           head_points_at);
 +              return error("%s points to something strange (%s)",
 +                           head_ref_name, *head_points_at);
        }
 -      if (is_null_oid(&head_oid)) {
 +      if (is_null_oid(head_oid)) {
                if (null_is_error) {
                        errors_found |= ERROR_REFS;
 -                      return error("HEAD: detached HEAD points at nothing");
 +                      return error("%s: detached HEAD points at nothing",
 +                                   head_ref_name);
                }
 -              fprintf(stderr, "notice: HEAD points to an unborn branch (%s)\n",
 -                      head_points_at + 11);
 +              fprintf(stderr, "notice: %s points to an unborn branch (%s)\n",
 +                      head_ref_name, *head_points_at + 11);
        }
        return 0;
  }
@@@ -748,6 -720,7 +748,6 @@@ int cmd_fsck(int argc, const char **arg
  
        git_config(fsck_config, NULL);
  
 -      fsck_head_link();
        if (connectivity_only) {
                for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
                for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
                        for (p = get_all_packs(the_repository); p;
                             p = p->next) {
                                /* verify gives error messages itself */
-                               if (verify_pack(p, fsck_obj_buffer,
+                               if (verify_pack(the_repository,
+                                               p, fsck_obj_buffer,
                                                progress, count))
                                        errors_found |= ERROR_PACK;
                                count += p->num_objects;
diff --combined builtin/merge.c
index c3c976d471ce78268e673a5135a4c37ebc6d0f6d,db22119c93c4d2a629ae8f07801270547dab659c..13afa47b14a3b581e43b7751803fb9b96d199fee
@@@ -224,7 -224,6 +224,7 @@@ static int option_parse_x(const struct 
  static int option_parse_n(const struct option *opt,
                          const char *arg, int unset)
  {
 +      BUG_ON_OPT_ARG(arg);
        show_diffstat = unset;
        return 0;
  }
@@@ -897,7 -896,7 +897,7 @@@ static int suggest_conflicts(void
        filename = git_path_merge_msg(the_repository);
        fp = xfopen(filename, "a");
  
-       append_conflicts_hint(&msgbuf);
+       append_conflicts_hint(&the_index, &msgbuf);
        fputs(msgbuf.buf, fp);
        strbuf_release(&msgbuf);
        fclose(fp);
@@@ -1337,10 -1336,6 +1337,10 @@@ int cmd_merge(int argc, const char **ar
                        die(_("%s - not something we can merge"), argv[0]);
                if (remoteheads->next)
                        die(_("Can merge only exactly one commit into empty head"));
 +
 +              if (verify_signatures)
 +                      verify_merge_signature(remoteheads->item, verbosity);
 +
                remote_head_oid = &remoteheads->item->object.oid;
                read_empty(remote_head_oid, 0);
                update_ref("initial pull", "HEAD", remote_head_oid, NULL, 0,
  
        if (verify_signatures) {
                for (p = remoteheads; p; p = p->next) {
 -                      struct commit *commit = p->item;
 -                      char hex[GIT_MAX_HEXSZ + 1];
 -                      struct signature_check signature_check;
 -                      memset(&signature_check, 0, sizeof(signature_check));
 -
 -                      check_commit_signature(commit, &signature_check);
 -
 -                      find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
 -                      switch (signature_check.result) {
 -                      case 'G':
 -                              break;
 -                      case 'U':
 -                              die(_("Commit %s has an untrusted GPG signature, "
 -                                    "allegedly by %s."), hex, signature_check.signer);
 -                      case 'B':
 -                              die(_("Commit %s has a bad GPG signature "
 -                                    "allegedly by %s."), hex, signature_check.signer);
 -                      default: /* 'N' */
 -                              die(_("Commit %s does not have a GPG signature."), hex);
 -                      }
 -                      if (verbosity >= 0 && signature_check.result == 'G')
 -                              printf(_("Commit %s has a good GPG signature by %s\n"),
 -                                     hex, signature_check.signer);
 -
 -                      signature_check_clear(&signature_check);
 +                      verify_merge_signature(p->item, verbosity);
                }
        }
  
diff --combined builtin/notes.c
index c78b7a0c5b7fbea81320ae9873553c437d82e73e,15a6c78855b4eeb704f1f90d1d0e881656e81a2c..4996a670f71333de09e1a0311fde85d6985c9c91
@@@ -215,8 -215,6 +215,8 @@@ static int parse_msg_arg(const struct o
  {
        struct note_data *d = opt->value;
  
 +      BUG_ON_OPT_NEG(unset);
 +
        strbuf_grow(&d->buf, strlen(arg) + 2);
        if (d->buf.len)
                strbuf_addch(&d->buf, '\n');
@@@ -231,8 -229,6 +231,8 @@@ static int parse_file_arg(const struct 
  {
        struct note_data *d = opt->value;
  
 +      BUG_ON_OPT_NEG(unset);
 +
        if (d->buf.len)
                strbuf_addch(&d->buf, '\n');
        if (!strcmp(arg, "-")) {
@@@ -254,15 -250,15 +254,15 @@@ static int parse_reuse_arg(const struc
        enum object_type type;
        unsigned long len;
  
 +      BUG_ON_OPT_NEG(unset);
 +
        if (d->buf.len)
                strbuf_addch(&d->buf, '\n');
  
        if (get_oid(arg, &object))
                die(_("failed to resolve '%s' as a valid ref."), arg);
 -      if (!(buf = read_object_file(&object, &type, &len))) {
 -              free(buf);
 +      if (!(buf = read_object_file(&object, &type, &len)))
                die(_("failed to read object '%s'."), arg);
 -      }
        if (type != OBJ_BLOB) {
                free(buf);
                die(_("cannot read note data from non-blob object '%s'."), arg);
  static int parse_reedit_arg(const struct option *opt, const char *arg, int unset)
  {
        struct note_data *d = opt->value;
 +      BUG_ON_OPT_NEG(unset);
        d->use_editor = 1;
        return parse_reuse_arg(opt, arg, unset);
  }
@@@ -813,7 -808,7 +813,7 @@@ static int merge(int argc, const char *
                usage_with_options(git_notes_merge_usage, options);
        }
  
-       init_notes_merge_options(&o);
+       init_notes_merge_options(the_repository, &o);
        o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT;
  
        if (do_abort)
diff --combined builtin/pack-objects.c
index 411aefd6875b2d35ee4a12d1a043ba50027021b3,8abfb69e2db06afd3eb4a3862e92b4f716f71ae5..24bba8147fc96ec2b124aa659c981af08e7a688d
@@@ -1953,6 -1953,8 +1953,6 @@@ static int delta_cacheable(unsigned lon
        return 0;
  }
  
 -#ifndef NO_PTHREADS
 -
  /* Protect access to object database */
  static pthread_mutex_t read_mutex;
  #define read_lock()           pthread_mutex_lock(&read_mutex)
@@@ -1977,6 -1979,16 +1977,6 @@@ static pthread_mutex_t progress_mutex
   * ahead in the list because they can be stolen and would need
   * progress_mutex for protection.
   */
 -#else
 -
 -#define read_lock()           (void)0
 -#define read_unlock()         (void)0
 -#define cache_lock()          (void)0
 -#define cache_unlock()                (void)0
 -#define progress_lock()               (void)0
 -#define progress_unlock()     (void)0
 -
 -#endif
  
  /*
   * Return the size of the object without doing any delta
@@@ -2083,9 -2095,9 +2083,9 @@@ static int try_delta(struct unpacked *t
                        die(_("object %s cannot be read"),
                            oid_to_hex(&trg_entry->idx.oid));
                if (sz != trg_size)
 -                      die(_("object %s inconsistent object length (%lu vs %lu)"),
 -                          oid_to_hex(&trg_entry->idx.oid), sz,
 -                          trg_size);
 +                      die(_("object %s inconsistent object length (%"PRIuMAX" vs %"PRIuMAX")"),
 +                          oid_to_hex(&trg_entry->idx.oid), (uintmax_t)sz,
 +                          (uintmax_t)trg_size);
                *mem_usage += sz;
        }
        if (!src->data) {
                            oid_to_hex(&src_entry->idx.oid));
                }
                if (sz != src_size)
 -                      die(_("object %s inconsistent object length (%lu vs %lu)"),
 -                          oid_to_hex(&src_entry->idx.oid), sz,
 -                          src_size);
 +                      die(_("object %s inconsistent object length (%"PRIuMAX" vs %"PRIuMAX")"),
 +                          oid_to_hex(&src_entry->idx.oid), (uintmax_t)sz,
 +                          (uintmax_t)src_size);
                *mem_usage += sz;
        }
        if (!src->index) {
@@@ -2335,6 -2347,8 +2335,6 @@@ static void find_deltas(struct object_e
        free(array);
  }
  
 -#ifndef NO_PTHREADS
 -
  static void try_to_free_from_threads(size_t size)
  {
        read_lock();
@@@ -2563,6 -2577,10 +2563,6 @@@ static void ll_find_deltas(struct objec
        free(p);
  }
  
 -#else
 -#define ll_find_deltas(l, s, w, d, p) find_deltas(l, &s, w, d, p)
 -#endif
 -
  static void add_tag_chain(const struct object_id *oid)
  {
        struct tag *tag;
@@@ -2610,7 -2628,7 +2610,7 @@@ static void prepare_pack(int window, in
        unsigned n;
  
        if (use_delta_islands)
-               resolve_tree_islands(progress, &to_pack);
+               resolve_tree_islands(the_repository, progress, &to_pack);
  
        get_object_details();
  
@@@ -2715,10 -2733,12 +2715,10 @@@ static int git_pack_config(const char *
                if (delta_search_threads < 0)
                        die(_("invalid number of threads specified (%d)"),
                            delta_search_threads);
 -#ifdef NO_PTHREADS
 -              if (delta_search_threads != 1) {
 +              if (!HAVE_THREADS && delta_search_threads != 1) {
                        warning(_("no threads support, ignoring %s"), k);
                        delta_search_threads = 0;
                }
 -#endif
                return 0;
        }
        if (!strcmp(k, "pack.indexversion")) {
@@@ -2786,11 -2806,9 +2786,11 @@@ static void show_object(struct object *
  
        if (use_delta_islands) {
                const char *p;
 -              unsigned depth = 0;
 +              unsigned depth;
                struct object_entry *ent;
  
 +              /* the empty string is a root tree, which is depth 0 */
 +              depth = *name ? 1 : 0;
                for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
                        depth++;
  
@@@ -3086,7 -3104,6 +3086,7 @@@ static void get_object_list(int ac, con
        struct rev_info revs;
        char line[1000];
        int flags = 0;
 +      int save_warning;
  
        repo_init_revisions(the_repository, &revs, NULL);
        save_commit_buffer = 0;
        /* make sure shallows are read */
        is_repository_shallow(the_repository);
  
 +      save_warning = warn_on_object_refname_ambiguity;
 +      warn_on_object_refname_ambiguity = 0;
 +
        while (fgets(line, sizeof(line), stdin) != NULL) {
                int len = strlen(line);
                if (len && line[len - 1] == '\n')
                        die(_("bad revision '%s'"), line);
        }
  
 +      warn_on_object_refname_ambiguity = save_warning;
 +
        if (use_bitmap_index && !get_object_list_from_bitmap(&revs))
                return;
  
        if (use_delta_islands)
-               load_delta_islands();
+               load_delta_islands(the_repository);
  
        if (prepare_revision_walk(&revs))
                die(_("revision walk setup failed"));
@@@ -3195,9 -3207,6 +3195,9 @@@ static int option_parse_index_version(c
  {
        char *c;
        const char *val = arg;
 +
 +      BUG_ON_OPT_NEG(unset);
 +
        pack_idx_opts.version = strtoul(val, &c, 10);
        if (pack_idx_opts.version > 2)
                die(_("unsupported index version %s"), val);
@@@ -3244,7 -3253,7 +3244,7 @@@ int cmd_pack_objects(int argc, const ch
                         N_("similar to --all-progress when progress meter is shown")),
                { OPTION_CALLBACK, 0, "index-version", NULL, N_("<version>[,<offset>]"),
                  N_("write the pack index file in the specified idx format version"),
 -                0, option_parse_index_version },
 +                PARSE_OPT_NONEG, option_parse_index_version },
                OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit,
                              N_("maximum size of each output pack file")),
                OPT_BOOL(0, "local", &local,
        if (!delta_search_threads)      /* --threads=0 means autodetect */
                delta_search_threads = online_cpus();
  
 -#ifdef NO_PTHREADS
 -      if (delta_search_threads != 1)
 +      if (!HAVE_THREADS && delta_search_threads != 1)
                warning(_("no threads support, ignoring --threads"));
 -#endif
        if (!pack_to_stdout && !pack_size_limit)
                pack_size_limit = pack_size_limit_cfg;
        if (pack_to_stdout && pack_size_limit)
                }
        }
  
-       prepare_packing_data(&to_pack);
+       prepare_packing_data(the_repository, &to_pack);
  
        if (progress)
                progress_state = start_progress(_("Enumerating objects"), 0);
diff --combined builtin/pull.c
index 1b90622b1311187612ef8b33995c92a6802eb343,6026ce1a694b7cb923828053ad8e737e018ec210..74808b94554a78e720128a721f21dc0d20dd839e
@@@ -557,17 -557,6 +557,17 @@@ static int run_fetch(const char *repo, 
  static int pull_into_void(const struct object_id *merge_head,
                const struct object_id *curr_head)
  {
 +      if (opt_verify_signatures) {
 +              struct commit *commit;
 +
 +              commit = lookup_commit(the_repository, merge_head);
 +              if (!commit)
 +                      die(_("unable to access commit %s"),
 +                          oid_to_hex(merge_head));
 +
 +              verify_merge_signature(commit, opt_verbosity);
 +      }
 +
        /*
         * Two-way merge: we treat the index as based on an empty tree,
         * and try to fast-forward to HEAD. This ensures we will not lose
@@@ -899,7 -888,8 +899,8 @@@ int cmd_pull(int argc, const char **arg
                        die(_("Updating an unborn branch with changes added to the index."));
  
                if (!autostash)
-                       require_clean_work_tree(N_("pull with rebase"),
+                       require_clean_work_tree(the_repository,
+                               N_("pull with rebase"),
                                _("please commit or stash them."), 1, 0);
  
                if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs))
diff --combined builtin/push.c
index 8bb8a0849ba90aff5d295acc3894b2034cbbdef2,efb3e38a8d5fe7c3219c2ed7f7ae4502a2c3f1ab..ee1e8420271d93620de98f74a7a515151a69cb23
@@@ -173,10 -173,10 +173,10 @@@ static NORETURN int die_push_simple(str
              "\n"
              "To push to the branch of the same name on the remote, use\n"
              "\n"
 -            "    git push %s %s\n"
 +            "    git push %s HEAD\n"
              "%s"),
            remote->name, short_upstream,
 -          remote->name, branch->name, advice_maybe);
 +          remote->name, advice_maybe);
  }
  
  static const char message_detached_head_die[] =
@@@ -355,7 -355,8 +355,8 @@@ static int push_with_options(struct tra
  
        if (verbosity > 0)
                fprintf(stderr, _("Pushing to %s\n"), transport->url);
-       err = transport_push(transport, rs, flags, &reject_reasons);
+       err = transport_push(the_repository, transport,
+                            rs, flags, &reject_reasons);
        if (err != 0) {
                fprintf(stderr, "%s", push_get_color(PUSH_COLOR_ERROR));
                error(_("failed to push some refs to '%s'"), transport->url);
diff --combined builtin/read-tree.c
index 183ee8c1e5d4de53d10e9ed00c624f615baf3fc9,c05c12d0340d736022d7dd7856ad0797c87abb05..ac255ad2c243192a9afd3b4578a2a501eb250aff
@@@ -44,7 -44,6 +44,7 @@@ static const char * const read_tree_usa
  static int index_output_cb(const struct option *opt, const char *arg,
                                 int unset)
  {
 +      BUG_ON_OPT_NEG(unset);
        set_alternate_index_output(arg);
        return 0;
  }
@@@ -55,8 -54,6 +55,8 @@@ static int exclude_per_directory_cb(con
        struct dir_struct *dir;
        struct unpack_trees_options *opts;
  
 +      BUG_ON_OPT_NEG(unset);
 +
        opts = (struct unpack_trees_options *)opt->value;
  
        if (opts->dir)
@@@ -258,7 -255,9 +258,9 @@@ int cmd_read_tree(int argc, const char 
         * what came from the tree.
         */
        if (nr_trees == 1 && !opts.prefix)
-               prime_cache_tree(&the_index, trees[0]);
+               prime_cache_tree(the_repository,
+                                the_repository->index,
+                                trees[0]);
  
        if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
                die("unable to write new index file");
diff --combined builtin/rebase.c
index b5c99ec10c200a5fccb293c0acadae80642f2808,bc07d932a55b5ed623a606a88d326f535f819489..00de70365ed41167c18e3233106e89d082370b6a
@@@ -23,7 -23,6 +23,7 @@@
  #include "revision.h"
  #include "commit-reach.h"
  #include "rerere.h"
 +#include "branch.h"
  
  static char const * const builtin_rebase_usage[] = {
        N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
@@@ -49,10 -48,7 +49,10 @@@ static int use_builtin_rebase(void
  {
        struct child_process cp = CHILD_PROCESS_INIT;
        struct strbuf out = STRBUF_INIT;
 -      int ret;
 +      int ret, env = git_env_bool("GIT_TEST_REBASE_USE_BUILTIN", -1);
 +
 +      if (env != -1)
 +              return env;
  
        argv_array_pushl(&cp.args,
                         "config", "--bool", "rebase.usebuiltin", NULL);
@@@ -91,7 -87,7 +91,7 @@@ struct rebase_options 
                REBASE_FORCE = 1<<3,
                REBASE_INTERACTIVE_EXPLICIT = 1<<4,
        } flags;
 -      struct strbuf git_am_opt;
 +      struct argv_array git_am_opts;
        const char *action;
        int signoff;
        int allow_rerere_autoupdate;
@@@ -343,7 -339,7 +343,7 @@@ N_("Resolve all conflicts manually, mar
  static int run_specific_rebase(struct rebase_options *opts)
  {
        const char *argv[] = { NULL, NULL };
 -      struct strbuf script_snippet = STRBUF_INIT;
 +      struct strbuf script_snippet = STRBUF_INIT, buf = STRBUF_INIT;
        int status;
        const char *backend, *backend_func;
  
                oid_to_hex(&opts->restrict_revision->object.oid) : NULL);
        add_var(&script_snippet, "GIT_QUIET",
                opts->flags & REBASE_NO_QUIET ? "" : "t");
 -      add_var(&script_snippet, "git_am_opt", opts->git_am_opt.buf);
 +      sq_quote_argv_pretty(&buf, opts->git_am_opts.argv);
 +      add_var(&script_snippet, "git_am_opt", buf.buf);
 +      strbuf_release(&buf);
        add_var(&script_snippet, "verbose",
                opts->flags & REBASE_VERBOSE ? "t" : "");
        add_var(&script_snippet, "diffstat",
@@@ -528,17 -522,12 +528,17 @@@ finished_rebase
  
  #define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
  
 +#define RESET_HEAD_DETACH (1<<0)
 +#define RESET_HEAD_HARD (1<<1)
 +
  static int reset_head(struct object_id *oid, const char *action,
 -                    const char *switch_to_branch, int detach_head,
 +                    const char *switch_to_branch, unsigned flags,
                      const char *reflog_orig_head, const char *reflog_head)
  {
 +      unsigned detach_head = flags & RESET_HEAD_DETACH;
 +      unsigned reset_hard = flags & RESET_HEAD_HARD;
        struct object_id head_oid;
 -      struct tree_desc desc;
 +      struct tree_desc desc[2] = { { NULL }, { NULL } };
        struct lock_file lock = LOCK_INIT;
        struct unpack_trees_options unpack_tree_opts;
        struct tree *tree;
        size_t prefix_len;
        struct object_id *orig = NULL, oid_orig,
                *old_orig = NULL, oid_old_orig;
 -      int ret = 0;
 +      int ret = 0, nr = 0;
  
        if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
                BUG("Not a fully qualified branch: '%s'", switch_to_branch);
  
 -      if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0)
 -              return -1;
 +      if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) {
 +              ret = -1;
 +              goto leave_reset_head;
 +      }
  
 -      if (!oid) {
 -              if (get_oid("HEAD", &head_oid)) {
 -                      rollback_lock_file(&lock);
 -                      return error(_("could not determine HEAD revision"));
 -              }
 -              oid = &head_oid;
 +      if ((!oid || !reset_hard) && get_oid("HEAD", &head_oid)) {
 +              ret = error(_("could not determine HEAD revision"));
 +              goto leave_reset_head;
        }
  
 +      if (!oid)
 +              oid = &head_oid;
 +
        memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
        setup_unpack_trees_porcelain(&unpack_tree_opts, action);
        unpack_tree_opts.head_idx = 1;
        unpack_tree_opts.src_index = the_repository->index;
        unpack_tree_opts.dst_index = the_repository->index;
 -      unpack_tree_opts.fn = oneway_merge;
 +      unpack_tree_opts.fn = reset_hard ? oneway_merge : twoway_merge;
        unpack_tree_opts.update = 1;
        unpack_tree_opts.merge = 1;
        if (!detach_head)
                unpack_tree_opts.reset = 1;
  
        if (read_index_unmerged(the_repository->index) < 0) {
 -              rollback_lock_file(&lock);
 -              return error(_("could not read index"));
 +              ret = error(_("could not read index"));
 +              goto leave_reset_head;
        }
  
 -      if (!fill_tree_descriptor(&desc, oid)) {
 -              error(_("failed to find tree of %s"), oid_to_hex(oid));
 -              rollback_lock_file(&lock);
 -              free((void *)desc.buffer);
 -              return -1;
 +      if (!reset_hard && !fill_tree_descriptor(&desc[nr++], &head_oid)) {
 +              ret = error(_("failed to find tree of %s"),
 +                          oid_to_hex(&head_oid));
 +              goto leave_reset_head;
        }
  
 -      if (unpack_trees(1, &desc, &unpack_tree_opts)) {
 -              rollback_lock_file(&lock);
 -              free((void *)desc.buffer);
 -              return -1;
 +      if (!fill_tree_descriptor(&desc[nr++], oid)) {
 +              ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
 +              goto leave_reset_head;
 +      }
 +
 +      if (unpack_trees(nr, desc, &unpack_tree_opts)) {
 +              ret = -1;
 +              goto leave_reset_head;
        }
  
        tree = parse_tree_indirect(oid);
-       prime_cache_tree(the_repository->index, tree);
+       prime_cache_tree(the_repository, the_repository->index, tree);
  
 -      if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0)
 +      if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0) {
                ret = error(_("could not write index"));
 -      free((void *)desc.buffer);
 -
 -      if (ret)
 -              return ret;
 +              goto leave_reset_head;
 +      }
  
        reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
        strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase");
                reflog_head = msg.buf;
        }
        if (!switch_to_branch)
 -              ret = update_ref(reflog_head, "HEAD", oid, orig, REF_NO_DEREF,
 +              ret = update_ref(reflog_head, "HEAD", oid, orig,
 +                               detach_head ? REF_NO_DEREF : 0,
                                 UPDATE_REFS_MSG_ON_ERR);
        else {
                ret = create_symref("HEAD", switch_to_branch, msg.buf);
                                         UPDATE_REFS_MSG_ON_ERR);
        }
  
 +leave_reset_head:
        strbuf_release(&msg);
 +      rollback_lock_file(&lock);
 +      while (nr)
 +              free((void *)desc[--nr].buffer);
        return ret;
  }
  
@@@ -722,9 -703,6 +722,9 @@@ static int parse_opt_merge(const struc
  {
        struct rebase_options *opts = opt->value;
  
 +      BUG_ON_OPT_NEG(unset);
 +      BUG_ON_OPT_ARG(arg);
 +
        if (!is_interactive(opts))
                opts->type = REBASE_MERGE;
  
@@@ -737,9 -715,6 +737,9 @@@ static int parse_opt_interactive(const 
  {
        struct rebase_options *opts = opt->value;
  
 +      BUG_ON_OPT_NEG(unset);
 +      BUG_ON_OPT_ARG(arg);
 +
        opts->type = REBASE_INTERACTIVE;
        opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
  
@@@ -776,29 -751,12 +776,29 @@@ static void NORETURN error_on_missing_d
        exit(1);
  }
  
 +static void set_reflog_action(struct rebase_options *options)
 +{
 +      const char *env;
 +      struct strbuf buf = STRBUF_INIT;
 +
 +      if (!is_interactive(options))
 +              return;
 +
 +      env = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
 +      if (env && strcmp("rebase", env))
 +              return; /* only override it if it is "rebase" */
 +
 +      strbuf_addf(&buf, "rebase -i (%s)", options->action);
 +      setenv(GIT_REFLOG_ACTION_ENVIRONMENT, buf.buf, 1);
 +      strbuf_release(&buf);
 +}
 +
  int cmd_rebase(int argc, const char **argv, const char *prefix)
  {
        struct rebase_options options = {
                .type = REBASE_UNSPECIFIED,
                .flags = REBASE_NO_QUIET,
 -              .git_am_opt = STRBUF_INIT,
 +              .git_am_opts = ARGV_ARRAY_INIT,
                .allow_rerere_autoupdate  = -1,
                .allow_empty_message = 1,
                .git_format_patch_opt = STRBUF_INIT,
                ACTION_EDIT_TODO,
                ACTION_SHOW_CURRENT_PATCH,
        } action = NO_ACTION;
 -      int committer_date_is_author_date = 0;
 -      int ignore_date = 0;
 -      int ignore_whitespace = 0;
        const char *gpg_sign = NULL;
 -      int opt_c = -1;
 -      struct string_list whitespace = STRING_LIST_INIT_NODUP;
        struct string_list exec = STRING_LIST_INIT_NODUP;
        const char *rebase_merges = NULL;
        int fork_point = -1;
                {OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL,
                        N_("do not show diffstat of what changed upstream"),
                        PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 -              OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
 -                       N_("passed to 'git apply'")),
                OPT_BOOL(0, "signoff", &options.signoff,
                         N_("add a Signed-off-by: line to each commit")),
 -              OPT_BOOL(0, "committer-date-is-author-date",
 -                       &committer_date_is_author_date,
 -                       N_("passed to 'git am'")),
 -              OPT_BOOL(0, "ignore-date", &ignore_date,
 -                       N_("passed to 'git am'")),
 +              OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
 +                                NULL, N_("passed to 'git am'"),
 +                                PARSE_OPT_NOARG),
 +              OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 +                                &options.git_am_opts, NULL,
 +                                N_("passed to 'git am'"), PARSE_OPT_NOARG),
 +              OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 +                                N_("passed to 'git am'"), PARSE_OPT_NOARG),
 +              OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 +                                N_("passed to 'git apply'"), 0),
 +              OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 +                                N_("action"), N_("passed to 'git apply'"), 0),
                OPT_BIT('f', "force-rebase", &options.flags,
                        N_("cherry-pick all commits, even if unchanged"),
                        REBASE_FORCE),
                               "them"), REBASE_PRESERVE_MERGES),
                OPT_BOOL(0, "rerere-autoupdate",
                         &options.allow_rerere_autoupdate,
 -                       N_("allow rerere to update index  with resolved "
 +                       N_("allow rerere to update index with resolved "
                            "conflict")),
                OPT_BOOL('k', "keep-empty", &options.keep_empty,
                         N_("preserve empty commits during rebase")),
                { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
                        N_("GPG-sign commits"),
                        PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 -              OPT_STRING_LIST(0, "whitespace", &whitespace,
 -                              N_("whitespace"), N_("passed to 'git apply'")),
 -              OPT_SET_INT('C', NULL, &opt_c, N_("passed to 'git apply'"),
 -                          REBASE_AM),
                OPT_BOOL(0, "autostash", &options.autostash,
                         N_("automatically stash/stash pop before and after")),
                OPT_STRING_LIST('x', "exec", &exec, N_("exec"),
                         N_("rebase all reachable commits up to the root(s)")),
                OPT_END(),
        };
 +      int i;
  
        /*
         * NEEDSWORK: Once the builtin rebase has been tested enough
  
        if (action != NO_ACTION && !in_progress)
                die(_("No rebase in progress?"));
 +      setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
  
        if (action == ACTION_EDIT_TODO && !is_interactive(&options))
                die(_("The --edit-todo action can only be used during "
                int fd;
  
                options.action = "continue";
 +              set_reflog_action(&options);
  
                /* Sanity check */
                if (get_oid("HEAD", &head))
                                             &lock_file);
                rollback_lock_file(&lock_file);
  
-               if (has_unstaged_changes(1)) {
+               if (has_unstaged_changes(the_repository, 1)) {
                        puts(_("You must edit all merge conflicts and then\n"
                               "mark them as resolved using git add"));
                        exit(1);
                struct string_list merge_rr = STRING_LIST_INIT_DUP;
  
                options.action = "skip";
 +              set_reflog_action(&options);
  
-               rerere_clear(&merge_rr);
+               rerere_clear(the_repository, &merge_rr);
                string_list_clear(&merge_rr, 1);
  
 -              if (reset_head(NULL, "reset", NULL, 0, NULL, NULL) < 0)
 +              if (reset_head(NULL, "reset", NULL, RESET_HEAD_HARD,
 +                             NULL, NULL) < 0)
                        die(_("could not discard worktree changes"));
-               remove_branch_state();
++              remove_branch_state(the_repository);
                if (read_basic_state(&options))
                        exit(1);
                goto run_rebase;
        case ACTION_ABORT: {
                struct string_list merge_rr = STRING_LIST_INIT_DUP;
                options.action = "abort";
 +              set_reflog_action(&options);
  
-               rerere_clear(&merge_rr);
+               rerere_clear(the_repository, &merge_rr);
                string_list_clear(&merge_rr, 1);
  
                if (read_basic_state(&options))
                        exit(1);
                if (reset_head(&options.orig_head, "reset",
 -                             options.head_name, 0, NULL, NULL) < 0)
 +                             options.head_name, RESET_HEAD_HARD,
 +                             NULL, NULL) < 0)
                        die(_("could not move back to %s"),
                            oid_to_hex(&options.orig_head));
-               remove_branch_state();
++              remove_branch_state(the_repository);
                ret = finish_rebase(&options);
                goto cleanup;
        }
                    state_dir_base, cmd_live_rebase, buf.buf);
        }
  
 -      if (!(options.flags & REBASE_NO_QUIET))
 -              strbuf_addstr(&options.git_am_opt, " -q");
 -
 -      if (committer_date_is_author_date) {
 -              strbuf_addstr(&options.git_am_opt,
 -                            " --committer-date-is-author-date");
 -              options.flags |= REBASE_FORCE;
 +      for (i = 0; i < options.git_am_opts.argc; i++) {
 +              const char *option = options.git_am_opts.argv[i], *p;
 +              if (!strcmp(option, "--committer-date-is-author-date") ||
 +                  !strcmp(option, "--ignore-date") ||
 +                  !strcmp(option, "--whitespace=fix") ||
 +                  !strcmp(option, "--whitespace=strip"))
 +                      options.flags |= REBASE_FORCE;
 +              else if (skip_prefix(option, "-C", &p)) {
 +                      while (*p)
 +                              if (!isdigit(*(p++)))
 +                                      die(_("switch `C' expects a "
 +                                            "numerical value"));
 +              } else if (skip_prefix(option, "--whitespace=", &p)) {
 +                      if (*p && strcmp(p, "warn") && strcmp(p, "nowarn") &&
 +                          strcmp(p, "error") && strcmp(p, "error-all"))
 +                              die("Invalid whitespace option: '%s'", p);
 +              }
        }
  
 -      if (ignore_whitespace)
 -              strbuf_addstr(&options.git_am_opt, " --ignore-whitespace");
 -
 -      if (ignore_date) {
 -              strbuf_addstr(&options.git_am_opt, " --ignore-date");
 -              options.flags |= REBASE_FORCE;
 -      }
 +      if (!(options.flags & REBASE_NO_QUIET))
 +              argv_array_push(&options.git_am_opts, "-q");
  
        if (options.keep_empty)
                imply_interactive(&options, "--keep-empty");
                options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
        }
  
 -      if (opt_c >= 0)
 -              strbuf_addf(&options.git_am_opt, " -C%d", opt_c);
 -
 -      if (whitespace.nr) {
 -              int i;
 -
 -              for (i = 0; i < whitespace.nr; i++) {
 -                      const char *item = whitespace.items[i].string;
 -
 -                      strbuf_addf(&options.git_am_opt, " --whitespace=%s",
 -                                  item);
 -
 -                      if ((!strcmp(item, "fix")) || (!strcmp(item, "strip")))
 -                              options.flags |= REBASE_FORCE;
 -              }
 -      }
 -
        if (exec.nr) {
                int i;
  
                break;
        }
  
 -      if (options.git_am_opt.len) {
 -              const char *p;
 -
 +      if (options.git_am_opts.argc) {
                /* all am options except -q are compatible only with --am */
 -              strbuf_reset(&buf);
 -              strbuf_addbuf(&buf, &options.git_am_opt);
 -              strbuf_addch(&buf, ' ');
 -              while ((p = strstr(buf.buf, " -q ")))
 -                      strbuf_splice(&buf, p - buf.buf, 4, " ", 1);
 -              strbuf_trim(&buf);
 +              for (i = options.git_am_opts.argc - 1; i >= 0; i--)
 +                      if (strcmp(options.git_am_opts.argv[i], "-q"))
 +                              break;
  
 -              if (is_interactive(&options) && buf.len)
 +              if (is_interactive(&options) && i >= 0)
                        die(_("error: cannot combine interactive options "
                              "(--interactive, --exec, --rebase-merges, "
                              "--preserve-merges, --keep-empty, --root + "
                              "--onto) with am options (%s)"), buf.buf);
 -              if (options.type == REBASE_MERGE && buf.len)
 +              if (options.type == REBASE_MERGE && i >= 0)
                        die(_("error: cannot combine merge options (--merge, "
                              "--strategy, --strategy-option) with am options "
                              "(%s)"), buf.buf);
                if (options.type == REBASE_PRESERVE_MERGES)
                        die("cannot combine '--signoff' with "
                            "'--preserve-merges'");
 -              strbuf_addstr(&options.git_am_opt, " --signoff");
 +              argv_array_push(&options.git_am_opts, "--signoff");
                options.flags |= REBASE_FORCE;
        }
  
                        update_index_if_able(&the_index, &lock_file);
                rollback_lock_file(&lock_file);
  
-               if (has_unstaged_changes(1) || has_uncommitted_changes(1)) {
+               if (has_unstaged_changes(the_repository, 1) ||
+                   has_uncommitted_changes(the_repository, 1)) {
                        const char *autostash =
                                state_dir_path("autostash", &options);
                        struct child_process stash = CHILD_PROCESS_INIT;
                        write_file(autostash, "%s", oid_to_hex(&oid));
                        printf(_("Created autostash: %s\n"), buf.buf);
                        if (reset_head(&head->object.oid, "reset --hard",
 -                                     NULL, 0, NULL, NULL) < 0)
 +                                     NULL, RESET_HEAD_HARD, NULL, NULL) < 0)
                                die(_("could not reset --hard"));
                        printf(_("HEAD is now at %s"),
                               find_unique_abbrev(&head->object.oid,
                }
        }
  
-       if (require_clean_work_tree("rebase",
+       if (require_clean_work_tree(the_repository, "rebase",
                                    _("Please commit or stash them."), 1, 1)) {
                ret = 1;
                goto cleanup;
                                }
  
                                strbuf_reset(&buf);
 -                              strbuf_addf(&buf, "rebase: checkout %s",
 +                              strbuf_addf(&buf, "%s: checkout %s",
 +                                          getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
                                            options.switch_to);
                                if (reset_head(&oid, "checkout",
                                               options.head_name, 0,
 -                                             NULL, NULL) < 0) {
 +                                             NULL, buf.buf) < 0) {
                                        ret = !!error(_("could not switch to "
                                                        "%s"),
                                                      options.switch_to);
        if (options.flags & REBASE_DIFFSTAT) {
                struct diff_options opts;
  
 -              if (options.flags & REBASE_VERBOSE)
 -                      printf(_("Changes from %s to %s:\n"),
 -                              oid_to_hex(&merge_base),
 -                              oid_to_hex(&options.onto->object.oid));
 +              if (options.flags & REBASE_VERBOSE) {
 +                      if (is_null_oid(&merge_base))
 +                              printf(_("Changes to %s:\n"),
 +                                     oid_to_hex(&options.onto->object.oid));
 +                      else
 +                              printf(_("Changes from %s to %s:\n"),
 +                                     oid_to_hex(&merge_base),
 +                                     oid_to_hex(&options.onto->object.oid));
 +              }
  
                /* We want color (if set), but no pager */
                diff_setup(&opts);
                        DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
                opts.detect_rename = DIFF_DETECT_RENAME;
                diff_setup_done(&opts);
 -              diff_tree_oid(&merge_base, &options.onto->object.oid,
 -                            "", &opts);
 +              diff_tree_oid(is_null_oid(&merge_base) ?
 +                            the_hash_algo->empty_tree : &merge_base,
 +                            &options.onto->object.oid, "", &opts);
                diffcore_std(&opts);
                diff_flush(&opts);
        }
                printf(_("First, rewinding head to replay your work on top of "
                         "it...\n"));
  
 -      strbuf_addf(&msg, "rebase: checkout %s", options.onto_name);
 -      if (reset_head(&options.onto->object.oid, "checkout", NULL, 1,
 -          NULL, msg.buf))
 +      strbuf_addf(&msg, "%s: checkout %s",
 +                  getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
 +      if (reset_head(&options.onto->object.oid, "checkout", NULL,
 +                     RESET_HEAD_DETACH, NULL, msg.buf))
                die(_("Could not detach HEAD"));
        strbuf_release(&msg);
  
         */
        strbuf_reset(&msg);
        if (!oidcmp(&merge_base, &options.orig_head)) {
 -              printf(_("Fast-forwarded %s to %s. \n"),
 +              printf(_("Fast-forwarded %s to %s.\n"),
                        branch_name, options.onto_name);
                strbuf_addf(&msg, "rebase finished: %s onto %s",
                        options.head_name ? options.head_name : "detached HEAD",
diff --combined builtin/rerere.c
index d78eeaed329e5c647e5474b6a4205194b539f4b4,6f28c19b20d0167c3d916eb180bc64b37e64528b..fd3be17b976c7d2f413b4e760236c2274f1e7639
@@@ -41,8 -41,7 +41,8 @@@ static int diff_two(const char *file1, 
        xpp.flags = 0;
        memset(&xecfg, 0, sizeof(xecfg));
        xecfg.ctxlen = 3;
 -      ecb.outf = outf;
 +      ecb.out_hunk = NULL;
 +      ecb.out_line = outf;
        ret = xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
  
        free(minus.ptr);
@@@ -83,11 -82,12 +83,12 @@@ int cmd_rerere(int argc, const char **a
        }
  
        if (!strcmp(argv[0], "clear")) {
-               rerere_clear(&merge_rr);
+               rerere_clear(the_repository, &merge_rr);
        } else if (!strcmp(argv[0], "gc"))
-               rerere_gc(&merge_rr);
+               rerere_gc(the_repository, &merge_rr);
        else if (!strcmp(argv[0], "status")) {
-               if (setup_rerere(&merge_rr, flags | RERERE_READONLY) < 0)
+               if (setup_rerere(the_repository, &merge_rr,
+                                flags | RERERE_READONLY) < 0)
                        return 0;
                for (i = 0; i < merge_rr.nr; i++)
                        printf("%s\n", merge_rr.items[i].string);
                                merge_rr.items[i].util = NULL;
                }
        } else if (!strcmp(argv[0], "diff")) {
-               if (setup_rerere(&merge_rr, flags | RERERE_READONLY) < 0)
+               if (setup_rerere(the_repository, &merge_rr,
+                                flags | RERERE_READONLY) < 0)
                        return 0;
                for (i = 0; i < merge_rr.nr; i++) {
                        const char *path = merge_rr.items[i].string;
diff --combined builtin/reset.c
index 58166964f84ce1b78f703bb10f92f713b2cce6b4,161b5e0cae8df3a5648835c5877bc7e1e1f5d548..59898c972eee5e8065c2a68b7c937cc3af11f513
@@@ -25,8 -25,6 +25,8 @@@
  #include "submodule.h"
  #include "submodule-config.h"
  
 +#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
 +
  static const char * const git_reset_usage[] = {
        N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
        N_("git reset [-q] [<tree-ish>] [--] <paths>..."),
@@@ -95,7 -93,7 +95,7 @@@ static int reset_index(const struct obj
  
        if (reset_type == MIXED || reset_type == HARD) {
                tree = parse_tree_indirect(oid);
-               prime_cache_tree(&the_index, tree);
+               prime_cache_tree(the_repository, the_repository->index, tree);
        }
  
        ret = 0;
@@@ -309,7 -307,6 +309,7 @@@ int cmd_reset(int argc, const char **ar
        };
  
        git_config(git_reset_config, NULL);
 +      git_config_get_bool("reset.quiet", &quiet);
  
        argc = parse_options(argc, argv, prefix, options, git_reset_usage,
                                                PARSE_OPT_KEEP_DASHDASH);
                        int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
                        if (read_from_tree(&pathspec, &oid, intent_to_add))
                                return 1;
 -                      if (get_git_work_tree())
 +                      if (!quiet && get_git_work_tree()) {
 +                              uint64_t t_begin, t_delta_in_ms;
 +
 +                              t_begin = getnanotime();
                                refresh_index(&the_index, flags, NULL, NULL,
                                              _("Unstaged changes after reset:"));
 +                              t_delta_in_ms = (getnanotime() - t_begin) / 1000000;
 +                              if (advice_reset_quiet_warning && t_delta_in_ms > REFRESH_INDEX_DELAY_WARNING_IN_MS) {
 +                                      printf(_("\nIt took %.2f seconds to enumerate unstaged changes after reset.  You can\n"
 +                                              "use '--quiet' to avoid this.  Set the config setting reset.quiet to true\n"
 +                                              "to make this the default.\n"), t_delta_in_ms / 1000.0);
 +                              }
 +                      }
                } else {
                        int err = reset_index(&oid, reset_type, quiet);
                        if (reset_type == KEEP && !err)
                        print_new_head_line(lookup_commit_reference(the_repository, &oid));
        }
        if (!pathspec.nr)
-               remove_branch_state();
+               remove_branch_state(the_repository);
  
        return update_ref_status;
  }
diff --combined bundle.c
index 88c3e16d86162518ddde771703a3d2b0fc622f3b,b94992675ab763728abdc47cc75ab9996f499ba1..37b1daa6918bafb6b21faba47d25fcc6433698ba
+++ b/bundle.c
@@@ -127,7 -127,9 +127,9 @@@ static int list_refs(struct ref_list *r
  /* Remember to update object flag allocation in object.h */
  #define PREREQ_MARK (1u<<16)
  
- int verify_bundle(struct bundle_header *header, int verbose)
+ int verify_bundle(struct repository *r,
+                 struct bundle_header *header,
+                 int verbose)
  {
        /*
         * Do fast check, then if any prereqs are missing then go line by line
        int i, ret = 0, req_nr;
        const char *message = _("Repository lacks these prerequisite commits:");
  
-       repo_init_revisions(the_repository, &revs, NULL);
+       repo_init_revisions(r, &revs, NULL);
        for (i = 0; i < p->nr; i++) {
                struct ref_list_entry *e = p->list + i;
-               struct object *o = parse_object(the_repository, &e->oid);
+               struct object *o = parse_object(r, &e->oid);
                if (o) {
                        o->flags |= PREREQ_MARK;
                        add_pending_object(&revs, o, e->name);
  
        for (i = 0; i < p->nr; i++) {
                struct ref_list_entry *e = p->list + i;
-               struct object *o = parse_object(the_repository, &e->oid);
+               struct object *o = parse_object(r, &e->oid);
                assert(o); /* otherwise we'd have returned early */
                if (o->flags & SHOWN)
                        continue;
        /* Clean up objects used, as they will be reused. */
        for (i = 0; i < p->nr; i++) {
                struct ref_list_entry *e = p->list + i;
-               commit = lookup_commit_reference_gently(the_repository, &e->oid, 1);
+               commit = lookup_commit_reference_gently(r, &e->oid, 1);
                if (commit)
                        clear_commit_marks(commit, ALL_REV_FLAGS);
        }
@@@ -243,7 -245,7 +245,7 @@@ out
  }
  
  
 -/* Write the pack data to bundle_fd, then close it if it is > 1. */
 +/* Write the pack data to bundle_fd */
  static int write_pack_data(int bundle_fd, struct rev_info *revs)
  {
        struct child_process pack_objects = CHILD_PROCESS_INIT;
        pack_objects.in = -1;
        pack_objects.out = bundle_fd;
        pack_objects.git_cmd = 1;
 +
 +      /*
 +       * start_command() will close our descriptor if it's >1. Duplicate it
 +       * to avoid surprising the caller.
 +       */
 +      if (pack_objects.out > 1) {
 +              pack_objects.out = dup(pack_objects.out);
 +              if (pack_objects.out < 0) {
 +                      error_errno(_("unable to dup bundle descriptor"));
 +                      child_process_clear(&pack_objects);
 +                      return -1;
 +              }
 +      }
 +
        if (start_command(&pack_objects))
                return error(_("Could not spawn pack-objects"));
  
@@@ -389,8 -377,7 +391,7 @@@ static int write_bundle_refs(int bundle
                         * in terms of a tag (e.g. v2.0 from the range
                         * "v1.0..v2.0")?
                         */
-                       struct commit *one = lookup_commit_reference(the_repository,
-                                                                    &oid);
+                       struct commit *one = lookup_commit_reference(revs->repo, &oid);
                        struct object *obj;
  
                        if (e->item == &(one->object)) {
        return ref_count;
  }
  
- int create_bundle(struct bundle_header *header, const char *path,
-                 int argc, const char **argv)
+ int create_bundle(struct repository *r, struct bundle_header *header,
+                 const char *path, int argc, const char **argv)
  {
        struct lock_file lock = LOCK_INIT;
        int bundle_fd = -1;
        bundle_to_stdout = !strcmp(path, "-");
        if (bundle_to_stdout)
                bundle_fd = 1;
 -      else {
 +      else
                bundle_fd = hold_lock_file_for_update(&lock, path,
                                                      LOCK_DIE_ON_ERROR);
  
 -              /*
 -               * write_pack_data() will close the fd passed to it,
 -               * but commit_lock_file() will also try to close the
 -               * lockfile's fd. So make a copy of the file
 -               * descriptor to avoid trying to close it twice.
 -               */
 -              bundle_fd = dup(bundle_fd);
 -              if (bundle_fd < 0)
 -                      die_errno("unable to dup file descriptor");
 -      }
 -
        /* write signature */
        write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
  
        /* init revs to list objects for pack-objects later */
        save_commit_buffer = 0;
-       repo_init_revisions(the_repository, &revs, NULL);
+       repo_init_revisions(r, &revs, NULL);
  
        /* write prerequisites */
        if (compute_and_write_prerequisites(bundle_fd, &revs, argc, argv))
                goto err;
  
        /* write pack */
 -      if (write_pack_data(bundle_fd, &revs)) {
 -              bundle_fd = -1; /* already closed by the above call */
 +      if (write_pack_data(bundle_fd, &revs))
                goto err;
 -      }
  
        if (!bundle_to_stdout) {
                if (commit_lock_file(&lock))
        }
        return 0;
  err:
 -      if (!bundle_to_stdout) {
 -              if (0 <= bundle_fd)
 -                      close(bundle_fd);
 -              rollback_lock_file(&lock);
 -      }
 +      rollback_lock_file(&lock);
        return -1;
  }
  
- int unbundle(struct bundle_header *header, int bundle_fd, int flags)
+ int unbundle(struct repository *r, struct bundle_header *header,
+            int bundle_fd, int flags)
  {
        const char *argv_index_pack[] = {"index-pack",
                                         "--fix-thin", "--stdin", NULL, NULL};
        if (flags & BUNDLE_VERBOSE)
                argv_index_pack[3] = "-v";
  
-       if (verify_bundle(header, 0))
+       if (verify_bundle(r, header, 0))
                return -1;
        ip.argv = argv_index_pack;
        ip.in = bundle_fd;
diff --combined combine-diff.c
index ad7752ea6b7e3173066e346b7dd314e7707f7d8c,3d796af3ca201cbcbbb1407fb5827481202f406c..a143c006341170fad8c42604eca8f9bbf3226de8
@@@ -345,43 -345,38 +345,43 @@@ struct combine_diff_state 
        struct sline *lost_bucket;
  };
  
 -static void consume_line(void *state_, char *line, unsigned long len)
 +static void consume_hunk(void *state_,
 +                       long ob, long on,
 +                       long nb, long nn,
 +                       const char *funcline, long funclen)
  {
        struct combine_diff_state *state = state_;
 -      if (5 < len && !memcmp("@@ -", line, 4)) {
 -              if (parse_hunk_header(line, len,
 -                                    &state->ob, &state->on,
 -                                    &state->nb, &state->nn))
 -                      return;
 -              state->lno = state->nb;
 -              if (state->nn == 0) {
 -                      /* @@ -X,Y +N,0 @@ removed Y lines
 -                       * that would have come *after* line N
 -                       * in the result.  Our lost buckets hang
 -                       * to the line after the removed lines,
 -                       *
 -                       * Note that this is correct even when N == 0,
 -                       * in which case the hunk removes the first
 -                       * line in the file.
 -                       */
 -                      state->lost_bucket = &state->sline[state->nb];
 -                      if (!state->nb)
 -                              state->nb = 1;
 -              } else {
 -                      state->lost_bucket = &state->sline[state->nb-1];
 -              }
 -              if (!state->sline[state->nb-1].p_lno)
 -                      state->sline[state->nb-1].p_lno =
 -                              xcalloc(state->num_parent,
 -                                      sizeof(unsigned long));
 -              state->sline[state->nb-1].p_lno[state->n] = state->ob;
 -              return;
 +
 +      state->ob = ob;
 +      state->on = on;
 +      state->nb = nb;
 +      state->nn = nn;
 +      state->lno = state->nb;
 +      if (state->nn == 0) {
 +              /* @@ -X,Y +N,0 @@ removed Y lines
 +               * that would have come *after* line N
 +               * in the result.  Our lost buckets hang
 +               * to the line after the removed lines,
 +               *
 +               * Note that this is correct even when N == 0,
 +               * in which case the hunk removes the first
 +               * line in the file.
 +               */
 +              state->lost_bucket = &state->sline[state->nb];
 +              if (!state->nb)
 +                      state->nb = 1;
 +      } else {
 +              state->lost_bucket = &state->sline[state->nb-1];
        }
 +      if (!state->sline[state->nb-1].p_lno)
 +              state->sline[state->nb-1].p_lno =
 +                      xcalloc(state->num_parent, sizeof(unsigned long));
 +      state->sline[state->nb-1].p_lno[state->n] = state->ob;
 +}
 +
 +static void consume_line(void *state_, char *line, unsigned long len)
 +{
 +      struct combine_diff_state *state = state_;
        if (!state->lost_bucket)
                return; /* not in any hunk yet */
        switch (line[0]) {
@@@ -426,8 -421,8 +426,8 @@@ static void combine_diff(struct reposit
        state.num_parent = num_parent;
        state.n = n;
  
 -      if (xdi_diff_outf(&parent_file, result_file, consume_line, &state,
 -                        &xpp, &xecfg))
 +      if (xdi_diff_outf(&parent_file, result_file, consume_hunk,
 +                        consume_line, &state, &xpp, &xecfg))
                die("unable to generate combined diff for %s",
                    oid_to_hex(parent));
        free(parent_file.ptr);
@@@ -996,7 -991,7 +996,7 @@@ static void show_patch_diff(struct comb
        if (!userdiff)
                userdiff = userdiff_find_by_name("default");
        if (opt->flags.allow_textconv)
-               textconv = userdiff_get_textconv(userdiff);
+               textconv = userdiff_get_textconv(opt->repo, userdiff);
  
        /* Read the result of merge first */
        if (!working_tree_file)
diff --combined diff.c
index dc9965e836cd49c46a01293ef1d678a619b8f997,1135377a7f09c7462bf6cf0c4a8906055c90426d..15556c190d2e368fb2967a966263d1bcbfc09db2
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -1912,17 -1912,19 +1912,17 @@@ static int color_words_output_graph_pre
        }
  }
  
 -static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
 +static void fn_out_diff_words_aux(void *priv,
 +                                long minus_first, long minus_len,
 +                                long plus_first, long plus_len,
 +                                const char *func, long funclen)
  {
        struct diff_words_data *diff_words = priv;
        struct diff_words_style *style = diff_words->style;
 -      int minus_first, minus_len, plus_first, plus_len;
        const char *minus_begin, *minus_end, *plus_begin, *plus_end;
        struct diff_options *opt = diff_words->opt;
        const char *line_prefix;
  
 -      if (line[0] != '@' || parse_hunk_header(line, len,
 -                      &minus_first, &minus_len, &plus_first, &plus_len))
 -              return;
 -
        assert(opt);
        line_prefix = diff_line_prefix(opt);
  
@@@ -2072,8 -2074,8 +2072,8 @@@ static void diff_words_show(struct diff
        xpp.flags = 0;
        /* as only the hunk header will be parsed, we need a 0-context */
        xecfg.ctxlen = 0;
 -      if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
 -                        &xpp, &xecfg))
 +      if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, NULL,
 +                        diff_words, &xpp, &xecfg))
                die("unable to generate word diff");
        free(minus.ptr);
        free(plus.ptr);
@@@ -3128,15 -3130,6 +3128,15 @@@ static int is_conflict_marker(const cha
        return 1;
  }
  
 +static void checkdiff_consume_hunk(void *priv,
 +                                 long ob, long on, long nb, long nn,
 +                                 const char *func, long funclen)
 +
 +{
 +      struct checkdiff_t *data = priv;
 +      data->lineno = nb - 1;
 +}
 +
  static void checkdiff_consume(void *priv, char *line, unsigned long len)
  {
        struct checkdiff_t *data = priv;
                              data->o->file, set, reset, ws);
        } else if (line[0] == ' ') {
                data->lineno++;
 -      } else if (line[0] == '@') {
 -              char *plus = strchr(line, '+');
 -              if (plus)
 -                      data->lineno = strtol(plus, NULL, 10) - 1;
 -              else
 -                      die("invalid diff");
        }
  }
  
@@@ -3228,7 -3227,7 +3228,7 @@@ static void emit_binary_diff_body(struc
        }
  
        if (delta && delta_size < deflate_size) {
 -              char *s = xstrfmt("%lu", orig_size);
 +              char *s = xstrfmt("%"PRIuMAX , (uintmax_t)orig_size);
                emit_diff_symbol(o, DIFF_SYMBOL_BINARY_DIFF_HEADER_DELTA,
                                 s, strlen(s), 0);
                free(s);
@@@ -3313,14 -3312,14 +3313,14 @@@ void diff_set_mnemonic_prefix(struct di
                options->b_prefix = b;
  }
  
- struct userdiff_driver *get_textconv(struct index_state *istate,
+ struct userdiff_driver *get_textconv(struct repository *r,
                                     struct diff_filespec *one)
  {
        if (!DIFF_FILE_VALID(one))
                return NULL;
  
-       diff_filespec_load_driver(one, istate);
-       return userdiff_get_textconv(one->driver);
+       diff_filespec_load_driver(one, r->index);
+       return userdiff_get_textconv(r, one->driver);
  }
  
  static void builtin_diff(const char *name_a,
        }
  
        if (o->flags.allow_textconv) {
-               textconv_one = get_textconv(o->repo->index, one);
-               textconv_two = get_textconv(o->repo->index, two);
+               textconv_one = get_textconv(o->repo, one);
+               textconv_two = get_textconv(o->repo, two);
        }
  
        /* Never use a non-valid filename anywhere if at all possible */
                        xecfg.ctxlen = strtoul(v, NULL, 10);
                if (o->word_diff)
                        init_diff_words_data(&ecbdata, o, one, two);
 -              if (xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
 -                                &xpp, &xecfg))
 +              if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
 +                                &ecbdata, &xpp, &xecfg))
                        die("unable to generate diff for %s", one->path);
                if (o->word_diff)
                        free_diff_words_data(&ecbdata);
@@@ -3638,8 -3637,8 +3638,8 @@@ static void builtin_diffstat(const cha
                xpp.anchors_nr = o->anchors_nr;
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
 -              if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
 -                                &xpp, &xecfg))
 +              if (xdi_diff_outf(&mf1, &mf2, discard_hunk_line,
 +                                diffstat_consume, diffstat, &xpp, &xecfg))
                        die("unable to generate diffstat for %s", one->path);
        }
  
@@@ -3687,8 -3686,7 +3687,8 @@@ static void builtin_checkdiff(const cha
                memset(&xecfg, 0, sizeof(xecfg));
                xecfg.ctxlen = 1; /* at least one context line */
                xpp.flags = 0;
 -              if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
 +              if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume_hunk,
 +                                checkdiff_consume, &data,
                                  &xpp, &xecfg))
                        die("unable to generate checkdiff for %s", one->path);
  
@@@ -5668,6 -5666,10 +5668,6 @@@ static void patch_id_consume(void *priv
        struct patch_id_t *data = priv;
        int new_len;
  
 -      /* Ignore line numbers when computing the SHA1 of the patch */
 -      if (starts_with(line, "@@ -"))
 -              return;
 -
        new_len = remove_space(line, len);
  
        git_SHA1_Update(data->ctx, line, new_len);
@@@ -5769,8 -5771,8 +5769,8 @@@ static int diff_get_patch_id(struct dif
                xpp.flags = 0;
                xecfg.ctxlen = 3;
                xecfg.flags = 0;
 -              if (xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
 -                                &xpp, &xecfg))
 +              if (xdi_diff_outf(&mf1, &mf2, discard_hunk_line,
 +                                patch_id_consume, &data, &xpp, &xecfg))
                        return error("unable to generate patch-id diff for %s",
                                     p->one->path);
        }
@@@ -6434,7 -6436,7 +6434,7 @@@ int textconv_object(struct repository *
  
        df = alloc_filespec(path);
        fill_filespec(df, oid, oid_valid, mode);
-       textconv = get_textconv(r->index, df);
+       textconv = get_textconv(r, df);
        if (!textconv) {
                free_filespec(df);
                return 0;
diff --combined diffcore-pickaxe.c
index 69fc55ea1e34af69b7ed4d57e521cb4825f99fd2,b815f1c4490ea969194376e976b1f91ca983a71e..ad939d2861554746a9fd52947a38943928ece552
@@@ -62,8 -62,7 +62,8 @@@ static int diff_grep(mmfile_t *one, mmf
        ecbdata.hit = 0;
        xecfg.ctxlen = o->context;
        xecfg.interhunkctxlen = o->interhunkcontext;
 -      if (xdi_diff_outf(one, two, diffgrep_consume, &ecbdata, &xpp, &xecfg))
 +      if (xdi_diff_outf(one, two, discard_hunk_line, diffgrep_consume,
 +                        &ecbdata, &xpp, &xecfg))
                return 0;
        return ecbdata.hit;
  }
@@@ -140,8 -139,8 +140,8 @@@ static int pickaxe_match(struct diff_fi
                return 0;
  
        if (o->flags.allow_textconv) {
-               textconv_one = get_textconv(o->repo->index, p->one);
-               textconv_two = get_textconv(o->repo->index, p->two);
+               textconv_one = get_textconv(o->repo, p->one);
+               textconv_two = get_textconv(o->repo, p->two);
        }
  
        /*
diff --combined grep.c
index 4db1510d167c9fc3cc7b129c90aa874a4c7c2b0f,b05b2e61bbac357eae855695b97a0a1a5ef0c41a..0d50598acda6f1c41951d1d656ea701114473239
--- 1/grep.c
--- 2/grep.c
+++ b/grep.c
@@@ -1513,6 -1513,7 +1513,6 @@@ static void show_line(struct grep_opt *
        }
  }
  
 -#ifndef NO_PTHREADS
  int grep_use_locks;
  
  /*
@@@ -1538,6 -1539,11 +1538,6 @@@ static inline void grep_attr_unlock(voi
   */
  pthread_mutex_t grep_read_mutex;
  
 -#else
 -#define grep_attr_lock()
 -#define grep_attr_unlock()
 -#endif
 -
  static int match_funcname(struct grep_opt *opt, struct grep_source *gs, char *bol, char *eol)
  {
        xdemitconf_t *xecfg = opt->priv;
@@@ -1805,7 -1811,7 +1805,7 @@@ static int grep_source_1(struct grep_op
                 * is not thread-safe.
                 */
                grep_attr_lock();
-               textconv = userdiff_get_textconv(gs->driver);
+               textconv = userdiff_get_textconv(opt->repo, gs->driver);
                grep_attr_unlock();
        }
  
diff --combined pack-objects.h
index dc869f26c2b753593a875f275d896933b7723b31,9e6af3f24f993e76f6b391c5c03ee9df88a8fd72..3cd8d1f00a95978a5a8c86805506b9927aefcd0e
@@@ -5,6 -5,8 +5,8 @@@
  #include "thread-utils.h"
  #include "pack.h"
  
+ struct repository;
  #define DEFAULT_DELTA_CACHE_SIZE (256 * 1024 * 1024)
  
  #define OE_DFS_STATE_BITS     2
@@@ -127,6 -129,7 +129,7 @@@ struct object_entry 
  };
  
  struct packing_data {
+       struct repository *repo;
        struct object_entry *objects;
        uint32_t nr_objects, nr_alloc;
  
        struct packed_git **in_pack_by_idx;
        struct packed_git **in_pack;
  
 -#ifndef NO_PTHREADS
        pthread_mutex_t lock;
 -#endif
  
        /*
         * This list contains entries for bases which we know the other side
        unsigned char *layer;
  };
  
- void prepare_packing_data(struct packing_data *pdata);
+ void prepare_packing_data(struct repository *r, struct packing_data *pdata);
  
  static inline void packing_data_lock(struct packing_data *pdata)
  {
 -#ifndef NO_PTHREADS
        pthread_mutex_lock(&pdata->lock);
 -#endif
  }
  static inline void packing_data_unlock(struct packing_data *pdata)
  {
 -#ifndef NO_PTHREADS
        pthread_mutex_unlock(&pdata->lock);
 -#endif
  }
  
  struct object_entry *packlist_alloc(struct packing_data *pdata,
@@@ -412,7 -421,7 +415,7 @@@ static inline void oe_set_tree_depth(st
                                     unsigned int tree_depth)
  {
        if (!pack->tree_depth)
 -              ALLOC_ARRAY(pack->tree_depth, pack->nr_objects);
 +              CALLOC_ARRAY(pack->tree_depth, pack->nr_alloc);
        pack->tree_depth[e - pack->objects] = tree_depth;
  }
  
@@@ -429,7 -438,7 +432,7 @@@ static inline void oe_set_layer(struct 
                                unsigned char layer)
  {
        if (!pack->layer)
 -              ALLOC_ARRAY(pack->layer, pack->nr_objects);
 +              CALLOC_ARRAY(pack->layer, pack->nr_alloc);
        pack->layer[e - pack->objects] = layer;
  }
  
diff --combined read-cache.c
index bd45dc3e24d7dc28820d26cc6e6d377f92fda46d,69944fc93388b009a4674d0adcbe19d6bfa3db2f..521be0b0454280ab88f65eed254ddae35334f49e
@@@ -1496,12 -1496,6 +1496,12 @@@ int refresh_index(struct index_state *i
        typechange_fmt = (in_porcelain ? "T\t%s\n" : "%s needs update\n");
        added_fmt = (in_porcelain ? "A\t%s\n" : "%s needs update\n");
        unmerged_fmt = (in_porcelain ? "U\t%s\n" : "%s: needs merge\n");
 +      /*
 +       * Use the multi-threaded preload_index() to refresh most of the
 +       * cache entries quickly then in the single threaded loop below,
 +       * we only have to do the special cases that are left.
 +       */
 +      preload_index(istate, pathspec, 0);
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce, *new_entry;
                int cache_errno = 0;
@@@ -1752,7 -1746,7 +1752,7 @@@ static struct cache_entry *create_from_
        size_t len;
        const char *name;
        unsigned int flags;
 -      size_t copy_len;
 +      size_t copy_len = 0;
        /*
         * Adjacent cache entries tend to share the leading paths, so it makes
         * sense to only store the differences in later entries.  In the v4
                                die(_("malformed name field in the index, near path '%s'"),
                                        previous_ce->name);
                        copy_len = previous_len - strip_len;
 -              } else {
 -                      copy_len = 0;
                }
                name = (const char *)cp;
        }
@@@ -1924,15 -1920,19 +1924,15 @@@ struct index_entry_offset_tabl
        struct index_entry_offset entries[FLEX_ARRAY];
  };
  
 -#ifndef NO_PTHREADS
  static struct index_entry_offset_table *read_ieot_extension(const char *mmap, size_t mmap_size, size_t offset);
  static void write_ieot_extension(struct strbuf *sb, struct index_entry_offset_table *ieot);
 -#endif
  
  static size_t read_eoie_extension(const char *mmap, size_t mmap_size);
  static void write_eoie_extension(struct strbuf *sb, git_hash_ctx *eoie_context, size_t offset);
  
  struct load_index_extensions
  {
 -#ifndef NO_PTHREADS
        pthread_t pthread;
 -#endif
        struct index_state *istate;
        const char *mmap;
        size_t mmap_size;
@@@ -2010,6 -2010,8 +2010,6 @@@ static unsigned long load_all_cache_ent
        return consumed;
  }
  
 -#ifndef NO_PTHREADS
 -
  /*
   * Mostly randomly chosen maximum thread counts: we
   * cap the parallelism to online_cpus() threads, and we want
@@@ -2120,6 -2122,7 +2120,6 @@@ static unsigned long load_cache_entries
  
        return consumed;
  }
 -#endif
  
  /* remember to discard_cache() before reading a different cache! */
  int do_read_index(struct index_state *istate, const char *path, int must_exist)
        size_t mmap_size;
        struct load_index_extensions p;
        size_t extension_offset = 0;
 -#ifndef NO_PTHREADS
        int nr_threads, cpus;
        struct index_entry_offset_table *ieot = NULL;
 -#endif
  
        if (istate->initialized)
                return istate->cache_nr;
  
        src_offset = sizeof(*hdr);
  
 -#ifndef NO_PTHREADS
 -      nr_threads = git_config_get_index_threads();
 +      if (git_config_get_index_threads(&nr_threads))
 +              nr_threads = 1;
  
        /* TODO: does creating more threads than cores help? */
        if (!nr_threads) {
                        nr_threads = cpus;
        }
  
 +      if (!HAVE_THREADS)
 +              nr_threads = 1;
 +
        if (nr_threads > 1) {
                extension_offset = read_eoie_extension(mmap, mmap_size);
                if (extension_offset) {
        } else {
                src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
        }
 -#else
 -      src_offset += load_all_cache_entries(istate, mmap, mmap_size, src_offset);
 -#endif
  
        istate->timestamp.sec = st.st_mtime;
        istate->timestamp.nsec = ST_MTIME_NSEC(st);
  
        /* if we created a thread, join it otherwise load the extensions on the primary thread */
 -#ifndef NO_PTHREADS
        if (extension_offset) {
                int ret = pthread_join(p.pthread, NULL);
                if (ret)
                        die(_("unable to join load_index_extensions thread: %s"), strerror(ret));
 -      }
 -#endif
 -      if (!extension_offset) {
 +      } else {
                p.src_offset = src_offset;
                load_index_extensions(&p);
        }
@@@ -2690,36 -2698,6 +2690,36 @@@ void update_index_if_able(struct index_
                rollback_lock_file(lockfile);
  }
  
 +static int record_eoie(void)
 +{
 +      int val;
 +
 +      if (!git_config_get_bool("index.recordendofindexentries", &val))
 +              return val;
 +
 +      /*
 +       * As a convenience, the end of index entries extension
 +       * used for threading is written by default if the user
 +       * explicitly requested threaded index reads.
 +       */
 +      return !git_config_get_index_threads(&val) && val != 1;
 +}
 +
 +static int record_ieot(void)
 +{
 +      int val;
 +
 +      if (!git_config_get_bool("index.recordoffsettable", &val))
 +              return val;
 +
 +      /*
 +       * As a convenience, the offset table used for threading is
 +       * written by default if the user explicitly requested
 +       * threaded index reads.
 +       */
 +      return !git_config_get_index_threads(&val) && val != 1;
 +}
 +
  /*
   * On success, `tempfile` is closed. If it is the temporary file
   * of a `struct lock_file`, we will therefore effectively perform
@@@ -2778,10 -2756,9 +2778,10 @@@ static int do_write_index(struct index_
        if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
                return -1;
  
 -#ifndef NO_PTHREADS
 -      nr_threads = git_config_get_index_threads();
 -      if (nr_threads != 1) {
 +      if (!HAVE_THREADS || git_config_get_index_threads(&nr_threads))
 +              nr_threads = 1;
 +
 +      if (nr_threads != 1 && record_ieot()) {
                int ieot_blocks, cpus;
  
                /*
                        ieot_entries = DIV_ROUND_UP(entries, ieot_blocks);
                }
        }
 -#endif
  
        offset = lseek(newfd, 0, SEEK_CUR);
        if (offset < 0) {
         * strip_extensions parameter as we need it when loading the shared
         * index.
         */
 -#ifndef NO_PTHREADS
        if (ieot) {
                struct strbuf sb = STRBUF_INIT;
  
                if (err)
                        return -1;
        }
 -#endif
  
        if (!strip_extensions && istate->split_index) {
                struct strbuf sb = STRBUF_INIT;
         * read.  Write it out regardless of the strip_extensions parameter as we need it
         * when loading the shared index.
         */
 -      if (offset) {
 +      if (offset && record_eoie()) {
                struct strbuf sb = STRBUF_INIT;
  
                write_eoie_extension(&sb, &eoie_c, offset);
@@@ -3146,7 -3126,7 +3146,7 @@@ int write_locked_index(struct index_sta
        struct split_index *si = istate->split_index;
  
        if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0))
-               cache_tree_verify(istate);
+               cache_tree_verify(the_repository, istate);
  
        if ((flags & SKIP_IF_UNCHANGED) && !istate->cache_changed) {
                if (flags & COMMIT_LOCK)
                struct tempfile *temp;
                int saved_errno;
  
 -              temp = mks_tempfile(git_path("sharedindex_XXXXXX"));
 +              /* Same initial permissions as the main .git/index file */
 +              temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666);
                if (!temp) {
                        oidclr(&si->base_oid);
                        ret = do_write_locked_index(istate, lock, flags);
@@@ -3490,6 -3469,7 +3490,6 @@@ static void write_eoie_extension(struc
        strbuf_add(sb, hash, the_hash_algo->rawsz);
  }
  
 -#ifndef NO_PTHREADS
  #define IEOT_VERSION  (1)
  
  static struct index_entry_offset_table *read_ieot_extension(const char *mmap, size_t mmap_size, size_t offset)
@@@ -3562,3 -3542,4 +3562,3 @@@ static void write_ieot_extension(struc
               strbuf_add(sb, &buffer, sizeof(uint32_t));
         }
  }
 -#endif
diff --combined ref-filter.c
index 5de616befe46e64b014ebe7c3feb5913bc8af2df,c4eaf3031388fce5ff5f57027ed3fb6e84c03743..9719efc267e141bcccadc2d0ad010a84d8774c4f
@@@ -534,10 -534,6 +534,10 @@@ static int parse_ref_filter_atom(const 
        if (ARRAY_SIZE(valid_atom) <= i)
                return strbuf_addf_ret(err, -1, _("unknown field name: %.*s"),
                                       (int)(ep-atom), atom);
 +      if (valid_atom[i].source != SOURCE_NONE && !have_git_dir())
 +              return strbuf_addf_ret(err, -1,
 +                                     _("not a git repository, but the field '%.*s' requires access to object data"),
 +                                     (int)(ep-atom), atom);
  
        /* Add it in, including the deref prefix */
        at = used_atom_cnt;
@@@ -882,7 -878,7 +882,7 @@@ static void grab_common_values(struct a
                        v->s = xstrdup(type_name(oi->type));
                else if (!strcmp(name, "objectsize")) {
                        v->value = oi->size;
 -                      v->s = xstrfmt("%lu", oi->size);
 +                      v->s = xstrfmt("%"PRIuMAX , (uintmax_t)oi->size);
                }
                else if (deref)
                        grab_objectname(name, &oi->oid, v, &used_atom[i]);
@@@ -1417,7 -1413,7 +1417,7 @@@ char *get_head_description(void
        struct strbuf desc = STRBUF_INIT;
        struct wt_status_state state;
        memset(&state, 0, sizeof(state));
-       wt_status_get_state(&state, 1);
+       wt_status_get_state(the_repository, &state, 1);
        if (state.rebase_in_progress ||
            state.rebase_interactive_in_progress) {
                if (state.branch)
@@@ -2320,8 -2316,6 +2320,8 @@@ int parse_opt_merge_filter(const struc
        struct object_id oid;
        int no_merged = starts_with(opt->long_name, "no");
  
 +      BUG_ON_OPT_NEG(unset);
 +
        if (rf->merge) {
                if (no_merged) {
                        return opterror(opt, "is incompatible with --merged", 0);
diff --combined sequencer.c
index e1a4dd15f1a826c7bd1bf4780c8f85c21117c43b,d726f77e11bf39e44037f65bf7bb561df4fd76bf..b68bca0bef927f0ebb2d8762f658946be7107fcb
@@@ -356,7 -356,8 +356,8 @@@ static void free_message(struct commit 
        unuse_commit_buffer(commit, msg->message);
  }
  
- static void print_advice(int show_hint, struct replay_opts *opts)
+ static void print_advice(struct repository *r, int show_hint,
+                        struct replay_opts *opts)
  {
        char *msg = getenv("GIT_CHERRY_PICK_HELP");
  
                 * (typically rebase --interactive) wants to take care
                 * of the commit itself so remove CHERRY_PICK_HEAD
                 */
-               unlink(git_path_cherry_pick_head(the_repository));
+               unlink(git_path_cherry_pick_head(r));
                return;
        }
  
@@@ -440,14 -441,14 +441,14 @@@ static int read_oneliner(struct strbuf 
        return 1;
  }
  
- static struct tree *empty_tree(void)
+ static struct tree *empty_tree(struct repository *r)
  {
-       return lookup_tree(the_repository, the_repository->hash_algo->empty_tree);
+       return lookup_tree(r, the_hash_algo->empty_tree);
  }
  
- static int error_dirty_index(struct replay_opts *opts)
+ static int error_dirty_index(struct index_state *istate, struct replay_opts *opts)
  {
-       if (read_cache_unmerged())
+       if (read_index_unmerged(istate))
                return error_resolve_conflict(_(action_name(opts)));
  
        error(_("your local changes would be overwritten by %s."),
@@@ -472,15 -473,18 +473,18 @@@ static void update_abort_safety_file(vo
                write_file(git_path_abort_safety_file(), "%s", "");
  }
  
- static int fast_forward_to(const struct object_id *to, const struct object_id *from,
-                       int unborn, struct replay_opts *opts)
+ static int fast_forward_to(struct repository *r,
+                          const struct object_id *to,
+                          const struct object_id *from,
+                          int unborn,
+                          struct replay_opts *opts)
  {
        struct ref_transaction *transaction;
        struct strbuf sb = STRBUF_INIT;
        struct strbuf err = STRBUF_INIT;
  
-       read_index(&the_index);
-       if (checkout_fast_forward(the_repository, from, to, 1))
+       read_index(r->index);
+       if (checkout_fast_forward(r, from, to, 1))
                return -1; /* the callee should have complained already */
  
        strbuf_addf(&sb, _("%s: fast-forward"), _(action_name(opts)));
        return 0;
  }
  
- void append_conflicts_hint(struct strbuf *msgbuf)
+ void append_conflicts_hint(struct index_state *istate,
+                          struct strbuf *msgbuf)
  {
        int i;
  
        strbuf_addch(msgbuf, '\n');
        strbuf_commented_addf(msgbuf, "Conflicts:\n");
-       for (i = 0; i < active_nr;) {
-               const struct cache_entry *ce = active_cache[i++];
+       for (i = 0; i < istate->cache_nr;) {
+               const struct cache_entry *ce = istate->cache[i++];
                if (ce_stage(ce)) {
                        strbuf_commented_addf(msgbuf, "\t%s\n", ce->name);
-                       while (i < active_nr && !strcmp(ce->name,
-                                                       active_cache[i]->name))
+                       while (i < istate->cache_nr &&
+                              !strcmp(ce->name, istate->cache[i]->name))
                                i++;
                }
        }
  }
  
- static int do_recursive_merge(struct commit *base, struct commit *next,
+ static int do_recursive_merge(struct repository *r,
+                             struct commit *base, struct commit *next,
                              const char *base_label, const char *next_label,
                              struct object_id *head, struct strbuf *msgbuf,
                              struct replay_opts *opts)
        if (hold_locked_index(&index_lock, LOCK_REPORT_ON_ERROR) < 0)
                return -1;
  
-       read_cache();
+       read_index(r->index);
  
        init_merge_options(&o);
        o.ancestor = base ? base_label : "(empty tree)";
        o.show_rename_progress = 1;
  
        head_tree = parse_tree_indirect(head);
-       next_tree = next ? get_commit_tree(next) : empty_tree();
-       base_tree = base ? get_commit_tree(base) : empty_tree();
+       next_tree = next ? get_commit_tree(next) : empty_tree(r);
+       base_tree = base ? get_commit_tree(base) : empty_tree(r);
  
        for (xopt = opts->xopts; xopt != opts->xopts + opts->xopts_nr; xopt++)
                parse_merge_opt(&o, *xopt);
                return clean;
        }
  
-       if (write_locked_index(&the_index, &index_lock,
+       if (write_locked_index(r->index, &index_lock,
                               COMMIT_LOCK | SKIP_IF_UNCHANGED))
                /*
                 * TRANSLATORS: %s will be "revert", "cherry-pick" or
                        _(action_name(opts)));
  
        if (!clean)
-               append_conflicts_hint(msgbuf);
+               append_conflicts_hint(r->index, msgbuf);
  
        return !clean;
  }
  
- static struct object_id *get_cache_tree_oid(void)
+ static struct object_id *get_cache_tree_oid(struct index_state *istate)
  {
-       if (!active_cache_tree)
-               active_cache_tree = cache_tree();
+       if (!istate->cache_tree)
+               istate->cache_tree = cache_tree();
  
-       if (!cache_tree_fully_valid(active_cache_tree))
-               if (cache_tree_update(&the_index, 0)) {
+       if (!cache_tree_fully_valid(istate->cache_tree))
+               if (cache_tree_update(istate, 0)) {
                        error(_("unable to update cache tree"));
                        return NULL;
                }
  
-       return &active_cache_tree->oid;
+       return &istate->cache_tree->oid;
  }
  
- static int is_index_unchanged(void)
+ static int is_index_unchanged(struct repository *r)
  {
        struct object_id head_oid, *cache_tree_oid;
        struct commit *head_commit;
+       struct index_state *istate = r->index;
  
        if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
                return error(_("could not resolve HEAD commit"));
  
-       head_commit = lookup_commit(the_repository, &head_oid);
+       head_commit = lookup_commit(r, &head_oid);
  
        /*
         * If head_commit is NULL, check_commit, called from
        if (parse_commit(head_commit))
                return -1;
  
-       if (!(cache_tree_oid = get_cache_tree_oid()))
+       if (!(cache_tree_oid = get_cache_tree_oid(istate)))
                return -1;
  
        return oideq(cache_tree_oid, get_commit_tree_oid(head_commit));
@@@ -669,131 -676,55 +676,131 @@@ missing_author
        return res;
  }
  
 +/**
 + * Take a series of KEY='VALUE' lines where VALUE part is
 + * sq-quoted, and append <KEY, VALUE> at the end of the string list
 + */
 +static int parse_key_value_squoted(char *buf, struct string_list *list)
 +{
 +      while (*buf) {
 +              struct string_list_item *item;
 +              char *np;
 +              char *cp = strchr(buf, '=');
 +              if (!cp) {
 +                      np = strchrnul(buf, '\n');
 +                      return error(_("no key present in '%.*s'"),
 +                                   (int) (np - buf), buf);
 +              }
 +              np = strchrnul(cp, '\n');
 +              *cp++ = '\0';
 +              item = string_list_append(list, buf);
 +
 +              buf = np + (*np == '\n');
 +              *np = '\0';
 +              cp = sq_dequote(cp);
 +              if (!cp)
 +                      return error(_("unable to dequote value of '%s'"),
 +                                   item->string);
 +              item->util = xstrdup(cp);
 +      }
 +      return 0;
 +}
  
 -/*
 - * write_author_script() used to fail to terminate the last line with a "'" and
 - * also escaped "'" incorrectly as "'\\\\''" rather than "'\\''". We check for
 - * the terminating "'" on the last line to see how "'" has been escaped in case
 - * git was upgraded while rebase was stopped.
 +/**
 + * Reads and parses the state directory's "author-script" file, and sets name,
 + * email and date accordingly.
 + * Returns 0 on success, -1 if the file could not be parsed.
 + *
 + * The author script is of the format:
 + *
 + *    GIT_AUTHOR_NAME='$author_name'
 + *    GIT_AUTHOR_EMAIL='$author_email'
 + *    GIT_AUTHOR_DATE='$author_date'
 + *
 + * where $author_name, $author_email and $author_date are quoted. We are strict
 + * with our parsing, as the file was meant to be eval'd in the old
 + * git-am.sh/git-rebase--interactive.sh scripts, and thus if the file differs
 + * from what this function expects, it is better to bail out than to do
 + * something that the user does not expect.
   */
 -static int quoting_is_broken(const char *s, size_t n)
 +int read_author_script(const char *path, char **name, char **email, char **date,
 +                     int allow_missing)
  {
 -      /* Skip any empty lines in case the file was hand edited */
 -      while (n > 0 && s[--n] == '\n')
 -              ; /* empty */
 -      if (n > 0 && s[n] != '\'')
 -              return 1;
 +      struct strbuf buf = STRBUF_INIT;
 +      struct string_list kv = STRING_LIST_INIT_DUP;
 +      int retval = -1; /* assume failure */
 +      int i, name_i = -2, email_i = -2, date_i = -2, err = 0;
  
 -      return 0;
 +      if (strbuf_read_file(&buf, path, 256) <= 0) {
 +              strbuf_release(&buf);
 +              if (errno == ENOENT && allow_missing)
 +                      return 0;
 +              else
 +                      return error_errno(_("could not open '%s' for reading"),
 +                                         path);
 +      }
 +
 +      if (parse_key_value_squoted(buf.buf, &kv))
 +              goto finish;
 +
 +      for (i = 0; i < kv.nr; i++) {
 +              if (!strcmp(kv.items[i].string, "GIT_AUTHOR_NAME")) {
 +                      if (name_i != -2)
 +                              name_i = error(_("'GIT_AUTHOR_NAME' already given"));
 +                      else
 +                              name_i = i;
 +              } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_EMAIL")) {
 +                      if (email_i != -2)
 +                              email_i = error(_("'GIT_AUTHOR_EMAIL' already given"));
 +                      else
 +                              email_i = i;
 +              } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_DATE")) {
 +                      if (date_i != -2)
 +                              date_i = error(_("'GIT_AUTHOR_DATE' already given"));
 +                      else
 +                              date_i = i;
 +              } else {
 +                      err = error(_("unknown variable '%s'"),
 +                                  kv.items[i].string);
 +              }
 +      }
 +      if (name_i == -2)
 +              error(_("missing 'GIT_AUTHOR_NAME'"));
 +      if (email_i == -2)
 +              error(_("missing 'GIT_AUTHOR_EMAIL'"));
 +      if (date_i == -2)
 +              error(_("missing 'GIT_AUTHOR_DATE'"));
 +      if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 +              goto finish;
 +      *name = kv.items[name_i].util;
 +      *email = kv.items[email_i].util;
 +      *date = kv.items[date_i].util;
 +      retval = 0;
 +finish:
 +      string_list_clear(&kv, !!retval);
 +      strbuf_release(&buf);
 +      return retval;
  }
  
  /*
 - * Read a list of environment variable assignments (such as the author-script
 - * file) into an environment block. Returns -1 on error, 0 otherwise.
 + * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL AND GIT_AUTHOR_DATE from a
 + * file with shell quoting into struct argv_array. Returns -1 on
 + * error, 0 otherwise.
   */
  static int read_env_script(struct argv_array *env)
  {
 -      struct strbuf script = STRBUF_INIT;
 -      int i, count = 0, sq_bug;
 -      const char *p2;
 -      char *p;
 +      char *name, *email, *date;
  
 -      if (strbuf_read_file(&script, rebase_path_author_script(), 256) <= 0)
 +      if (read_author_script(rebase_path_author_script(),
 +                             &name, &email, &date, 0))
                return -1;
 -      /* write_author_script() used to quote incorrectly */
 -      sq_bug = quoting_is_broken(script.buf, script.len);
 -      for (p = script.buf; *p; p++)
 -              if (sq_bug && skip_prefix(p, "'\\\\''", &p2))
 -                      strbuf_splice(&script, p - script.buf, p2 - p, "'", 1);
 -              else if (skip_prefix(p, "'\\''", &p2))
 -                      strbuf_splice(&script, p - script.buf, p2 - p, "'", 1);
 -              else if (*p == '\'')
 -                      strbuf_splice(&script, p-- - script.buf, 1, "", 0);
 -              else if (*p == '\n') {
 -                      *p = '\0';
 -                      count++;
 -              }
  
 -      for (i = 0, p = script.buf; i < count; i++) {
 -              argv_array_push(env, p);
 -              p += strlen(p) + 1;
 -      }
 +      argv_array_pushf(env, "GIT_AUTHOR_NAME=%s", name);
 +      argv_array_pushf(env, "GIT_AUTHOR_EMAIL=%s", email);
 +      argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
 +      free(name);
 +      free(email);
 +      free(date);
  
        return 0;
  }
@@@ -813,28 -744,54 +820,28 @@@ static char *get_author(const char *mes
  /* Read author-script and return an ident line (author <email> timestamp) */
  static const char *read_author_ident(struct strbuf *buf)
  {
 -      const char *keys[] = {
 -              "GIT_AUTHOR_NAME=", "GIT_AUTHOR_EMAIL=", "GIT_AUTHOR_DATE="
 -      };
        struct strbuf out = STRBUF_INIT;
 -      char *in, *eol;
 -      const char *val[3];
 -      int i = 0;
 +      char *name, *email, *date;
  
 -      if (strbuf_read_file(buf, rebase_path_author_script(), 256) <= 0)
 +      if (read_author_script(rebase_path_author_script(),
 +                             &name, &email, &date, 0))
                return NULL;
  
 -      /* dequote values and construct ident line in-place */
 -      for (in = buf->buf; i < 3 && in - buf->buf < buf->len; i++) {
 -              if (!skip_prefix(in, keys[i], (const char **)&in)) {
 -                      warning(_("could not parse '%s' (looking for '%s')"),
 -                              rebase_path_author_script(), keys[i]);
 -                      return NULL;
 -              }
 -
 -              eol = strchrnul(in, '\n');
 -              *eol = '\0';
 -              if (!sq_dequote(in)) {
 -                      warning(_("bad quoting on %s value in '%s'"),
 -                              keys[i], rebase_path_author_script());
 -                      return NULL;
 -              }
 -              val[i] = in;
 -              in = eol + 1;
 -      }
 -
 -      if (i < 3) {
 -              warning(_("could not parse '%s' (looking for '%s')"),
 -                      rebase_path_author_script(), keys[i]);
 -              return NULL;
 -      }
 -
        /* validate date since fmt_ident() will die() on bad value */
 -      if (parse_date(val[2], &out)){
 +      if (parse_date(date, &out)){
                warning(_("invalid date format '%s' in '%s'"),
 -                      val[2], rebase_path_author_script());
 +                      date, rebase_path_author_script());
                strbuf_release(&out);
                return NULL;
        }
  
        strbuf_reset(&out);
 -      strbuf_addstr(&out, fmt_ident(val[0], val[1], val[2], 0));
 +      strbuf_addstr(&out, fmt_ident(name, email, date, 0));
        strbuf_swap(buf, &out);
        strbuf_release(&out);
 +      free(name);
 +      free(email);
 +      free(date);
        return buf->buf;
  }
  
@@@ -888,7 -845,9 +895,9 @@@ static int run_command_silent_on_succes
   * interactive rebase: in that case, we will want to retain the
   * author metadata.
   */
- static int run_git_commit(const char *defmsg, struct replay_opts *opts,
+ static int run_git_commit(struct repository *r,
+                         const char *defmsg,
+                         struct replay_opts *opts,
                          unsigned int flags)
  {
        struct child_process cmd = CHILD_PROCESS_INIT;
                if (!defmsg)
                        BUG("root commit without message");
  
-               if (!(cache_tree_oid = get_cache_tree_oid()))
+               if (!(cache_tree_oid = get_cache_tree_oid(r->index)))
                        res = -1;
  
                if (!res)
@@@ -1120,7 -1079,9 +1129,9 @@@ void commit_post_rewrite(const struct c
        run_rewrite_hook(&old_head->object.oid, new_head);
  }
  
- static int run_prepare_commit_msg_hook(struct strbuf *msg, const char *commit)
+ static int run_prepare_commit_msg_hook(struct repository *r,
+                                      struct strbuf *msg,
+                                      const char *commit)
  {
        struct argv_array hook_env = ARGV_ARRAY_INIT;
        int ret;
        if (write_message(msg->buf, msg->len, name, 0))
                return -1;
  
-       argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", get_index_file());
+       argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", r->index_file);
        argv_array_push(&hook_env, "GIT_EDITOR=:");
        if (commit)
                ret = run_hook_le(hook_env.argv, "prepare-commit-msg", name,
@@@ -1186,7 -1147,9 +1197,9 @@@ static const char *implicit_ident_advic
  
  }
  
- void print_commit_summary(const char *prefix, const struct object_id *oid,
+ void print_commit_summary(struct repository *r,
+                         const char *prefix,
+                         const struct object_id *oid,
                          unsigned int flags)
  {
        struct rev_info rev;
        struct strbuf author_ident = STRBUF_INIT;
        struct strbuf committer_ident = STRBUF_INIT;
  
-       commit = lookup_commit(the_repository, oid);
+       commit = lookup_commit(r, oid);
        if (!commit)
                die(_("couldn't look up newly created commit"));
        if (parse_commit(commit))
        strbuf_release(&author_ident);
        strbuf_release(&committer_ident);
  
-       repo_init_revisions(the_repository, &rev, prefix);
+       repo_init_revisions(r, &rev, prefix);
        setup_revisions(0, NULL, &rev, NULL);
  
        rev.diff = 1;
        strbuf_release(&format);
  }
  
- static int parse_head(struct commit **head)
+ static int parse_head(struct repository *r, struct commit **head)
  {
        struct commit *current_head;
        struct object_id oid;
        if (get_oid("HEAD", &oid)) {
                current_head = NULL;
        } else {
-               current_head = lookup_commit_reference(the_repository, &oid);
+               current_head = lookup_commit_reference(r, &oid);
                if (!current_head)
                        return error(_("could not parse HEAD"));
                if (!oideq(&oid, &current_head->object.oid)) {
   *   0 - success
   *   1 - run 'git commit'
   */
- static int try_to_commit(struct strbuf *msg, const char *author,
+ static int try_to_commit(struct repository *r,
+                        struct strbuf *msg, const char *author,
                         struct replay_opts *opts, unsigned int flags,
                         struct object_id *oid)
  {
        enum commit_msg_cleanup_mode cleanup;
        int res = 0;
  
-       if (parse_head(&current_head))
+       if (parse_head(r, &current_head))
                return -1;
  
        if (flags & AMEND_MSG) {
                commit_list_insert(current_head, &parents);
        }
  
-       if (write_index_as_tree(&tree, &the_index, get_index_file(), 0, NULL)) {
+       if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
                res = error(_("git write-tree failed to write a tree"));
                goto out;
        }
        }
  
        if (find_hook("prepare-commit-msg")) {
-               res = run_prepare_commit_msg_hook(msg, hook_commit);
+               res = run_prepare_commit_msg_hook(r, msg, hook_commit);
                if (res)
                        goto out;
                if (strbuf_read_file(&commit_msg, git_path_commit_editmsg(),
@@@ -1402,7 -1366,8 +1416,8 @@@ out
        return res;
  }
  
- static int do_commit(const char *msg_file, const char *author,
+ static int do_commit(struct repository *r,
+                    const char *msg_file, const char *author,
                     struct replay_opts *opts, unsigned int flags)
  {
        int res = 1;
                                             "from '%s'"),
                                           msg_file);
  
-               res = try_to_commit(msg_file ? &sb : NULL, author, opts, flags,
-                                   &oid);
+               res = try_to_commit(r, msg_file ? &sb : NULL,
+                                   author, opts, flags, &oid);
                strbuf_release(&sb);
                if (!res) {
-                       unlink(git_path_cherry_pick_head(the_repository));
-                       unlink(git_path_merge_msg(the_repository));
+                       unlink(git_path_cherry_pick_head(r));
+                       unlink(git_path_merge_msg(r));
                        if (!is_rebase_i(opts))
-                               print_commit_summary(NULL, &oid,
+                               print_commit_summary(r, NULL, &oid,
                                                SUMMARY_SHOW_AUTHOR_DATE);
                        return res;
                }
        }
        if (res == 1)
-               return run_git_commit(msg_file, opts, flags);
+               return run_git_commit(r, msg_file, opts, flags);
  
        return res;
  }
@@@ -1458,7 -1423,9 +1473,9 @@@ static int is_original_commit_empty(str
  /*
   * Do we run "git commit" with "--allow-empty"?
   */
- static int allow_empty(struct replay_opts *opts, struct commit *commit)
+ static int allow_empty(struct repository *r,
+                      struct replay_opts *opts,
+                      struct commit *commit)
  {
        int index_unchanged, empty_commit;
  
        if (!opts->allow_empty)
                return 0; /* let "git commit" barf as necessary */
  
-       index_unchanged = is_index_unchanged();
+       index_unchanged = is_index_unchanged(r);
        if (index_unchanged < 0)
                return index_unchanged;
        if (!index_unchanged)
@@@ -1579,8 -1546,10 +1596,10 @@@ static int is_pick_or_similar(enum todo
        }
  }
  
- static int update_squash_messages(enum todo_command command,
-               struct commit *commit, struct replay_opts *opts)
+ static int update_squash_messages(struct repository *r,
+                                 enum todo_command command,
+                                 struct commit *commit,
+                                 struct replay_opts *opts)
  {
        struct strbuf buf = STRBUF_INIT;
        int res;
  
                if (get_oid("HEAD", &head))
                        return error(_("need a HEAD to fixup"));
-               if (!(head_commit = lookup_commit_reference(the_repository, &head)))
+               if (!(head_commit = lookup_commit_reference(r, &head)))
                        return error(_("could not read HEAD"));
                if (!(head_message = get_commit_buffer(head_commit, NULL)))
                        return error(_("could not read HEAD's commit message"));
@@@ -1708,11 -1677,14 +1727,14 @@@ static void record_in_rewritten(struct 
                flush_rewritten_pending();
  }
  
- static int do_pick_commit(enum todo_command command, struct commit *commit,
-               struct replay_opts *opts, int final_fixup)
+ static int do_pick_commit(struct repository *r,
+                         enum todo_command command,
+                         struct commit *commit,
+                         struct replay_opts *opts,
+                         int final_fixup)
  {
        unsigned int flags = opts->edit ? EDIT_MSG : 0;
-       const char *msg_file = opts->edit ? NULL : git_path_merge_msg(the_repository);
+       const char *msg_file = opts->edit ? NULL : git_path_merge_msg(r);
        struct object_id head;
        struct commit *base, *next, *parent;
        const char *base_label, *next_label;
                 * that represents the "current" state for merge-recursive
                 * to work on.
                 */
-               if (write_index_as_tree(&head, &the_index, get_index_file(), 0, NULL))
+               if (write_index_as_tree(&head, r->index, r->index_file, 0, NULL))
                        return error(_("your index file is unmerged."));
        } else {
                unborn = get_oid("HEAD", &head);
                        unborn = 1;
                } else if (unborn)
                        oidcpy(&head, the_hash_algo->empty_tree);
-               if (index_differs_from(unborn ? empty_tree_oid_hex() : "HEAD",
+               if (index_differs_from(r, unborn ? empty_tree_oid_hex() : "HEAD",
                                       NULL, 0))
-                       return error_dirty_index(opts);
+                       return error_dirty_index(r->index, opts);
        }
-       discard_cache();
+       discard_index(r->index);
  
        if (!commit->parents)
                parent = NULL;
             (!parent && unborn))) {
                if (is_rebase_i(opts))
                        write_author_script(msg.message);
-               res = fast_forward_to(&commit->object.oid, &head, unborn,
+               res = fast_forward_to(r, &commit->object.oid, &head, unborn,
                        opts);
                if (res || command != TODO_REWORD)
                        goto leave;
        if (command == TODO_REWORD)
                flags |= EDIT_MSG | VERIFY_MSG;
        else if (is_fixup(command)) {
-               if (update_squash_messages(command, commit, opts))
+               if (update_squash_messages(r, command, commit, opts))
                        return -1;
                flags |= AMEND_MSG;
                if (!final_fixup)
                        flags |= CLEANUP_MSG;
                        msg_file = rebase_path_fixup_msg();
                } else {
-                       const char *dest = git_path_squash_msg(the_repository);
+                       const char *dest = git_path_squash_msg(r);
                        unlink(dest);
                        if (copy_file(dest, rebase_path_squash_msg(), 0666))
                                return error(_("could not rename '%s' to '%s'"),
                                             rebase_path_squash_msg(), dest);
-                       unlink(git_path_merge_msg(the_repository));
+                       unlink(git_path_merge_msg(r));
                        msg_file = dest;
                        flags |= EDIT_MSG;
                }
        if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
                res = -1;
        else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
-               res = do_recursive_merge(base, next, base_label, next_label,
+               res = do_recursive_merge(r, base, next, base_label, next_label,
                                         &head, &msgbuf, opts);
                if (res < 0)
                        goto leave;
  
                res |= write_message(msgbuf.buf, msgbuf.len,
-                                    git_path_merge_msg(the_repository), 0);
+                                    git_path_merge_msg(r), 0);
        } else {
                struct commit_list *common = NULL;
                struct commit_list *remotes = NULL;
  
                res = write_message(msgbuf.buf, msgbuf.len,
-                                   git_path_merge_msg(the_repository), 0);
+                                   git_path_merge_msg(r), 0);
  
                commit_list_insert(base, &common);
                commit_list_insert(next, &remotes);
-               res |= try_merge_command(the_repository, opts->strategy,
+               res |= try_merge_command(r, opts->strategy,
                                         opts->xopts_nr, (const char **)opts->xopts,
                                        common, oid_to_hex(&head), remotes);
                free_commit_list(common);
                      ? _("could not revert %s... %s")
                      : _("could not apply %s... %s"),
                      short_commit_name(commit), msg.subject);
-               print_advice(res == 1, opts);
-               repo_rerere(the_repository, opts->allow_rerere_auto);
+               print_advice(r, res == 1, opts);
+               repo_rerere(r, opts->allow_rerere_auto);
                goto leave;
        }
  
-       allow = allow_empty(opts, commit);
+       allow = allow_empty(r, opts, commit);
        if (allow < 0) {
                res = allow;
                goto leave;
        if (!opts->no_commit) {
  fast_forward_edit:
                if (author || command == TODO_REVERT || (flags & AMEND_MSG))
-                       res = do_commit(msg_file, author, opts, flags);
+                       res = do_commit(r, msg_file, author, opts, flags);
                else
                        res = error(_("unable to parse commit author"));
        }
@@@ -1965,18 -1937,19 +1987,19 @@@ static int prepare_revs(struct replay_o
        return 0;
  }
  
- static int read_and_refresh_cache(struct replay_opts *opts)
+ static int read_and_refresh_cache(struct repository *r,
+                                 struct replay_opts *opts)
  {
        struct lock_file index_lock = LOCK_INIT;
        int index_fd = hold_locked_index(&index_lock, 0);
-       if (read_index(&the_index) < 0) {
 -      if (read_index_preload(r->index, NULL, 0) < 0) {
++      if (read_index(r->index) < 0) {
                rollback_lock_file(&index_lock);
                return error(_("git %s: failed to read the index"),
                        _(action_name(opts)));
        }
-       refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
+       refresh_index(r->index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
        if (index_fd >= 0) {
-               if (write_locked_index(&the_index, &index_lock,
+               if (write_locked_index(r->index, &index_lock,
                                       COMMIT_LOCK | SKIP_IF_UNCHANGED)) {
                        return error(_("git %s: failed to refresh the index"),
                                _(action_name(opts)));
@@@ -2021,7 -1994,8 +2044,8 @@@ static struct todo_item *append_new_tod
        return todo_list->items + todo_list->nr++;
  }
  
- static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
+ static int parse_insn_line(struct repository *r, struct todo_item *item,
+                          const char *bol, char *eol)
  {
        struct object_id commit_oid;
        char *end_of_object_name;
        if (status < 0)
                return -1;
  
-       item->commit = lookup_commit_reference(the_repository, &commit_oid);
+       item->commit = lookup_commit_reference(r, &commit_oid);
        return !item->commit;
  }
  
- static int parse_insn_buffer(char *buf, struct todo_list *todo_list)
+ static int parse_insn_buffer(struct repository *r, char *buf,
+                            struct todo_list *todo_list)
  {
        struct todo_item *item;
        char *p = buf, *next_p;
  
                item = append_new_todo(todo_list);
                item->offset_in_buf = p - todo_list->buf.buf;
-               if (parse_insn_line(item, p, eol)) {
+               if (parse_insn_line(r, item, p, eol)) {
                        res = error(_("invalid line %d: %.*s"),
                                i, (int)(eol - p), p);
                        item->command = TODO_NOOP;
@@@ -2187,8 -2162,9 +2212,9 @@@ static ssize_t strbuf_read_file_or_whin
        return len;
  }
  
- static int read_populate_todo(struct todo_list *todo_list,
-                       struct replay_opts *opts)
+ static int read_populate_todo(struct repository *r,
+                             struct todo_list *todo_list,
+                             struct replay_opts *opts)
  {
        struct stat st;
        const char *todo_file = get_todo_path(opts);
                return error(_("could not stat '%s'"), todo_file);
        fill_stat_data(&todo_list->stat, &st);
  
-       res = parse_insn_buffer(todo_list->buf.buf, todo_list);
+       res = parse_insn_buffer(r, todo_list->buf.buf, todo_list);
        if (res) {
                if (is_rebase_i(opts))
                        return error(_("please fix this using "
                FILE *f = fopen_or_warn(rebase_path_msgtotal(), "w");
  
                if (strbuf_read_file(&done.buf, rebase_path_done(), 0) > 0 &&
-                               !parse_insn_buffer(done.buf.buf, &done))
+                   !parse_insn_buffer(r, done.buf.buf, &done))
                        todo_list->done_nr = count_commands(&done);
                else
                        todo_list->done_nr = 0;
@@@ -2551,12 -2527,12 +2577,12 @@@ static int reset_for_rollback(const str
        return run_command_v_opt(argv, RUN_GIT_CMD);
  }
  
- static int rollback_single_pick(void)
+ static int rollback_single_pick(struct repository *r)
  {
        struct object_id head_oid;
  
-       if (!file_exists(git_path_cherry_pick_head(the_repository)) &&
-           !file_exists(git_path_revert_head(the_repository)))
+       if (!file_exists(git_path_cherry_pick_head(r)) &&
+           !file_exists(git_path_revert_head(r)))
                return error(_("no cherry-pick or revert in progress"));
        if (read_ref_full("HEAD", 0, &head_oid, NULL))
                return error(_("cannot resolve HEAD"));
        return reset_for_rollback(&head_oid);
  }
  
- int sequencer_rollback(struct replay_opts *opts)
+ int sequencer_rollback(struct repository *r, struct replay_opts *opts)
  {
        FILE *f;
        struct object_id oid;
                 * If CHERRY_PICK_HEAD or REVERT_HEAD indicates
                 * a single-cherry-pick in progress, abort that.
                 */
-               return rollback_single_pick();
+               return rollback_single_pick(r);
        }
        if (!f)
                return error_errno(_("cannot open '%s'"), git_path_head_file());
@@@ -2694,7 -2670,9 +2720,9 @@@ static int save_opts(struct replay_opt
        return res;
  }
  
- static int make_patch(struct commit *commit, struct replay_opts *opts)
+ static int make_patch(struct repository *r,
+                     struct commit *commit,
+                     struct replay_opts *opts)
  {
        struct strbuf buf = STRBUF_INIT;
        struct rev_info log_tree_opt;
  
        strbuf_addf(&buf, "%s/patch", get_dir(opts));
        memset(&log_tree_opt, 0, sizeof(log_tree_opt));
-       repo_init_revisions(the_repository, &log_tree_opt, NULL);
+       repo_init_revisions(r, &log_tree_opt, NULL);
        log_tree_opt.abbrev = 0;
        log_tree_opt.diff = 1;
        log_tree_opt.diffopt.output_format = DIFF_FORMAT_PATCH;
@@@ -2750,17 -2728,19 +2778,19 @@@ static int intend_to_amend(void
        return write_message(p, strlen(p), rebase_path_amend(), 1);
  }
  
- static int error_with_patch(struct commit *commit,
-       const char *subject, int subject_len,
-       struct replay_opts *opts, int exit_code, int to_amend)
+ static int error_with_patch(struct repository *r,
+                           struct commit *commit,
+                           const char *subject, int subject_len,
+                           struct replay_opts *opts,
+                           int exit_code, int to_amend)
  {
        if (commit) {
-               if (make_patch(commit, opts))
+               if (make_patch(r, commit, opts))
                        return -1;
        } else if (copy_file(rebase_path_message(),
-                            git_path_merge_msg(the_repository), 0666))
+                            git_path_merge_msg(r), 0666))
                return error(_("unable to copy '%s' to '%s'"),
-                            git_path_merge_msg(the_repository), rebase_path_message());
+                            git_path_merge_msg(r), rebase_path_message());
  
        if (to_amend) {
                if (intend_to_amend())
        return exit_code;
  }
  
- static int error_failed_squash(struct commit *commit,
-       struct replay_opts *opts, int subject_len, const char *subject)
+ static int error_failed_squash(struct repository *r,
+                              struct commit *commit,
+                              struct replay_opts *opts,
+                              int subject_len,
+                              const char *subject)
  {
        if (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))
                return error(_("could not copy '%s' to '%s'"),
                        rebase_path_squash_msg(), rebase_path_message());
-       unlink(git_path_merge_msg(the_repository));
-       if (copy_file(git_path_merge_msg(the_repository), rebase_path_message(), 0666))
+       unlink(git_path_merge_msg(r));
+       if (copy_file(git_path_merge_msg(r), rebase_path_message(), 0666))
                return error(_("could not copy '%s' to '%s'"),
                             rebase_path_message(),
-                            git_path_merge_msg(the_repository));
-       return error_with_patch(commit, subject, subject_len, opts, 1, 0);
+                            git_path_merge_msg(r));
+       return error_with_patch(r, commit, subject, subject_len, opts, 1, 0);
  }
  
- static int do_exec(const char *command_line)
+ static int do_exec(struct repository *r, const char *command_line)
  {
        struct argv_array child_env = ARGV_ARRAY_INIT;
        const char *child_argv[] = { NULL, NULL };
                                          child_env.argv);
  
        /* force re-reading of the cache */
-       if (discard_cache() < 0 || read_cache() < 0)
+       if (discard_index(r->index) < 0 || read_index(r->index) < 0)
                return error(_("could not read index"));
  
-       dirty = require_clean_work_tree("rebase", NULL, 1, 1);
+       dirty = require_clean_work_tree(r, "rebase", NULL, 1, 1);
  
        if (status) {
                warning(_("execution failed: %s\n%s"
@@@ -2889,9 -2872,9 +2922,9 @@@ static int safe_append(const char *file
        return 0;
  }
  
- static int do_label(const char *name, int len)
+ static int do_label(struct repository *r, const char *name, int len)
  {
-       struct ref_store *refs = get_main_ref_store(the_repository);
+       struct ref_store *refs = get_main_ref_store(r);
        struct ref_transaction *transaction;
        struct strbuf ref_name = STRBUF_INIT, err = STRBUF_INIT;
        struct strbuf msg = STRBUF_INIT;
  static const char *reflog_message(struct replay_opts *opts,
        const char *sub_action, const char *fmt, ...);
  
- static int do_reset(const char *name, int len, struct replay_opts *opts)
+ static int do_reset(struct repository *r,
+                   const char *name, int len,
+                   struct replay_opts *opts)
  {
        struct strbuf ref_name = STRBUF_INIT;
        struct object_id oid;
        struct tree_desc desc;
        struct tree *tree;
        struct unpack_trees_options unpack_tree_opts;
 -      int ret = 0, i;
 +      int ret = 0;
  
        if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0)
                return -1;
                }
                oidcpy(&oid, &opts->squash_onto);
        } else {
 +              int i;
 +
                /* Determine the length of the label */
                for (i = 0; i < len; i++)
                        if (isspace(name[i]))
 -                              len = i;
 +                              break;
 +              len = i;
  
                strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name);
                if (get_oid(ref_name.buf, &oid) &&
        memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
        setup_unpack_trees_porcelain(&unpack_tree_opts, "reset");
        unpack_tree_opts.head_idx = 1;
-       unpack_tree_opts.src_index = &the_index;
-       unpack_tree_opts.dst_index = &the_index;
+       unpack_tree_opts.src_index = r->index;
+       unpack_tree_opts.dst_index = r->index;
        unpack_tree_opts.fn = oneway_merge;
        unpack_tree_opts.merge = 1;
        unpack_tree_opts.update = 1;
  
-       if (read_cache_unmerged()) {
+       if (read_index_unmerged(r->index)) {
                rollback_lock_file(&lock);
                strbuf_release(&ref_name);
                return error_resolve_conflict(_(action_name(opts)));
        }
  
        tree = parse_tree_indirect(&oid);
-       prime_cache_tree(&the_index, tree);
+       prime_cache_tree(r, r->index, tree);
  
-       if (write_locked_index(&the_index, &lock, COMMIT_LOCK) < 0)
+       if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0)
                ret = error(_("could not write index"));
        free((void *)desc.buffer);
  
@@@ -3044,7 -3026,9 +3079,9 @@@ static struct commit *lookup_label(cons
        return commit;
  }
  
- static int do_merge(struct commit *commit, const char *arg, int arg_len,
+ static int do_merge(struct repository *r,
+                   struct commit *commit,
+                   const char *arg, int arg_len,
                    int flags, struct replay_opts *opts)
  {
        int run_commit_flags = (flags & TODO_EDIT_MERGE_MSG) ?
                        ret = error(_("octopus merge cannot be executed on "
                                      "top of a [new root]"));
                else
-                       ret = fast_forward_to(&to_merge->item->object.oid,
+                       ret = fast_forward_to(r, &to_merge->item->object.oid,
                                              &head_commit->object.oid, 0,
                                              opts);
                goto leave_merge;
                write_author_script(message);
                find_commit_subject(message, &body);
                len = strlen(body);
-               ret = write_message(body, len, git_path_merge_msg(the_repository), 0);
+               ret = write_message(body, len, git_path_merge_msg(r), 0);
                unuse_commit_buffer(commit, message);
                if (ret) {
                        error_errno(_("could not write '%s'"),
-                                   git_path_merge_msg(the_repository));
+                                   git_path_merge_msg(r));
                        goto leave_merge;
                }
        } else {
                        len = buf.len;
                }
  
-               ret = write_message(p, len, git_path_merge_msg(the_repository), 0);
+               ret = write_message(p, len, git_path_merge_msg(r), 0);
                strbuf_release(&buf);
                if (ret) {
                        error_errno(_("could not write '%s'"),
-                                   git_path_merge_msg(the_repository));
+                                   git_path_merge_msg(r));
                        goto leave_merge;
                }
        }
  
        if (can_fast_forward) {
                rollback_lock_file(&lock);
-               ret = fast_forward_to(&commit->object.oid,
+               ret = fast_forward_to(r, &commit->object.oid,
                                      &head_commit->object.oid, 0, opts);
                goto leave_merge;
        }
                argv_array_push(&cmd.args, "--no-log");
                argv_array_push(&cmd.args, "--no-stat");
                argv_array_push(&cmd.args, "-F");
-               argv_array_push(&cmd.args, git_path_merge_msg(the_repository));
+               argv_array_push(&cmd.args, git_path_merge_msg(r));
                if (opts->gpg_sign)
                        argv_array_push(&cmd.args, opts->gpg_sign);
  
                                        oid_to_hex(&j->item->object.oid));
  
                strbuf_release(&ref_name);
-               unlink(git_path_cherry_pick_head(the_repository));
+               unlink(git_path_cherry_pick_head(r));
                rollback_lock_file(&lock);
  
                rollback_lock_file(&lock);
                ret = run_command(&cmd);
  
                /* force re-reading of the cache */
-               if (!ret && (discard_cache() < 0 || read_cache() < 0))
+               if (!ret && (discard_index(r->index) < 0 ||
+                            read_index(r->index) < 0))
                        ret = error(_("could not read index"));
                goto leave_merge;
        }
  
        merge_commit = to_merge->item;
 -      write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ,
 -                    git_path_merge_head(r), 0);
 -      write_message("no-ff", 5, git_path_merge_mode(r), 0);
 -
        bases = get_merge_bases(head_commit, merge_commit);
        if (bases && oideq(&merge_commit->object.oid,
                           &bases->item->object.oid)) {
                goto leave_merge;
        }
  
-                     git_path_merge_head(the_repository), 0);
-       write_message("no-ff", 5, git_path_merge_mode(the_repository), 0);
 +      write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ,
++                    git_path_merge_head(r), 0);
++      write_message("no-ff", 5, git_path_merge_mode(r), 0);
 +
        for (j = bases; j; j = j->next)
                commit_list_insert(j->item, &reversed);
        free_commit_list(bases);
  
-       read_cache();
+       read_index(r->index);
        init_merge_options(&o);
        o.branch1 = "HEAD";
        o.branch2 = ref_name.buf;
         */
        ret = !ret;
  
-       if (active_cache_changed &&
-           write_locked_index(&the_index, &lock, COMMIT_LOCK)) {
+       if (r->index->cache_changed &&
+           write_locked_index(r->index, &lock, COMMIT_LOCK)) {
                ret = error(_("merge: Unable to write new index file"));
                goto leave_merge;
        }
  
        rollback_lock_file(&lock);
        if (ret)
-               repo_rerere(the_repository, opts->allow_rerere_auto);
+               repo_rerere(r, opts->allow_rerere_auto);
        else
                /*
                 * In case of problems, we now want to return a positive
                 * value (a negative one would indicate that the `merge`
                 * command needs to be rescheduled).
                 */
-               ret = !!run_git_commit(git_path_merge_msg(the_repository), opts,
-                                    run_commit_flags);
+               ret = !!run_git_commit(r, git_path_merge_msg(r), opts,
+                                      run_commit_flags);
  
  leave_merge:
        strbuf_release(&ref_name);
@@@ -3449,14 -3434,14 +3487,14 @@@ static int checkout_onto(struct replay_
        return update_ref(NULL, "ORIG_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
  }
  
- static int stopped_at_head(void)
+ static int stopped_at_head(struct repository *r)
  {
        struct object_id head;
        struct commit *commit;
        struct commit_message message;
  
        if (get_oid("HEAD", &head) ||
-           !(commit = lookup_commit(the_repository, &head)) ||
+           !(commit = lookup_commit(r, &head)) ||
            parse_commit(commit) || get_message(commit, &message))
                fprintf(stderr, _("Stopped at HEAD\n"));
        else {
@@@ -3478,7 -3463,9 +3516,9 @@@ N_("Could not execute the todo command\
  "    git rebase --edit-todo\n"
  "    git rebase --continue\n");
  
- static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
+ static int pick_commits(struct repository *r,
+                       struct todo_list *todo_list,
+                       struct replay_opts *opts)
  {
        int res = 0, reschedule = 0;
  
        if (opts->allow_ff)
                assert(!(opts->signoff || opts->no_commit ||
                                opts->record_origin || opts->edit));
-       if (read_and_refresh_cache(opts))
+       if (read_and_refresh_cache(r, opts))
                return -1;
  
        while (todo_list->current < todo_list->nr) {
                        unlink(rebase_path_author_script());
                        unlink(rebase_path_stopped_sha());
                        unlink(rebase_path_amend());
 +                      unlink(git_path_merge_head(the_repository));
                        delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
  
                        if (item->command == TODO_BREAK)
-                               return stopped_at_head();
+                               return stopped_at_head(r);
                }
                if (item->command <= TODO_SQUASH) {
                        if (is_rebase_i(opts))
                                setenv("GIT_REFLOG_ACTION", reflog_message(opts,
                                        command_to_string(item->command), NULL),
                                        1);
-                       res = do_pick_commit(item->command, item->commit,
+                       res = do_pick_commit(r, item->command, item->commit,
                                        opts, is_final_fixup(todo_list));
                        if (is_rebase_i(opts) && res < 0) {
                                /* Reschedule */
                                                _("Stopped at %s...  %.*s\n"),
                                                short_commit_name(commit),
                                                item->arg_len, item->arg);
-                               return error_with_patch(commit,
+                               return error_with_patch(r, commit,
                                        item->arg, item->arg_len, opts, res,
                                        !res);
                        }
                        if (res && is_fixup(item->command)) {
                                if (res == 1)
                                        intend_to_amend();
-                               return error_failed_squash(item->commit, opts,
+                               return error_failed_squash(r, item->commit, opts,
                                        item->arg_len, item->arg);
                        } else if (res && is_rebase_i(opts) && item->commit) {
                                int to_amend = 0;
                                      oideq(&opts->squash_onto, &oid))))
                                        to_amend = 1;
  
-                               return res | error_with_patch(item->commit,
+                               return res | error_with_patch(r, item->commit,
                                                item->arg, item->arg_len, opts,
                                                res, to_amend);
                        }
                        struct stat st;
  
                        *end_of_arg = '\0';
-                       res = do_exec(item->arg);
+                       res = do_exec(r, item->arg);
                        *end_of_arg = saved;
  
                        /* Reread the todo file if it has changed. */
                                                  get_todo_path(opts));
                        else if (match_stat_data(&todo_list->stat, &st)) {
                                todo_list_release(todo_list);
-                               if (read_populate_todo(todo_list, opts))
+                               if (read_populate_todo(r, todo_list, opts))
                                        res = -1; /* message was printed */
                                /* `current` will be incremented below */
                                todo_list->current = -1;
                        }
                } else if (item->command == TODO_LABEL) {
-                       if ((res = do_label(item->arg, item->arg_len)))
+                       if ((res = do_label(r, item->arg, item->arg_len)))
                                reschedule = 1;
                } else if (item->command == TODO_RESET) {
-                       if ((res = do_reset(item->arg, item->arg_len, opts)))
+                       if ((res = do_reset(r, item->arg, item->arg_len, opts)))
                                reschedule = 1;
                } else if (item->command == TODO_MERGE) {
-                       if ((res = do_merge(item->commit,
+                       if ((res = do_merge(r, item->commit,
                                            item->arg, item->arg_len,
                                            item->flags, opts)) < 0)
                                reschedule = 1;
                                                    peek_command(todo_list, 1));
                        if (res > 0)
                                /* failed with merge conflicts */
-                               return error_with_patch(item->commit,
+                               return error_with_patch(r, item->commit,
                                                        item->arg,
                                                        item->arg_len, opts,
                                                        res, 0);
                        if (save_todo(todo_list, opts))
                                return -1;
                        if (item->commit)
-                               return error_with_patch(item->commit,
+                               return error_with_patch(r,
+                                                       item->commit,
                                                        item->arg,
                                                        item->arg_len, opts,
                                                        res, 0);
@@@ -3695,7 -3682,7 +3736,7 @@@ cleanup_head_ref
                        struct object_id orig, head;
  
                        memset(&log_tree_opt, 0, sizeof(log_tree_opt));
-                       repo_init_revisions(the_repository, &log_tree_opt, NULL);
+                       repo_init_revisions(r, &log_tree_opt, NULL);
                        log_tree_opt.diff = 1;
                        log_tree_opt.diffopt.output_format =
                                DIFF_FORMAT_DIFFSTAT;
        return sequencer_remove_state(opts);
  }
  
- static int continue_single_pick(void)
+ static int continue_single_pick(struct repository *r)
  {
        const char *argv[] = { "commit", NULL };
  
-       if (!file_exists(git_path_cherry_pick_head(the_repository)) &&
-           !file_exists(git_path_revert_head(the_repository)))
+       if (!file_exists(git_path_cherry_pick_head(r)) &&
+           !file_exists(git_path_revert_head(r)))
                return error(_("no cherry-pick or revert in progress"));
        return run_command_v_opt(argv, RUN_GIT_CMD);
  }
  
- static int commit_staged_changes(struct replay_opts *opts,
+ static int commit_staged_changes(struct repository *r,
+                                struct replay_opts *opts,
                                 struct todo_list *todo_list)
  {
        unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
        unsigned int final_fixup = 0, is_clean;
  
-       if (has_unstaged_changes(1))
+       if (has_unstaged_changes(r, 1))
                return error(_("cannot rebase: You have unstaged changes."));
  
-       is_clean = !has_uncommitted_changes(0);
+       is_clean = !has_uncommitted_changes(r, 0);
  
        if (file_exists(rebase_path_amend())) {
                struct strbuf rev = STRBUF_INIT;
                                struct commit *commit;
                                const char *path = rebase_path_squash_msg();
  
-                               if (parse_head(&commit) ||
+                               if (parse_head(r, &commit) ||
                                    !(p = get_commit_buffer(commit, NULL)) ||
                                    write_message(p, strlen(p), path, 0)) {
                                        unuse_commit_buffer(commit, p);
        }
  
        if (is_clean) {
-               const char *cherry_pick_head = git_path_cherry_pick_head(the_repository);
+               const char *cherry_pick_head = git_path_cherry_pick_head(r);
  
                if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
                        return error(_("could not remove CHERRY_PICK_HEAD"));
                        return 0;
        }
  
-       if (run_git_commit(final_fixup ? NULL : rebase_path_message(),
+       if (run_git_commit(r, final_fixup ? NULL : rebase_path_message(),
                           opts, flags))
                return error(_("could not commit staged changes."));
        unlink(rebase_path_amend());
 +      unlink(git_path_merge_head(the_repository));
        if (final_fixup) {
                unlink(rebase_path_fixup_msg());
                unlink(rebase_path_squash_msg());
        return 0;
  }
  
- int sequencer_continue(struct replay_opts *opts)
+ int sequencer_continue(struct repository *r, struct replay_opts *opts)
  {
        struct todo_list todo_list = TODO_LIST_INIT;
        int res;
  
-       if (read_and_refresh_cache(opts))
+       if (read_and_refresh_cache(r, opts))
                return -1;
  
        if (read_populate_opts(opts))
                return -1;
        if (is_rebase_i(opts)) {
-               if ((res = read_populate_todo(&todo_list, opts)))
+               if ((res = read_populate_todo(r, &todo_list, opts)))
                        goto release_todo_list;
-               if (commit_staged_changes(opts, &todo_list))
+               if (commit_staged_changes(r, opts, &todo_list))
                        return -1;
        } else if (!file_exists(get_todo_path(opts)))
-               return continue_single_pick();
-       else if ((res = read_populate_todo(&todo_list, opts)))
+               return continue_single_pick(r);
+       else if ((res = read_populate_todo(r, &todo_list, opts)))
                goto release_todo_list;
  
        if (!is_rebase_i(opts)) {
                /* Verify that the conflict has been resolved */
-               if (file_exists(git_path_cherry_pick_head(the_repository)) ||
-                   file_exists(git_path_revert_head(the_repository))) {
-                       res = continue_single_pick();
+               if (file_exists(git_path_cherry_pick_head(r)) ||
+                   file_exists(git_path_revert_head(r))) {
+                       res = continue_single_pick(r);
                        if (res)
                                goto release_todo_list;
                }
-               if (index_differs_from("HEAD", NULL, 0)) {
-                       res = error_dirty_index(opts);
+               if (index_differs_from(r, "HEAD", NULL, 0)) {
+                       res = error_dirty_index(r->index, opts);
                        goto release_todo_list;
                }
                todo_list.current++;
                strbuf_release(&buf);
        }
  
-       res = pick_commits(&todo_list, opts);
+       res = pick_commits(r, &todo_list, opts);
  release_todo_list:
        todo_list_release(&todo_list);
        return res;
  }
  
- static int single_pick(struct commit *cmit, struct replay_opts *opts)
+ static int single_pick(struct repository *r,
+                      struct commit *cmit,
+                      struct replay_opts *opts)
  {
        setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
-       return do_pick_commit(opts->action == REPLAY_PICK ?
+       return do_pick_commit(r, opts->action == REPLAY_PICK ?
                TODO_PICK : TODO_REVERT, cmit, opts, 0);
  }
  
- int sequencer_pick_revisions(struct replay_opts *opts)
+ int sequencer_pick_revisions(struct repository *r,
+                            struct replay_opts *opts)
  {
        struct todo_list todo_list = TODO_LIST_INIT;
        struct object_id oid;
        int i, res;
  
        assert(opts->revs);
-       if (read_and_refresh_cache(opts))
+       if (read_and_refresh_cache(r, opts))
                return -1;
  
        for (i = 0; i < opts->revs->pending.nr; i++) {
                        continue;
  
                if (!get_oid(name, &oid)) {
-                       if (!lookup_commit_reference_gently(the_repository, &oid, 1)) {
-                               enum object_type type = oid_object_info(the_repository,
+                       if (!lookup_commit_reference_gently(r, &oid, 1)) {
+                               enum object_type type = oid_object_info(r,
                                                                        &oid,
                                                                        NULL);
                                return error(_("%s: can't cherry-pick a %s"),
                        return error(_("empty commit set passed"));
                if (get_revision(opts->revs))
                        BUG("unexpected extra commit from walk");
-               return single_pick(cmit, opts);
+               return single_pick(r, cmit, opts);
        }
  
        /*
        if (save_opts(opts))
                return -1;
        update_abort_safety_file();
-       res = pick_commits(&todo_list, opts);
+       res = pick_commits(r, &todo_list, opts);
        todo_list_release(&todo_list);
        return res;
  }
@@@ -4428,7 -4418,8 +4473,8 @@@ static int make_script_with_merges(stru
        return 0;
  }
  
- int sequencer_make_script(FILE *out, int argc, const char **argv,
+ int sequencer_make_script(struct repository *r, FILE *out,
+                         int argc, const char **argv,
                          unsigned flags)
  {
        char *format = NULL;
        const char *insn = flags & TODO_LIST_ABBREVIATE_CMDS ? "p" : "pick";
        int rebase_merges = flags & TODO_LIST_REBASE_MERGES;
  
-       repo_init_revisions(the_repository, &revs, NULL);
+       repo_init_revisions(r, &revs, NULL);
        revs.verbose_header = 1;
        if (!rebase_merges)
                revs.max_parents = 1;
   * Add commands after pick and (series of) squash/fixup commands
   * in the todo list.
   */
- int sequencer_add_exec_commands(const char *commands)
+ int sequencer_add_exec_commands(struct repository *r,
+                               const char *commands)
  {
        const char *todo_file = rebase_path_todo();
        struct todo_list todo_list = TODO_LIST_INIT;
        if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
                return error(_("could not read '%s'."), todo_file);
  
-       if (parse_insn_buffer(todo_list.buf.buf, &todo_list)) {
+       if (parse_insn_buffer(r, todo_list.buf.buf, &todo_list)) {
                todo_list_release(&todo_list);
                return error(_("unusable todo list: '%s'"), todo_file);
        }
        return i;
  }
  
- int transform_todos(unsigned flags)
+ int transform_todos(struct repository *r, unsigned flags)
  {
        const char *todo_file = rebase_path_todo();
        struct todo_list todo_list = TODO_LIST_INIT;
        if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
                return error(_("could not read '%s'."), todo_file);
  
-       if (parse_insn_buffer(todo_list.buf.buf, &todo_list)) {
+       if (parse_insn_buffer(r, todo_list.buf.buf, &todo_list)) {
                todo_list_release(&todo_list);
                return error(_("unusable todo list: '%s'"), todo_file);
        }
@@@ -4629,7 -4621,7 +4676,7 @@@ define_commit_slab(commit_seen, unsigne
   * Check if there is an unrecognized command or a
   * bad SHA-1 in a command.
   */
- int check_todo_list(void)
+ int check_todo_list(struct repository *r)
  {
        enum missing_commit_check_level check_level = get_missing_commit_check_level();
        struct strbuf todo_file = STRBUF_INIT;
                goto leave_check;
        }
        advise_to_edit_todo = res =
-               parse_insn_buffer(todo_list.buf.buf, &todo_list);
+               parse_insn_buffer(r, todo_list.buf.buf, &todo_list);
  
        if (res || check_level == MISSING_COMMIT_CHECK_IGNORE)
                goto leave_check;
                goto leave_check;
        }
        strbuf_release(&todo_file);
-       res = !!parse_insn_buffer(todo_list.buf.buf, &todo_list);
+       res = !!parse_insn_buffer(r, todo_list.buf.buf, &todo_list);
  
        /* Find commits in git-rebase-todo.backup yet unseen */
        for (i = todo_list.nr - 1; i >= 0; i--) {
@@@ -4729,7 -4721,7 +4776,7 @@@ static int rewrite_file(const char *pat
  }
  
  /* skip picking commits whose parents are unchanged */
- static int skip_unnecessary_picks(struct object_id *output_oid)
+ static int skip_unnecessary_picks(struct repository *r, struct object_id *output_oid)
  {
        const char *todo_file = rebase_path_todo();
        struct strbuf buf = STRBUF_INIT;
  
        if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
                return -1;
-       if (parse_insn_buffer(todo_list.buf.buf, &todo_list) < 0) {
+       if (parse_insn_buffer(r, todo_list.buf.buf, &todo_list) < 0) {
                todo_list_release(&todo_list);
                return -1;
        }
        return 0;
  }
  
- int complete_action(struct replay_opts *opts, unsigned flags,
+ int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
                    const char *shortrevisions, const char *onto_name,
                    const char *onto, const char *orig_head, const char *cmd,
                    unsigned autosquash)
            write_message("noop\n", 5, todo_file, 0))
                return -1;
  
-       if (autosquash && rearrange_squash())
+       if (autosquash && rearrange_squash(r))
                return -1;
  
        if (cmd && *cmd)
-               sequencer_add_exec_commands(cmd);
+               sequencer_add_exec_commands(r, cmd);
  
        if (strbuf_read_file(buf, todo_file, 0) < 0)
                return error_errno(_("could not read '%s'."), todo_file);
  
-       if (parse_insn_buffer(buf->buf, &todo_list)) {
+       if (parse_insn_buffer(r, buf->buf, &todo_list)) {
                todo_list_release(&todo_list);
                return error(_("unusable todo list: '%s'"), todo_file);
        }
                return error(_("could not copy '%s' to '%s'."), todo_file,
                             rebase_path_todo_backup());
  
-       if (transform_todos(flags | TODO_LIST_SHORTEN_IDS))
+       if (transform_todos(r, flags | TODO_LIST_SHORTEN_IDS))
                return error(_("could not transform the todo list"));
  
        strbuf_reset(buf);
  
        todo_list_release(&todo_list);
  
-       if (check_todo_list()) {
+       if (check_todo_list(r)) {
                checkout_onto(opts, onto_name, onto, orig_head);
                return -1;
        }
  
-       if (transform_todos(flags & ~(TODO_LIST_SHORTEN_IDS)))
+       if (transform_todos(r, flags & ~(TODO_LIST_SHORTEN_IDS)))
                return error(_("could not transform the todo list"));
  
-       if (opts->allow_ff && skip_unnecessary_picks(&oid))
+       if (opts->allow_ff && skip_unnecessary_picks(r, &oid))
                return error(_("could not skip unnecessary pick commands"));
  
        if (checkout_onto(opts, onto_name, oid_to_hex(&oid), orig_head))
                return -1;
 -;
 +
-       if (require_clean_work_tree("rebase", "", 1, 1))
+       if (require_clean_work_tree(r, "rebase", "", 1, 1))
                return -1;
  
-       return sequencer_continue(opts);
+       return sequencer_continue(r, opts);
  }
  
  struct subject2item_entry {
@@@ -4932,7 -4924,7 +4979,7 @@@ define_commit_slab(commit_todo_item, st
   * message will have to be retrieved from the commit (as the oneline in the
   * script cannot be trusted) in order to normalize the autosquash arrangement.
   */
- int rearrange_squash(void)
+ int rearrange_squash(struct repository *r)
  {
        const char *todo_file = rebase_path_todo();
        struct todo_list todo_list = TODO_LIST_INIT;
  
        if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
                return -1;
-       if (parse_insn_buffer(todo_list.buf.buf, &todo_list) < 0) {
+       if (parse_insn_buffer(r, todo_list.buf.buf, &todo_list) < 0) {
                todo_list_release(&todo_list);
                return -1;
        }
diff --combined sequencer.h
index 5071a73563f1cdfc35060603d1fef4e085497798,d2c18edd3ae150b665dd4ecc0c104d30d09a1211..9d83f0f3e90313be990439972845e9d4f2bc1804
@@@ -5,6 -5,7 +5,7 @@@
  #include "strbuf.h"
  
  struct commit;
+ struct repository;
  
  const char *git_path_commit_editmsg(void);
  const char *git_path_seq_dir(void);
@@@ -74,9 -75,10 +75,10 @@@ int write_message(const void *buf, size
  
  /* Call this to setup defaults before parsing command line options */
  void sequencer_init_config(struct replay_opts *opts);
- int sequencer_pick_revisions(struct replay_opts *opts);
- int sequencer_continue(struct replay_opts *opts);
- int sequencer_rollback(struct replay_opts *opts);
+ int sequencer_pick_revisions(struct repository *repo,
+                            struct replay_opts *opts);
+ int sequencer_continue(struct repository *repo, struct replay_opts *opts);
+ int sequencer_rollback(struct repository *repo, struct replay_opts *opts);
  int sequencer_remove_state(struct replay_opts *opts);
  
  #define TODO_LIST_KEEP_EMPTY (1U << 0)
   * commits should be rebased onto the new base, this flag needs to be passed.
   */
  #define TODO_LIST_REBASE_COUSINS (1U << 4)
- int sequencer_make_script(FILE *out, int argc, const char **argv,
+ int sequencer_make_script(struct repository *repo, FILE *out,
+                         int argc, const char **argv,
                          unsigned flags);
  
- int sequencer_add_exec_commands(const char *command);
- int transform_todos(unsigned flags);
+ int sequencer_add_exec_commands(struct repository *r, const char *command);
+ int transform_todos(struct repository *r, unsigned flags);
  enum missing_commit_check_level get_missing_commit_check_level(void);
- int check_todo_list(void);
- int complete_action(struct replay_opts *opts, unsigned flags,
+ int check_todo_list(struct repository *r);
+ int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
                    const char *shortrevisions, const char *onto_name,
                    const char *onto, const char *orig_head, const char *cmd,
                    unsigned autosquash);
- int rearrange_squash(void);
+ int rearrange_squash(struct repository *r);
  
  extern const char sign_off_header[];
  
   */
  void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag);
  
- void append_conflicts_hint(struct strbuf *msgbuf);
+ void append_conflicts_hint(struct index_state *istate, struct strbuf *msgbuf);
  int message_is_empty(const struct strbuf *sb,
                     enum commit_msg_cleanup_mode cleanup_mode);
  int template_untouched(const struct strbuf *sb, const char *template_file,
@@@ -128,11 -131,10 +131,13 @@@ int prepare_branch_to_be_rebased(struc
  
  #define SUMMARY_INITIAL_COMMIT   (1 << 0)
  #define SUMMARY_SHOW_AUTHOR_DATE (1 << 1)
- void print_commit_summary(const char *prefix, const struct object_id *oid,
+ void print_commit_summary(struct repository *repo,
+                         const char *prefix,
+                         const struct object_id *oid,
                          unsigned int flags);
 +
 +int read_author_script(const char *path, char **name, char **email, char **date,
 +                     int allow_missing);
  #endif
  
  void parse_strategy_opts(struct replay_opts *opts, char *raw_opts);
diff --combined wt-status.c
index a24711374c41918bed46fbe5d5a3060312917fa6,e582c54238719f50143f68229b1e0cf8a9ac9571..0fe3bcd4cd057b72a61cfc6d46e892ac890f0634
@@@ -119,9 -119,10 +119,10 @@@ static void status_printf_more(struct w
        va_end(ap);
  }
  
- void wt_status_prepare(struct wt_status *s)
+ void wt_status_prepare(struct repository *r, struct wt_status *s)
  {
        memset(s, 0, sizeof(*s));
+       s->repo = r;
        memcpy(s->color_palette, default_wt_status_colors,
               sizeof(default_wt_status_colors));
        s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
@@@ -494,19 -495,19 +495,19 @@@ static void wt_status_collect_changed_c
        }
  }
  
- static int unmerged_mask(const char *path)
+ static int unmerged_mask(struct index_state *istate, const char *path)
  {
        int pos, mask;
        const struct cache_entry *ce;
  
-       pos = cache_name_pos(path, strlen(path));
+       pos = index_name_pos(istate, path, strlen(path));
        if (0 <= pos)
                return 0;
  
        mask = 0;
        pos = -pos-1;
-       while (pos < active_nr) {
-               ce = active_cache[pos++];
+       while (pos < istate->cache_nr) {
+               ce = istate->cache[pos++];
                if (strcmp(ce->name, path) || !ce_stage(ce))
                        break;
                mask |= (1 << (ce_stage(ce) - 1));
@@@ -566,7 -567,8 +567,8 @@@ static void wt_status_collect_updated_c
                        s->committable = 1;
                        break;
                case DIFF_STATUS_UNMERGED:
-                       d->stagemask = unmerged_mask(p->two->path);
+                       d->stagemask = unmerged_mask(s->repo->index,
+                                                    p->two->path);
                        /*
                         * Don't bother setting {mode,oid}_{head,index} since the print
                         * code will output the stage values directly and not use the
@@@ -585,7 -587,7 +587,7 @@@ static void wt_status_collect_changes_w
  {
        struct rev_info rev;
  
-       repo_init_revisions(the_repository, &rev, NULL);
+       repo_init_revisions(s->repo, &rev, NULL);
        setup_revisions(0, NULL, &rev, NULL);
        rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
        rev.diffopt.flags.dirty_submodules = 1;
@@@ -610,7 -612,7 +612,7 @@@ static void wt_status_collect_changes_i
        struct rev_info rev;
        struct setup_revision_opt opt;
  
-       repo_init_revisions(the_repository, &rev, NULL);
+       repo_init_revisions(s->repo, &rev, NULL);
        memset(&opt, 0, sizeof(opt));
        opt.def = s->is_initial ? empty_tree_oid_hex() : s->reference;
        setup_revisions(0, NULL, &rev, &opt);
  
  static void wt_status_collect_changes_initial(struct wt_status *s)
  {
+       struct index_state *istate = s->repo->index;
        int i;
  
-       for (i = 0; i < active_nr; i++) {
+       for (i = 0; i < istate->cache_nr; i++) {
                struct string_list_item *it;
                struct wt_status_change_data *d;
-               const struct cache_entry *ce = active_cache[i];
+               const struct cache_entry *ce = istate->cache[i];
  
-               if (!ce_path_match(&the_index, ce, &s->pathspec, NULL))
+               if (!ce_path_match(istate, ce, &s->pathspec, NULL))
                        continue;
                if (ce_intent_to_add(ce))
                        continue;
@@@ -684,6 -687,7 +687,7 @@@ static void wt_status_collect_untracked
        int i;
        struct dir_struct dir;
        uint64_t t_begin = getnanotime();
+       struct index_state *istate = s->repo->index;
  
        if (!s->show_untracked_files)
                return;
                if (s->show_ignored_mode == SHOW_MATCHING_IGNORED)
                        dir.flags |= DIR_SHOW_IGNORED_TOO_MODE_MATCHING;
        } else {
-               dir.untracked = the_index.untracked;
+               dir.untracked = istate->untracked;
        }
  
        setup_standard_excludes(&dir);
  
-       fill_directory(&dir, &the_index, &s->pathspec);
+       fill_directory(&dir, istate, &s->pathspec);
  
        for (i = 0; i < dir.nr; i++) {
                struct dir_entry *ent = dir.entries[i];
-               if (cache_name_is_other(ent->name, ent->len) &&
-                   dir_path_match(&the_index, ent, &s->pathspec, 0, NULL))
+               if (index_name_is_other(istate, ent->name, ent->len) &&
+                   dir_path_match(istate, ent, &s->pathspec, 0, NULL))
                        string_list_insert(&s->untracked, ent->name);
                free(ent);
        }
  
        for (i = 0; i < dir.ignored_nr; i++) {
                struct dir_entry *ent = dir.ignored[i];
-               if (cache_name_is_other(ent->name, ent->len) &&
-                   dir_path_match(&the_index, ent, &s->pathspec, 0, NULL))
+               if (index_name_is_other(istate, ent->name, ent->len) &&
+                   dir_path_match(istate, ent, &s->pathspec, 0, NULL))
                        string_list_insert(&s->ignored, ent->name);
                free(ent);
        }
@@@ -751,7 -755,7 +755,7 @@@ void wt_status_collect(struct wt_statu
                wt_status_collect_changes_index(s);
        wt_status_collect_untracked(s);
  
-       wt_status_get_state(&s->state, s->branch && !strcmp(s->branch, "HEAD"));
+       wt_status_get_state(s->repo, &s->state, s->branch && !strcmp(s->branch, "HEAD"));
        if (s->state.merge_in_progress && !has_unmerged(s))
                s->committable = 1;
  }
@@@ -1009,7 -1013,7 +1013,7 @@@ static void wt_longstatus_print_verbose
        int dirty_submodules;
        const char *c = color(WT_STATUS_HEADER, s);
  
-       repo_init_revisions(the_repository, &rev, NULL);
+       repo_init_revisions(s->repo, &rev, NULL);
        rev.diffopt.flags.allow_textconv = 1;
        rev.diffopt.ita_invisible_in_index = 1;
  
@@@ -1326,7 -1330,7 +1330,7 @@@ static void show_rebase_in_progress(str
                                _("  (use \"git rebase --abort\" to check out the original branch)"));
                }
        } else if (s->state.rebase_in_progress ||
-                  !stat(git_path_merge_msg(the_repository), &st)) {
+                  !stat(git_path_merge_msg(s->repo), &st)) {
                print_rebase_state(s, color);
                if (s->hints)
                        status_printf_ln(s, color,
@@@ -1478,7 -1482,8 +1482,8 @@@ static int grab_1st_switch(struct objec
        return 1;
  }
  
- static void wt_status_get_detached_from(struct wt_status_state *state)
+ static void wt_status_get_detached_from(struct repository *r,
+                                       struct wt_status_state *state)
  {
        struct grab_1st_switch_cbdata cb;
        struct commit *commit;
            /* sha1 is a commit? match without further lookup */
            (oideq(&cb.noid, &oid) ||
             /* perhaps sha1 is a tag, try to dereference to a commit */
-            ((commit = lookup_commit_reference_gently(the_repository, &oid, 1)) != NULL &&
+            ((commit = lookup_commit_reference_gently(r, &oid, 1)) != NULL &&
              oideq(&cb.noid, &commit->object.oid)))) {
                const char *from = ref;
                if (!skip_prefix(from, "refs/tags/", &from))
@@@ -1552,31 -1557,31 +1557,32 @@@ int wt_status_check_bisect(const struc
        return 0;
  }
  
- void wt_status_get_state(struct wt_status_state *state,
+ void wt_status_get_state(struct repository *r,
+                        struct wt_status_state *state,
                         int get_detached_from)
  {
        struct stat st;
        struct object_id oid;
  
-       if (!stat(git_path_merge_head(the_repository), &st)) {
+       if (!stat(git_path_merge_head(r), &st)) {
 +              wt_status_check_rebase(NULL, state);
                state->merge_in_progress = 1;
        } else if (wt_status_check_rebase(NULL, state)) {
                ;               /* all set */
-       } else if (!stat(git_path_cherry_pick_head(the_repository), &st) &&
+       } else if (!stat(git_path_cherry_pick_head(r), &st) &&
                        !get_oid("CHERRY_PICK_HEAD", &oid)) {
                state->cherry_pick_in_progress = 1;
                oidcpy(&state->cherry_pick_head_oid, &oid);
        }
        wt_status_check_bisect(NULL, state);
-       if (!stat(git_path_revert_head(the_repository), &st) &&
+       if (!stat(git_path_revert_head(r), &st) &&
            !get_oid("REVERT_HEAD", &oid)) {
                state->revert_in_progress = 1;
                oidcpy(&state->revert_head_oid, &oid);
        }
  
        if (get_detached_from)
-               wt_status_get_detached_from(state);
+               wt_status_get_detached_from(r, state);
  }
  
  static void wt_longstatus_print_state(struct wt_status *s)
        const char *state_color = color(WT_STATUS_HEADER, s);
        struct wt_status_state *state = &s->state;
  
 -      if (state->merge_in_progress)
 +      if (state->merge_in_progress) {
 +              if (state->rebase_interactive_in_progress) {
 +                      show_rebase_information(s, state_color);
 +                      fputs("\n", s->fp);
 +              }
                show_merge_in_progress(s, state_color);
 -      else if (state->am_in_progress)
 +      else if (state->am_in_progress)
                show_am_in_progress(s, state_color);
        else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
                show_rebase_in_progress(s, state_color);
@@@ -2140,6 -2141,7 +2146,7 @@@ static void wt_porcelain_v2_print_unmer
        struct wt_status *s)
  {
        struct wt_status_change_data *d = it->util;
+       struct index_state *istate = s->repo->index;
        const struct cache_entry *ce;
        struct strbuf buf_index = STRBUF_INIT;
        const char *path_index = NULL;
         */
        memset(stages, 0, sizeof(stages));
        sum = 0;
-       pos = cache_name_pos(it->string, strlen(it->string));
+       pos = index_name_pos(istate, it->string, strlen(it->string));
        assert(pos < 0);
        pos = -pos-1;
-       while (pos < active_nr) {
-               ce = active_cache[pos++];
+       while (pos < istate->cache_nr) {
+               ce = istate->cache[pos++];
                stage = ce_stage(ce);
                if (strcmp(ce->name, it->string) || !stage)
                        break;
@@@ -2307,12 -2309,12 +2314,12 @@@ void wt_status_print(struct wt_status *
  /**
   * Returns 1 if there are unstaged changes, 0 otherwise.
   */
- int has_unstaged_changes(int ignore_submodules)
+ int has_unstaged_changes(struct repository *r, int ignore_submodules)
  {
        struct rev_info rev_info;
        int result;
  
-       repo_init_revisions(the_repository, &rev_info, NULL);
+       repo_init_revisions(r, &rev_info, NULL);
        if (ignore_submodules) {
                rev_info.diffopt.flags.ignore_submodules = 1;
                rev_info.diffopt.flags.override_submodule_config = 1;
  /**
   * Returns 1 if there are uncommitted changes, 0 otherwise.
   */
- int has_uncommitted_changes(int ignore_submodules)
+ int has_uncommitted_changes(struct repository *r,
+                           int ignore_submodules)
  {
        struct rev_info rev_info;
        int result;
  
-       if (is_cache_unborn())
+       if (is_index_unborn(r->index))
                return 0;
  
-       repo_init_revisions(the_repository, &rev_info, NULL);
+       repo_init_revisions(r, &rev_info, NULL);
        if (ignore_submodules)
                rev_info.diffopt.flags.ignore_submodules = 1;
        rev_info.diffopt.flags.quick = 1;
                 * We have no head (or it's corrupt); use the empty tree,
                 * which will complain if the index is non-empty.
                 */
-               struct tree *tree = lookup_tree(the_repository, the_hash_algo->empty_tree);
+               struct tree *tree = lookup_tree(r, the_hash_algo->empty_tree);
                add_pending_object(&rev_info, &tree->object, "");
        }
  
   * If the work tree has unstaged or uncommitted changes, dies with the
   * appropriate message.
   */
- int require_clean_work_tree(const char *action, const char *hint, int ignore_submodules, int gently)
+ int require_clean_work_tree(struct repository *r,
+                           const char *action,
+                           const char *hint,
+                           int ignore_submodules,
+                           int gently)
  {
        struct lock_file lock_file = LOCK_INIT;
        int err = 0, fd;
  
        fd = hold_locked_index(&lock_file, 0);
-       refresh_cache(REFRESH_QUIET);
+       refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL);
        if (0 <= fd)
-               update_index_if_able(&the_index, &lock_file);
+               update_index_if_able(r->index, &lock_file);
        rollback_lock_file(&lock_file);
  
-       if (has_unstaged_changes(ignore_submodules)) {
+       if (has_unstaged_changes(r, ignore_submodules)) {
                /* TRANSLATORS: the action is e.g. "pull with rebase" */
                error(_("cannot %s: You have unstaged changes."), _(action));
                err = 1;
        }
  
-       if (has_uncommitted_changes(ignore_submodules)) {
+       if (has_uncommitted_changes(r, ignore_submodules)) {
                if (err)
                        error(_("additionally, your index contains uncommitted changes."));
                else