Merge branch 'nd/the-index-final'
authorJunio C Hamano <gitster@pobox.com>
Thu, 7 Feb 2019 06:05:22 +0000 (22:05 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 7 Feb 2019 06:05:23 +0000 (22:05 -0800)
The assumption to work on the single "in-core index" instance has
been reduced from the library-ish part of the codebase.

* nd/the-index-final:
cache.h: flip NO_THE_INDEX_COMPATIBILITY_MACROS switch
read-cache.c: remove the_* from index_has_changes()
merge-recursive.c: remove implicit dependency on the_repository
merge-recursive.c: remove implicit dependency on the_index
sha1-name.c: remove implicit dependency on the_index
read-cache.c: replace update_index_if_able with repo_&
read-cache.c: kill read_index()
checkout: avoid the_index when possible
repository.c: replace hold_locked_index() with repo_hold_locked_index()
notes-utils.c: remove the_repository references
grep: use grep_opt->repo instead of explict repo argument

38 files changed:
1  2 
apply.c
attr.c
builtin/add.c
builtin/am.c
builtin/cat-file.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clone.c
builtin/commit.c
builtin/difftool.c
builtin/fsck.c
builtin/grep.c
builtin/log.c
builtin/ls-files.c
builtin/merge-recursive.c
builtin/merge-tree.c
builtin/pack-objects.c
builtin/rebase--interactive.c
builtin/rebase.c
builtin/submodule--helper.c
cache.h
convert.c
dir.c
git.c
list-objects-filter-options.c
merge-recursive.c
pathspec.c
read-cache.c
repository.c
repository.h
revision.c
sequencer.c
sequencer.h
sha1-name.c
submodule.c
t/helper/test-tool.h
tree.c
unpack-trees.c
diff --combined apply.c
index 3703bfc8d03deb3be3a3fa9a45a2dd64b0a8eafd,e040c0b957be27c3f805ae3280d160161358a3ce..f489a56f39c9a5f9541e5709d883c9d41d629193
+++ b/apply.c
@@@ -3352,8 -3352,7 +3352,8 @@@ static int checkout_target(struct index
  
        costate.refresh_cache = 1;
        costate.istate = istate;
 -      if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st))
 +      if (checkout_entry(ce, &costate, NULL, NULL) ||
 +          lstat(ce->name, st))
                return error(_("cannot checkout %s"), ce->name);
        return 0;
  }
@@@ -4020,7 -4019,7 +4020,7 @@@ static int read_apply_cache(struct appl
                return read_index_from(state->repo->index, state->index_file,
                                       get_git_dir());
        else
-               return read_index(state->repo->index);
+               return repo_read_index(state->repo);
  }
  
  /* This function tries to read the object name from the current index */
@@@ -4713,7 -4712,8 +4713,8 @@@ static int apply_patch(struct apply_sta
                                                  state->index_file,
                                                  LOCK_DIE_ON_ERROR);
                else
-                       hold_locked_index(&state->lock_file, LOCK_DIE_ON_ERROR);
+                       repo_hold_locked_index(state->repo, &state->lock_file,
+                                              LOCK_DIE_ON_ERROR);
        }
  
        if (state->check_index && read_apply_cache(state) < 0) {
diff --combined attr.c
index 0cba78912907e35a26e43156e124912467e46b27,e4e4574857dd086301279cbac51a4e11fb65f093..fdd110bec55cb3bc5c8ebbb8cffbc33cced530b2
--- 1/attr.c
--- 2/attr.c
+++ b/attr.c
@@@ -7,7 -7,6 +7,6 @@@
   * an insanely large number of attributes.
   */
  
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "exec-cmd.h"
@@@ -1092,7 -1091,7 +1091,7 @@@ static void collect_some_attrs(const st
                               const char *path,
                               struct attr_check *check)
  {
 -      int i, pathlen, rem, dirlen;
 +      int pathlen, rem, dirlen;
        const char *cp, *last_slash = NULL;
        int basename_offset;
  
        all_attrs_init(&g_attr_hashmap, check);
        determine_macros(check->all_attrs, check->stack);
  
 -      if (check->nr) {
 -              rem = 0;
 -              for (i = 0; i < check->nr; i++) {
 -                      int n = check->items[i].attr->attr_nr;
 -                      struct all_attrs_item *item = &check->all_attrs[n];
 -                      if (item->macro) {
 -                              item->value = ATTR__UNSET;
 -                              rem++;
 -                      }
 -              }
 -              if (rem == check->nr)
 -                      return;
 -      }
 -
        rem = check->all_attrs_nr;
        fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
  }
diff --combined builtin/add.c
index 7c2a7c5a4d4aa619e81ef61a69b619b7c96b8ac5,81df0d34dec18bfded5100075ebffc1a19a3f48e..db2dfa43502d0059219189f01731e143982345ab
@@@ -3,6 -3,7 +3,7 @@@
   *
   * Copyright (C) 2006 Linus Torvalds
   */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "builtin.h"
@@@ -137,7 -138,7 +138,7 @@@ static int renormalize_tracked_files(co
                        continue; /* do not touch non blobs */
                if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
                        continue;
 -              retval |= add_file_to_cache(ce->name, flags | HASH_RENORMALIZE);
 +              retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE);
        }
  
        return retval;
