Merge branch 'jk/init-core-worktree-at-root' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 13 May 2015 21:05:49 +0000 (14:05 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 13 May 2015 21:05:49 +0000 (14:05 -0700)
We avoid setting core.worktree when the repository location is the
".git" directory directly at the top level of the working tree, but
the code misdetected the case in which the working tree is at the
root level of the filesystem (which arguably is a silly thing to
do, but still valid).

* jk/init-core-worktree-at-root:
init: don't set core.worktree when initializing /.git

1  2 
builtin/init-db.c
diff --combined builtin/init-db.c
index 6723d39c3baf3571552a57732e4da16278269edf,a6aea7ebb1faa0220c538d07be0e765197831c14..ab9f86b8890ed99547144096ff56c3cbef780505
@@@ -119,18 -119,15 +119,18 @@@ static void copy_templates(const char *
        DIR *dir;
        const char *git_dir = get_git_dir();
        int len = strlen(git_dir);
 +      char *to_free = NULL;
  
        if (!template_dir)
                template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
        if (!template_dir)
                template_dir = init_db_template_dir;
        if (!template_dir)
 -              template_dir = system_path(DEFAULT_GIT_TEMPLATE_DIR);
 -      if (!template_dir[0])
 +              template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR);
 +      if (!template_dir[0]) {
 +              free(to_free);
                return;
 +      }
        template_len = strlen(template_dir);
        if (PATH_MAX <= (template_len+strlen("/config")))
                die(_("insanely long template path %s"), template_dir);
        dir = opendir(template_path);
        if (!dir) {
                warning(_("templates not found %s"), template_dir);
 -              return;
 +              goto free_return;
        }
  
        /* Make sure that template is from the correct vintage */
                        "a wrong format version %d from '%s'"),
                        repository_format_version,
                        template_dir);
 -              closedir(dir);
 -              return;
 +              goto close_free_return;
        }
  
        memcpy(path, git_dir, len);
        copy_templates_1(path, len,
                         template_path, template_len,
                         dir);
 +close_free_return:
        closedir(dir);
 +free_return:
 +      free(to_free);
  }
  
  static int git_init_db_config(const char *k, const char *v, void *cb)
        return 0;
  }
  
+ /*
+  * If the git_dir is not directly inside the working tree, then git will not
+  * find it by default, and we need to set the worktree explicitly.
+  */
+ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
+ {
+       if (!strcmp(work_tree, "/") && !strcmp(git_dir, "/.git"))
+               return 0;
+       if (skip_prefix(git_dir, work_tree, &git_dir) &&
+           !strcmp(git_dir, "/.git"))
+               return 0;
+       return 1;
+ }
  static int create_default_files(const char *template_path)
  {
        const char *git_dir = get_git_dir();
                struct stat st2;
                filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
                                !lstat(path, &st2) &&
 -                              st1.st_mode != st2.st_mode);
 +                              st1.st_mode != st2.st_mode &&
 +                              !chmod(path, st1.st_mode));
 +              if (filemode && !reinit && (st1.st_mode & S_IXUSR))
 +                      filemode = 0;
        }
        git_config_set("core.filemode", filemode ? "true" : "false");
  
                /* allow template config file to override the default */
                if (log_all_ref_updates == -1)
                    git_config_set("core.logallrefupdates", "true");
-               if (!starts_with(git_dir, work_tree) ||
-                   strcmp(git_dir + strlen(work_tree), "/.git")) {
+               if (needs_work_tree_config(git_dir, work_tree))
                        git_config_set("core.worktree", work_tree);
-               }
        }
  
        if (!reinit) {
@@@ -338,12 -342,12 +350,12 @@@ int set_git_dir_init(const char *git_di
                 * moving the target repo later on in separate_git_dir()
                 */
                git_link = xstrdup(real_path(git_dir));
 +              set_git_dir(real_path(real_git_dir));
        }
        else {
 -              real_git_dir = real_path(git_dir);
 +              set_git_dir(real_path(git_dir));
                git_link = NULL;
        }
 -      set_git_dir(real_path(real_git_dir));
        return 0;
  }
  
@@@ -434,9 -438,8 +446,9 @@@ int init_db(const char *template_dir, u
  
  static int guess_repository_type(const char *git_dir)
  {
 -      char cwd[PATH_MAX];
        const char *slash;
 +      char *cwd;
 +      int cwd_is_git_dir;
  
        /*
         * "GIT_DIR=. git init" is always bare.
         */
        if (!strcmp(".", git_dir))
                return 1;
 -      if (!getcwd(cwd, sizeof(cwd)))
 -              die_errno(_("cannot tell cwd"));
 -      if (!strcmp(git_dir, cwd))
 +      cwd = xgetcwd();
 +      cwd_is_git_dir = !strcmp(git_dir, cwd);
 +      free(cwd);
 +      if (cwd_is_git_dir)
                return 1;
        /*
         * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
@@@ -472,7 -474,7 +484,7 @@@ static int shared_callback(const struc
  }
  
  static const char *const init_db_usage[] = {
 -      N_("git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [directory]"),
 +      N_("git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [<directory>]"),
        NULL
  };
  
@@@ -545,9 -547,10 +557,9 @@@ int cmd_init_db(int argc, const char **
                usage(init_db_usage[0]);
        }
        if (is_bare_repository_cfg == 1) {
 -              static char git_dir[PATH_MAX+1];
 -
 -              setenv(GIT_DIR_ENVIRONMENT,
 -                      getcwd(git_dir, sizeof(git_dir)), argc > 0);
 +              char *cwd = xgetcwd();
 +              setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
 +              free(cwd);
        }
  
        if (init_shared_repository != -1)
                        git_work_tree_cfg = xstrdup(real_path(rel));
                        free(rel);
                }
 -              if (!git_work_tree_cfg) {
 -                      git_work_tree_cfg = xcalloc(PATH_MAX, 1);
 -                      if (!getcwd(git_work_tree_cfg, PATH_MAX))
 -                              die_errno (_("Cannot access current working directory"));
 -              }
 +              if (!git_work_tree_cfg)
 +                      git_work_tree_cfg = xgetcwd();
                if (work_tree)
 -                      set_git_work_tree(real_path(work_tree));
 +                      set_git_work_tree(work_tree);
                else
                        set_git_work_tree(git_work_tree_cfg);
                if (access(get_git_work_tree(), X_OK))
        }
        else {
                if (work_tree)
 -                      set_git_work_tree(real_path(work_tree));
 +                      set_git_work_tree(work_tree);
        }
  
        set_git_dir_init(git_dir, real_git_dir, 1);