Merge branch 'sb/object-store-lookup'
authorJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:42 +0000 (15:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:42 +0000 (15:30 -0700)
lookup_commit_reference() and friends have been updated to find
in-core object for a specific in-core repository instance.

* sb/object-store-lookup: (32 commits)
commit.c: allow lookup_commit_reference to handle arbitrary repositories
commit.c: allow lookup_commit_reference_gently to handle arbitrary repositories
tag.c: allow deref_tag to handle arbitrary repositories
object.c: allow parse_object to handle arbitrary repositories
object.c: allow parse_object_buffer to handle arbitrary repositories
commit.c: allow get_cached_commit_buffer to handle arbitrary repositories
commit.c: allow set_commit_buffer to handle arbitrary repositories
commit.c: migrate the commit buffer to the parsed object store
commit-slabs: remove realloc counter outside of slab struct
commit.c: allow parse_commit_buffer to handle arbitrary repositories
tag: allow parse_tag_buffer to handle arbitrary repositories
tag: allow lookup_tag to handle arbitrary repositories
commit: allow lookup_commit to handle arbitrary repositories
tree: allow lookup_tree to handle arbitrary repositories
blob: allow lookup_blob to handle arbitrary repositories
object: allow lookup_object to handle arbitrary repositories
object: allow object_as_type to handle arbitrary repositories
tag: add repository argument to deref_tag
tag: add repository argument to parse_tag_buffer
tag: add repository argument to lookup_tag
...

35 files changed:
1  2 
builtin/branch.c
builtin/checkout.c
builtin/clone.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/fsck.c
builtin/grep.c
builtin/log.c
builtin/pack-objects.c
builtin/receive-pack.c
builtin/rev-list.c
commit-graph.c
commit.c
commit.h
fast-import.c
fetch-pack.c
fsck.c
line-log.c
list-objects.c
log-tree.c
merge-recursive.c
negotiator/default.c
object.h
pretty.c
ref-filter.c
refs.c
refs/files-backend.c
remote.c
revision.c
sequencer.c
sha1-file.c
sha1-name.c
submodule.c
upload-pack.c
wt-status.c
diff --combined builtin/branch.c
index 0192d4a8795b64cb45fc84577c8ee30122fddd05,a50632fb23f52e3bad6de8a8e225498f4071fc58..4fc55c3508c2fff3e92e6235ed35ba582caf4b15
@@@ -37,7 -37,6 +37,7 @@@ static const char * const builtin_branc
  
  static const char *head;
  static struct object_id head_oid;
 +static int used_deprecated_reflog_option;
  
  static int branch_use_color = -1;
  static char branch_colors[][COLOR_MAXLEN] = {
@@@ -122,7 -121,8 +122,8 @@@ static int branch_merged(int kind, cons
                    (reference_name = reference_name_to_free =
                     resolve_refdup(upstream, RESOLVE_REF_READING,
                                    &oid, NULL)) != NULL)
-                       reference_rev = lookup_commit_reference(&oid);
+                       reference_rev = lookup_commit_reference(the_repository,
+                                                               &oid);
        }
        if (!reference_rev)
                reference_rev = head_rev;
@@@ -155,7 -155,7 +156,7 @@@ static int check_branch_commit(const ch
                               const struct object_id *oid, struct commit *head_rev,
                               int kinds, int force)
  {
-       struct commit *rev = lookup_commit_reference(oid);
+       struct commit *rev = lookup_commit_reference(the_repository, oid);
        if (!rev) {
                error(_("Couldn't look up commit object for '%s'"), refname);
                return -1;
@@@ -209,7 -209,7 +210,7 @@@ static int delete_branches(int argc, co
        }
  
        if (!force) {
-               head_rev = lookup_commit_reference(&head_oid);
+               head_rev = lookup_commit_reference(the_repository, &head_oid);
                if (!head_rev)
                        die(_("Couldn't look up commit object for HEAD"));
        }
@@@ -569,14 -569,6 +570,14 @@@ static int edit_branch_description(cons
        return 0;
  }
  
 +static int deprecated_reflog_option_cb(const struct option *opt,
 +                                     const char *arg, int unset)
 +{
 +      used_deprecated_reflog_option = 1;
 +      *(int *)opt->value = !unset;
 +      return 0;
 +}
 +
  int cmd_branch(int argc, const char **argv, const char *prefix)
  {
        int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
                OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
                OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
                OPT_BOOL(0, "list", &list, N_("list branch names")),
 -              OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
 +              OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")),
 +              {
 +                      OPTION_CALLBACK, 'l', NULL, &reflog, NULL,
 +                      N_("deprecated synonym for --create-reflog"),
 +                      PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
 +                      deprecated_reflog_option_cb
 +              },
                OPT_BOOL(0, "edit-description", &edit_description,
                         N_("edit the description for the branch")),
                OPT__FORCE(&force, N_("force creation, move/rename, deletion"), PARSE_OPT_NOCOMPLETE),
        if (list)
                setup_auto_pager("branch", 1);
  
 +      if (used_deprecated_reflog_option && !list) {
 +              warning("the '-l' alias for '--create-reflog' is deprecated;");
 +              warning("it will be removed in a future version of Git");
 +      }
 +
        if (delete) {
                if (!argc)
                        die(_("branch name required"));
diff --combined builtin/checkout.c
index 2de10d28c76e7616748ef37def3b6e4f43a4e7a7,40c27bf54d7049e830f1628bd83dddfd86dd137a..923b8cbd8240e16bad5adace670b3b63b9c02768
@@@ -23,7 -23,6 +23,7 @@@
  #include "resolve-undo.h"
  #include "submodule-config.h"
  #include "submodule.h"
 +#include "advice.h"
  
  static const char * const checkout_usage[] = {
        N_("git checkout [<options>] <branch>"),
@@@ -380,7 -379,7 +380,7 @@@ static int checkout_paths(const struct 
                die(_("unable to write new index file"));
  
        read_ref_full("HEAD", 0, &rev, NULL);
-       head = lookup_commit_reference_gently(&rev, 1);
+       head = lookup_commit_reference_gently(the_repository, &rev, 1);
  
        errs |= post_checkout_hook(head, head, 0);
        return errs;
@@@ -831,7 -830,7 +831,7 @@@ static int switch_branches(const struc
        memset(&old_branch_info, 0, sizeof(old_branch_info));
        old_branch_info.path = path_to_free = resolve_refdup("HEAD", 0, &rev, &flag);
        if (old_branch_info.path)
-               old_branch_info.commit = lookup_commit_reference_gently(&rev, 1);
+               old_branch_info.commit = lookup_commit_reference_gently(the_repository, &rev, 1);
        if (!(flag & REF_ISSYMREF))
                old_branch_info.path = NULL;
  
@@@ -880,8 -879,7 +880,8 @@@ static int parse_branchname_arg(int arg
                                int dwim_new_local_branch_ok,
                                struct branch_info *new_branch_info,
                                struct checkout_opts *opts,
 -                              struct object_id *rev)
 +                              struct object_id *rev,
 +                              int *dwim_remotes_matched)
  {
        struct tree **source_tree = &opts->source_tree;
        const char **new_branch = &opts->new_branch;
         *   (b) If <something> is _not_ a commit, either "--" is present
         *       or <something> is not a path, no -t or -b was given, and
         *       and there is a tracking branch whose name is <something>
 -       *       in one and only one remote, then this is a short-hand to
 -       *       fork local <something> from that remote-tracking branch.
 +       *       in one and only one remote (or if the branch exists on the
 +       *       remote named in checkout.defaultRemote), then this is a
 +       *       short-hand to fork local <something> from that
 +       *       remote-tracking branch.
         *
         *   (c) Otherwise, if "--" is present, treat it like case (1).
         *
                        recover_with_dwim = 0;
  
                if (recover_with_dwim) {
 -                      const char *remote = unique_tracking_name(arg, rev);
 +                      const char *remote = unique_tracking_name(arg, rev,
 +                                                                dwim_remotes_matched);
                        if (remote) {
                                *new_branch = arg;
                                arg = remote;
        else
                new_branch_info->path = NULL; /* not an existing branch */
  
-       new_branch_info->commit = lookup_commit_reference_gently(rev, 1);
+       new_branch_info->commit = lookup_commit_reference_gently(the_repository, rev, 1);
        if (!new_branch_info->commit) {
                /* not a commit */
                *source_tree = parse_tree_indirect(rev);
@@@ -1115,7 -1110,6 +1115,7 @@@ int cmd_checkout(int argc, const char *
        struct branch_info new_branch_info;
        char *conflict_style = NULL;
        int dwim_new_local_branch = 1;
 +      int dwim_remotes_matched = 0;
        struct option options[] = {
                OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
                OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
                        opts.track == BRANCH_TRACK_UNSPECIFIED &&
                        !opts.new_branch;
                int n = parse_branchname_arg(argc, argv, dwim_ok,
 -                                           &new_branch_info, &opts, &rev);
 +                                           &new_branch_info, &opts, &rev,
 +                                           &dwim_remotes_matched);
                argv += n;
                argc -= n;
        }
        }
  
        UNLEAK(opts);
 -      if (opts.patch_mode || opts.pathspec.nr)
 -              return checkout_paths(&opts, new_branch_info.name);
 -      else
 +      if (opts.patch_mode || opts.pathspec.nr) {
 +              int ret = checkout_paths(&opts, new_branch_info.name);
 +              if (ret && dwim_remotes_matched > 1 &&
 +                  advice_checkout_ambiguous_remote_branch_name)
 +                      advise(_("'%s' matched more than one remote tracking branch.\n"
 +                               "We found %d remotes with a reference that matched. So we fell back\n"
 +                               "on trying to resolve the argument as a path, but failed there too!\n"
 +                               "\n"
 +                               "If you meant to check out a remote tracking branch on, e.g. 'origin',\n"
 +                               "you can do so by fully qualifying the name with the --track option:\n"
 +                               "\n"
 +                               "    git checkout --track origin/<name>\n"
 +                               "\n"
 +                               "If you'd like to always have checkouts of an ambiguous <name> prefer\n"
 +                               "one remote, e.g. the 'origin' remote, consider setting\n"
 +                               "checkout.defaultRemote=origin in your config."),
 +                             argv[0],
 +                             dwim_remotes_matched);
 +              return ret;
 +      } else {
                return checkout_branch(&opts, &new_branch_info);
 +      }
  }
diff --combined builtin/clone.c
index 5c439f1394c9a097e48f24d73790f276a958bf2d,4b3b48ee84ac59a546038a0dd9a84521e96e3cd7..9ebb5acf56c5e03f8acafda4d806d6e3a41ee91f
@@@ -696,7 -696,8 +696,8 @@@ static void update_head(const struct re
                        install_branch_config(0, head, option_origin, our->name);
                }
        } else if (our) {
-               struct commit *c = lookup_commit_reference(&our->old_oid);
+               struct commit *c = lookup_commit_reference(the_repository,
+                                                          &our->old_oid);
                /* --branch specifies a non-branch (i.e. tags), detach HEAD */
                update_ref(msg, "HEAD", &c->object.oid, NULL, REF_NO_DEREF,
                           UPDATE_REFS_DIE_ON_ERR);
@@@ -1156,7 -1157,7 +1157,7 @@@ int cmd_clone(int argc, const char **ar
                        }
  
                if (!is_local && !complete_refs_before_fetch)
 -                      transport_fetch_refs(transport, mapped_refs);
 +                      transport_fetch_refs(transport, mapped_refs, NULL);
  
                remote_head = find_ref_by_name(refs, "HEAD");
                remote_head_points_at =
        if (is_local)
                clone_local(path, git_dir);
        else if (refs && complete_refs_before_fetch)
 -              transport_fetch_refs(transport, mapped_refs);
 +              transport_fetch_refs(transport, mapped_refs, NULL);
  
        update_remote_refs(refs, mapped_refs, remote_head_points_at,
                           branch_top.buf, reflog_msg.buf, transport,
 -                         !is_local && !filter_options.choice);
 +                         !is_local);
  
        update_head(our_head_points_at, remote_head, reflog_msg.buf);
  
diff --combined builtin/fetch.c
index ac06f6a5765d2f630116ab588c0e34eb2f0e4db4,f5d960baecf6c901ca656370308ebebd8dbcdb76..c3c58a545349e33d73aa9f65c60f414a06c06ee4
@@@ -94,6 -94,19 +94,6 @@@ static int git_fetch_config(const char 
        return git_default_config(k, v, cb);
  }
  
 -static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
 -{
 -      if (!strcmp(var, "submodule.fetchjobs")) {
 -              max_children = parse_submodule_fetchjobs(var, value);
 -              return 0;
 -      } else if (!strcmp(var, "fetch.recursesubmodules")) {
 -              recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
 -              return 0;
 -      }
 -
 -      return 0;
 -}
 -
  static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
  {
        /*
@@@ -242,9 -255,9 +242,9 @@@ static int will_fetch(struct ref **head
        return 0;
  }
  
 -static void find_non_local_tags(struct transport *transport,
 -                      struct ref **head,
 -                      struct ref ***tail)
 +static void find_non_local_tags(const struct ref *refs,
 +                              struct ref **head,
 +                              struct ref ***tail)
  {
        struct string_list existing_refs = STRING_LIST_INIT_DUP;
        struct string_list remote_refs = STRING_LIST_INIT_NODUP;
        struct string_list_item *item = NULL;
  
        for_each_ref(add_existing, &existing_refs);
 -      for (ref = transport_get_remote_refs(transport, NULL); ref; ref = ref->next) {
 +      for (ref = refs; ref; ref = ref->next) {
                if (!starts_with(ref->name, "refs/tags/"))
                        continue;
  
        string_list_clear(&remote_refs, 0);
  }
  
 -static struct ref *get_ref_map(struct transport *transport,
 +static struct ref *get_ref_map(struct remote *remote,
 +                             const struct ref *remote_refs,
                               struct refspec *rs,
                               int tags, int *autotags)
  {
        struct ref *rm;
        struct ref *ref_map = NULL;
        struct ref **tail = &ref_map;
 -      struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
  
        /* opportunistically-updated references: */
        struct ref *orefs = NULL, **oref_tail = &orefs;
  
 -      const struct ref *remote_refs;
 -
 -      if (rs->nr)
 -              refspec_ref_prefixes(rs, &ref_prefixes);
 -      else if (transport->remote && transport->remote->fetch.nr)
 -              refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
 -
 -      if (ref_prefixes.argc &&
 -          (tags == TAGS_SET || (tags == TAGS_DEFAULT && !rs->nr))) {
 -              argv_array_push(&ref_prefixes, "refs/tags/");
 -      }
 -
 -      remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
 -
 -      argv_array_clear(&ref_prefixes);
 +      struct string_list existing_refs = STRING_LIST_INIT_DUP;
  
        if (rs->nr) {
                struct refspec *fetch_refspec;
                if (refmap.nr)
                        fetch_refspec = &refmap;
                else
 -                      fetch_refspec = &transport->remote->fetch;
 +                      fetch_refspec = &remote->fetch;
  
                for (i = 0; i < fetch_refspec->nr; i++)
                        get_fetch_map(ref_map, &fetch_refspec->items[i], &oref_tail, 1);
                die("--refmap option is only meaningful with command-line refspec(s).");
        } else {
                /* Use the defaults */
 -              struct remote *remote = transport->remote;
                struct branch *branch = branch_get(NULL);
                int has_merge = branch_has_merge_config(branch);
                if (remote &&
                /* also fetch all tags */
                get_fetch_map(remote_refs, tag_refspec, &tail, 0);
        else if (tags == TAGS_DEFAULT && *autotags)
 -              find_non_local_tags(transport, &ref_map, &tail);
 +              find_non_local_tags(remote_refs, &ref_map, &tail);
  
        /* Now append any refs to be updated opportunistically: */
        *tail = orefs;
                tail = &rm->next;
        }
  
 -      return ref_remove_duplicates(ref_map);
 +      ref_map = ref_remove_duplicates(ref_map);
 +
 +      for_each_ref(add_existing, &existing_refs);
 +      for (rm = ref_map; rm; rm = rm->next) {
 +              if (rm->peer_ref) {
 +                      struct string_list_item *peer_item =
 +                              string_list_lookup(&existing_refs,
 +                                                 rm->peer_ref->name);
 +                      if (peer_item) {
 +                              struct object_id *old_oid = peer_item->util;
 +                              oidcpy(&rm->peer_ref->old_oid, old_oid);
 +                      }
 +              }
 +      }
 +      string_list_clear(&existing_refs, 1);
 +
 +      return ref_map;
  }
  
  #define STORE_REF_ERROR_OTHER 1
@@@ -672,8 -684,10 +672,10 @@@ static int update_local_ref(struct ref 
                return r;
        }
  
-       current = lookup_commit_reference_gently(&ref->old_oid, 1);
-       updated = lookup_commit_reference_gently(&ref->new_oid, 1);
+       current = lookup_commit_reference_gently(the_repository,
+                                                &ref->old_oid, 1);
+       updated = lookup_commit_reference_gently(the_repository,
+                                                &ref->new_oid, 1);
        if (!current || !updated) {
                const char *msg;
                const char *what;
@@@ -757,7 -771,7 +759,7 @@@ static int iterate_ref_map(void *cb_dat
  }
  
  static int store_updated_refs(const char *raw_url, const char *remote_name,
 -              struct ref *ref_map)
 +                            int connectivity_checked, struct ref *ref_map)
  {
        FILE *fp;
        struct commit *commit;
        else
                url = xstrdup("foreign");
  
 -      rm = ref_map;
 -      if (check_connected(iterate_ref_map, &rm, NULL)) {
 -              rc = error(_("%s did not send all necessary objects\n"), url);
 -              goto abort;
 +      if (!connectivity_checked) {
 +              rm = ref_map;
 +              if (check_connected(iterate_ref_map, &rm, NULL)) {
 +                      rc = error(_("%s did not send all necessary objects\n"), url);
 +                      goto abort;
 +              }
        }
  
        prepare_format_display(ref_map);
                                continue;
                        }
  
-                       commit = lookup_commit_reference_gently(&rm->old_oid,
+                       commit = lookup_commit_reference_gently(the_repository,
+                                                               &rm->old_oid,
                                                                1);
                        if (!commit)
                                rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
@@@ -936,32 -949,15 +939,32 @@@ static int quickfetch(struct ref *ref_m
        return check_connected(iterate_ref_map, &rm, &opt);
  }
  
 -static int fetch_refs(struct transport *transport, struct ref *ref_map)
 +static int fetch_refs(struct transport *transport, struct ref *ref_map,
 +                    struct ref **updated_remote_refs)
  {
        int ret = quickfetch(ref_map);
        if (ret)
 -              ret = transport_fetch_refs(transport, ref_map);
 +              ret = transport_fetch_refs(transport, ref_map,
 +                                         updated_remote_refs);
        if (!ret)
 -              ret |= store_updated_refs(transport->url,
 -                              transport->remote->name,
 -                              ref_map);
 +              /*
 +               * Keep the new pack's ".keep" file around to allow the caller
 +               * time to update refs to reference the new objects.
 +               */
 +              return 0;
 +      transport_unlock_pack(transport);
 +      return ret;
 +}
 +
 +/* Update local refs based on the ref values fetched from a remote */
 +static int consume_refs(struct transport *transport, struct ref *ref_map)
 +{
 +      int connectivity_checked = transport->smart_options
 +              ? transport->smart_options->connectivity_checked : 0;
 +      int ret = store_updated_refs(transport->url,
 +                                   transport->remote->name,
 +                                   connectivity_checked,
 +                                   ref_map);
        transport_unlock_pack(transport);
        return ret;
  }
@@@ -1107,8 -1103,7 +1110,8 @@@ static void backfill_tags(struct transp
        transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
        transport_set_option(transport, TRANS_OPT_DEPTH, "0");
        transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
 -      fetch_refs(transport, ref_map);
 +      if (!fetch_refs(transport, ref_map, NULL))
 +              consume_refs(transport, ref_map);
  
        if (gsecondary) {
                transport_disconnect(gsecondary);
  static int do_fetch(struct transport *transport,
                    struct refspec *rs)
  {
 -      struct string_list existing_refs = STRING_LIST_INIT_DUP;
        struct ref *ref_map;
 -      struct ref *rm;
        int autotags = (transport->remote->fetch_tags == 1);
        int retcode = 0;
 -
 -      for_each_ref(add_existing, &existing_refs);
 +      const struct ref *remote_refs;
 +      struct ref *updated_remote_refs = NULL;
 +      struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
  
        if (tags == TAGS_DEFAULT) {
                if (transport->remote->fetch_tags == 2)
                        goto cleanup;
        }
  
 -      ref_map = get_ref_map(transport, rs, tags, &autotags);
 -      if (!update_head_ok)
 -              check_not_current_branch(ref_map);
 +      if (rs->nr)
 +              refspec_ref_prefixes(rs, &ref_prefixes);
 +      else if (transport->remote && transport->remote->fetch.nr)
 +              refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
  
 -      for (rm = ref_map; rm; rm = rm->next) {
 -              if (rm->peer_ref) {
 -                      struct string_list_item *peer_item =
 -                              string_list_lookup(&existing_refs,
 -                                                 rm->peer_ref->name);
 -                      if (peer_item) {
 -                              struct object_id *old_oid = peer_item->util;
 -                              oidcpy(&rm->peer_ref->old_oid, old_oid);
 -                      }
 -              }
 +      if (ref_prefixes.argc &&
 +          (tags == TAGS_SET || (tags == TAGS_DEFAULT && !rs->nr))) {
 +              argv_array_push(&ref_prefixes, "refs/tags/");
        }
  
 +      remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
 +      argv_array_clear(&ref_prefixes);
 +
 +      ref_map = get_ref_map(transport->remote, remote_refs, rs,
 +                            tags, &autotags);
 +      if (!update_head_ok)
 +              check_not_current_branch(ref_map);
 +
        if (tags == TAGS_DEFAULT && autotags)
                transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
        if (prune) {
                                   transport->url);
                }
        }
 -      if (fetch_refs(transport, ref_map)) {
 +
 +      if (fetch_refs(transport, ref_map, &updated_remote_refs)) {
 +              free_refs(ref_map);
 +              retcode = 1;
 +              goto cleanup;
 +      }
 +      if (updated_remote_refs) {
 +              /*
 +               * Regenerate ref_map using the updated remote refs.  This is
 +               * to account for additional information which may be provided
 +               * by the transport (e.g. shallow info).
 +               */
 +              free_refs(ref_map);
 +              ref_map = get_ref_map(transport->remote, updated_remote_refs, rs,
 +                                    tags, &autotags);
 +              free_refs(updated_remote_refs);
 +      }
 +      if (consume_refs(transport, ref_map)) {
                free_refs(ref_map);
                retcode = 1;
                goto cleanup;
        if (tags == TAGS_DEFAULT && autotags) {
                struct ref **tail = &ref_map;
                ref_map = NULL;
 -              find_non_local_tags(transport, &ref_map, &tail);
 +              find_non_local_tags(remote_refs, &ref_map, &tail);
                if (ref_map)
                        backfill_tags(transport, ref_map);
                free_refs(ref_map);
        }
  
   cleanup:
 -      string_list_clear(&existing_refs, 1);
        return retcode;
  }
  
@@@ -1459,7 -1437,7 +1462,7 @@@ int cmd_fetch(int argc, const char **ar
        for (i = 1; i < argc; i++)
                strbuf_addf(&default_rla, " %s", argv[i]);
  
 -      config_from_gitmodules(gitmodules_fetch_config, NULL);
 +      fetch_config_from_gitmodules(&max_children, &recurse_submodules);
        git_config(git_fetch_config, NULL);
  
        argc = parse_options(argc, argv, prefix,
diff --combined builtin/fmt-merge-msg.c
index 8ccb14b87071d4d7285235738bc639051124a550,ff165c0fcd209f1bab596905a61bdfa6b491208a..ca9206fbbe1c2d9da706111a8de31396b3bf5909
@@@ -11,6 -11,7 +11,7 @@@
  #include "branch.h"
  #include "fmt-merge-msg.h"
  #include "gpg-interface.h"
+ #include "repository.h"
  
  static const char * const fmt_merge_msg_usage[] = {
        N_("git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"),
@@@ -109,15 -110,14 +110,15 @@@ static int handle_line(char *line, stru
        struct string_list_item *item;
        int pulling_head = 0;
        struct object_id oid;
 +      const unsigned hexsz = the_hash_algo->hexsz;
  
 -      if (len < GIT_SHA1_HEXSZ + 3 || line[GIT_SHA1_HEXSZ] != '\t')
 +      if (len < hexsz + 3 || line[hexsz] != '\t')
                return 1;
  
 -      if (starts_with(line + GIT_SHA1_HEXSZ + 1, "not-for-merge"))
 +      if (starts_with(line + hexsz + 1, "not-for-merge"))
                return 0;
  
 -      if (line[GIT_SHA1_HEXSZ + 1] != '\t')
 +      if (line[hexsz + 1] != '\t')
                return 2;
  
        i = get_oid_hex(line, &oid);
  
        if (line[len - 1] == '\n')
                line[len - 1] = 0;
 -      line += GIT_SHA1_HEXSZ + 2;
 +      line += hexsz + 2;
  
        /*
         * At this point, line points at the beginning of comment e.g.
@@@ -344,7 -344,9 +345,9 @@@ static void shortlog(const char *name
        const struct object_id *oid = &origin_data->oid;
        int limit = opts->shortlog_len;
  
-       branch = deref_tag(parse_object(oid), oid_to_hex(oid), the_hash_algo->hexsz);
+       branch = deref_tag(the_repository, parse_object(the_repository, oid),
+                          oid_to_hex(oid),
 -                         GIT_SHA1_HEXSZ);
++                         the_hash_algo->hexsz);
        if (!branch || branch->type != OBJ_COMMIT)
                return;
  
@@@ -547,7 -549,6 +550,7 @@@ static void find_merge_parents(struct m
                int len;
                char *p = in->buf + pos;
                char *newline = strchr(p, '\n');
 +              const char *q;
                struct object_id oid;
                struct commit *parent;
                struct object *obj;
                len = newline ? newline - p : strlen(p);
                pos += len + !!newline;
  
 -              if (len < GIT_SHA1_HEXSZ + 3 ||
 -                  get_oid_hex(p, &oid) ||
 -                  p[GIT_SHA1_HEXSZ] != '\t' ||
 -                  p[GIT_SHA1_HEXSZ + 1] != '\t')
 +              if (parse_oid_hex(p, &oid, &q) ||
 +                  q[0] != '\t' ||
 +                  q[1] != '\t')
                        continue; /* skip not-for-merge */
                /*
                 * Do not use get_merge_parent() here; we do not have
                 * "name" here and we do not want to contaminate its
                 * util field yet.
                 */
-               obj = parse_object(&oid);
+               obj = parse_object(the_repository, &oid);
                parent = (struct commit *)peel_to_type(NULL, 0, obj, OBJ_COMMIT);
                if (!parent)
                        continue;
                commit_list_insert(parent, &parents);
                add_merge_parent(result, &obj->oid, &parent->object.oid);
        }
-       head_commit = lookup_commit(head);
+       head_commit = lookup_commit(the_repository, head);
        if (head_commit)
                commit_list_insert(head_commit, &parents);
        reduce_heads_replace(&parents);
diff --combined builtin/fsck.c
index eca7900ee08841ec3efdaf24555a76e426fbbf28,263191942d4c6f785961fd0ed36cbac9b5748206..ea5e2a03e6c882c674dbef9b3f6e99e93b552f64
@@@ -18,7 -18,6 +18,7 @@@
  #include "decorate.h"
  #include "packfile.h"
  #include "object-store.h"
 +#include "run-command.h"
  
  #define REACHABLE 0x0001
  #define SEEN      0x0002
@@@ -48,7 -47,6 +48,7 @@@ static int name_objects
  #define ERROR_REACHABLE 02
  #define ERROR_PACK 04
  #define ERROR_REFS 010
 +#define ERROR_COMMIT_GRAPH 020
  
  static const char *describe_object(struct object *obj)
  {
@@@ -72,7 -70,7 +72,7 @@@ static const char *printable_type(struc
                enum object_type type = oid_object_info(the_repository,
                                                        &obj->oid, NULL);
                if (type > 0)
-                       object_as_type(obj, type, 0);
+                       object_as_type(the_repository, obj, type, 0);
        }
  
        ret = type_name(obj->type);
@@@ -394,7 -392,8 +394,8 @@@ static int fsck_obj_buffer(const struc
         * verify_packfile(), data_valid variable for details.
         */
        struct object *obj;
-       obj = parse_object_buffer(oid, type, size, buffer, eaten);
+       obj = parse_object_buffer(the_repository, oid, type, size, buffer,
+                                 eaten);
        if (!obj) {
                errors_found |= ERROR_OBJECT;
                return error("%s: object corrupt or missing", oid_to_hex(oid));
@@@ -412,7 -411,7 +413,7 @@@ static void fsck_handle_reflog_oid(cons
        struct object *obj;
  
        if (!is_null_oid(oid)) {
-               obj = lookup_object(oid->hash);
+               obj = lookup_object(the_repository, oid->hash);
                if (obj && (obj->flags & HAS_OBJ)) {
                        if (timestamp && name_objects)
                                add_decoration(fsck_walk_options.object_names,
@@@ -454,7 -453,7 +455,7 @@@ static int fsck_handle_ref(const char *
  {
        struct object *obj;
  
-       obj = parse_object(oid);
+       obj = parse_object(the_repository, oid);
        if (!obj) {
                if (is_promisor_object(oid)) {
                        /*
@@@ -527,7 -526,9 +528,9 @@@ static int fsck_loose(const struct obje
        if (!contents && type != OBJ_BLOB)
                BUG("read_loose_object streamed a non-blob");
  
-       obj = parse_object_buffer(oid, type, size, contents, &eaten);
+       obj = parse_object_buffer(the_repository, oid, type, size,
+                                 contents, &eaten);
        if (!obj) {
                errors_found |= ERROR_OBJECT;
                error("%s: object could not be parsed: %s",
@@@ -616,7 -617,7 +619,7 @@@ static int fsck_cache_tree(struct cache
                fprintf(stderr, "Checking cache tree\n");
  
        if (0 <= it->entry_count) {
-               struct object *obj = parse_object(&it->oid);
+               struct object *obj = parse_object(the_repository, &it->oid);
                if (!obj) {
                        error("%s: invalid sha1 pointer in cache-tree",
                              oid_to_hex(&it->oid));
@@@ -765,7 -766,8 +768,8 @@@ int cmd_fsck(int argc, const char **arg
                const char *arg = argv[i];
                struct object_id oid;
                if (!get_oid(arg, &oid)) {
-                       struct object *obj = lookup_object(oid.hash);
+                       struct object *obj = lookup_object(the_repository,
+                                                          oid.hash);
  
                        if (!obj || !(obj->flags & HAS_OBJ)) {
                                if (is_promisor_object(&oid))
                        mode = active_cache[i]->ce_mode;
                        if (S_ISGITLINK(mode))
                                continue;
-                       blob = lookup_blob(&active_cache[i]->oid);
+                       blob = lookup_blob(the_repository,
+                                          &active_cache[i]->oid);
                        if (!blob)
                                continue;
                        obj = &blob->object;
        }
  
        check_connectivity();
 +
 +      if (core_commit_graph) {
 +              struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
 +              const char *verify_argv[] = { "commit-graph", "verify", NULL, NULL, NULL };
 +
 +              commit_graph_verify.argv = verify_argv;
 +              commit_graph_verify.git_cmd = 1;
 +              if (run_command(&commit_graph_verify))
 +                      errors_found |= ERROR_COMMIT_GRAPH;
 +
 +              prepare_alt_odb(the_repository);
 +              for (alt =  the_repository->objects->alt_odb_list; alt; alt = alt->next) {
 +                      verify_argv[2] = "--object-dir";
 +                      verify_argv[3] = alt->path;
 +                      if (run_command(&commit_graph_verify))
 +                              errors_found |= ERROR_COMMIT_GRAPH;
 +              }
 +      }
 +
        return errors_found;
  }
diff --combined builtin/grep.c
index 61bcaf6e58d67c8bc66f6d8d260e91e7804caa5b,538a818e6dd63cd0825bb6c1b195e49bad9442b9..f9678f19e4aff52ae82ee1ff5d9842950b943f43
@@@ -647,7 -647,8 +647,8 @@@ static int grep_objects(struct grep_op
  
        for (i = 0; i < nr; i++) {
                struct object *real_obj;
-               real_obj = deref_tag(list->objects[i].item, NULL, 0);
+               real_obj = deref_tag(the_repository, list->objects[i].item,
+                                    NULL, 0);
  
                /* load the gitmodules file for this rev */
                if (recurse_submodules) {
@@@ -828,7 -829,6 +829,7 @@@ int cmd_grep(int argc, const char **arg
                            GREP_PATTERN_TYPE_PCRE),
                OPT_GROUP(""),
                OPT_BOOL('n', "line-number", &opt.linenum, N_("show line numbers")),
 +              OPT_BOOL(0, "column", &opt.columnnum, N_("show column number of first match")),
                OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1),
                OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
                OPT_NEGBIT(0, "full-name", &opt.relative,
diff --combined builtin/log.c
index 805f89d7e1552e86a8c2b990a0e213d09f91d42a,55a6286d7f4a954db80a1564f15d0db465f9b1d6..574595132af4a799da3665543d19787e670b2791
@@@ -30,6 -30,7 +30,7 @@@
  #include "gpg-interface.h"
  #include "progress.h"
  #include "commit-slab.h"
+ #include "repository.h"
  
  #define MAIL_DEFAULT_WRAP 72
  
@@@ -619,7 -620,7 +620,7 @@@ int cmd_show(int argc, const char **arg
                        rev.shown_one = 1;
                        if (ret)
                                break;
-                       o = parse_object(&t->tagged->oid);
+                       o = parse_object(the_repository, &t->tagged->oid);
                        if (!o)
                                ret = error(_("Could not read object %s"),
                                            oid_to_hex(&t->tagged->oid));
@@@ -906,8 -907,8 +907,8 @@@ static void get_patch_ids(struct rev_in
        o2 = rev->pending.objects[1].item;
        flags1 = o1->flags;
        flags2 = o2->flags;
-       c1 = lookup_commit_reference(&o1->oid);
-       c2 = lookup_commit_reference(&o2->oid);
+       c1 = lookup_commit_reference(the_repository, &o1->oid);
+       c2 = lookup_commit_reference(the_repository, &o2->oid);
  
        if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
                die(_("Not a range."));
@@@ -1756,7 -1757,6 +1757,7 @@@ int cmd_format_patch(int argc, const ch
        if (base_commit || base_auto) {
                struct commit *base = get_base_commit(base_commit, list, nr);
                reset_revision_walk();
 +              clear_object_flags(UNINTERESTING);
                prepare_bases(&bases, base, list, nr);
        }
  
@@@ -1864,7 -1864,8 +1865,8 @@@ static int add_pending_commit(const cha
  {
        struct object_id oid;
        if (get_oid(arg, &oid) == 0) {
-               struct commit *commit = lookup_commit_reference(&oid);
+               struct commit *commit = lookup_commit_reference(the_repository,
+                                                               &oid);
                if (commit) {
                        commit->object.flags |= flags;
                        add_pending_object(revs, &commit->object, arg);
diff --combined builtin/pack-objects.c
index ebc8cefb53f4a1fde99eff8d6f19c8df0cec0ede,6565c800ac3865f9325c21bf28707cce0506195e..4391504a91367bc8c4897e66921fe9a91263f0d0
@@@ -2474,7 -2474,7 +2474,7 @@@ static void add_tag_chain(const struct 
        if (packlist_find(&to_pack, oid->hash, NULL))
                return;
  
-       tag = lookup_tag(oid);
+       tag = lookup_tag(the_repository, oid);
        while (1) {
                if (!tag || parse_tag(tag) || !tag->tagged)
                        die("unable to pack objects reachable from tag %s",
@@@ -2929,13 -2929,11 +2929,13 @@@ static int pack_options_allow_reuse(voi
  
  static int get_object_list_from_bitmap(struct rev_info *revs)
  {
 -      if (prepare_bitmap_walk(revs) < 0)
 +      struct bitmap_index *bitmap_git;
 +      if (!(bitmap_git = prepare_bitmap_walk(revs)))
                return -1;
  
        if (pack_options_allow_reuse() &&
            !reuse_partial_packfile_from_bitmap(
 +                      bitmap_git,
                        &reuse_packfile,
                        &reuse_packfile_objects,
                        &reuse_packfile_offset)) {
                display_progress(progress_state, nr_result);
        }
  
 -      traverse_bitmap_commit_list(&add_object_entry_from_bitmap);
 +      traverse_bitmap_commit_list(bitmap_git, &add_object_entry_from_bitmap);
 +      free_bitmap_index(bitmap_git);
        return 0;
  }
  
diff --combined builtin/receive-pack.c
index f1c5d079f9fc38513e06fd303e826928d529d1b6,400d31c18ccd97a896f686c05a646147aa07ca2c..c17ce94e12ee34c5b822b0e09fcd6d7264e759ad
@@@ -630,6 -630,8 +630,6 @@@ static void prepare_push_cert_sha1(stru
                return;
  
        if (!already_done) {
 -              struct strbuf gpg_output = STRBUF_INIT;
 -              struct strbuf gpg_status = STRBUF_INIT;
                int bogs /* beginning_of_gpg_sig */;
  
                already_done = 1;
                        oidclr(&push_cert_oid);
  
                memset(&sigcheck, '\0', sizeof(sigcheck));
 -              sigcheck.result = 'N';
  
                bogs = parse_signature(push_cert.buf, push_cert.len);
 -              if (verify_signed_buffer(push_cert.buf, bogs,
 -                                       push_cert.buf + bogs, push_cert.len - bogs,
 -                                       &gpg_output, &gpg_status) < 0) {
 -                      ; /* error running gpg */
 -              } else {
 -                      sigcheck.payload = push_cert.buf;
 -                      sigcheck.gpg_output = gpg_output.buf;
 -                      sigcheck.gpg_status = gpg_status.buf;
 -                      parse_gpg_output(&sigcheck);
 -              }
 +              check_signature(push_cert.buf, bogs, push_cert.buf + bogs,
 +                              push_cert.len - bogs, &sigcheck);
  
 -              strbuf_release(&gpg_output);
 -              strbuf_release(&gpg_status);
                nonce_status = check_nonce(push_cert.buf, bogs);
        }
        if (!is_null_oid(&push_cert_oid)) {
@@@ -1095,8 -1108,8 +1095,8 @@@ static const char *update(struct comman
                struct object *old_object, *new_object;
                struct commit *old_commit, *new_commit;
  
-               old_object = parse_object(old_oid);
-               new_object = parse_object(new_oid);
+               old_object = parse_object(the_repository, old_oid);
+               new_object = parse_object(the_repository, new_oid);
  
                if (!old_object || !new_object ||
                    old_object->type != OBJ_COMMIT ||
  
        if (is_null_oid(new_oid)) {
                struct strbuf err = STRBUF_INIT;
-               if (!parse_object(old_oid)) {
+               if (!parse_object(the_repository, old_oid)) {
                        old_oid = NULL;
                        if (ref_exists(name)) {
                                rp_warning("Allowing deletion of corrupt ref.");
diff --combined builtin/rev-list.c
index 6fcb0ff6d56154b9849108028f529c09d0c3450e,cbaaae83eaed295c49608954e23f3cd62e78d55f..5b07f3f4a2cf6cd5f73f20a930934ca2277c8391
@@@ -17,7 -17,6 +17,7 @@@
  #include "reflog-walk.h"
  #include "oidset.h"
  #include "packfile.h"
 +#include "object-store.h"
  
  static const char rev_list_usage[] =
  "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@@ -240,7 -239,7 +240,7 @@@ static int finish_object(struct object 
                return 1;
        }
        if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
-               parse_object(&obj->oid);
+               parse_object(the_repository, &obj->oid);
        return 0;
  }
  
@@@ -516,21 -515,17 +516,21 @@@ int cmd_rev_list(int argc, const char *
                if (revs.count && !revs.left_right && !revs.cherry_mark) {
                        uint32_t commit_count;
                        int max_count = revs.max_count;
 -                      if (!prepare_bitmap_walk(&revs)) {
 -                              count_bitmap_commit_list(&commit_count, NULL, NULL, NULL);
 +                      struct bitmap_index *bitmap_git;
 +                      if ((bitmap_git = prepare_bitmap_walk(&revs))) {
 +                              count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL);
                                if (max_count >= 0 && max_count < commit_count)
                                        commit_count = max_count;
                                printf("%d\n", commit_count);
 +                              free_bitmap_index(bitmap_git);
                                return 0;
                        }
                } else if (revs.max_count < 0 &&
                           revs.tag_objects && revs.tree_objects && revs.blob_objects) {
 -                      if (!prepare_bitmap_walk(&revs)) {
 -                              traverse_bitmap_commit_list(&show_object_fast);
 +                      struct bitmap_index *bitmap_git;
 +                      if ((bitmap_git = prepare_bitmap_walk(&revs))) {
 +                              traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
 +                              free_bitmap_index(bitmap_git);
                                return 0;
                        }
                }
diff --combined commit-graph.c
index 212232e752a812c7707d174fcf19db5f0eb02010,7f907b4bfb2ff722e93e13ec3d03c2c4452bc8c9..41a0133ff7506131d4966bd6bdee9cf6ea7614a2
@@@ -7,12 -7,10 +7,12 @@@
  #include "packfile.h"
  #include "commit.h"
  #include "object.h"
 +#include "refs.h"
  #include "revision.h"
  #include "sha1-lookup.h"
  #include "commit-graph.h"
  #include "object-store.h"
 +#include "alloc.h"
  
  #define GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
  #define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
  
  #define GRAPH_LAST_EDGE 0x80000000
  
 +#define GRAPH_HEADER_SIZE 8
  #define GRAPH_FANOUT_SIZE (4 * 256)
  #define GRAPH_CHUNKLOOKUP_WIDTH 12
 -#define GRAPH_MIN_SIZE (5 * GRAPH_CHUNKLOOKUP_WIDTH + GRAPH_FANOUT_SIZE + \
 -                      GRAPH_OID_LEN + 8)
 +#define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * GRAPH_CHUNKLOOKUP_WIDTH \
 +                      + GRAPH_FANOUT_SIZE + GRAPH_OID_LEN)
  
  char *get_commit_graph_filename(const char *obj_dir)
  {
@@@ -244,12 -241,8 +244,12 @@@ static struct commit_list **insert_pare
  {
        struct commit *c;
        struct object_id oid;
 +
 +      if (pos >= g->num_commits)
 +              die("invalid parent position %"PRIu64, pos);
 +
        hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * pos);
-       c = lookup_commit(&oid);
+       c = lookup_commit(the_repository, &oid);
        if (!c)
                die("could not find commit %s", oid_to_hex(&oid));
        c->graph_pos = pos;
@@@ -320,7 -313,7 +320,7 @@@ static int find_commit_in_graph(struct 
        }
  }
  
 -int parse_commit_in_graph(struct commit *item)
 +static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item)
  {
        uint32_t pos;
  
                return 0;
        if (item->object.parsed)
                return 1;
 +
 +      if (find_commit_in_graph(item, g, &pos))
 +              return fill_commit_in_graph(item, g, pos);
 +
 +      return 0;
 +}
 +
 +int parse_commit_in_graph(struct commit *item)
 +{
 +      if (!core_commit_graph)
 +              return 0;
 +
        prepare_commit_graph();
 -      if (commit_graph && find_commit_in_graph(item, commit_graph, &pos))
 -              return fill_commit_in_graph(item, commit_graph, pos);
 +      if (commit_graph)
 +              return parse_commit_in_graph_one(commit_graph, item);
        return 0;
  }
  
@@@ -363,25 -344,19 +363,25 @@@ static struct tree *load_tree_for_commi
                                           GRAPH_DATA_WIDTH * (c->graph_pos);
  
        hashcpy(oid.hash, commit_data);
-       c->maybe_tree = lookup_tree(&oid);
+       c->maybe_tree = lookup_tree(the_repository, &oid);
  
        return c->maybe_tree;
  }
  
 -struct tree *get_commit_tree_in_graph(const struct commit *c)
 +static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g,
 +                                               const struct commit *c)
  {
        if (c->maybe_tree)
                return c->maybe_tree;
        if (c->graph_pos == COMMIT_NOT_FROM_GRAPH)
 -              BUG("get_commit_tree_in_graph called from non-commit-graph commit");
 +              BUG("get_commit_tree_in_graph_one called from non-commit-graph commit");
 +
 +      return load_tree_for_commit(g, (struct commit *)c);
 +}
  
 -      return load_tree_for_commit(commit_graph, (struct commit *)c);
 +struct tree *get_commit_tree_in_graph(const struct commit *c)
 +{
 +      return get_commit_tree_in_graph_one(commit_graph, c);
  }
  
  static void write_graph_chunk_fanout(struct hashfile *f,
@@@ -593,7 -568,7 +593,7 @@@ static void close_reachable(struct pack
        struct commit *commit;
  
        for (i = 0; i < oids->nr; i++) {
-               commit = lookup_commit(&oids->list[i]);
+               commit = lookup_commit(the_repository, &oids->list[i]);
                if (commit)
                        commit->object.flags |= UNINTERESTING;
        }
         * closure.
         */
        for (i = 0; i < oids->nr; i++) {
-               commit = lookup_commit(&oids->list[i]);
+               commit = lookup_commit(the_repository, &oids->list[i]);
  
                if (commit && !parse_commit(commit))
                        add_missing_parents(oids, commit);
        }
  
        for (i = 0; i < oids->nr; i++) {
-               commit = lookup_commit(&oids->list[i]);
+               commit = lookup_commit(the_repository, &oids->list[i]);
  
                if (commit)
                        commit->object.flags &= ~UNINTERESTING;
@@@ -657,28 -632,11 +657,28 @@@ static void compute_generation_numbers(
        }
  }
  
 +static int add_ref_to_list(const char *refname,
 +                         const struct object_id *oid,
 +                         int flags, void *cb_data)
 +{
 +      struct string_list *list = (struct string_list *)cb_data;
 +
 +      string_list_append(list, oid_to_hex(oid));
 +      return 0;
 +}
 +
 +void write_commit_graph_reachable(const char *obj_dir, int append)
 +{
 +      struct string_list list;
 +
 +      string_list_init(&list, 1);
 +      for_each_ref(add_ref_to_list, &list);
 +      write_commit_graph(obj_dir, NULL, &list, append);
 +}
 +
  void write_commit_graph(const char *obj_dir,
 -                      const char **pack_indexes,
 -                      int nr_packs,
 -                      const char **commit_hex,
 -                      int nr_commits,
 +                      struct string_list *pack_indexes,
 +                      struct string_list *commit_hex,
                        int append)
  {
        struct packed_oid_list oids;
                int dirlen;
                strbuf_addf(&packname, "%s/pack/", obj_dir);
                dirlen = packname.len;
 -              for (i = 0; i < nr_packs; i++) {
 +              for (i = 0; i < pack_indexes->nr; i++) {
                        struct packed_git *p;
                        strbuf_setlen(&packname, dirlen);
 -                      strbuf_addstr(&packname, pack_indexes[i]);
 +                      strbuf_addstr(&packname, pack_indexes->items[i].string);
                        p = add_packed_git(packname.buf, packname.len, 1);
                        if (!p)
                                die("error adding pack %s", packname.buf);
        }
  
        if (commit_hex) {
 -              for (i = 0; i < nr_commits; i++) {
 +              for (i = 0; i < commit_hex->nr; i++) {
                        const char *end;
                        struct object_id oid;
                        struct commit *result;
  
 -                      if (commit_hex[i] && parse_oid_hex(commit_hex[i], &oid, &end))
 +                      if (commit_hex->items[i].string &&
 +                          parse_oid_hex(commit_hex->items[i].string, &oid, &end))
                                continue;
  
-                       result = lookup_commit_reference_gently(&oid, 1);
+                       result = lookup_commit_reference_gently(the_repository, &oid, 1);
  
                        if (result) {
                                ALLOC_GROW(oids.list, oids.nr + 1, oids.alloc);
                if (i > 0 && !oidcmp(&oids.list[i-1], &oids.list[i]))
                        continue;
  
-               commits.list[commits.nr] = lookup_commit(&oids.list[i]);
+               commits.list[commits.nr] = lookup_commit(the_repository, &oids.list[i]);
                parse_commit(commits.list[commits.nr]);
  
                for (parent = commits.list[commits.nr]->parents;
        oids.alloc = 0;
        oids.nr = 0;
  }
-               graph_commit = lookup_commit(&cur_oid);
 +
 +#define VERIFY_COMMIT_GRAPH_ERROR_HASH 2
 +static int verify_commit_graph_error;
 +
 +static void graph_report(const char *fmt, ...)
 +{
 +      va_list ap;
 +
 +      verify_commit_graph_error = 1;
 +      va_start(ap, fmt);
 +      vfprintf(stderr, fmt, ap);
 +      fprintf(stderr, "\n");
 +      va_end(ap);
 +}
 +
 +#define GENERATION_ZERO_EXISTS 1
 +#define GENERATION_NUMBER_EXISTS 2
 +
 +int verify_commit_graph(struct repository *r, struct commit_graph *g)
 +{
 +      uint32_t i, cur_fanout_pos = 0;
 +      struct object_id prev_oid, cur_oid, checksum;
 +      int generation_zero = 0;
 +      struct hashfile *f;
 +      int devnull;
 +
 +      if (!g) {
 +              graph_report("no commit-graph file loaded");
 +              return 1;
 +      }
 +
 +      verify_commit_graph_error = 0;
 +
 +      if (!g->chunk_oid_fanout)
 +              graph_report("commit-graph is missing the OID Fanout chunk");
 +      if (!g->chunk_oid_lookup)
 +              graph_report("commit-graph is missing the OID Lookup chunk");
 +      if (!g->chunk_commit_data)
 +              graph_report("commit-graph is missing the Commit Data chunk");
 +
 +      if (verify_commit_graph_error)
 +              return verify_commit_graph_error;
 +
 +      devnull = open("/dev/null", O_WRONLY);
 +      f = hashfd(devnull, NULL);
 +      hashwrite(f, g->data, g->data_len - g->hash_len);
 +      finalize_hashfile(f, checksum.hash, CSUM_CLOSE);
 +      if (hashcmp(checksum.hash, g->data + g->data_len - g->hash_len)) {
 +              graph_report(_("the commit-graph file has incorrect checksum and is likely corrupt"));
 +              verify_commit_graph_error = VERIFY_COMMIT_GRAPH_ERROR_HASH;
 +      }
 +
 +      for (i = 0; i < g->num_commits; i++) {
 +              struct commit *graph_commit;
 +
 +              hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
 +
 +              if (i && oidcmp(&prev_oid, &cur_oid) >= 0)
 +                      graph_report("commit-graph has incorrect OID order: %s then %s",
 +                                   oid_to_hex(&prev_oid),
 +                                   oid_to_hex(&cur_oid));
 +
 +              oidcpy(&prev_oid, &cur_oid);
 +
 +              while (cur_oid.hash[0] > cur_fanout_pos) {
 +                      uint32_t fanout_value = get_be32(g->chunk_oid_fanout + cur_fanout_pos);
 +
 +                      if (i != fanout_value)
 +                              graph_report("commit-graph has incorrect fanout value: fanout[%d] = %u != %u",
 +                                           cur_fanout_pos, fanout_value, i);
 +                      cur_fanout_pos++;
 +              }
 +
-               graph_commit = lookup_commit(&cur_oid);
++              graph_commit = lookup_commit(r, &cur_oid);
 +              if (!parse_commit_in_graph_one(g, graph_commit))
 +                      graph_report("failed to parse %s from commit-graph",
 +                                   oid_to_hex(&cur_oid));
 +      }
 +
 +      while (cur_fanout_pos < 256) {
 +              uint32_t fanout_value = get_be32(g->chunk_oid_fanout + cur_fanout_pos);
 +
 +              if (g->num_commits != fanout_value)
 +                      graph_report("commit-graph has incorrect fanout value: fanout[%d] = %u != %u",
 +                                   cur_fanout_pos, fanout_value, i);
 +
 +              cur_fanout_pos++;
 +      }
 +
 +      if (verify_commit_graph_error & ~VERIFY_COMMIT_GRAPH_ERROR_HASH)
 +              return verify_commit_graph_error;
 +
 +      for (i = 0; i < g->num_commits; i++) {
 +              struct commit *graph_commit, *odb_commit;
 +              struct commit_list *graph_parents, *odb_parents;
 +              uint32_t max_generation = 0;
 +
 +              hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
 +
++              graph_commit = lookup_commit(r, &cur_oid);
 +              odb_commit = (struct commit *)create_object(r, cur_oid.hash, alloc_commit_node(r));
 +              if (parse_commit_internal(odb_commit, 0, 0)) {
 +                      graph_report("failed to parse %s from object database",
 +                                   oid_to_hex(&cur_oid));
 +                      continue;
 +              }
 +
 +              if (oidcmp(&get_commit_tree_in_graph_one(g, graph_commit)->object.oid,
 +                         get_commit_tree_oid(odb_commit)))
 +                      graph_report("root tree OID for commit %s in commit-graph is %s != %s",
 +                                   oid_to_hex(&cur_oid),
 +                                   oid_to_hex(get_commit_tree_oid(graph_commit)),
 +                                   oid_to_hex(get_commit_tree_oid(odb_commit)));
 +
 +              graph_parents = graph_commit->parents;
 +              odb_parents = odb_commit->parents;
 +
 +              while (graph_parents) {
 +                      if (odb_parents == NULL) {
 +                              graph_report("commit-graph parent list for commit %s is too long",
 +                                           oid_to_hex(&cur_oid));
 +                              break;
 +                      }
 +
 +                      if (oidcmp(&graph_parents->item->object.oid, &odb_parents->item->object.oid))
 +                              graph_report("commit-graph parent for %s is %s != %s",
 +                                           oid_to_hex(&cur_oid),
 +                                           oid_to_hex(&graph_parents->item->object.oid),
 +                                           oid_to_hex(&odb_parents->item->object.oid));
 +
 +                      if (graph_parents->item->generation > max_generation)
 +                              max_generation = graph_parents->item->generation;
 +
 +                      graph_parents = graph_parents->next;
 +                      odb_parents = odb_parents->next;
 +              }
 +
 +              if (odb_parents != NULL)
 +                      graph_report("commit-graph parent list for commit %s terminates early",
 +                                   oid_to_hex(&cur_oid));
 +
 +              if (!graph_commit->generation) {
 +                      if (generation_zero == GENERATION_NUMBER_EXISTS)
 +                              graph_report("commit-graph has generation number zero for commit %s, but non-zero elsewhere",
 +                                           oid_to_hex(&cur_oid));
 +                      generation_zero = GENERATION_ZERO_EXISTS;
 +              } else if (generation_zero == GENERATION_ZERO_EXISTS)
 +                      graph_report("commit-graph has non-zero generation number for commit %s, but zero elsewhere",
 +                                   oid_to_hex(&cur_oid));
 +
 +              if (generation_zero == GENERATION_ZERO_EXISTS)
 +                      continue;
 +
 +              /*
 +               * If one of our parents has generation GENERATION_NUMBER_MAX, then
 +               * our generation is also GENERATION_NUMBER_MAX. Decrement to avoid
 +               * extra logic in the following condition.
 +               */
 +              if (max_generation == GENERATION_NUMBER_MAX)
 +                      max_generation--;
 +
 +              if (graph_commit->generation != max_generation + 1)
 +                      graph_report("commit-graph generation for commit %s is %u != %u",
 +                                   oid_to_hex(&cur_oid),
 +                                   graph_commit->generation,
 +                                   max_generation + 1);
 +
 +              if (graph_commit->date != odb_commit->date)
 +                      graph_report("commit date for commit %s in commit-graph is %"PRItime" != %"PRItime,
 +                                   oid_to_hex(&cur_oid),
 +                                   graph_commit->date,
 +                                   odb_commit->date);
 +      }
 +
 +      return verify_commit_graph_error;
 +}
diff --combined commit.c
index 8985c9c049bfcfb96a6d02be4496adc1ce1bb0ba,b88ced5b0265f705ad1dbd0c5b8dfb8eed6427a7..add310d4231d4cc71068b64827dc041aae0bb011
+++ b/commit.c
@@@ -24,24 -24,26 +24,26 @@@ int save_commit_buffer = 1
  
  const char *commit_type = "commit";
  
- struct commit *lookup_commit_reference_gently(const struct object_id *oid,
-                                             int quiet)
+ struct commit *lookup_commit_reference_gently(struct repository *r,
+               const struct object_id *oid, int quiet)
  {
-       struct object *obj = deref_tag(parse_object(oid), NULL, 0);
+       struct object *obj = deref_tag(r,
+                                      parse_object(r, oid),
+                                      NULL, 0);
  
        if (!obj)
                return NULL;
-       return object_as_type(obj, OBJ_COMMIT, quiet);
+       return object_as_type(r, obj, OBJ_COMMIT, quiet);
  }
  
- struct commit *lookup_commit_reference(const struct object_id *oid)
+ struct commit *lookup_commit_reference(struct repository *r, const struct object_id *oid)
  {
-       return lookup_commit_reference_gently(oid, 0);
+       return lookup_commit_reference_gently(r, oid, 0);
  }
  
  struct commit *lookup_commit_or_die(const struct object_id *oid, const char *ref_name)
  {
-       struct commit *c = lookup_commit_reference(oid);
+       struct commit *c = lookup_commit_reference(the_repository, oid);
        if (!c)
                die(_("could not parse %s"), ref_name);
        if (oidcmp(oid, &c->object.oid)) {
        return c;
  }
  
- struct commit *lookup_commit(const struct object_id *oid)
+ struct commit *lookup_commit(struct repository *r, const struct object_id *oid)
  {
-       struct object *obj = lookup_object(oid->hash);
+       struct object *obj = lookup_object(r, oid->hash);
        if (!obj)
-               return create_object(the_repository, oid->hash,
-                                    alloc_commit_node(the_repository));
-       return object_as_type(obj, OBJ_COMMIT, 0);
+               return create_object(r, oid->hash,
+                                    alloc_commit_node(r));
+       return object_as_type(r, obj, OBJ_COMMIT, 0);
  }
  
  struct commit *lookup_commit_reference_by_name(const char *name)
@@@ -67,7 -69,7 +69,7 @@@
  
        if (get_oid_committish(name, &oid))
                return NULL;
-       commit = lookup_commit_reference(&oid);
+       commit = lookup_commit_reference(the_repository, &oid);
        if (parse_commit(commit))
                return NULL;
        return commit;
@@@ -259,18 -261,32 +261,32 @@@ struct commit_buffer 
        unsigned long size;
  };
  define_commit_slab(buffer_slab, struct commit_buffer);
- static struct buffer_slab buffer_slab = COMMIT_SLAB_INIT(1, buffer_slab);
  
void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
struct buffer_slab *allocate_commit_buffer_slab(void)
  {
-       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       struct buffer_slab *bs = xmalloc(sizeof(*bs));
+       init_buffer_slab(bs);
+       return bs;
+ }
+ void free_commit_buffer_slab(struct buffer_slab *bs)
+ {
+       clear_buffer_slab(bs);
+       free(bs);
+ }
+ void set_commit_buffer(struct repository *r, struct commit *commit, void *buffer, unsigned long size)
+ {
+       struct commit_buffer *v = buffer_slab_at(
+               r->parsed_objects->buffer_slab, commit);
        v->buffer = buffer;
        v->size = size;
  }
  
- const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
+ const void *get_cached_commit_buffer(struct repository *r, const struct commit *commit, unsigned long *sizep)
  {
-       struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
+       struct commit_buffer *v = buffer_slab_peek(
+               r->parsed_objects->buffer_slab, commit);
        if (!v) {
                if (sizep)
                        *sizep = 0;
  
  const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
  {
-       const void *ret = get_cached_commit_buffer(commit, sizep);
+       const void *ret = get_cached_commit_buffer(the_repository, commit, sizep);
        if (!ret) {
                enum object_type type;
                unsigned long size;
  
  void unuse_commit_buffer(const struct commit *commit, const void *buffer)
  {
-       struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
+       struct commit_buffer *v = buffer_slab_peek(
+               the_repository->parsed_objects->buffer_slab, commit);
        if (!(v && v->buffer == buffer))
                free((void *)buffer);
  }
  
  void free_commit_buffer(struct commit *commit)
  {
-       struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
+       struct commit_buffer *v = buffer_slab_peek(
+               the_repository->parsed_objects->buffer_slab, commit);
        if (v) {
                FREE_AND_NULL(v->buffer);
                v->size = 0;
@@@ -345,7 -363,8 +363,8 @@@ void release_commit_memory(struct commi
  
  const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
  {
-       struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
+       struct commit_buffer *v = buffer_slab_peek(
+               the_repository->parsed_objects->buffer_slab, commit);
        void *ret;
  
        if (!v) {
        return ret;
  }
  
- int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size, int check_graph)
+ int parse_commit_buffer(struct repository *r, struct commit *item, const void *buffer, unsigned long size, int check_graph)
  {
        const char *tail = buffer;
        const char *bufptr = buffer;
        struct object_id parent;
        struct commit_list **pptr;
        struct commit_graft *graft;
 -      const int tree_entry_len = GIT_SHA1_HEXSZ + 5;
 -      const int parent_entry_len = GIT_SHA1_HEXSZ + 7;
 +      const int tree_entry_len = the_hash_algo->hexsz + 5;
 +      const int parent_entry_len = the_hash_algo->hexsz + 7;
  
        if (item->object.parsed)
                return 0;
        if (get_oid_hex(bufptr + 5, &parent) < 0)
                return error("bad tree pointer in commit %s",
                             oid_to_hex(&item->object.oid));
-       item->maybe_tree = lookup_tree(&parent);
+       item->maybe_tree = lookup_tree(r, &parent);
        bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */
        pptr = &item->parents;
  
-       graft = lookup_commit_graft(the_repository, &item->object.oid);
+       graft = lookup_commit_graft(r, &item->object.oid);
        while (bufptr + parent_entry_len < tail && !memcmp(bufptr, "parent ", 7)) {
                struct commit *new_parent;
  
                 */
                if (graft && (graft->nr_parent < 0 || grafts_replace_parents))
                        continue;
-               new_parent = lookup_commit(&parent);
+               new_parent = lookup_commit(r, &parent);
                if (new_parent)
                        pptr = &commit_list_insert(new_parent, pptr)->next;
        }
                int i;
                struct commit *new_parent;
                for (i = 0; i < graft->nr_parent; i++) {
-                       new_parent = lookup_commit(&graft->parent[i]);
+                       new_parent = lookup_commit(r,
+                                                  &graft->parent[i]);
                        if (!new_parent)
                                continue;
                        pptr = &commit_list_insert(new_parent, pptr)->next;
        return 0;
  }
  
 -int parse_commit_gently(struct commit *item, int quiet_on_missing)
 +int parse_commit_internal(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 (parse_commit_in_graph(item))
 +      if (use_commit_graph && parse_commit_in_graph(item))
                return 0;
        buffer = read_object_file(&item->object.oid, &type, &size);
        if (!buffer)
                return error("Object %s not a commit",
                             oid_to_hex(&item->object.oid));
        }
-       ret = parse_commit_buffer(item, buffer, size, 0);
 +
+       ret = parse_commit_buffer(the_repository, item, buffer, size, 0);
        if (save_commit_buffer && !ret) {
-               set_commit_buffer(item, buffer, size);
+               set_commit_buffer(the_repository, item, buffer, size);
                return 0;
        }
        free(buffer);
        return ret;
  }
  
 +int parse_commit_gently(struct commit *item, int quiet_on_missing)
 +{
 +      return parse_commit_internal(item, quiet_on_missing, 1);
 +}
 +
  void parse_commit_or_die(struct commit *item)
  {
        if (parse_commit(item))
@@@ -1698,7 -1712,7 +1718,7 @@@ struct commit *get_merge_parent(const c
        struct object_id oid;
        if (get_oid(name, &oid))
                return NULL;
-       obj = parse_object(&oid);
+       obj = parse_object(the_repository, &oid);
        commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
        if (commit && !merge_remote_util(commit))
                set_merge_remote_desc(commit, name, obj);
diff --combined commit.h
index f089f547ed8e6244d372d23f2305434d1dcec894,8b2cf9692dec335c75074736038b4ebfe0ac822e..da0db36eba2bf16277dbb7aadcb3384e29191ecc
+++ b/commit.h
@@@ -63,9 -63,11 +63,11 @@@ enum decoration_type 
  void add_name_decoration(enum decoration_type type, const char *name, struct object *obj);
  const struct name_decoration *get_name_decoration(const struct object *obj);
  
- struct commit *lookup_commit(const struct object_id *oid);
- struct commit *lookup_commit_reference(const struct object_id *oid);
- struct commit *lookup_commit_reference_gently(const struct object_id *oid,
+ struct commit *lookup_commit(struct repository *r, const struct object_id *oid);
+ struct commit *lookup_commit_reference(struct repository *r,
+                                      const struct object_id *oid);
+ struct commit *lookup_commit_reference_gently(struct repository *r,
+                                             const struct object_id *oid,
                                              int quiet);
  struct commit *lookup_commit_reference_by_name(const char *name);
  
@@@ -76,8 -78,7 +78,8 @@@
   */
  struct commit *lookup_commit_or_die(const struct object_id *oid, const char *ref_name);
  
- int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size, int check_graph);
+ 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)
  {
  }
  void parse_commit_or_die(struct commit *item);
  
+ struct buffer_slab;
+ struct buffer_slab *allocate_commit_buffer_slab(void);
+ void free_commit_buffer_slab(struct buffer_slab *bs);
  /*
   * Associate an object buffer with the commit. The ownership of the
   * memory is handed over to the commit, and must be free()-able.
   */
- void set_commit_buffer(struct commit *, void *buffer, unsigned long size);
+ void set_commit_buffer(struct repository *r, struct commit *, void *buffer, unsigned long size);
  
  /*
   * Get any cached object buffer associated with the commit. Returns NULL
   * if none. The resulting memory should not be freed.
   */
- const void *get_cached_commit_buffer(const struct commit *, unsigned long *size);
+ const void *get_cached_commit_buffer(struct repository *, const struct commit *, unsigned long *size);
  
  /*
   * Get the commit's object contents, either from cache or by reading the object
diff --combined fast-import.c
index 12195d54d744f60c0a4e1074814559325e42085e,3ea5781029de661fb083fcd99acbae7c39c22904..89bb0c9db3de9b380aad53709d882cb04f7d054a
@@@ -1076,7 -1076,7 +1076,7 @@@ static int store_object
                return 1;
        }
  
 -      if (last && last->data.buf && last->depth < max_depth
 +      if (last && last->data.len && last->data.buf && last->depth < max_depth
                && dat->len > the_hash_algo->rawsz) {
  
                delta_count_attempts_by_type[type]++;
@@@ -1724,8 -1724,10 +1724,10 @@@ static int update_branch(struct branch 
        if (!force_update && !is_null_oid(&old_oid)) {
                struct commit *old_cmit, *new_cmit;
  
-               old_cmit = lookup_commit_reference_gently(&old_oid, 0);
-               new_cmit = lookup_commit_reference_gently(&b->oid, 0);
+               old_cmit = lookup_commit_reference_gently(the_repository,
+                                                         &old_oid, 0);
+               new_cmit = lookup_commit_reference_gently(the_repository,
+                                                         &b->oid, 0);
                if (!old_cmit || !new_cmit)
                        return error("Branch %s is missing commits.", b->name);
  
diff --combined fetch-pack.c
index 8fb67b0e31e82ed5f0daeb1dec10ca7a04e4321f,d60d83f174be139aefbbcaa8fce662b3c10d8169..5056e22e6d01751eddb17391e5cb68051a5ff9ff
  #include "connect.h"
  #include "transport.h"
  #include "version.h"
 -#include "prio-queue.h"
  #include "sha1-array.h"
  #include "oidset.h"
  #include "packfile.h"
  #include "object-store.h"
 +#include "connected.h"
 +#include "fetch-negotiator.h"
  
  static int transfer_unpack_limit = -1;
  static int fetch_unpack_limit = -1;
@@@ -38,7 -37,13 +38,7 @@@ static const char *alternate_shallow_fi
  
  /* Remember to update object flag allocation in object.h */
  #define COMPLETE      (1U << 0)
 -#define COMMON                (1U << 1)
 -#define COMMON_REF    (1U << 2)
 -#define SEEN          (1U << 3)
 -#define POPPED                (1U << 4)
 -#define ALTERNATE     (1U << 5)
 -
 -static int marked;
 +#define ALTERNATE     (1U << 1)
  
  /*
   * After sending this many "have"s if we do not get any new ACK , we
@@@ -46,7 -51,8 +46,7 @@@
   */
  #define MAX_IN_VAIN 256
  
 -static struct prio_queue rev_list = { compare_commits_by_commit_date };
 -static int non_common_revs, multi_ack, use_sideband;
 +static int multi_ack, use_sideband;
  /* Allow specifying sha1 if it is a ref tip. */
  #define ALLOW_TIP_SHA1        01
  /* Allow request of a sha1 if it is reachable from a ref (possibly hidden ref). */
@@@ -78,7 -84,7 +78,7 @@@ static void cache_one_alternate(const c
                                void *vcache)
  {
        struct alternate_object_cache *cache = vcache;
-       struct object *obj = parse_object(oid);
+       struct object *obj = parse_object(the_repository, oid);
  
        if (!obj || (obj->flags & ALTERNATE))
                return;
@@@ -88,9 -94,7 +88,9 @@@
        cache->items[cache->nr++] = obj;
  }
  
 -static void for_each_cached_alternate(void (*cb)(struct object *))
 +static void for_each_cached_alternate(struct fetch_negotiator *negotiator,
 +                                    void (*cb)(struct fetch_negotiator *,
 +                                               struct object *))
  {
        static int initialized;
        static struct alternate_object_cache cache;
        }
  
        for (i = 0; i < cache.nr; i++)
 -              cb(cache.items[i]);
 +              cb(negotiator, cache.items[i]);
  }
  
 -static void rev_list_push(struct commit *commit, int mark)
 -{
 -      if (!(commit->object.flags & mark)) {
 -              commit->object.flags |= mark;
 -
 -              if (parse_commit(commit))
 -                      return;
 -
 -              prio_queue_put(&rev_list, commit);
 -
 -              if (!(commit->object.flags & COMMON))
 -                      non_common_revs++;
 -      }
 -}
 -
 -static int rev_list_insert_ref(const char *refname, const struct object_id *oid)
 +static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
 +                             const char *refname,
 +                             const struct object_id *oid)
  {
-       struct object *o = deref_tag(parse_object(oid), refname, 0);
+       struct object *o = deref_tag(the_repository,
+                                    parse_object(the_repository, oid),
+                                    refname, 0);
  
        if (o && o->type == OBJ_COMMIT)
 -              rev_list_push((struct commit *)o, SEEN);
 +              negotiator->add_tip(negotiator, (struct commit *)o);
  
        return 0;
  }
  static int rev_list_insert_ref_oid(const char *refname, const struct object_id *oid,
                                   int flag, void *cb_data)
  {
 -      return rev_list_insert_ref(refname, oid);
 -}
 -
 -static int clear_marks(const char *refname, const struct object_id *oid,
 -                     int flag, void *cb_data)
 -{
 -      struct object *o = deref_tag(the_repository,
 -                                   parse_object(the_repository, oid),
 -                                   refname, 0);
 -
 -      if (o && o->type == OBJ_COMMIT)
 -              clear_commit_marks((struct commit *)o,
 -                                 COMMON | COMMON_REF | SEEN | POPPED);
 -      return 0;
 -}
 -
 -/*
 -   This function marks a rev and its ancestors as common.
 -   In some cases, it is desirable to mark only the ancestors (for example
 -   when only the server does not yet know that they are common).
 -*/
 -
 -static void mark_common(struct commit *commit,
 -              int ancestors_only, int dont_parse)
 -{
 -      if (commit != NULL && !(commit->object.flags & COMMON)) {
 -              struct object *o = (struct object *)commit;
 -
 -              if (!ancestors_only)
 -                      o->flags |= COMMON;
 -
 -              if (!(o->flags & SEEN))
 -                      rev_list_push(commit, SEEN);
 -              else {
 -                      struct commit_list *parents;
 -
 -                      if (!ancestors_only && !(o->flags & POPPED))
 -                              non_common_revs--;
 -                      if (!o->parsed && !dont_parse)
 -                              if (parse_commit(commit))
 -                                      return;
 -
 -                      for (parents = commit->parents;
 -                                      parents;
 -                                      parents = parents->next)
 -                              mark_common(parents->item, 0, dont_parse);
 -              }
 -      }
 -}
 -
 -/*
 -  Get the next rev to send, ignoring the common.
 -*/
 -
 -static const struct object_id *get_rev(void)
 -{
 -      struct commit *commit = NULL;
 -
 -      while (commit == NULL) {
 -              unsigned int mark;
 -              struct commit_list *parents;
 -
 -              if (rev_list.nr == 0 || non_common_revs == 0)
 -                      return NULL;
 -
 -              commit = prio_queue_get(&rev_list);
 -              parse_commit(commit);
 -              parents = commit->parents;
 -
 -              commit->object.flags |= POPPED;
 -              if (!(commit->object.flags & COMMON))
 -                      non_common_revs--;
 -
 -              if (commit->object.flags & COMMON) {
 -                      /* do not send "have", and ignore ancestors */
 -                      commit = NULL;
 -                      mark = COMMON | SEEN;
 -              } else if (commit->object.flags & COMMON_REF)
 -                      /* send "have", and ignore ancestors */
 -                      mark = COMMON | SEEN;
 -              else
 -                      /* send "have", also for its ancestors */
 -                      mark = SEEN;
 -
 -              while (parents) {
 -                      if (!(parents->item->object.flags & SEEN))
 -                              rev_list_push(parents->item, mark);
 -                      if (mark & COMMON)
 -                              mark_common(parents->item, 1, 0);
 -                      parents = parents->next;
 -              }
 -      }
 -
 -      return &commit->object.oid;
 +      return rev_list_insert_ref(cb_data, refname, oid);
  }
  
  enum ack_type {
@@@ -189,10 -301,9 +191,10 @@@ static void send_request(struct fetch_p
                write_or_die(fd, buf->buf, buf->len);
  }
  
 -static void insert_one_alternate_object(struct object *obj)
 +static void insert_one_alternate_object(struct fetch_negotiator *negotiator,
 +                                      struct object *obj)
  {
 -      rev_list_insert_ref(NULL, &obj->oid);
 +      rev_list_insert_ref(negotiator, NULL, &obj->oid);
  }
  
  #define INITIAL_FLUSH 16
@@@ -215,8 -326,7 +217,8 @@@ static int next_flush(int stateless_rpc
        return count;
  }
  
 -static int find_common(struct fetch_pack_args *args,
 +static int find_common(struct fetch_negotiator *negotiator,
 +                     struct fetch_pack_args *args,
                       int fd[2], struct object_id *result_oid,
                       struct ref *refs)
  {
  
        if (args->stateless_rpc && multi_ack == 1)
                die(_("--stateless-rpc requires multi_ack_detailed"));
 -      if (marked)
 -              for_each_ref(clear_marks, NULL);
 -      marked = 1;
  
 -      for_each_ref(rev_list_insert_ref_oid, NULL);
 -      for_each_cached_alternate(insert_one_alternate_object);
 +      for_each_ref(rev_list_insert_ref_oid, negotiator);
 +      for_each_cached_alternate(negotiator, insert_one_alternate_object);
  
        fetching = 0;
        for ( ; refs ; refs = refs->next) {
                 * interested in the case we *know* the object is
                 * reachable and we have already scanned it.
                 */
-               if (((o = lookup_object(remote->hash)) != NULL) &&
+               if (((o = lookup_object(the_repository, remote->hash)) != NULL) &&
                                (o->flags & COMPLETE)) {
                        continue;
                }
                        if (skip_prefix(line, "unshallow ", &arg)) {
                                if (get_oid_hex(arg, &oid))
                                        die(_("invalid unshallow line: %s"), line);
-                               if (!lookup_object(oid.hash))
+                               if (!lookup_object(the_repository, oid.hash))
                                        die(_("object not found: %s"), line);
                                /* make sure that it is parsed as shallow */
-                               if (!parse_object(&oid))
+                               if (!parse_object(the_repository, &oid))
                                        die(_("error in object: %s"), line);
                                if (unregister_shallow(&oid))
                                        die(_("no shallow found: %s"), line);
        retval = -1;
        if (args->no_dependents)
                goto done;
 -      while ((oid = get_rev())) {
 +      while ((oid = negotiator->next(negotiator))) {
                packet_buf_write(&req_buf, "have %s\n", oid_to_hex(oid));
                print_verbose(args, "have %s", oid_to_hex(oid));
                in_vain++;
                                case ACK_ready:
                                case ACK_continue: {
                                        struct commit *commit =
-                                               lookup_commit(result_oid);
+                                               lookup_commit(the_repository,
+                                                             result_oid);
 +                                      int was_common;
++
                                        if (!commit)
                                                die(_("invalid commit %s"), oid_to_hex(result_oid));
 +                                      was_common = negotiator->ack(negotiator, commit);
                                        if (args->stateless_rpc
                                         && ack == ACK_common
 -                                       && !(commit->object.flags & COMMON)) {
 +                                       && !was_common) {
                                                /* We need to replay the have for this object
                                                 * on the next RPC request so the peer knows
                                                 * it is in common with us.
                                        } else if (!args->stateless_rpc
                                                   || ack != ACK_common)
                                                in_vain = 0;
 -                                      mark_common(commit, 0, 1);
                                        retval = 0;
                                        got_continue = 1;
 -                                      if (ack == ACK_ready) {
 -                                              clear_prio_queue(&rev_list);
 +                                      if (ack == ACK_ready)
                                                got_ready = 1;
 -                                      }
                                        break;
                                        }
                                }
                                print_verbose(args, _("giving up"));
                                break; /* give up */
                        }
 +                      if (got_ready)
 +                              break;
                }
        }
  done:
@@@ -462,14 -575,14 +466,14 @@@ static struct commit_list *complete
  
  static int mark_complete(const struct object_id *oid)
  {
-       struct object *o = parse_object(oid);
+       struct object *o = parse_object(the_repository, oid);
  
        while (o && o->type == OBJ_TAG) {
                struct tag *t = (struct tag *) o;
                if (!t->tagged)
                        break; /* broken repository */
                o->flags |= COMPLETE;
-               o = parse_object(&t->tagged->oid);
+               o = parse_object(the_repository, &t->tagged->oid);
        }
        if (o && o->type == OBJ_COMMIT) {
                struct commit *commit = (struct commit *)o;
@@@ -600,8 -713,7 +604,8 @@@ static void filter_refs(struct fetch_pa
        *refs = newlist;
  }
  
 -static void mark_alternate_complete(struct object *obj)
 +static void mark_alternate_complete(struct fetch_negotiator *unused,
 +                                  struct object *obj)
  {
        mark_complete(&obj->oid);
  }
@@@ -628,21 -740,12 +632,21 @@@ static int add_loose_objects_to_set(con
        return 0;
  }
  
 -static int everything_local(struct fetch_pack_args *args,
 -                          struct ref **refs,
 -                          struct ref **sought, int nr_sought)
 +/*
 + * Mark recent commits available locally and reachable from a local ref as
 + * COMPLETE. If args->no_dependents is false, also mark COMPLETE remote refs as
 + * COMMON_REF (otherwise, we are not planning to participate in negotiation, and
 + * thus do not need COMMON_REF marks).
 + *
 + * The cutoff time for recency is determined by this heuristic: it is the
 + * earliest commit time of the objects in refs that are commits and that we know
 + * the commit time of.
 + */
 +static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
 +                                       struct fetch_pack_args *args,
 +                                       struct ref **refs)
  {
        struct ref *ref;
 -      int retval;
        int old_save_commit_buffer = save_commit_buffer;
        timestamp_t cutoff = 0;
        struct oidset loose_oid_set = OIDSET_INIT;
  
                if (!has_object_file_with_flags(&ref->old_oid, flags))
                        continue;
-               o = parse_object(&ref->old_oid);
+               o = parse_object(the_repository, &ref->old_oid);
                if (!o)
                        continue;
  
        if (!args->no_dependents) {
                if (!args->deepen) {
                        for_each_ref(mark_complete_oid, NULL);
 -                      for_each_cached_alternate(mark_alternate_complete);
 +                      for_each_cached_alternate(NULL, mark_alternate_complete);
                        commit_list_sort_by_date(&complete);
                        if (cutoff)
                                mark_recent_complete_commits(args, cutoff);
                 * Don't mark them common yet; the server has to be told so first.
                 */
                for (ref = *refs; ref; ref = ref->next) {
-                       struct object *o = deref_tag(lookup_object(ref->old_oid.hash),
+                       struct object *o = deref_tag(the_repository,
+                                                    lookup_object(the_repository,
+                                                    ref->old_oid.hash),
                                                     NULL, 0);
  
                        if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
                                continue;
  
 -                      if (!(o->flags & SEEN)) {
 -                              rev_list_push((struct commit *)o, COMMON_REF | SEEN);
 -
 -                              mark_common((struct commit *)o, 1, 1);
 -                      }
 +                      negotiator->known_common(negotiator,
 +                                               (struct commit *)o);
                }
        }
  
 -      filter_refs(args, refs, sought, nr_sought);
 +      save_commit_buffer = old_save_commit_buffer;
 +}
 +
 +/*
 + * Returns 1 if every object pointed to by the given remote refs is available
 + * locally and reachable from a local ref, and 0 otherwise.
 + */
 +static int everything_local(struct fetch_pack_args *args,
 +                          struct ref **refs)
 +{
 +      struct ref *ref;
 +      int retval;
  
        for (retval = 1, ref = *refs; ref ; ref = ref->next) {
                const struct object_id *remote = &ref->old_oid;
                struct object *o;
  
-               o = lookup_object(remote->hash);
+               o = lookup_object(the_repository, remote->hash);
                if (!o || !(o->flags & COMPLETE)) {
                        retval = 0;
                        print_verbose(args, "want %s (%s)", oid_to_hex(remote),
                              ref->name);
        }
  
 -      save_commit_buffer = old_save_commit_buffer;
 -
        return retval;
  }
  
@@@ -890,8 -989,6 +896,8 @@@ static struct ref *do_fetch_pack(struc
        struct object_id oid;
        const char *agent_feature;
        int agent_len;
 +      struct fetch_negotiator negotiator;
 +      fetch_negotiator_init(&negotiator);
  
        sort_ref_list(&ref, ref_compare_name);
        QSORT(sought, nr_sought, cmp_ref_by_name);
        if (!server_supports("deepen-relative") && args->deepen_relative)
                die(_("Server does not support --deepen"));
  
 -      if (everything_local(args, &ref, sought, nr_sought)) {
 +      mark_complete_and_common_ref(&negotiator, args, &ref);
 +      filter_refs(args, &ref, sought, nr_sought);
 +      if (everything_local(args, &ref)) {
                packet_flush(fd[1]);
                goto all_done;
        }
 -      if (find_common(args, fd, &oid, ref) < 0)
 +      if (find_common(&negotiator, args, fd, &oid, ref) < 0)
                if (!args->keep_pack)
                        /* When cloning, it is not unusual to have
                         * no common commit.
                die(_("git fetch-pack: fetch failed."));
  
   all_done:
 +      negotiator.release(&negotiator);
        return ref;
  }
  
@@@ -1016,10 -1110,9 +1022,10 @@@ static void add_shallow_requests(struc
  
  static void add_wants(const struct ref *wants, struct strbuf *req_buf)
  {
 +      int use_ref_in_want = server_supports_feature("fetch", "ref-in-want", 0);
 +
        for ( ; wants ; wants = wants->next) {
                const struct object_id *remote = &wants->old_oid;
 -              const char *remote_hex;
                struct object *o;
  
                /*
                 * interested in the case we *know* the object is
                 * reachable and we have already scanned it.
                 */
-               if (((o = lookup_object(remote->hash)) != NULL) &&
+               if (((o = lookup_object(the_repository, remote->hash)) != NULL) &&
                    (o->flags & COMPLETE)) {
                        continue;
                }
  
 -              remote_hex = oid_to_hex(remote);
 -              packet_buf_write(req_buf, "want %s\n", remote_hex);
 +              if (!use_ref_in_want || wants->exact_oid)
 +                      packet_buf_write(req_buf, "want %s\n", oid_to_hex(remote));
 +              else
 +                      packet_buf_write(req_buf, "want-ref %s\n", wants->name);
        }
  }
  
@@@ -1055,15 -1146,13 +1061,15 @@@ static void add_common(struct strbuf *r
        }
  }
  
 -static int add_haves(struct strbuf *req_buf, int *haves_to_send, int *in_vain)
 +static int add_haves(struct fetch_negotiator *negotiator,
 +                   struct strbuf *req_buf,
 +                   int *haves_to_send, int *in_vain)
  {
        int ret = 0;
        int haves_added = 0;
        const struct object_id *oid;
  
 -      while ((oid = get_rev())) {
 +      while ((oid = negotiator->next(negotiator))) {
                packet_buf_write(req_buf, "have %s\n", oid_to_hex(oid));
                if (++haves_added >= *haves_to_send)
                        break;
        return ret;
  }
  
 -static int send_fetch_request(int fd_out, const struct fetch_pack_args *args,
 +static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
 +                            const struct fetch_pack_args *args,
                              const struct ref *wants, struct oidset *common,
                              int *haves_to_send, int *in_vain)
  {
                add_common(&req_buf, common);
  
                /* Add initial haves */
 -              ret = add_haves(&req_buf, haves_to_send, in_vain);
 +              ret = add_haves(negotiator, &req_buf, haves_to_send, in_vain);
        }
  
        /* Send request */
@@@ -1176,9 -1264,7 +1182,9 @@@ static int process_section_header(struc
        return ret;
  }
  
 -static int process_acks(struct packet_reader *reader, struct oidset *common)
 +static int process_acks(struct fetch_negotiator *negotiator,
 +                      struct packet_reader *reader,
 +                      struct oidset *common)
  {
        /* received */
        int received_ready = 0;
                        if (!get_oid_hex(arg, &oid)) {
                                struct commit *commit;
                                oidset_insert(common, &oid);
-                               commit = lookup_commit(&oid);
+                               commit = lookup_commit(the_repository, &oid);
 -                              mark_common(commit, 0, 1);
 +                              negotiator->ack(negotiator, commit);
                        }
                        continue;
                }
  
                if (!strcmp(reader->line, "ready")) {
 -                      clear_prio_queue(&rev_list);
                        received_ready = 1;
                        continue;
                }
@@@ -1235,10 -1322,10 +1241,10 @@@ static void receive_shallow_info(struc
                if (skip_prefix(reader->line, "unshallow ", &arg)) {
                        if (get_oid_hex(arg, &oid))
                                die(_("invalid unshallow line: %s"), reader->line);
-                       if (!lookup_object(oid.hash))
+                       if (!lookup_object(the_repository, oid.hash))
                                die(_("object not found: %s"), reader->line);
                        /* make sure that it is parsed as shallow */
-                       if (!parse_object(&oid))
+                       if (!parse_object(the_repository, &oid))
                                die(_("error in object: %s"), reader->line);
                        if (unregister_shallow(&oid))
                                die(_("no shallow found: %s"), reader->line);
        args->deepen = 1;
  }
  
 +static void receive_wanted_refs(struct packet_reader *reader, struct ref *refs)
 +{
 +      process_section_header(reader, "wanted-refs", 0);
 +      while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
 +              struct object_id oid;
 +              const char *end;
 +              struct ref *r = NULL;
 +
 +              if (parse_oid_hex(reader->line, &oid, &end) || *end++ != ' ')
 +                      die("expected wanted-ref, got '%s'", reader->line);
 +
 +              for (r = refs; r; r = r->next) {
 +                      if (!strcmp(end, r->name)) {
 +                              oidcpy(&r->old_oid, &oid);
 +                              break;
 +                      }
 +              }
 +
 +              if (!r)
 +                      die("unexpected wanted-ref: '%s'", reader->line);
 +      }
 +
 +      if (reader->status != PACKET_READ_DELIM)
 +              die("error processing wanted refs: %d", reader->status);
 +}
 +
  enum fetch_state {
        FETCH_CHECK_LOCAL = 0,
        FETCH_SEND_REQUEST,
@@@ -1301,8 -1362,6 +1307,8 @@@ static struct ref *do_fetch_pack_v2(str
        struct packet_reader reader;
        int in_vain = 0;
        int haves_to_send = INITIAL_FLUSH;
 +      struct fetch_negotiator negotiator;
 +      fetch_negotiator_init(&negotiator);
        packet_reader_init(&reader, fd[0], NULL, 0,
                           PACKET_READ_CHOMP_NEWLINE);
  
                        if (args->depth > 0 || args->deepen_since || args->deepen_not)
                                args->deepen = 1;
  
 -                      if (marked)
 -                              for_each_ref(clear_marks, NULL);
 -                      marked = 1;
 -
 -                      for_each_ref(rev_list_insert_ref_oid, NULL);
 -                      for_each_cached_alternate(insert_one_alternate_object);
 -
                        /* Filter 'ref' by 'sought' and those that aren't local */
 -                      if (everything_local(args, &ref, sought, nr_sought))
 +                      mark_complete_and_common_ref(&negotiator, args, &ref);
 +                      filter_refs(args, &ref, sought, nr_sought);
 +                      if (everything_local(args, &ref))
                                state = FETCH_DONE;
                        else
                                state = FETCH_SEND_REQUEST;
 +
 +                      for_each_ref(rev_list_insert_ref_oid, &negotiator);
 +                      for_each_cached_alternate(&negotiator,
 +                                                insert_one_alternate_object);
                        break;
                case FETCH_SEND_REQUEST:
 -                      if (send_fetch_request(fd[1], args, ref, &common,
 +                      if (send_fetch_request(&negotiator, fd[1], args, ref,
 +                                             &common,
                                               &haves_to_send, &in_vain))
                                state = FETCH_GET_PACK;
                        else
                        break;
                case FETCH_PROCESS_ACKS:
                        /* Process ACKs/NAKs */
 -                      switch (process_acks(&reader, &common)) {
 +                      switch (process_acks(&negotiator, &reader, &common)) {
                        case 2:
                                state = FETCH_GET_PACK;
                                break;
                        if (process_section_header(&reader, "shallow-info", 1))
                                receive_shallow_info(args, &reader);
  
 +                      if (process_section_header(&reader, "wanted-refs", 1))
 +                              receive_wanted_refs(&reader, ref);
 +
                        /* get the pack */
                        process_section_header(&reader, "packfile", 0);
                        if (get_pack(args, fd, pack_lockfile))
                }
        }
  
 +      negotiator.release(&negotiator);
        oidset_clear(&common);
        return ref;
  }
@@@ -1423,13 -1478,12 +1429,13 @@@ static int remove_duplicates_in_refs(st
  }
  
  static void update_shallow(struct fetch_pack_args *args,
 -                         struct ref **sought, int nr_sought,
 +                         struct ref *refs,
                           struct shallow_info *si)
  {
        struct oid_array ref = OID_ARRAY_INIT;
        int *status;
        int i;
 +      struct ref *r;
  
        if (args->deepen && alternate_shallow_file) {
                if (*alternate_shallow_file == '\0') { /* --unshallow */
        remove_nonexistent_theirs_shallow(si);
        if (!si->nr_ours && !si->nr_theirs)
                return;
 -      for (i = 0; i < nr_sought; i++)
 -              oid_array_append(&ref, &sought[i]->old_oid);
 +      for (r = refs; r; r = r->next)
 +              oid_array_append(&ref, &r->old_oid);
        si->ref = &ref;
  
        if (args->update_shallow) {
         * remote is also shallow, check what ref is safe to update
         * without updating .git/shallow
         */
 -      status = xcalloc(nr_sought, sizeof(*status));
 +      status = xcalloc(ref.nr, sizeof(*status));
        assign_shallow_commits_to_refs(si, NULL, status);
        if (si->nr_ours || si->nr_theirs) {
 -              for (i = 0; i < nr_sought; i++)
 +              for (r = refs, i = 0; r; r = r->next, i++)
                        if (status[i])
 -                              sought[i]->status = REF_STATUS_REJECT_SHALLOW;
 +                              r->status = REF_STATUS_REJECT_SHALLOW;
        }
        free(status);
        oid_array_clear(&ref);
  }
  
 +static int iterate_ref_map(void *cb_data, struct object_id *oid)
 +{
 +      struct ref **rm = cb_data;
 +      struct ref *ref = *rm;
 +
 +      if (!ref)
 +              return -1; /* end of the list */
 +      *rm = ref->next;
 +      oidcpy(oid, &ref->old_oid);
 +      return 0;
 +}
 +
  struct ref *fetch_pack(struct fetch_pack_args *args,
                       int fd[], struct child_process *conn,
                       const struct ref *ref,
                ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
                                        &si, pack_lockfile);
        reprepare_packed_git(the_repository);
 -      update_shallow(args, sought, nr_sought, &si);
 +
 +      if (!args->cloning && args->deepen) {
 +              struct check_connected_options opt = CHECK_CONNECTED_INIT;
 +              struct ref *iterator = ref_cpy;
 +              opt.shallow_file = alternate_shallow_file;
 +              if (args->deepen)
 +                      opt.is_deepening_fetch = 1;
 +              if (check_connected(iterate_ref_map, &iterator, &opt)) {
 +                      error(_("remote did not send all necessary objects"));
 +                      free_refs(ref_cpy);
 +                      ref_cpy = NULL;
 +                      rollback_lock_file(&shallow_lock);
 +                      goto cleanup;
 +              }
 +              args->connectivity_checked = 1;
 +      }
 +
 +      update_shallow(args, ref_cpy, &si);
 +cleanup:
        clear_shallow_info(&si);
        return ref_cpy;
  }
diff --combined fsck.c
index cabca15b1f0ed5bdb8fe1a5d5439516264a8f9c8,93459798bcb2144081b829c3a860b294ba5a3be3..a0cee0be590020e4ff4b42da86c322ba4d0010ae
--- 1/fsck.c
--- 2/fsck.c
+++ b/fsck.c
@@@ -1,5 -1,6 +1,6 @@@
  #include "cache.h"
  #include "object-store.h"
+ #include "repository.h"
  #include "object.h"
  #include "blob.h"
  #include "tree.h"
@@@ -63,7 -64,7 +64,7 @@@ static struct oidset gitmodules_done = 
        FUNC(ZERO_PADDED_DATE, ERROR) \
        FUNC(GITMODULES_MISSING, ERROR) \
        FUNC(GITMODULES_BLOB, ERROR) \
 -      FUNC(GITMODULES_PARSE, ERROR) \
 +      FUNC(GITMODULES_LARGE, ERROR) \
        FUNC(GITMODULES_NAME, ERROR) \
        FUNC(GITMODULES_SYMLINK, ERROR) \
        /* warnings */ \
@@@ -77,7 -78,6 +78,7 @@@
        FUNC(ZERO_PADDED_FILEMODE, WARN) \
        FUNC(NUL_IN_COMMIT, WARN) \
        /* infos (reported as warnings, but ignored by default) */ \
 +      FUNC(GITMODULES_PARSE, INFO) \
        FUNC(BAD_TAG_NAME, INFO) \
        FUNC(MISSING_TAGGER_ENTRY, INFO)
  
@@@ -317,13 -317,6 +318,13 @@@ static void append_msg_id(struct strbu
        strbuf_addstr(sb, ": ");
  }
  
 +static int object_on_skiplist(struct fsck_options *opts, struct object *obj)
 +{
 +      if (opts && opts->skiplist && obj)
 +              return oid_array_lookup(opts->skiplist, &obj->oid) >= 0;
 +      return 0;
 +}
 +
  __attribute__((format (printf, 4, 5)))
  static int report(struct fsck_options *options, struct object *object,
        enum fsck_msg_id id, const char *fmt, ...)
        if (msg_type == FSCK_IGNORE)
                return 0;
  
 -      if (options->skiplist && object &&
 -                      oid_array_lookup(options->skiplist, &object->oid) >= 0)
 +      if (object_on_skiplist(options, object))
                return 0;
  
        if (msg_type == FSCK_FATAL)
@@@ -413,14 -407,14 +414,14 @@@ static int fsck_walk_tree(struct tree *
                        continue;
  
                if (S_ISDIR(entry.mode)) {
-                       obj = (struct object *)lookup_tree(entry.oid);
+                       obj = (struct object *)lookup_tree(the_repository, entry.oid);
                        if (name && obj)
                                put_object_name(options, obj, "%s%s/", name,
                                        entry.path);
                        result = options->walk(obj, OBJ_TREE, data, options);
                }
                else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) {
-                       obj = (struct object *)lookup_blob(entry.oid);
+                       obj = (struct object *)lookup_blob(the_repository, entry.oid);
                        if (name && obj)
                                put_object_name(options, obj, "%s%s", name,
                                        entry.path);
@@@ -518,7 -512,7 +519,7 @@@ int fsck_walk(struct object *obj, void 
                return -1;
  
        if (obj->type == OBJ_NONE)
-               parse_object(&obj->oid);
+               parse_object(the_repository, &obj->oid);
  
        switch (obj->type) {
        case OBJ_BLOB:
@@@ -1000,15 -994,11 +1001,15 @@@ static int fsck_blob(struct blob *blob
                     unsigned long size, struct fsck_options *options)
  {
        struct fsck_gitmodules_data data;
 +      struct config_options config_opts = { 0 };
  
        if (!oidset_contains(&gitmodules_found, &blob->object.oid))
                return 0;
        oidset_insert(&gitmodules_done, &blob->object.oid);
  
 +      if (object_on_skiplist(options, &blob->object))
 +              return 0;
 +
        if (!buf) {
                /*
                 * A missing buffer here is a sign that the caller found the
                 * that an error.
                 */
                return report(options, &blob->object,
 -                            FSCK_MSG_GITMODULES_PARSE,
 +                            FSCK_MSG_GITMODULES_LARGE,
                              ".gitmodules too large to parse");
        }
  
        data.obj = &blob->object;
        data.options = options;
        data.ret = 0;
 +      config_opts.error_action = CONFIG_ERROR_SILENT;
        if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
 -                              ".gitmodules", buf, size, &data))
 +                              ".gitmodules", buf, size, &data, &config_opts))
                data.ret |= report(options, &blob->object,
                                   FSCK_MSG_GITMODULES_PARSE,
                                   "could not parse gitmodules blob");
@@@ -1081,7 -1070,7 +1082,7 @@@ int fsck_finish(struct fsck_options *op
                if (oidset_contains(&gitmodules_done, oid))
                        continue;
  
-               blob = lookup_blob(oid);
+               blob = lookup_blob(the_repository, oid);
                if (!blob) {
                        struct object *obj = lookup_unknown_object(oid->hash);
                        ret |= report(options, obj,
diff --combined line-log.c
index e5af5d0e455abd1361e696783e468a074a49fc2f,7fa0f16eba6bbb851be38dd266d597cf450a0275..72a5fed661ca0a0f0eb1fe726e91acc8cd47512a
@@@ -479,7 -479,7 +479,7 @@@ static struct commit *check_single_comm
                struct object *obj = revs->pending.objects[i].item;
                if (obj->flags & UNINTERESTING)
                        continue;
-               obj = deref_tag(obj, NULL, 0);
+               obj = deref_tag(the_repository, obj, NULL, 0);
                if (obj->type != OBJ_COMMIT)
                        die("Non commit %s?", revs->pending.objects[i].name);
                if (commit)
@@@ -598,11 -598,11 +598,11 @@@ parse_lines(struct commit *commit, cons
                                    lines, anchor, &begin, &end,
                                    full_name))
                        die("malformed -L argument '%s'", range_part);
 -              if (lines < end || ((lines || begin) && lines < begin))
 +              if ((!lines && (begin || end)) || lines < begin)
                        die("file %s has only %lu lines", name_part, lines);
                if (begin < 1)
                        begin = 1;
 -              if (end < 1)
 +              if (end < 1 || lines < end)
                        end = lines;
                begin--;
                line_log_data_insert(&ranges, full_name, begin, end);
diff --combined list-objects.c
index b1f2138c294adb50cacdcf43601ff82d69eebbae,782c0e189f933869d3df4f1ba1e17398e95b215b..c99c47ac181612db5122a313557090e1957fea4f
@@@ -48,7 -48,7 +48,7 @@@ static void process_blob(struct rev_inf
  
        pathlen = path->len;
        strbuf_addstr(path, name);
 -      if (filter_fn)
 +      if (!(obj->flags & USER_GIVEN) && filter_fn)
                r = filter_fn(LOFS_BLOB, obj,
                              path->buf, &path->buf[pathlen],
                              filter_data);
@@@ -133,7 -133,7 +133,7 @@@ static void process_tree(struct rev_inf
        }
  
        strbuf_addstr(base, name);
 -      if (filter_fn)
 +      if (!(obj->flags & USER_GIVEN) && filter_fn)
                r = filter_fn(LOFS_BEGIN_TREE, obj,
                              base->buf, &base->buf[baselen],
                              filter_data);
  
                if (S_ISDIR(entry.mode))
                        process_tree(revs,
-                                    lookup_tree(entry.oid),
+                                    lookup_tree(the_repository, entry.oid),
                                     show, base, entry.path,
                                     cb_data, filter_fn, filter_data);
                else if (S_ISGITLINK(entry.mode))
                                        cb_data);
                else
                        process_blob(revs,
-                                    lookup_blob(entry.oid),
+                                    lookup_blob(the_repository, entry.oid),
                                     show, base, entry.path,
                                     cb_data, filter_fn, filter_data);
        }
  
 -      if (filter_fn) {
 +      if (!(obj->flags & USER_GIVEN) && filter_fn) {
                r = filter_fn(LOFS_END_TREE, obj,
                              base->buf, &base->buf[baselen],
                              filter_data);
diff --combined log-tree.c
index f2ca0fbd53fa3da7759b5d77d97b6816dfe23430,76475d0136b60d1f19ae1267014bed8485dc2898..c0ac7af7cb6bffea85447ba3af151ee6b8ab65e3
@@@ -2,6 -2,7 +2,7 @@@
  #include "config.h"
  #include "diff.h"
  #include "object-store.h"
+ #include "repository.h"
  #include "commit.h"
  #include "tag.h"
  #include "graph.h"
@@@ -98,13 -99,13 +99,13 @@@ static int add_ref_decoration(const cha
                        warning("invalid replace ref %s", refname);
                        return 0;
                }
-               obj = parse_object(&original_oid);
+               obj = parse_object(the_repository, &original_oid);
                if (obj)
                        add_name_decoration(DECORATION_GRAFTED, "replaced", obj);
                return 0;
        }
  
-       obj = parse_object(oid);
+       obj = parse_object(the_repository, oid);
        if (!obj)
                return 0;
  
                if (!obj)
                        break;
                if (!obj->parsed)
-                       parse_object(&obj->oid);
+                       parse_object(the_repository, &obj->oid);
                add_name_decoration(DECORATION_REF_TAG, refname, obj);
        }
        return 0;
  
  static int add_graft_decoration(const struct commit_graft *graft, void *cb_data)
  {
-       struct commit *commit = lookup_commit(&graft->oid);
+       struct commit *commit = lookup_commit(the_repository, &graft->oid);
        if (!commit)
                return 0;
        add_name_decoration(DECORATION_GRAFTED, "grafted", &commit->object);
@@@ -497,12 -498,12 +498,12 @@@ static int show_one_mergetag(struct com
        size_t payload_size, gpg_message_offset;
  
        hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &oid);
-       tag = lookup_tag(&oid);
+       tag = lookup_tag(the_repository, &oid);
        if (!tag)
                return -1; /* error message already given */
  
        strbuf_init(&verify_message, 256);
-       if (parse_tag_buffer(tag, extra->value, extra->len))
+       if (parse_tag_buffer(the_repository, tag, extra->value, extra->len))
                strbuf_addstr(&verify_message, "malformed mergetag\n");
        else if (is_common_merge(commit) &&
                 !oidcmp(&tag->tagged->oid,
@@@ -546,7 -547,7 +547,7 @@@ void show_log(struct rev_info *opt
        struct strbuf msgbuf = STRBUF_INIT;
        struct log_info *log = opt->loginfo;
        struct commit *commit = log->commit, *parent = log->parent;
 -      int abbrev_commit = opt->abbrev_commit ? opt->abbrev : GIT_SHA1_HEXSZ;
 +      int abbrev_commit = opt->abbrev_commit ? opt->abbrev : the_hash_algo->hexsz;
        const char *extra_headers = opt->extra_headers;
        struct pretty_print_context ctx = {0};
  
diff --combined merge-recursive.c
index 113c1d69625935a2f3c476af0ec0ca92201417e7,1dd6ec384de132d24f96b2ee89639bb765de9589..3d6b34b4f7438d2408780d73095e9a1bd0cd4338
@@@ -9,6 -9,7 +9,7 @@@
  #include "lockfile.h"
  #include "cache-tree.h"
  #include "object-store.h"
+ #include "repository.h"
  #include "commit.h"
  #include "blob.h"
  #include "builtin.h"
@@@ -157,7 -158,7 +158,7 @@@ static struct tree *shift_tree_object(s
        }
        if (!oidcmp(&two->object.oid, &shifted))
                return two;
-       return lookup_tree(&shifted);
+       return lookup_tree(the_repository, &shifted);
  }
  
  static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
@@@ -183,7 -184,7 +184,7 @@@ static int oid_eq(const struct object_i
  
  enum rename_type {
        RENAME_NORMAL = 0,
 -      RENAME_DIR,
 +      RENAME_VIA_DIR,
        RENAME_DELETE,
        RENAME_ONE_FILE_TO_ONE,
        RENAME_ONE_FILE_TO_TWO,
@@@ -313,8 -314,8 +314,8 @@@ static void output_commit_title(struct 
  }
  
  static int add_cacheinfo(struct merge_options *o,
 -              unsigned int mode, const struct object_id *oid,
 -              const char *path, int stage, int refresh, int options)
 +                       unsigned int mode, const struct object_id *oid,
 +                       const char *path, int stage, int refresh, int options)
  {
        struct cache_entry *ce;
        int ret;
@@@ -415,14 -416,14 +416,14 @@@ struct tree *write_tree_from_memory(str
                return NULL;
        }
  
-       result = lookup_tree(&active_cache_tree->oid);
+       result = lookup_tree(the_repository, &active_cache_tree->oid);
  
        return result;
  }
  
  static int save_files_dirs(const struct object_id *oid,
 -              struct strbuf *base, const char *path,
 -              unsigned int mode, int stage, void *context)
 +                         struct strbuf *base, const char *path,
 +                         unsigned int mode, int stage, void *context)
  {
        struct path_hashmap_entry *entry;
        int baselen = base->len;
@@@ -543,7 -544,7 +544,7 @@@ static void record_df_conflict_files(st
                                     struct string_list *entries)
  {
        /* If there is a D/F conflict and the file for such a conflict
 -       * currently exist in the working tree, we want to allow it to be
 +       * currently exists in the working tree, we want to allow it to be
         * removed to make room for the corresponding directory if needed.
         * The files underneath the directories of such D/F conflicts will
         * be processed before the corresponding file involved in the D/F
@@@ -917,7 -918,7 +918,7 @@@ static int make_room_for_path(struct me
         */
        if (would_lose_untracked(path))
                return err(o, _("refusing to lose untracked file at '%s'"),
 -                           path);
 +                         path);
  
        /* Successful unlink is good.. */
        if (!unlink(path))
@@@ -996,16 -997,16 +997,16 @@@ static int update_file_flags(struct mer
                        unlink(path);
                        if (symlink(lnk, path))
                                ret = err(o, _("failed to symlink '%s': %s"),
 -                                      path, strerror(errno));
 +                                        path, strerror(errno));
                        free(lnk);
                } else
                        ret = err(o,
                                  _("do not know what to do with %06o %s '%s'"),
                                  mode, oid_to_hex(oid), path);
 - free_buf:
 +      free_buf:
                free(buf);
        }
 - update_index:
 +update_index:
        if (!ret && update_cache)
                if (add_cacheinfo(o, mode, oid, path, 0, update_wd,
                                  ADD_CACHE_OK_TO_ADD))
@@@ -1094,7 -1095,7 +1095,7 @@@ static int merge_3way(struct merge_opti
  }
  
  static int find_first_merges(struct object_array *result, const char *path,
 -              struct commit *a, struct commit *b)
 +                           struct commit *a, struct commit *b)
  {
        int i, j;
        struct object_array merges = OBJECT_ARRAY_INIT;
  
        /* get all revisions that merge commit a */
        xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
 -                      oid_to_hex(&a->object.oid));
 +                oid_to_hex(&a->object.oid));
        init_revisions(&revs, NULL);
        rev_opts.submodule = path;
        /* FIXME: can't handle linked worktrees in submodules yet */
@@@ -1191,9 -1192,9 +1192,9 @@@ static int merge_submodule(struct merge
                return 0;
        }
  
-       if (!(commit_base = lookup_commit_reference(base)) ||
-           !(commit_a = lookup_commit_reference(a)) ||
-           !(commit_b = lookup_commit_reference(b))) {
+       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))) {
                output(o, 1, _("Failed to merge submodule %s (commits not present)"), path);
                return 0;
        }
                output(o, 2, _("Found a possible merge resolution for the submodule:\n"));
                print_commit((struct commit *) merges.objects[0].item);
                output(o, 2, _(
 -                      "If this is correct simply add it to the index "
 -                      "for example\n"
 -                      "by using:\n\n"
 -                      "  git update-index --cacheinfo 160000 %s \"%s\"\n\n"
 -                      "which will accept this suggestion.\n"),
 -                      oid_to_hex(&merges.objects[0].item->oid), path);
 +                     "If this is correct simply add it to the index "
 +                     "for example\n"
 +                     "by using:\n\n"
 +                     "  git update-index --cacheinfo 160000 %s \"%s\"\n\n"
 +                     "which will accept this suggestion.\n"),
 +                     oid_to_hex(&merges.objects[0].item->oid), path);
                break;
  
        default:
@@@ -1336,10 -1337,10 +1337,10 @@@ static int merge_file_1(struct merge_op
                        result->clean = (merge_status == 0);
                } else if (S_ISGITLINK(a->mode)) {
                        result->clean = merge_submodule(o, &result->oid,
 -                                                     one->path,
 -                                                     &one->oid,
 -                                                     &a->oid,
 -                                                     &b->oid);
 +                                                      one->path,
 +                                                      &one->oid,
 +                                                      &a->oid,
 +                                                      &b->oid);
                } else if (S_ISLNK(a->mode)) {
                        switch (o->recursive_variant) {
                        case MERGE_RECURSIVE_NORMAL:
@@@ -1414,17 -1415,11 +1415,17 @@@ static int merge_file_one(struct merge_
        return merge_file_1(o, &one, &a, &b, path, branch1, branch2, mfi);
  }
  
 -static int conflict_rename_dir(struct merge_options *o,
 -                             struct diff_filepair *pair,
 -                             const char *rename_branch,
 -                             const char *other_branch)
 +static int handle_rename_via_dir(struct merge_options *o,
 +                               struct diff_filepair *pair,
 +                               const char *rename_branch,
 +                               const char *other_branch)
  {
 +      /*
 +       * Handle file adds that need to be renamed due to directory rename
 +       * detection.  This differs from handle_rename_normal, because
 +       * there is no content merge to do; just move the file into the
 +       * desired final location.
 +       */
        const struct diff_filespec *dest = pair->two;
  
        if (!o->call_depth && would_lose_untracked(dest->path)) {
  }
  
  static int handle_change_delete(struct merge_options *o,
 -                               const char *path, const char *old_path,
 -                               const struct object_id *o_oid, int o_mode,
 -                               const struct object_id *changed_oid,
 -                               int changed_mode,
 -                               const char *change_branch,
 -                               const char *delete_branch,
 -                               const char *change, const char *change_past)
 +                              const char *path, const char *old_path,
 +                              const struct object_id *o_oid, int o_mode,
 +                              const struct object_id *changed_oid,
 +                              int changed_mode,
 +                              const char *change_branch,
 +                              const char *delete_branch,
 +                              const char *change, const char *change_past)
  {
        char *alt_path = NULL;
        const char *update_path = path;
                if (!ret)
                        ret = update_file(o, 0, o_oid, o_mode, update_path);
        } else {
 +              /*
 +               * Despite the four nearly duplicate messages and argument
 +               * lists below and the ugliness of the nested if-statements,
 +               * having complete messages makes the job easier for
 +               * translators.
 +               *
 +               * The slight variance among the cases is due to the fact
 +               * that:
 +               *   1) directory/file conflicts (in effect if
 +               *      !alt_path) could cause us to need to write the
 +               *      file to a different path.
 +               *   2) renames (in effect if !old_path) could mean that
 +               *      there are two names for the path that the user
 +               *      may know the file by.
 +               */
                if (!alt_path) {
                        if (!old_path) {
                                output(o, 1, _("CONFLICT (%s/delete): %s deleted in %s "
        return ret;
  }
  
 -static int conflict_rename_delete(struct merge_options *o,
 -                                 struct diff_filepair *pair,
 -                                 const char *rename_branch,
 -                                 const char *delete_branch)
 +static int handle_rename_delete(struct merge_options *o,
 +                              struct diff_filepair *pair,
 +                              const char *rename_branch,
 +                              const char *delete_branch)
  {
        const struct diff_filespec *orig = pair->one;
        const struct diff_filespec *dest = pair->two;
@@@ -1639,8 -1619,8 +1640,8 @@@ static int handle_file(struct merge_opt
        return ret;
  }
  
 -static int conflict_rename_rename_1to2(struct merge_options *o,
 -                                      struct rename_conflict_info *ci)
 +static int handle_rename_rename_1to2(struct merge_options *o,
 +                                   struct rename_conflict_info *ci)
  {
        /* One file was renamed in both branches, but to different names. */
        struct diff_filespec *one = ci->pair1->one;
        return 0;
  }
  
 -static int conflict_rename_rename_2to1(struct merge_options *o,
 -                                      struct rename_conflict_info *ci)
 +static int handle_rename_rename_2to1(struct merge_options *o,
 +                                   struct rename_conflict_info *ci)
  {
        /* Two files, a & b, were renamed to the same thing, c. */
        struct diff_filespec *a = ci->pair1->one;
@@@ -2444,7 -2424,7 +2445,7 @@@ static void apply_directory_rename_modi
         * "NOTE" in update_stages(), doing so will modify the current
         * in-memory index which will break calls to would_lose_untracked()
         * that we need to make.  Instead, we need to just make sure that
 -       * the various conflict_rename_*() functions update the index
 +       * the various handle_rename_*() functions update the index
         * explicitly rather than relying on unpack_trees() to have done it.
         */
        get_tree_entry(&tree->object.oid,
@@@ -2717,7 -2697,7 +2718,7 @@@ static int process_renames(struct merge
  
                        if (oid_eq(&src_other.oid, &null_oid) &&
                            ren1->add_turned_into_rename) {
 -                              setup_rename_conflict_info(RENAME_DIR,
 +                              setup_rename_conflict_info(RENAME_VIA_DIR,
                                                           ren1->pair,
                                                           NULL,
                                                           branch1,
@@@ -2848,12 -2828,12 +2849,12 @@@ static void initial_cleanup_rename(stru
        free(pairs);
  }
  
 -static int handle_renames(struct merge_options *o,
 -                        struct tree *common,
 -                        struct tree *head,
 -                        struct tree *merge,
 -                        struct string_list *entries,
 -                        struct rename_info *ri)
 +static int detect_and_process_renames(struct merge_options *o,
 +                                    struct tree *common,
 +                                    struct tree *head,
 +                                    struct tree *merge,
 +                                    struct string_list *entries,
 +                                    struct rename_info *ri)
  {
        struct diff_queue_struct *head_pairs, *merge_pairs;
        struct hashmap *dir_re_head, *dir_re_merge;
@@@ -2929,8 -2909,7 +2930,8 @@@ static struct object_id *stage_oid(cons
  }
  
  static int read_oid_strbuf(struct merge_options *o,
 -      const struct object_id *oid, struct strbuf *dst)
 +                         const struct object_id *oid,
 +                         struct strbuf *dst)
  {
        void *buf;
        enum object_type type;
@@@ -2983,10 -2962,10 +2984,10 @@@ error_return
  }
  
  static int handle_modify_delete(struct merge_options *o,
 -                               const char *path,
 -                               struct object_id *o_oid, int o_mode,
 -                               struct object_id *a_oid, int a_mode,
 -                               struct object_id *b_oid, int b_mode)
 +                              const char *path,
 +                              struct object_id *o_oid, int o_mode,
 +                              struct object_id *a_oid, int a_mode,
 +                              struct object_id *b_oid, int b_mode)
  {
        const char *modify_branch, *delete_branch;
        struct object_id *changed_oid;
@@@ -3124,12 -3103,12 +3125,12 @@@ static int merge_content(struct merge_o
        return !is_dirty && mfi.clean;
  }
  
 -static int conflict_rename_normal(struct merge_options *o,
 -                                const char *path,
 -                                struct object_id *o_oid, unsigned int o_mode,
 -                                struct object_id *a_oid, unsigned int a_mode,
 -                                struct object_id *b_oid, unsigned int b_mode,
 -                                struct rename_conflict_info *ci)
 +static int handle_rename_normal(struct merge_options *o,
 +                              const char *path,
 +                              struct object_id *o_oid, unsigned int o_mode,
 +                              struct object_id *a_oid, unsigned int a_mode,
 +                              struct object_id *b_oid, unsigned int b_mode,
 +                              struct rename_conflict_info *ci)
  {
        /* Merge the content and write it out */
        return merge_content(o, path, was_dirty(o, path),
@@@ -3156,37 -3135,37 +3157,37 @@@ static int process_entry(struct merge_o
                switch (conflict_info->rename_type) {
                case RENAME_NORMAL:
                case RENAME_ONE_FILE_TO_ONE:
 -                      clean_merge = conflict_rename_normal(o,
 -                                                           path,
 -                                                           o_oid, o_mode,
 -                                                           a_oid, a_mode,
 -                                                           b_oid, b_mode,
 -                                                           conflict_info);
 +                      clean_merge = handle_rename_normal(o,
 +                                                         path,
 +                                                         o_oid, o_mode,
 +                                                         a_oid, a_mode,
 +                                                         b_oid, b_mode,
 +                                                         conflict_info);
                        break;
 -              case RENAME_DIR:
 +              case RENAME_VIA_DIR:
                        clean_merge = 1;
 -                      if (conflict_rename_dir(o,
 -                                              conflict_info->pair1,
 -                                              conflict_info->branch1,
 -                                              conflict_info->branch2))
 +                      if (handle_rename_via_dir(o,
 +                                                conflict_info->pair1,
 +                                                conflict_info->branch1,
 +                                                conflict_info->branch2))
                                clean_merge = -1;
                        break;
                case RENAME_DELETE:
                        clean_merge = 0;
 -                      if (conflict_rename_delete(o,
 -                                                 conflict_info->pair1,
 -                                                 conflict_info->branch1,
 -                                                 conflict_info->branch2))
 +                      if (handle_rename_delete(o,
 +                                               conflict_info->pair1,
 +                                               conflict_info->branch1,
 +                                               conflict_info->branch2))
                                clean_merge = -1;
                        break;
                case RENAME_ONE_FILE_TO_TWO:
                        clean_merge = 0;
 -                      if (conflict_rename_rename_1to2(o, conflict_info))
 +                      if (handle_rename_rename_1to2(o, conflict_info))
                                clean_merge = -1;
                        break;
                case RENAME_TWO_FILES_TO_ONE:
                        clean_merge = 0;
 -                      if (conflict_rename_rename_2to1(o, conflict_info))
 +                      if (handle_rename_rename_2to1(o, conflict_info))
                                clean_merge = -1;
                        break;
                default:
@@@ -3326,8 -3305,8 +3327,8 @@@ int merge_trees(struct merge_options *o
                get_files_dirs(o, merge);
  
                entries = get_unmerged();
 -              clean = handle_renames(o, common, head, merge, entries,
 -                                     &re_info);
 +              clean = detect_and_process_renames(o, common, head, merge,
 +                                                 entries, &re_info);
                record_df_conflict_files(o, entries);
                if (clean < 0)
                        goto cleanup;
                                    entries->items[i].string);
                }
  
 -cleanup:
 +      cleanup:
                final_cleanup_renames(&re_info);
  
                string_list_clear(entries, 1);
@@@ -3426,7 -3405,7 +3427,7 @@@ int merge_recursive(struct merge_option
                /* if there is no common ancestor, use an empty tree */
                struct tree *tree;
  
-               tree = lookup_tree(the_hash_algo->empty_tree);
+               tree = lookup_tree(the_repository, the_repository->hash_algo->empty_tree);
                merged_common_ancestors = make_virtual_commit(tree, "ancestor");
        }
  
@@@ -3488,7 -3467,9 +3489,9 @@@ static struct commit *get_ref(const str
  {
        struct object *object;
  
-       object = deref_tag(parse_object(oid), name, strlen(name));
+       object = deref_tag(the_repository, parse_object(the_repository, oid),
+                          name,
+                          strlen(name));
        if (!object)
                return NULL;
        if (object->type == OBJ_TREE)
@@@ -3519,14 -3500,14 +3522,14 @@@ int merge_recursive_generic(struct merg
                        struct commit *base;
                        if (!(base = get_ref(base_list[i], oid_to_hex(base_list[i]))))
                                return err(o, _("Could not parse object '%s'"),
 -                                      oid_to_hex(base_list[i]));
 +                                         oid_to_hex(base_list[i]));
                        commit_list_insert(base, &ca);
                }
        }
  
        hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
        clean = merge_recursive(o, head_commit, next_commit, ca,
 -                      result);
 +                              result);
        if (clean < 0) {
                rollback_lock_file(&lock);
                return clean;
diff --combined negotiator/default.c
index 382fc77722a396778c308c7ecbee780dd3b79588,0000000000000000000000000000000000000000..4b78f6bf36a0479a55934a6e4ac4c288775217f5
mode 100644,000000..100644
--- /dev/null
@@@ -1,176 -1,0 +1,176 @@@
-       struct object *o = deref_tag(parse_object(oid), refname, 0);
 +#include "cache.h"
 +#include "default.h"
 +#include "../commit.h"
 +#include "../fetch-negotiator.h"
 +#include "../prio-queue.h"
 +#include "../refs.h"
 +#include "../tag.h"
 +
 +/* Remember to update object flag allocation in object.h */
 +#define COMMON                (1U << 2)
 +#define COMMON_REF    (1U << 3)
 +#define SEEN          (1U << 4)
 +#define POPPED                (1U << 5)
 +
 +static int marked;
 +
 +struct negotiation_state {
 +      struct prio_queue rev_list;
 +      int non_common_revs;
 +};
 +
 +static void rev_list_push(struct negotiation_state *ns,
 +                        struct commit *commit, int mark)
 +{
 +      if (!(commit->object.flags & mark)) {
 +              commit->object.flags |= mark;
 +
 +              if (parse_commit(commit))
 +                      return;
 +
 +              prio_queue_put(&ns->rev_list, commit);
 +
 +              if (!(commit->object.flags & COMMON))
 +                      ns->non_common_revs++;
 +      }
 +}
 +
 +static int clear_marks(const char *refname, const struct object_id *oid,
 +                     int flag, void *cb_data)
 +{
++      struct object *o = deref_tag(the_repository, parse_object(the_repository, oid), refname, 0);
 +
 +      if (o && o->type == OBJ_COMMIT)
 +              clear_commit_marks((struct commit *)o,
 +                                 COMMON | COMMON_REF | SEEN | POPPED);
 +      return 0;
 +}
 +
 +/*
 + * This function marks a rev and its ancestors as common.
 + * In some cases, it is desirable to mark only the ancestors (for example
 + * when only the server does not yet know that they are common).
 + */
 +static void mark_common(struct negotiation_state *ns, struct commit *commit,
 +              int ancestors_only, int dont_parse)
 +{
 +      if (commit != NULL && !(commit->object.flags & COMMON)) {
 +              struct object *o = (struct object *)commit;
 +
 +              if (!ancestors_only)
 +                      o->flags |= COMMON;
 +
 +              if (!(o->flags & SEEN))
 +                      rev_list_push(ns, commit, SEEN);
 +              else {
 +                      struct commit_list *parents;
 +
 +                      if (!ancestors_only && !(o->flags & POPPED))
 +                              ns->non_common_revs--;
 +                      if (!o->parsed && !dont_parse)
 +                              if (parse_commit(commit))
 +                                      return;
 +
 +                      for (parents = commit->parents;
 +                                      parents;
 +                                      parents = parents->next)
 +                              mark_common(ns, parents->item, 0,
 +                                          dont_parse);
 +              }
 +      }
 +}
 +
 +/*
 + * Get the next rev to send, ignoring the common.
 + */
 +static const struct object_id *get_rev(struct negotiation_state *ns)
 +{
 +      struct commit *commit = NULL;
 +
 +      while (commit == NULL) {
 +              unsigned int mark;
 +              struct commit_list *parents;
 +
 +              if (ns->rev_list.nr == 0 || ns->non_common_revs == 0)
 +                      return NULL;
 +
 +              commit = prio_queue_get(&ns->rev_list);
 +              parse_commit(commit);
 +              parents = commit->parents;
 +
 +              commit->object.flags |= POPPED;
 +              if (!(commit->object.flags & COMMON))
 +                      ns->non_common_revs--;
 +
 +              if (commit->object.flags & COMMON) {
 +                      /* do not send "have", and ignore ancestors */
 +                      commit = NULL;
 +                      mark = COMMON | SEEN;
 +              } else if (commit->object.flags & COMMON_REF)
 +                      /* send "have", and ignore ancestors */
 +                      mark = COMMON | SEEN;
 +              else
 +                      /* send "have", also for its ancestors */
 +                      mark = SEEN;
 +
 +              while (parents) {
 +                      if (!(parents->item->object.flags & SEEN))
 +                              rev_list_push(ns, parents->item, mark);
 +                      if (mark & COMMON)
 +                              mark_common(ns, parents->item, 1, 0);
 +                      parents = parents->next;
 +              }
 +      }
 +
 +      return &commit->object.oid;
 +}
 +
 +static void known_common(struct fetch_negotiator *n, struct commit *c)
 +{
 +      if (!(c->object.flags & SEEN)) {
 +              rev_list_push(n->data, c, COMMON_REF | SEEN);
 +              mark_common(n->data, c, 1, 1);
 +      }
 +}
 +
 +static void add_tip(struct fetch_negotiator *n, struct commit *c)
 +{
 +      n->known_common = NULL;
 +      rev_list_push(n->data, c, SEEN);
 +}
 +
 +static const struct object_id *next(struct fetch_negotiator *n)
 +{
 +      n->known_common = NULL;
 +      n->add_tip = NULL;
 +      return get_rev(n->data);
 +}
 +
 +static int ack(struct fetch_negotiator *n, struct commit *c)
 +{
 +      int known_to_be_common = !!(c->object.flags & COMMON);
 +      mark_common(n->data, c, 0, 1);
 +      return known_to_be_common;
 +}
 +
 +static void release(struct fetch_negotiator *n)
 +{
 +      clear_prio_queue(&((struct negotiation_state *)n->data)->rev_list);
 +      FREE_AND_NULL(n->data);
 +}
 +
 +void default_negotiator_init(struct fetch_negotiator *negotiator)
 +{
 +      struct negotiation_state *ns;
 +      negotiator->known_common = known_common;
 +      negotiator->add_tip = add_tip;
 +      negotiator->next = next;
 +      negotiator->ack = ack;
 +      negotiator->release = release;
 +      negotiator->data = ns = xcalloc(1, sizeof(*ns));
 +      ns->rev_list.compare = compare_commits_by_commit_date;
 +
 +      if (marked)
 +              for_each_ref(clear_marks, NULL);
 +      marked = 1;
 +}
diff --combined object.h
index 7227b9716672dd15e60e3f1a953f02cbb1f7e14a,fa5ca9756786307e52004dfc3cb18d11a889dbb9..177b1a4571fb60f75d523124c09c133c2f5c84e6
+++ b/object.h
@@@ -1,6 -1,8 +1,8 @@@
  #ifndef OBJECT_H
  #define OBJECT_H
  
+ struct buffer_slab;
  struct parsed_object_pool {
        struct object **obj_hash;
        int nr_objs, obj_hash_size;
@@@ -22,6 -24,8 +24,8 @@@
        char *alternate_shallow_file;
  
        int commit_graft_prepared;
+       struct buffer_slab *buffer_slab;
  };
  
  struct parsed_object_pool *parsed_object_pool_new(void);
@@@ -53,9 -57,8 +57,9 @@@ struct object_array 
  
  /*
   * object flag allocation:
 - * revision.h:               0---------10                                26
 - * fetch-pack.c:             0----5
 + * revision.h:               0---------10                              2526
 + * fetch-pack.c:             01
 + * negotiator/default.c:       2--5
   * walker.c:                 0-2
   * upload-pack.c:                4       11----------------19
   * builtin/blame.c:                        12-13
@@@ -110,18 -113,18 +114,18 @@@ extern struct object *get_indexed_objec
   * half-initialised objects, the caller is expected to initialize them
   * by calling parse_object() on them.
   */
- struct object *lookup_object(const unsigned char *sha1);
+ struct object *lookup_object(struct repository *r, const unsigned char *sha1);
  
  extern void *create_object(struct repository *r, const unsigned char *sha1, void *obj);
  
- void *object_as_type(struct object *obj, enum object_type type, int quiet);
+ void *object_as_type(struct repository *r, struct object *obj, enum object_type type, int quiet);
  
  /*
   * Returns the object, having parsed it to find out what it is.
   *
   * Returns NULL if the object is missing or corrupt.
   */
- struct object *parse_object(const struct object_id *oid);
+ struct object *parse_object(struct repository *r, const struct object_id *oid);
  
  /*
   * Like parse_object, but will die() instead of returning NULL. If the
@@@ -134,7 -137,7 +138,7 @@@ struct object *parse_object_or_die(cons
   * parsing it.  eaten_p indicates if the object has a borrowed copy
   * of buffer and the caller should not free() it.
   */
- struct object *parse_object_buffer(const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p);
+ struct object *parse_object_buffer(struct repository *r, const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p);
  
  /** Returns the object, with potentially excess memory allocated. **/
  struct object *lookup_unknown_object(const unsigned  char *sha1);
diff --combined pretty.c
index b0e653ff254f0a139a0246f3d49078c8c54493e2,cde4fe07db0403d8cb63848842a4db26f62c12c7..2b12da324bc0171c24fd88b6da636f70cd11f214
+++ b/pretty.c
@@@ -630,7 -630,7 +630,7 @@@ const char *logmsg_reencode(const struc
                 * the cached copy from get_commit_buffer, we need to duplicate it
                 * to avoid munging the cached copy.
                 */
-               if (msg == get_cached_commit_buffer(commit, NULL))
+               if (msg == get_cached_commit_buffer(the_repository, commit, NULL))
                        out = xstrdup(msg);
                else
                        out = (char *)msg;
@@@ -1146,7 -1146,7 +1146,7 @@@ static size_t format_commit_one(struct 
  
        /* these depend on the commit */
        if (!commit->object.parsed)
-               parse_object(&commit->object.oid);
+               parse_object(the_repository, &commit->object.oid);
  
        switch (placeholder[0]) {
        case 'H':               /* commit hash */
@@@ -1575,7 -1575,7 +1575,7 @@@ static void pp_header(struct pretty_pri
                }
  
                if (starts_with(line, "parent ")) {
 -                      if (linelen != 48)
 +                      if (linelen != the_hash_algo->hexsz + 8)
                                die("bad parent line in commit");
                        continue;
                }
                if (!parents_shown) {
                        unsigned num = commit_list_count(commit->parents);
                        /* with enough slop */
 -                      strbuf_grow(sb, num * 50 + 20);
 +                      strbuf_grow(sb, num * (GIT_MAX_HEXSZ + 10) + 20);
                        add_merge_info(pp, sb, commit);
                        parents_shown = 1;
                }
diff --combined ref-filter.c
index 492f2b770d909185dbeb65a0d42e62186981ab8a,49021ee4467de5a3f12845ab47507a6222cd07ae..600774de68a95ca416b069351cef4724ca7a9cd0
@@@ -4,6 -4,7 +4,7 @@@
  #include "refs.h"
  #include "wildmatch.h"
  #include "object-store.h"
+ #include "repository.h"
  #include "commit.h"
  #include "remote.h"
  #include "color.h"
@@@ -806,7 -807,8 +807,8 @@@ static void *get_obj(const struct objec
        void *buf = read_object_file(oid, &type, sz);
  
        if (buf)
-               *obj = parse_object_buffer(oid, type, *sz, buf, eaten);
+               *obj = parse_object_buffer(the_repository, oid, type, *sz,
+                                          buf, eaten);
        else
                *obj = NULL;
        return buf;
@@@ -1814,7 -1816,7 +1816,7 @@@ static int match_name_as_path(const str
                     refname[plen] == '/' ||
                     p[plen-1] == '/'))
                        return 1;
 -              if (!wildmatch(p, refname, WM_PATHNAME))
 +              if (!wildmatch(p, refname, flags))
                        return 1;
        }
        return 0;
@@@ -1869,15 -1871,6 +1871,15 @@@ static int for_each_fullref_in_pattern(
                return for_each_fullref_in("", cb, cb_data, broken);
        }
  
 +      if (filter->ignore_case) {
 +              /*
 +               * we can't handle case-insensitive comparisons,
 +               * so just return everything and let the caller
 +               * sort it out.
 +               */
 +              return for_each_fullref_in("", cb, cb_data, broken);
 +      }
 +
        if (!filter->name_patterns[0]) {
                /* no patterns; we have to look at everything */
                return for_each_fullref_in("", cb, cb_data, broken);
@@@ -1923,7 -1916,7 +1925,7 @@@ static const struct object_id *match_po
  
        if (oid_array_lookup(points_at, oid) >= 0)
                return oid;
-       obj = parse_object(oid);
+       obj = parse_object(the_repository, oid);
        if (!obj)
                die(_("malformed object at '%s'"), refname);
        if (obj->type == OBJ_TAG)
@@@ -2033,7 -2026,8 +2035,8 @@@ static int ref_filter_handler(const cha
         * non-commits early. The actual filtering is done later.
         */
        if (filter->merge_commit || filter->with_commit || filter->no_commit || filter->verbose) {
-               commit = lookup_commit_reference_gently(oid, 1);
+               commit = lookup_commit_reference_gently(the_repository, oid,
+                                                       1);
                if (!commit)
                        return 0;
                /* We perform the filtering for the '--contains' option... */
@@@ -2390,7 -2384,8 +2393,8 @@@ int parse_opt_merge_filter(const struc
        if (get_oid(arg, &oid))
                die(_("malformed object name %s"), arg);
  
-       rf->merge_commit = lookup_commit_reference_gently(&oid, 0);
+       rf->merge_commit = lookup_commit_reference_gently(the_repository,
+                                                         &oid, 0);
        if (!rf->merge_commit)
                return opterror(opt, "must point to a commit", 0);
  
diff --combined refs.c
index 08fb5a99148ab903f8c049479d227392b78775f7,fcfd3171e83a116d4ba2014b2f88622969f21a2d..457fb78057a9375eb2b2cda44214a1705a28fc1e
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -305,7 -305,7 +305,7 @@@ enum peel_status peel_object(const stru
  
        if (o->type == OBJ_NONE) {
                int type = oid_object_info(the_repository, name, NULL);
-               if (type < 0 || !object_as_type(o, type, 0))
+               if (type < 0 || !object_as_type(the_repository, o, type, 0))
                        return PEEL_INVALID;
        }
  
@@@ -787,21 -787,25 +787,21 @@@ int delete_ref(const char *msg, const c
                               old_oid, flags);
  }
  
 -int copy_reflog_msg(char *buf, const char *msg)
 +void copy_reflog_msg(struct strbuf *sb, const char *msg)
  {
 -      char *cp = buf;
        char c;
        int wasspace = 1;
  
 -      *cp++ = '\t';
 +      strbuf_addch(sb, '\t');
        while ((c = *msg++)) {
                if (wasspace && isspace(c))
                        continue;
                wasspace = isspace(c);
                if (wasspace)
                        c = ' ';
 -              *cp++ = c;
 +              strbuf_addch(sb, c);
        }
 -      while (buf < cp && isspace(cp[-1]))
 -              cp--;
 -      *cp++ = '\n';
 -      return cp - buf;
 +      strbuf_rtrim(sb);
  }
  
  int should_autocreate_reflog(const char *refname)
diff --combined refs/files-backend.c
index 4e43dd46b543d3665ab5d1128ccbbd5e26b6fbb0,55c2ae0bd591f01760cc3824edebf8893689f152..b9eb3aabe6388a6437109439c3ac2ca298853892
@@@ -1582,17 -1582,26 +1582,17 @@@ static int log_ref_write_fd(int fd, con
                            const struct object_id *new_oid,
                            const char *committer, const char *msg)
  {
 -      int msglen, written;
 -      unsigned maxlen, len;
 -      char *logrec;
 -
 -      msglen = msg ? strlen(msg) : 0;
 -      maxlen = strlen(committer) + msglen + 100;
 -      logrec = xmalloc(maxlen);
 -      len = xsnprintf(logrec, maxlen, "%s %s %s\n",
 -                      oid_to_hex(old_oid),
 -                      oid_to_hex(new_oid),
 -                      committer);
 -      if (msglen)
 -              len += copy_reflog_msg(logrec + len - 1, msg) - 1;
 -
 -      written = len <= maxlen ? write_in_full(fd, logrec, len) : -1;
 -      free(logrec);
 -      if (written < 0)
 -              return -1;
 +      struct strbuf sb = STRBUF_INIT;
 +      int ret = 0;
  
 -      return 0;
 +      strbuf_addf(&sb, "%s %s %s", oid_to_hex(old_oid), oid_to_hex(new_oid), committer);
 +      if (msg && *msg)
 +              copy_reflog_msg(&sb, msg);
 +      strbuf_addch(&sb, '\n');
 +      if (write_in_full(fd, sb.buf, sb.len) < 0)
 +              ret = -1;
 +      strbuf_release(&sb);
 +      return ret;
  }
  
  static int files_log_ref_write(struct files_ref_store *refs,
@@@ -1651,7 -1660,7 +1651,7 @@@ static int write_ref_to_lockfile(struc
        struct object *o;
        int fd;
  
-       o = parse_object(oid);
+       o = parse_object(the_repository, oid);
        if (!o) {
                strbuf_addf(err,
                            "trying to write ref '%s' with nonexistent object %s",
                return -1;
        }
        fd = get_lock_file_fd(&lock->lk);
 -      if (write_in_full(fd, oid_to_hex(oid), GIT_SHA1_HEXSZ) < 0 ||
 +      if (write_in_full(fd, oid_to_hex(oid), the_hash_algo->hexsz) < 0 ||
            write_in_full(fd, &term, 1) < 0 ||
            close_ref_gently(lock) < 0) {
                strbuf_addf(err,
@@@ -3061,7 -3070,7 +3061,7 @@@ static int files_reflog_expire(struct r
                        rollback_lock_file(&reflog_lock);
                } else if (update &&
                           (write_in_full(get_lock_file_fd(&lock->lk),
 -                              oid_to_hex(&cb.last_kept_oid), GIT_SHA1_HEXSZ) < 0 ||
 +                              oid_to_hex(&cb.last_kept_oid), the_hash_algo->hexsz) < 0 ||
                            write_str_in_full(get_lock_file_fd(&lock->lk), "\n") < 0 ||
                            close_ref_gently(lock) < 0)) {
                        status |= error("couldn't write %s",
diff --combined remote.c
index 3fd43453f4d6dffad22f16ea6b54c5a37455dd26,26b1fbd9a881d2af7d7cc7a098fe182d36502d80..86e6098774d891a3b7045cf1dd9c11959faf13dc
+++ b/remote.c
@@@ -1149,7 -1149,7 +1149,7 @@@ static void add_to_tips(struct tips *ti
  
        if (is_null_oid(oid))
                return;
-       commit = lookup_commit_reference_gently(oid, 1);
+       commit = lookup_commit_reference_gently(the_repository, oid, 1);
        if (!commit || (commit->object.flags & TMP_MARK))
                return;
        commit->object.flags |= TMP_MARK;
@@@ -1211,7 -1211,8 +1211,8 @@@ static void add_missing_tags(struct re
  
                        if (is_null_oid(&ref->new_oid))
                                continue;
-                       commit = lookup_commit_reference_gently(&ref->new_oid,
+                       commit = lookup_commit_reference_gently(the_repository,
+                                                               &ref->new_oid,
                                                                1);
                        if (!commit)
                                /* not pushing a commit, which is not an error */
@@@ -1435,8 -1436,8 +1436,8 @@@ void set_ref_status_for_push(struct re
                                reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
                        else if (!has_object_file(&ref->old_oid))
                                reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
-                       else if (!lookup_commit_reference_gently(&ref->old_oid, 1) ||
-                                !lookup_commit_reference_gently(&ref->new_oid, 1))
+                       else if (!lookup_commit_reference_gently(the_repository, &ref->old_oid, 1) ||
+                                !lookup_commit_reference_gently(the_repository, &ref->new_oid, 1))
                                reject_reason = REF_STATUS_REJECT_NEEDS_FORCE;
                        else if (!ref_newer(&ref->new_oid, &ref->old_oid))
                                reject_reason = REF_STATUS_REJECT_NONFASTFORWARD;
@@@ -1736,7 -1737,6 +1737,7 @@@ int get_fetch_map(const struct ref *rem
                if (refspec->exact_sha1) {
                        ref_map = alloc_ref(name);
                        get_oid_hex(name, &ref_map->old_oid);
 +                      ref_map->exact_oid = 1;
                } else {
                        ref_map = get_remote_ref(remote_refs, name);
                }
@@@ -1802,12 -1802,14 +1803,14 @@@ int ref_newer(const struct object_id *n
         * Both new_commit and old_commit must be commit-ish and new_commit is descendant of
         * old_commit.  Otherwise we require --force.
         */
-       o = deref_tag(parse_object(old_oid), NULL, 0);
+       o = deref_tag(the_repository, parse_object(the_repository, old_oid),
+                     NULL, 0);
        if (!o || o->type != OBJ_COMMIT)
                return 0;
        old_commit = (struct commit *) o;
  
-       o = deref_tag(parse_object(new_oid), NULL, 0);
+       o = deref_tag(the_repository, parse_object(the_repository, new_oid),
+                     NULL, 0);
        if (!o || o->type != OBJ_COMMIT)
                return 0;
        new_commit = (struct commit *) o;
@@@ -1865,13 -1867,13 +1868,13 @@@ int stat_tracking_info(struct branch *b
        /* Cannot stat if what we used to build on no longer exists */
        if (read_ref(base, &oid))
                return -1;
-       theirs = lookup_commit_reference(&oid);
+       theirs = lookup_commit_reference(the_repository, &oid);
        if (!theirs)
                return -1;
  
        if (read_ref(branch->refname, &oid))
                return -1;
-       ours = lookup_commit_reference(&oid);
+       ours = lookup_commit_reference(the_repository, &oid);
        if (!ours)
                return -1;
  
diff --combined revision.c
index a2570397b6685fbd6e3a7d77ad7e2c554cc03772,4dbe406bed2aa13f0685d98f0932f997e88b4972..8bd2e27037d8136ec96d31ed1a41eb45a040e475
@@@ -63,10 -63,10 +63,10 @@@ static void mark_tree_contents_unintere
        while (tree_entry(&desc, &entry)) {
                switch (object_type(entry.mode)) {
                case OBJ_TREE:
-                       mark_tree_uninteresting(lookup_tree(entry.oid));
+                       mark_tree_uninteresting(lookup_tree(the_repository, entry.oid));
                        break;
                case OBJ_BLOB:
-                       mark_blob_uninteresting(lookup_blob(entry.oid));
+                       mark_blob_uninteresting(lookup_blob(the_repository, entry.oid));
                        break;
                default:
                        /* Subproject commit - not in this repository */
@@@ -175,7 -175,6 +175,7 @@@ static void add_pending_object_with_pat
                strbuf_release(&buf);
                return; /* do not add the commit itself */
        }
 +      obj->flags |= USER_GIVEN;
        add_object_array_with_path(obj, name, &revs->pending, mode, path);
  }
  
@@@ -198,7 -197,7 +198,7 @@@ void add_head_to_pending(struct rev_inf
        struct object *obj;
        if (get_oid("HEAD", &oid))
                return;
-       obj = parse_object(&oid);
+       obj = parse_object(the_repository, &oid);
        if (!obj)
                return;
        add_pending_object(revs, obj, "HEAD");
@@@ -210,7 -209,7 +210,7 @@@ static struct object *get_reference(str
  {
        struct object *object;
  
-       object = parse_object(oid);
+       object = parse_object(the_repository, oid);
        if (!object) {
                if (revs->ignore_missing)
                        return object;
@@@ -247,7 -246,7 +247,7 @@@ static struct commit *handle_commit(str
                        add_pending_object(revs, object, tag->tag);
                if (!tag->tagged)
                        die("bad tag");
-               object = parse_object(&tag->tagged->oid);
+               object = parse_object(the_repository, &tag->tagged->oid);
                if (!object) {
                        if (revs->ignore_missing_links || (flags & UNINTERESTING))
                                return NULL;
@@@ -1250,7 -1249,7 +1250,7 @@@ static void handle_one_reflog_commit(st
  {
        struct all_refs_cb *cb = cb_data;
        if (!is_null_oid(oid)) {
-               struct object *o = parse_object(oid);
+               struct object *o = parse_object(the_repository, oid);
                if (o) {
                        o->flags |= cb->all_flags;
                        /* ??? CMDLINEFLAGS ??? */
@@@ -1323,7 -1322,7 +1323,7 @@@ static void add_cache_tree(struct cache
        int i;
  
        if (it->entry_count >= 0) {
-               struct tree *tree = lookup_tree(&it->oid);
+               struct tree *tree = lookup_tree(the_repository, &it->oid);
                add_pending_object_with_path(revs, &tree->object, "",
                                             040000, path->buf);
        }
@@@ -1349,7 -1348,7 +1349,7 @@@ static void do_add_index_objects_to_pen
                if (S_ISGITLINK(ce->ce_mode))
                        continue;
  
-               blob = lookup_blob(&ce->oid);
+               blob = lookup_blob(the_repository, &ce->oid);
                if (!blob)
                        die("unable to add index blob to traversal");
                add_pending_object_with_path(revs, &blob->object, "",
@@@ -1578,8 -1577,8 +1578,8 @@@ static int handle_dotdot_1(const char *
                *dotdot = '\0';
        }
  
-       a_obj = parse_object(&a_oid);
-       b_obj = parse_object(&b_oid);
+       a_obj = parse_object(the_repository, &a_oid);
+       b_obj = parse_object(the_repository, &b_oid);
        if (!a_obj || !b_obj)
                return dotdot_missing(arg, dotdot, revs, symmetric);
  
                struct commit *a, *b;
                struct commit_list *exclude;
  
-               a = lookup_commit_reference(&a_obj->oid);
-               b = lookup_commit_reference(&b_obj->oid);
+               a = lookup_commit_reference(the_repository, &a_obj->oid);
+               b = lookup_commit_reference(the_repository, &b_obj->oid);
                if (!a || !b)
                        return dotdot_missing(arg, dotdot, revs, symmetric);
  
@@@ -2884,7 -2883,7 +2884,7 @@@ static int mark_uninteresting(const str
                              uint32_t pos,
                              void *unused)
  {
-       struct object *o = parse_object(oid);
+       struct object *o = parse_object(the_repository, oid);
        o->flags |= UNINTERESTING | SEEN;
        return 0;
  }
diff --combined sequencer.c
index 16c1411054ab16a677b323bee035ef27a9005d18,d1d07bed5bb051d980015c85129333effe66391c..5a068fd35116a1e664d7cefbd363e984be6cc0b6
@@@ -63,12 -63,12 +63,12 @@@ static GIT_PATH_FUNC(rebase_path_done, 
   * The file to keep track of how many commands were already processed (e.g.
   * for the prompt).
   */
 -static GIT_PATH_FUNC(rebase_path_msgnum, "rebase-merge/msgnum");
 +static GIT_PATH_FUNC(rebase_path_msgnum, "rebase-merge/msgnum")
  /*
   * The file to keep track of how many commands are to be processed in total
   * (e.g. for the prompt).
   */
 -static GIT_PATH_FUNC(rebase_path_msgtotal, "rebase-merge/end");
 +static GIT_PATH_FUNC(rebase_path_msgtotal, "rebase-merge/end")
  /*
   * The commit message that is planned to be used for any changes that
   * need to be committed following a user interaction.
@@@ -433,7 -433,7 +433,7 @@@ static int read_oneliner(struct strbuf 
  
  static struct tree *empty_tree(void)
  {
-       return lookup_tree(the_hash_algo->empty_tree);
+       return lookup_tree(the_repository, the_repository->hash_algo->empty_tree);
  }
  
  static int error_dirty_index(struct replay_opts *opts)
@@@ -594,7 -594,7 +594,7 @@@ static int is_index_unchanged(void
        if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
                return error(_("could not resolve HEAD commit"));
  
-       head_commit = lookup_commit(&head_oid);
+       head_commit = lookup_commit(the_repository, &head_oid);
  
        /*
         * If head_commit is NULL, check_commit, called from
@@@ -1101,7 -1101,7 +1101,7 @@@ void print_commit_summary(const char *p
        struct strbuf author_ident = STRBUF_INIT;
        struct strbuf committer_ident = STRBUF_INIT;
  
-       commit = lookup_commit(oid);
+       commit = lookup_commit(the_repository, oid);
        if (!commit)
                die(_("couldn't look up newly created commit"));
        if (parse_commit(commit))
@@@ -1176,7 -1176,7 +1176,7 @@@ static int parse_head(struct commit **h
        if (get_oid("HEAD", &oid)) {
                current_head = NULL;
        } else {
-               current_head = lookup_commit_reference(&oid);
+               current_head = lookup_commit_reference(the_repository, &oid);
                if (!current_head)
                        return error(_("could not parse HEAD"));
                if (oidcmp(&oid, &current_head->object.oid)) {
@@@ -1511,7 -1511,7 +1511,7 @@@ static int update_squash_messages(enum 
  
                if (get_oid("HEAD", &head))
                        return error(_("need a HEAD to fixup"));
-               if (!(head_commit = lookup_commit_reference(&head)))
+               if (!(head_commit = lookup_commit_reference(the_repository, &head)))
                        return error(_("could not read HEAD"));
                if (!(head_message = get_commit_buffer(head_commit, NULL)))
                        return error(_("could not read HEAD's commit message"));
@@@ -1864,6 -1864,8 +1864,6 @@@ static int prepare_revs(struct replay_o
        if (prepare_revision_walk(opts->revs))
                return error(_("revision walk setup failed"));
  
 -      if (!opts->revs->commits)
 -              return error(_("empty commit set passed"));
        return 0;
  }
  
@@@ -2007,7 -2009,7 +2007,7 @@@ static int parse_insn_line(struct todo_
        if (status < 0)
                return -1;
  
-       item->commit = lookup_commit_reference(&commit_oid);
+       item->commit = lookup_commit_reference(the_repository, &commit_oid);
        return !item->commit;
  }
  
@@@ -2205,7 -2207,6 +2205,7 @@@ static int populate_opts_cb(const char 
  static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
  {
        int i;
 +      char *strategy_opts_string;
  
        strbuf_reset(buf);
        if (!read_oneliner(buf, rebase_path_strategy(), 0))
        if (!read_oneliner(buf, rebase_path_strategy_opts(), 0))
                return;
  
 -      opts->xopts_nr = split_cmdline(buf->buf, (const char ***)&opts->xopts);
 +      strategy_opts_string = buf->buf;
 +      if (*strategy_opts_string == ' ')
 +              strategy_opts_string++;
 +      opts->xopts_nr = split_cmdline(strategy_opts_string,
 +                                     (const char ***)&opts->xopts);
        for (i = 0; i < opts->xopts_nr; i++) {
                const char *arg = opts->xopts[i];
  
@@@ -2321,10 -2318,6 +2321,10 @@@ static int walk_revs_populate_todo(stru
                        short_commit_name(commit), subject_len, subject);
                unuse_commit_buffer(commit, commit_buffer);
        }
 +
 +      if (!todo_list->nr)
 +              return error(_("empty commit set passed"));
 +
        return 0;
  }
  
@@@ -3226,27 -3219,10 +3226,27 @@@ static int pick_commits(struct todo_lis
                                        intend_to_amend();
                                return error_failed_squash(item->commit, opts,
                                        item->arg_len, item->arg);
 -                      } else if (res && is_rebase_i(opts) && item->commit)
 +                      } else if (res && is_rebase_i(opts) && item->commit) {
 +                              int to_amend = 0;
 +                              struct object_id oid;
 +
 +                              /*
 +                               * If we are rewording and have either
 +                               * fast-forwarded already, or are about to
 +                               * create a new root commit, we want to amend,
 +                               * otherwise we do not.
 +                               */
 +                              if (item->command == TODO_REWORD &&
 +                                  !get_oid("HEAD", &oid) &&
 +                                  (!oidcmp(&item->commit->object.oid, &oid) ||
 +                                   (opts->have_squash_onto &&
 +                                    !oidcmp(&opts->squash_onto, &oid))))
 +                                      to_amend = 1;
 +
                                return res | error_with_patch(item->commit,
 -                                      item->arg, item->arg_len, opts, res,
 -                                      item->command == TODO_REWORD);
 +                                              item->arg, item->arg_len, opts,
 +                                              res, to_amend);
 +                      }
                } else if (item->command == TODO_EXEC) {
                        char *end_of_arg = (char *)(item->arg + item->arg_len);
                        int saved = *end_of_arg;
@@@ -3634,7 -3610,7 +3634,7 @@@ int sequencer_pick_revisions(struct rep
                        continue;
  
                if (!get_oid(name, &oid)) {
-                       if (!lookup_commit_reference_gently(&oid, 1)) {
+                       if (!lookup_commit_reference_gently(the_repository, &oid, 1)) {
                                enum object_type type = oid_object_info(the_repository,
                                                                        &oid,
                                                                        NULL);
                if (prepare_revision_walk(opts->revs))
                        return error(_("revision walk setup failed"));
                cmit = get_revision(opts->revs);
 -              if (!cmit || get_revision(opts->revs))
 -                      return error("BUG: expected exactly one commit from walk");
 +              if (!cmit)
 +                      return error(_("empty commit set passed"));
 +              if (get_revision(opts->revs))
 +                      BUG("unexpected extra commit from walk");
                return single_pick(cmit, opts);
        }
  
@@@ -4022,7 -3996,7 +4022,7 @@@ static int make_script_with_merges(stru
                entry = oidmap_get(&state.commit2label, &commit->object.oid);
  
                if (entry)
 -                      fprintf(out, "\n# Branch %s\n", entry->string);
 +                      fprintf(out, "\n%c Branch %s\n", comment_line_char, entry->string);
                else
                        fprintf(out, "\n");
  
diff --combined sha1-file.c
index 1f66b9594f6b8cc4672ea273a7f657b8e29f6905,c75ef771f8b5c9280466917f8b314d0fe9659884..dfa8a35d68d9b40d4fa30cff15c1f027a201192e
@@@ -336,7 -336,7 +336,7 @@@ out
  static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
  {
        int i;
 -      for (i = 0; i < 20; i++) {
 +      for (i = 0; i < the_hash_algo->rawsz; i++) {
                static char hex[] = "0123456789abcdef";
                unsigned int val = sha1[i];
                strbuf_addch(buf, hex[val >> 4]);
@@@ -1473,7 -1473,7 +1473,7 @@@ void *read_object_with_reference(const 
                }
                ref_length = strlen(ref_type);
  
 -              if (ref_length + GIT_SHA1_HEXSZ > isize ||
 +              if (ref_length + the_hash_algo->hexsz > isize ||
                    memcmp(buffer, ref_type, ref_length) ||
                    get_oid_hex((char *) buffer + ref_length, &actual_oid)) {
                        free(buffer);
@@@ -1801,7 -1801,7 +1801,7 @@@ static void check_commit(const void *bu
  {
        struct commit c;
        memset(&c, 0, sizeof(c));
-       if (parse_commit_buffer(&c, buf, size, 0))
+       if (parse_commit_buffer(the_repository, &c, buf, size, 0))
                die("corrupt commit");
  }
  
@@@ -1809,7 -1809,7 +1809,7 @@@ static void check_tag(const void *buf, 
  {
        struct tag t;
        memset(&t, 0, sizeof(t));
-       if (parse_tag_buffer(&t, buf, size))
+       if (parse_tag_buffer(the_repository, &t, buf, size))
                die("corrupt tag");
  }
  
@@@ -2062,9 -2062,9 +2062,9 @@@ int for_each_file_in_obj_subdir(unsigne
                namelen = strlen(de->d_name);
                strbuf_setlen(path, baselen);
                strbuf_add(path, de->d_name, namelen);
 -              if (namelen == GIT_SHA1_HEXSZ - 2 &&
 +              if (namelen == the_hash_algo->hexsz - 2 &&
                    !hex_to_bytes(oid.hash + 1, de->d_name,
 -                                GIT_SHA1_RAWSZ - 1)) {
 +                                the_hash_algo->rawsz - 1)) {
                        if (obj_cb) {
                                r = obj_cb(&oid, path->buf, data);
                                if (r)
diff --combined sha1-name.c
index e072d48ddafc5d998b9ad42ada4297a01a5fee07,009faab4aefc34f55daf6fd7e6e63ec0f0ee108a..c9cc1318b7394e86704bda95651c9a4db3015b9a
@@@ -239,7 -239,8 +239,8 @@@ static int disambiguate_committish_only
                return 0;
  
        /* We need to do this the hard way... */
-       obj = deref_tag(parse_object(oid), NULL, 0);
+       obj = deref_tag(the_repository, parse_object(the_repository, oid),
+                       NULL, 0);
        if (obj && obj->type == OBJ_COMMIT)
                return 1;
        return 0;
@@@ -263,7 -264,8 +264,8 @@@ static int disambiguate_treeish_only(co
                return 0;
  
        /* We need to do this the hard way... */
-       obj = deref_tag(parse_object(oid), NULL, 0);
+       obj = deref_tag(the_repository, parse_object(the_repository, oid),
+                       NULL, 0);
        if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT))
                return 1;
        return 0;
@@@ -310,7 -312,7 +312,7 @@@ static int init_object_disambiguation(c
  {
        int i;
  
 -      if (len < MINIMUM_ABBREV || len > GIT_SHA1_HEXSZ)
 +      if (len < MINIMUM_ABBREV || len > the_hash_algo->hexsz)
                return -1;
  
        memset(ds, 0, sizeof(*ds));
@@@ -351,14 -353,14 +353,14 @@@ static int show_ambiguous_object(const 
  
        type = oid_object_info(the_repository, oid, NULL);
        if (type == OBJ_COMMIT) {
-               struct commit *commit = lookup_commit(oid);
+               struct commit *commit = lookup_commit(the_repository, oid);
                if (commit) {
                        struct pretty_print_context pp = {0};
                        pp.date_mode.type = DATE_SHORT;
                        format_commit_message(commit, " %ad - %s", &desc, &pp);
                }
        } else if (type == OBJ_TAG) {
-               struct tag *tag = lookup_tag(oid);
+               struct tag *tag = lookup_tag(the_repository, oid);
                if (!parse_tag(tag) && tag->tag)
                        strbuf_addf(&desc, " %s", tag->tag);
        }
@@@ -576,8 -578,6 +578,8 @@@ int find_unique_abbrev_r(char *hex, con
        struct disambiguate_state ds;
        struct min_abbrev_data mad;
        struct object_id oid_ret;
 +      const unsigned hexsz = the_hash_algo->hexsz;
 +
        if (len < 0) {
                unsigned long count = approximate_object_count();
                /*
        }
  
        oid_to_hex_r(hex, oid);
 -      if (len == GIT_SHA1_HEXSZ || !len)
 -              return GIT_SHA1_HEXSZ;
 +      if (len == hexsz || !len)
 +              return hexsz;
  
        mad.init_len = len;
        mad.cur_len = len;
@@@ -708,7 -708,7 +710,7 @@@ static int get_oid_basic(const char *st
        int refs_found = 0;
        int at, reflog_len, nth_prior = 0;
  
 -      if (len == GIT_SHA1_HEXSZ && !get_oid_hex(str, oid)) {
 +      if (len == the_hash_algo->hexsz && !get_oid_hex(str, oid)) {
                if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
                        refs_found = dwim_ref(str, len, &tmp_oid, &real_ref);
                        if (refs_found > 0) {
                int detached;
  
                if (interpret_nth_prior_checkout(str, len, &buf) > 0) {
 -                      detached = (buf.len == GIT_SHA1_HEXSZ && !get_oid_hex(buf.buf, oid));
 +                      detached = (buf.len == the_hash_algo->hexsz && !get_oid_hex(buf.buf, oid));
                        strbuf_release(&buf);
                        if (detached)
                                return 0;
@@@ -846,7 -846,7 +848,7 @@@ static int get_parent(const char *name
  
        if (ret)
                return ret;
-       commit = lookup_commit_reference(&oid);
+       commit = lookup_commit_reference(the_repository, &oid);
        if (parse_commit(commit))
                return -1;
        if (!idx) {
@@@ -874,7 -874,7 +876,7 @@@ static int get_nth_ancestor(const char 
        ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);
        if (ret)
                return ret;
-       commit = lookup_commit_reference(&oid);
+       commit = lookup_commit_reference(the_repository, &oid);
        if (!commit)
                return -1;
  
@@@ -893,7 -893,7 +895,7 @@@ struct object *peel_to_type(const char 
        if (name && !namelen)
                namelen = strlen(name);
        while (1) {
-               if (!o || (!o->parsed && !parse_object(&o->oid)))
+               if (!o || (!o->parsed && !parse_object(the_repository, &o->oid)))
                        return NULL;
                if (expected_type == OBJ_ANY || o->type == expected_type)
                        return o;
@@@ -966,12 -966,12 +968,12 @@@ static int peel_onion(const char *name
        if (get_oid_1(name, sp - name - 2, &outer, lookup_flags))
                return -1;
  
-       o = parse_object(&outer);
+       o = parse_object(the_repository, &outer);
        if (!o)
                return -1;
        if (!expected_type) {
-               o = deref_tag(o, name, sp - name - 2);
-               if (!o || (!o->parsed && !parse_object(&o->oid)))
+               o = deref_tag(the_repository, o, name, sp - name - 2);
+               if (!o || (!o->parsed && !parse_object(the_repository, &o->oid)))
                        return -1;
                oidcpy(oid, &o->oid);
                return 0;
@@@ -1098,11 -1098,12 +1100,12 @@@ static int handle_one_ref(const char *p
                          int flag, void *cb_data)
  {
        struct commit_list **list = cb_data;
-       struct object *object = parse_object(oid);
+       struct object *object = parse_object(the_repository, oid);
        if (!object)
                return 0;
        if (object->type == OBJ_TAG) {
-               object = deref_tag(object, path, strlen(path));
+               object = deref_tag(the_repository, object, path,
+                                  strlen(path));
                if (!object)
                        return 0;
        }
@@@ -1144,7 -1145,7 +1147,7 @@@ static int get_oid_oneline(const char *
                int matches;
  
                commit = pop_most_recent_commit(&list, ONELINE_SEEN);
-               if (!parse_object(&commit->object.oid))
+               if (!parse_object(the_repository, &commit->object.oid))
                        continue;
                buf = get_commit_buffer(commit, NULL);
                p = strstr(buf, "\n\n");
@@@ -1253,13 -1254,13 +1256,13 @@@ int get_oid_mb(const char *name, struc
        }
        if (st)
                return st;
-       one = lookup_commit_reference_gently(&oid_tmp, 0);
+       one = lookup_commit_reference_gently(the_repository, &oid_tmp, 0);
        if (!one)
                return -1;
  
        if (get_oid_committish(dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
                return -1;
-       two = lookup_commit_reference_gently(&oid_tmp, 0);
+       two = lookup_commit_reference_gently(the_repository, &oid_tmp, 0);
        if (!two)
                return -1;
        mbs = get_merge_bases(one, two);
@@@ -1652,7 -1653,6 +1655,7 @@@ static int get_oid_with_context_1(cons
                        struct commit_list *list = NULL;
  
                        for_each_ref(handle_one_ref, &list);
 +                      head_ref(handle_one_ref, &list);
                        commit_list_sort_by_date(&list);
                        return get_oid_oneline(name + 2, oid, list);
                }
diff --combined submodule.c
index 2a6381864e128c0122c1cbab6d148cf3c0d82961,6688dd5d45949597d7d5761c9b88ea9fcceabf2d..6e14547e9e0000e6bf80e9ad21da81795cebcab7
@@@ -517,8 -517,8 +517,8 @@@ static void show_submodule_header(struc
         * Attempt to lookup the commit references, and determine if this is
         * a fast forward or fast backwards update.
         */
-       *left = lookup_commit_reference(one);
-       *right = lookup_commit_reference(two);
+       *left = lookup_commit_reference(the_repository, one);
+       *right = lookup_commit_reference(the_repository, two);
  
        /*
         * Warn about missing commits in the submodule project, but only if
        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();
@@@ -1682,7 -1670,7 +1682,7 @@@ int submodule_move_head(const char *pat
        argv_array_push(&cp.args, new_head ? new_head : empty_tree_oid_hex());
  
        if (run_command(&cp)) {
 -              ret = -1;
 +              ret = error(_("Submodule '%s' could not be updated."), path);
                goto out;
        }
  
  
                        if (is_empty_dir(path))
                                rmdir_or_warn(path);
 +
 +                      submodule_unset_core_worktree(sub);
                }
        }
  out:
diff --combined upload-pack.c
index de6106a9dd5da2a26c93da3516793e885b459c0e,4ca052d0b6418404a81a86df9e434c5a9ba77ab2..82b393ec31917c0c2bcd904668a60b5aaef00633
@@@ -3,6 -3,7 +3,7 @@@
  #include "refs.h"
  #include "pkt-line.h"
  #include "sideband.h"
+ #include "repository.h"
  #include "object-store.h"
  #include "tag.h"
  #include "object.h"
@@@ -65,7 -66,6 +66,7 @@@ static const char *pack_objects_hook
  
  static int filter_capability_requested;
  static int allow_filter;
 +static int allow_ref_in_want;
  static struct list_objects_filter_options filter_options;
  
  static void reset_timeout(void)
@@@ -312,7 -312,7 +313,7 @@@ static int got_oid(const char *hex, str
        if (!has_object_file(oid))
                return -1;
  
-       o = parse_object(oid);
+       o = parse_object(the_repository, oid);
        if (!o)
                die("oops (%s)", oid_to_hex(oid));
        if (o->type == OBJ_COMMIT) {
@@@ -350,7 -350,7 +351,7 @@@ static int reachable(struct commit *wan
                        break;
                }
                if (!commit->object.parsed)
-                       parse_object(&commit->object.oid);
+                       parse_object(the_repository, &commit->object.oid);
                if (commit->object.flags & REACHABLE)
                        continue;
                commit->object.flags |= REACHABLE;
@@@ -380,7 -380,7 +381,7 @@@ static int ok_to_give_up(void
  
                if (want->flags & COMMON_KNOWN)
                        continue;
-               want = deref_tag(want, "a want line", 0);
+               want = deref_tag(the_repository, want, "a want line", 0);
                if (!want || want->type != OBJ_COMMIT) {
                        /* no way to tell if this is reachable by
                         * looking at the ancestry chain alone, so
@@@ -570,7 -570,7 +571,7 @@@ static int get_reachable_list(struct ob
                if (parse_oid_hex(namebuf, &sha1, &p) || *p != '\n')
                        break;
  
-               o = lookup_object(sha1.hash);
+               o = lookup_object(the_repository, sha1.hash);
                if (o && o->type == OBJ_COMMIT) {
                        o->flags &= ~TMP_MARK;
                }
@@@ -801,7 -801,7 +802,7 @@@ static int process_shallow(const char *
                struct object *object;
                if (get_oid_hex(arg, &oid))
                        die("invalid shallow line: %s", line);
-               object = parse_object(&oid);
+               object = parse_object(the_repository, &oid);
                if (!object)
                        return 1;
                if (object->type != OBJ_COMMIT)
@@@ -927,7 -927,7 +928,7 @@@ static void receive_needs(void
                if (allow_filter && parse_feature_request(features, "filter"))
                        filter_capability_requested = 1;
  
-               o = parse_object(&oid_buf);
+               o = parse_object(the_repository, &oid_buf);
                if (!o) {
                        packet_write_fmt(1,
                                         "ERR upload-pack: not our ref %s",
@@@ -1078,8 -1078,6 +1079,8 @@@ static int upload_pack_config(const cha
                        return git_config_string(&pack_objects_hook, var, value);
        } else if (!strcmp("uploadpack.allowfilter", var)) {
                allow_filter = git_config_bool(var, value);
 +      } else if (!strcmp("uploadpack.allowrefinwant", var)) {
 +              allow_ref_in_want = git_config_bool(var, value);
        }
        return parse_hide_refs_config(var, value, "uploadpack");
  }
@@@ -1119,7 -1117,6 +1120,7 @@@ void upload_pack(struct upload_pack_opt
  
  struct upload_pack_data {
        struct object_array wants;
 +      struct string_list wanted_refs;
        struct oid_array haves;
  
        struct object_array shallows;
  static void upload_pack_data_init(struct upload_pack_data *data)
  {
        struct object_array wants = OBJECT_ARRAY_INIT;
 +      struct string_list wanted_refs = STRING_LIST_INIT_DUP;
        struct oid_array haves = OID_ARRAY_INIT;
        struct object_array shallows = OBJECT_ARRAY_INIT;
        struct string_list deepen_not = STRING_LIST_INIT_DUP;
  
        memset(data, 0, sizeof(*data));
        data->wants = wants;
 +      data->wanted_refs = wanted_refs;
        data->haves = haves;
        data->shallows = shallows;
        data->deepen_not = deepen_not;
  static void upload_pack_data_clear(struct upload_pack_data *data)
  {
        object_array_clear(&data->wants);
 +      string_list_clear(&data->wanted_refs, 1);
        oid_array_clear(&data->haves);
        object_array_clear(&data->shallows);
        string_list_clear(&data->deepen_not, 0);
@@@ -1174,7 -1168,7 +1175,7 @@@ static int parse_want(const char *line
                        die("git upload-pack: protocol error, "
                            "expected to get oid, not '%s'", line);
  
-               o = parse_object(&oid);
+               o = parse_object(the_repository, &oid);
                if (!o) {
                        packet_write_fmt(1,
                                         "ERR upload-pack: not our ref %s",
        return 0;
  }
  
 +static int parse_want_ref(const char *line, struct string_list *wanted_refs)
 +{
 +      const char *arg;
 +      if (skip_prefix(line, "want-ref ", &arg)) {
 +              struct object_id oid;
 +              struct string_list_item *item;
 +              struct object *o;
 +
 +              if (read_ref(arg, &oid)) {
 +                      packet_write_fmt(1, "ERR unknown ref %s", arg);
 +                      die("unknown ref %s", arg);
 +              }
 +
 +              item = string_list_append(wanted_refs, arg);
 +              item->util = oiddup(&oid);
 +
 +              o = parse_object_or_die(&oid, arg);
 +              if (!(o->flags & WANTED)) {
 +                      o->flags |= WANTED;
 +                      add_object_array(o, NULL, &want_obj);
 +              }
 +
 +              return 1;
 +      }
 +
 +      return 0;
 +}
 +
  static int parse_have(const char *line, struct oid_array *haves)
  {
        const char *arg;
@@@ -1247,8 -1213,6 +1248,8 @@@ static void process_args(struct packet_
                /* process want */
                if (parse_want(arg))
                        continue;
 +              if (allow_ref_in_want && parse_want_ref(arg, &data->wanted_refs))
 +                      continue;
                /* process have line */
                if (parse_have(arg, &data->haves))
                        continue;
@@@ -1316,7 -1280,7 +1317,7 @@@ static int process_haves(struct oid_arr
  
                oid_array_append(common, oid);
  
-               o = parse_object(oid);
+               o = parse_object(the_repository, oid);
                if (!o)
                        die("oops (%s)", oid_to_hex(oid));
                if (o->type == OBJ_COMMIT) {
@@@ -1391,24 -1355,6 +1392,24 @@@ static int process_haves_and_send_acks(
        return ret;
  }
  
 +static void send_wanted_ref_info(struct upload_pack_data *data)
 +{
 +      const struct string_list_item *item;
 +
 +      if (!data->wanted_refs.nr)
 +              return;
 +
 +      packet_write_fmt(1, "wanted-refs\n");
 +
 +      for_each_string_list_item(item, &data->wanted_refs) {
 +              packet_write_fmt(1, "%s %s\n",
 +                               oid_to_hex(item->util),
 +                               item->string);
 +      }
 +
 +      packet_delim(1);
 +}
 +
  static void send_shallow_info(struct upload_pack_data *data)
  {
        /* No shallow info needs to be sent */
@@@ -1476,7 -1422,6 +1477,7 @@@ int upload_pack_v2(struct repository *r
                                state = FETCH_DONE;
                        break;
                case FETCH_SEND_PACK:
 +                      send_wanted_ref_info(&data);
                        send_shallow_info(&data);
  
                        packet_write_fmt(1, "packfile\n");
@@@ -1497,22 -1442,12 +1498,22 @@@ int upload_pack_advertise(struct reposi
  {
        if (value) {
                int allow_filter_value;
 +              int allow_ref_in_want;
 +
                strbuf_addstr(value, "shallow");
 +
                if (!repo_config_get_bool(the_repository,
                                         "uploadpack.allowfilter",
                                         &allow_filter_value) &&
                    allow_filter_value)
                        strbuf_addstr(value, " filter");
 +
 +              if (!repo_config_get_bool(the_repository,
 +                                       "uploadpack.allowrefinwant",
 +                                       &allow_ref_in_want) &&
 +                  allow_ref_in_want)
 +                      strbuf_addstr(value, " ref-in-want");
        }
 +
        return 1;
  }
diff --combined wt-status.c
index fadbed0de9710643ac595f551f2897133b05f8c9,6c0e400f8130743b0c0fef2764bd804451b016a6..6bf2fdbab67fffb4c9ef451b61bbc7ca8f6780ea
@@@ -1489,7 -1489,7 +1489,7 @@@ static void wt_status_get_detached_from
            /* sha1 is a commit? match without further lookup */
            (!oidcmp(&cb.noid, &oid) ||
             /* perhaps sha1 is a tag, try to dereference to a commit */
-            ((commit = lookup_commit_reference_gently(&oid, 1)) != NULL &&
+            ((commit = lookup_commit_reference_gently(the_repository, &oid, 1)) != NULL &&
              !oidcmp(&cb.noid, &commit->object.oid)))) {
                const char *from = ref;
                if (!skip_prefix(from, "refs/tags/", &from))
@@@ -2340,17 -2340,7 +2340,17 @@@ int has_uncommitted_changes(int ignore_
        if (ignore_submodules)
                rev_info.diffopt.flags.ignore_submodules = 1;
        rev_info.diffopt.flags.quick = 1;
 +
        add_head_to_pending(&rev_info);
-               struct tree *tree = lookup_tree(the_hash_algo->empty_tree);
 +      if (!rev_info.pending.nr) {
 +              /*
 +               * We have no head (or it's corrupt); use the empty tree,
 +               * which will complain if the index is non-empty.
 +               */
++              struct tree *tree = lookup_tree(the_repository, the_hash_algo->empty_tree);
 +              add_pending_object(&rev_info, &tree->object, "");
 +      }
 +
        diff_setup_done(&rev_info.diffopt);
        result = run_diff_index(&rev_info, 1);
        return diff_result_code(&rev_info.diffopt, result);