The same old problem reappears after setup code is reworked. We tend to assume there is at least one path component in a path and forget that path can be simply '/'. Reported-by: Matthijs Kooijman <matthijs@xxxxxxxx> Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx> --- cache.h | 2 ++ path.c | 35 +++++++++++++++++++++++++++++++++++ setup.c | 5 ++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/cache.h b/cache.h index f765cf5..f579807 100644 --- a/cache.h +++ b/cache.h @@ -741,6 +741,8 @@ int longest_ancestor_length(const char *path, const char *prefix_list); char *strip_path_suffix(const char *path, const char *suffix); int daemon_avoid_alias(const char *path); int offset_1st_component(const char *path); +int is_subdir_or_same(const char *subdir, const char *dir); +const char *skip_dir(const char *dir, int skip); /* Read and unpack a sha1 file into memory, write memory to a sha1 file */ extern int sha1_object_info(const unsigned char *, unsigned long *); diff --git a/path.c b/path.c index 4d73cc9..9f77aea 100644 --- a/path.c +++ b/path.c @@ -662,3 +662,38 @@ int offset_1st_component(const char *path) return 2 + is_dir_sep(path[2]); return is_dir_sep(path[0]); } + +/* return 1 if subdir is either dir or inside dir */ +int is_subdir_or_same(const char *subdir, const char *dir) +{ + if (!*subdir || !*dir) + die("BUG: how can I compare a dir to empty?"); + + while (*dir && *subdir && *dir == *subdir) { + dir++; + subdir++; + } + + /* help/me vs hell/yeah */ + if (*dir && *subdir) + return 0; + + if (!*subdir) + return !*dir; /* same dir */ + + /* foo/bar vs foo/ */ + if (is_dir_sep(dir[-1])) + return is_dir_sep(subdir[-1]); + + /* foo/bar vs foo */ + return is_dir_sep(*subdir); +} + +/* skip 'skip' chars and the trailing separator if any */ +const char *skip_dir(const char *dir, int skip) +{ + dir += skip; + if (is_dir_sep(*dir)) + dir++; + return dir; +} diff --git a/setup.c b/setup.c index 03cd84f..79f8ea7 100644 --- a/setup.c +++ b/setup.c @@ -390,15 +390,14 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, return NULL; } - if (!prefixcmp(cwd, worktree) && - cwd[strlen(worktree)] == '/') { /* cwd inside worktree */ + if (is_subdir_or_same(cwd, worktree)) { /* cwd inside worktree? */ set_git_dir(real_path(gitdirenv)); if (chdir(worktree)) die_errno("Could not chdir to '%s'", worktree); cwd[len++] = '/'; cwd[len] = '\0'; free(gitfile); - return cwd + strlen(worktree) + 1; + return skip_dir(cwd, strlen(worktree)); } /* cwd outside worktree */ -- 1.7.4.74.g639db -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html