Merge branch 'jk/core-use-replace-refs'
authorJunio C Hamano <gitster@pobox.com>
Wed, 15 Aug 2018 22:08:22 +0000 (15:08 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Aug 2018 22:08:23 +0000 (15:08 -0700)
A new configuration variable core.usereplacerefs has been added,
primarily to help server installations that want to ignore the
replace mechanism altogether.

* jk/core-use-replace-refs:
add core.usereplacerefs config option
check_replace_refs: rename to read_replace_refs
check_replace_refs: fix outdated comment

12 files changed:
1  2 
Documentation/config.txt
builtin/fsck.c
builtin/index-pack.c
builtin/pack-objects.c
builtin/prune.c
builtin/replace.c
builtin/unpack-objects.c
cache.h
config.c
environment.c
git.c
log-tree.c
diff --combined Documentation/config.txt
index 63365dcf3db6f57f978ed5d2fc67af5fecb0c535,bcf3d21ecb2aa7a2d78d5e9eca82fe1e4e88b5a9..3a4ff5722cfdc2214cfebe93f1f48b6767fa34d1
@@@ -344,16 -344,6 +344,16 @@@ advice.*:
                Advice shown when you used linkgit:git-checkout[1] to
                move to the detach HEAD state, to instruct how to create
                a local branch after the fact.
 +      checkoutAmbiguousRemoteBranchName::
 +              Advice shown when the argument to
 +              linkgit:git-checkout[1] ambiguously resolves to a
 +              remote tracking branch on more than one remote in
 +              situations where an unambiguous argument would have
 +              otherwise caused a remote-tracking branch to be
 +              checked out. See the `checkout.defaultRemote`
 +              configuration variable for how to set a given remote
 +              to used by default in some situations where this
 +              advice would be printed.
        amWorkDir::
                Advice that shows the location of the patch file when
                linkgit:git-am[1] fails to apply it.
@@@ -917,13 -907,15 +917,18 @@@ core.notesRef:
  This setting defaults to "refs/notes/commits", and it can be overridden by
  the `GIT_NOTES_REF` environment variable.  See linkgit:git-notes[1].
  
 -core.commitGraph::
 -      Enable git commit graph feature. Allows reading from the
 -      commit-graph file.
 +gc.commitGraph::
 +      If true, then gc will rewrite the commit-graph file when
 +      linkgit:git-gc[1] is run. When using linkgit:git-gc[1]
 +      '--auto' the commit-graph will be updated if housekeeping is
 +      required. Default is false. See linkgit:git-commit-graph[1]
 +      for details.
  
+ core.useReplaceRefs::
+       If set to `false`, behave as if the `--no-replace-objects`
+       option was given on the command line. See linkgit:git[1] and
+       linkgit:git-replace[1] for more information.
  core.sparseCheckout::
        Enable "sparse checkout" feature. See section "Sparse checkout" in
        linkgit:git-read-tree[1] for more information.
@@@ -1114,22 -1106,6 +1119,22 @@@ browser.<tool>.path:
        browse HTML help (see `-w` option in linkgit:git-help[1]) or a
        working repository in gitweb (see linkgit:git-instaweb[1]).
  
 +checkout.defaultRemote::
 +      When you run 'git checkout <something>' and only have one
 +      remote, it may implicitly fall back on checking out and
 +      tracking e.g. 'origin/<something>'. This stops working as soon
 +      as you have more than one remote with a '<something>'
 +      reference. This setting allows for setting the name of a
 +      preferred remote that should always win when it comes to
 +      disambiguation. The typical use-case is to set this to
 +      `origin`.
 ++
 +Currently this is used by linkgit:git-checkout[1] when 'git checkout
 +<something>' will checkout the '<something>' branch on another remote,
 +and by linkgit:git-worktree[1] when 'git worktree add' refers to a
 +remote branch. This setting might be used for other checkout-like
 +commands or functionality in the future.
 +
  clean.requireForce::
        A boolean to make git-clean do nothing unless given -f,
        -i or -n.   Defaults to true.
@@@ -1178,11 -1154,6 +1183,11 @@@ diff.colorMoved:
        true the default color mode will be used. When set to false,
        moved lines are not colored.
  
 +diff.colorMovedWS::
 +      When moved lines are colored using e.g. the `diff.colorMoved` setting,
 +      this option controls the `<mode>` how spaces are treated
 +      for details of valid modes see '--color-moved-ws' in linkgit:git-diff[1].
 +
  color.diff.<slot>::
        Use customized color for diff colorization.  `<slot>` specifies
        which part of the patch to use the specified color, and is one
@@@ -1531,15 -1502,6 +1536,15 @@@ fetch.output:
        `full` and `compact`. Default value is `full`. See section
        OUTPUT in linkgit:git-fetch[1] for detail.
  
 +fetch.negotiationAlgorithm::
 +      Control how information about the commits in the local repository is
 +      sent when negotiating the contents of the packfile to be sent by the
 +      server. Set to "skipping" to use an algorithm that skips commits in an
 +      effort to converge faster, but may result in a larger-than-necessary
 +      packfile; any other value instructs Git to use the default algorithm
 +      that never skips commits (unless the server has acknowledged it or one
 +      of its descendants).
 +
  format.attach::
        Enable multipart/mixed attachments as the default for
        'format-patch'.  The value can also be a double quoted string
@@@ -3532,13 -3494,6 +3537,13 @@@ Note that this configuration variable i
  repository-level config (this is a safety measure against fetching from
  untrusted repositories).
  
 +uploadpack.allowRefInWant::
 +      If this option is set, `upload-pack` will support the `ref-in-want`
 +      feature of the protocol version 2 `fetch` command.  This feature
 +      is intended for the benefit of load-balanced servers which may
 +      not have the same view of what OIDs their refs point to due to
 +      replication delay.
 +
  url.<base>.insteadOf::
        Any URL that starts with this value will be rewritten to
        start, instead, with <base>. In cases where some site serves a
diff --combined builtin/fsck.c
index c96f3f4fccea0bbd78e4fe1b09e5d8c51e302bb0,0c3cbb86fc29397cc2b7bc79a47363b9acf3a240..250f5af1182ddc66ac0a729c1d39e94d8b19a878
@@@ -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,8 -392,7 +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));
@@@ -413,7 -410,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,
@@@ -455,7 -452,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)) {
                        /*
@@@ -528,9 -525,7 +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",
@@@ -619,7 -614,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));
@@@ -694,7 -689,7 +694,7 @@@ int cmd_fsck(int argc, const char **arg
        fetch_if_missing = 0;
  
        errors_found = 0;
-       check_replace_refs = 0;
+       read_replace_refs = 0;
  
        argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
  
                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 (!git_config_get_bool("core.commitgraph", &i) && i) {
 +              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/index-pack.c
index de311febe3034cb17cb26a57757c144842af8d9f,a24faa0e511cbe2790c6dd1add3d57d62f5558fe..9582ead9507ee27f88386fcc55c044eba233c770
@@@ -832,7 -832,7 +832,7 @@@ static void sha1_object(const void *dat
        if (strict || do_fsck_object) {
                read_lock();
                if (type == OBJ_BLOB) {
 -                      struct blob *blob = lookup_blob(oid);
 +                      struct blob *blob = lookup_blob(the_repository, oid);
                        if (blob)
                                blob->object.flags |= FLAG_CHECKED;
                        else
                         * we do not need to free the memory here, as the
                         * buf is deleted by the caller.
                         */
 -                      obj = parse_object_buffer(oid, type, size, buf,
 +                      obj = parse_object_buffer(the_repository, oid, type,
 +                                                size, buf,
                                                  &eaten);
                        if (!obj)
                                die(_("invalid %s"), type_name(type));
@@@ -1680,7 -1679,7 +1680,7 @@@ int cmd_index_pack(int argc, const cha
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage(index_pack_usage);
  
-       check_replace_refs = 0;
+       read_replace_refs = 0;
        fsck_options.walk = mark_link;
  
        reset_pack_idx_option(&opts);
diff --combined builtin/pack-objects.c
index 4391504a91367bc8c4897e66921fe9a91263f0d0,14235b0ac22145b40f0d96282eb89e2767691d8f..33f23f99ceba8f52271f50759142579f656bcdf4
@@@ -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",
@@@ -3188,7 -3188,7 +3188,7 @@@ int cmd_pack_objects(int argc, const ch
        if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS))
                BUG("too many dfs states, increase OE_DFS_STATE_BITS");
  
-       check_replace_refs = 0;
+       read_replace_refs = 0;
  
        reset_pack_idx_option(&pack_idx_opts);
        git_config(git_pack_config, NULL);
diff --combined builtin/prune.c
index 72b0621b7683e4c7b8efced044b831bf9ebc1941,89f9d8155a6d233b199c75579ab3d2b274bfaeea..4916a4daa264ee695dbfbde81dbd8ef0072ac9c4
@@@ -40,7 -40,7 +40,7 @@@ static int prune_object(const struct ob
         * Do we know about this object?
         * It must have been reachable
         */
 -      if (lookup_object(oid->hash))
 +      if (lookup_object(the_repository, oid->hash))
                return 0;
  
        if (lstat(fullpath, &st)) {
@@@ -118,7 -118,7 +118,7 @@@ int cmd_prune(int argc, const char **ar
  
        expire = TIME_MAX;
        save_commit_buffer = 0;
-       check_replace_refs = 0;
+       read_replace_refs = 0;
        ref_paranoia = 1;
        init_revisions(&revs, prefix);
  
diff --combined builtin/replace.c
index ef22d724bbc74c8f48249da0f68b9878a4d7339c,18609c6a8d2bade96fc418a27e48d13cb24586a8..e997a562f0fc9201f22b3a162621d3888dc1b70c
@@@ -371,7 -371,7 +371,7 @@@ static int replace_parents(struct strbu
                        return error(_("Not a valid object name: '%s'"),
                                     argv[i]);
                }
 -              if (!lookup_commit_reference(&oid)) {
 +              if (!lookup_commit_reference(the_repository, &oid)) {
                        strbuf_release(&new_parents);
                        return error(_("could not parse %s"), argv[i]);
                }
@@@ -402,10 -402,10 +402,10 @@@ static int check_one_mergetag(struct co
        int i;
  
        hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &tag_oid);
 -      tag = lookup_tag(&tag_oid);
 +      tag = lookup_tag(the_repository, &tag_oid);
        if (!tag)
                return error(_("bad mergetag in commit '%s'"), ref);
 -      if (parse_tag_buffer(tag, extra->value, extra->len))
 +      if (parse_tag_buffer(the_repository, tag, extra->value, extra->len))
                return error(_("malformed mergetag in commit '%s'"), ref);
  
        /* iterate over new parents */
@@@ -443,7 -443,7 +443,7 @@@ static int create_graft(int argc, cons
  
        if (get_oid(old_ref, &old_oid) < 0)
                return error(_("Not a valid object name: '%s'"), old_ref);
 -      commit = lookup_commit_reference(&old_oid);
 +      commit = lookup_commit_reference(the_repository, &old_oid);
        if (!commit)
                return error(_("could not parse %s"), old_ref);
  
@@@ -544,7 -544,7 +544,7 @@@ int cmd_replace(int argc, const char **
                OPT_END()
        };
  
-       check_replace_refs = 0;
+       read_replace_refs = 0;
        git_config(git_default_config, NULL);
  
        argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
diff --combined builtin/unpack-objects.c
index 716408e3a9db7499e338905b68444c7dc0a3149f,665fa899f41a53319836240f7d4f3c82a9f213b4..30d9413b4bfb95ad1ee774430b8f954699e46d74
@@@ -254,7 -254,7 +254,7 @@@ static void write_object(unsigned nr, e
                added_object(nr, type, buf, size);
                free(buf);
  
 -              blob = lookup_blob(&obj_list[nr].oid);
 +              blob = lookup_blob(the_repository, &obj_list[nr].oid);
                if (blob)
                        blob->object.flags |= FLAG_WRITTEN;
                else
                int eaten;
                hash_object_file(buf, size, type_name(type), &obj_list[nr].oid);
                added_object(nr, type, buf, size);
 -              obj = parse_object_buffer(&obj_list[nr].oid, type, size, buf,
 +              obj = parse_object_buffer(the_repository, &obj_list[nr].oid,
 +                                        type, size, buf,
                                          &eaten);
                if (!obj)
                        die("invalid %s", type_name(type));
@@@ -332,7 -331,7 +332,7 @@@ static int resolve_against_held(unsigne
  {
        struct object *obj;
        struct obj_buffer *obj_buffer;
 -      obj = lookup_object(base->hash);
 +      obj = lookup_object(the_repository, base->hash);
        if (!obj)
                return 0;
        obj_buffer = lookup_object_buffer(obj);
@@@ -514,7 -513,7 +514,7 @@@ int cmd_unpack_objects(int argc, const 
        int i;
        struct object_id oid;
  
-       check_replace_refs = 0;
+       read_replace_refs = 0;
  
        git_config(git_default_config, NULL);
  
diff --combined cache.h
index 8dc7134f002e0f8bfe693d2679cda6a95fc7c118,3880b6a98bb7c7323385b2d8972416dae326b9ef..8cf62b5aaaad65c070ec53af9aa0e0890857e497
+++ b/cache.h
@@@ -15,7 -15,6 +15,7 @@@
  #include "path.h"
  #include "sha1-array.h"
  #include "repository.h"
 +#include "mem-pool.h"
  
  #include <zlib.h>
  typedef struct git_zstream {
@@@ -157,7 -156,6 +157,7 @@@ struct cache_entry 
        struct stat_data ce_stat_data;
        unsigned int ce_mode;
        unsigned int ce_flags;
 +      unsigned int mem_pool_allocated;
        unsigned int ce_namelen;
        unsigned int index;     /* for link extension */
        struct object_id oid;
  /* Forward structure decls */
  struct pathspec;
  struct child_process;
 +struct tree;
  
  /*
   * Copy the sha1 and stat state of a cache entry from one to
@@@ -230,7 -227,6 +230,7 @@@ static inline void copy_cache_entry(str
                                    const struct cache_entry *src)
  {
        unsigned int state = dst->ce_flags & CE_HASHED;
 +      int mem_pool_allocated = dst->mem_pool_allocated;
  
        /* Don't copy hash chain and name */
        memcpy(&dst->ce_stat_data, &src->ce_stat_data,
  
        /* Restore the hash state */
        dst->ce_flags = (dst->ce_flags & ~CE_HASHED) | state;
 +
 +      /* Restore the mem_pool_allocated flag */
 +      dst->mem_pool_allocated = mem_pool_allocated;
  }
  
  static inline unsigned create_ce_flags(unsigned stage)
@@@ -335,7 -328,6 +335,7 @@@ struct index_state 
        struct untracked_cache *untracked;
        uint64_t fsmonitor_last_update;
        struct ewah_bitmap *fsmonitor_dirty;
 +      struct mem_pool *ce_mem_pool;
  };
  
  extern struct index_state the_index;
@@@ -347,60 -339,6 +347,60 @@@ extern void remove_name_hash(struct ind
  extern void free_name_hash(struct index_state *istate);
  
  
 +/* Cache entry creation and cleanup */
 +
 +/*
 + * Create cache_entry intended for use in the specified index. Caller
 + * is responsible for discarding the cache_entry with
 + * `discard_cache_entry`.
 + */
 +struct cache_entry *make_cache_entry(struct index_state *istate,
 +                                   unsigned int mode,
 +                                   const struct object_id *oid,
 +                                   const char *path,
 +                                   int stage,
 +                                   unsigned int refresh_options);
 +
 +struct cache_entry *make_empty_cache_entry(struct index_state *istate,
 +                                         size_t name_len);
 +
 +/*
 + * Create a cache_entry that is not intended to be added to an index.
 + * Caller is responsible for discarding the cache_entry
 + * with `discard_cache_entry`.
 + */
 +struct cache_entry *make_transient_cache_entry(unsigned int mode,
 +                                             const struct object_id *oid,
 +                                             const char *path,
 +                                             int stage);
 +
 +struct cache_entry *make_empty_transient_cache_entry(size_t name_len);
 +
 +/*
 + * Discard cache entry.
 + */
 +void discard_cache_entry(struct cache_entry *ce);
 +
 +/*
 + * Check configuration if we should perform extra validation on cache
 + * entries.
 + */
 +int should_validate_cache_entries(void);
 +
 +/*
 + * Duplicate a cache_entry. Allocate memory for the new entry from a
 + * memory_pool. Takes into account cache_entry fields that are meant
 + * for managing the underlying memory allocation of the cache_entry.
 + */
 +struct cache_entry *dup_cache_entry(const struct cache_entry *ce, struct index_state *istate);
 +
 +/*
 + * Validate the cache entries in the index.  This is an internal
 + * consistency check that the cache_entry structs are allocated from
 + * the expected memory pool.
 + */
 +void validate_cache_entries(const struct index_state *istate);
 +
  #ifndef NO_THE_INDEX_COMPATIBILITY_MACROS
  #define active_cache (the_index.cache)
  #define active_nr (the_index.cache_nr)
@@@ -697,15 -635,12 +697,15 @@@ extern void move_index_extensions(struc
  extern int unmerged_index(const struct index_state *);
  
  /**
 - * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn
 - * branch, returns 1 if there are entries in the index, 0 otherwise. If an
 - * strbuf is provided, the space-separated list of files that differ will be
 - * appended to it.
 + * Returns 1 if istate differs from tree, 0 otherwise.  If tree is NULL,
 + * compares istate to HEAD.  If tree is NULL and on an unborn branch,
 + * returns 1 if there are entries in istate, 0 otherwise.  If an strbuf is
 + * provided, the space-separated list of files that differ will be appended
 + * to it.
   */
 -extern int index_has_changes(struct strbuf *sb);
 +extern int index_has_changes(const struct index_state *istate,
 +                           struct tree *tree,
 +                           struct strbuf *sb);
  
  extern int verify_path(const char *path, unsigned mode);
  extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
@@@ -763,6 -698,7 +763,6 @@@ extern int remove_file_from_index(struc
  extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
  
 -extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, unsigned int refresh_options);
  extern int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
  extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
  extern void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
@@@ -815,7 -751,7 +815,7 @@@ extern void fill_stat_cache_info(struc
  #define REFRESH_IGNORE_SUBMODULES     0x0010  /* ignore submodules */
  #define REFRESH_IN_PORCELAIN  0x0020  /* user friendly output, not "needs update" */
  extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
 -extern struct cache_entry *refresh_cache_entry(struct cache_entry *, unsigned int);
 +extern struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
  
  /*
   * Opportunistically update the index but do not complain if we can't.
@@@ -868,15 -804,14 +868,13 @@@ void reset_shared_repository(void)
   * Do replace refs need to be checked this run?  This variable is
   * initialized to true unless --no-replace-object is used or
   * $GIT_NO_REPLACE_OBJECTS is set, but is set to false by some
-  * commands that do not want replace references to be active.  As an
-  * optimization it is also set to false if replace references have
-  * been sought but there were none.
+  * commands that do not want replace references to be active.
   */
- extern int check_replace_refs;
+ extern int read_replace_refs;
  extern char *git_replace_ref_base;
  
  extern int fsync_object_files;
  extern int core_preload_index;
 -extern int core_commit_graph;
  extern int core_apply_sparse_checkout;
  extern int precomposed_unicode;
  extern int protect_hfs;
@@@ -1035,7 -970,7 +1033,7 @@@ extern const struct object_id null_oid
  
  static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
  {
 -      return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
 +      return memcmp(sha1, sha2, the_hash_algo->rawsz);
  }
  
  static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2)
@@@ -1055,7 -990,7 +1053,7 @@@ static inline int is_null_oid(const str
  
  static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src)
  {
 -      memcpy(sha_dst, sha_src, GIT_SHA1_RAWSZ);
 +      memcpy(sha_dst, sha_src, the_hash_algo->rawsz);
  }
  
  static inline void oidcpy(struct object_id *dst, const struct object_id *src)
@@@ -1072,7 -1007,7 +1070,7 @@@ static inline struct object_id *oiddup(
  
  static inline void hashclr(unsigned char *hash)
  {
 -      memset(hash, 0, GIT_SHA1_RAWSZ);
 +      memset(hash, 0, the_hash_algo->rawsz);
  }
  
  static inline void oidclr(struct object_id *oid)
diff --combined config.c
index 66645047eb3f9f84f185e0339807548fd562ea7d,5c6d8d17dd6d5321b28d6f4951c241d38b73af15..efe27d5e525a8ce15d588c0dad1fff184952b927
+++ b/config.c
@@@ -32,7 -32,7 +32,7 @@@ struct config_source 
        enum config_origin_type origin_type;
        const char *name;
        const char *path;
 -      int die_on_error;
 +      enum config_error_action default_error_action;
        int linenr;
        int eof;
        struct strbuf value;
@@@ -810,21 -810,10 +810,21 @@@ static int git_parse_source(config_fn_
                                      cf->linenr, cf->name);
        }
  
 -      if (cf->die_on_error)
 +      switch (opts && opts->error_action ?
 +              opts->error_action :
 +              cf->default_error_action) {
 +      case CONFIG_ERROR_DIE:
                die("%s", error_msg);
 -      else
 +              break;
 +      case CONFIG_ERROR_ERROR:
                error_return = error("%s", error_msg);
 +              break;
 +      case CONFIG_ERROR_SILENT:
 +              error_return = -1;
 +              break;
 +      case CONFIG_ERROR_UNSET:
 +              BUG("config error action unset");
 +      }
  
        free(error_msg);
        return error_return;
@@@ -1320,6 -1309,11 +1320,6 @@@ static int git_default_core_config(cons
                return 0;
        }
  
 -      if (!strcmp(var, "core.commitgraph")) {
 -              core_commit_graph = git_config_bool(var, value);
 -              return 0;
 -      }
 -
        if (!strcmp(var, "core.sparsecheckout")) {
                core_apply_sparse_checkout = git_config_bool(var, value);
                return 0;
                                         var, value);
        }
  
+       if (!strcmp(var, "core.usereplacerefs")) {
+               read_replace_refs = git_config_bool(var, value);
+               return 0;
+       }
        /* Add other config variables here and to Documentation/config.txt. */
        return 0;
  }
@@@ -1527,7 -1526,7 +1532,7 @@@ static int do_config_from_file(config_f
        top.origin_type = origin_type;
        top.name = name;
        top.path = path;
 -      top.die_on_error = 1;
 +      top.default_error_action = CONFIG_ERROR_DIE;
        top.do_fgetc = config_file_fgetc;
        top.do_ungetc = config_file_ungetc;
        top.do_ftell = config_file_ftell;
@@@ -1565,10 -1564,8 +1570,10 @@@ int git_config_from_file(config_fn_t fn
        return git_config_from_file_with_options(fn, filename, data, NULL);
  }
  
 -int git_config_from_mem(config_fn_t fn, const enum config_origin_type origin_type,
 -                      const char *name, const char *buf, size_t len, void *data)
 +int git_config_from_mem(config_fn_t fn,
 +                      const enum config_origin_type origin_type,
 +                      const char *name, const char *buf, size_t len,
 +                      void *data, const struct config_options *opts)
  {
        struct config_source top;
  
        top.origin_type = origin_type;
        top.name = name;
        top.path = NULL;
 -      top.die_on_error = 0;
 +      top.default_error_action = CONFIG_ERROR_ERROR;
        top.do_fgetc = config_buf_fgetc;
        top.do_ungetc = config_buf_ungetc;
        top.do_ftell = config_buf_ftell;
  
 -      return do_config_from(&top, fn, data, NULL);
 +      return do_config_from(&top, fn, data, opts);
  }
  
  int git_config_from_blob_oid(config_fn_t fn,
                return error("reference '%s' does not point to a blob", name);
        }
  
 -      ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size, data);
 +      ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size,
 +                                data, NULL);
        free(buf);
  
        return ret;
diff --combined environment.c
index 6cf00793894f75230e5d66d39d56fe2e5388c8a6,3042e5f40f2679b1d7b59cf80bc191752e2a71b9..b9d71a7fecc4de2b1381e71944cc4103e1e5124a
@@@ -51,7 -51,7 +51,7 @@@ const char *editor_program
  const char *askpass_program;
  const char *excludes_file;
  enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
- int check_replace_refs = 1; /* NEEDSWORK: rename to read_replace_refs */
+ int read_replace_refs = 1;
  char *git_replace_ref_base;
  enum eol core_eol = EOL_UNSET;
  int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
@@@ -66,6 -66,7 +66,6 @@@ enum push_default_type push_default = P
  enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
  char *notes_ref_name;
  int grafts_replace_parents = 1;
 -int core_commit_graph;
  int core_apply_sparse_checkout;
  int merge_log_config = -1;
  int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
@@@ -182,7 -183,7 +182,7 @@@ void setup_git_env(const char *git_dir
        argv_array_clear(&to_free);
  
        if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
-               check_replace_refs = 0;
+               read_replace_refs = 0;
        replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
        free(git_replace_ref_base);
        git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
diff --combined git.c
index fc7d15d549e49113fba73ee98161fafd3fd10a56,f4e04a82c929be6bd27982444d20072ed3fc3919..cc0fad93e0ac38459b981b0700260e5832e30cc9
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -164,7 -164,7 +164,7 @@@ static int handle_options(const char **
                        if (envchanged)
                                *envchanged = 1;
                } else if (!strcmp(cmd, "--no-replace-objects")) {
-                       check_replace_refs = 0;
+                       read_replace_refs = 0;
                        setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
                        if (envchanged)
                                *envchanged = 1;
@@@ -414,10 -414,7 +414,10 @@@ static int run_builtin(struct cmd_struc
  
        trace_argv_printf(argv, "trace: built-in: git");
  
 +      validate_cache_entries(&the_index);
        status = p->fn(argc, argv, prefix);
 +      validate_cache_entries(&the_index);
 +
        if (status)
                return status;
  
diff --combined log-tree.c
index c0ac7af7cb6bffea85447ba3af151ee6b8ab65e3,ec3a689c6adef891f1dec427c95fb3fdbd1483a2..7443e5fcc74b7964c478327c6557d53eb4f6b425
@@@ -2,7 -2,6 +2,7 @@@
  #include "config.h"
  #include "diff.h"
  #include "object-store.h"
 +#include "repository.h"
  #include "commit.h"
  #include "tag.h"
  #include "graph.h"
@@@ -92,20 -91,20 +92,20 @@@ static int add_ref_decoration(const cha
  
        if (starts_with(refname, git_replace_ref_base)) {
                struct object_id original_oid;
-               if (!check_replace_refs)
+               if (!read_replace_refs)
                        return 0;
                if (get_oid_hex(refname + strlen(git_replace_ref_base),
                                &original_oid)) {
                        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);
@@@ -498,12 -497,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,
@@@ -547,7 -546,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};