Merge branch 'maint' of git://linux-nfs.org/~bfields/git into maint
[gitweb.git] / builtin-init-db.c
index 0d9b1e0559d04ebda464d2975aaf196378eeb481..763fa55e76ef5b7e2f244f11199b5925382dac92 100644 (file)
@@ -264,9 +264,62 @@ static int create_default_files(const char *git_dir, const char *template_path)
                if (work_tree != git_work_tree_cfg)
                        git_config_set("core.worktree", work_tree);
        }
+
+       /* Check if symlink is supported in the work tree */
+       if (!reinit) {
+               path[len] = 0;
+               strcpy(path + len, "tXXXXXX");
+               if (!close(xmkstemp(path)) &&
+                   !unlink(path) &&
+                   !symlink("testing", path) &&
+                   !lstat(path, &st1) &&
+                   S_ISLNK(st1.st_mode))
+                       unlink(path); /* good */
+               else
+                       git_config_set("core.symlinks", "false");
+       }
+
        return reinit;
 }
 
+static void guess_repository_type(const char *git_dir)
+{
+       char cwd[PATH_MAX];
+       const char *slash;
+
+       if (0 <= is_bare_repository_cfg)
+               return;
+       if (!git_dir)
+               return;
+
+       /*
+        * "GIT_DIR=. git init" is always bare.
+        * "GIT_DIR=`pwd` git init" too.
+        */
+       if (!strcmp(".", git_dir))
+               goto force_bare;
+       if (!getcwd(cwd, sizeof(cwd)))
+               die("cannot tell cwd");
+       if (!strcmp(git_dir, cwd))
+               goto force_bare;
+       /*
+        * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
+        */
+       if (!strcmp(git_dir, ".git"))
+               return;
+       slash = strrchr(git_dir, '/');
+       if (slash && !strcmp(slash, "/.git"))
+               return;
+
+       /*
+        * Otherwise it is often bare.  At this point
+        * we are just guessing.
+        */
+ force_bare:
+       is_bare_repository_cfg = 1;
+       return;
+}
+
 static const char init_db_usage[] =
 "git-init [-q | --quiet] [--template=<template-directory>] [--shared]";
 
@@ -299,11 +352,28 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                        usage(init_db_usage);
        }
 
-       git_work_tree_cfg = xcalloc(PATH_MAX, 1);
-       if (!getcwd(git_work_tree_cfg, PATH_MAX))
-               die ("Cannot access current working directory.");
-       if (access(get_git_work_tree(), X_OK))
-               die ("Cannot access work tree '%s'", get_git_work_tree());
+       /*
+        * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
+        * without --bare.  Catch the error early.
+        */
+       git_dir = getenv(GIT_DIR_ENVIRONMENT);
+       if ((!git_dir || is_bare_repository_cfg == 1)
+           && getenv(GIT_WORK_TREE_ENVIRONMENT))
+               die("%s (or --work-tree=<directory>) not allowed without "
+                   "specifying %s (or --git-dir=<directory>)",
+                   GIT_WORK_TREE_ENVIRONMENT,
+                   GIT_DIR_ENVIRONMENT);
+
+       guess_repository_type(git_dir);
+
+       if (is_bare_repository_cfg <= 0) {
+               git_work_tree_cfg = xcalloc(PATH_MAX, 1);
+               if (!getcwd(git_work_tree_cfg, PATH_MAX))
+                       die ("Cannot access current working directory.");
+               if (access(get_git_work_tree(), X_OK))
+                       die ("Cannot access work tree '%s'",
+                            get_git_work_tree());
+       }
 
        /*
         * Set up the default .git directory contents