X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=setup.c;h=e9d3f5aab63225df7f1b495a19740408d23973a8;hb=eec102524fda2df7d2846e865805ca213119bf10;hp=9a46a58a4a34a345eb9f9b623a255c9bcba4c757;hpb=01fe679a341ed3b1a816404faf76bf454712aa2f;p=git.git diff --git a/setup.c b/setup.c index 9a46a58a4..e9d3f5aab 100644 --- a/setup.c +++ b/setup.c @@ -95,6 +95,8 @@ void verify_non_filename(const char *prefix, const char *arg) const char *name; struct stat st; + if (is_inside_git_dir()) + return; if (*arg == '-') return; /* flag */ name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg; @@ -131,28 +133,69 @@ const char **get_pathspec(const char *prefix, const char **pathspec) } /* - * Test if it looks like we're at the top level git directory. + * Test if it looks like we're at a git directory. * We want to see: * - * - either a .git/objects/ directory _or_ the proper + * - either a objects/ directory _or_ the proper * GIT_OBJECT_DIRECTORY environment variable - * - a refs/ directory under ".git" + * - a refs/ directory * - either a HEAD symlink or a HEAD file that is formatted as - * a proper "ref:". + * a proper "ref:", or a regular file HEAD that has a properly + * formatted sha1 object name. */ -static int is_toplevel_directory(void) +static int is_git_directory(const char *suspect) { - if (access(".git/refs/", X_OK) || - access(getenv(DB_ENVIRONMENT) ? - getenv(DB_ENVIRONMENT) : ".git/objects/", X_OK) || - validate_symref(".git/HEAD")) + char path[PATH_MAX]; + size_t len = strlen(suspect); + + strcpy(path, suspect); + if (getenv(DB_ENVIRONMENT)) { + if (access(getenv(DB_ENVIRONMENT), X_OK)) + return 0; + } + else { + strcpy(path + len, "/objects"); + if (access(path, X_OK)) + return 0; + } + + strcpy(path + len, "/refs"); + if (access(path, X_OK)) return 0; + + strcpy(path + len, "/HEAD"); + if (validate_headref(path)) + return 0; + return 1; } +static int inside_git_dir = -1; + +int is_inside_git_dir(void) +{ + if (inside_git_dir < 0) { + char buffer[1024]; + + if (is_bare_repository()) + return (inside_git_dir = 1); + if (getcwd(buffer, sizeof(buffer))) { + const char *git_dir = get_git_dir(), *cwd = buffer; + while (*git_dir && *git_dir == *cwd) { + git_dir++; + cwd++; + } + inside_git_dir = !*git_dir; + } else + inside_git_dir = 0; + } + return inside_git_dir; +} + const char *setup_git_directory_gently(int *nongit_ok) { static char cwd[PATH_MAX+1]; + const char *gitdirenv; int len, offset; /* @@ -160,36 +203,17 @@ const char *setup_git_directory_gently(int *nongit_ok) * to do any discovery, but we still do repository * validation. */ - if (getenv(GIT_DIR_ENVIRONMENT)) { - char path[PATH_MAX]; - int len = strlen(getenv(GIT_DIR_ENVIRONMENT)); - if (sizeof(path) - 40 < len) + gitdirenv = getenv(GIT_DIR_ENVIRONMENT); + if (gitdirenv) { + if (PATH_MAX - 40 < strlen(gitdirenv)) die("'$%s' too big", GIT_DIR_ENVIRONMENT); - memcpy(path, getenv(GIT_DIR_ENVIRONMENT), len); - - strcpy(path + len, "/refs"); - if (access(path, X_OK)) - goto bad_dir_environ; - strcpy(path + len, "/HEAD"); - if (validate_symref(path)) - goto bad_dir_environ; - if (getenv(DB_ENVIRONMENT)) { - if (access(getenv(DB_ENVIRONMENT), X_OK)) - goto bad_dir_environ; - } - else { - strcpy(path + len, "/objects"); - if (access(path, X_OK)) - goto bad_dir_environ; - } - return NULL; - bad_dir_environ: + if (is_git_directory(gitdirenv)) + return NULL; if (nongit_ok) { *nongit_ok = 1; return NULL; } - path[len] = 0; - die("Not a git repository: '%s'", path); + die("Not a git repository: '%s'", gitdirenv); } if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/') @@ -197,11 +221,18 @@ const char *setup_git_directory_gently(int *nongit_ok) offset = len = strlen(cwd); for (;;) { - if (is_toplevel_directory()) + if (is_git_directory(".git")) break; chdir(".."); do { if (!offset) { + if (is_git_directory(cwd)) { + if (chdir(cwd)) + die("Cannot come back to cwd"); + setenv(GIT_DIR_ENVIRONMENT, cwd, 1); + inside_git_dir = 1; + return NULL; + } if (nongit_ok) { if (chdir(cwd)) die("Cannot come back to cwd"); @@ -220,6 +251,7 @@ const char *setup_git_directory_gently(int *nongit_ok) offset++; cwd[len++] = '/'; cwd[len] = 0; + inside_git_dir = !strncmp(cwd + offset, ".git/", 5); return cwd + offset; } @@ -244,8 +276,6 @@ int check_repository_format_version(const char *var, const char *value) repository_format_version = git_config_int(var, value); else if (strcmp(var, "core.sharedrepository") == 0) shared_repository = git_config_perm(var, value); - else if (strcmp(var, "receive.denynonfastforwards") == 0) - deny_non_fast_forwards = git_config_bool(var, value); return 0; }