@@@ -176,7 -177,7 +177,7 @@@ static void refresh(int verbose, const 
                        die(_("pathspec '%s' did not match any files"),
                            pathspec->items[i].match);
        }
 -        free(seen);
 +      free(seen);
  }
  
  int run_add_interactive(const char *revision, const char *patch_mode,
@@@ -239,7 -240,7 +240,7 @@@ static int edit_patch(int argc, const c
        rev.diffopt.output_format = DIFF_FORMAT_PATCH;
        rev.diffopt.use_color = 0;
        rev.diffopt.flags.ignore_dirty_submodules = 1;
 -      out = open(file, O_CREAT | O_WRONLY, 0666);
 +      out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
        if (out < 0)
                die(_("Could not open '%s' for writing."), file);
        rev.diffopt.file = xfdopen(out, "w");
diff --combined builtin/am.c
index 0cc399729205a3adfc8afe0d211bdba13e1a3977,ad913ef20e18b177055a0d10895b267b9128b82f..58a2aef28bbcd715660422dc37042e79d4d350c1
@@@ -3,6 -3,7 +3,7 @@@
   *
   * Based on git-am.sh by Junio C Hamano.
   */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "builtin.h"
  #include "packfile.h"
  #include "repository.h"
  
 -/**
 - * Returns 1 if the file is empty or does not exist, 0 otherwise.
 - */
 -static int is_empty_file(const char *filename)
 -{
 -      struct stat st;
 -
 -      if (stat(filename, &st) < 0) {
 -              if (errno == ENOENT)
 -                      return 1;
 -              die_errno(_("could not stat %s"), filename);
 -      }
 -
 -      return !st.st_size;
 -}
 -
  /**
   * Returns the length of the first line of msg.
   */
@@@ -511,7 -528,7 +512,7 @@@ static int copy_notes_for_rebase(const 
        }
  
  finish:
-       finish_copy_notes_for_rewrite(c, msg);
+       finish_copy_notes_for_rewrite(the_repository, c, msg);
        fclose(fp);
        strbuf_release(&sb);
        return ret;
@@@ -1204,7 -1221,7 +1205,7 @@@ static int parse_mail(struct am_state *
                goto finish;
        }
  
 -      if (is_empty_file(am_path(state, "patch"))) {
 +      if (is_empty_or_missing_file(am_path(state, "patch"))) {
                printf_ln(_("Patch is empty."));
                die_user_resolve(state);
        }
@@@ -1529,7 -1546,7 +1530,7 @@@ static int fall_back_threeway(const str
         * changes.
         */
  
-       init_merge_options(&o);
+       init_merge_options(&o, the_repository);
  
        o.branch1 = "HEAD";
        their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
@@@ -1703,7 -1720,7 +1704,7 @@@ static void am_run(struct am_state *sta
  
        refresh_and_write_cache();
  
-       if (index_has_changes(&the_index, NULL, &sb)) {
+       if (repo_index_has_changes(the_repository, NULL, &sb)) {
                write_state_bool(state, "dirtyindex", 1);
                die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf);
        }
                         * the result may have produced the same tree as ours.
                         */
                        if (!apply_status &&
-                           !index_has_changes(&the_index, NULL, NULL)) {
+                           !repo_index_has_changes(the_repository, NULL, NULL)) {
                                say(state, stdout, _("No changes -- Patch already applied."));
                                goto next;
                        }
@@@ -1787,7 -1804,7 +1788,7 @@@ next
                resume = 0;
        }
  
 -      if (!is_empty_file(am_path(state, "rewritten"))) {
 +      if (!is_empty_or_missing_file(am_path(state, "rewritten"))) {
                assert(state->rebasing);
                copy_notes_for_rebase(state);
                run_post_rewrite_hook(state);
@@@ -1815,7 -1832,7 +1816,7 @@@ static void am_resolve(struct am_state 
  
        say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
  
-       if (!index_has_changes(&the_index, NULL, NULL)) {
+       if (!repo_index_has_changes(the_repository, NULL, NULL)) {
                printf_ln(_("No changes - did you forget to use 'git add'?\n"
                        "If there is nothing left to stage, chances are that something else\n"
                        "already introduced the same changes; you might want to skip this patch."));
@@@ -1984,15 -2001,6 +1985,15 @@@ static void am_skip(struct am_state *st
        if (clean_index(&head, &head))
                die(_("failed to clean index"));
  
 +      if (state->rebasing) {
 +              FILE *fp = xfopen(am_path(state, "rewritten"), "a");
 +
 +              assert(!is_null_oid(&state->orig_commit));
 +              fprintf(fp, "%s ", oid_to_hex(&state->orig_commit));
 +              fprintf(fp, "%s\n", oid_to_hex(&head));
 +              fclose(fp);
 +      }
 +
        am_next(state);
        am_load(state);
        am_run(state, 0);
@@@ -2271,7 -2279,7 +2272,7 @@@ int cmd_am(int argc, const char **argv
        /* Ensure a valid committer ident can be constructed */
        git_committer_info(IDENT_STRICT);
  
-       if (read_index_preload(&the_index, NULL, 0) < 0)
+       if (repo_read_index_preload(the_repository, NULL, 0) < 0)
                die(_("failed to read the index"));
  
        if (in_progress) {
diff --combined builtin/cat-file.c
index cebc6d7f8a197495e7c87f6b2430f340dc224891,a5ca47c697e6ef363a40224916fd451554120fb8..8487cd7dba0681087a5700039c234084f071333c
@@@ -3,6 -3,7 +3,7 @@@
   *
   * Copyright (C) Linus Torvalds, 2005
   */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "builtin.h"
@@@ -73,7 -74,8 +74,8 @@@ static int cat_one_file(int opt, const 
        if (unknown_type)
                flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
  
-       if (get_oid_with_context(obj_name, GET_OID_RECORD_PATH,
+       if (get_oid_with_context(the_repository, obj_name,
+                                GET_OID_RECORD_PATH,
                                 &oid, &obj_context))
                die("Not a valid object name %s", obj_name);
  
@@@ -380,17 -382,15 +382,18 @@@ static void batch_one_object(const cha
  {
        struct object_context ctx;
        int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
 -      enum follow_symlinks_result result;
 +      enum get_oid_result result;
  
-       result = get_oid_with_context(obj_name, flags, &data->oid, &ctx);
+       result = get_oid_with_context(the_repository, obj_name,
+                                     flags, &data->oid, &ctx);
        if (result != FOUND) {
                switch (result) {
                case MISSING_OBJECT:
                        printf("%s missing\n", obj_name);
                        break;
 +              case SHORT_NAME_AMBIGUOUS:
 +                      printf("%s ambiguous\n", obj_name);
 +                      break;
                case DANGLING_SYMLINK:
                        printf("dangling %"PRIuMAX"\n%s\n",
                               (uintmax_t)strlen(obj_name), obj_name);
diff --combined builtin/checkout-index.c
index a2a726ad8d8fa65d2fbcd1b111d71bad61c5cee8,345591bc4b5c5462e18046face3f8ce956483c9a..1ac1cc290ed7db86d3ae42b7df2246dad1c507e3
@@@ -4,6 -4,7 +4,7 @@@
   * Copyright (C) 2005 Linus Torvalds
   *
   */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "config.h"
  #include "lockfile.h"
@@@ -67,8 -68,7 +68,8 @@@ static int checkout_file(const char *na
                        continue;
                did_checkout = 1;
                if (checkout_entry(ce, &state,
 -                  to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
 +                                 to_tempfile ? topath[ce_stage(ce)] : NULL,
 +                                 NULL) < 0)
                        errs++;
        }
  
@@@ -112,8 -112,7 +113,8 @@@ static void checkout_all(const char *pr
                                write_tempfile_record(last_ce->name, prefix);
                }
                if (checkout_entry(ce, &state,
 -                  to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
 +                                 to_tempfile ? topath[ce_stage(ce)] : NULL,
 +                                 NULL) < 0)
                        errs++;
                last_ce = ce;
        }
diff --combined builtin/checkout.c
index 9f8f3466f66d8845a60719cc608375b71679d4b4,0446cac05e72befa69f61ff200fbd17befa7796f..ece4eb14bf1e92742b9fc0723a150e595883d8c6
@@@ -1,3 -1,4 +1,4 @@@
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "config.h"
  #include "checkout.h"
@@@ -44,7 -45,6 +45,7 @@@ struct checkout_opts 
        int ignore_skipworktree;
        int ignore_other_worktrees;
        int show_progress;
 +      int count_checkout_paths;
        /*
         * If new checkout options are added, skip_merge_working_tree
         * should be updated accordingly.
@@@ -116,8 -116,7 +117,8 @@@ static int update_some(const struct obj
  
  static int read_tree_some(struct tree *tree, const struct pathspec *pathspec)
  {
 -      read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL);
 +      read_tree_recursive(the_repository, tree, "", 0, 0,
 +                          pathspec, update_some, NULL);
  
        /* update the index with the given tree's info
         * for all args, expanding wildcards, and exit
@@@ -167,13 -166,12 +168,13 @@@ static int check_stages(unsigned stages
  }
  
  static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
 -                        const struct checkout *state)
 +                        const struct checkout *state, int *nr_checkouts)
  {
        while (pos < active_nr &&
               !strcmp(active_cache[pos]->name, ce->name)) {
                if (ce_stage(active_cache[pos]) == stage)
 -                      return checkout_entry(active_cache[pos], state, NULL);
 +                      return checkout_entry(active_cache[pos], state,
 +                                            NULL, nr_checkouts);
                pos++;
        }
        if (stage == 2)
                return error(_("path '%s' does not have their version"), ce->name);
  }
  
 -static int checkout_merged(int pos, const struct checkout *state)
 +static int checkout_merged(int pos, const struct checkout *state, int *nr_checkouts)
  {
        struct cache_entry *ce = active_cache[pos];
        const char *path = ce->name;
        ce = make_transient_cache_entry(mode, &oid, path, 2);
        if (!ce)
                die(_("make_cache_entry failed for path '%s'"), path);
 -      status = checkout_entry(ce, state, NULL);
 +      status = checkout_entry(ce, state, NULL, nr_checkouts);
        discard_cache_entry(ce);
        return status;
  }
@@@ -260,7 -258,6 +261,7 @@@ static int checkout_paths(const struct 
        struct commit *head;
        int errs = 0;
        struct lock_file lock_file = LOCK_INIT;
 +      int nr_checkouts = 0;
  
        if (opts->track != BRANCH_TRACK_UNSPECIFIED)
                die(_("'%s' cannot be used with updating paths"), "--track");
                return run_add_interactive(revision, "--patch=checkout",
                                           &opts->pathspec);
  
-       hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
+       repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
        if (read_cache_preload(&opts->pathspec) < 0)
                return error(_("index file corrupt"));
  
                struct cache_entry *ce = active_cache[pos];
                if (ce->ce_flags & CE_MATCHED) {
                        if (!ce_stage(ce)) {
 -                              errs |= checkout_entry(ce, &state, NULL);
 +                              errs |= checkout_entry(ce, &state,
 +                                                     NULL, &nr_checkouts);
                                continue;
                        }
                        if (opts->writeout_stage)
 -                              errs |= checkout_stage(opts->writeout_stage, ce, pos, &state);
 +                              errs |= checkout_stage(opts->writeout_stage,
 +                                                     ce, pos,
 +                                                     &state, &nr_checkouts);
                        else if (opts->merge)
 -                              errs |= checkout_merged(pos, &state);
 +                              errs |= checkout_merged(pos, &state,
 +                                                      &nr_checkouts);
                        pos = skip_same_name(ce, pos) - 1;
                }
        }
 -      errs |= finish_delayed_checkout(&state);
 +      errs |= finish_delayed_checkout(&state, &nr_checkouts);
 +
 +      if (opts->count_checkout_paths) {
 +              if (opts->source_tree)
 +                      fprintf_ln(stderr, Q_("Checked out %d path out of %s",
 +                                            "Checked out %d paths out of %s",
 +                                            nr_checkouts),
 +                                 nr_checkouts,
 +                                 find_unique_abbrev(&opts->source_tree->object.oid,
 +                                                    DEFAULT_ABBREV));
 +              else
 +                      fprintf_ln(stderr, Q_("Checked out %d path out of the index",
 +                                            "Checked out %d paths out of the index",
 +                                            nr_checkouts),
 +                                 nr_checkouts);
 +      }
  
        if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
                die(_("unable to write new index file"));
@@@ -592,14 -570,6 +593,14 @@@ static int skip_merge_working_tree(cons
         * Remaining variables are not checkout options but used to track state
         */
  
 +       /*
 +        * Do the merge if this is the initial checkout. We cannot use
 +        * is_cache_unborn() here because the index hasn't been loaded yet
 +        * so cache_nr and timestamp.sec are always zero.
 +        */
 +      if (!file_exists(get_index_file()))
 +              return 0;
 +
        return 1;
  }
  
@@@ -701,7 -671,7 +702,7 @@@ static int merge_working_tree(const str
                         * a pain; plumb in an option to set
                         * o.renormalize?
                         */
-                       init_merge_options(&o);
+                       init_merge_options(&o, the_repository);
                        o.verbosity = 0;
                        work = write_tree_from_memory(&o);
  
@@@ -1096,7 -1066,6 +1097,7 @@@ static int parse_branchname_arg(int arg
                has_dash_dash = 1; /* case (3) or (1) */
        else if (dash_dash_pos >= 2)
                die(_("only one reference expected, %d given."), dash_dash_pos);
 +      opts->count_checkout_paths = !opts->quiet && !has_dash_dash;
  
        if (!strcmp(arg, "-"))
                arg = "@{-1}";
diff --combined builtin/clone.c
index 739de68820c52a3d24f8f256bb36ed72877740b6,ddb3230d2165c7969e8192520cb17be567835354..50bde9961809b1d55c74fb6d3cbfbf5a86ddf5c7
@@@ -8,6 -8,7 +8,7 @@@
   * Clone a repository into a different directory that does not yet exist.
   */
  
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "config.h"
  #include "lockfile.h"
@@@ -1136,13 -1137,9 +1137,13 @@@ int cmd_clone(int argc, const char **ar
                                     option_upload_pack);
  
        if (filter_options.choice) {
 +              struct strbuf expanded_filter_spec = STRBUF_INIT;
 +              expand_list_objects_filter_spec(&filter_options,
 +                                              &expanded_filter_spec);
                transport_set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
 -                                   filter_options.filter_spec);
 +                                   expanded_filter_spec.buf);
                transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
 +              strbuf_release(&expanded_filter_spec);
        }
  
        if (transport->smart_options && !deepen && !filter_options.choice)
diff --combined builtin/commit.c
index 7d2e0b61e5fc73a9b338a4f37b9a51ddc6cbf306,2f4af02a27281ca9b7dc7cd579c53680f9d41b56..2986553d5ffb97f0798e4d4eb921073439fb9a92
@@@ -5,6 -5,7 +5,7 @@@
   * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
   */
  
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "lockfile.h"
@@@ -351,7 -352,7 +352,7 @@@ static const char *prepare_index(int ar
                if (write_locked_index(&the_index, &index_lock, 0))
                        die(_("unable to create temporary index"));
  
 -              old_index_env = getenv(INDEX_ENVIRONMENT);
 +              old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
                setenv(INDEX_ENVIRONMENT, get_lock_file_path(&index_lock), 1);
  
                if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
                        setenv(INDEX_ENVIRONMENT, old_index_env, 1);
                else
                        unsetenv(INDEX_ENVIRONMENT);
 +              FREE_AND_NULL(old_index_env);
  
                discard_cache();
                read_cache_from(get_lock_file_path(&index_lock));
@@@ -1368,7 -1368,7 +1369,7 @@@ int cmd_status(int argc, const char **a
        if (status_format != STATUS_FORMAT_PORCELAIN &&
            status_format != STATUS_FORMAT_PORCELAIN_V2)
                progress_flag = REFRESH_PROGRESS;
-       read_index(&the_index);
+       repo_read_index(the_repository);
        refresh_index(&the_index,
                      REFRESH_QUIET|REFRESH_UNMERGED|progress_flag,
                      &s.pathspec, NULL, NULL);
        wt_status_collect(&s);
  
        if (0 <= fd)
-               update_index_if_able(&the_index, &index_lock);
+               repo_update_index_if_able(the_repository, &index_lock);
  
        if (s.relative_paths)
                s.prefix = prefix;
@@@ -1675,7 -1675,7 +1676,7 @@@ int cmd_commit(int argc, const char **a
        run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
        run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
        if (amend && !no_post_rewrite) {
-               commit_post_rewrite(current_head, &oid);
+               commit_post_rewrite(the_repository, current_head, &oid);
        }
        if (!quiet) {
                unsigned int flags = 0;
diff --combined builtin/difftool.c
index 71318c26e177e8aa4176201e4f23e6f43b63b630,eeb9e370b9c5b3d11fb9f4774aee7cdf952e3b51..a3ea60ea71428ee59ab20a67f6e9ccf76c841f85
@@@ -11,6 -11,7 +11,7 @@@
   *
   * Copyright (C) 2016 Johannes Schindelin
   */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "builtin.h"
@@@ -323,7 -324,7 +324,7 @@@ static int checkout_path(unsigned mode
        int ret;
  
        ce = make_transient_cache_entry(mode, oid, path, 0);
 -      ret = checkout_entry(ce, state, NULL);
 +      ret = checkout_entry(ce, state, NULL, NULL);
  
        discard_cache_entry(ce);
        return ret;
diff --combined builtin/fsck.c
index 9c4c11d0adedc7ebd5c48f8c786c6780394f22b1,46f6ea9baa909bf5aeec43a08461ad2328d5eb13..bb4227bebc606dfac8337d7aa3e78705113a79b5
@@@ -1,3 -1,4 +1,4 @@@
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "cache.h"
  #include "repository.h"
@@@ -401,8 -402,7 +402,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;
  }
  
diff --combined builtin/grep.c
index dd52ea968baf1b5b971c5f59152a561744cf9b92,39a8e9d4a35a02e3bba8c43f77def39fa8f75bb2..580fd38f41704b6d534c04f2dee1bf85eee67c3c
@@@ -3,6 -3,7 +3,7 @@@
   *
   * Copyright (c) 2006 Junio C Hamano
   */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "repository.h"
  #include "config.h"
@@@ -393,21 -394,20 +394,22 @@@ static void run_pager(struct grep_opt *
                exit(status);
  }
  
- static int grep_cache(struct grep_opt *opt, struct repository *repo,
+ static int grep_cache(struct grep_opt *opt,
                      const struct pathspec *pathspec, int cached);
  static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                     struct tree_desc *tree, struct strbuf *base, int tn_len,
-                    int check_attr, struct repository *repo);
+                    int check_attr);
  
- static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
+ static int grep_submodule(struct grep_opt *opt,
                          const struct pathspec *pathspec,
                          const struct object_id *oid,
                          const char *filename, const char *path)
  {
 -      struct repository submodule;
 +      struct repository subrepo;
+       struct repository *superproject = opt->repo;
 +      const struct submodule *sub = submodule_from_path(superproject,
 +                                                        &null_oid, path);
+       struct grep_opt subopt;
        int hit;
  
        /*
                return 0;
        }
  
 -      if (repo_submodule_init(&submodule, superproject, path)) {
 +      if (repo_submodule_init(&subrepo, superproject, sub)) {
                grep_read_unlock();
                return 0;
        }
  
 -      repo_read_gitmodules(&submodule);
 +      repo_read_gitmodules(&subrepo);
  
        /*
         * NEEDSWORK: This adds the submodule's object directory to the list of
         * store is no longer global and instead is a member of the repository
         * object.
         */
 -      add_to_alternates_memory(submodule.objects->odb->path);
 +      add_to_alternates_memory(subrepo.objects->odb->path);
        grep_read_unlock();
  
 -      subopt.repo = &submodule;
+       memcpy(&subopt, opt, sizeof(subopt));
++      subopt.repo = &subrepo;
        if (oid) {
                struct object *object;
                struct tree_desc tree;
                strbuf_addch(&base, '/');
  
                init_tree_desc(&tree, data, size);
-               hit = grep_tree(opt, pathspec, &tree, &base, base.len,
-                               object->type == OBJ_COMMIT, &subrepo);
+               hit = grep_tree(&subopt, pathspec, &tree, &base, base.len,
+                               object->type == OBJ_COMMIT);
                strbuf_release(&base);
                free(data);
        } else {
-               hit = grep_cache(opt, &subrepo, pathspec, 1);
+               hit = grep_cache(&subopt, pathspec, 1);
        }
  
 -      repo_clear(&submodule);
 +      repo_clear(&subrepo);
        return hit;
  }
  
- static int grep_cache(struct grep_opt *opt, struct repository *repo,
+ static int grep_cache(struct grep_opt *opt,
                      const struct pathspec *pathspec, int cached)
  {
+       struct repository *repo = opt->repo;
        int hit = 0;
        int nr;
        struct strbuf name = STRBUF_INIT;
                        }
                } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
                           submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
-                       hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name);
+                       hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
                } else {
                        continue;
                }
  
  static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                     struct tree_desc *tree, struct strbuf *base, int tn_len,
-                    int check_attr, struct repository *repo)
+                    int check_attr)
  {
+       struct repository *repo = opt->repo;
        int hit = 0;
        enum interesting match = entry_not_interesting;
        struct name_entry entry;
  
                if (match != all_entries_interesting) {
                        strbuf_addstr(&name, base->buf + tn_len);
 -                      match = tree_entry_interesting(&entry, &name,
 +                      match = tree_entry_interesting(repo->index,
 +                                                     &entry, &name,
                                                       0, pathspec);
                        strbuf_setlen(&name, name_base_len);
  
                strbuf_add(base, entry.path, te_len);
  
                if (S_ISREG(entry.mode)) {
 -                      hit |= grep_oid(opt, entry.oid, base->buf, tn_len,
 +                      hit |= grep_oid(opt, &entry.oid, base->buf, tn_len,
                                         check_attr ? base->buf + tn_len : NULL);
                } else if (S_ISDIR(entry.mode)) {
                        enum object_type type;
                        void *data;
                        unsigned long size;
  
 -                      data = lock_and_read_oid_file(entry.oid, &type, &size);
 +                      data = lock_and_read_oid_file(&entry.oid, &type, &size);
                        if (!data)
                                die(_("unable to read tree (%s)"),
 -                                  oid_to_hex(entry.oid));
 +                                  oid_to_hex(&entry.oid));
  
                        strbuf_addch(base, '/');
                        init_tree_desc(&sub, data, size);
                        hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
-                                        check_attr, repo);
+                                        check_attr);
                        free(data);
                } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
-                       hit |= grep_submodule(opt, repo, pathspec, &entry.oid,
 -                      hit |= grep_submodule(opt, pathspec, entry.oid,
++                      hit |= grep_submodule(opt, pathspec, &entry.oid,
                                              base->buf, base->buf + tn_len);
                }
  
@@@ -631,7 -635,7 +638,7 @@@ static int grep_object(struct grep_opt 
                }
                init_tree_desc(&tree, data, size);
                hit = grep_tree(opt, pathspec, &tree, &base, base.len,
-                               obj->type == OBJ_COMMIT, the_repository);
+                               obj->type == OBJ_COMMIT);
                strbuf_release(&base);
                free(data);
                return hit;
@@@ -648,12 -652,12 +655,12 @@@ static int grep_objects(struct grep_op
  
        for (i = 0; i < nr; i++) {
                struct object *real_obj;
-               real_obj = deref_tag(the_repository, list->objects[i].item,
+               real_obj = deref_tag(opt->repo, list->objects[i].item,
                                     NULL, 0);
  
                /* load the gitmodules file for this rev */
                if (recurse_submodules) {
-                       submodule_free(the_repository);
+                       submodule_free(opt->repo);
                        gitmodules_config_oid(&real_obj->oid);
                }
                if (grep_object(opt, pathspec, real_obj, list->objects[i].name,
@@@ -678,9 -682,9 +685,9 @@@ static int grep_directory(struct grep_o
        if (exc_std)
                setup_standard_excludes(&dir);
  
-       fill_directory(&dir, &the_index, pathspec);
+       fill_directory(&dir, opt->repo->index, pathspec);
        for (i = 0; i < dir.nr; i++) {
-               if (!dir_path_match(&the_index, dir.entries[i], pathspec, 0, NULL))
+               if (!dir_path_match(opt->repo->index, dir.entries[i], pathspec, 0, NULL))
                        continue;
                hit |= grep_file(opt, dir.entries[i]->name);
                if (hit && opt->status_only)
@@@ -1018,7 -1022,8 +1025,8 @@@ int cmd_grep(int argc, const char **arg
                        break;
                }
  
-               if (get_oid_with_context(arg, GET_OID_RECORD_PATH,
+               if (get_oid_with_context(the_repository, arg,
+                                        GET_OID_RECORD_PATH,
                                         &oid, &oc)) {
                        if (seen_dashdash)
                                die(_("unable to resolve revision: %s"), arg);
                if (!cached)
                        setup_work_tree();
  
-               hit = grep_cache(&opt, the_repository, &pathspec, cached);
+               hit = grep_cache(&opt, &pathspec, cached);
        } else {
                if (cached)
                        die(_("both --cached and trees are given"));
diff --combined builtin/log.c
index c91a59dec16f43771629715f112899e2bb2b0214,195ff0b4713fd3b126125a56b30814f12bb8b4c9..57869267d8d75e06a1a34e4dea104102aac21a65
@@@ -4,6 -4,7 +4,7 @@@
   * (C) Copyright 2006 Linus Torvalds
   *             2006 Junio Hamano
   */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "refs.h"
@@@ -203,7 -204,7 +204,7 @@@ static void cmd_log_init_finish(int arg
            rev->diffopt.filter || rev->diffopt.flags.follow_renames)
                rev->always_show_header = 0;
  
 -      if (source) {
 +      if (source || w.source) {
                init_revision_sources(&revision_sources);
                rev->sources = &revision_sources;
        }
@@@ -397,8 -398,7 +398,8 @@@ static int cmd_log_walk(struct rev_inf
                         * We may show a given commit multiple times when
                         * walking the reflogs.
                         */
 -                      free_commit_buffer(commit);
 +                      free_commit_buffer(the_repository->parsed_objects,
 +                                         commit);
                        free_commit_list(commit->parents);
                        commit->parents = NULL;
                }
@@@ -509,7 -509,8 +510,8 @@@ static int show_blob_object(const struc
            !rev->diffopt.flags.allow_textconv)
                return stream_blob_to_fd(1, oid, NULL, 0);
  
-       if (get_oid_with_context(obj_name, GET_OID_RECORD_PATH,
+       if (get_oid_with_context(the_repository, obj_name,
+                                GET_OID_RECORD_PATH,
                                 &oidc, &obj_context))
                die(_("Not a valid object name %s"), obj_name);
        if (!obj_context.path ||
@@@ -642,9 -643,8 +644,9 @@@ int cmd_show(int argc, const char **arg
                                        diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        name,
                                        diff_get_color_opt(&rev.diffopt, DIFF_RESET));
 -                      read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
 -                                      show_tree_object, rev.diffopt.file);
 +                      read_tree_recursive(the_repository, (struct tree *)o, "",
 +                                          0, 0, &match_all, show_tree_object,
 +                                          rev.diffopt.file);
                        rev.shown_one = 1;
                        break;
                case OBJ_COMMIT:
@@@ -1941,8 -1941,7 +1943,8 @@@ int cmd_format_patch(int argc, const ch
                    open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
                        die(_("Failed to create output files"));
                shown = log_tree_commit(&rev, commit);
 -              free_commit_buffer(commit);
 +              free_commit_buffer(the_repository->parsed_objects,
 +                                 commit);
  
                /* We put one extra blank line between formatted
                 * patches and this flag is used by log-tree code
diff --combined builtin/ls-files.c
index cde87cbeeb8e8d7389c95c33ff60e6e5c39e10cd,7cc7ec22c96d30bed42b67279de1413115f47689..29a8762d46eb7aa9a9b456e2564062fdbdb48a06
@@@ -5,7 -5,6 +5,6 @@@
   *
   * Copyright (C) Linus Torvalds, 2005
   */
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "repository.h"
  #include "config.h"
@@@ -206,19 -205,17 +205,19 @@@ static void show_files(struct repositor
  static void show_submodule(struct repository *superproject,
                           struct dir_struct *dir, const char *path)
  {
 -      struct repository submodule;
 +      struct repository subrepo;
 +      const struct submodule *sub = submodule_from_path(superproject,
 +                                                        &null_oid, path);
  
 -      if (repo_submodule_init(&submodule, superproject, path))
 +      if (repo_submodule_init(&subrepo, superproject, sub))
                return;
  
 -      if (repo_read_index(&submodule) < 0)
 +      if (repo_read_index(&subrepo) < 0)
                die("index file corrupt");
  
 -      show_files(&submodule, dir);
 +      show_files(&subrepo, dir);
  
 -      repo_clear(&submodule);
 +      repo_clear(&subrepo);
  }
  
  static void show_ce(struct repository *repo, struct dir_struct *dir,
@@@ -443,7 -440,7 +442,7 @@@ void overlay_tree_on_index(struct index
                               PATHSPEC_PREFER_CWD, prefix, matchbuf);
        } else
                memset(&pathspec, 0, sizeof(pathspec));
 -      if (read_tree(tree, 1, &pathspec, istate))
 +      if (read_tree(the_repository, tree, 1, &pathspec, istate))
                die("unable to read tree entries %s", tree_name);
  
        for (i = 0; i < istate->cache_nr; i++) {
index 7545136c2a6da526ab7998106f2a28bfcbe8bd81,4864f7b22f3d11a2b28f0653031ee2f74f946e91..5b910e351e4dede4527d23a04a8294e17ebd371c
@@@ -7,16 -7,16 +7,16 @@@
  static const char builtin_merge_recursive_usage[] =
        "git %s <base>... -- <head> <remote> ...";
  
 -static const char *better_branch_name(const char *branch)
 +static char *better_branch_name(const char *branch)
  {
        static char githead_env[8 + GIT_MAX_HEXSZ + 1];
        char *name;
  
        if (strlen(branch) != the_hash_algo->hexsz)
 -              return branch;
 +              return xstrdup(branch);
        xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch);
        name = getenv(githead_env);
 -      return name ? name : branch;
 +      return xstrdup(name ? name : branch);
  }
  
  int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
        int i, failed;
        struct object_id h1, h2;
        struct merge_options o;
 +      char *better1, *better2;
        struct commit *result;
  
-       init_merge_options(&o);
+       init_merge_options(&o, the_repository);
        if (argv[0] && ends_with(argv[0], "-subtree"))
                o.subtree_shift = "";
  
        if (get_oid(o.branch2, &h2))
                die(_("could not resolve ref '%s'"), o.branch2);
  
 -      o.branch1 = better_branch_name(o.branch1);
 -      o.branch2 = better_branch_name(o.branch2);
 +      o.branch1 = better1 = better_branch_name(o.branch1);
 +      o.branch2 = better2 = better_branch_name(o.branch2);
  
        if (o.verbosity >= 3)
                printf(_("Merging %s with %s\n"), o.branch1, o.branch2);
  
        failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result);
 +
 +      free(better1);
 +      free(better2);
 +
        if (failed < 0)
                return 128; /* die() error code */
        return failed;
diff --combined builtin/merge-tree.c
index 5541ad091eb8c4b975d25be6386ea79be4831e5b,53719e0b9d3f9eb683b0809488ea354391639a58..34ca0258b12ae4e4a04c495c244fb9c18268e7d8
@@@ -1,3 -1,4 +1,4 @@@
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "tree-walk.h"
  #include "xdiff-interface.h"
@@@ -76,7 -77,8 +77,8 @@@ static void *result(struct merge_list *
        their = NULL;
        if (entry)
                their = entry->blob;
-       return merge_blobs(&the_index, path, base, our, their, size);
+       return merge_blobs(the_repository->index, path,
+                          base, our, their, size);
  }
  
  static void *origin(struct merge_list *entry, unsigned long *size)
@@@ -154,15 -156,15 +156,15 @@@ static void show_result(void
  /* An empty entry never compares same, not even to another empty entry */
  static int same_entry(struct name_entry *a, struct name_entry *b)
  {
 -      return  a->oid &&
 -              b->oid &&
 -              oideq(a->oid, b->oid) &&
 +      return  !is_null_oid(&a->oid) &&
 +              !is_null_oid(&b->oid) &&
 +              oideq(&a->oid, &b->oid) &&
                a->mode == b->mode;
  }
  
  static int both_empty(struct name_entry *a, struct name_entry *b)
  {
 -      return !(a->oid || b->oid);
 +      return is_null_oid(&a->oid) && is_null_oid(&b->oid);
  }
  
  static struct merge_list *create_entry(unsigned stage, unsigned mode, const struct object_id *oid, const char *path)
  
  static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
  {
 -      char *path = xmallocz(traverse_path_len(info, n));
 +      char *path = xmallocz(traverse_path_len(info, n) + the_hash_algo->rawsz);
        return make_traverse_path(path, info, n);
  }
  
@@@ -192,8 -194,8 +194,8 @@@ static void resolve(const struct traver
                return;
  
        path = traverse_path(info, result);
 -      orig = create_entry(2, ours->mode, ours->oid, path);
 -      final = create_entry(0, result->mode, result->oid, path);
 +      orig = create_entry(2, ours->mode, &ours->oid, path);
 +      final = create_entry(0, result->mode, &result->oid, path);
  
        final->link = orig;
  
@@@ -217,7 -219,7 +219,7 @@@ static void unresolved_directory(const 
  
        newbase = traverse_path(info, p);
  
 -#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid : NULL)
 +#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? &(e)->oid : NULL)
        buf0 = fill_tree_descriptor(t + 0, ENTRY_OID(n + 0));
        buf1 = fill_tree_descriptor(t + 1, ENTRY_OID(n + 1));
        buf2 = fill_tree_descriptor(t + 2, ENTRY_OID(n + 2));
@@@ -243,7 -245,7 +245,7 @@@ static struct merge_list *link_entry(un
                path = entry->path;
        else
                path = traverse_path(info, n);
 -      link = create_entry(stage, n->mode, n->oid, path);
 +      link = create_entry(stage, n->mode, &n->oid, path);
        link->link = entry;
        return link;
  }
@@@ -318,7 -320,7 +320,7 @@@ static int threeway_callback(int n, uns
        }
  
        if (same_entry(entry+0, entry+1)) {
 -              if (entry[2].oid && !S_ISDIR(entry[2].mode)) {
 +              if (!is_null_oid(&entry[2].oid) && !S_ISDIR(entry[2].mode)) {
                        /* We did not touch, they modified -- take theirs */
                        resolve(info, entry+1, entry+2);
                        return mask;
@@@ -346,7 -348,7 +348,7 @@@ static void merge_trees(struct tree_des
  
        setup_traverse_info(&info, base);
        info.fn = threeway_callback;
 -      traverse_trees(3, t, &info);
 +      traverse_trees(&the_index, 3, t, &info);
  }
  
  static void *get_tree_descriptor(struct tree_desc *desc, const char *rev)
diff --combined builtin/pack-objects.c
index 8eb5391c089d1add157cb677db037e30cd9ada16,d9d3b90b23935eb6bc2bdefa52f43b917cb7d152..ffef8dcf2f279cfe31363fe5051ff2bac3c5a77f
@@@ -970,7 -970,7 +970,7 @@@ static int no_try_delta(const char *pat
  
        if (!check)
                check = attr_check_initl("delta", NULL);
-       git_check_attr(&the_index, path, check);
+       git_check_attr(the_repository->index, path, check);
        if (ATTR_FALSE(check->items[0].value))
                return 1;
        return 0;
@@@ -1334,7 -1334,7 +1334,7 @@@ static void add_pbase_object(struct tre
                if (cmp < 0)
                        return;
                if (name[cmplen] != '/') {
 -                      add_object_entry(entry.oid,
 +                      add_object_entry(&entry.oid,
                                         object_type(entry.mode),
                                         fullname, 1);
                        return;
                        const char *down = name+cmplen+1;
                        int downlen = name_cmp_len(down);
  
 -                      tree = pbase_tree_get(entry.oid);
 +                      tree = pbase_tree_get(&entry.oid);
                        if (!tree)
                                return;
                        init_tree_desc(&sub, tree->tree_data, tree->tree_size);
@@@ -1953,6 -1953,11 +1953,6 @@@ static int delta_cacheable(unsigned lon
        return 0;
  }
  
 -/* Protect access to object database */
 -static pthread_mutex_t read_mutex;
 -#define read_lock()           pthread_mutex_lock(&read_mutex)
 -#define read_unlock()         pthread_mutex_unlock(&read_mutex)
 -
  /* Protect delta_cache_size */
  static pthread_mutex_t cache_mutex;
  #define cache_lock()          pthread_mutex_lock(&cache_mutex)
@@@ -1988,11 -1993,11 +1988,11 @@@ unsigned long oe_get_size_slow(struct p
        unsigned long used, avail, size;
  
        if (e->type_ != OBJ_OFS_DELTA && e->type_ != OBJ_REF_DELTA) {
 -              read_lock();
 +              packing_data_lock(&to_pack);
                if (oid_object_info(the_repository, &e->idx.oid, &size) < 0)
                        die(_("unable to get size of %s"),
                            oid_to_hex(&e->idx.oid));
 -              read_unlock();
 +              packing_data_unlock(&to_pack);
                return size;
        }
  
        if (!p)
                BUG("when e->type is a delta, it must belong to a pack");
  
 -      read_lock();
 +      packing_data_lock(&to_pack);
        w_curs = NULL;
        buf = use_pack(p, &w_curs, e->in_pack_offset, &avail);
        used = unpack_object_header_buffer(buf, avail, &type, &size);
                    oid_to_hex(&e->idx.oid));
  
        unuse_pack(&w_curs);
 -      read_unlock();
 +      packing_data_unlock(&to_pack);
        return size;
  }
  
@@@ -2071,9 -2076,9 +2071,9 @@@ static int try_delta(struct unpacked *t
  
        /* Load data if not already done */
        if (!trg->data) {
 -              read_lock();
 +              packing_data_lock(&to_pack);
                trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz);
 -              read_unlock();
 +              packing_data_unlock(&to_pack);
                if (!trg->data)
                        die(_("object %s cannot be read"),
                            oid_to_hex(&trg_entry->idx.oid));
                *mem_usage += sz;
        }
        if (!src->data) {
 -              read_lock();
 +              packing_data_lock(&to_pack);
                src->data = read_object_file(&src_entry->idx.oid, &type, &sz);
 -              read_unlock();
 +              packing_data_unlock(&to_pack);
                if (!src->data) {
                        if (src_entry->preferred_base) {
                                static int warned = 0;
@@@ -2332,9 -2337,9 +2332,9 @@@ static void find_deltas(struct object_e
  
  static void try_to_free_from_threads(size_t size)
  {
 -      read_lock();
 +      packing_data_lock(&to_pack);
        release_pack_memory(size);
 -      read_unlock();
 +      packing_data_unlock(&to_pack);
  }
  
  static try_to_free_t old_try_to_free_routine;
@@@ -2376,6 -2381,7 +2376,6 @@@ static pthread_cond_t progress_cond
   */
  static void init_threaded_search(void)
  {
 -      init_recursive_mutex(&read_mutex);
        pthread_mutex_init(&cache_mutex, NULL);
        pthread_mutex_init(&progress_mutex, NULL);
        pthread_cond_init(&progress_cond, NULL);
@@@ -2386,6 -2392,7 +2386,6 @@@ static void cleanup_threaded_search(voi
  {
        set_try_to_free_routine(old_try_to_free_routine);
        pthread_cond_destroy(&progress_cond);
 -      pthread_mutex_destroy(&read_mutex);
        pthread_mutex_destroy(&cache_mutex);
        pthread_mutex_destroy(&progress_mutex);
  }
@@@ -3077,16 -3084,14 +3077,16 @@@ static void record_recent_commit(struc
  static void get_object_list(int ac, const char **av)
  {
        struct rev_info revs;
 +      struct setup_revision_opt s_r_opt = {
 +              .allow_exclude_promisor_objects = 1,
 +      };
        char line[1000];
        int flags = 0;
        int save_warning;
  
        repo_init_revisions(the_repository, &revs, NULL);
        save_commit_buffer = 0;
 -      revs.allow_exclude_promisor_objects_opt = 1;
 -      setup_revisions(ac, av, &revs, NULL);
 +      setup_revisions(ac, av, &revs, &s_r_opt);
  
        /* make sure shallows are read */
        is_repository_shallow(the_repository);
index c2c2d51a3b03edf17de5b37811dadd66ca4f774b,6895322d613afcf3cebb0ded610c45ab343ef688..888390f9114321a489f8210659487ef2d2897fae
@@@ -1,3 -1,4 +1,4 @@@
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "cache.h"
  #include "config.h"
@@@ -193,8 -194,6 +194,8 @@@ int cmd_rebase__interactive(int argc, c
                OPT_STRING(0, "onto-name", &onto_name, N_("onto-name"), N_("onto name")),
                OPT_STRING(0, "cmd", &cmd, N_("cmd"), N_("the command to run")),
                OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_auto),
 +              OPT_BOOL(0, "reschedule-failed-exec", &opts.reschedule_failed_exec,
 +                       N_("automatically re-schedule any `exec` that fails")),
                OPT_END()
        };
  
diff --combined builtin/rebase.c
index 8d49e53997b3579623a284845cd49aa9b67b14a7,b66783727628c3867683236e5afeef247c5054f4..0b039319e134d0c33df842666eddc820dc6c410c
@@@ -4,6 -4,7 +4,7 @@@
   * Copyright (c) 2018 Pratik Karki
   */
  
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "run-command.h"
  #include "exec-cmd.h"
@@@ -104,7 -105,6 +105,7 @@@ struct rebase_options 
        int rebase_merges, rebase_cousins;
        char *strategy, *strategy_opts;
        struct strbuf git_format_patch_opt;
 +      int reschedule_failed_exec;
  };
  
  static int is_interactive(struct rebase_options *opts)
@@@ -123,7 -123,7 +124,7 @@@ static void imply_interactive(struct re
        case REBASE_PRESERVE_MERGES:
                break;
        case REBASE_MERGE:
 -              /* we silently *upgrade* --merge to --interactive if needed */
 +              /* we now implement --merge via --interactive */
        default:
                opts->type = REBASE_INTERACTIVE; /* implied */
                break;
@@@ -186,7 -186,10 +187,7 @@@ static int read_basic_state(struct reba
        if (get_oid(buf.buf, &opts->orig_head))
                return error(_("invalid orig-head: '%s'"), buf.buf);
  
 -      strbuf_reset(&buf);
 -      if (read_one(state_dir_path("quiet", opts), &buf))
 -              return -1;
 -      if (buf.len)
 +      if (file_exists(state_dir_path("quiet", opts)))
                opts->flags &= ~REBASE_NO_QUIET;
        else
                opts->flags |= REBASE_NO_QUIET;
        return 0;
  }
  
 +static int write_basic_state(struct rebase_options *opts)
 +{
 +      write_file(state_dir_path("head-name", opts), "%s",
 +                 opts->head_name ? opts->head_name : "detached HEAD");
 +      write_file(state_dir_path("onto", opts), "%s",
 +                 opts->onto ? oid_to_hex(&opts->onto->object.oid) : "");
 +      write_file(state_dir_path("orig-head", opts), "%s",
 +                 oid_to_hex(&opts->orig_head));
 +      write_file(state_dir_path("quiet", opts), "%s",
 +                 opts->flags & REBASE_NO_QUIET ? "" : "t");
 +      if (opts->flags & REBASE_VERBOSE)
 +              write_file(state_dir_path("verbose", opts), "%s", "");
 +      if (opts->strategy)
 +              write_file(state_dir_path("strategy", opts), "%s",
 +                         opts->strategy);
 +      if (opts->strategy_opts)
 +              write_file(state_dir_path("strategy_opts", opts), "%s",
 +                         opts->strategy_opts);
 +      if (opts->allow_rerere_autoupdate >= 0)
 +              write_file(state_dir_path("allow_rerere_autoupdate", opts),
 +                         "-%s-rerere-autoupdate",
 +                         opts->allow_rerere_autoupdate ? "" : "-no");
 +      if (opts->gpg_sign_opt)
 +              write_file(state_dir_path("gpg_sign_opt", opts), "%s",
 +                         opts->gpg_sign_opt);
 +      if (opts->signoff)
 +              write_file(state_dir_path("strategy", opts), "--signoff");
 +
 +      return 0;
 +}
 +
  static int apply_autostash(struct rebase_options *opts)
  {
        const char *path = state_dir_path("autostash", opts);
@@@ -362,161 -334,6 +363,161 @@@ static void add_var(struct strbuf *buf
        }
  }
  
-       if (read_index_unmerged(the_repository->index) < 0) {
 +#define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
 +
 +#define RESET_HEAD_DETACH (1<<0)
 +#define RESET_HEAD_HARD (1<<1)
 +#define RESET_HEAD_RUN_POST_CHECKOUT_HOOK (1<<2)
 +#define RESET_HEAD_REFS_ONLY (1<<3)
 +
 +static int reset_head(struct object_id *oid, const char *action,
 +                    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;
 +      unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
 +      unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
 +      struct object_id head_oid;
 +      struct tree_desc desc[2] = { { NULL }, { NULL } };
 +      struct lock_file lock = LOCK_INIT;
 +      struct unpack_trees_options unpack_tree_opts;
 +      struct tree *tree;
 +      const char *reflog_action;
 +      struct strbuf msg = STRBUF_INIT;
 +      size_t prefix_len;
 +      struct object_id *orig = NULL, oid_orig,
 +              *old_orig = NULL, oid_old_orig;
 +      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 (!refs_only && hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) {
 +              ret = -1;
 +              goto leave_reset_head;
 +      }
 +
 +      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;
 +
 +      if (refs_only)
 +              goto reset_head_refs;
 +
 +      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 = 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 (repo_read_index_unmerged(the_repository) < 0) {
 +              ret = error(_("could not read index"));
 +              goto leave_reset_head;
 +      }
 +
 +      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 (!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, the_repository->index, tree);
 +
 +      if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0) {
 +              ret = error(_("could not write index"));
 +              goto leave_reset_head;
 +      }
 +
 +reset_head_refs:
 +      reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
 +      strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase");
 +      prefix_len = msg.len;
 +
 +      if (!get_oid("ORIG_HEAD", &oid_old_orig))
 +              old_orig = &oid_old_orig;
 +      if (!get_oid("HEAD", &oid_orig)) {
 +              orig = &oid_orig;
 +              if (!reflog_orig_head) {
 +                      strbuf_addstr(&msg, "updating ORIG_HEAD");
 +                      reflog_orig_head = msg.buf;
 +              }
 +              update_ref(reflog_orig_head, "ORIG_HEAD", orig, old_orig, 0,
 +                         UPDATE_REFS_MSG_ON_ERR);
 +      } else if (old_orig)
 +              delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
 +      if (!reflog_head) {
 +              strbuf_setlen(&msg, prefix_len);
 +              strbuf_addstr(&msg, "updating HEAD");
 +              reflog_head = msg.buf;
 +      }
 +      if (!switch_to_branch)
 +              ret = update_ref(reflog_head, "HEAD", oid, orig,
 +                               detach_head ? REF_NO_DEREF : 0,
 +                               UPDATE_REFS_MSG_ON_ERR);
 +      else {
 +              ret = update_ref(reflog_orig_head, switch_to_branch, oid,
 +                               NULL, 0, UPDATE_REFS_MSG_ON_ERR);
 +              if (!ret)
 +                      ret = create_symref("HEAD", switch_to_branch,
 +                                          reflog_head);
 +      }
 +      if (run_hook)
 +              run_hook_le(NULL, "post-checkout",
 +                          oid_to_hex(orig ? orig : &null_oid),
 +                          oid_to_hex(oid), "1", NULL);
 +
 +leave_reset_head:
 +      strbuf_release(&msg);
 +      rollback_lock_file(&lock);
 +      while (nr)
 +              free((void *)desc[--nr].buffer);
 +      return ret;
 +}
 +
 +static int move_to_original_branch(struct rebase_options *opts)
 +{
 +      struct strbuf orig_head_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;
 +      int ret;
 +
 +      if (!opts->head_name)
 +              return 0; /* nothing to move back to */
 +
 +      if (!opts->onto)
 +              BUG("move_to_original_branch without onto");
 +
 +      strbuf_addf(&orig_head_reflog, "rebase finished: %s onto %s",
 +                  opts->head_name, oid_to_hex(&opts->onto->object.oid));
 +      strbuf_addf(&head_reflog, "rebase finished: returning to %s",
 +                  opts->head_name);
 +      ret = reset_head(NULL, "", opts->head_name, RESET_HEAD_REFS_ONLY,
 +                       orig_head_reflog.buf, head_reflog.buf);
 +
 +      strbuf_release(&orig_head_reflog);
 +      strbuf_release(&head_reflog);
 +      return ret;
 +}
 +
  static const char *resolvemsg =
  N_("Resolve all conflicts manually, mark them as resolved with\n"
  "\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
  "To abort and get back to the state before \"git rebase\", run "
  "\"git rebase --abort\".");
  
 +static int run_am(struct rebase_options *opts)
 +{
 +      struct child_process am = CHILD_PROCESS_INIT;
 +      struct child_process format_patch = CHILD_PROCESS_INIT;
 +      struct strbuf revisions = STRBUF_INIT;
 +      int status;
 +      char *rebased_patches;
 +
 +      am.git_cmd = 1;
 +      argv_array_push(&am.args, "am");
 +
 +      if (opts->action && !strcmp("continue", opts->action)) {
 +              argv_array_push(&am.args, "--resolved");
 +              argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
 +              if (opts->gpg_sign_opt)
 +                      argv_array_push(&am.args, opts->gpg_sign_opt);
 +              status = run_command(&am);
 +              if (status)
 +                      return status;
 +
 +              return move_to_original_branch(opts);
 +      }
 +      if (opts->action && !strcmp("skip", opts->action)) {
 +              argv_array_push(&am.args, "--skip");
 +              argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
 +              status = run_command(&am);
 +              if (status)
 +                      return status;
 +
 +              return move_to_original_branch(opts);
 +      }
 +      if (opts->action && !strcmp("show-current-patch", opts->action)) {
 +              argv_array_push(&am.args, "--show-current-patch");
 +              return run_command(&am);
 +      }
 +
 +      strbuf_addf(&revisions, "%s...%s",
 +                  oid_to_hex(opts->root ?
 +                             /* this is now equivalent to !opts->upstream */
 +                             &opts->onto->object.oid :
 +                             &opts->upstream->object.oid),
 +                  oid_to_hex(&opts->orig_head));
 +
 +      rebased_patches = xstrdup(git_path("rebased-patches"));
 +      format_patch.out = open(rebased_patches,
 +                              O_WRONLY | O_CREAT | O_TRUNC, 0666);
 +      if (format_patch.out < 0) {
 +              status = error_errno(_("could not open '%s' for writing"),
 +                                   rebased_patches);
 +              free(rebased_patches);
 +              argv_array_clear(&am.args);
 +              return status;
 +      }
 +
 +      format_patch.git_cmd = 1;
 +      argv_array_pushl(&format_patch.args, "format-patch", "-k", "--stdout",
 +                       "--full-index", "--cherry-pick", "--right-only",
 +                       "--src-prefix=a/", "--dst-prefix=b/", "--no-renames",
 +                       "--no-cover-letter", "--pretty=mboxrd", "--topo-order", NULL);
 +      if (opts->git_format_patch_opt.len)
 +              argv_array_split(&format_patch.args,
 +                               opts->git_format_patch_opt.buf);
 +      argv_array_push(&format_patch.args, revisions.buf);
 +      if (opts->restrict_revision)
 +              argv_array_pushf(&format_patch.args, "^%s",
 +                               oid_to_hex(&opts->restrict_revision->object.oid));
 +
 +      status = run_command(&format_patch);
 +      if (status) {
 +              unlink(rebased_patches);
 +              free(rebased_patches);
 +              argv_array_clear(&am.args);
 +
 +              reset_head(&opts->orig_head, "checkout", opts->head_name, 0,
 +                         "HEAD", NULL);
 +              error(_("\ngit encountered an error while preparing the "
 +                      "patches to replay\n"
 +                      "these revisions:\n"
 +                      "\n    %s\n\n"
 +                      "As a result, git cannot rebase them."),
 +                    opts->revisions);
 +
 +              strbuf_release(&revisions);
 +              return status;
 +      }
 +      strbuf_release(&revisions);
 +
 +      am.in = open(rebased_patches, O_RDONLY);
 +      if (am.in < 0) {
 +              status = error_errno(_("could not open '%s' for reading"),
 +                                   rebased_patches);
 +              free(rebased_patches);
 +              argv_array_clear(&am.args);
 +              return status;
 +      }
 +
 +      argv_array_pushv(&am.args, opts->git_am_opts.argv);
 +      argv_array_push(&am.args, "--rebasing");
 +      argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
 +      argv_array_push(&am.args, "--patch-format=mboxrd");
 +      if (opts->allow_rerere_autoupdate > 0)
 +              argv_array_push(&am.args, "--rerere-autoupdate");
 +      else if (opts->allow_rerere_autoupdate == 0)
 +              argv_array_push(&am.args, "--no-rerere-autoupdate");
 +      if (opts->gpg_sign_opt)
 +              argv_array_push(&am.args, opts->gpg_sign_opt);
 +      status = run_command(&am);
 +      unlink(rebased_patches);
 +      free(rebased_patches);
 +
 +      if (!status) {
 +              return move_to_original_branch(opts);
 +      }
 +
 +      if (is_directory(opts->state_dir))
 +              write_basic_state(opts);
 +
 +      return status;
 +}
 +
  static int run_specific_rebase(struct rebase_options *opts)
  {
        const char *argv[] = { NULL, NULL };
                argv_array_pushf(&child.env_array, "GIT_CHERRY_PICK_HELP=%s",
                                 resolvemsg);
                if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
 -                      argv_array_push(&child.env_array, "GIT_EDITOR=:");
 +                      argv_array_push(&child.env_array,
 +                                      "GIT_SEQUENCE_EDITOR=:");
                        opts->autosquash = 0;
                }
  
                        argv_array_push(&child.args, opts->gpg_sign_opt);
                if (opts->signoff)
                        argv_array_push(&child.args, "--signoff");
 +              if (opts->reschedule_failed_exec)
 +                      argv_array_push(&child.args, "--reschedule-failed-exec");
  
                status = run_command(&child);
                goto finished_rebase;
        }
  
 +      if (opts->type == REBASE_AM) {
 +              status = run_am(opts);
 +              goto finished_rebase;
 +      }
 +
        add_var(&script_snippet, "GIT_DIR", absolute_path(get_git_dir()));
        add_var(&script_snippet, "state_dir", opts->state_dir);
  
        if (is_interactive(opts) &&
            !(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
                strbuf_addstr(&script_snippet,
 -                            "GIT_EDITOR=:; export GIT_EDITOR; ");
 +                            "GIT_SEQUENCE_EDITOR=:; export GIT_SEQUENCE_EDITOR; ");
                opts->autosquash = 0;
        }
  
                backend = "git-rebase--am";
                backend_func = "git_rebase__am";
                break;
 -      case REBASE_MERGE:
 -              backend = "git-rebase--merge";
 -              backend_func = "git_rebase__merge";
 -              break;
        case REBASE_PRESERVE_MERGES:
                backend = "git-rebase--preserve-merges";
                backend_func = "git_rebase__preserve_merges";
@@@ -834,6 -527,125 +835,6 @@@ finished_rebase
        return status ? -1 : 0;
  }
  
 -#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, 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[2] = { { NULL }, { NULL } };
 -      struct lock_file lock = LOCK_INIT;
 -      struct unpack_trees_options unpack_tree_opts;
 -      struct tree *tree;
 -      const char *reflog_action;
 -      struct strbuf msg = STRBUF_INIT;
 -      size_t prefix_len;
 -      struct object_id *orig = NULL, oid_orig,
 -              *old_orig = NULL, oid_old_orig;
 -      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) {
 -              ret = -1;
 -              goto leave_reset_head;
 -      }
 -
 -      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 = 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 (repo_read_index_unmerged(the_repository) < 0) {
 -              ret = error(_("could not read index"));
 -              goto leave_reset_head;
 -      }
 -
 -      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 (!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, the_repository->index, tree);
 -
 -      if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0) {
 -              ret = error(_("could not write index"));
 -              goto leave_reset_head;
 -      }
 -
 -      reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
 -      strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase");
 -      prefix_len = msg.len;
 -
 -      if (!get_oid("ORIG_HEAD", &oid_old_orig))
 -              old_orig = &oid_old_orig;
 -      if (!get_oid("HEAD", &oid_orig)) {
 -              orig = &oid_orig;
 -              if (!reflog_orig_head) {
 -                      strbuf_addstr(&msg, "updating ORIG_HEAD");
 -                      reflog_orig_head = msg.buf;
 -              }
 -              update_ref(reflog_orig_head, "ORIG_HEAD", orig, old_orig, 0,
 -                         UPDATE_REFS_MSG_ON_ERR);
 -      } else if (old_orig)
 -              delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
 -      if (!reflog_head) {
 -              strbuf_setlen(&msg, prefix_len);
 -              strbuf_addstr(&msg, "updating HEAD");
 -              reflog_head = msg.buf;
 -      }
 -      if (!switch_to_branch)
 -              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);
 -              if (!ret)
 -                      ret = update_ref(reflog_head, "HEAD", oid, NULL, 0,
 -                                       UPDATE_REFS_MSG_ON_ERR);
 -      }
 -
 -leave_reset_head:
 -      strbuf_release(&msg);
 -      rollback_lock_file(&lock);
 -      while (nr)
 -              free((void *)desc[--nr].buffer);
 -      return ret;
 -}
 -
  static int rebase_config(const char *var, const char *value, void *data)
  {
        struct rebase_options *opts = data;
                return 0;
        }
  
 +      if (!strcmp(var, "rebase.reschedulefailedexec")) {
 +              opts->reschedule_failed_exec = git_config_bool(var, value);
 +              return 0;
 +      }
 +
        return git_default_config(var, value, data);
  }
  
@@@ -940,23 -747,6 +941,23 @@@ static int parse_opt_interactive(const 
        return 0;
  }
  
 +struct opt_y {
 +      struct string_list *list;
 +      struct rebase_options *options;
 +};
 +
 +static int parse_opt_y(const struct option *opt, const char *arg, int unset)
 +{
 +      struct opt_y *o = opt->value;
 +
 +      if (unset || !arg)
 +              return -1;
 +
 +      o->options->reschedule_failed_exec = 1;
 +      string_list_append(o->list, arg);
 +      return 0;
 +}
 +
  static void NORETURN error_on_missing_default_upstream(void)
  {
        struct branch *current_branch = branch_get(NULL);
@@@ -1037,7 -827,6 +1038,7 @@@ int cmd_rebase(int argc, const char **a
        struct string_list strategy_options = STRING_LIST_INIT_NODUP;
        struct object_id squash_onto;
        char *squash_onto_name = NULL;
 +      struct opt_y opt_y = { .list = &exec, .options = &options };
        struct option builtin_rebase_options[] = {
                OPT_STRING(0, "onto", &options.onto_name,
                           N_("revision"),
                OPT_STRING_LIST('x', "exec", &exec, N_("exec"),
                                N_("add exec lines after each commit of the "
                                   "editable list")),
 +              { OPTION_CALLBACK, 'y', NULL, &opt_y, N_("<cmd>"),
 +                      N_("same as --reschedule-failed-exec -x <cmd>"),
 +                      PARSE_OPT_NONEG, parse_opt_y },
                OPT_BOOL(0, "allow-empty-message",
                         &options.allow_empty_message,
                         N_("allow rebasing commits with empty messages")),
                                   "strategy")),
                OPT_BOOL(0, "root", &options.root,
                         N_("rebase all reachable commits up to the root(s)")),
 +              OPT_BOOL(0, "reschedule-failed-exec",
 +                       &options.reschedule_failed_exec,
 +                       N_("automatically re-schedule any `exec` that fails")),
                OPT_END(),
        };
        int i;
                        die(_("Cannot read HEAD"));
  
                fd = hold_locked_index(&lock_file, 0);
-               if (read_index(the_repository->index) < 0)
+               if (repo_read_index(the_repository) < 0)
                        die(_("could not read index"));
                refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL,
                              NULL);
                if (0 <= fd)
-                       update_index_if_able(the_repository->index,
-                                            &lock_file);
+                       repo_update_index_if_able(the_repository, &lock_file);
                rollback_lock_file(&lock_file);
  
                if (has_unstaged_changes(the_repository, 1)) {
                }
        }
  
 +      if (options.type == REBASE_MERGE)
 +              imply_interactive(&options, "--merge");
 +
        if (options.root && !options.onto_name)
                imply_interactive(&options, "--root without --onto");
  
                break;
        }
  
 +      if (options.reschedule_failed_exec && !is_interactive(&options))
 +              die(_("--reschedule-failed-exec requires an interactive rebase"));
 +
        if (options.git_am_opts.argc) {
                /* all am options except -q are compatible only with --am */
                for (i = options.git_am_opts.argc - 1; i >= 0; i--)
                                break;
  
                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 && i >= 0)
 -                      die(_("error: cannot combine merge options (--merge, "
 -                            "--strategy, --strategy-option) with am options "
 -                            "(%s)"), buf.buf);
 +                      die(_("cannot combine am options with either "
 +                            "interactive or merge options"));
        }
  
        if (options.signoff) {
                options.flags |= REBASE_FORCE;
        }
  
 -      if (options.type == REBASE_PRESERVE_MERGES)
 +      if (options.type == REBASE_PRESERVE_MERGES) {
                /*
                 * Note: incompatibility with --signoff handled in signoff block above
                 * Note: incompatibility with --interactive is just a strong warning;
                 *       git-rebase.txt caveats with "unless you know what you are doing"
                 */
                if (options.rebase_merges)
 -                      die(_("error: cannot combine '--preserve-merges' with "
 +                      die(_("cannot combine '--preserve-merges' with "
                              "'--rebase-merges'"));
  
 +              if (options.reschedule_failed_exec)
 +                      die(_("error: cannot combine '--preserve-merges' with "
 +                            "'--reschedule-failed-exec'"));
 +      }
 +
        if (options.rebase_merges) {
                if (strategy_options.nr)
 -                      die(_("error: cannot combine '--rebase-merges' with "
 +                      die(_("cannot combine '--rebase-merges' with "
                              "'--strategy-option'"));
                if (options.strategy)
 -                      die(_("error: cannot combine '--rebase-merges' with "
 +                      die(_("cannot combine '--rebase-merges' with "
                              "'--strategy'"));
        }
  
                        get_fork_point(options.upstream_name, head);
        }
  
-       if (read_index(the_repository->index) < 0)
+       if (repo_read_index(the_repository) < 0)
                die(_("could not read index"));
  
        if (options.autostash) {
                fd = hold_locked_index(&lock_file, 0);
                refresh_cache(REFRESH_QUIET);
                if (0 <= fd)
-                       update_index_if_able(&the_index, &lock_file);
+                       repo_update_index_if_able(the_repository, &lock_file);
                rollback_lock_file(&lock_file);
  
                if (has_unstaged_changes(the_repository, 1) ||
                        putchar('\n');
  
                        if (discard_index(the_repository->index) < 0 ||
-                               read_index(the_repository->index) < 0)
+                               repo_read_index(the_repository) < 0)
                                die(_("could not read index"));
                }
        }
                                            getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
                                            options.switch_to);
                                if (reset_head(&oid, "checkout",
 -                                             options.head_name, 0,
 +                                             options.head_name,
 +                                             RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
                                               NULL, buf.buf) < 0) {
                                        ret = !!error(_("could not switch to "
                                                        "%s"),
        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))
 +                     RESET_HEAD_DETACH | RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
 +                     NULL, msg.buf))
                die(_("Could not detach HEAD"));
        strbuf_release(&msg);
  
index 0e140f176ce3b559478a5bc4245bf36905c543cf,9c832fc606d636f141ec806cf0281489ea199885..b80fc4ba3d88b56436fa3f6b9a132bfe9e82b79b
@@@ -1,3 -1,4 +1,4 @@@
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "builtin.h"
  #include "repository.h"
  #include "cache.h"
@@@ -1131,8 -1132,6 +1132,8 @@@ static void deinit_submodule(const cha
                if (!(flags & OPT_QUIET))
                        printf(format, displaypath);
  
 +              submodule_unset_core_worktree(sub);
 +
                strbuf_release(&sb_rm);
        }
  
@@@ -1554,7 -1553,7 +1555,7 @@@ struct submodule_update_clone 
  #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
        SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \
        NULL, NULL, NULL, \
 -      NULL, 0, 0, 0, NULL, 0, 0, 0}
 +      NULL, 0, 0, 0, NULL, 0, 0, 1}
  
  
  static void next_submodule_warn_missing(struct submodule_update_clone *suc,
@@@ -2048,7 -2047,7 +2049,7 @@@ static int ensure_core_worktree(int arg
        struct repository subrepo;
  
        if (argc != 2)
 -              BUG("submodule--helper connect-gitdir-workingtree <name> <path>");
 +              BUG("submodule--helper ensure-core-worktree <path>");
  
        path = argv[1];
  
        if (!sub)
                BUG("We could get the submodule handle before?");
  
 -      if (repo_submodule_init(&subrepo, the_repository, path))
 +      if (repo_submodule_init(&subrepo, the_repository, sub))
                die(_("could not get a repository handle for submodule '%s'"), path);
  
        if (!repo_config_get_string(&subrepo, "core.worktree", &cw)) {
diff --combined cache.h
index bcf9fd445f47d97b07e11365421a4e39e22fc8c8,962eb127d3a9e51e3a4cb3911a856320af26f2a4..c653668340232e2610729665c6fc740ee748232a
+++ b/cache.h
@@@ -45,20 -45,10 +45,20 @@@ unsigned long git_deflate_bound(git_zst
  /* The length in bytes and in hex digits of an object name (SHA-1 value). */
  #define GIT_SHA1_RAWSZ 20
  #define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
 +/* The block size of SHA-1. */
 +#define GIT_SHA1_BLKSZ 64
 +
 +/* The length in bytes and in hex digits of an object name (SHA-256 value). */
 +#define GIT_SHA256_RAWSZ 32
 +#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
 +/* The block size of SHA-256. */
 +#define GIT_SHA256_BLKSZ 64
  
  /* The length in byte and in hex digits of the largest possible hash value. */
 -#define GIT_MAX_RAWSZ GIT_SHA1_RAWSZ
 -#define GIT_MAX_HEXSZ GIT_SHA1_HEXSZ
 +#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
 +#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
 +/* The largest possible block size for any supported hash. */
 +#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
  
  struct object_id {
        unsigned char hash[GIT_MAX_RAWSZ];
@@@ -348,8 -338,6 +348,6 @@@ struct index_state 
        struct mem_pool *ce_mem_pool;
  };
  
- extern struct index_state the_index;
  /* Name hashing */
  extern int test_lazy_init_name_hash(struct index_state *istate, int try_threaded);
  extern void add_name_hash(struct index_state *istate, struct cache_entry *ce);
@@@ -411,18 -399,20 +409,20 @@@ struct cache_entry *dup_cache_entry(con
   */
  void validate_cache_entries(const struct index_state *istate);
  
- #ifndef NO_THE_INDEX_COMPATIBILITY_MACROS
+ #ifdef USE_THE_INDEX_COMPATIBILITY_MACROS
+ extern struct index_state the_index;
  #define active_cache (the_index.cache)
  #define active_nr (the_index.cache_nr)
  #define active_alloc (the_index.cache_alloc)
  #define active_cache_changed (the_index.cache_changed)
  #define active_cache_tree (the_index.cache_tree)
  
- #define read_cache() read_index(&the_index)
+ #define read_cache() repo_read_index(the_repository)
  #define read_cache_from(path) read_index_from(&the_index, (path), (get_git_dir()))
- #define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec), 0)
+ #define read_cache_preload(pathspec) repo_read_index_preload(the_repository, (pathspec), 0)
  #define is_cache_unborn() is_index_unborn(&the_index)
- #define read_cache_unmerged() read_index_unmerged(&the_index)
+ #define read_cache_unmerged() repo_read_index_unmerged(the_repository)
  #define discard_cache() discard_index(&the_index)
  #define unmerged_cache() unmerged_index(&the_index)
  #define cache_name_pos(name, namelen) index_name_pos(&the_index,(name),(namelen))
  #define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)
  #define unmerge_cache(pathspec) unmerge_index(&the_index, pathspec)
  #define read_blob_data_from_cache(path, sz) read_blob_data_from_index(&the_index, (path), (sz))
+ #define hold_locked_index(lock_file, flags) repo_hold_locked_index(the_repository, (lock_file), (flags))
  #endif
  
  #define TYPE_BITS 3
@@@ -670,19 -661,14 +671,14 @@@ extern int daemonize(void)
  
  /* Initialize and use the cache information */
  struct lock_file;
- extern int read_index(struct index_state *);
  extern void preload_index(struct index_state *index,
                          const struct pathspec *pathspec,
                          unsigned int refresh_flags);
- extern int read_index_preload(struct index_state *,
-                             const struct pathspec *pathspec,
-                             unsigned int refresh_flags);
  extern int do_read_index(struct index_state *istate, const char *path,
                         int must_exist); /* for testting only! */
  extern int read_index_from(struct index_state *, const char *path,
                           const char *gitdir);
  extern int is_index_unborn(struct index_state *);
- extern int read_index_unmerged(struct index_state *);
  
  /* For use with `write_locked_index()`. */
  #define COMMIT_LOCK           (1 << 0)
@@@ -720,9 -706,9 +716,9 @@@ extern int unmerged_index(const struct 
   * provided, the space-separated list of files that differ will be appended
   * to it.
   */
- extern int index_has_changes(struct index_state *istate,
-                            struct tree *tree,
-                            struct strbuf *sb);
+ extern int repo_index_has_changes(struct repository *repo,
+                                 struct tree *tree,
+                                 struct strbuf *sb);
  
  extern int verify_path(const char *path, unsigned mode);
  extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
@@@ -755,7 -741,6 +751,7 @@@ extern int index_name_pos(const struct 
  #define ADD_CACHE_JUST_APPEND 8               /* Append only; tree.c::read_tree() */
  #define ADD_CACHE_NEW_ONLY 16         /* Do not replace existing ones */
  #define ADD_CACHE_KEEP_CACHE_TREE 32  /* Do not invalidate cache-tree */
 +#define ADD_CACHE_RENORMALIZE 64        /* Pass along HASH_RENORMALIZE */
  extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
  extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
  
@@@ -838,13 -823,6 +834,6 @@@ extern void fill_stat_cache_info(struc
  extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
  extern struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
  
- /*
-  * Opportunistically update the index but do not complain if we can't.
-  * The lockfile is always committed or rolled back.
-  */
- extern void update_index_if_able(struct index_state *, struct lock_file *);
- extern int hold_locked_index(struct lock_file *, int);
  extern void set_alternate_index_output(const char *);
  
  extern int verify_index_checksum;
@@@ -1039,12 -1017,16 +1028,12 @@@ extern const struct object_id null_oid
  static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
  {
        /*
 -       * This is a temporary optimization hack. By asserting the size here,
 -       * we let the compiler know that it's always going to be 20, which lets
 -       * it turn this fixed-size memcmp into a few inline instructions.
 -       *
 -       * This will need to be extended or ripped out when we learn about
 -       * hashes of different sizes.
 +       * Teach the compiler that there are only two possibilities of hash size
 +       * here, so that it can optimize for this case as much as possible.
         */
 -      if (the_hash_algo->rawsz != 20)
 -              BUG("hash size not yet supported by hashcmp");
 -      return memcmp(sha1, sha2, the_hash_algo->rawsz);
 +      if (the_hash_algo->rawsz == GIT_MAX_RAWSZ)
 +              return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
 +      return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
  }
  
  static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2)
  
  static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2)
  {
 -      return !hashcmp(sha1, sha2);
 +      /*
 +       * We write this here instead of deferring to hashcmp so that the
 +       * compiler can properly inline it and avoid calling memcmp.
 +       */
 +      if (the_hash_algo->rawsz == GIT_MAX_RAWSZ)
 +              return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
 +      return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
  }
  
  static inline int oideq(const struct object_id *oid1, const struct object_id *oid2)
@@@ -1085,7 -1061,7 +1074,7 @@@ static inline void hashcpy(unsigned cha
  
  static inline void oidcpy(struct object_id *dst, const struct object_id *src)
  {
 -      hashcpy(dst->hash, src->hash);
 +      memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
  }
  
  static inline struct object_id *oiddup(const struct object_id *src)
@@@ -1345,24 -1321,6 +1334,24 @@@ struct object_context 
        GET_OID_TREE | GET_OID_TREEISH | \
        GET_OID_BLOB)
  
 +enum get_oid_result {
 +      FOUND = 0,
 +      MISSING_OBJECT = -1, /* The requested object is missing */
 +      SHORT_NAME_AMBIGUOUS = -2,
 +      /* The following only apply when symlinks are followed */
 +      DANGLING_SYMLINK = -4, /*
 +                              * The initial symlink is there, but
 +                              * (transitively) points to a missing
 +                              * in-tree file
 +                              */
 +      SYMLINK_LOOP = -5,
 +      NOT_DIR = -6, /*
 +                     * Somewhere along the symlink chain, a path is
 +                     * requested which contains a file as a
 +                     * non-final element.
 +                     */
 +};
 +
  extern int get_oid(const char *str, struct object_id *oid);
  extern int get_oid_commit(const char *str, struct object_id *oid);
  extern int get_oid_committish(const char *str, struct object_id *oid);
@@@ -1370,9 -1328,11 +1359,10 @@@ extern int get_oid_tree(const char *str
  extern int get_oid_treeish(const char *str, struct object_id *oid);
  extern int get_oid_blob(const char *str, struct object_id *oid);
  extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
- extern enum get_oid_result get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
 -extern int get_oid_with_context(struct repository *repo, const char *str,
++extern enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
+                               unsigned flags, struct object_id *oid,
+                               struct object_context *oc);
  
 -
  typedef int each_abbrev_fn(const struct object_id *oid, void *);
  extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
  
@@@ -1396,9 -1356,9 +1386,9 @@@ extern int get_oid_hex(const char *hex
  extern int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
  
  /*
 - * Convert a binary sha1 to its hex equivalent. The `_r` variant is reentrant,
 + * Convert a binary hash to its hex equivalent. The `_r` variant is reentrant,
   * and writes the NUL-terminated output to the buffer `out`, which must be at
 - * least `GIT_SHA1_HEXSZ + 1` bytes, and returns a pointer to out for
 + * least `GIT_MAX_HEXSZ + 1` bytes, and returns a pointer to out for
   * convenience.
   *
   * The non-`_r` variant returns a static buffer, but uses a ring of 4
   *
   *   printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two));
   */
 -extern char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 -extern char *oid_to_hex_r(char *out, const struct object_id *oid);
 -extern char *sha1_to_hex(const unsigned char *sha1);  /* static buffer result! */
 -extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */
 +char *hash_to_hex_algop_r(char *buffer, const unsigned char *hash, const struct git_hash_algo *);
 +char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 +char *oid_to_hex_r(char *out, const struct object_id *oid);
 +char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *);     /* static buffer result! */
 +char *sha1_to_hex(const unsigned char *sha1);                                         /* same static buffer */
 +char *hash_to_hex(const unsigned char *hash);                                         /* same static buffer */
 +char *oid_to_hex(const struct object_id *oid);                                                /* same static buffer */
  
  /*
   * Parse a 40-character hexadecimal object ID starting from hex, updating the
@@@ -1573,9 -1530,9 +1563,9 @@@ struct checkout 
  #define CHECKOUT_INIT { NULL, "" }
  
  #define TEMPORARY_FILENAME_LENGTH 25
 -extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 +extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath, int *nr_checkouts);
  extern void enable_delayed_checkout(struct checkout *state);
 -extern int finish_delayed_checkout(struct checkout *state);
 +extern int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
  
  struct cache_def {
        struct strbuf path;
@@@ -1822,7 -1779,4 +1812,7 @@@ void safe_create_dir(const char *dir, i
   */
  extern int print_sha1_ellipsis(void);
  
 +/* Return 1 if the file is empty or does not exists, 0 otherwise. */
 +extern int is_empty_or_missing_file(const char *filename);
 +
  #endif /* CACHE_H */
diff --combined convert.c
index 0d89ae7c2302a4bff3a6fdcb4a7015a81eeb8025,df8c6a0bf86097ca0d9864b4ec5233fb0b1c5939..489510c35374ed148bbf578400d7780bf57af9e3
+++ b/convert.c
@@@ -1,4 -1,3 +1,3 @@@
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "object-store.h"
@@@ -705,7 -704,7 +704,7 @@@ static int filter_buffer_or_fd(int in, 
  }
  
  static int apply_single_file_filter(const char *path, const char *src, size_t len, int fd,
 -                        struct strbuf *dst, const char *cmd)
 +                                  struct strbuf *dst, const char *cmd)
  {
        /*
         * Create a pipeline to have the command filter the buffer's
@@@ -778,8 -777,7 +777,8 @@@ static int start_multi_file_filter_fn(s
  
  static void handle_filter_error(const struct strbuf *filter_status,
                                struct cmd2process *entry,
 -                              const unsigned int wanted_capability) {
 +                              const unsigned int wanted_capability)
 +{
        if (!strcmp(filter_status->buf, "error"))
                ; /* The filter signaled a problem with the file. */
        else if (!strcmp(filter_status->buf, "abort") && wanted_capability) {
@@@ -1092,7 -1090,7 +1091,7 @@@ static int count_ident(const char *cp, 
  }
  
  static int ident_to_git(const char *path, const char *src, size_t len,
 -                        struct strbuf *buf, int ident)
 +                      struct strbuf *buf, int ident)
  {
        char *dst, *dollar;
  
  }
  
  static int ident_to_worktree(const char *path, const char *src, size_t len,
 -                             struct strbuf *buf, int ident)
 +                           struct strbuf *buf, int ident)
  {
        struct object_id oid;
        char *to_free = NULL, *dollar, *spc;
diff --combined dir.c
index 21284482198147687fb03892265f97ac5ed58d18,80e07441f7eb893b898e5481427fb6f100402fc4..b2cabadf2503b22cc10b3e47c548a5904d77158e
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -7,7 -7,6 +7,6 @@@
   * Copyright (C) Linus Torvalds, 2005-2006
   *             Junio Hamano, 2005-2006
   */
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "dir.h"
@@@ -276,6 -275,44 +275,6 @@@ static int do_read_blob(const struct ob
  #define DO_MATCH_DIRECTORY (1<<1)
  #define DO_MATCH_SUBMODULE (1<<2)
  
 -static int match_attrs(const struct index_state *istate,
 -                     const char *name, int namelen,
 -                     const struct pathspec_item *item)
 -{
 -      int i;
 -      char *to_free = NULL;
 -
 -      if (name[namelen])
 -              name = to_free = xmemdupz(name, namelen);
 -
 -      git_check_attr(istate, name, item->attr_check);
 -
 -      free(to_free);
 -
 -      for (i = 0; i < item->attr_match_nr; i++) {
 -              const char *value;
 -              int matched;
 -              enum attr_match_mode match_mode;
 -
 -              value = item->attr_check->items[i].value;
 -              match_mode = item->attr_match[i].match_mode;
 -
 -              if (ATTR_TRUE(value))
 -                      matched = (match_mode == MATCH_SET);
 -              else if (ATTR_FALSE(value))
 -                      matched = (match_mode == MATCH_UNSET);
 -              else if (ATTR_UNSET(value))
 -                      matched = (match_mode == MATCH_UNSPECIFIED);
 -              else
 -                      matched = (match_mode == MATCH_VALUE &&
 -                                 !strcmp(item->attr_match[i].value, value));
 -              if (!matched)
 -                      return 0;
 -      }
 -
 -      return 1;
 -}
 -
  /*
   * Does 'match' match the given name?
   * A match is found if
@@@ -329,8 -366,7 +328,8 @@@ static int match_pathspec_item(const st
            strncmp(item->match, name - prefix, item->prefix))
                return 0;
  
 -      if (item->attr_match_nr && !match_attrs(istate, name, namelen, item))
 +      if (item->attr_match_nr &&
 +          !match_pathspec_attrs(istate, name, namelen, item))
                return 0;
  
        /* If the match was just the prefix, we matched */
diff --combined git.c
index 0ce0e13f0f4879ae4608bd61d3a6a1f55ef7892e,0c2b26979743946f26b607d90884287aea68836b..2dd588674f621e2df2af1a3833c2cb3fa8417de4
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -98,8 -98,7 +98,8 @@@ static int list_cmds(const char *spec
        return 0;
  }
  
 -static void commit_pager_choice(void) {
 +static void commit_pager_choice(void)
 +{
        switch (use_pager) {
        case 0:
                setenv("GIT_PAGER", "cat", 1);
@@@ -418,9 -417,9 +418,9 @@@ static int run_builtin(struct cmd_struc
  
        trace_argv_printf(argv, "trace: built-in: git");
  
-       validate_cache_entries(&the_index);
+       validate_cache_entries(the_repository->index);
        status = p->fn(argc, argv, prefix);
-       validate_cache_entries(&the_index);
+       validate_cache_entries(the_repository->index);
  
        if (status)
                return status;
index 9efb3e99023877c804cf0dcf6cf100d6c09c716b,8443184e22718a94d7d84df72fe602c333fde39b..b71bd1fb65bc6b9d6c6889b7dcf8d210d57f1e53
@@@ -18,9 -18,8 +18,9 @@@
   * See Documentation/rev-list-options.txt for allowed values for <arg>.
   *
   * Capture the given arg as the "filter_spec".  This can be forwarded to
 - * subordinate commands when necessary.  We also "intern" the arg for
 - * the convenience of the current command.
 + * subordinate commands when necessary (although it's better to pass it through
 + * expand_list_objects_filter_spec() first).  We also "intern" the arg for the
 + * convenience of the current command.
   */
  static int gently_parse_list_objects_filter(
        struct list_objects_filter_options *filter_options,
                }
  
        } else if (skip_prefix(arg, "tree:", &v0)) {
 -              unsigned long depth;
 -              if (!git_parse_ulong(v0, &depth) || depth != 0) {
 +              if (!git_parse_ulong(v0, &filter_options->tree_exclude_depth)) {
                        if (errbuf) {
                                strbuf_addstr(
                                        errbuf,
 -                                      _("only 'tree:0' is supported"));
 +                                      _("expected 'tree:<depth>'"));
                        }
                        return 1;
                }
 -              filter_options->choice = LOFC_TREE_NONE;
 +              filter_options->choice = LOFC_TREE_DEPTH;
                return 0;
  
        } else if (skip_prefix(arg, "sparse:oid=", &v0)) {
@@@ -71,7 -71,7 +71,7 @@@
                 * command, but DO NOT complain if we don't have the blob or
                 * ref locally.
                 */
-               if (!get_oid_with_context(v0, GET_OID_BLOB,
+               if (!get_oid_with_context(the_repository, v0, GET_OID_BLOB,
                                          &sparse_oid, &oc))
                        filter_options->sparse_oid_value = oiddup(&sparse_oid);
                filter_options->choice = LOFC_SPARSE_OID;
@@@ -112,21 -112,6 +112,21 @@@ int opt_parse_list_objects_filter(cons
        return parse_list_objects_filter(filter_options, arg);
  }
  
 +void expand_list_objects_filter_spec(
 +      const struct list_objects_filter_options *filter,
 +      struct strbuf *expanded_spec)
 +{
 +      strbuf_init(expanded_spec, strlen(filter->filter_spec));
 +      if (filter->choice == LOFC_BLOB_LIMIT)
 +              strbuf_addf(expanded_spec, "blob:limit=%lu",
 +                          filter->blob_limit_value);
 +      else if (filter->choice == LOFC_TREE_DEPTH)
 +              strbuf_addf(expanded_spec, "tree:%lu",
 +                          filter->tree_exclude_depth);
 +      else
 +              strbuf_addstr(expanded_spec, filter->filter_spec);
 +}
 +
  void list_objects_filter_release(
        struct list_objects_filter_options *filter_options)
  {
diff --combined merge-recursive.c
index 59ba4b4a1a083b07050c5e6eba8306cb63736a3e,df00896b251d1608c85cd5abb489ea051eef8eee..4851825aebf29d129aa4b82d860adcbb2697a300
@@@ -146,7 -146,8 +146,8 @@@ static int err(struct merge_options *o
        return -1;
  }
  
- static struct tree *shift_tree_object(struct tree *one, struct tree *two,
+ static struct tree *shift_tree_object(struct repository *repo,
+                                     struct tree *one, struct tree *two,
                                      const char *subtree_shift)
  {
        struct object_id shifted;
        }
        if (oideq(&two->object.oid, &shifted))
                return two;
-       return lookup_tree(the_repository, &shifted);
+       return lookup_tree(repo, &shifted);
  }
  
- static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
+ static struct commit *make_virtual_commit(struct repository *repo,
+                                         struct tree *tree,
+                                         const char *comment)
  {
-       struct commit *commit = alloc_commit_node(the_repository);
+       struct commit *commit = alloc_commit_node(repo);
  
        set_merge_remote_desc(commit, comment, (struct object *)commit);
        commit->maybe_tree = tree;
@@@ -343,22 -346,24 +346,24 @@@ static int add_cacheinfo(struct merge_o
                         unsigned int mode, const struct object_id *oid,
                         const char *path, int stage, int refresh, int options)
  {
+       struct index_state *istate = o->repo->index;
        struct cache_entry *ce;
        int ret;
  
-       ce = make_cache_entry(&the_index, mode, oid ? oid : &null_oid, path, stage, 0);
+       ce = make_cache_entry(istate, mode, oid ? oid : &null_oid, path, stage, 0);
        if (!ce)
                return err(o, _("add_cacheinfo failed for path '%s'; merge aborting."), path);
  
-       ret = add_cache_entry(ce, options);
+       ret = add_index_entry(istate, ce, options);
        if (refresh) {
                struct cache_entry *nce;
  
-               nce = refresh_cache_entry(&the_index, ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
+               nce = refresh_cache_entry(istate, ce,
+                                         CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
                if (!nce)
                        return err(o, _("add_cacheinfo failed to refresh for path '%s'; merge aborting."), path);
                if (nce != ce)
-                       ret = add_cache_entry(nce, options);
+                       ret = add_index_entry(istate, nce, options);
        }
        return ret;
  }
@@@ -386,7 -391,7 +391,7 @@@ static int unpack_trees_start(struct me
        o->unpack_opts.merge = 1;
        o->unpack_opts.head_idx = 2;
        o->unpack_opts.fn = threeway_merge;
-       o->unpack_opts.src_index = &the_index;
+       o->unpack_opts.src_index = o->repo->index;
        o->unpack_opts.dst_index = &tmp_index;
        o->unpack_opts.aggressive = !merge_detect_rename(o);
        setup_unpack_trees_porcelain(&o->unpack_opts, "merge");
        init_tree_desc_from_tree(t+2, merge);
  
        rc = unpack_trees(3, t, &o->unpack_opts);
-       cache_tree_free(&active_cache_tree);
+       cache_tree_free(&o->repo->index->cache_tree);
  
        /*
-        * Update the_index to match the new results, AFTER saving a copy
+        * Update o->repo->index to match the new results, AFTER saving a copy
         * in o->orig_index.  Update src_index to point to the saved copy.
         * (verify_uptodate() checks src_index, and the original index is
         * the one that had the necessary modification timestamps.)
         */
-       o->orig_index = the_index;
-       the_index = tmp_index;
+       o->orig_index = *o->repo->index;
+       *o->repo->index = tmp_index;
        o->unpack_opts.src_index = &o->orig_index;
  
        return rc;
@@@ -420,12 -425,13 +425,13 @@@ static void unpack_trees_finish(struct 
  struct tree *write_tree_from_memory(struct merge_options *o)
  {
        struct tree *result = NULL;
+       struct index_state *istate = o->repo->index;
  
-       if (unmerged_cache()) {
+       if (unmerged_index(istate)) {
                int i;
                fprintf(stderr, "BUG: There are unmerged index entries:\n");
-               for (i = 0; i < active_nr; i++) {
-                       const struct cache_entry *ce = active_cache[i];
+               for (i = 0; i < istate->cache_nr; i++) {
+                       const struct cache_entry *ce = istate->cache[i];
                        if (ce_stage(ce))
                                fprintf(stderr, "BUG: %d %.*s\n", ce_stage(ce),
                                        (int)ce_namelen(ce), ce->name);
                BUG("unmerged index entries in merge-recursive.c");
        }
  
-       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) &&
-           cache_tree_update(&the_index, 0) < 0) {
+       if (!cache_tree_fully_valid(istate->cache_tree) &&
+           cache_tree_update(istate, 0) < 0) {
                err(o, _("error building trees"));
                return NULL;
        }
  
-       result = lookup_tree(the_repository, &active_cache_tree->oid);
+       result = lookup_tree(o->repo, &istate->cache_tree->oid);
  
        return result;
  }
@@@ -469,8 -475,7 +475,8 @@@ static void get_files_dirs(struct merge
  {
        struct pathspec match_all;
        memset(&match_all, 0, sizeof(match_all));
 -      read_tree_recursive(tree, "", 0, 0, &match_all, save_files_dirs, o);
 +      read_tree_recursive(the_repository, tree, "", 0, 0,
 +                          &match_all, save_files_dirs, o);
  }
  
  static int get_tree_entry_if_blob(const struct object_id *tree,
@@@ -513,17 -518,17 +519,17 @@@ static struct stage_data *insert_stage_
   * Create a dictionary mapping file names to stage_data objects. The
   * dictionary contains one entry for every path with a non-zero stage entry.
   */
- static struct string_list *get_unmerged(void)
+ static struct string_list *get_unmerged(struct index_state *istate)
  {
        struct string_list *unmerged = xcalloc(1, sizeof(struct string_list));
        int i;
  
        unmerged->strdup_strings = 1;
  
-       for (i = 0; i < active_nr; i++) {
+       for (i = 0; i < istate->cache_nr; i++) {
                struct string_list_item *item;
                struct stage_data *e;
-               const struct cache_entry *ce = active_cache[i];
+               const struct cache_entry *ce = istate->cache[i];
                if (!ce_stage(ce))
                        continue;
  
@@@ -683,7 -688,7 +689,7 @@@ static int update_stages(struct merge_o
        int clear = 1;
        int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK;
        if (clear)
-               if (remove_file_from_cache(path))
+               if (remove_file_from_index(opt->repo->index, path))
                        return -1;
        if (o)
                if (add_cacheinfo(opt, o->mode, &o->oid, path, 1, 0, options))
@@@ -718,13 -723,14 +724,14 @@@ static int remove_file(struct merge_opt
        int update_working_directory = !o->call_depth && !no_wd;
  
        if (update_cache) {
-               if (remove_file_from_cache(path))
+               if (remove_file_from_index(o->repo->index, path))
                        return -1;
        }
        if (update_working_directory) {
                if (ignore_case) {
                        struct cache_entry *ce;
-                       ce = cache_file_exists(path, strlen(path), ignore_case);
+                       ce = index_file_exists(o->repo->index, path, strlen(path),
+                                              ignore_case);
                        if (ce && ce_stage(ce) == 0 && strcmp(path, ce->name))
                                return 0;
                }
@@@ -774,7 -780,8 +781,8 @@@ static char *unique_path(struct merge_o
   * check the working directory.  If empty_ok is non-zero, also return
   * 0 in the case where the working-tree dir exists but is empty.
   */
- static int dir_in_way(const char *path, int check_working_copy, int empty_ok)
+ static int dir_in_way(struct index_state *istate, const char *path,
+                     int check_working_copy, int empty_ok)
  {
        int pos;
        struct strbuf dirpath = STRBUF_INIT;
        strbuf_addstr(&dirpath, path);
        strbuf_addch(&dirpath, '/');
  
-       pos = cache_name_pos(dirpath.buf, dirpath.len);
+       pos = index_name_pos(istate, dirpath.buf, dirpath.len);
  
        if (pos < 0)
                pos = -1 - pos;
-       if (pos < active_nr &&
-           !strncmp(dirpath.buf, active_cache[pos]->name, dirpath.len)) {
+       if (pos < istate->cache_nr &&
+           !strncmp(dirpath.buf, istate->cache[pos]->name, dirpath.len)) {
                strbuf_release(&dirpath);
                return 1;
        }
@@@ -831,8 -838,10 +839,10 @@@ static int was_tracked(struct merge_opt
        return 0;
  }
  
- static int would_lose_untracked(const char *path)
+ static int would_lose_untracked(struct merge_options *o, const char *path)
  {
+       struct index_state *istate = o->repo->index;
        /*
         * This may look like it can be simplified to:
         *   return !was_tracked(o, path) && file_exists(path)
         * update_file()/would_lose_untracked(); see every comment in this
         * file which mentions "update_stages".
         */
-       int pos = cache_name_pos(path, strlen(path));
+       int pos = index_name_pos(istate, path, strlen(path));
  
        if (pos < 0)
                pos = -1 - pos;
-       while (pos < active_nr &&
-              !strcmp(path, active_cache[pos]->name)) {
+       while (pos < istate->cache_nr &&
+              !strcmp(path, istate->cache[pos]->name)) {
                /*
                 * If stage #0, it is definitely tracked.
                 * If it has stage #2 then it was tracked
                 * before this merge started.  All other
                 * cases the path was not tracked.
                 */
-               switch (ce_stage(active_cache[pos])) {
+               switch (ce_stage(istate->cache[pos])) {
                case 0:
                case 2:
                        return 0;
@@@ -922,7 -931,7 +932,7 @@@ static int make_room_for_path(struct me
         * Do not unlink a file in the work tree if we are not
         * tracking it.
         */
-       if (would_lose_untracked(path))
+       if (would_lose_untracked(o, path))
                return err(o, _("refusing to lose untracked file at '%s'"),
                           path);
  
@@@ -972,7 -981,7 +982,7 @@@ static int update_file_flags(struct mer
                }
                if (S_ISREG(mode)) {
                        struct strbuf strbuf = STRBUF_INIT;
-                       if (convert_to_working_tree(&the_index, path, buf, size, &strbuf)) {
+                       if (convert_to_working_tree(o->repo->index, path, buf, size, &strbuf)) {
                                free(buf);
                                size = strbuf.len;
                                buf = strbuf_detach(&strbuf, NULL);
@@@ -1092,7 -1101,7 +1102,7 @@@ static int merge_3way(struct merge_opti
  
        merge_status = ll_merge(result_buf, a->path, &orig, base_name,
                                &src1, name1, &src2, name2,
-                               &the_index, &ll_opts);
+                               o->repo->index, &ll_opts);
  
        free(base_name);
        free(name1);
        return merge_status;
  }
  
- static int find_first_merges(struct object_array *result, const char *path,
+ static int find_first_merges(struct repository *repo,
+                            struct object_array *result, const char *path,
                             struct commit *a, struct commit *b)
  {
        int i, j;
        /* get all revisions that merge commit a */
        xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
                  oid_to_hex(&a->object.oid));
-       repo_init_revisions(the_repository, &revs, NULL);
+       repo_init_revisions(repo, &revs, NULL);
        rev_opts.submodule = path;
        /* FIXME: can't handle linked worktrees in submodules yet */
        revs.single_worktree = path != NULL;
@@@ -1201,9 -1211,9 +1212,9 @@@ static int merge_submodule(struct merge
                return 0;
        }
  
-       if (!(commit_base = lookup_commit_reference(the_repository, base)) ||
-           !(commit_a = lookup_commit_reference(the_repository, a)) ||
-           !(commit_b = lookup_commit_reference(the_repository, b))) {
+       if (!(commit_base = lookup_commit_reference(o->repo, base)) ||
+           !(commit_a = lookup_commit_reference(o->repo, a)) ||
+           !(commit_b = lookup_commit_reference(o->repo, b))) {
                output(o, 1, _("Failed to merge submodule %s (commits not present)"), path);
                return 0;
        }
                return 0;
  
        /* find commit which merges them */
-       parent_count = find_first_merges(&merges, path, commit_a, commit_b);
+       parent_count = find_first_merges(o->repo, &merges, path,
+                                        commit_a, commit_b);
        switch (parent_count) {
        case 0:
                output(o, 1, _("Failed to merge submodule %s (merge following commits not found)"), path);
@@@ -1401,7 -1412,7 +1413,7 @@@ static int handle_rename_via_dir(struc
         */
        const struct diff_filespec *dest = pair->two;
  
-       if (!o->call_depth && would_lose_untracked(dest->path)) {
+       if (!o->call_depth && would_lose_untracked(o, dest->path)) {
                char *alt_path = unique_path(o, dest->path, rename_branch);
  
                output(o, 1, _("Error: Refusing to lose untracked file at %s; "
@@@ -1439,8 -1450,8 +1451,8 @@@ static int handle_change_delete(struct 
        const char *update_path = path;
        int ret = 0;
  
-       if (dir_in_way(path, !o->call_depth, 0) ||
-           (!o->call_depth && would_lose_untracked(path))) {
+       if (dir_in_way(o->repo->index, path, !o->call_depth, 0) ||
+           (!o->call_depth && would_lose_untracked(o, path))) {
                update_path = alt_path = unique_path(o, path, change_branch);
        }
  
                 * correct; since there is no true "middle point" between
                 * them, simply reuse the base version for virtual merge base.
                 */
-               ret = remove_file_from_cache(path);
+               ret = remove_file_from_index(o->repo->index, path);
                if (!ret)
                        ret = update_file(o, 0, o_oid, o_mode, update_path);
        } else {
@@@ -1526,7 -1537,7 +1538,7 @@@ static int handle_rename_delete(struct 
                return -1;
  
        if (o->call_depth)
-               return remove_file_from_cache(dest->path);
+               return remove_file_from_index(o->repo->index, dest->path);
        else
                return update_stages(o, dest->path, NULL,
                                     rename_branch == o->branch1 ? dest : NULL,
@@@ -1607,10 -1618,10 +1619,10 @@@ static int handle_file_collision(struc
        /* Remove rename sources if rename/add or rename/rename(2to1) */
        if (prev_path1)
                remove_file(o, 1, prev_path1,
-                           o->call_depth || would_lose_untracked(prev_path1));
+                           o->call_depth || would_lose_untracked(o, prev_path1));
        if (prev_path2)
                remove_file(o, 1, prev_path2,
-                           o->call_depth || would_lose_untracked(prev_path2));
+                           o->call_depth || would_lose_untracked(o, prev_path2));
  
        /*
         * Remove the collision path, if it wouldn't cause dirty contents
                output(o, 1, _("Refusing to lose dirty file at %s"),
                       collide_path);
                update_path = alt_path = unique_path(o, collide_path, "merged");
-       } else if (would_lose_untracked(collide_path)) {
+       } else if (would_lose_untracked(o, collide_path)) {
                /*
                 * Only way we get here is if both renames were from
                 * a directory rename AND user had an untracked file
@@@ -1717,12 -1728,12 +1729,12 @@@ static char *find_path_for_conflict(str
                                    const char *branch2)
  {
        char *new_path = NULL;
-       if (dir_in_way(path, !o->call_depth, 0)) {
+       if (dir_in_way(o->repo->index, path, !o->call_depth, 0)) {
                new_path = unique_path(o, path, branch1);
                output(o, 1, _("%s is a directory in %s adding "
                               "as %s instead"),
                       path, branch2, new_path);
-       } else if (would_lose_untracked(path)) {
+       } else if (would_lose_untracked(o, path)) {
                new_path = unique_path(o, path, branch1);
                output(o, 1, _("Refusing to lose untracked file"
                               " at %s; adding as %s instead"),
@@@ -1783,14 -1794,14 +1795,14 @@@ static int handle_rename_rename_1to2(st
                                return -1;
                }
                else
-                       remove_file_from_cache(a->path);
+                       remove_file_from_index(o->repo->index, a->path);
                add = filespec_from_entry(&other, ci->dst_entry2, 3 ^ 1);
                if (add) {
                        if (update_file(o, 0, &add->oid, add->mode, b->path))
                                return -1;
                }
                else
-                       remove_file_from_cache(b->path);
+                       remove_file_from_index(o->repo->index, b->path);
        } else {
                /*
                 * For each destination path, we need to see if there is a
@@@ -1887,7 -1898,7 +1899,7 @@@ static struct diff_queue_struct *get_di
        struct diff_queue_struct *ret;
        struct diff_options opts;
  
-       repo_diff_setup(the_repository, &opts);
+       repo_diff_setup(o->repo, &opts);
        opts.flags.recursive = 1;
        opts.flags.rename_empty = 0;
        opts.detect_rename = merge_detect_rename(o);
@@@ -3042,8 -3053,8 +3054,8 @@@ static int blob_unchanged(struct merge_
         * performed.  Comparison can be skipped if both files are
         * unchanged since their sha1s have already been compared.
         */
-       if (renormalize_buffer(&the_index, path, o.buf, o.len, &o) |
-           renormalize_buffer(&the_index, path, a.buf, a.len, &a))
+       if (renormalize_buffer(opt->repo->index, path, o.buf, o.len, &o) |
+           renormalize_buffer(opt->repo->index, path, a.buf, a.len, &a))
                ret = (o.len == a.len && !memcmp(o.buf, a.buf, o.len));
  
  error_return:
@@@ -3124,7 -3135,7 +3136,7 @@@ static int handle_content_merge(struct 
                a.path = (char *)path1;
                b.path = (char *)path2;
  
-               if (dir_in_way(path, !o->call_depth,
+               if (dir_in_way(o->repo->index, path, !o->call_depth,
                               S_ISGITLINK(pair1->two->mode)))
                        df_conflict_remains = 1;
        }
                pos = index_name_pos(&o->orig_index, path, strlen(path));
                ce = o->orig_index.cache[pos];
                if (ce_skip_worktree(ce)) {
-                       pos = index_name_pos(&the_index, path, strlen(path));
-                       ce = the_index.cache[pos];
+                       pos = index_name_pos(o->repo->index, path, strlen(path));
+                       ce = o->repo->index->cache[pos];
                        ce->ce_flags |= CE_SKIP_WORKTREE;
                }
                return mfi.clean;
        if (df_conflict_remains || is_dirty) {
                char *new_path;
                if (o->call_depth) {
-                       remove_file_from_cache(path);
+                       remove_file_from_index(o->repo->index, path);
                } else {
                        if (!mfi.clean) {
                                if (update_stages(o, path, &one, &a, &b))
@@@ -3338,7 -3349,7 +3350,7 @@@ static int process_entry(struct merge_o
                        oid = b_oid;
                        conf = _("directory/file");
                }
-               if (dir_in_way(path,
+               if (dir_in_way(o->repo->index, path,
                               !o->call_depth && !S_ISGITLINK(a_mode),
                               0)) {
                        char *new_path = unique_path(o, path, add_branch);
                        if (update_file(o, 0, oid, mode, new_path))
                                clean_merge = -1;
                        else if (o->call_depth)
-                               remove_file_from_cache(path);
+                               remove_file_from_index(o->repo->index, path);
                        free(new_path);
                } else {
                        output(o, 2, _("Adding %s"), path);
@@@ -3397,18 -3408,19 +3409,19 @@@ int merge_trees(struct merge_options *o
                struct tree *common,
                struct tree **result)
  {
+       struct index_state *istate = o->repo->index;
        int code, clean;
        struct strbuf sb = STRBUF_INIT;
  
-       if (!o->call_depth && index_has_changes(&the_index, head, &sb)) {
+       if (!o->call_depth && repo_index_has_changes(o->repo, head, &sb)) {
                err(o, _("Your local changes to the following files would be overwritten by merge:\n  %s"),
                    sb.buf);
                return -1;
        }
  
        if (o->subtree_shift) {
-               merge = shift_tree_object(head, merge, o->subtree_shift);
-               common = shift_tree_object(head, common, o->subtree_shift);
+               merge = shift_tree_object(o->repo, head, merge, o->subtree_shift);
+               common = shift_tree_object(o->repo, head, common, o->subtree_shift);
        }
  
        if (oid_eq(&common->object.oid, &merge->object.oid)) {
                return -1;
        }
  
-       if (unmerged_cache()) {
+       if (unmerged_index(istate)) {
                struct string_list *entries;
                struct rename_info re_info;
                int i;
                get_files_dirs(o, head);
                get_files_dirs(o, merge);
  
-               entries = get_unmerged();
+               entries = get_unmerged(o->repo->index);
                clean = detect_and_process_renames(o, common, head, merge,
                                                   entries, &re_info);
                record_df_conflict_files(o, entries);
@@@ -3544,8 -3556,8 +3557,8 @@@ int merge_recursive(struct merge_option
                /* if there is no common ancestor, use an empty tree */
                struct tree *tree;
  
-               tree = lookup_tree(the_repository, the_repository->hash_algo->empty_tree);
-               merged_common_ancestors = make_virtual_commit(tree, "ancestor");
+               tree = lookup_tree(o->repo, o->repo->hash_algo->empty_tree);
+               merged_common_ancestors = make_virtual_commit(o->repo, tree, "ancestor");
        }
  
        for (iter = ca; iter; iter = iter->next) {
                 * overwritten it: the committed "conflicts" were
                 * already resolved.
                 */
-               discard_cache();
+               discard_index(o->repo->index);
                saved_b1 = o->branch1;
                saved_b2 = o->branch2;
                o->branch1 = "Temporary merge branch 1";
                        return err(o, _("merge returned no commit"));
        }
  
-       discard_cache();
+       discard_index(o->repo->index);
        if (!o->call_depth)
-               read_cache();
+               repo_read_index(o->repo);
  
        o->ancestor = "merged common ancestors";
        clean = merge_trees(o, get_commit_tree(h1), get_commit_tree(h2),
        }
  
        if (o->call_depth) {
-               *result = make_virtual_commit(mrtree, "merged tree");
+               *result = make_virtual_commit(o->repo, mrtree, "merged tree");
                commit_list_insert(h1, &(*result)->parents);
                commit_list_insert(h2, &(*result)->parents->next);
        }
        return clean;
  }
  
- static struct commit *get_ref(const struct object_id *oid, const char *name)
+ static struct commit *get_ref(struct repository *repo, const struct object_id *oid,
+                             const char *name)
  {
        struct object *object;
  
-       object = deref_tag(the_repository, parse_object(the_repository, oid),
-                          name,
-                          strlen(name));
+       object = deref_tag(repo, parse_object(repo, oid),
+                          name, strlen(name));
        if (!object)
                return NULL;
        if (object->type == OBJ_TREE)
-               return make_virtual_commit((struct tree*)object, name);
+               return make_virtual_commit(repo, (struct tree*)object, name);
        if (object->type != OBJ_COMMIT)
                return NULL;
        if (parse_commit((struct commit *)object))
@@@ -3629,22 -3641,22 +3642,22 @@@ int merge_recursive_generic(struct merg
  {
        int clean;
        struct lock_file lock = LOCK_INIT;
-       struct commit *head_commit = get_ref(head, o->branch1);
-       struct commit *next_commit = get_ref(merge, o->branch2);
+       struct commit *head_commit = get_ref(o->repo, head, o->branch1);
+       struct commit *next_commit = get_ref(o->repo, merge, o->branch2);
        struct commit_list *ca = NULL;
  
        if (base_list) {
                int i;
                for (i = 0; i < num_base_list; ++i) {
                        struct commit *base;
-                       if (!(base = get_ref(base_list[i], oid_to_hex(base_list[i]))))
+                       if (!(base = get_ref(o->repo, base_list[i], oid_to_hex(base_list[i]))))
                                return err(o, _("Could not parse object '%s'"),
                                           oid_to_hex(base_list[i]));
                        commit_list_insert(base, &ca);
                }
        }
  
-       hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
+       repo_hold_locked_index(o->repo, &lock, LOCK_DIE_ON_ERROR);
        clean = merge_recursive(o, head_commit, next_commit, ca,
                                result);
        if (clean < 0) {
                return clean;
        }
  
-       if (write_locked_index(&the_index, &lock,
+       if (write_locked_index(o->repo->index, &lock,
                               COMMIT_LOCK | SKIP_IF_UNCHANGED))
                return err(o, _("Unable to write index."));
  
@@@ -3676,10 -3688,12 +3689,12 @@@ static void merge_recursive_config(stru
        git_config(git_xmerge_config, NULL);
  }
  
- void init_merge_options(struct merge_options *o)
+ void init_merge_options(struct merge_options *o,
+                       struct repository *repo)
  {
        const char *merge_verbosity;
        memset(o, 0, sizeof(struct merge_options));
+       o->repo = repo;
        o->verbosity = 2;
        o->buffer_output = 1;
        o->diff_rename_limit = -1;
diff --combined pathspec.c
index e85298f68cfeee14494466b0604e572a5c345810,f1505cfd0af0eb5969d1623cec1bf197be95fb27..12c2b322b30a59d2091d2c87df1bed88246d5950
@@@ -1,4 -1,3 +1,3 @@@
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "dir.h"
@@@ -659,41 -658,3 +658,41 @@@ void clear_pathspec(struct pathspec *pa
        FREE_AND_NULL(pathspec->items);
        pathspec->nr = 0;
  }
 +
 +int match_pathspec_attrs(const struct index_state *istate,
 +                       const char *name, int namelen,
 +                       const struct pathspec_item *item)
 +{
 +      int i;
 +      char *to_free = NULL;
 +
 +      if (name[namelen])
 +              name = to_free = xmemdupz(name, namelen);
 +
 +      git_check_attr(istate, name, item->attr_check);
 +
 +      free(to_free);
 +
 +      for (i = 0; i < item->attr_match_nr; i++) {
 +              const char *value;
 +              int matched;
 +              enum attr_match_mode match_mode;
 +
 +              value = item->attr_check->items[i].value;
 +              match_mode = item->attr_match[i].match_mode;
 +
 +              if (ATTR_TRUE(value))
 +                      matched = (match_mode == MATCH_SET);
 +              else if (ATTR_FALSE(value))
 +                      matched = (match_mode == MATCH_UNSET);
 +              else if (ATTR_UNSET(value))
 +                      matched = (match_mode == MATCH_UNSPECIFIED);
 +              else
 +                      matched = (match_mode == MATCH_VALUE &&
 +                                 !strcmp(item->attr_match[i].value, value));
 +              if (!matched)
 +                      return 0;
 +      }
 +
 +      return 1;
 +}
diff --combined read-cache.c
index 9783c493a321046e80a36847d8c36d1af6d263e3,b3865d688493b5cc2522a33bd4c3d0975226fb1a..a66c87bc7a8346d1df529cae5154c8f35ba9d1ca
@@@ -3,7 -3,6 +3,6 @@@
   *
   * Copyright (C) Linus Torvalds, 2005
   */
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "diff.h"
@@@ -95,7 -94,6 +94,6 @@@ static struct mem_pool *find_mem_pool(s
        return *pool_ptr;
  }
  
- struct index_state the_index;
  static const char *alternate_index_output;
  
  static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
@@@ -703,10 -701,10 +701,10 @@@ int add_to_index(struct index_state *is
        int intent_only = flags & ADD_CACHE_INTENT;
        int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
                          (intent_only ? ADD_CACHE_NEW_ONLY : 0));
 -      int newflags = HASH_WRITE_OBJECT;
 +      int hash_flags = HASH_WRITE_OBJECT;
  
 -      if (flags & HASH_RENORMALIZE)
 -              newflags |= HASH_RENORMALIZE;
 +      if (flags & ADD_CACHE_RENORMALIZE)
 +              hash_flags |= HASH_RENORMALIZE;
  
        if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
                return error(_("%s: can only add regular files, symbolic links or git-directories"), path);
                }
        }
        if (!intent_only) {
 -              if (index_path(istate, &ce->oid, path, st, newflags)) {
 +              if (index_path(istate, &ce->oid, path, st, hash_flags)) {
                        discard_cache_entry(ce);
                        return error(_("unable to index file '%s'"), path);
                }
@@@ -1733,16 -1731,6 +1731,6 @@@ static int read_index_extension(struct 
        return 0;
  }
  
- int hold_locked_index(struct lock_file *lk, int lock_flags)
- {
-       return hold_lock_file_for_update(lk, get_index_file(), lock_flags);
- }
- int read_index(struct index_state *istate)
- {
-       return read_index_from(istate, get_index_file(), get_git_dir());
- }
  static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
                                            unsigned int version,
                                            struct ondisk_cache_entry *ondisk,
@@@ -2375,22 -2363,20 +2363,20 @@@ int unmerged_index(const struct index_s
        return 0;
  }
  
- int index_has_changes(struct index_state *istate,
-                     struct tree *tree,
-                     struct strbuf *sb)
+ int repo_index_has_changes(struct repository *repo,
+                          struct tree *tree,
+                          struct strbuf *sb)
  {
+       struct index_state *istate = repo->index;
        struct object_id cmp;
        int i;
  
-       if (istate != &the_index) {
-               BUG("index_has_changes cannot yet accept istate != &the_index; do_diff_cache needs updating first.");
-       }
        if (tree)
                cmp = tree->object.oid;
        if (tree || !get_oid_tree("HEAD", &cmp)) {
                struct diff_options opt;
  
-               repo_diff_setup(the_repository, &opt);
+               repo_diff_setup(repo, &opt);
                opt.flags.exit_with_status = 1;
                if (!sb)
                        opt.flags.quick = 1;
@@@ -2664,9 -2650,9 +2650,9 @@@ out
        return 0;
  }
  
- static int verify_index(const struct index_state *istate)
+ static int repo_verify_index(struct repository *repo)
  {
-       return verify_index_from(istate, get_index_file());
+       return verify_index_from(repo->index, repo->index_file);
  }
  
  static int has_racy_timestamp(struct index_state *istate)
        return 0;
  }
  
- void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
+ void repo_update_index_if_able(struct repository *repo,
+                              struct lock_file *lockfile)
  {
-       if ((istate->cache_changed || has_racy_timestamp(istate)) &&
-           verify_index(istate))
-               write_locked_index(istate, lockfile, COMMIT_LOCK);
+       if ((repo->index->cache_changed ||
+            has_racy_timestamp(repo->index)) &&
+           repo_verify_index(repo))
+               write_locked_index(repo->index, lockfile, COMMIT_LOCK);
        else
                rollback_lock_file(lockfile);
  }
   * state can call this and check its return value, instead of calling
   * read_cache().
   */
- int read_index_unmerged(struct index_state *istate)
+ int repo_read_index_unmerged(struct repository *repo)
  {
+       struct index_state *istate;
        int i;
        int unmerged = 0;
  
-       read_index(istate);
+       repo_read_index(repo);
+       istate = repo->index;
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce = istate->cache[i];
                struct cache_entry *new_ce;
@@@ -3495,71 -3485,71 +3485,71 @@@ static void write_eoie_extension(struc
  
  static struct index_entry_offset_table *read_ieot_extension(const char *mmap, size_t mmap_size, size_t offset)
  {
 -       const char *index = NULL;
 -       uint32_t extsize, ext_version;
 -       struct index_entry_offset_table *ieot;
 -       int i, nr;
 -
 -       /* find the IEOT extension */
 -       if (!offset)
 -             return NULL;
 -       while (offset <= mmap_size - the_hash_algo->rawsz - 8) {
 -             extsize = get_be32(mmap + offset + 4);
 -             if (CACHE_EXT((mmap + offset)) == CACHE_EXT_INDEXENTRYOFFSETTABLE) {
 -                     index = mmap + offset + 4 + 4;
 -                     break;
 -             }
 -             offset += 8;
 -             offset += extsize;
 -       }
 -       if (!index)
 -             return NULL;
 -
 -       /* validate the version is IEOT_VERSION */
 -       ext_version = get_be32(index);
 -       if (ext_version != IEOT_VERSION) {
 -             error("invalid IEOT version %d", ext_version);
 -             return NULL;
 -       }
 -       index += sizeof(uint32_t);
 -
 -       /* extension size - version bytes / bytes per entry */
 -       nr = (extsize - sizeof(uint32_t)) / (sizeof(uint32_t) + sizeof(uint32_t));
 -       if (!nr) {
 -             error("invalid number of IEOT entries %d", nr);
 -             return NULL;
 -       }
 -       ieot = xmalloc(sizeof(struct index_entry_offset_table)
 -             + (nr * sizeof(struct index_entry_offset)));
 -       ieot->nr = nr;
 -       for (i = 0; i < nr; i++) {
 -             ieot->entries[i].offset = get_be32(index);
 -             index += sizeof(uint32_t);
 -             ieot->entries[i].nr = get_be32(index);
 -             index += sizeof(uint32_t);
 -       }
 -
 -       return ieot;
 +      const char *index = NULL;
 +      uint32_t extsize, ext_version;
 +      struct index_entry_offset_table *ieot;
 +      int i, nr;
 +
 +      /* find the IEOT extension */
 +      if (!offset)
 +              return NULL;
 +      while (offset <= mmap_size - the_hash_algo->rawsz - 8) {
 +              extsize = get_be32(mmap + offset + 4);
 +              if (CACHE_EXT((mmap + offset)) == CACHE_EXT_INDEXENTRYOFFSETTABLE) {
 +                      index = mmap + offset + 4 + 4;
 +                      break;
 +              }
 +              offset += 8;
 +              offset += extsize;
 +      }
 +      if (!index)
 +              return NULL;
 +
 +      /* validate the version is IEOT_VERSION */
 +      ext_version = get_be32(index);
 +      if (ext_version != IEOT_VERSION) {
 +              error("invalid IEOT version %d", ext_version);
 +              return NULL;
 +      }
 +      index += sizeof(uint32_t);
 +
 +      /* extension size - version bytes / bytes per entry */
 +      nr = (extsize - sizeof(uint32_t)) / (sizeof(uint32_t) + sizeof(uint32_t));
 +      if (!nr) {
 +              error("invalid number of IEOT entries %d", nr);
 +              return NULL;
 +      }
 +      ieot = xmalloc(sizeof(struct index_entry_offset_table)
 +                     + (nr * sizeof(struct index_entry_offset)));
 +      ieot->nr = nr;
 +      for (i = 0; i < nr; i++) {
 +              ieot->entries[i].offset = get_be32(index);
 +              index += sizeof(uint32_t);
 +              ieot->entries[i].nr = get_be32(index);
 +              index += sizeof(uint32_t);
 +      }
 +
 +      return ieot;
  }
  
  static void write_ieot_extension(struct strbuf *sb, struct index_entry_offset_table *ieot)
  {
 -       uint32_t buffer;
 -       int i;
 +      uint32_t buffer;
 +      int i;
  
 -       /* version */
 -       put_be32(&buffer, IEOT_VERSION);
 -       strbuf_add(sb, &buffer, sizeof(uint32_t));
 +      /* version */
 +      put_be32(&buffer, IEOT_VERSION);
 +      strbuf_add(sb, &buffer, sizeof(uint32_t));
  
 -       /* ieot */
 -       for (i = 0; i < ieot->nr; i++) {
 +      /* ieot */
 +      for (i = 0; i < ieot->nr; i++) {
  
 -             /* offset */
 -             put_be32(&buffer, ieot->entries[i].offset);
 -             strbuf_add(sb, &buffer, sizeof(uint32_t));
 +              /* offset */
 +              put_be32(&buffer, ieot->entries[i].offset);
 +              strbuf_add(sb, &buffer, sizeof(uint32_t));
  
 -             /* count */
 -             put_be32(&buffer, ieot->entries[i].nr);
 -             strbuf_add(sb, &buffer, sizeof(uint32_t));
 -       }
 +              /* count */
 +              put_be32(&buffer, ieot->entries[i].nr);
 +              strbuf_add(sb, &buffer, sizeof(uint32_t));
 +      }
  }
diff --combined repository.c
index 20c509a9226645b1890c8433b22a7182699fc847,36a3b52d709a4516a7987c2c64288dc523adf415..65e6f8b8fdfcf89e5c86cbee9590aa555f7b0b47
@@@ -1,13 -1,20 +1,20 @@@
+ /*
+  * not really _using_ the compat macros, just make sure the_index
+  * declaration matches the definition in this file.
+  */
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "repository.h"
  #include "object-store.h"
  #include "config.h"
  #include "object.h"
+ #include "lockfile.h"
  #include "submodule-config.h"
  
  /* The main repository */
  static struct repository the_repo;
  struct repository *the_repository;
+ struct index_state the_index;
  
  void initialize_the_repository(void)
  {
@@@ -172,23 -179,30 +179,23 @@@ error
        return -1;
  }
  
 -/*
 - * Initialize 'submodule' as the submodule given by 'path' in parent repository
 - * 'superproject'.
 - * Return 0 upon success and a non-zero value upon failure.
 - */
 -int repo_submodule_init(struct repository *submodule,
 +int repo_submodule_init(struct repository *subrepo,
                        struct repository *superproject,
 -                      const char *path)
 +                      const struct submodule *sub)
  {
 -      const struct submodule *sub;
        struct strbuf gitdir = STRBUF_INIT;
        struct strbuf worktree = STRBUF_INIT;
        int ret = 0;
  
 -      sub = submodule_from_path(superproject, &null_oid, path);
        if (!sub) {
                ret = -1;
                goto out;
        }
  
 -      strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path);
 -      strbuf_repo_worktree_path(&worktree, superproject, "%s", path);
 +      strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", sub->path);
 +      strbuf_repo_worktree_path(&worktree, superproject, "%s", sub->path);
  
 -      if (repo_init(submodule, gitdir.buf, worktree.buf)) {
 +      if (repo_init(subrepo, gitdir.buf, worktree.buf)) {
                /*
                 * If initilization fails then it may be due to the submodule
                 * not being populated in the superproject's worktree.  Instead
                strbuf_repo_git_path(&gitdir, superproject,
                                     "modules/%s", sub->name);
  
 -              if (repo_init(submodule, gitdir.buf, NULL)) {
 +              if (repo_init(subrepo, gitdir.buf, NULL)) {
                        ret = -1;
                        goto out;
                }
        }
  
 -      submodule->submodule_prefix = xstrfmt("%s%s/",
 -                                            superproject->submodule_prefix ?
 -                                            superproject->submodule_prefix :
 -                                            "", path);
 +      subrepo->submodule_prefix = xstrfmt("%s%s/",
 +                                          superproject->submodule_prefix ?
 +                                          superproject->submodule_prefix :
 +                                          "", sub->path);
  
  out:
        strbuf_release(&gitdir);
@@@ -256,3 -270,12 +263,12 @@@ int repo_read_index(struct repository *
  
        return read_index_from(repo->index, repo->index_file, repo->gitdir);
  }
+ int repo_hold_locked_index(struct repository *repo,
+                          struct lock_file *lf,
+                          int flags)
+ {
+       if (!repo->index_file)
+               BUG("the repo hasn't been setup");
+       return hold_lock_file_for_update(lf, repo->index_file, flags);
+ }
diff --combined repository.h
index 0e482b7d49e82c3cf46d81523e057e3a02d2e8f4,6fe1c089db9d8e72158290512ba147abb3d1d3cb..8981649d43736ee283fcd23cd3185288252d5357
@@@ -6,6 -6,8 +6,8 @@@
  struct config_set;
  struct git_hash_algo;
  struct index_state;
+ struct lock_file;
+ struct pathspec;
  struct raw_object_store;
  struct submodule_cache;
  
@@@ -116,17 -118,9 +118,17 @@@ void repo_set_worktree(struct repositor
  void repo_set_hash_algo(struct repository *repo, int algo);
  void initialize_the_repository(void);
  int repo_init(struct repository *r, const char *gitdir, const char *worktree);
 -int repo_submodule_init(struct repository *submodule,
 +
 +/*
 + * Initialize the repository 'subrepo' as the submodule given by the
 + * struct submodule 'sub' in parent repository 'superproject'.
 + * Return 0 upon success and a non-zero value upon failure, which may happen
 + * if the submodule is not found, or 'sub' is NULL.
 + */
 +struct submodule;
 +int repo_submodule_init(struct repository *subrepo,
                        struct repository *superproject,
 -                      const char *path);
 +                      const struct submodule *sub);
  void repo_clear(struct repository *repo);
  
  /*
   * populated then the number of entries will simply be returned.
   */
  int repo_read_index(struct repository *repo);
+ int repo_hold_locked_index(struct repository *repo,
+                          struct lock_file *lf,
+                          int flags);
+ int repo_read_index_preload(struct repository *,
+                           const struct pathspec *pathspec,
+                           unsigned refresh_flags);
+ int repo_read_index_unmerged(struct repository *);
+ /*
+  * Opportunistically update the index but do not complain if we can't.
+  * The lockfile is always committed or rolled back.
+  */
+ void repo_update_index_if_able(struct repository *, struct lock_file *);
  
  #endif /* REPOSITORY_H */
diff --combined revision.c
index 8f886fe8c644bfce221ddd2be94db7f05b5451e7,4a723efe9a653db16a2e069bd8b20f7a262753d3..5c7d3c75d7d8697dbf4ab41441a9e22b7f0a536d
@@@ -67,10 -67,10 +67,10 @@@ static void mark_tree_contents_unintere
        while (tree_entry(&desc, &entry)) {
                switch (object_type(entry.mode)) {
                case OBJ_TREE:
 -                      mark_tree_uninteresting(r, lookup_tree(r, entry.oid));
 +                      mark_tree_uninteresting(r, lookup_tree(r, &entry.oid));
                        break;
                case OBJ_BLOB:
 -                      mark_blob_uninteresting(lookup_blob(r, entry.oid));
 +                      mark_blob_uninteresting(lookup_blob(r, &entry.oid));
                        break;
                default:
                        /* Subproject commit - not in this repository */
@@@ -213,20 -213,7 +213,20 @@@ static struct object *get_reference(str
  {
        struct object *object;
  
 -      object = parse_object(revs->repo, oid);
 +      /*
 +       * If the repository has commit graphs, repo_parse_commit() avoids
 +       * reading the object buffer, so use it whenever possible.
 +       */
 +      if (oid_object_info(revs->repo, oid, NULL) == OBJ_COMMIT) {
 +              struct commit *c = lookup_commit(revs->repo, oid);
 +              if (!repo_parse_commit(revs->repo, c))
 +                      object = (struct object *) c;
 +              else
 +                      object = NULL;
 +      } else {
 +              object = parse_object(revs->repo, oid);
 +      }
 +
        if (!object) {
                if (revs->ignore_missing)
                        return object;
@@@ -1397,7 -1384,7 +1397,7 @@@ void add_index_objects_to_pending(struc
  {
        struct worktree **worktrees, **p;
  
-       read_index(revs->repo->index);
+       repo_read_index(revs->repo);
        do_add_index_objects_to_pending(revs, revs->repo->index, flags);
  
        if (revs->single_worktree)
@@@ -1476,7 -1463,6 +1476,7 @@@ void repo_init_revisions(struct reposit
        revs->abbrev = DEFAULT_ABBREV;
        revs->ignore_merges = 1;
        revs->simplify_history = 1;
 +      revs->pruning.repo = r;
        revs->pruning.flags.recursive = 1;
        revs->pruning.flags.quick = 1;
        revs->pruning.add_remove = file_add_remove;
  }
  
  static void add_pending_commit_list(struct rev_info *revs,
 -                                    struct commit_list *commit_list,
 -                                    unsigned int flags)
 +                                  struct commit_list *commit_list,
 +                                  unsigned int flags)
  {
        while (commit_list) {
                struct object *object = &commit_list->item->object;
@@@ -1544,7 -1530,7 +1544,7 @@@ static void prepare_show_merge(struct r
        head->object.flags |= SYMMETRIC_LEFT;
  
        if (!istate->cache_nr)
-               read_index(istate);
+               repo_read_index(revs->repo);
        for (i = 0; i < istate->cache_nr; i++) {
                const struct cache_entry *ce = istate->cache[i];
                if (!ce_stage(ce))
@@@ -1603,8 -1589,8 +1603,8 @@@ static int handle_dotdot_1(const char *
        if (!*b_name)
                b_name = "HEAD";
  
-       if (get_oid_with_context(a_name, oc_flags, &a_oid, a_oc) ||
-           get_oid_with_context(b_name, oc_flags, &b_oid, b_oc))
+       if (get_oid_with_context(revs->repo, a_name, oc_flags, &a_oid, a_oc) ||
+           get_oid_with_context(revs->repo, b_name, oc_flags, &b_oid, b_oc))
                return -1;
  
        if (!cant_be_filename) {
@@@ -1738,13 -1724,11 +1738,13 @@@ int handle_revision_arg(const char *arg
        if (revarg_opt & REVARG_COMMITTISH)
                get_sha1_flags |= GET_OID_COMMITTISH;
  
-       if (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))
+       if (get_oid_with_context(revs->repo, arg, get_sha1_flags, &oid, &oc))
                return revs->ignore_missing ? 0 : -1;
        if (!cant_be_filename)
                verify_non_filename(revs->prefix, arg);
        object = get_reference(revs, arg, &oid, flags ^ local_flags);
 +      if (!object)
 +              return revs->ignore_missing ? 0 : -1;
        add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags);
        add_pending_object_with_path(revs, object, arg, oc.mode, oc.path);
        free(oc.path);
@@@ -1807,8 -1791,7 +1807,8 @@@ static void add_message_grep(struct rev
  }
  
  static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
 -                             int *unkc, const char **unkv)
 +                             int *unkc, const char **unkv,
 +                             const struct setup_revision_opt* opt)
  {
        const char *arg = argv[0];
        const char *optarg;
                revs->limited = 1;
        } else if (!strcmp(arg, "--ignore-missing")) {
                revs->ignore_missing = 1;
 -      } else if (revs->allow_exclude_promisor_objects_opt &&
 +      } else if (opt && opt->allow_exclude_promisor_objects &&
                   !strcmp(arg, "--exclude-promisor-objects")) {
                if (fetch_if_missing)
                        BUG("exclude_promisor_objects can only be used when fetch_if_missing is 0");
@@@ -2190,7 -2173,7 +2190,7 @@@ void parse_revision_opt(struct rev_inf
                        const char * const usagestr[])
  {
        int n = handle_revision_opt(revs, ctx->argc, ctx->argv,
 -                                  &ctx->cpidx, ctx->out);
 +                                  &ctx->cpidx, ctx->out, NULL);
        if (n <= 0) {
                error("unknown option `%s'", ctx->argv[0]);
                usage_with_options(usagestr, options);
@@@ -2408,8 -2391,7 +2408,8 @@@ int setup_revisions(int argc, const cha
                                continue;
                        }
  
 -                      opts = handle_revision_opt(revs, argc - i, argv + i, &left, argv);
 +                      opts = handle_revision_opt(revs, argc - i, argv + i,
 +                                                 &left, argv, opt);
                        if (opts > 0) {
                                i += opts - 1;
                                continue;
                struct object_id oid;
                struct object *object;
                struct object_context oc;
-               if (get_oid_with_context(revs->def, 0, &oid, &oc))
+               if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc))
                        diagnose_missing_default(revs->def);
                object = get_reference(revs, revs->def, &oid, 0);
                add_pending_object_with_mode(revs, object, revs->def, oc.mode);
diff --combined sequencer.c
index a6333abd3990825ed0573c408837dbf164f31f4f,cede6ea095b3220ceef853705b946d39b41bad2a..972402e8c0a09de5ec9069826cbb7ecae1ac9803
@@@ -150,7 -150,6 +150,7 @@@ static GIT_PATH_FUNC(rebase_path_refs_t
  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 +static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
  static GIT_PATH_FUNC(rebase_path_signoff, "rebase-merge/signoff")
  static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
  static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
@@@ -158,7 -157,7 +158,7 @@@ static GIT_PATH_FUNC(rebase_path_autost
  static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
  static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
  static GIT_PATH_FUNC(rebase_path_allow_rerere_autoupdate, "rebase-merge/allow_rerere_autoupdate")
 -static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
 +static GIT_PATH_FUNC(rebase_path_reschedule_failed_exec, "rebase-merge/reschedule-failed-exec")
  
  static int git_sequencer_config(const char *k, const char *v, void *cb)
  {
@@@ -447,9 -446,9 +447,9 @@@ static struct tree *empty_tree(struct r
        return lookup_tree(r, the_hash_algo->empty_tree);
  }
  
- static int error_dirty_index(struct index_state *istate, struct replay_opts *opts)
+ static int error_dirty_index(struct repository *repo, struct replay_opts *opts)
  {
-       if (read_index_unmerged(istate))
+       if (repo_read_index_unmerged(repo))
                return error_resolve_conflict(_(action_name(opts)));
  
        error(_("your local changes would be overwritten by %s."),
@@@ -484,7 -483,7 +484,7 @@@ static int fast_forward_to(struct repos
        struct strbuf sb = STRBUF_INIT;
        struct strbuf err = STRBUF_INIT;
  
-       read_index(r->index);
+       repo_read_index(r);
        if (checkout_fast_forward(r, from, to, 1))
                return -1; /* the callee should have complained already */
  
@@@ -541,12 -540,12 +541,12 @@@ static int do_recursive_merge(struct re
        char **xopt;
        struct lock_file index_lock = LOCK_INIT;
  
-       if (hold_locked_index(&index_lock, LOCK_REPORT_ON_ERROR) < 0)
+       if (repo_hold_locked_index(r, &index_lock, LOCK_REPORT_ON_ERROR) < 0)
                return -1;
  
-       read_index(r->index);
+       repo_read_index(r);
  
-       init_merge_options(&o);
+       init_merge_options(&o, r);
        o.ancestor = base ? base_label : "(empty tree)";
        o.branch1 = "HEAD";
        o.branch2 = next ? next_label : "(empty tree)";
@@@ -1116,7 -1115,8 +1116,8 @@@ static int run_rewrite_hook(const struc
        return finish_command(&proc);
  }
  
- void commit_post_rewrite(const struct commit *old_head,
+ void commit_post_rewrite(struct repository *r,
+                        const struct commit *old_head,
                         const struct object_id *new_head)
  {
        struct notes_rewrite_cfg *cfg;
        if (cfg) {
                /* we are amending, so old_head is not NULL */
                copy_note_for_rewrite(cfg, &old_head->object.oid, new_head);
-               finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
+               finish_copy_notes_for_rewrite(r, cfg, "Notes added by 'git commit --amend'");
        }
        run_rewrite_hook(&old_head->object.oid, new_head);
  }
@@@ -1406,7 -1406,7 +1407,7 @@@ static int try_to_commit(struct reposit
        }
  
        if (flags & AMEND_MSG)
-               commit_post_rewrite(current_head, oid);
+               commit_post_rewrite(r, current_head, oid);
  
  out:
        free_commit_extra_headers(extra);
@@@ -1690,8 -1690,7 +1691,8 @@@ static int update_squash_messages(struc
        return res;
  }
  
 -static void flush_rewritten_pending(void) {
 +static void flush_rewritten_pending(void)
 +{
        struct strbuf buf = STRBUF_INIT;
        struct object_id newoid;
        FILE *out;
  }
  
  static void record_in_rewritten(struct object_id *oid,
 -              enum todo_command next_command) {
 +              enum todo_command next_command)
 +{
        FILE *out = fopen_or_warn(rebase_path_rewritten_pending(), "a");
  
        if (!out)
@@@ -1768,7 -1766,7 +1769,7 @@@ static int do_pick_commit(struct reposi
                        oidcpy(&head, the_hash_algo->empty_tree);
                if (index_differs_from(r, unborn ? empty_tree_oid_hex() : "HEAD",
                                       NULL, 0))
-                       return error_dirty_index(r->index, opts);
+                       return error_dirty_index(r, opts);
        }
        discard_index(r->index);
  
                        return error(_("commit %s does not have parent %d"),
                                oid_to_hex(&commit->object.oid), opts->mainline);
                parent = p->item;
 -      } else if (0 < opts->mainline)
 -              return error(_("mainline was specified but commit %s is not a merge."),
 -                      oid_to_hex(&commit->object.oid));
 +      } else if (1 < opts->mainline)
 +              /*
 +               *  Non-first parent explicitly specified as mainline for
 +               *  non-merge commit
 +               */
 +              return error(_("commit %s does not have parent %d"),
 +                           oid_to_hex(&commit->object.oid), opts->mainline);
        else
                parent = commit->parents->item;
  
@@@ -1998,8 -1992,8 +1999,8 @@@ static int read_and_refresh_cache(struc
                                  struct replay_opts *opts)
  {
        struct lock_file index_lock = LOCK_INIT;
-       int index_fd = hold_locked_index(&index_lock, 0);
-       if (read_index(r->index) < 0) {
+       int index_fd = repo_hold_locked_index(r, &index_lock, 0);
+       if (repo_read_index(r) < 0) {
                rollback_lock_file(&index_lock);
                return error(_("git %s: failed to read the index"),
                        _(action_name(opts)));
@@@ -2390,17 -2384,11 +2391,17 @@@ static int read_populate_opts(struct re
                if (file_exists(rebase_path_verbose()))
                        opts->verbose = 1;
  
 +              if (file_exists(rebase_path_quiet()))
 +                      opts->quiet = 1;
 +
                if (file_exists(rebase_path_signoff())) {
                        opts->allow_ff = 0;
                        opts->signoff = 1;
                }
  
 +              if (file_exists(rebase_path_reschedule_failed_exec()))
 +                      opts->reschedule_failed_exec = 1;
 +
                read_strategy_opts(opts, &buf);
                strbuf_release(&buf);
  
@@@ -2463,6 -2451,9 +2464,6 @@@ int write_basic_state(struct replay_opt
  
        if (quiet)
                write_file(rebase_path_quiet(), "%s\n", quiet);
 -      else
 -              write_file(rebase_path_quiet(), "\n");
 -
        if (opts->verbose)
                write_file(rebase_path_verbose(), "%s", "");
        if (opts->strategy)
                write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
        if (opts->signoff)
                write_file(rebase_path_signoff(), "--signoff\n");
 +      if (opts->reschedule_failed_exec)
 +              write_file(rebase_path_reschedule_failed_exec(), "%s", "");
  
        return 0;
  }
@@@ -2865,7 -2854,7 +2866,7 @@@ static int do_exec(struct repository *r
                                          child_env.argv);
  
        /* force re-reading of the cache */
-       if (discard_index(r->index) < 0 || read_index(r->index) < 0)
+       if (discard_index(r->index) < 0 || repo_read_index(r) < 0)
                return error(_("could not read index"));
  
        dirty = require_clean_work_tree(r, "rebase", NULL, 1, 1);
@@@ -2989,7 -2978,7 +2990,7 @@@ static int do_reset(struct repository *
        struct unpack_trees_options unpack_tree_opts;
        int ret = 0;
  
-       if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0)
+       if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0)
                return -1;
  
        if (len == 10 && !strncmp("[new root]", name, len)) {
        unpack_tree_opts.merge = 1;
        unpack_tree_opts.update = 1;
  
-       if (read_index_unmerged(r->index)) {
+       if (repo_read_index_unmerged(r)) {
                rollback_lock_file(&lock);
                strbuf_release(&ref_name);
                return error_resolve_conflict(_(action_name(opts)));
@@@ -3107,7 -3096,7 +3108,7 @@@ static int do_merge(struct repository *
        static struct lock_file lock;
        const char *p;
  
-       if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) {
+       if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
                ret = -1;
                goto leave_merge;
        }
  
                /* force re-reading of the cache */
                if (!ret && (discard_index(r->index) < 0 ||
-                            read_index(r->index) < 0))
+                            repo_read_index(r) < 0))
                        ret = error(_("could not read index"));
                goto leave_merge;
        }
                commit_list_insert(j->item, &reversed);
        free_commit_list(bases);
  
-       read_index(r->index);
-       init_merge_options(&o);
+       repo_read_index(r);
+       init_merge_options(&o, r);
        o.branch1 = "HEAD";
        o.branch2 = ref_name.buf;
        o.buffer_output = 2;
@@@ -3555,11 -3544,10 +3556,11 @@@ static int pick_commits(struct reposito
                                        fprintf(f, "%d\n", todo_list->done_nr);
                                        fclose(f);
                                }
 -                              fprintf(stderr, "Rebasing (%d/%d)%s",
 -                                      todo_list->done_nr,
 -                                      todo_list->total_nr,
 -                                      opts->verbose ? "\n" : "\r");
 +                              if (!opts->quiet)
 +                                      fprintf(stderr, "Rebasing (%d/%d)%s",
 +                                              todo_list->done_nr,
 +                                              todo_list->total_nr,
 +                                              opts->verbose ? "\n" : "\r");
                        }
                        unlink(rebase_path_message());
                        unlink(rebase_path_author_script());
                        *end_of_arg = saved;
  
                        /* Reread the todo file if it has changed. */
 -                      if (res)
 -                              ; /* fall through */
 -                      else if (stat(get_todo_path(opts), &st))
 +                      if (res) {
 +                              if (opts->reschedule_failed_exec)
 +                                      reschedule = 1;
 +                      } else if (stat(get_todo_path(opts), &st))
                                res = error_errno(_("could not stat '%s'"),
                                                  get_todo_path(opts));
                        else if (match_stat_data(&todo_list->stat, &st)) {
@@@ -3793,10 -3780,8 +3794,10 @@@ cleanup_head_ref
                }
                apply_autostash(opts);
  
 -              fprintf(stderr, "Successfully rebased and updated %s.\n",
 -                      head_ref.buf);
 +              if (!opts->quiet)
 +                      fprintf(stderr,
 +                              "Successfully rebased and updated %s.\n",
 +                              head_ref.buf);
  
                strbuf_release(&buf);
                strbuf_release(&head_ref);
@@@ -3987,7 -3972,7 +3988,7 @@@ int sequencer_continue(struct repositor
                                goto release_todo_list;
                }
                if (index_differs_from(r, "HEAD", NULL, 0)) {
-                       res = error_dirty_index(r->index, opts);
+                       res = error_dirty_index(r, opts);
                        goto release_todo_list;
                }
                todo_list.current++;
diff --combined sequencer.h
index 53b86797188e8bef7371cd922bfafdc2464c1281,2caecd550b869945ceb020929fdb5fc06728d901..93e891309bb7982c283c77e8950ba8848fdd7d2b
@@@ -40,8 -40,6 +40,8 @@@ struct replay_opts 
        int allow_empty_message;
        int keep_redundant_commits;
        int verbose;
 +      int quiet;
 +      int reschedule_failed_exec;
  
        int mainline;
  
@@@ -126,7 -124,8 +126,8 @@@ int update_head_with_reflog(const struc
                            const struct object_id *new_head,
                            const char *action, const struct strbuf *msg,
                            struct strbuf *err);
- void commit_post_rewrite(const struct commit *current_head,
+ void commit_post_rewrite(struct repository *r,
+                        const struct commit *current_head,
                         const struct object_id *new_head);
  
  int prepare_branch_to_be_rebased(struct replay_opts *opts, const char *commit);
diff --combined sha1-name.c
index 4acd406b0ad7ed448878fe416c1d0221032ca65e,d8cab7b5a60095a6a61973e3a7de498ddf6c702b..d1cc77c124c11ffd49be472b1368baeda3afbe17
@@@ -87,21 -87,21 +87,21 @@@ static int match_sha(unsigned, const un
  
  static void find_short_object_filename(struct disambiguate_state *ds)
  {
 -      int subdir_nr = ds->bin_pfx.hash[0];
        struct object_directory *odb;
  
        for (odb = the_repository->objects->odb;
             odb && !ds->ambiguous;
             odb = odb->next) {
                int pos;
 +              struct oid_array *loose_objects;
  
 -              odb_load_loose_cache(odb, subdir_nr);
 -              pos = oid_array_lookup(&odb->loose_objects_cache, &ds->bin_pfx);
 +              loose_objects = odb_loose_cache(odb, &ds->bin_pfx);
 +              pos = oid_array_lookup(loose_objects, &ds->bin_pfx);
                if (pos < 0)
                        pos = -1 - pos;
 -              while (!ds->ambiguous && pos < odb->loose_objects_cache.nr) {
 +              while (!ds->ambiguous && pos < loose_objects->nr) {
                        const struct object_id *oid;
 -                      oid = odb->loose_objects_cache.oid + pos;
 +                      oid = loose_objects->oid + pos;
                        if (!match_sha(ds->len, ds->bin_pfx.hash, oid->hash))
                                break;
                        update_candidates(ds, oid);
@@@ -190,6 -190,9 +190,6 @@@ static void find_short_packed_object(st
                unique_in_pack(p, ds);
  }
  
 -#define SHORT_NAME_NOT_FOUND (-1)
 -#define SHORT_NAME_AMBIGUOUS (-2)
 -
  static int finish_object_disambiguation(struct disambiguate_state *ds,
                                        struct object_id *oid)
  {
                return SHORT_NAME_AMBIGUOUS;
  
        if (!ds->candidate_exists)
 -              return SHORT_NAME_NOT_FOUND;
 +              return MISSING_OBJECT;
  
        if (!ds->candidate_checked)
                /*
@@@ -411,9 -414,8 +411,9 @@@ static int sort_ambiguous(const void *a
        return a_type_sort > b_type_sort ? 1 : -1;
  }
  
 -static int get_short_oid(const char *name, int len, struct object_id *oid,
 -                        unsigned flags)
 +static enum get_oid_result get_short_oid(const char *name, int len,
 +                                       struct object_id *oid,
 +                                       unsigned flags)
  {
        int status;
        struct disambiguate_state ds;
@@@ -731,7 -733,7 +731,7 @@@ static inline int push_mark(const char 
        return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
  }
  
 -static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);
 +static enum get_oid_result get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);
  static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
  
  static int get_oid_basic(const char *str, int len, struct object_id *oid,
        return 0;
  }
  
 -static int get_parent(const char *name, int len,
 -                    struct object_id *result, int idx)
 +static enum get_oid_result get_parent(const char *name, int len,
 +                                    struct object_id *result, int idx)
  {
        struct object_id oid;
 -      int ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);
 +      enum get_oid_result ret = get_oid_1(name, len, &oid,
 +                                          GET_OID_COMMITTISH);
        struct commit *commit;
        struct commit_list *p;
  
                return ret;
        commit = lookup_commit_reference(the_repository, &oid);
        if (parse_commit(commit))
 -              return -1;
 +              return MISSING_OBJECT;
        if (!idx) {
                oidcpy(result, &commit->object.oid);
 -              return 0;
 +              return FOUND;
        }
        p = commit->parents;
        while (p) {
                if (!--idx) {
                        oidcpy(result, &p->item->object.oid);
 -                      return 0;
 +                      return FOUND;
                }
                p = p->next;
        }
 -      return -1;
 +      return MISSING_OBJECT;
  }
  
 -static int get_nth_ancestor(const char *name, int len,
 -                          struct object_id *result, int generation)
 +static enum get_oid_result get_nth_ancestor(const char *name, int len,
 +                                          struct object_id *result,
 +                                          int generation)
  {
        struct object_id oid;
        struct commit *commit;
                return ret;
        commit = lookup_commit_reference(the_repository, &oid);
        if (!commit)
 -              return -1;
 +              return MISSING_OBJECT;
  
        while (generation--) {
                if (parse_commit(commit) || !commit->parents)
 -                      return -1;
 +                      return MISSING_OBJECT;
                commit = commit->parents->item;
        }
        oidcpy(result, &commit->object.oid);
 -      return 0;
 +      return FOUND;
  }
  
  struct object *peel_to_type(const char *name, int namelen,
@@@ -1077,9 -1077,7 +1077,9 @@@ static int get_describe_name(const cha
        return -1;
  }
  
 -static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags)
 +static enum get_oid_result get_oid_1(const char *name, int len,
 +                                   struct object_id *oid,
 +                                   unsigned lookup_flags)
  {
        int ret, has_suffix;
        const char *cp;
  
        ret = peel_onion(name, len, oid, lookup_flags);
        if (!ret)
 -              return 0;
 +              return FOUND;
  
        ret = get_oid_basic(name, len, oid, lookup_flags);
        if (!ret)
 -              return 0;
 +              return FOUND;
  
        /* It could be describe output that is "SOMETHING-gXXXX" */
        ret = get_describe_name(name, len, oid);
        if (!ret)
 -              return 0;
 +              return FOUND;
  
        return get_short_oid(name, len, oid, lookup_flags);
  }
@@@ -1515,7 -1513,7 +1515,7 @@@ int strbuf_check_branch_ref(struct strb
  int get_oid(const char *name, struct object_id *oid)
  {
        struct object_context unused;
-       return get_oid_with_context(name, 0, oid, &unused);
+       return get_oid_with_context(the_repository, name, 0, oid, &unused);
  }
  
  
  int get_oid_committish(const char *name, struct object_id *oid)
  {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_COMMITTISH,
+       return get_oid_with_context(the_repository,
+                                   name, GET_OID_COMMITTISH,
                                    oid, &unused);
  }
  
  int get_oid_treeish(const char *name, struct object_id *oid)
  {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_TREEISH,
+       return get_oid_with_context(the_repository,
+                                   name, GET_OID_TREEISH,
                                    oid, &unused);
  }
  
  int get_oid_commit(const char *name, struct object_id *oid)
  {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_COMMIT,
+       return get_oid_with_context(the_repository,
+                                   name, GET_OID_COMMIT,
                                    oid, &unused);
  }
  
  int get_oid_tree(const char *name, struct object_id *oid)
  {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_TREE,
+       return get_oid_with_context(the_repository,
+                                   name, GET_OID_TREE,
                                    oid, &unused);
  }
  
  int get_oid_blob(const char *name, struct object_id *oid)
  {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_BLOB,
+       return get_oid_with_context(the_repository,
+                                   name, GET_OID_BLOB,
                                    oid, &unused);
  }
  
@@@ -1599,7 -1602,8 +1604,8 @@@ static void diagnose_invalid_oid_path(c
  }
  
  /* Must be called only when :stage:filename doesn't exist. */
- static void diagnose_invalid_index_path(int stage,
+ static void diagnose_invalid_index_path(struct index_state *istate,
+                                       int stage,
                                        const char *prefix,
                                        const char *filename)
  {
                prefix = "";
  
        /* Wrong stage number? */
-       pos = cache_name_pos(filename, namelen);
+       pos = index_name_pos(istate, filename, namelen);
        if (pos < 0)
                pos = -pos - 1;
-       if (pos < active_nr) {
-               ce = active_cache[pos];
+       if (pos < istate->cache_nr) {
+               ce = istate->cache[pos];
                if (ce_namelen(ce) == namelen &&
                    !memcmp(ce->name, filename, namelen))
                        die("Path '%s' is in the index, but not at stage %d.\n"
        /* Confusion between relative and absolute filenames? */
        strbuf_addstr(&fullname, prefix);
        strbuf_addstr(&fullname, filename);
-       pos = cache_name_pos(fullname.buf, fullname.len);
+       pos = index_name_pos(istate, fullname.buf, fullname.len);
        if (pos < 0)
                pos = -pos - 1;
-       if (pos < active_nr) {
-               ce = active_cache[pos];
+       if (pos < istate->cache_nr) {
+               ce = istate->cache[pos];
                if (ce_namelen(ce) == fullname.len &&
                    !memcmp(ce->name, fullname.buf, fullname.len))
                        die("Path '%s' is in the index, but not '%s'.\n"
@@@ -1666,11 -1670,12 +1672,12 @@@ static char *resolve_relative_path(cons
                           rel);
  }
  
- static enum get_oid_result get_oid_with_context_1(const char *name,
-                                                 unsigned flags,
-                                                 const char *prefix,
-                                                 struct object_id *oid,
-                                                 struct object_context *oc)
 -static int get_oid_with_context_1(struct repository *repo,
++static enum get_oid_result get_oid_with_context_1(struct repository *repo,
+                                 const char *name,
+                                 unsigned flags,
+                                 const char *prefix,
+                                 struct object_id *oid,
+                                 struct object_context *oc)
  {
        int ret, bracket_depth;
        int namelen = strlen(name);
                if (flags & GET_OID_RECORD_PATH)
                        oc->path = xstrdup(cp);
  
-               if (!active_cache)
-                       read_cache();
-               pos = cache_name_pos(cp, namelen);
+               if (!repo->index->cache)
+                       repo_read_index(the_repository);
+               pos = index_name_pos(repo->index, cp, namelen);
                if (pos < 0)
                        pos = -pos - 1;
-               while (pos < active_nr) {
-                       ce = active_cache[pos];
+               while (pos < repo->index->cache_nr) {
+                       ce = repo->index->cache[pos];
                        if (ce_namelen(ce) != namelen ||
                            memcmp(ce->name, cp, namelen))
                                break;
                        pos++;
                }
                if (only_to_die && name[1] && name[1] != '/')
-                       diagnose_invalid_index_path(stage, prefix, cp);
+                       diagnose_invalid_index_path(repo->index, stage, prefix, cp);
                free(new_path);
                return -1;
        }
@@@ -1809,12 -1814,15 +1816,15 @@@ void maybe_die_on_misspelt_object_name(
  {
        struct object_context oc;
        struct object_id oid;
-       get_oid_with_context_1(name, GET_OID_ONLY_TO_DIE, prefix, &oid, &oc);
+       get_oid_with_context_1(the_repository, name, GET_OID_ONLY_TO_DIE,
+                              prefix, &oid, &oc);
  }
  
- int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc)
+ int get_oid_with_context(struct repository *repo, const char *str,
+                        unsigned flags, struct object_id *oid,
+                        struct object_context *oc)
  {
        if (flags & GET_OID_FOLLOW_SYMLINKS && flags & GET_OID_ONLY_TO_DIE)
                BUG("incompatible flags for get_sha1_with_context");
-       return get_oid_with_context_1(str, flags, NULL, oid, oc);
+       return get_oid_with_context_1(repo, str, flags, NULL, oid, oc);
  }
diff --combined submodule.c
index a5f2694a5f651a51b3012ce4a454e63698a7e0e7,4208a502603ff8f763dd959610500eb718a76383..934ecfa2943bcb5ee87e7ac431b5332a5f3adcde
@@@ -1,4 -1,3 +1,3 @@@
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  
  #include "cache.h"
  #include "repository.h"
@@@ -25,6 -24,7 +24,6 @@@
  #include "commit-reach.h"
  
  static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
 -static struct string_list changed_submodule_names = STRING_LIST_INIT_DUP;
  static int initialized_fetch_ref_tips;
  static struct oid_array ref_tips_before_fetch;
  static struct oid_array ref_tips_after_fetch;
@@@ -456,7 -456,7 +455,7 @@@ static int prepare_submodule_summary(st
        return prepare_revision_walk(rev);
  }
  
 -static void print_submodule_summary(struct rev_info *rev, struct diff_options *o)
 +static void print_submodule_summary(struct repository *r, struct rev_info *rev, struct diff_options *o)
  {
        static const char format[] = "  %m %s";
        struct strbuf sb = STRBUF_INIT;
                ctx.date_mode = rev->date_mode;
                ctx.output_encoding = get_log_output_encoding();
                strbuf_setlen(&sb, 0);
 -              format_commit_message(commit, format, &sb, &ctx);
 +              repo_format_commit_message(r, commit, format, &sb,
 +                                    &ctx);
                strbuf_addch(&sb, '\n');
                if (commit->object.flags & SYMMETRIC_LEFT)
                        diff_emit_submodule_del(o, sb.buf);
@@@ -495,52 -494,14 +494,52 @@@ void prepare_submodule_repo_env(struct 
                         DEFAULT_GIT_DIR_ENVIRONMENT);
  }
  
 -/* Helper function to display the submodule header line prior to the full
 - * summary output. If it can locate the submodule objects directory it will
 - * attempt to lookup both the left and right commits and put them into the
 - * left and right pointers.
 +static void prepare_submodule_repo_env_in_gitdir(struct argv_array *out)
 +{
 +      prepare_submodule_repo_env_no_git_dir(out);
 +      argv_array_pushf(out, "%s=.", GIT_DIR_ENVIRONMENT);
 +}
 +
 +/*
 + * Initialize a repository struct for a submodule based on the provided 'path'.
 + *
 + * Unlike repo_submodule_init, this tolerates submodules not present
 + * in .gitmodules. This function exists only to preserve historical behavior,
 + *
 + * Returns the repository struct on success,
 + * NULL when the submodule is not present.
   */
 -static void show_submodule_header(struct diff_options *o, const char *path,
 +static struct repository *open_submodule(const char *path)
 +{
 +      struct strbuf sb = STRBUF_INIT;
 +      struct repository *out = xmalloc(sizeof(*out));
 +
 +      if (submodule_to_gitdir(&sb, path) || repo_init(out, sb.buf, NULL)) {
 +              strbuf_release(&sb);
 +              free(out);
 +              return NULL;
 +      }
 +
 +      /* Mark it as a submodule */
 +      out->submodule_prefix = xstrdup(path);
 +
 +      strbuf_release(&sb);
 +      return out;
 +}
 +
 +/*
 + * Helper function to display the submodule header line prior to the full
 + * summary output.
 + *
 + * If it can locate the submodule git directory it will create a repository
 + * handle for the submodule and lookup both the left and right commits and
 + * put them into the left and right pointers.
 + */
 +static void show_submodule_header(struct diff_options *o,
 +              const char *path,
                struct object_id *one, struct object_id *two,
                unsigned dirty_submodule,
 +              struct repository *sub,
                struct commit **left, struct commit **right,
                struct commit_list **merge_bases)
  {
        else if (is_null_oid(two))
                message = "(submodule deleted)";
  
 -      if (add_submodule_odb(path)) {
 +      if (!sub) {
                if (!message)
                        message = "(commits not present)";
                goto output_header;
         * Attempt to lookup the commit references, and determine if this is
         * a fast forward or fast backwards update.
         */
 -      *left = lookup_commit_reference(the_repository, one);
 -      *right = lookup_commit_reference(the_repository, two);
 +      *left = lookup_commit_reference(sub, one);
 +      *right = lookup_commit_reference(sub, two);
  
        /*
         * Warn about missing commits in the submodule project, but only if
             (!is_null_oid(two) && !*right))
                message = "(commits not present)";
  
 -      *merge_bases = get_merge_bases(*left, *right);
 +      *merge_bases = repo_get_merge_bases(sub, *left, *right);
        if (*merge_bases) {
                if ((*merge_bases)->item == *left)
                        fast_forward = 1;
@@@ -614,18 -575,16 +613,18 @@@ void show_submodule_summary(struct diff
        struct rev_info rev;
        struct commit *left = NULL, *right = NULL;
        struct commit_list *merge_bases = NULL;
 +      struct repository *sub;
  
 +      sub = open_submodule(path);
        show_submodule_header(o, path, one, two, dirty_submodule,
 -                            &left, &right, &merge_bases);
 +                            sub, &left, &right, &merge_bases);
  
        /*
         * If we don't have both a left and a right pointer, there is no
         * reason to try and display a summary. The header line should contain
         * all the information the user needs.
         */
 -      if (!left || !right)
 +      if (!left || !right || !sub)
                goto out;
  
        /* Treat revision walker failure the same as missing commits */
                goto out;
        }
  
 -      print_submodule_summary(&rev, o);
 +      print_submodule_summary(sub, &rev, o);
  
  out:
        if (merge_bases)
                free_commit_list(merge_bases);
        clear_commit_marks(left, ~0);
        clear_commit_marks(right, ~0);
 +      if (sub) {
 +              repo_clear(sub);
 +              free(sub);
 +      }
  }
  
  void show_submodule_inline_diff(struct diff_options *o, const char *path,
        struct commit_list *merge_bases = NULL;
        struct child_process cp = CHILD_PROCESS_INIT;
        struct strbuf sb = STRBUF_INIT;
 +      struct repository *sub;
  
 +      sub = open_submodule(path);
        show_submodule_header(o, path, one, two, dirty_submodule,
 -                            &left, &right, &merge_bases);
 +                            sub, &left, &right, &merge_bases);
  
        /* We need a valid left and right commit to display a difference */
        if (!(left || is_null_oid(one)) ||
@@@ -721,10 -674,6 +720,10 @@@ done
                clear_commit_marks(left, ~0);
        if (right)
                clear_commit_marks(right, ~0);
 +      if (sub) {
 +              repo_clear(sub);
 +              free(sub);
 +      }
  }
  
  int should_update_submodules(void)
@@@ -1049,6 -998,9 +1048,6 @@@ static int push_submodule(const char *p
                          const struct string_list *push_options,
                          int dry_run)
  {
 -      if (add_submodule_odb(path))
 -              return 1;
 -
        if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
                struct child_process cp = CHILD_PROCESS_INIT;
                argv_array_push(&cp.args, "push");
@@@ -1183,11 -1135,11 +1182,11 @@@ void check_for_new_submodule_commits(st
        oid_array_append(&ref_tips_after_fetch, oid);
  }
  
 -static void calculate_changed_submodule_paths(struct repository *r)
 +static void calculate_changed_submodule_paths(struct repository *r,
 +              struct string_list *changed_submodule_names)
  {
        struct argv_array argv = ARGV_ARRAY_INIT;
 -      struct string_list changed_submodules = STRING_LIST_INIT_DUP;
 -      const struct string_list_item *name;
 +      struct string_list_item *name;
  
        /* No need to check if there are no submodules configured */
        if (!submodule_from_path(r, NULL, NULL))
         * Collect all submodules (whether checked out or not) for which new
         * commits have been recorded upstream in "changed_submodule_names".
         */
 -      collect_changed_submodules(r, &changed_submodules, &argv);
 +      collect_changed_submodules(r, changed_submodule_names, &argv);
  
 -      for_each_string_list_item(name, &changed_submodules) {
 +      for_each_string_list_item(name, changed_submodule_names) {
                struct oid_array *commits = name->util;
                const struct submodule *submodule;
                const char *path = NULL;
                if (!path)
                        continue;
  
 -              if (!submodule_has_commits(r, path, commits))
 -                      string_list_append(&changed_submodule_names, name->string);
 +              if (submodule_has_commits(r, path, commits)) {
 +                      oid_array_clear(commits);
 +                      *name->string = '\0';
 +              }
        }
  
 -      free_submodules_oids(&changed_submodules);
 +      string_list_remove_empty_items(changed_submodule_names, 1);
 +
        argv_array_clear(&argv);
        oid_array_clear(&ref_tips_before_fetch);
        oid_array_clear(&ref_tips_after_fetch);
@@@ -1271,16 -1220,8 +1270,16 @@@ struct submodule_parallel_fetch 
        int default_option;
        int quiet;
        int result;
 +
 +      struct string_list changed_submodule_names;
 +
 +      /* Pending fetches by OIDs */
 +      struct fetch_task **oid_fetch_tasks;
 +      int oid_fetch_tasks_nr, oid_fetch_tasks_alloc;
  };
 -#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0, 0}
 +#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0, 0, \
 +                STRING_LIST_INIT_DUP, \
 +                NULL, 0, 0}
  
  static int get_fetch_recurse_config(const struct submodule *submodule,
                                    struct submodule_parallel_fetch *spf)
        return spf->default_option;
  }
  
 +/*
 + * Fetch in progress (if callback data) or
 + * pending (if in oid_fetch_tasks in struct submodule_parallel_fetch)
 + */
 +struct fetch_task {
 +      struct repository *repo;
 +      const struct submodule *sub;
 +      unsigned free_sub : 1; /* Do we need to free the submodule? */
 +
 +      struct oid_array *commits; /* Ensure these commits are fetched */
 +};
 +
 +/**
 + * When a submodule is not defined in .gitmodules, we cannot access it
 + * via the regular submodule-config. Create a fake submodule, which we can
 + * work on.
 + */
 +static const struct submodule *get_non_gitmodules_submodule(const char *path)
 +{
 +      struct submodule *ret = NULL;
 +      const char *name = default_name_or_path(path);
 +
 +      if (!name)
 +              return NULL;
 +
 +      ret = xmalloc(sizeof(*ret));
 +      memset(ret, 0, sizeof(*ret));
 +      ret->path = name;
 +      ret->name = name;
 +
 +      return (const struct submodule *) ret;
 +}
 +
 +static struct fetch_task *fetch_task_create(struct repository *r,
 +                                          const char *path)
 +{
 +      struct fetch_task *task = xmalloc(sizeof(*task));
 +      memset(task, 0, sizeof(*task));
 +
 +      task->sub = submodule_from_path(r, &null_oid, path);
 +      if (!task->sub) {
 +              /*
 +               * No entry in .gitmodules? Technically not a submodule,
 +               * but historically we supported repositories that happen to be
 +               * in-place where a gitlink is. Keep supporting them.
 +               */
 +              task->sub = get_non_gitmodules_submodule(path);
 +              if (!task->sub) {
 +                      free(task);
 +                      return NULL;
 +              }
 +
 +              task->free_sub = 1;
 +      }
 +
 +      return task;
 +}
 +
 +static void fetch_task_release(struct fetch_task *p)
 +{
 +      if (p->free_sub)
 +              free((void*)p->sub);
 +      p->free_sub = 0;
 +      p->sub = NULL;
 +
 +      if (p->repo)
 +              repo_clear(p->repo);
 +      FREE_AND_NULL(p->repo);
 +}
 +
 +static struct repository *get_submodule_repo_for(struct repository *r,
 +                                               const struct submodule *sub)
 +{
 +      struct repository *ret = xmalloc(sizeof(*ret));
 +
 +      if (repo_submodule_init(ret, r, sub)) {
 +              /*
 +               * No entry in .gitmodules? Technically not a submodule,
 +               * but historically we supported repositories that happen to be
 +               * in-place where a gitlink is. Keep supporting them.
 +               */
 +              struct strbuf gitdir = STRBUF_INIT;
 +              strbuf_repo_worktree_path(&gitdir, r, "%s/.git", sub->path);
 +              if (repo_init(ret, gitdir.buf, NULL)) {
 +                      strbuf_release(&gitdir);
 +                      free(ret);
 +                      return NULL;
 +              }
 +              strbuf_release(&gitdir);
 +      }
 +
 +      return ret;
 +}
 +
  static int get_next_submodule(struct child_process *cp,
                              struct strbuf *err, void *data, void **task_cb)
  {
 -      int ret = 0;
        struct submodule_parallel_fetch *spf = data;
  
        for (; spf->count < spf->r->index->cache_nr; spf->count++) {
 -              struct strbuf submodule_path = STRBUF_INIT;
 -              struct strbuf submodule_git_dir = STRBUF_INIT;
 -              struct strbuf submodule_prefix = STRBUF_INIT;
                const struct cache_entry *ce = spf->r->index->cache[spf->count];
 -              const char *git_dir, *default_argv;
 -              const struct submodule *submodule;
 -              struct submodule default_submodule = SUBMODULE_INIT;
 +              const char *default_argv;
 +              struct fetch_task *task;
  
                if (!S_ISGITLINK(ce->ce_mode))
                        continue;
  
 -              submodule = submodule_from_path(spf->r, &null_oid, ce->name);
 -              if (!submodule) {
 -                      const char *name = default_name_or_path(ce->name);
 -                      if (name) {
 -                              default_submodule.path = default_submodule.name = name;
 -                              submodule = &default_submodule;
 -                      }
 -              }
 +              task = fetch_task_create(spf->r, ce->name);
 +              if (!task)
 +                      continue;
  
 -              switch (get_fetch_recurse_config(submodule, spf))
 +              switch (get_fetch_recurse_config(task->sub, spf))
                {
                default:
                case RECURSE_SUBMODULES_DEFAULT:
                case RECURSE_SUBMODULES_ON_DEMAND:
 -                      if (!submodule || !unsorted_string_list_lookup(&changed_submodule_names,
 -                                                       submodule->name))
 +                      if (!task->sub ||
 +                          !string_list_lookup(
 +                                      &spf->changed_submodule_names,
 +                                      task->sub->name))
                                continue;
                        default_argv = "on-demand";
                        break;
                        continue;
                }
  
 -              strbuf_repo_worktree_path(&submodule_path, spf->r, "%s", ce->name);
 -              strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf);
 -              strbuf_addf(&submodule_prefix, "%s%s/", spf->prefix, ce->name);
 -              git_dir = read_gitfile(submodule_git_dir.buf);
 -              if (!git_dir)
 -                      git_dir = submodule_git_dir.buf;
 -              if (is_directory(git_dir)) {
 +              task->repo = get_submodule_repo_for(spf->r, task->sub);
 +              if (task->repo) {
 +                      struct strbuf submodule_prefix = STRBUF_INIT;
                        child_process_init(cp);
 -                      cp->dir = strbuf_detach(&submodule_path, NULL);
 -                      prepare_submodule_repo_env(&cp->env_array);
 +                      cp->dir = task->repo->gitdir;
 +                      prepare_submodule_repo_env_in_gitdir(&cp->env_array);
                        cp->git_cmd = 1;
                        if (!spf->quiet)
                                strbuf_addf(err, "Fetching submodule %s%s\n",
                        argv_array_pushv(&cp->args, spf->args.argv);
                        argv_array_push(&cp->args, default_argv);
                        argv_array_push(&cp->args, "--submodule-prefix");
 +
 +                      strbuf_addf(&submodule_prefix, "%s%s/",
 +                                                     spf->prefix,
 +                                                     task->sub->path);
                        argv_array_push(&cp->args, submodule_prefix.buf);
 -                      ret = 1;
 -              }
 -              strbuf_release(&submodule_path);
 -              strbuf_release(&submodule_git_dir);
 -              strbuf_release(&submodule_prefix);
 -              if (ret) {
 +
                        spf->count++;
 +                      *task_cb = task;
 +
 +                      strbuf_release(&submodule_prefix);
                        return 1;
 +              } else {
 +
 +                      fetch_task_release(task);
 +                      free(task);
 +
 +                      /*
 +                       * An empty directory is normal,
 +                       * the submodule is not initialized
 +                       */
 +                      if (S_ISGITLINK(ce->ce_mode) &&
 +                          !is_empty_dir(ce->name)) {
 +                              spf->result = 1;
 +                              strbuf_addf(err,
 +                                          _("Could not access submodule '%s'"),
 +                                          ce->name);
 +                      }
                }
        }
 +
 +      if (spf->oid_fetch_tasks_nr) {
 +              struct fetch_task *task =
 +                      spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr - 1];
 +              struct strbuf submodule_prefix = STRBUF_INIT;
 +              spf->oid_fetch_tasks_nr--;
 +
 +              strbuf_addf(&submodule_prefix, "%s%s/",
 +                          spf->prefix, task->sub->path);
 +
 +              child_process_init(cp);
 +              prepare_submodule_repo_env_in_gitdir(&cp->env_array);
 +              cp->git_cmd = 1;
 +              cp->dir = task->repo->gitdir;
 +
 +              argv_array_init(&cp->args);
 +              argv_array_pushv(&cp->args, spf->args.argv);
 +              argv_array_push(&cp->args, "on-demand");
 +              argv_array_push(&cp->args, "--submodule-prefix");
 +              argv_array_push(&cp->args, submodule_prefix.buf);
 +
 +              /* NEEDSWORK: have get_default_remote from submodule--helper */
 +              argv_array_push(&cp->args, "origin");
 +              oid_array_for_each_unique(task->commits,
 +                                        append_oid_to_argv, &cp->args);
 +
 +              *task_cb = task;
 +              strbuf_release(&submodule_prefix);
 +              return 1;
 +      }
 +
        return 0;
  }
  
@@@ -1518,66 -1328,20 +1517,66 @@@ static int fetch_start_failure(struct s
                               void *cb, void *task_cb)
  {
        struct submodule_parallel_fetch *spf = cb;
 +      struct fetch_task *task = task_cb;
  
        spf->result = 1;
  
 +      fetch_task_release(task);
        return 0;
  }
  
 +static int commit_missing_in_sub(const struct object_id *oid, void *data)
 +{
 +      struct repository *subrepo = data;
 +
 +      enum object_type type = oid_object_info(subrepo, oid, NULL);
 +
 +      return type != OBJ_COMMIT;
 +}
 +
  static int fetch_finish(int retvalue, struct strbuf *err,
                        void *cb, void *task_cb)
  {
        struct submodule_parallel_fetch *spf = cb;
 +      struct fetch_task *task = task_cb;
 +
 +      struct string_list_item *it;
 +      struct oid_array *commits;
  
        if (retvalue)
                spf->result = 1;
  
 +      if (!task || !task->sub)
 +              BUG("callback cookie bogus");
 +
 +      /* Is this the second time we process this submodule? */
 +      if (task->commits)
 +              goto out;
 +
 +      it = string_list_lookup(&spf->changed_submodule_names, task->sub->name);
 +      if (!it)
 +              /* Could be an unchanged submodule, not contained in the list */
 +              goto out;
 +
 +      commits = it->util;
 +      oid_array_filter(commits,
 +                       commit_missing_in_sub,
 +                       task->repo);
 +
 +      /* Are there commits we want, but do not exist? */
 +      if (commits->nr) {
 +              task->commits = commits;
 +              ALLOC_GROW(spf->oid_fetch_tasks,
 +                         spf->oid_fetch_tasks_nr + 1,
 +                         spf->oid_fetch_tasks_alloc);
 +              spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr] = task;
 +              spf->oid_fetch_tasks_nr++;
 +              return 0;
 +      }
 +
 +out:
 +      fetch_task_release(task);
 +
        return 0;
  }
  
@@@ -1608,8 -1372,7 +1607,8 @@@ int fetch_populated_submodules(struct r
        argv_array_push(&spf.args, "--recurse-submodules-default");
        /* default value, "--submodule-prefix" and its value are added later */
  
 -      calculate_changed_submodule_paths(r);
 +      calculate_changed_submodule_paths(r, &spf.changed_submodule_names);
 +      string_list_sort(&spf.changed_submodule_names);
        run_processes_parallel(max_parallel_jobs,
                               get_next_submodule,
                               fetch_start_failure,
  
        argv_array_clear(&spf.args);
  out:
 -      string_list_clear(&changed_submodule_names, 1);
 +      free_submodules_oids(&spf.changed_submodule_names);
        return spf.result;
  }
  
        return ret;
  }
  
 +void submodule_unset_core_worktree(const struct submodule *sub)
 +{
 +      char *config_path = xstrfmt("%s/modules/%s/config",
 +                                  get_git_common_dir(), sub->name);
 +
 +      if (git_config_set_in_file_gently(config_path, "core.worktree", NULL))
 +              warning(_("Could not unset core.worktree setting in submodule '%s'"),
 +                        sub->path);
 +
 +      free(config_path);
 +}
 +
  static const char *get_super_prefix_or_empty(void)
  {
        const char *s = get_super_prefix();
@@@ -1974,8 -1725,6 +1973,8 @@@ int submodule_move_head(const char *pat
  
                        if (is_empty_dir(path))
                                rmdir_or_warn(path);
 +
 +                      submodule_unset_core_worktree(sub);
                }
        }
  out:
diff --combined t/helper/test-tool.h
index ca5c88edb2ac8ae99090ec21e6b3d636bc03e96c,f4fb3b986156f5b786120fd4eaea2c0c9093f381..a396c10947e86bb88e47a8e4df4fef2de64024e8
@@@ -1,6 -1,7 +1,7 @@@
  #ifndef TEST_TOOL_H
  #define TEST_TOOL_H
  
+ #define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "git-compat-util.h"
  
  int cmd__chmtime(int argc, const char **argv);
@@@ -16,7 -17,6 +17,7 @@@ int cmd__dump_untracked_cache(int argc
  int cmd__example_decorate(int argc, const char **argv);
  int cmd__genrandom(int argc, const char **argv);
  int cmd__hashmap(int argc, const char **argv);
 +int cmd__hash_speed(int argc, const char **argv);
  int cmd__index_version(int argc, const char **argv);
  int cmd__json_writer(int argc, const char **argv);
  int cmd__lazy_init_name_hash(int argc, const char **argv);
@@@ -39,7 -39,6 +40,7 @@@ int cmd__run_command(int argc, const ch
  int cmd__scrap_cache_tree(int argc, const char **argv);
  int cmd__sha1(int argc, const char **argv);
  int cmd__sha1_array(int argc, const char **argv);
 +int cmd__sha256(int argc, const char **argv);
  int cmd__sigchain(int argc, const char **argv);
  int cmd__strcmp_offset(int argc, const char **argv);
  int cmd__string_list(int argc, const char **argv);
@@@ -53,6 -52,4 +54,6 @@@ int cmd__windows_named_pipe(int argc, c
  #endif
  int cmd__write_cache(int argc, const char **argv);
  
 +int cmd_hash_impl(int ac, const char **av, int algo);
 +
  #endif
diff --combined tree.c
index 9f0457c05acf1e4d7bd9f215dd3c710b3cb2df4f,181a3778f37d2bbbc6d69a37d93936988ae67cc2..f416afc57d784f8f63ba66ec8c7424ef1e4fcaa1
--- 1/tree.c
--- 2/tree.c
+++ b/tree.c
@@@ -1,4 -1,3 +1,3 @@@
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "cache-tree.h"
  #include "tree.h"
@@@ -60,8 -59,7 +59,8 @@@ static int read_one_entry_quick(const s
                                  ADD_CACHE_JUST_APPEND);
  }
  
 -static int read_tree_1(struct tree *tree, struct strbuf *base,
 +static int read_tree_1(struct repository *r,
 +                     struct tree *tree, struct strbuf *base,
                       int stage, const struct pathspec *pathspec,
                       read_tree_fn_t fn, void *context)
  {
  
        while (tree_entry(&desc, &entry)) {
                if (retval != all_entries_interesting) {
 -                      retval = tree_entry_interesting(&entry, base, 0, pathspec);
 +                      retval = tree_entry_interesting(r->index, &entry,
 +                                                      base, 0, pathspec);
                        if (retval == all_entries_not_interesting)
                                break;
                        if (retval == entry_not_interesting)
                                continue;
                }
  
 -              switch (fn(entry.oid, base,
 +              switch (fn(&entry.oid, base,
                           entry.path, entry.mode, stage, context)) {
                case 0:
                        continue;
                }
  
                if (S_ISDIR(entry.mode))
 -                      oidcpy(&oid, entry.oid);
 +                      oidcpy(&oid, &entry.oid);
                else if (S_ISGITLINK(entry.mode)) {
                        struct commit *commit;
  
 -                      commit = lookup_commit(the_repository, entry.oid);
 +                      commit = lookup_commit(r, &entry.oid);
                        if (!commit)
                                die("Commit %s in submodule path %s%s not found",
 -                                  oid_to_hex(entry.oid),
 +                                  oid_to_hex(&entry.oid),
                                    base->buf, entry.path);
  
                        if (parse_commit(commit))
                                die("Invalid commit %s in submodule path %s%s",
 -                                  oid_to_hex(entry.oid),
 +                                  oid_to_hex(&entry.oid),
                                    base->buf, entry.path);
  
                        oidcpy(&oid, get_commit_tree_oid(commit));
                len = tree_entry_len(&entry);
                strbuf_add(base, entry.path, len);
                strbuf_addch(base, '/');
 -              retval = read_tree_1(lookup_tree(the_repository, &oid),
 +              retval = read_tree_1(r, lookup_tree(r, &oid),
                                     base, stage, pathspec,
                                     fn, context);
                strbuf_setlen(base, oldlen);
        return 0;
  }
  
 -int read_tree_recursive(struct tree *tree,
 +int read_tree_recursive(struct repository *r,
 +                      struct tree *tree,
                        const char *base, int baselen,
                        int stage, const struct pathspec *pathspec,
                        read_tree_fn_t fn, void *context)
        int ret;
  
        strbuf_add(&sb, base, baselen);
 -      ret = read_tree_1(tree, &sb, stage, pathspec, fn, context);
 +      ret = read_tree_1(r, tree, &sb, stage, pathspec, fn, context);
        strbuf_release(&sb);
        return ret;
  }
@@@ -155,8 -151,8 +154,8 @@@ static int cmp_cache_name_compare(cons
                                  ce2->name, ce2->ce_namelen, ce_stage(ce2));
  }
  
 -int read_tree(struct tree *tree, int stage, struct pathspec *match,
 -            struct index_state *istate)
 +int read_tree(struct repository *r, struct tree *tree, int stage,
 +            struct pathspec *match, struct index_state *istate)
  {
        read_tree_fn_t fn = NULL;
        int i, err;
  
        if (!fn)
                fn = read_one_entry_quick;
 -      err = read_tree_recursive(tree, "", 0, stage, match, fn, istate);
 +      err = read_tree_recursive(r, tree, "", 0, stage, match, fn, istate);
        if (fn == read_one_entry || err)
                return err;
  
diff --combined unpack-trees.c
index 01c2175f7c12f2bbfe6d24c73d32c60131fdc723,40f554814d30c8f2cbd91f1d34c618a3d567ac17..3563daae1aa6bceb4f7a4715ee574e1359622239
@@@ -1,4 -1,3 +1,3 @@@
- #define NO_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "argv-array.h"
  #include "repository.h"
@@@ -294,7 -293,7 +293,7 @@@ static void load_gitmodules_file(struc
                        repo_read_gitmodules(the_repository);
                } else if (state && (ce->ce_flags & CE_UPDATE)) {
                        submodule_free(the_repository);
 -                      checkout_entry(ce, state, NULL);
 +                      checkout_entry(ce, state, NULL, NULL);
                        repo_read_gitmodules(the_repository);
                }
        }
@@@ -450,12 -449,12 +449,12 @@@ static int check_updates(struct unpack_
                        display_progress(progress, ++cnt);
                        ce->ce_flags &= ~CE_UPDATE;
                        if (o->update && !o->dry_run) {
 -                              errs |= checkout_entry(ce, &state, NULL);
 +                              errs |= checkout_entry(ce, &state, NULL, NULL);
                        }
                }
        }
        stop_progress(&progress);
 -      errs |= finish_delayed_checkout(&state);
 +      errs |= finish_delayed_checkout(&state, NULL);
        if (o->update)
                git_attr_set_direction(GIT_ATTR_CHECKIN);
  
@@@ -679,7 -678,7 +678,7 @@@ static int switch_cache_bottom(struct t
  
  static inline int are_same_oid(struct name_entry *name_j, struct name_entry *name_k)
  {
 -      return name_j->oid && name_k->oid && oideq(name_j->oid, name_k->oid);
 +      return !is_null_oid(&name_j->oid) && !is_null_oid(&name_k->oid) && oideq(&name_j->oid, &name_k->oid);
  }
  
  static int all_trees_same_as_cache_tree(int n, unsigned long dirmask,
@@@ -794,7 -793,6 +793,7 @@@ static int traverse_trees_recursive(in
                                    struct name_entry *names,
                                    struct traverse_info *info)
  {
 +      struct unpack_trees_options *o = info->data;
        int i, ret, bottom;
        int nr_buf = 0;
        struct tree_desc t[MAX_UNPACK_TREES];
  
        nr_entries = all_trees_same_as_cache_tree(n, dirmask, names, info);
        if (nr_entries > 0) {
 -              struct unpack_trees_options *o = info->data;
                int pos = index_pos_by_traverse_info(names, info);
  
                if (!o->merge || df_conflicts)
                else {
                        const struct object_id *oid = NULL;
                        if (dirmask & 1)
 -                              oid = names[i].oid;
 +                              oid = &names[i].oid;
                        buf[nr_buf++] = fill_tree_descriptor(t + i, oid);
                }
        }
  
        bottom = switch_cache_bottom(&newinfo);
 -      ret = traverse_trees(n, t, &newinfo);
 +      ret = traverse_trees(o->src_index, n, t, &newinfo);
        restore_cache_bottom(&newinfo, bottom);
  
        for (i = 0; i < nr_buf; i++)
@@@ -981,7 -980,7 +980,7 @@@ static struct cache_entry *create_ce_en
        ce->ce_mode = create_ce_mode(n->mode);
        ce->ce_flags = create_ce_flags(stage);
        ce->ce_namelen = len;
 -      oidcpy(&ce->oid, n->oid);
 +      oidcpy(&ce->oid, &n->oid);
        make_traverse_path(ce->name, info, n);
  
        return ce;
@@@ -1550,7 -1549,7 +1549,7 @@@ int unpack_trees(unsigned len, struct t
                }
  
                trace_performance_enter();
 -              ret = traverse_trees(len, t, &info);
 +              ret = traverse_trees(o->src_index, len, t, &info);
                trace_performance_leave("traverse_trees");
                if (ret < 0)
                        goto return_failed;