Merge branch 'sb/more-repo-in-api' into md/list-objects-filter-by-depth
authorJunio C Hamano <gitster@pobox.com>
Fri, 28 Dec 2018 18:40:58 +0000 (10:40 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 28 Dec 2018 18:40:58 +0000 (10:40 -0800)
14 files changed:
1  2 
builtin/fsck.c
builtin/log.c
builtin/rev-list.c
cache.h
commit-reach.c
commit-reach.h
commit.c
commit.h
packfile.c
packfile.h
pretty.c
sha1-file.c
streaming.c
submodule.c
diff --combined builtin/fsck.c
index 3c3e0f06e78009ee3ee2d54333dfc4740b8792a9,c476ac69838650ccdb1b376f71bfd189433e2bd1..967341e1d3ad9b4c7caba8ba36bc9f2e485c6b02
@@@ -19,7 -19,6 +19,7 @@@
  #include "packfile.h"
  #include "object-store.h"
  #include "run-command.h"
 +#include "worktree.h"
  
  #define REACHABLE 0x0001
  #define SEEN      0x0002
@@@ -37,6 -36,8 +37,6 @@@ static int check_strict
  static int keep_cache_objects;
  static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT;
  static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT;
 -static struct object_id head_oid;
 -static const char *head_points_at;
  static int errors_found;
  static int write_lost_and_found;
  static int verbose;
@@@ -381,7 -382,8 +381,8 @@@ out
        if (obj->type == OBJ_TREE)
                free_tree_buffer((struct tree *)obj);
        if (obj->type == OBJ_COMMIT)
-               free_commit_buffer((struct commit *)obj);
+               free_commit_buffer(the_repository->parsed_objects,
+                                  (struct commit *)obj);
        return err;
  }
  
