On 02/27, Nguyễn Thái Ngọc Duy wrote:
> It does not make sense that generic repository code contains handling
> of environment variables, which are specific for the main repository
> only. Refactor repo_set_gitdir() function to take $GIT_DIR and
> optionally _all_ other customizable paths. These optional paths can be
> NULL and will be calculated according to the default directory layout.
> 
> Note that some dead functions are left behind to reduce diff
> noise. They will be deleted in the next patch.
> 
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
> ---
>  cache.h       |  2 +-
>  environment.c | 29 +++++++++++++++++++++++++---
>  repository.c  | 53 +++++++++++++++++++++++++++++++++++++++++++++------
>  repository.h  | 11 ++++++++++-
>  setup.c       |  3 +--
>  5 files changed, 85 insertions(+), 13 deletions(-)
> 
> diff --git a/cache.h b/cache.h
> index 5717399183..b164a407eb 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -459,7 +459,7 @@ static inline enum object_type object_type(unsigned int 
> mode)
>   */
>  extern const char * const local_repo_env[];
>  
> -extern void setup_git_env(void);
> +extern void setup_git_env(const char *git_dir);
>  
>  /*
>   * Returns true iff we have a configured git repository (either via
> diff --git a/environment.c b/environment.c
> index ec10b062e6..74a2900ddf 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -14,6 +14,7 @@
>  #include "fmt-merge-msg.h"
>  #include "commit.h"
>  #include "object-store.h"
> +#include "argv-array.h"
>  
>  int trust_executable_bit = 1;
>  int trust_ctime = 1;
> @@ -148,10 +149,33 @@ static char *expand_namespace(const char *raw_namespace)
>       return strbuf_detach(&buf, NULL);
>  }
>  
> -void setup_git_env(void)
> +/* Wrapper of getenv() that returns a strdup value. This value is kept
> + * in argv to be freed later.
> + */
> +static const char *getenv_safe(struct argv_array *argv, const char *name)
> +{
> +     const char *value = getenv(name);
> +
> +     if (!value)
> +             return NULL;
> +
> +     argv_array_push(argv, value);
> +     return argv->argv[argv->argc - 1];
> +}
> +
> +void setup_git_env(const char *git_dir)
>  {
>       const char *shallow_file;
>       const char *replace_ref_base;
> +     struct set_gitdir_args args = { NULL };
> +     struct argv_array to_free = ARGV_ARRAY_INIT;
> +
> +     args.shared_root = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);
> +     args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);
> +     args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);
> +     args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);
> +     repo_set_gitdir(the_repository, git_dir, &args);
> +     argv_array_clear(&to_free);
>  
>       if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
>               check_replace_refs = 0;
> @@ -301,8 +325,7 @@ int set_git_dir(const char *path)
>  {
>       if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
>               return error("Could not set GIT_DIR to '%s'", path);
> -     repo_set_gitdir(the_repository, path);
> -     setup_git_env();
> +     setup_git_env(path);
>       return 0;
>  }
>  
> diff --git a/repository.c b/repository.c
> index a069b1b640..343efe7282 100644
> --- a/repository.c
> +++ b/repository.c
> @@ -61,15 +61,55 @@ static void repo_setup_env(struct repository *repo)
>                                            "index", !repo->ignore_env);
>  }
>  
> -void repo_set_gitdir(struct repository *repo, const char *path)
> +static void expand_base_dir(char **out, const char *in,
> +                         const char *base_dir, const char *def_in)
>  {
> -     const char *gitfile = read_gitfile(path);
> -     char *old_gitdir = repo->gitdir;
> +     free(*out);
> +     if (in)
> +             *out = xstrdup(in);
> +     else
> +             *out = xstrfmt("%s/%s", base_dir, def_in);
> +}
> +
> +static void repo_set_commondir(struct repository *repo,
> +                            const char *shared_root)
> +{
> +     struct strbuf sb = STRBUF_INIT;
> +
> +     free(repo->commondir);
>  
> -     repo->gitdir = xstrdup(gitfile ? gitfile : path);
> -     repo_setup_env(repo);
> +     if (shared_root) {
> +             repo->different_commondir = 1;
> +             repo->commondir = xstrdup(shared_root);
> +             return;
> +     }
>  
> +     repo->different_commondir = get_common_dir_noenv(&sb, repo->gitdir);
> +     repo->commondir = strbuf_detach(&sb, NULL);
> +}
> +
> +void repo_set_gitdir(struct repository *repo,
> +                  const char *root,
> +                  const struct set_gitdir_args *o)
> +{
> +     const char *gitfile = read_gitfile(root);
> +     /*
> +      * repo->gitdir is saved because the caller could pass "root"
> +      * that also points to repo->gitdir. We want to keep it alive
> +      * until after xstrdup(root). Then we can free it.
> +      */
> +     char *old_gitdir = repo->gitdir;
> +
> +     repo->gitdir = xstrdup(gitfile ? gitfile : root);
>       free(old_gitdir);
> +
> +     repo_set_commondir(repo, o->shared_root);
> +     expand_base_dir(&repo->objects.objectdir, o->object_dir,
> +                     repo->commondir, "objects");
> +     expand_base_dir(&repo->graft_file, o->graft_file,
> +                     repo->commondir, "info/grafts");
> +     expand_base_dir(&repo->index_file, o->index_file,
> +                     repo->gitdir, "index");
>  }
>  
>  void repo_set_hash_algo(struct repository *repo, int hash_algo)
> @@ -87,6 +127,7 @@ static int repo_init_gitdir(struct repository *repo, const 
> char *gitdir)
>       int error = 0;
>       char *abspath = NULL;
>       const char *resolved_gitdir;
> +     struct set_gitdir_args args = { NULL };
>  
>       abspath = real_pathdup(gitdir, 0);
>       if (!abspath) {
> @@ -101,7 +142,7 @@ static int repo_init_gitdir(struct repository *repo, 
> const char *gitdir)
>               goto out;
>       }
>  
> -     repo_set_gitdir(repo, resolved_gitdir);
> +     repo_set_gitdir(repo, resolved_gitdir, &args);
>  
>  out:
>       free(abspath);
> diff --git a/repository.h b/repository.h
> index fa73ab8e93..b5b5d138aa 100644
> --- a/repository.h
> +++ b/repository.h
> @@ -89,7 +89,16 @@ struct repository {
>  
>  extern struct repository *the_repository;
>  
> -extern void repo_set_gitdir(struct repository *repo, const char *path);
> +struct set_gitdir_args {
> +     const char *shared_root;

Can you add a comment explaining what shared_root is? From reading the
code it seems to be the common gitdir but its not clear from just
reading this.

> +     const char *object_dir;
> +     const char *graft_file;
> +     const char *index_file;
> +};
> +
> +extern void repo_set_gitdir(struct repository *repo,
> +                         const char *root,
> +                         const struct set_gitdir_args *optional);
>  extern void repo_set_worktree(struct repository *repo, const char *path);
>  extern void repo_set_hash_algo(struct repository *repo, int algo);
>  extern int repo_init(struct repository *repo, const char *gitdir, const char 
> *worktree);
> diff --git a/setup.c b/setup.c
> index c5d55dcee4..6fac1bb58a 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -1116,8 +1116,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
>                       const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
>                       if (!gitdir)
>                               gitdir = DEFAULT_GIT_DIR_ENVIRONMENT;
> -                     repo_set_gitdir(the_repository, gitdir);
> -                     setup_git_env();
> +                     setup_git_env(gitdir);
>               }
>               if (startup_info->have_repository)
>                       repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
> -- 
> 2.16.1.435.g8f24da2e1a
> 

-- 
Brandon Williams

Reply via email to