summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiang Xin <worldhello.net@gmail.com>2013-10-14 10:29:40 +0800
committerJonathan Nieder <jrnieder@gmail.com>2013-10-14 07:00:33 -0700
commit41894ae3a315f75ebc924881c6ce9a69d70ce9c0 (patch)
tree0142f9019fd20e4f9469e7b97847cbe8a12dcaee
parent7fbd422162f2b49bc06a29a063f519450165dc86 (diff)
downloadgit-41894ae3a315f75ebc924881c6ce9a69d70ce9c0.tar.gz
Use simpler relative_path when set_git_dirjx/relative-path-regression-fix
Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc. 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-ge02ca72) changed that. Always use relative_path as git_dir may bring troubles like $gmane/234434. 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: Karsten Blees <karsten.blees@gmail.com> Signed-off-by: Jiang Xin <worldhello.net@gmail.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
-rw-r--r--cache.h1
-rw-r--r--path.c45
-rw-r--r--setup.c5
3 files changed, 47 insertions, 4 deletions
diff --git a/cache.h b/cache.h
index 8e42256942..94475bd9ee 100644
--- a/cache.h
+++ b/cache.h
@@ -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);
diff --git a/path.c b/path.c
index 0c16dc5fdb..fa62da58ed 100644
--- a/path.c
+++ b/path.c
@@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,
}
/*
+ * 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]))
+ i++;
+ while (is_dir_sep(in[j]))
+ j++;
+ continue;
+ } else if (in[j] != prefix[i]) {
+ return in;
+ }
+ i++;
+ j++;
+ }
+ 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]))
+ j++;
+ if (!in[j])
+ strcpy(buf, ".");
+ else
+ strcpy(buf, in + j);
+ return buf;
+}
+
+/*
* It is okay if dst == src, but they should not overlap otherwise.
*
* Performs the following normalizations on src, storing the result in dst:
diff --git a/setup.c b/setup.c
index 0d9ea6239f..dad39c1aba 100644
--- a/setup.c
+++ b/setup.c
@@ -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)
if (getenv(GIT_WORK_TREE_ENVIRONMENT))
setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
- set_git_dir(relative_path(git_dir, work_tree, &sb));
+ set_git_dir(remove_leading_path(git_dir, work_tree));
initialized = 1;
-
- strbuf_release(&sb);
}
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)