diff options
author | Jiang Xin <worldhello.net@gmail.com> | 2013-10-14 10:29:40 +0800 |
---|---|---|
committer | Jonathan Nieder <jrnieder@gmail.com> | 2013-10-14 07:00:33 -0700 |
commit | 41894ae3a315f75ebc924881c6ce9a69d70ce9c0 (patch) | |
tree | 0142f9019fd20e4f9469e7b97847cbe8a12dcaee /path.c | |
parent | 7fbd422162f2b49bc06a29a063f519450165dc86 (diff) | |
download | git-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>
Diffstat (limited to 'path.c')
-rw-r--r-- | path.c | 45 |
1 files changed, 45 insertions, 0 deletions
@@ -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: |