summaryrefslogtreecommitdiff
path: root/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'setup.c')
-rw-r--r--setup.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/setup.c b/setup.c
index e2a479a64f..65fe5ecefb 100644
--- a/setup.c
+++ b/setup.c
@@ -32,6 +32,7 @@ static int abspath_part_inside_repo(char *path)
char *path0;
int off;
const char *work_tree = get_git_work_tree();
+ struct strbuf realpath = STRBUF_INIT;
if (!work_tree)
return -1;
@@ -60,8 +61,10 @@ static int abspath_part_inside_repo(char *path)
path++;
if (*path == '/') {
*path = '\0';
- if (fspathcmp(real_path(path0), work_tree) == 0) {
+ strbuf_realpath(&realpath, path0, 1);
+ if (fspathcmp(realpath.buf, work_tree) == 0) {
memmove(path0, path + 1, len - (path - path0));
+ strbuf_release(&realpath);
return 0;
}
*path = '/';
@@ -69,11 +72,14 @@ static int abspath_part_inside_repo(char *path)
}
/* check whole path */
- if (fspathcmp(real_path(path0), work_tree) == 0) {
+ strbuf_realpath(&realpath, path0, 1);
+ if (fspathcmp(realpath.buf, work_tree) == 0) {
*path0 = '\0';
+ strbuf_release(&realpath);
return 0;
}
+ strbuf_release(&realpath);
return -1;
}
@@ -120,8 +126,13 @@ char *prefix_path_gently(const char *prefix, int len,
char *prefix_path(const char *prefix, int len, const char *path)
{
char *r = prefix_path_gently(prefix, len, NULL, path);
- if (!r)
- die(_("'%s' is outside repository"), path);
+ if (!r) {
+ const char *hint_path = get_git_work_tree();
+ if (!hint_path)
+ hint_path = get_git_dir();
+ die(_("'%s' is outside repository at '%s'"), path,
+ absolute_path(hint_path));
+ }
return r;
}
@@ -197,9 +208,26 @@ static void NORETURN die_verify_filename(struct repository *r,
*/
static int looks_like_pathspec(const char *arg)
{
- /* anything with a wildcard character */
- if (!no_wildcard(arg))
- return 1;
+ const char *p;
+ int escaped = 0;
+
+ /*
+ * Wildcard characters imply the user is looking to match pathspecs
+ * that aren't in the filesystem. Note that this doesn't include
+ * backslash even though it's a glob special; by itself it doesn't
+ * cause any increase in the match. Likewise ignore backslash-escaped
+ * wildcard characters.
+ */
+ for (p = arg; *p; p++) {
+ if (escaped) {
+ escaped = 0;
+ } else if (is_glob_special(*p)) {
+ if (*p == '\\')
+ escaped = 1;
+ else
+ return 1;
+ }
+ }
/* long-form pathspec magic */
if (starts_with(arg, ":("))
@@ -601,6 +629,7 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
struct stat st;
int fd;
ssize_t len;
+ static struct strbuf realpath = STRBUF_INIT;
if (stat(path, &st)) {
/* NEEDSWORK: discern between ENOENT vs other errors */
@@ -651,7 +680,9 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
error_code = READ_GITFILE_ERR_NOT_A_REPO;
goto cleanup_return;
}
- path = real_path(dir);
+
+ strbuf_realpath(&realpath, dir, 1);
+ path = realpath.buf;
cleanup_return:
if (return_error_code)
@@ -707,7 +738,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
}
/* #18, #26 */
- set_git_dir(gitdirenv);
+ set_git_dir(gitdirenv, 0);
free(gitfile);
return NULL;
}
@@ -729,7 +760,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
}
else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
/* #16d */
- set_git_dir(gitdirenv);
+ set_git_dir(gitdirenv, 0);
free(gitfile);
return NULL;
}
@@ -741,14 +772,14 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
/* both get_git_work_tree() and cwd are already normalized */
if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */
- set_git_dir(gitdirenv);
+ set_git_dir(gitdirenv, 0);
free(gitfile);
return NULL;
}
offset = dir_inside_of(cwd->buf, worktree);
if (offset >= 0) { /* cwd inside worktree? */
- set_git_dir(real_path(gitdirenv));
+ set_git_dir(gitdirenv, 1);
if (chdir(worktree))
die_errno(_("cannot chdir to '%s'"), worktree);
strbuf_addch(cwd, '/');
@@ -757,7 +788,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
}
/* cwd outside worktree */
- set_git_dir(gitdirenv);
+ set_git_dir(gitdirenv, 0);
free(gitfile);
return NULL;
}
@@ -786,7 +817,7 @@ static const char *setup_discovered_git_dir(const char *gitdir,
/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
if (is_bare_repository_cfg > 0) {
- set_git_dir(offset == cwd->len ? gitdir : real_path(gitdir));
+ set_git_dir(gitdir, (offset != cwd->len));
if (chdir(cwd->buf))
die_errno(_("cannot come back to cwd"));
return NULL;
@@ -795,7 +826,7 @@ static const char *setup_discovered_git_dir(const char *gitdir,
/* #0, #1, #5, #8, #9, #12, #13 */
set_git_work_tree(".");
if (strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT))
- set_git_dir(gitdir);
+ set_git_dir(gitdir, 0);
inside_git_dir = 0;
inside_work_tree = 1;
if (offset >= cwd->len)
@@ -838,10 +869,10 @@ static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
die_errno(_("cannot come back to cwd"));
root_len = offset_1st_component(cwd->buf);
strbuf_setlen(cwd, offset > root_len ? offset : root_len);
- set_git_dir(cwd->buf);
+ set_git_dir(cwd->buf, 0);
}
else
- set_git_dir(".");
+ set_git_dir(".", 0);
return NULL;
}
@@ -859,7 +890,7 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
/*
* A "string_list_each_func_t" function that canonicalizes an entry
- * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or
+ * from GIT_CEILING_DIRECTORIES using real_pathdup(), or
* discards it if unusable. The presence of an empty entry in
* GIT_CEILING_DIRECTORIES turns off canonicalization for all
* subsequent entries.
@@ -1235,10 +1266,12 @@ int git_config_perm(const char *var, const char *value)
return -(i & 0666);
}
-void check_repository_format(void)
+void check_repository_format(struct repository_format *fmt)
{
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
- check_repository_format_gently(get_git_dir(), &repo_fmt, NULL);
+ if (!fmt)
+ fmt = &repo_fmt;
+ check_repository_format_gently(get_git_dir(), fmt, NULL);
startup_info->have_repository = 1;
clear_repository_format(&repo_fmt);
}