@@@ -445,11 -447,7 +446,11 @@@ static int fsck_handle_reflog_ent(struc
  static int fsck_handle_reflog(const char *logname, const struct object_id *oid,
                              int flag, void *cb_data)
  {
 -      for_each_reflog_ent(logname, fsck_handle_reflog_ent, (void *)logname);
 +      struct strbuf refname = STRBUF_INIT;
 +
 +      strbuf_worktree_ref(cb_data, &refname, logname);
 +      for_each_reflog_ent(refname.buf, fsck_handle_reflog_ent, refname.buf);
 +      strbuf_release(&refname);
        return 0;
  }
  
@@@ -487,34 -485,13 +488,34 @@@ static int fsck_handle_ref(const char *
        return 0;
  }
  
 +static int fsck_head_link(const char *head_ref_name,
 +                        const char **head_points_at,
 +                        struct object_id *head_oid);
 +
  static void get_default_heads(void)
  {
 -      if (head_points_at && !is_null_oid(&head_oid))
 -              fsck_handle_ref("HEAD", &head_oid, 0, NULL);
 +      struct worktree **worktrees, **p;
 +      const char *head_points_at;
 +      struct object_id head_oid;
 +
        for_each_rawref(fsck_handle_ref, NULL);
 -      if (include_reflogs)
 -              for_each_reflog(fsck_handle_reflog, NULL);
 +
 +      worktrees = get_worktrees(0);
 +      for (p = worktrees; *p; p++) {
 +              struct worktree *wt = *p;
 +              struct strbuf ref = STRBUF_INIT;
 +
 +              strbuf_worktree_ref(wt, &ref, "HEAD");
 +              fsck_head_link(ref.buf, &head_points_at, &head_oid);
 +              if (head_points_at && !is_null_oid(&head_oid))
 +                      fsck_handle_ref(ref.buf, &head_oid, 0, NULL);
 +              strbuf_release(&ref);
 +
 +              if (include_reflogs)
 +                      refs_for_each_reflog(get_worktree_ref_store(wt),
 +                                           fsck_handle_reflog, wt);
 +      }
 +      free_worktrees(worktrees);
  
        /*
         * Not having any default heads isn't really fatal, but
@@@ -603,36 -580,33 +604,36 @@@ static void fsck_object_dir(const char 
        stop_progress(&progress);
  }
  
 -static int fsck_head_link(void)
 +static int fsck_head_link(const char *head_ref_name,
 +                        const char **head_points_at,
 +                        struct object_id *head_oid)
  {
        int null_is_error = 0;
  
        if (verbose)
 -              fprintf(stderr, "Checking HEAD link\n");
 +              fprintf(stderr, "Checking %s link\n", head_ref_name);
  
 -      head_points_at = resolve_ref_unsafe("HEAD", 0, &head_oid, NULL);
 -      if (!head_points_at) {
 +      *head_points_at = resolve_ref_unsafe(head_ref_name, 0, head_oid, NULL);
 +      if (!*head_points_at) {
                errors_found |= ERROR_REFS;
 -              return error("Invalid HEAD");
 +              return error("Invalid %s", head_ref_name);
        }
 -      if (!strcmp(head_points_at, "HEAD"))
 +      if (!strcmp(*head_points_at, head_ref_name))
                /* detached HEAD */
                null_is_error = 1;
 -      else if (!starts_with(head_points_at, "refs/heads/")) {
 +      else if (!starts_with(*head_points_at, "refs/heads/")) {
                errors_found |= ERROR_REFS;
 -              return error("HEAD points to something strange (%s)",
 -                           head_points_at);
 +              return error("%s points to something strange (%s)",
 +                           head_ref_name, *head_points_at);
        }
 -      if (is_null_oid(&head_oid)) {
 +      if (is_null_oid(head_oid)) {
                if (null_is_error) {
                        errors_found |= ERROR_REFS;
 -                      return error("HEAD: detached HEAD points at nothing");
 +                      return error("%s: detached HEAD points at nothing",
 +                                   head_ref_name);
                }
 -              fprintf(stderr, "notice: HEAD points to an unborn branch (%s)\n",
 -                      head_points_at + 11);
 +              fprintf(stderr, "notice: %s points to an unborn branch (%s)\n",
 +                      head_ref_name, *head_points_at + 11);
        }
        return 0;
  }
@@@ -747,6 -721,7 +748,6 @@@ int cmd_fsck(int argc, const char **arg
  
        git_config(fsck_config, NULL);
  
 -      fsck_head_link();
        if (connectivity_only) {
                for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
                for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
diff --combined builtin/log.c
index e8e51068bd903c01e12207637d59d80ea940bf2d,64c2649c7cff2b18379882eb4c4337e4615e7eee..45aa376a596f08430f7ee59a7f995223c8b5e7a8
@@@ -107,8 -107,6 +107,8 @@@ static int log_line_range_callback(cons
  {
        struct line_opt_callback_data *data = option->value;
  
 +      BUG_ON_OPT_NEG(unset);
 +
        if (!arg)
                return -1;
  
@@@ -397,7 -395,8 +397,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;
                }
@@@ -1011,6 -1010,8 +1012,6 @@@ static void show_diffstat(struct rev_in
  
        memcpy(&opts, &rev->diffopt, sizeof(opts));
        opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
 -      opts.stat_width = MAIL_DEFAULT_WRAP;
 -
        diff_setup_done(&opts);
  
        diff_tree_oid(get_commit_tree_oid(origin),
@@@ -1094,18 -1095,9 +1095,18 @@@ static void make_cover_letter(struct re
        }
  
        if (rev->rdiff1) {
 +              /*
 +               * Pass minimum required diff-options to range-diff; others
 +               * can be added later if deemed desirable.
 +               */
 +              struct diff_options opts;
 +              diff_setup(&opts);
 +              opts.file = rev->diffopt.file;
 +              opts.use_color = rev->diffopt.use_color;
 +              diff_setup_done(&opts);
                fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title);
                show_range_diff(rev->rdiff1, rev->rdiff2,
 -                              rev->creation_factor, 1, &rev->diffopt);
 +                              rev->creation_factor, 1, &opts);
        }
  }
  
@@@ -1160,8 -1152,6 +1161,8 @@@ static int keep_subject = 0
  
  static int keep_callback(const struct option *opt, const char *arg, int unset)
  {
 +      BUG_ON_OPT_NEG(unset);
 +      BUG_ON_OPT_ARG(arg);
        ((struct rev_info *)opt->value)->total = -1;
        keep_subject = 1;
        return 0;
@@@ -1172,7 -1162,6 +1173,7 @@@ static int subject_prefix = 0
  static int subject_prefix_callback(const struct option *opt, const char *arg,
                            int unset)
  {
 +      BUG_ON_OPT_NEG(unset);
        subject_prefix = 1;
        ((struct rev_info *)opt->value)->subject_prefix = arg;
        return 0;
  
  static int rfc_callback(const struct option *opt, const char *arg, int unset)
  {
 +      BUG_ON_OPT_NEG(unset);
 +      BUG_ON_OPT_ARG(arg);
        return subject_prefix_callback(opt, "RFC PATCH", unset);
  }
  
@@@ -1190,7 -1177,6 +1191,7 @@@ static int numbered_cmdline_opt = 0
  static int numbered_callback(const struct option *opt, const char *arg,
                             int unset)
  {
 +      BUG_ON_OPT_ARG(arg);
        *(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
        if (unset)
                auto_number =  0;
  static int no_numbered_callback(const struct option *opt, const char *arg,
                                int unset)
  {
 +      BUG_ON_OPT_NEG(unset);
        return numbered_callback(opt, arg, 1);
  }
  
@@@ -1208,7 -1193,6 +1209,7 @@@ static int output_directory_callback(co
                              int unset)
  {
        const char **dir = (const char **)opt->value;
 +      BUG_ON_OPT_NEG(unset);
        if (*dir)
                die(_("Two output directories?"));
        *dir = arg;
@@@ -1525,7 -1509,7 +1526,7 @@@ int cmd_format_patch(int argc, const ch
                            PARSE_OPT_NOARG, numbered_callback },
                { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
                            N_("use [PATCH] even with multiple patches"),
 -                          PARSE_OPT_NOARG, no_numbered_callback },
 +                          PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback },
                OPT_BOOL('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
                OPT_BOOL(0, "stdout", &use_stdout,
                            N_("print patches to standard out")),
                    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/rev-list.c
index 2880ed37e3f97193d2374657346b4de52bc44954,2b301fa3152dd490ff0d230a41805c79b3266803..3a2c0c23b6b5b69883bb94398975dc6049ab4108
@@@ -6,7 -6,6 +6,7 @@@
  #include "list-objects.h"
  #include "list-objects-filter.h"
  #include "list-objects-filter-options.h"
 +#include "object.h"
  #include "object-store.h"
  #include "pack.h"
  #include "pack-bitmap.h"
@@@ -197,7 -196,8 +197,8 @@@ static void finish_commit(struct commi
                free_commit_list(commit->parents);
                commit->parents = NULL;
        }
-       free_commit_buffer(commit);
+       free_commit_buffer(the_repository->parsed_objects,
+                          commit);
  }
  
  static inline void finish_object__ma(struct object *obj)
         */
        switch (arg_missing_action) {
        case MA_ERROR:
 -              die("missing blob object '%s'", oid_to_hex(&obj->oid));
 +              die("missing %s object '%s'",
 +                  type_name(obj->type), oid_to_hex(&obj->oid));
                return;
  
        case MA_ALLOW_ANY:
        case MA_ALLOW_PROMISOR:
                if (is_promisor_object(&obj->oid))
                        return;
 -              die("unexpected missing blob object '%s'",
 -                  oid_to_hex(&obj->oid));
 +              die("unexpected missing %s object '%s'",
 +                  type_name(obj->type), oid_to_hex(&obj->oid));
                return;
  
        default:
  static int finish_object(struct object *obj, const char *name, void *cb_data)
  {
        struct rev_list_info *info = cb_data;
 -      if (obj->type == OBJ_BLOB && !has_object_file(&obj->oid)) {
 +      if (!has_object_file(&obj->oid)) {
                finish_object__ma(obj);
                return 1;
        }
@@@ -374,9 -373,7 +375,9 @@@ int cmd_rev_list(int argc, const char *
        git_config(git_default_config, NULL);
        repo_init_revisions(the_repository, &revs, prefix);
        revs.abbrev = DEFAULT_ABBREV;
 +      revs.allow_exclude_promisor_objects_opt = 1;
        revs.commit_format = CMIT_FMT_UNSPECIFIED;
 +      revs.do_not_die_on_missing_tree = 1;
  
        /*
         * Scan the argument list before invoking setup_revisions(), so that we
diff --combined cache.h
index ca36b44ee0b5851f837616c322a201ac420a90d2,8864d7ec1518dc6e280d068d315025fa30344c83..b7acd81d2e077c430ac3c3f19a118db2251d423e
+++ b/cache.h
@@@ -486,8 -486,6 +486,8 @@@ static inline enum object_type object_t
  #define INFOATTRIBUTES_FILE "info/attributes"
  #define ATTRIBUTE_MACRO_PREFIX "[attr]"
  #define GITMODULES_FILE ".gitmodules"
 +#define GITMODULES_INDEX ":.gitmodules"
 +#define GITMODULES_HEAD "HEAD:.gitmodules"
  #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
  #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
  #define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
@@@ -661,9 -659,6 +661,9 @@@ 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);
@@@ -788,8 -783,6 +788,8 @@@ extern void *read_blob_data_from_index(
  #define CE_MATCH_REFRESH              0x10
  /* don't refresh_fsmonitor state or do stat comparison even if CE_FSMONITOR_VALID is true */
  #define CE_MATCH_IGNORE_FSMONITOR 0X20
 +extern int is_racy_timestamp(const struct index_state *istate,
 +                           const struct cache_entry *ce);
  extern int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
  extern int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
  
@@@ -911,6 -904,14 +911,6 @@@ int use_optional_locks(void)
  extern char comment_line_char;
  extern int auto_comment_line_char;
  
 -/* Windows only */
 -enum hide_dotfiles_type {
 -      HIDE_DOTFILES_FALSE = 0,
 -      HIDE_DOTFILES_TRUE,
 -      HIDE_DOTFILES_DOTGITONLY
 -};
 -extern enum hide_dotfiles_type hide_dotfiles;
 -
  enum log_refs_config {
        LOG_REFS_UNSET = -1,
        LOG_REFS_NONE = 0,
@@@ -959,13 -960,11 +959,13 @@@ extern int grafts_replace_parents
  extern int repository_format_precious_objects;
  extern char *repository_format_partial_clone;
  extern const char *core_partial_clone_filter_default;
 +extern int repository_format_worktree_config;
  
  struct repository_format {
        int version;
        int precious_objects;
        char *partial_clone; /* value of extensions.partialclone */
 +      int worktree_config;
        int is_bare;
        int hash_algo;
        char *work_tree;
@@@ -1034,6 -1033,8 +1034,8 @@@ static inline int hashcmp(const unsigne
         *
         * This will need to be extended or ripped out when we learn about
         * hashes of different sizes.
+        *
+        * When ripping this out, see TODO in test-repository.c.
         */
        if (the_hash_algo->rawsz != 20)
                BUG("hash size not yet supported by hashcmp");
@@@ -1486,7 -1487,6 +1488,7 @@@ extern const char *fmt_name(const char 
  extern const char *ident_default_name(void);
  extern const char *ident_default_email(void);
  extern const char *git_editor(void);
 +extern const char *git_sequence_editor(void);
  extern const char *git_pager(int stdout_is_tty);
  extern int is_terminal_dumb(void);
  extern int git_ident_config(const char *, const char *, void *);
diff --combined commit-reach.c
index d5a39defd3d5144f83d4f48e43e54e1f7f49ab29,8715008fef964a446e3ba8c221734b667b54c170..3ea174788a4f0229460bad65373e974cc3f87c64
@@@ -30,7 -30,8 +30,8 @@@ static int queue_has_nonstale(struct pr
  }
  
  /* all input commits in one and twos[] must have been parsed! */
- static struct commit_list *paint_down_to_common(struct commit *one, int n,
+ static struct commit_list *paint_down_to_common(struct repository *r,
+                                               struct commit *one, int n,
                                                struct commit **twos,
                                                int min_generation)
  {
@@@ -83,7 -84,7 +84,7 @@@
                        parents = parents->next;
                        if ((p->object.flags & flags) == flags)
                                continue;
-                       if (parse_commit(p))
+                       if (repo_parse_commit(r, p))
                                return NULL;
                        p->object.flags |= flags;
                        prio_queue_put(&queue, p);
@@@ -94,7 -95,9 +95,9 @@@
        return result;
  }
  
- static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
+ static struct commit_list *merge_bases_many(struct repository *r,
+                                           struct commit *one, int n,
+                                           struct commit **twos)
  {
        struct commit_list *list = NULL;
        struct commit_list *result = NULL;
                        return commit_list_insert(one, &result);
        }
  
-       if (parse_commit(one))
+       if (repo_parse_commit(r, one))
                return NULL;
        for (i = 0; i < n; i++) {
-               if (parse_commit(twos[i]))
+               if (repo_parse_commit(r, twos[i]))
                        return NULL;
        }
  
-       list = paint_down_to_common(one, n, twos, 0);
+       list = paint_down_to_common(r, one, n, twos, 0);
  
        while (list) {
                struct commit *commit = pop_commit(&list);
@@@ -153,7 -156,7 +156,7 @@@ struct commit_list *get_octopus_merge_b
        return ret;
  }
  
- static int remove_redundant(struct commit **array, int cnt)
+ static int remove_redundant(struct repository *r, struct commit **array, int cnt)
  {
        /*
         * Some commit in the array may be an ancestor of
        ALLOC_ARRAY(filled_index, cnt - 1);
  
        for (i = 0; i < cnt; i++)
-               parse_commit(array[i]);
+               repo_parse_commit(r, array[i]);
        for (i = 0; i < cnt; i++) {
                struct commit_list *common;
                uint32_t min_generation = array[i]->generation;
                        if (array[j]->generation < min_generation)
                                min_generation = array[j]->generation;
                }
-               common = paint_down_to_common(array[i], filled, work,
-                                             min_generation);
+               common = paint_down_to_common(r, array[i], filled,
+                                             work, min_generation);
                if (array[i]->object.flags & PARENT2)
                        redundant[i] = 1;
                for (j = 0; j < filled; j++)
        return filled;
  }
  
- static struct commit_list *get_merge_bases_many_0(struct commit *one,
+ static struct commit_list *get_merge_bases_many_0(struct repository *r,
+                                                 struct commit *one,
                                                  int n,
                                                  struct commit **twos,
                                                  int cleanup)
        struct commit_list *result;
        int cnt, i;
  
-       result = merge_bases_many(one, n, twos);
+       result = merge_bases_many(r, one, n, twos);
        for (i = 0; i < n; i++) {
                if (one == twos[i])
                        return result;
        clear_commit_marks(one, all_flags);
        clear_commit_marks_many(n, twos, all_flags);
  
-       cnt = remove_redundant(rslt, cnt);
+       cnt = remove_redundant(r, rslt, cnt);
        result = NULL;
        for (i = 0; i < cnt; i++)
                commit_list_insert_by_date(rslt[i], &result);
        return result;
  }
  
- struct commit_list *get_merge_bases_many(struct commit *one,
-                                        int n,
-                                        struct commit **twos)
+ struct commit_list *repo_get_merge_bases_many(struct repository *r,
+                                             struct commit *one,
+                                             int n,
+                                             struct commit **twos)
  {
-       return get_merge_bases_many_0(one, n, twos, 1);
+       return get_merge_bases_many_0(r, one, n, twos, 1);
  }
  
- struct commit_list *get_merge_bases_many_dirty(struct commit *one,
-                                              int n,
-                                              struct commit **twos)
+ struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
+                                                   struct commit *one,
+                                                   int n,
+                                                   struct commit **twos)
  {
-       return get_merge_bases_many_0(one, n, twos, 0);
+       return get_merge_bases_many_0(r, one, n, twos, 0);
  }
  
- struct commit_list *get_merge_bases(struct commit *one, struct commit *two)
+ struct commit_list *repo_get_merge_bases(struct repository *r,
+                                        struct commit *one,
+                                        struct commit *two)
  {
-       return get_merge_bases_many_0(one, 1, &two, 1);
+       return get_merge_bases_many_0(r, one, 1, &two, 1);
  }
  
  /*
@@@ -304,16 -312,17 +312,17 @@@ int is_descendant_of(struct commit *com
  /*
   * Is "commit" an ancestor of one of the "references"?
   */
- int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference)
+ int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
+                            int nr_reference, struct commit **reference)
  {
        struct commit_list *bases;
        int ret = 0, i;
        uint32_t min_generation = GENERATION_NUMBER_INFINITY;
  
-       if (parse_commit(commit))
+       if (repo_parse_commit(r, commit))
                return ret;
        for (i = 0; i < nr_reference; i++) {
-               if (parse_commit(reference[i]))
+               if (repo_parse_commit(r, reference[i]))
                        return ret;
                if (reference[i]->generation < min_generation)
                        min_generation = reference[i]->generation;
        if (commit->generation > min_generation)
                return ret;
  
-       bases = paint_down_to_common(commit, nr_reference, reference, commit->generation);
+       bases = paint_down_to_common(r, commit,
+                                    nr_reference, reference,
+                                    commit->generation);
        if (commit->object.flags & PARENT2)
                ret = 1;
        clear_commit_marks(commit, all_flags);
  /*
   * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
   */
- int in_merge_bases(struct commit *commit, struct commit *reference)
+ int repo_in_merge_bases(struct repository *r,
+                       struct commit *commit,
+                       struct commit *reference)
  {
-       return in_merge_bases_many(commit, 1, &reference);
+       return repo_in_merge_bases_many(r, commit, 1, &reference);
  }
  
  struct commit_list *reduce_heads(struct commit_list *heads)
                        p->item->object.flags &= ~STALE;
                }
        }
-       num_head = remove_redundant(array, num_head);
+       num_head = remove_redundant(the_repository, array, num_head);
        for (i = 0; i < num_head; i++)
                tail = &commit_list_insert(array[i], tail)->next;
        free(array);
@@@ -529,8 -542,8 +542,8 @@@ int commit_contains(struct ref_filter *
  
  static int compare_commits_by_gen(const void *_a, const void *_b)
  {
 -      const struct commit *a = (const struct commit *)_a;
 -      const struct commit *b = (const struct commit *)_b;
 +      const struct commit *a = *(const struct commit * const *)_a;
 +      const struct commit *b = *(const struct commit * const *)_b;
  
        if (a->generation < b->generation)
                return -1;
@@@ -593,10 -606,8 +606,10 @@@ int can_all_from_reach_with_flag(struc
                while (stack) {
                        struct commit_list *parent;
  
 -                      if (stack->item->object.flags & with_flag) {
 +                      if (stack->item->object.flags & (with_flag | RESULT)) {
                                pop_commit(&stack);
 +                              if (stack)
 +                                      stack->item->object.flags |= RESULT;
                                continue;
                        }
  
@@@ -690,72 -701,3 +703,72 @@@ int can_all_from_reach(struct commit_li
        object_array_clear(&from_objs);
        return result;
  }
 +
 +struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
 +                                       struct commit **to, int nr_to,
 +                                       unsigned int reachable_flag)
 +{
 +      struct commit **item;
 +      struct commit *current;
 +      struct commit_list *found_commits = NULL;
 +      struct commit **to_last = to + nr_to;
 +      struct commit **from_last = from + nr_from;
 +      uint32_t min_generation = GENERATION_NUMBER_INFINITY;
 +      int num_to_find = 0;
 +
 +      struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
 +
 +      for (item = to; item < to_last; item++) {
 +              struct commit *c = *item;
 +
 +              parse_commit(c);
 +              if (c->generation < min_generation)
 +                      min_generation = c->generation;
 +
 +              if (!(c->object.flags & PARENT1)) {
 +                      c->object.flags |= PARENT1;
 +                      num_to_find++;
 +              }
 +      }
 +
 +      for (item = from; item < from_last; item++) {
 +              struct commit *c = *item;
 +              if (!(c->object.flags & PARENT2)) {
 +                      c->object.flags |= PARENT2;
 +                      parse_commit(c);
 +
 +                      prio_queue_put(&queue, *item);
 +              }
 +      }
 +
 +      while (num_to_find && (current = prio_queue_get(&queue)) != NULL) {
 +              struct commit_list *parents;
 +
 +              if (current->object.flags & PARENT1) {
 +                      current->object.flags &= ~PARENT1;
 +                      current->object.flags |= reachable_flag;
 +                      commit_list_insert(current, &found_commits);
 +                      num_to_find--;
 +              }
 +
 +              for (parents = current->parents; parents; parents = parents->next) {
 +                      struct commit *p = parents->item;
 +
 +                      parse_commit(p);
 +
 +                      if (p->generation < min_generation)
 +                              continue;
 +
 +                      if (p->object.flags & PARENT2)
 +                              continue;
 +
 +                      p->object.flags |= PARENT2;
 +                      prio_queue_put(&queue, p);
 +              }
 +      }
 +
 +      clear_commit_marks_many(nr_to, to, PARENT1);
 +      clear_commit_marks_many(nr_from, from, PARENT2);
 +
 +      return found_commits;
 +}
diff --combined commit-reach.h
index fb8082a2ece94a94cf2f9a55ba95950caa41a914,a0d4a29d259ae8e4bc08463d848d28f5fa06728e..99a43e8b64fc803d7b7f4d09d11c2ec31fdb0a76
@@@ -1,29 -1,42 +1,43 @@@
 -#ifndef __COMMIT_REACH_H__
 -#define __COMMIT_REACH_H__
 +#ifndef COMMIT_REACH_H
 +#define COMMIT_REACH_H
  
 +#include "commit.h"
  #include "commit-slab.h"
  
 -struct commit;
  struct commit_list;
 -struct contains_cache;
  struct ref_filter;
 +struct object_id;
 +struct object_array;
  
- struct commit_list *get_merge_bases_many(struct commit *one,
-                                        int n,
-                                        struct commit **twos);
- struct commit_list *get_merge_bases_many_dirty(struct commit *one,
-                                              int n,
-                                              struct commit **twos);
- struct commit_list *get_merge_bases(struct commit *one, struct commit *two);
- struct commit_list *get_octopus_merge_bases(struct commit_list *in);
+ struct commit_list *repo_get_merge_bases(struct repository *r,
+                                        struct commit *rev1,
+                                        struct commit *rev2);
+ struct commit_list *repo_get_merge_bases_many(struct repository *r,
+                                             struct commit *one, int n,
+                                             struct commit **twos);
  /* To be used only when object flags after this call no longer matter */
- struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos);
+ struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
+                                                   struct commit *one, int n,
+                                                   struct commit **twos);
+ #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
+ #define get_merge_bases(r1, r2)           repo_get_merge_bases(the_repository, r1, r2)
+ #define get_merge_bases_many(one, n, two) repo_get_merge_bases_many(the_repository, one, n, two)
+ #define get_merge_bases_many_dirty(one, n, twos) repo_get_merge_bases_many_dirty(the_repository, one, n, twos)
+ #endif
+ struct commit_list *get_octopus_merge_bases(struct commit_list *in);
  
  int is_descendant_of(struct commit *commit, struct commit_list *with_commit);
- int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference);
- int in_merge_bases(struct commit *commit, struct commit *reference);
+ int repo_in_merge_bases(struct repository *r,
+                       struct commit *commit,
+                       struct commit *reference);
+ int repo_in_merge_bases_many(struct repository *r,
+                            struct commit *commit,
+                            int nr_reference, struct commit **reference);
+ #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
+ #define in_merge_bases(c1, c2) repo_in_merge_bases(the_repository, c1, c2)
+ #define in_merge_bases_many(c1, n, cs) repo_in_merge_bases_many(the_repository, c1, n, cs)
+ #endif
  
  /*
   * Takes a list of commits and returns a new list where those
@@@ -75,17 -88,4 +89,17 @@@ int can_all_from_reach_with_flag(struc
  int can_all_from_reach(struct commit_list *from, struct commit_list *to,
                       int commit_date_cutoff);
  
 +
 +/*
 + * Return a list of commits containing the commits in the 'to' array
 + * that are reachable from at least one commit in the 'from' array.
 + * Also add the given 'flag' to each of the commits in the returned list.
 + *
 + * This method uses the PARENT1 and PARENT2 flags during its operation,
 + * so be sure these flags are not set before calling the method.
 + */
 +struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
 +                                       struct commit **to, int nr_to,
 +                                       unsigned int reachable_flag);
 +
  #endif
diff --combined commit.c
index d13a7bc3746406bdaf0bda0975c25b40111afe47,4fe74aa4bcdd772f4018e470d95189e8612567d8..a5333c7ac6c373a13f9298b36be5ff94a90a3e3f
+++ b/commit.c
@@@ -17,8 -17,6 +17,8 @@@
  #include "sha1-lookup.h"
  #include "wt-status.h"
  #include "advice.h"
 +#include "refs.h"
 +#include "commit-reach.h"
  
  static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
  
@@@ -299,13 -297,15 +299,15 @@@ const void *get_cached_commit_buffer(st
        return v->buffer;
  }
  
- const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
+ const void *repo_get_commit_buffer(struct repository *r,
+                                  const struct commit *commit,
+                                  unsigned long *sizep)
  {
-       const void *ret = get_cached_commit_buffer(the_repository, commit, sizep);
+       const void *ret = get_cached_commit_buffer(r, commit, sizep);
        if (!ret) {
                enum object_type type;
                unsigned long size;
-               ret = read_object_file(&commit->object.oid, &type, &size);
+               ret = repo_read_object_file(r, &commit->object.oid, &type, &size);
                if (!ret)
                        die("cannot read commit object %s",
                            oid_to_hex(&commit->object.oid));
        return ret;
  }
  
- void unuse_commit_buffer(const struct commit *commit, const void *buffer)
+ void repo_unuse_commit_buffer(struct repository *r,
+                             const struct commit *commit,
+                             const void *buffer)
  {
        struct commit_buffer *v = buffer_slab_peek(
-               the_repository->parsed_objects->buffer_slab, commit);
+               r->parsed_objects->buffer_slab, commit);
        if (!(v && v->buffer == buffer))
                free((void *)buffer);
  }
  
- void free_commit_buffer(struct commit *commit)
+ void free_commit_buffer(struct parsed_object_pool *pool, struct commit *commit)
  {
        struct commit_buffer *v = buffer_slab_peek(
-               the_repository->parsed_objects->buffer_slab, commit);
+               pool->buffer_slab, commit);
        if (v) {
                FREE_AND_NULL(v->buffer);
                v->size = 0;
@@@ -352,13 -354,12 +356,12 @@@ struct object_id *get_commit_tree_oid(c
        return &get_commit_tree(commit)->object.oid;
  }
  
- void release_commit_memory(struct commit *c)
+ void release_commit_memory(struct parsed_object_pool *pool, struct commit *c)
  {
        c->maybe_tree = NULL;
        c->index = 0;
-       free_commit_buffer(c);
+       free_commit_buffer(pool, c);
        free_commit_list(c->parents);
-       /* TODO: what about commit->util? */
  
        c->object.parsed = 0;
  }
@@@ -445,7 -446,10 +448,10 @@@ int parse_commit_buffer(struct reposito
        return 0;
  }
  
- int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_commit_graph)
+ int repo_parse_commit_internal(struct repository *r,
+                              struct commit *item,
+                              int quiet_on_missing,
+                              int use_commit_graph)
  {
        enum object_type type;
        void *buffer;
                return -1;
        if (item->object.parsed)
                return 0;
-       if (use_commit_graph && parse_commit_in_graph(the_repository, item))
+       if (use_commit_graph && parse_commit_in_graph(r, item))
                return 0;
-       buffer = read_object_file(&item->object.oid, &type, &size);
+       buffer = repo_read_object_file(r, &item->object.oid, &type, &size);
        if (!buffer)
                return quiet_on_missing ? -1 :
                        error("Could not read %s",
                             oid_to_hex(&item->object.oid));
        }
  
-       ret = parse_commit_buffer(the_repository, item, buffer, size, 0);
+       ret = parse_commit_buffer(r, item, buffer, size, 0);
        if (save_commit_buffer && !ret) {
-               set_commit_buffer(the_repository, item, buffer, size);
+               set_commit_buffer(r, item, buffer, size);
                return 0;
        }
        free(buffer);
        return ret;
  }
  
- int parse_commit_gently(struct commit *item, int quiet_on_missing)
+ int repo_parse_commit_gently(struct repository *r,
+                            struct commit *item, int quiet_on_missing)
  {
-       return parse_commit_internal(item, quiet_on_missing, 1);
+       return repo_parse_commit_internal(r, item, quiet_on_missing, 1);
  }
  
  void parse_commit_or_die(struct commit *item)
@@@ -657,10 -662,11 +664,10 @@@ struct commit *pop_commit(struct commit
  /* count number of children that have not been emitted */
  define_commit_slab(indegree_slab, int);
  
 -/* record author-date for each commit object */
  define_commit_slab(author_date_slab, timestamp_t);
  
 -static void record_author_date(struct author_date_slab *author_date,
 -                             struct commit *commit)
 +void record_author_date(struct author_date_slab *author_date,
 +                      struct commit *commit)
  {
        const char *buffer = get_commit_buffer(commit, NULL);
        struct ident_split ident;
@@@ -685,8 -691,8 +692,8 @@@ fail_exit
        unuse_commit_buffer(commit, buffer);
  }
  
 -static int compare_commits_by_author_date(const void *a_, const void *b_,
 -                                        void *cb_data)
 +int compare_commits_by_author_date(const void *a_, const void *b_,
 +                                 void *cb_data)
  {
        const struct commit *a = a_, *b = b_;
        struct author_date_slab *author_date = cb_data;
@@@ -844,86 -850,6 +851,86 @@@ void sort_in_topological_order(struct c
                clear_author_date_slab(&author_date);
  }
  
 +struct rev_collect {
 +      struct commit **commit;
 +      int nr;
 +      int alloc;
 +      unsigned int initial : 1;
 +};
 +
 +static void add_one_commit(struct object_id *oid, struct rev_collect *revs)
 +{
 +      struct commit *commit;
 +
 +      if (is_null_oid(oid))
 +              return;
 +
 +      commit = lookup_commit(the_repository, oid);
 +      if (!commit ||
 +          (commit->object.flags & TMP_MARK) ||
 +          parse_commit(commit))
 +              return;
 +
 +      ALLOC_GROW(revs->commit, revs->nr + 1, revs->alloc);
 +      revs->commit[revs->nr++] = commit;
 +      commit->object.flags |= TMP_MARK;
 +}
 +
 +static int collect_one_reflog_ent(struct object_id *ooid, struct object_id *noid,
 +                                const char *ident, timestamp_t timestamp,
 +                                int tz, const char *message, void *cbdata)
 +{
 +      struct rev_collect *revs = cbdata;
 +
 +      if (revs->initial) {
 +              revs->initial = 0;
 +              add_one_commit(ooid, revs);
 +      }
 +      add_one_commit(noid, revs);
 +      return 0;
 +}
 +
 +struct commit *get_fork_point(const char *refname, struct commit *commit)
 +{
 +      struct object_id oid;
 +      struct rev_collect revs;
 +      struct commit_list *bases;
 +      int i;
 +      struct commit *ret = NULL;
 +
 +      memset(&revs, 0, sizeof(revs));
 +      revs.initial = 1;
 +      for_each_reflog_ent(refname, collect_one_reflog_ent, &revs);
 +
 +      if (!revs.nr && !get_oid(refname, &oid))
 +              add_one_commit(&oid, &revs);
 +
 +      for (i = 0; i < revs.nr; i++)
 +              revs.commit[i]->object.flags &= ~TMP_MARK;
 +
 +      bases = get_merge_bases_many(commit, revs.nr, revs.commit);
 +
 +      /*
 +       * There should be one and only one merge base, when we found
 +       * a common ancestor among reflog entries.
 +       */
 +      if (!bases || bases->next)
 +              goto cleanup_return;
 +
 +      /* And the found one must be one of the reflog entries */
 +      for (i = 0; i < revs.nr; i++)
 +              if (&bases->item->object == &revs.commit[i]->object)
 +                      break; /* found */
 +      if (revs.nr <= i)
 +              goto cleanup_return;
 +
 +      ret = bases->item;
 +
 +cleanup_return:
 +      free_commit_list(bases);
 +      return ret;
 +}
 +
  static const char gpg_sig_header[] = "gpgsig";
  static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;
  
@@@ -1099,33 -1025,7 +1106,33 @@@ int check_commit_signature(const struc
        return ret;
  }
  
 +void verify_merge_signature(struct commit *commit, int verbosity)
 +{
 +      char hex[GIT_MAX_HEXSZ + 1];
 +      struct signature_check signature_check;
 +      memset(&signature_check, 0, sizeof(signature_check));
 +
 +      check_commit_signature(commit, &signature_check);
  
 +      find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
 +      switch (signature_check.result) {
 +      case 'G':
 +              break;
 +      case 'U':
 +              die(_("Commit %s has an untrusted GPG signature, "
 +                    "allegedly by %s."), hex, signature_check.signer);
 +      case 'B':
 +              die(_("Commit %s has a bad GPG signature "
 +                    "allegedly by %s."), hex, signature_check.signer);
 +      default: /* 'N' */
 +              die(_("Commit %s does not have a GPG signature."), hex);
 +      }
 +      if (verbosity >= 0 && signature_check.result == 'G')
 +              printf(_("Commit %s has a good GPG signature by %s\n"),
 +                     hex, signature_check.signer);
 +
 +      signature_check_clear(&signature_check);
 +}
  
  void append_merge_tag_headers(struct commit_list *parents,
                              struct commit_extra_header ***tail)
diff --combined commit.h
index 98664536cb82c65f04a1742c3e5c1e269afc9493,d2779a23f6b8613223251f938e8347d922883198..42728c2906608a9f4f1724e02b16d913b74b8728
+++ b/commit.h
@@@ -8,7 -8,6 +8,7 @@@
  #include "gpg-interface.h"
  #include "string-list.h"
  #include "pretty.h"
 +#include "commit-slab.h"
  
  #define COMMIT_NOT_FROM_GRAPH 0xFFFFFFFF
  #define GENERATION_NUMBER_INFINITY 0xFFFFFFFF
@@@ -80,12 -79,21 +80,21 @@@ struct commit *lookup_commit_reference_
  struct commit *lookup_commit_or_die(const struct object_id *oid, const char *ref_name);
  
  int parse_commit_buffer(struct repository *r, struct commit *item, const void *buffer, unsigned long size, int check_graph);
- int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_commit_graph);
- int parse_commit_gently(struct commit *item, int quiet_on_missing);
- static inline int parse_commit(struct commit *item)
+ int repo_parse_commit_internal(struct repository *r, struct commit *item,
+                              int quiet_on_missing, int use_commit_graph);
+ int repo_parse_commit_gently(struct repository *r,
+                            struct commit *item,
+                            int quiet_on_missing);
+ static inline int repo_parse_commit(struct repository *r, struct commit *item)
  {
-       return parse_commit_gently(item, 0);
+       return repo_parse_commit_gently(r, item, 0);
  }
+ #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
+ #define parse_commit_internal(item, quiet, use) repo_parse_commit_internal(the_repository, item, quiet, use)
+ #define parse_commit_gently(item, quiet) repo_parse_commit_gently(the_repository, item, quiet)
+ #define parse_commit(item) repo_parse_commit(the_repository, item)
+ #endif
  void parse_commit_or_die(struct commit *item);
  
  struct buffer_slab;
@@@ -109,7 -117,12 +118,12 @@@ const void *get_cached_commit_buffer(st
   * from disk. The resulting memory should not be modified, and must be given
   * to unuse_commit_buffer when the caller is done.
   */
- const void *get_commit_buffer(const struct commit *, unsigned long *size);
+ const void *repo_get_commit_buffer(struct repository *r,
+                                  const struct commit *,
+                                  unsigned long *size);
+ #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
+ #define get_commit_buffer(c, s) repo_get_commit_buffer(the_repository, c, s)
+ #endif
  
  /*
   * Tell the commit subsytem that we are done with a particular commit buffer.
   * from an earlier call to get_commit_buffer.  The buffer may or may not be
   * freed by this call; callers should not access the memory afterwards.
   */
- void unuse_commit_buffer(const struct commit *, const void *buffer);
+ void repo_unuse_commit_buffer(struct repository *r,
+                             const struct commit *,
+                             const void *buffer);
+ #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
+ #define unuse_commit_buffer(c, b) repo_unuse_commit_buffer(the_repository, c, b)
+ #endif
  
  /*
   * Free any cached object buffer associated with the commit.
   */
- void free_commit_buffer(struct commit *);
+ void free_commit_buffer(struct parsed_object_pool *pool, struct commit *);
  
  struct tree *get_commit_tree(const struct commit *);
  struct object_id *get_commit_tree_oid(const struct commit *);
   * Release memory related to a commit, including the parent list and
   * any cached object buffer.
   */
- void release_commit_memory(struct commit *c);
+ void release_commit_memory(struct parsed_object_pool *pool, struct commit *c);
  
  /*
   * Disassociate any cached object buffer from the commit, but do not free it.
@@@ -162,6 -180,14 +181,14 @@@ extern int has_non_ascii(const char *te
  extern const char *logmsg_reencode(const struct commit *commit,
                                   char **commit_encoding,
                                   const char *output_encoding);
+ const char *repo_logmsg_reencode(struct repository *r,
+                                const struct commit *commit,
+                                char **commit_encoding,
+                                const char *output_encoding);
+ #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
+ #define logmsg_reencode(c, enc, out) repo_logmsg_reencode(the_repository, c, enc, out)
+ #endif
  extern const char *skip_blank_lines(const char *msg);
  
  /** Removes the first commit from a list sorted by date, and adds all
@@@ -206,8 -232,6 +233,8 @@@ int register_commit_graft(struct reposi
  void prepare_commit_graft(struct repository *r);
  struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid);
  
 +struct commit *get_fork_point(const char *refname, struct commit *commit);
 +
  /* largest positive number a signed 32-bit integer can contain */
  #define INFINITE_DEPTH 0x7fffffff
  
@@@ -252,9 -276,7 +279,9 @@@ extern void assign_shallow_commits_to_r
                                           uint32_t **used,
                                           int *ref_status);
  extern int delayed_reachability_test(struct shallow_info *si, int c);
 -extern void prune_shallow(int show_only);
 +#define PRUNE_SHOW_ONLY 1
 +#define PRUNE_QUICK 2
 +extern void prune_shallow(unsigned options);
  extern struct trace_key trace_shallow;
  
  extern int interactive_add(int argc, const char **argv, const char *prefix, int patch);
@@@ -334,20 -356,6 +361,20 @@@ extern int remove_signature(struct strb
   */
  extern int check_commit_signature(const struct commit *commit, struct signature_check *sigc);
  
 +/* record author-date for each commit object */
 +struct author_date_slab;
 +void record_author_date(struct author_date_slab *author_date,
 +                      struct commit *commit);
 +
 +int compare_commits_by_author_date(const void *a_, const void *b_, void *unused);
 +
 +/*
 + * Verify a single commit with check_commit_signature() and die() if it is not
 + * a good signature. This isn't really suitable for general use, but is a
 + * helper to implement consistent logic for pull/merge --verify-signatures.
 + */
 +void verify_merge_signature(struct commit *commit, int verbose);
 +
  int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
  int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused);
  
diff --combined packfile.c
index d1e6683ffe877d9bf1b0996f25f0720fdffe983a,bc2e0f5043bed2e230b21179b4034fdde58e7f68..570adfc3c65e5b333f3b839a341de3fb7239e689
@@@ -80,8 -80,10 +80,8 @@@ void pack_report(void
  static int check_packed_git_idx(const char *path, struct packed_git *p)
  {
        void *idx_map;
 -      struct pack_idx_header *hdr;
        size_t idx_size;
 -      uint32_t version, nr, i, *index;
 -      int fd = git_open(path);
 +      int fd = git_open(path), ret;
        struct stat st;
        const unsigned int hashsz = the_hash_algo->rawsz;
  
        idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
        close(fd);
  
 -      hdr = idx_map;
 +      ret = load_idx(path, hashsz, idx_map, idx_size, p);
 +
 +      if (ret)
 +              munmap(idx_map, idx_size);
 +
 +      return ret;
 +}
 +
 +int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
 +           size_t idx_size, struct packed_git *p)
 +{
 +      struct pack_idx_header *hdr = idx_map;
 +      uint32_t version, nr, i, *index;
 +
 +      if (idx_size < 4 * 256 + hashsz + hashsz)
 +              return error("index file %s is too small", path);
 +      if (idx_map == NULL)
 +              return error("empty data");
 +
        if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
                version = ntohl(hdr->idx_version);
 -              if (version < 2 || version > 2) {
 -                      munmap(idx_map, idx_size);
 +              if (version < 2 || version > 2)
                        return error("index file %s is version %"PRIu32
                                     " and is not supported by this binary"
                                     " (try upgrading GIT to a newer version)",
                                     path, version);
 -              }
        } else
                version = 1;
  
                index += 2;  /* skip index header */
        for (i = 0; i < 256; i++) {
                uint32_t n = ntohl(index[i]);
 -              if (n < nr) {
 -                      munmap(idx_map, idx_size);
 +              if (n < nr)
                        return error("non-monotonic index %s", path);
 -              }
                nr = n;
        }
  
                 *  - hash of the packfile
                 *  - file checksum
                 */
 -              if (idx_size != 4*256 + nr * (hashsz + 4) + hashsz + hashsz) {
 -                      munmap(idx_map, idx_size);
 +              if (idx_size != 4 * 256 + nr * (hashsz + 4) + hashsz + hashsz)
                        return error("wrong index v1 file size in %s", path);
 -              }
        } else if (version == 2) {
                /*
                 * Minimum size:
                unsigned long max_size = min_size;
                if (nr)
                        max_size += (nr - 1)*8;
 -              if (idx_size < min_size || idx_size > max_size) {
 -                      munmap(idx_map, idx_size);
 +              if (idx_size < min_size || idx_size > max_size)
                        return error("wrong index v2 file size in %s", path);
 -              }
                if (idx_size != min_size &&
                    /*
                     * make sure we can deal with large pack offsets.
                     * 31-bit signed offset won't be enough, neither
                     * 32-bit unsigned one will be.
                     */
 -                  (sizeof(off_t) <= 4)) {
 -                      munmap(idx_map, idx_size);
 +                  (sizeof(off_t) <= 4))
                        return error("pack too large for current definition of off_t in %s", path);
 -              }
        }
  
        p->index_version = version;
@@@ -345,11 -339,6 +345,11 @@@ void close_all_packs(struct raw_object_
                        BUG("want to close pack marked 'do-not-close'");
                else
                        close_pack(p);
 +
 +      if (o->multi_pack_index) {
 +              close_midx(o->multi_pack_index);
 +              o->multi_pack_index = NULL;
 +      }
  }
  
  /*
@@@ -1132,23 -1121,23 +1132,24 @@@ int unpack_object_header(struct packed_
  void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1)
  {
        unsigned i;
 +      const unsigned hashsz = the_hash_algo->rawsz;
        for (i = 0; i < p->num_bad_objects; i++)
 -              if (hasheq(sha1, p->bad_object_sha1 + GIT_SHA1_RAWSZ * i))
 +              if (hasheq(sha1, p->bad_object_sha1 + hashsz * i))
                        return;
        p->bad_object_sha1 = xrealloc(p->bad_object_sha1,
                                      st_mult(GIT_MAX_RAWSZ,
                                              st_add(p->num_bad_objects, 1)));
 -      hashcpy(p->bad_object_sha1 + GIT_SHA1_RAWSZ * p->num_bad_objects, sha1);
 +      hashcpy(p->bad_object_sha1 + hashsz * p->num_bad_objects, sha1);
        p->num_bad_objects++;
  }
  
- const struct packed_git *has_packed_and_bad(const unsigned char *sha1)
+ const struct packed_git *has_packed_and_bad(struct repository *r,
+                                           const unsigned char *sha1)
  {
        struct packed_git *p;
        unsigned i;
  
-       for (p = the_repository->objects->packed_git; p; p = p->next)
+       for (p = r->objects->packed_git; p; p = p->next)
                for (i = 0; i < p->num_bad_objects; i++)
                        if (hasheq(sha1,
                                   p->bad_object_sha1 + the_hash_algo->rawsz * i))
diff --combined packfile.h
index 6c4037605d0dfee59a084c440506f1af11708d63,7a62d722317734794d30e09191b1d09e25b0969b..d70c6d9afb94c77c285fe8ee3237f7a40867157a
@@@ -146,7 -146,7 +146,7 @@@ extern int packed_object_info(struct re
                              off_t offset, struct object_info *);
  
  extern void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1);
- extern const struct packed_git *has_packed_and_bad(const unsigned char *sha1);
+ extern const struct packed_git *has_packed_and_bad(struct repository *r, const unsigned char *sha1);
  
  /*
   * Iff a pack file in the given repository contains the object named by sha1,
@@@ -164,17 -164,4 +164,17 @@@ extern int has_pack_index(const unsigne
   */
  extern int is_promisor_object(const struct object_id *oid);
  
 +/*
 + * Expose a function for fuzz testing.
 + *
 + * load_idx() parses a block of memory as a packfile index and puts the results
 + * into a struct packed_git.
 + *
 + * This function should not be used directly. It is exposed here only so that we
 + * have a convenient entry-point for fuzz testing. For real uses, you should
 + * probably use open_pack_index() or parse_pack_index() instead.
 + */
 +extern int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
 +                  size_t idx_size, struct packed_git *p);
 +
  #endif
diff --combined pretty.c
index b83a3ecd2331af7f2e7e03bd76336cde3c2a6dfc,32404953089e98409a93b3720cc3d9f20792f60d..e89b89248e823f8c86bfd29ad82eb8c05b3cb840
+++ b/pretty.c
@@@ -595,14 -595,15 +595,15 @@@ static char *replace_encoding_header(ch
        return strbuf_detach(&tmp, NULL);
  }
  
- const char *logmsg_reencode(const struct commit *commit,
-                           char **commit_encoding,
-                           const char *output_encoding)
+ const char *repo_logmsg_reencode(struct repository *r,
+                                const struct commit *commit,
+                                char **commit_encoding,
+                                const char *output_encoding)
  {
        static const char *utf8 = "UTF-8";
        const char *use_encoding;
        char *encoding;
-       const char *msg = get_commit_buffer(commit, NULL);
+       const char *msg = repo_get_commit_buffer(r, commit, NULL);
        char *out;
  
        if (!output_encoding || !*output_encoding) {
                 * the cached copy from get_commit_buffer, we need to duplicate it
                 * to avoid munging the cached copy.
                 */
-               if (msg == get_cached_commit_buffer(the_repository, commit, NULL))
+               if (msg == get_cached_commit_buffer(r, commit, NULL))
                        out = xstrdup(msg);
                else
                        out = (char *)msg;
                 */
                out = reencode_string(msg, output_encoding, use_encoding);
                if (out)
-                       unuse_commit_buffer(commit, msg);
+                       repo_unuse_commit_buffer(r, commit, msg);
        }
  
        /*
@@@ -1256,14 -1257,6 +1257,14 @@@ static size_t format_commit_one(struct 
                        if (c->signature_check.key)
                                strbuf_addstr(sb, c->signature_check.key);
                        break;
 +              case 'F':
 +                      if (c->signature_check.fingerprint)
 +                              strbuf_addstr(sb, c->signature_check.fingerprint);
 +                      break;
 +              case 'P':
 +                      if (c->signature_check.primary_key_fingerprint)
 +                              strbuf_addstr(sb, c->signature_check.primary_key_fingerprint);
 +                      break;
                default:
                        return 0;
                }
@@@ -1515,9 -1508,10 +1516,10 @@@ void userformat_find_requirements(cons
        strbuf_release(&dummy);
  }
  
- void format_commit_message(const struct commit *commit,
-                          const char *format, struct strbuf *sb,
-                          const struct pretty_print_context *pretty_ctx)
+ void repo_format_commit_message(struct repository *r,
+                               const struct commit *commit,
+                               const char *format, struct strbuf *sb,
+                               const struct pretty_print_context *pretty_ctx)
  {
        struct format_commit_context context;
        const char *output_enc = pretty_ctx->output_encoding;
         * convert a commit message to UTF-8 first
         * as far as 'format_commit_item' assumes it in UTF-8
         */
-       context.message = logmsg_reencode(commit,
-                                         &context.commit_encoding,
-                                         utf8);
+       context.message = repo_logmsg_reencode(r, commit,
+                                              &context.commit_encoding,
+                                              utf8);
  
        strbuf_expand(sb, format, format_commit_item, &context);
        rewrap_message_tail(sb, &context, 0, 0, 0);
        }
  
        free(context.commit_encoding);
-       unuse_commit_buffer(commit, context.message);
+       repo_unuse_commit_buffer(r, commit, context.message);
  }
  
  static void pp_header(struct pretty_print_context *pp,
diff --combined sha1-file.c
index 5bd11c85bc563618b59dad3ff06e5ae5296c892b,e77273ccfd4bd5e840e99f1eb47af1fd8753e3c6..cc952864b2382962f310da6ffed055fed123ab3c
@@@ -833,7 -833,7 +833,7 @@@ int check_object_signature(const struc
                return -1;
  
        /* Generate the header */
 -      hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(obj_type), size) + 1;
 +      hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1;
  
        /* Sha1.. */
        the_hash_algo->init_fn(&c);
@@@ -1361,7 -1361,9 +1361,9 @@@ int oid_object_info(struct repository *
        return type;
  }
  
- static void *read_object(const unsigned char *sha1, enum object_type *type,
+ static void *read_object(struct repository *r,
+                        const unsigned char *sha1,
+                        enum object_type *type,
                         unsigned long *size)
  {
        struct object_id oid;
  
        hashcpy(oid.hash, sha1);
  
-       if (oid_object_info_extended(the_repository, &oid, &oi, 0) < 0)
+       if (oid_object_info_extended(r, &oid, &oi, 0) < 0)
                return NULL;
        return content;
  }
@@@ -1401,7 -1403,8 +1403,8 @@@ int pretend_object_file(void *buf, unsi
   * deal with them should arrange to call read_object() and give error
   * messages themselves.
   */
- void *read_object_file_extended(const struct object_id *oid,
+ void *read_object_file_extended(struct repository *r,
+                               const struct object_id *oid,
                                enum object_type *type,
                                unsigned long *size,
                                int lookup_replace)
        const char *path;
        struct stat st;
        const struct object_id *repl = lookup_replace ?
-               lookup_replace_object(the_repository, oid) : oid;
+               lookup_replace_object(r, oid) : oid;
  
        errno = 0;
-       data = read_object(repl->hash, type, size);
+       data = read_object(r, repl->hash, type, size);
        if (data)
                return data;
  
                die(_("replacement %s not found for %s"),
                    oid_to_hex(repl), oid_to_hex(oid));
  
-       if (!stat_sha1_file(the_repository, repl->hash, &st, &path))
+       if (!stat_sha1_file(r, repl->hash, &st, &path))
                die(_("loose object %s (stored in %s) is corrupt"),
                    oid_to_hex(repl), path);
  
-       if ((p = has_packed_and_bad(repl->hash)) != NULL)
+       if ((p = has_packed_and_bad(r, repl->hash)) != NULL)
                die(_("packed object %s (stored in %s) is corrupt"),
                    oid_to_hex(repl), p->pack_name);
  
@@@ -1492,7 -1495,7 +1495,7 @@@ static void write_object_file_prepare(c
        git_hash_ctx c;
  
        /* Generate the header */
 -      *hdrlen = xsnprintf(hdr, *hdrlen, "%s %lu", type, len)+1;
 +      *hdrlen = xsnprintf(hdr, *hdrlen, "%s %"PRIuMAX , type, (uintmax_t)len)+1;
  
        /* Sha1.. */
        the_hash_algo->init_fn(&c);
@@@ -1755,34 -1758,37 +1758,37 @@@ int force_object_loose(const struct obj
  
        if (has_loose_object(oid))
                return 0;
-       buf = read_object(oid->hash, &type, &len);
+       buf = read_object(the_repository, oid->hash, &type, &len);
        if (!buf)
                return error(_("cannot read sha1_file for %s"), oid_to_hex(oid));
 -      hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(type), len) + 1;
 +      hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1;
        ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime);
        free(buf);
  
        return ret;
  }
  
- int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
+ int repo_has_sha1_file_with_flags(struct repository *r,
+                                 const unsigned char *sha1, int flags)
  {
        struct object_id oid;
        if (!startup_info->have_repository)
                return 0;
        hashcpy(oid.hash, sha1);
-       return oid_object_info_extended(the_repository, &oid, NULL,
+       return oid_object_info_extended(r, &oid, NULL,
                                        flags | OBJECT_INFO_SKIP_CACHED) >= 0;
  }
  
- int has_object_file(const struct object_id *oid)
+ int repo_has_object_file(struct repository *r,
+                        const struct object_id *oid)
  {
-       return has_sha1_file(oid->hash);
+       return repo_has_sha1_file(r, oid->hash);
  }
  
- int has_object_file_with_flags(const struct object_id *oid, int flags)
+ int repo_has_object_file_with_flags(struct repository *r,
+                                   const struct object_id *oid, int flags)
  {
-       return has_sha1_file_with_flags(oid->hash, flags);
+       return repo_has_sha1_file_with_flags(r, oid->hash, flags);
  }
  
  static void check_tree(const void *buf, size_t size)
@@@ -2199,8 -2205,7 +2205,8 @@@ static int check_stream_sha1(git_zstrea
         * see the comment in unpack_sha1_rest for details.
         */
        while (total_read <= size &&
 -             (status == Z_OK || status == Z_BUF_ERROR)) {
 +             (status == Z_OK ||
 +              (status == Z_BUF_ERROR && !stream->avail_out))) {
                stream->next_out = buf;
                stream->avail_out = sizeof(buf);
                if (size - total_read < stream->avail_out)
diff --combined streaming.c
index ac7c7a22f90b7320a235f23db9387fd91ba5b2cd,c843a1230f35e255ba627ef47e0873b103110425..891f82f51a753d065ce67b111bce86e790801599
@@@ -408,15 -408,6 +408,15 @@@ static read_method_decl(pack_non_delta
                        st->z_state = z_done;
                        break;
                }
 +
 +              /*
 +               * Unlike the loose object case, we do not have to worry here
 +               * about running out of input bytes and spinning infinitely. If
 +               * we get Z_BUF_ERROR due to too few input bytes, then we'll
 +               * replenish them in the next use_pack() call when we loop. If
 +               * we truly hit the end of the pack (i.e., because it's corrupt
 +               * or truncated), then use_pack() catches that and will die().
 +               */
                if (status != Z_OK && status != Z_BUF_ERROR) {
                        git_inflate_end(&st->z);
                        st->z_state = z_error;
@@@ -499,7 -490,7 +499,7 @@@ static struct stream_vtbl incore_vtbl 
  
  static open_method_decl(incore)
  {
-       st->u.incore.buf = read_object_file_extended(oid, type, &st->size, 0);
+       st->u.incore.buf = read_object_file_extended(the_repository, oid, type, &st->size, 0);
        st->u.incore.read_ptr = 0;
        st->vtbl = &incore_vtbl;
  
diff --combined submodule.c
index 6415cc55807c7ed9ee4cbcaa57f41a5804b6e854,d9c06767a168cbe48906389a2c8af2879d9cf5eb..aa7854f3f9db2f0e7bbf7040b02b909e1451d47a
@@@ -51,24 -51,6 +51,24 @@@ int is_gitmodules_unmerged(const struc
        return 0;
  }
  
 +/*
 + * Check if the .gitmodules file is safe to write.
 + *
 + * Writing to the .gitmodules file requires that the file exists in the
 + * working tree or, if it doesn't, that a brand new .gitmodules file is going
 + * to be created (i.e. it's neither in the index nor in the current branch).
 + *
 + * It is not safe to write to .gitmodules if it's not in the working tree but
 + * it is in the index or in the current branch, because writing new values
 + * (and staging them) would blindly overwrite ALL the old content.
 + */
 +int is_writing_gitmodules_ok(void)
 +{
 +      struct object_id oid;
 +      return file_exists(GITMODULES_FILE) ||
 +              (get_oid(GITMODULES_INDEX, &oid) < 0 && get_oid(GITMODULES_HEAD, &oid) < 0);
 +}
 +
  /*
   * Check if the .gitmodules file has unstaged modifications.  This must be
   * checked before allowing modifications to the .gitmodules file with the
@@@ -107,7 -89,6 +107,7 @@@ int update_path_in_gitmodules(const cha
  {
        struct strbuf entry = STRBUF_INIT;
        const struct submodule *submodule;
 +      int ret;
  
        if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
                return -1;
        strbuf_addstr(&entry, "submodule.");
        strbuf_addstr(&entry, submodule->name);
        strbuf_addstr(&entry, ".path");
 -      if (git_config_set_in_file_gently(GITMODULES_FILE, entry.buf, newpath) < 0) {
 -              /* Maybe the user already did that, don't error out here */
 -              warning(_("Could not update .gitmodules entry %s"), entry.buf);
 -              strbuf_release(&entry);
 -              return -1;
 -      }
 +      ret = config_set_in_gitmodules_file_gently(entry.buf, newpath);
        strbuf_release(&entry);
 -      return 0;
 +      return ret;
  }
  
  /*
@@@ -457,7 -443,7 +457,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,14 -482,46 +496,46 @@@ 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.
+ /*
+  * 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;
@@@ -576,16 -595,18 +609,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)) ||
@@@ -675,6 -702,10 +716,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)
@@@ -708,7 -739,6 +753,7 @@@ static struct oid_array *submodule_comm
  }
  
  struct collect_changed_submodules_cb_data {
 +      struct repository *repo;
        struct string_list *changed;
        const struct object_id *commit_oid;
  };
@@@ -748,7 -778,7 +793,7 @@@ static void collect_changed_submodules_
                if (!S_ISGITLINK(p->two->mode))
                        continue;
  
 -              submodule = submodule_from_path(the_repository,
 +              submodule = submodule_from_path(me->repo,
                                                commit_oid, p->two->path);
                if (submodule)
                        name = submodule->name;
                        name = default_name_or_path(p->two->path);
                        /* make sure name does not collide with existing one */
                        if (name)
 -                              submodule = submodule_from_name(the_repository,
 +                              submodule = submodule_from_name(me->repo,
                                                                commit_oid, name);
                        if (submodule) {
                                warning("Submodule in commit %s at path: "
   * have a corresponding 'struct oid_array' (in the 'util' field) which lists
   * what the submodule pointers were updated to during the change.
   */
 -static void collect_changed_submodules(struct index_state *istate,
 +static void collect_changed_submodules(struct repository *r,
                                       struct string_list *changed,
                                       struct argv_array *argv)
  {
        struct rev_info rev;
        const struct commit *commit;
  
 -      repo_init_revisions(the_repository, &rev, NULL);
 +      repo_init_revisions(r, &rev, NULL);
        setup_revisions(argv->argc, argv->argv, &rev, NULL);
        if (prepare_revision_walk(&rev))
                die("revision walk setup failed");
        while ((commit = get_revision(&rev))) {
                struct rev_info diff_rev;
                struct collect_changed_submodules_cb_data data;
 +              data.repo = r;
                data.changed = changed;
                data.commit_oid = &commit->object.oid;
  
 -              repo_init_revisions(the_repository, &diff_rev, NULL);
 +              repo_init_revisions(r, &diff_rev, NULL);
                diff_rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
                diff_rev.diffopt.format_callback = collect_changed_submodules_cb;
                diff_rev.diffopt.format_callback_data = &data;
@@@ -832,7 -861,6 +877,7 @@@ static int append_oid_to_argv(const str
  }
  
  struct has_commit_data {
 +      struct repository *repo;
        int result;
        const char *path;
  };
@@@ -841,7 -869,7 +886,7 @@@ static int check_has_commit(const struc
  {
        struct has_commit_data *cb = data;
  
 -      enum object_type type = oid_object_info(the_repository, oid, NULL);
 +      enum object_type type = oid_object_info(cb->repo, oid, NULL);
  
        switch (type) {
        case OBJ_COMMIT:
        }
  }
  
 -static int submodule_has_commits(const char *path, struct oid_array *commits)
 +static int submodule_has_commits(struct repository *r,
 +                               const char *path,
 +                               struct oid_array *commits)
  {
 -      struct has_commit_data has_commit = { 1, path };
 +      struct has_commit_data has_commit = { r, 1, path };
  
        /*
         * Perform a cheap, but incorrect check for the existence of 'commits'.
        return has_commit.result;
  }
  
 -static int submodule_needs_pushing(const char *path, struct oid_array *commits)
 +static int submodule_needs_pushing(struct repository *r,
 +                                 const char *path,
 +                                 struct oid_array *commits)
  {
 -      if (!submodule_has_commits(path, commits))
 +      if (!submodule_has_commits(r, path, commits))
                /*
                 * NOTE: We do consider it safe to return "no" here. The
                 * correct answer would be "We do not know" instead of
        return 0;
  }
  
 -int find_unpushed_submodules(struct index_state *istate,
 +int find_unpushed_submodules(struct repository *r,
                             struct oid_array *commits,
                             const char *remotes_name,
                             struct string_list *needs_pushing)
        argv_array_push(&argv, "--not");
        argv_array_pushf(&argv, "--remotes=%s", remotes_name);
  
 -      collect_changed_submodules(istate, &submodules, &argv);
 +      collect_changed_submodules(r, &submodules, &argv);
  
        for_each_string_list_item(name, &submodules) {
                struct oid_array *commits = name->util;
                const struct submodule *submodule;
                const char *path = NULL;
  
 -              submodule = submodule_from_name(the_repository, &null_oid, name->string);
 +              submodule = submodule_from_name(r, &null_oid, name->string);
                if (submodule)
                        path = submodule->path;
                else
                if (!path)
                        continue;
  
 -              if (submodule_needs_pushing(path, commits))
 +              if (submodule_needs_pushing(r, path, commits))
                        string_list_insert(needs_pushing, path);
        }
  
@@@ -999,9 -1023,6 +1044,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");
@@@ -1068,7 -1089,7 +1110,7 @@@ static void submodule_push_check(const 
                die("process for submodule '%s' failed", path);
  }
  
 -int push_unpushed_submodules(struct index_state *istate,
 +int push_unpushed_submodules(struct repository *r,
                             struct oid_array *commits,
                             const struct remote *remote,
                             const struct refspec *rs,
        int i, ret = 1;
        struct string_list needs_pushing = STRING_LIST_INIT_DUP;
  
 -      if (!find_unpushed_submodules(istate, commits,
 +      if (!find_unpushed_submodules(r, commits,
                                      remote->name, &needs_pushing))
                return 1;
  
@@@ -1136,14 -1157,14 +1178,14 @@@ void check_for_new_submodule_commits(st
        oid_array_append(&ref_tips_after_fetch, oid);
  }
  
 -static void calculate_changed_submodule_paths(struct index_state *istate)
 +static void calculate_changed_submodule_paths(struct repository *r)
  {
        struct argv_array argv = ARGV_ARRAY_INIT;
        struct string_list changed_submodules = STRING_LIST_INIT_DUP;
        const struct string_list_item *name;
  
        /* No need to check if there are no submodules configured */
 -      if (!submodule_from_path(the_repository, NULL, NULL))
 +      if (!submodule_from_path(r, NULL, NULL))
                return;
  
        argv_array_push(&argv, "--"); /* argv[0] program name */
         * Collect all submodules (whether checked out or not) for which new
         * commits have been recorded upstream in "changed_submodule_names".
         */
 -      collect_changed_submodules(istate, &changed_submodules, &argv);
 +      collect_changed_submodules(r, &changed_submodules, &argv);
  
        for_each_string_list_item(name, &changed_submodules) {
                struct oid_array *commits = name->util;
                const struct submodule *submodule;
                const char *path = NULL;
  
 -              submodule = submodule_from_name(the_repository, &null_oid, name->string);
 +              submodule = submodule_from_name(r, &null_oid, name->string);
                if (submodule)
                        path = submodule->path;
                else
                if (!path)
                        continue;
  
 -              if (!submodule_has_commits(path, commits))
 +              if (!submodule_has_commits(r, path, commits))
                        string_list_append(&changed_submodule_names, name->string);
        }
  
        initialized_fetch_ref_tips = 0;
  }
  
 -int submodule_touches_in_range(struct index_state *istate,
 +int submodule_touches_in_range(struct repository *r,
                               struct object_id *excl_oid,
                               struct object_id *incl_oid)
  {
        int ret;
  
        /* No need to check if there are no submodules configured */
 -      if (!submodule_from_path(the_repository, NULL, NULL))
 +      if (!submodule_from_path(r, NULL, NULL))
                return 0;
  
        argv_array_push(&args, "--"); /* args[0] program name */
                argv_array_push(&args, oid_to_hex(excl_oid));
        }
  
 -      collect_changed_submodules(istate, &subs, &args);
 +      collect_changed_submodules(r, &subs, &args);
        ret = subs.nr;
  
        argv_array_clear(&args);
@@@ -1373,7 -1394,7 +1415,7 @@@ 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->index);
 +      calculate_changed_submodule_paths(r);
        run_processes_parallel(max_parallel_jobs,
                               get_next_submodule,
                               fetch_start_failure,