Merge branch 'jt/commit-graph-per-object-store'
authorJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:47 +0000 (15:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2018 22:30:47 +0000 (15:30 -0700)
The singleton commit-graph in-core instance is made per in-core
repository instance.

* jt/commit-graph-per-object-store:
commit-graph: add repo arg to graph readers
commit-graph: store graph in struct object_store
commit-graph: add free_commit_graph
commit-graph: add missing forward declaration
object-store: add missing include
commit-graph: refactor preparing commit graph

1  2 
Makefile
cache.h
commit.c
config.c
ref-filter.c
diff --combined Makefile
index 74588d3ddaa0d1dd8365bbf441845db4f08cb166,bb8bd672016ddbe3bf89db9f035b89b85cd3a4a9..bc4fc8eeab21862887c0b19560b07646e0c4848f
+++ b/Makefile
@@@ -719,6 -719,7 +719,7 @@@ TEST_BUILTINS_OBJS += test-prio-queue.
  TEST_BUILTINS_OBJS += test-read-cache.o
  TEST_BUILTINS_OBJS += test-ref-store.o
  TEST_BUILTINS_OBJS += test-regex.o
+ TEST_BUILTINS_OBJS += test-repository.o
  TEST_BUILTINS_OBJS += test-revision-walking.o
  TEST_BUILTINS_OBJS += test-run-command.o
  TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
@@@ -859,7 -860,6 +860,7 @@@ LIB_OBJS += ewah/ewah_bitmap.
  LIB_OBJS += ewah/ewah_io.o
  LIB_OBJS += ewah/ewah_rlw.o
  LIB_OBJS += exec-cmd.o
 +LIB_OBJS += fetch-negotiator.o
  LIB_OBJS += fetch-object.o
  LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
@@@ -892,8 -892,6 +893,8 @@@ LIB_OBJS += merge-blobs.
  LIB_OBJS += merge-recursive.o
  LIB_OBJS += mergesort.o
  LIB_OBJS += name-hash.o
 +LIB_OBJS += negotiator/default.o
 +LIB_OBJS += negotiator/skipping.o
  LIB_OBJS += notes.o
  LIB_OBJS += notes-cache.o
  LIB_OBJS += notes-merge.o
@@@ -2024,9 -2022,8 +2025,9 @@@ version.sp version.s version.o: GIT-VER
  version.sp version.s version.o: EXTRA_CPPFLAGS = \
        '-DGIT_VERSION="$(GIT_VERSION)"' \
        '-DGIT_USER_AGENT=$(GIT_USER_AGENT_CQ_SQ)' \
 -      '-DGIT_BUILT_FROM_COMMIT="$(shell GIT_CEILING_DIRECTORIES=\"$(CURDIR)/..\" \
 -              git rev-parse -q --verify HEAD || :)"'
 +      '-DGIT_BUILT_FROM_COMMIT="$(shell \
 +              GIT_CEILING_DIRECTORIES="$(CURDIR)/.." \
 +              git rev-parse -q --verify HEAD 2>/dev/null)"'
  
  $(BUILT_INS): git$X
        $(QUIET_BUILT_IN)$(RM) $@ && \
@@@ -2114,7 -2111,7 +2115,7 @@@ $(SCRIPT_PERL_GEN): % : %.perl GIT-PERL
        $(QUIET_GEN)$(RM) $@ $@+ && \
        sed -e '1{' \
            -e '        s|#!.*perl|#!$(PERL_PATH_SQ)|' \
 -          -e '        rGIT-PERL-HEADER' \
 +          -e '        r GIT-PERL-HEADER' \
            -e '        G' \
            -e '}' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
diff --combined cache.h
index 87785fc83218cff355f02e2e92a7f819594e5b15,3311f4c9e2711f4560f4151f1777c9b04459345a..8dc7134f002e0f8bfe693d2679cda6a95fc7c118
+++ 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.
@@@ -877,7 -813,6 +877,6 @@@ 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;
@@@ -1036,7 -971,7 +1035,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)
@@@ -1056,7 -991,7 +1055,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)
@@@ -1073,7 -1008,7 +1072,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 commit.c
index add310d4231d4cc71068b64827dc041aae0bb011,39b80bd21d59ca66c113d87371cf5b0159ed2dd9..30d1af2b20660de99bed06486c11d1aef3763849
+++ b/commit.c
@@@ -342,7 -342,7 +342,7 @@@ struct tree *get_commit_tree(const stru
        if (commit->graph_pos == COMMIT_NOT_FROM_GRAPH)
                BUG("commit has NULL tree, but was not loaded from commit-graph");
  
-       return get_commit_tree_in_graph(commit);
+       return get_commit_tree_in_graph(the_repository, commit);
  }
  
  struct object_id *get_commit_tree_oid(const struct commit *commit)
@@@ -388,8 -388,8 +388,8 @@@ int parse_commit_buffer(struct reposito
        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;
        item->date = parse_commit_date(bufptr, tail);
  
        if (check_graph)
-               load_commit_graph_info(item);
+               load_commit_graph_info(the_repository, item);
  
        return 0;
  }
@@@ -454,7 -454,7 +454,7 @@@ int parse_commit_internal(struct commi
                return -1;
        if (item->object.parsed)
                return 0;
-       if (use_commit_graph && parse_commit_in_graph(item))
+       if (use_commit_graph && parse_commit_in_graph(the_repository, item))
                return 0;
        buffer = read_object_file(&item->object.oid, &type, &size);
        if (!buffer)
diff --combined config.c
index 35a9bc79555ade317e965b031a7a8a402bddf43f,3aacddfec4b9dd1a066af099ff018001bfb95d19..66645047eb3f9f84f185e0339807548fd562ea7d
+++ 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,11 -1309,6 +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;
@@@ -1532,7 -1516,7 +1527,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;
@@@ -1570,10 -1554,8 +1565,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;
@@@ -2187,6 -2168,23 +2182,6 @@@ int git_config_get_pathname(const char 
        return repo_config_get_pathname(the_repository, key, dest);
  }
  
 -/*
 - * Note: This function exists solely to maintain backward compatibility with
 - * 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should
 - * NOT be used anywhere else.
 - *
 - * Runs the provided config function on the '.gitmodules' file found in the
 - * working directory.
 - */
 -void config_from_gitmodules(config_fn_t fn, void *data)
 -{
 -      if (the_repository->worktree) {
 -              char *file = repo_worktree_path(the_repository, GITMODULES_FILE);
 -              git_config_from_file(fn, file, data);
 -              free(file);
 -      }
 -}
 -
  int git_config_get_expiry(const char *key, const char **output)
  {
        int ret = git_config_get_string_const(key, output);
diff --combined ref-filter.c
index 600774de68a95ca416b069351cef4724ca7a9cd0,9b2da883926dcee0210b5fd0b0051ee84f9adadb..a8def7b3a36fde5fd4b7184b84f8ae36740642f5
@@@ -1713,7 -1713,7 +1713,7 @@@ static enum contains_result contains_ta
  
        for (p = want; p; p = p->next) {
                struct commit *c = p->item;
-               load_commit_graph_info(c);
+               load_commit_graph_info(the_repository, c);
                if (c->generation < cutoff)
                        cutoff = c->generation;
        }
@@@ -1816,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;
@@@ -1871,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);