Merge branch 'bw/repo-object'
authorJunio C Hamano <gitster@pobox.com>
Wed, 5 Jul 2017 20:32:55 +0000 (13:32 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 5 Jul 2017 20:32:56 +0000 (13:32 -0700)
Introduce a "repository" object to eventually make it easier to
work in multiple repositories (the primary focus is to work with
the superproject and its submodules) in a single process.

* bw/repo-object:
ls-files: use repository object
repository: enable initialization of submodules
submodule: convert is_submodule_initialized to work on a repository
submodule: add repo_read_gitmodules
submodule-config: store the_submodule_cache in the_repository
repository: add index_state to struct repo
config: read config from a repository object
path: add repo_worktree_path and strbuf_repo_worktree_path
path: add repo_git_path and strbuf_repo_git_path
path: worktree_git_path() should not use file relocation
path: convert do_git_path to take a 'struct repository'
path: convert strbuf_git_common_path to take a 'struct repository'
path: always pass in commondir to update_common_dir
path: create path.h
environment: store worktree in the_repository
environment: place key repository state in the_repository
repository: introduce the repository object
environment: remove namespace_len variable
setup: add comment indicating a hack
setup: don't perform lazy initialization of repository state

1  2 
Makefile
builtin/grep.c
config.c
submodule.c
diff --combined Makefile
index b94cd5633c8ebda7e09874a1012fb75cbccc64e0,32e4efc71080c728f49d74961933a83416bd6966..9c9c42f8f9c527a7e2147835a23c4c9af43cb96e
+++ b/Makefile
@@@ -19,8 -19,7 +19,8 @@@ all:
  # have been written to the final string if enough space had been available.
  #
  # Define FREAD_READS_DIRECTORIES if you are on a system which succeeds
 -# when attempting to read from an fopen'ed directory.
 +# when attempting to read from an fopen'ed directory (or even to fopen
 +# it at all).
  #
  # Define NO_OPENSSL environment variable if you do not have OpenSSL.
  # This also implies BLK_SHA1.
@@@ -840,6 -839,7 +840,7 @@@ LIB_OBJS += refs/ref-cache.
  LIB_OBJS += ref-filter.o
  LIB_OBJS += remote.o
  LIB_OBJS += replace_object.o
+ LIB_OBJS += repository.o
  LIB_OBJS += rerere.o
  LIB_OBJS += resolve-undo.o
  LIB_OBJS += revision.o
diff --combined builtin/grep.c
index f752f642fffc757979c3727c55ed3bb14d7d524c,e3ba1d98e3b399941c7c25093f8d5b63327d7d2a..fa351c49f4fd74b3cde1703ef98dba5f0c2c4e8f
@@@ -4,6 -4,7 +4,7 @@@
   * Copyright (c) 2006 Junio C Hamano
   */
  #include "cache.h"
+ #include "repository.h"
  #include "config.h"
  #include "blob.h"
  #include "tree.h"
@@@ -643,11 -644,11 +644,11 @@@ static int grep_submodule_launch(struc
  static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
                          const char *filename, const char *path)
  {
-       if (!is_submodule_initialized(path))
+       if (!is_submodule_active(the_repository, path))
                return 0;
        if (!is_submodule_populated_gently(path, NULL)) {
                /*
 -               * If searching history, check for the presense of the
 +               * If searching history, check for the presence of the
                 * submodule's gitdir before skipping the submodule.
                 */
                if (oid) {
diff --combined config.c
index 1cd40a5fe6802db723de0d0c78b7d316735e80b3,be1c640a4c845bcee1b04f232ea47deda76377d1..4638b0696ab8885afe1fc696dd6e0a25dcc1c89f
+++ b/config.c
@@@ -7,6 -7,7 +7,7 @@@
   */
  #include "cache.h"
  #include "config.h"
+ #include "repository.h"
  #include "lockfile.h"
  #include "exec_cmd.h"
  #include "strbuf.h"
@@@ -72,13 -73,6 +73,6 @@@ static int core_compression_seen
  static int pack_compression_seen;
  static int zlib_compression_seen;
  
- /*
-  * Default config_set that contains key-value pairs from the usual set of config
-  * config files (i.e repo specific .git/config, user wide ~/.gitconfig, XDG
-  * config file and the global /etc/gitconfig)
-  */
- static struct config_set the_config_set;
  static int config_file_fgetc(struct config_source *conf)
  {
        return getc_unlocked(conf->u.file);
@@@ -394,7 -388,8 +388,7 @@@ static int git_config_parse_key_1(cons
  
  out_free_ret_1:
        if (store_key) {
 -              free(*store_key);
 -              *store_key = NULL;
 +              FREE_AND_NULL(*store_key);
        }
        return -CONFIG_INVALID_KEY;
  }
@@@ -1604,31 -1599,6 +1598,6 @@@ int config_with_options(config_fn_t fn
        return do_git_config_sequence(opts, fn, data);
  }
  
- static void git_config_raw(config_fn_t fn, void *data)
- {
-       struct config_options opts = {0};
-       opts.respect_includes = 1;
-       if (have_git_dir()) {
-               opts.commondir = get_git_common_dir();
-               opts.git_dir = get_git_dir();
-       }
-       if (config_with_options(fn, data, NULL, &opts) < 0)
-               /*
-                * config_with_options() normally returns only
-                * zero, as most errors are fatal, and
-                * non-fatal potential errors are guarded by "if"
-                * statements that are entered only when no error is
-                * possible.
-                *
-                * If we ever encounter a non-fatal error, it means
-                * something went really wrong and we should stop
-                * immediately.
-                */
-               die(_("unknown error occurred while reading the configuration files"));
- }
  static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
  {
        int i, value_index;
@@@ -1682,14 -1652,6 +1651,6 @@@ void read_early_config(config_fn_t cb, 
        strbuf_release(&gitdir);
  }
  
- static void git_config_check_init(void);
- void git_config(config_fn_t fn, void *data)
- {
-       git_config_check_init();
-       configset_iter(&the_config_set, fn, data);
- }
  static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
  {
        struct config_set_element k;
@@@ -1899,87 -1861,194 +1860,194 @@@ int git_configset_get_pathname(struct c
                return 1;
  }
  
- static void git_config_check_init(void)
+ /* Functions use to read configuration from a repository */
+ static void repo_read_config(struct repository *repo)
  {
-       if (the_config_set.hash_initialized)
+       struct config_options opts;
+       opts.respect_includes = 1;
+       opts.commondir = repo->commondir;
+       opts.git_dir = repo->gitdir;
+       if (!repo->config)
+               repo->config = xcalloc(1, sizeof(struct config_set));
+       else
+               git_configset_clear(repo->config);
+       git_configset_init(repo->config);
+       if (config_with_options(config_set_callback, repo->config, NULL, &opts) < 0)
+               /*
+                * config_with_options() normally returns only
+                * zero, as most errors are fatal, and
+                * non-fatal potential errors are guarded by "if"
+                * statements that are entered only when no error is
+                * possible.
+                *
+                * If we ever encounter a non-fatal error, it means
+                * something went really wrong and we should stop
+                * immediately.
+                */
+               die(_("unknown error occurred while reading the configuration files"));
+ }
+ static void git_config_check_init(struct repository *repo)
+ {
+       if (repo->config && repo->config->hash_initialized)
                return;
-       git_configset_init(&the_config_set);
-       git_config_raw(config_set_callback, &the_config_set);
+       repo_read_config(repo);
  }
  
void git_config_clear(void)
static void repo_config_clear(struct repository *repo)
  {
-       if (!the_config_set.hash_initialized)
+       if (!repo->config || !repo->config->hash_initialized)
                return;
-       git_configset_clear(&the_config_set);
+       git_configset_clear(repo->config);
  }
  
int git_config_get_value(const char *key, const char **value)
void repo_config(struct repository *repo, config_fn_t fn, void *data)
  {
-       git_config_check_init();
-       return git_configset_get_value(&the_config_set, key, value);
+       git_config_check_init(repo);
+       configset_iter(repo->config, fn, data);
  }
  
- const struct string_list *git_config_get_value_multi(const char *key)
+ int repo_config_get_value(struct repository *repo,
+                         const char *key, const char **value)
  {
-       git_config_check_init();
-       return git_configset_get_value_multi(&the_config_set, key);
+       git_config_check_init(repo);
+       return git_configset_get_value(repo->config, key, value);
  }
  
- int git_config_get_string_const(const char *key, const char **dest)
+ const struct string_list *repo_config_get_value_multi(struct repository *repo,
+                                                     const char *key)
+ {
+       git_config_check_init(repo);
+       return git_configset_get_value_multi(repo->config, key);
+ }
+ int repo_config_get_string_const(struct repository *repo,
+                                const char *key, const char **dest)
+ {
+       int ret;
+       git_config_check_init(repo);
+       ret = git_configset_get_string_const(repo->config, key, dest);
+       if (ret < 0)
+               git_die_config(key, NULL);
+       return ret;
+ }
+ int repo_config_get_string(struct repository *repo,
+                          const char *key, char **dest)
+ {
+       git_config_check_init(repo);
+       return repo_config_get_string_const(repo, key, (const char **)dest);
+ }
+ int repo_config_get_int(struct repository *repo,
+                       const char *key, int *dest)
+ {
+       git_config_check_init(repo);
+       return git_configset_get_int(repo->config, key, dest);
+ }
+ int repo_config_get_ulong(struct repository *repo,
+                         const char *key, unsigned long *dest)
+ {
+       git_config_check_init(repo);
+       return git_configset_get_ulong(repo->config, key, dest);
+ }
+ int repo_config_get_bool(struct repository *repo,
+                        const char *key, int *dest)
+ {
+       git_config_check_init(repo);
+       return git_configset_get_bool(repo->config, key, dest);
+ }
+ int repo_config_get_bool_or_int(struct repository *repo,
+                               const char *key, int *is_bool, int *dest)
+ {
+       git_config_check_init(repo);
+       return git_configset_get_bool_or_int(repo->config, key, is_bool, dest);
+ }
+ int repo_config_get_maybe_bool(struct repository *repo,
+                              const char *key, int *dest)
+ {
+       git_config_check_init(repo);
+       return git_configset_get_maybe_bool(repo->config, key, dest);
+ }
+ int repo_config_get_pathname(struct repository *repo,
+                            const char *key, const char **dest)
  {
        int ret;
-       git_config_check_init();
-       ret = git_configset_get_string_const(&the_config_set, key, dest);
+       git_config_check_init(repo);
+       ret = git_configset_get_pathname(repo->config, key, dest);
        if (ret < 0)
                git_die_config(key, NULL);
        return ret;
  }
  
+ /* Functions used historically to read configuration from 'the_repository' */
+ void git_config(config_fn_t fn, void *data)
+ {
+       repo_config(the_repository, fn, data);
+ }
+ void git_config_clear(void)
+ {
+       repo_config_clear(the_repository);
+ }
+ int git_config_get_value(const char *key, const char **value)
+ {
+       return repo_config_get_value(the_repository, key, value);
+ }
+ const struct string_list *git_config_get_value_multi(const char *key)
+ {
+       return repo_config_get_value_multi(the_repository, key);
+ }
+ int git_config_get_string_const(const char *key, const char **dest)
+ {
+       return repo_config_get_string_const(the_repository, key, dest);
+ }
  int git_config_get_string(const char *key, char **dest)
  {
-       git_config_check_init();
-       return git_config_get_string_const(key, (const char **)dest);
+       return repo_config_get_string(the_repository, key, dest);
  }
  
  int git_config_get_int(const char *key, int *dest)
  {
-       git_config_check_init();
-       return git_configset_get_int(&the_config_set, key, dest);
+       return repo_config_get_int(the_repository, key, dest);
  }
  
  int git_config_get_ulong(const char *key, unsigned long *dest)
  {
-       git_config_check_init();
-       return git_configset_get_ulong(&the_config_set, key, dest);
+       return repo_config_get_ulong(the_repository, key, dest);
  }
  
  int git_config_get_bool(const char *key, int *dest)
  {
-       git_config_check_init();
-       return git_configset_get_bool(&the_config_set, key, dest);
+       return repo_config_get_bool(the_repository, key, dest);
  }
  
  int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)
  {
-       git_config_check_init();
-       return git_configset_get_bool_or_int(&the_config_set, key, is_bool, dest);
+       return repo_config_get_bool_or_int(the_repository, key, is_bool, dest);
  }
  
  int git_config_get_maybe_bool(const char *key, int *dest)
  {
-       git_config_check_init();
-       return git_configset_get_maybe_bool(&the_config_set, key, dest);
+       return repo_config_get_maybe_bool(the_repository, key, dest);
  }
  
  int git_config_get_pathname(const char *key, const char **dest)
  {
-       int ret;
-       git_config_check_init();
-       ret = git_configset_get_pathname(&the_config_set, key, dest);
-       if (ret < 0)
-               git_die_config(key, NULL);
-       return ret;
+       return repo_config_get_pathname(the_repository, key, dest);
  }
  
  int git_config_get_expiry(const char *key, const char **output)
diff --combined submodule.c
index 71e0c5a85b2c3c52bf400f4712ceb447b814f769,b23c2531183fcd7bc37b4638b6f56a3facac9553..da2b4848791382b30147cd8fe921996cfb8a92a7
@@@ -1,4 -1,5 +1,5 @@@
  #include "cache.h"
+ #include "repository.h"
  #include "config.h"
  #include "submodule-config.h"
  #include "submodule.h"
@@@ -255,6 -256,20 +256,20 @@@ void gitmodules_config(void
        }
  }
  
+ static int gitmodules_cb(const char *var, const char *value, void *data)
+ {
+       struct repository *repo = data;
+       return submodule_config_option(repo, var, value);
+ }
+ void repo_read_gitmodules(struct repository *repo)
+ {
+       char *gitmodules_path = repo_worktree_path(repo, ".gitmodules");
+       git_config_from_file(gitmodules_cb, gitmodules_path, repo);
+       free(gitmodules_path);
+ }
  void gitmodules_config_sha1(const unsigned char *commit_sha1)
  {
        struct strbuf rev = STRBUF_INIT;
  }
  
  /*
-  * NEEDSWORK: With the addition of different configuration options to determine
-  * if a submodule is of interests, the validity of this function's name comes
-  * into question.  Once the dust has settled and more concrete terminology is
-  * decided upon, come up with a more proper name for this function.  One
-  * potential candidate could be 'is_submodule_active()'.
-  *
   * Determine if a submodule has been initialized at a given 'path'
   */
- int is_submodule_initialized(const char *path)
+ int is_submodule_active(struct repository *repo, const char *path)
  {
        int ret = 0;
        char *key = NULL;
        char *value = NULL;
        const struct string_list *sl;
-       const struct submodule *module = submodule_from_path(null_sha1, path);
+       const struct submodule *module;
+       module = submodule_from_cache(repo, null_sha1, path);
  
        /* early return if there isn't a path->module mapping */
        if (!module)
  
        /* submodule.<name>.active is set */
        key = xstrfmt("submodule.%s.active", module->name);
-       if (!git_config_get_bool(key, &ret)) {
+       if (!repo_config_get_bool(repo, key, &ret)) {
                free(key);
                return ret;
        }
        free(key);
  
        /* submodule.active is set */
-       sl = git_config_get_value_multi("submodule.active");
+       sl = repo_config_get_value_multi(repo, "submodule.active");
        if (sl) {
                struct pathspec ps;
                struct argv_array args = ARGV_ARRAY_INIT;
  
        /* fallback to checking if the URL is set */
        key = xstrfmt("submodule.%s.url", module->name);
-       ret = !git_config_get_string(key, &value);
+       ret = !repo_config_get_string(repo, key, &value);
  
        free(value);
        free(key);
@@@ -846,9 -857,9 +857,9 @@@ static int submodule_has_commits(const 
        int has_commit = 1;
  
        /*
 -       * Perform a cheap, but incorrect check for the existance of 'commits'.
 +       * Perform a cheap, but incorrect check for the existence of 'commits'.
         * This is done by adding the submodule's object store to the in-core
 -       * object store, and then querying for each commit's existance.  If we
 +       * object store, and then querying for each commit's existence.  If we
         * do not have the commit object anywhere, there is no chance we have
         * it in the object store of the correct submodule and have it
         * reachable from a ref, so we can fail early without spawning rev-list
@@@ -1517,7 -1528,7 +1528,7 @@@ int submodule_move_head(const char *pat
        const struct submodule *sub;
        int *error_code_ptr, error_code;
  
-       if (!is_submodule_initialized(path))
+       if (!is_submodule_active(the_repository, path))
                return 0;
  
        if (flags & SUBMODULE_MOVE_HEAD_FORCE)