Commit 41894ae3 authored by Jiang Xin's avatar Jiang Xin Committed by Jonathan Nieder

Use simpler relative_path when set_git_dir

Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbcb.
It will make git_dir shorter only if git_dir is inside work_tree,
and this will increase performance. But my last refactor effort on
relative_path function (commit v1.8.3-rc2-12-ge02ca72f) changed that.
Always use relative_path as git_dir may bring troubles like

Because new relative_path is a combination of original relative_path
from path.c and original path_relative from quote.c, so in order to
restore the origin implementation, save the original relative_path
as remove_leading_path, and call it in setup.c.
Suggested-by: default avatarKarsten Blees <[email protected]>
Signed-off-by: Jiang Xin's avatarJiang Xin <[email protected]>
Signed-off-by: default avatarJonathan Nieder <[email protected]>
parent 7fbd4221
......@@ -737,6 +737,7 @@ int is_directory(const char *);
const char *real_path(const char *path);
const char *real_path_if_valid(const char *path);
const char *absolute_path(const char *path);
const char *remove_leading_path(const char *in, const char *prefix);
const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
int normalize_path_copy(char *dst, const char *src);
int longest_ancestor_length(const char *path, struct string_list *prefixes);
......@@ -557,6 +557,51 @@ const char *relative_path(const char *in, const char *prefix,
return sb->buf;
* A simpler implementation of relative_path
* Get relative path by removing "prefix" from "in". This function
* first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
* to increase performance when traversing the path to work_tree.
const char *remove_leading_path(const char *in, const char *prefix)
static char buf[PATH_MAX + 1];
int i = 0, j = 0;
if (!prefix || !prefix[0])
return in;
while (prefix[i]) {
if (is_dir_sep(prefix[i])) {
if (!is_dir_sep(in[j]))
return in;
while (is_dir_sep(prefix[i]))
while (is_dir_sep(in[j]))
} else if (in[j] != prefix[i]) {
return in;
if (
/* "/foo" is a prefix of "/foo" */
in[j] &&
/* "/foo" is not a prefix of "/foobar" */
!is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
return in;
while (is_dir_sep(in[j]))
if (!in[j])
strcpy(buf, ".");
strcpy(buf, in + j);
return buf;
* It is okay if dst == src, but they should not overlap otherwise.
......@@ -360,7 +360,6 @@ int is_inside_work_tree(void)
void setup_work_tree(void)
struct strbuf sb = STRBUF_INIT;
const char *work_tree, *git_dir;
static int initialized = 0;
......@@ -380,10 +379,8 @@ void setup_work_tree(void)
set_git_dir(relative_path(git_dir, work_tree, &sb));
set_git_dir(remove_leading_path(git_dir, work_tree));
initialized = 1;
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment