From ae299be0e5e610027e6492d48d70c1cbb0e9edd8 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Mon, 19 May 2008 23:48:54 -0700 Subject: [PATCH 1/4] Implement normalize_absolute_path normalize_absolute_path removes several oddities form absolute paths, giving nice clean paths like "/dir/sub1/sub2". Also add a test case for this utility, based on a new test program (in the style of test-sha1). Signed-off-by: David Reiss Signed-off-by: Junio C Hamano --- .gitignore | 1 + Makefile | 2 +- cache.h | 1 + path.c | 53 +++++++++++++++++++++++++++++++++++++++++++ t/t0060-path-utils.sh | 40 ++++++++++++++++++++++++++++++++ test-path-utils.c | 13 +++++++++++ 6 files changed, 109 insertions(+), 1 deletion(-) create mode 100755 t/t0060-path-utils.sh create mode 100644 test-path-utils.c diff --git a/.gitignore b/.gitignore index 4ff2fec278..c54c473e94 100644 --- a/.gitignore +++ b/.gitignore @@ -150,6 +150,7 @@ test-dump-cache-tree test-genrandom test-match-trees test-parse-options +test-path-utils test-sha1 common-cmds.h *.tar.gz diff --git a/Makefile b/Makefile index a2de075799..ada85686ea 100644 --- a/Makefile +++ b/Makefile @@ -1186,7 +1186,7 @@ endif ### Testing rules -TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X +TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X test-path-utils$X all:: $(TEST_PROGRAMS) diff --git a/cache.h b/cache.h index 093f04cec0..88c390d9f1 100644 --- a/cache.h +++ b/cache.h @@ -514,6 +514,7 @@ static inline int is_absolute_path(const char *path) return path[0] == '/'; } const char *make_absolute_path(const char *path); +int normalize_absolute_path(char *buf, const char *path); /* 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 b7c24a2aac..7175a06ed8 100644 --- a/path.c +++ b/path.c @@ -357,3 +357,56 @@ const char *make_absolute_path(const char *path) return buf; } + +/* + * path = absolute path + * buf = buffer of at least max(2, strlen(path)+1) bytes + * It is okay if buf == path, but they should not overlap otherwise. + * + * Performs the following normalizations on path, storing the result in buf: + * - Removes trailing slashes. + * - Removes empty components. + * - Removes "." components. + * - Removes ".." components, and the components the precede them. + * "" and paths that contain only slashes are normalized to "/". + * Returns the length of the output. + * + * Note that this function is purely textual. It does not follow symlinks, + * verify the existence of the path, or make any system calls. + */ +int normalize_absolute_path(char *buf, const char *path) +{ + const char *comp_start = path, *comp_end = path; + char *dst = buf; + int comp_len; + assert(buf); + assert(path); + + while (*comp_start) { + assert(*comp_start == '/'); + while (*++comp_end && *comp_end != '/') + ; /* nothing */ + comp_len = comp_end - comp_start; + + if (!strncmp("/", comp_start, comp_len) || + !strncmp("/.", comp_start, comp_len)) + goto next; + + if (!strncmp("/..", comp_start, comp_len)) { + while (dst > buf && *--dst != '/') + ; /* nothing */ + goto next; + } + + memcpy(dst, comp_start, comp_len); + dst += comp_len; + next: + comp_start = comp_end; + } + + if (dst == buf) + *dst++ = '/'; + + *dst = '\0'; + return dst - buf; +} diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh new file mode 100755 index 0000000000..9076b3bd81 --- /dev/null +++ b/t/t0060-path-utils.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# +# Copyright (c) 2008 David Reiss +# + +test_description='Test various path utilities' + +. ./test-lib.sh + +norm_abs() { + test_expect_success "normalize absolute" \ + "test \$(test-path-utils normalize_absolute_path '$1') = '$2'" +} + +norm_abs "" / +norm_abs / / +norm_abs // / +norm_abs /// / +norm_abs /. / +norm_abs /./ / +norm_abs /./.. / +norm_abs /../. / +norm_abs /./../.// / +norm_abs /dir/.. / +norm_abs /dir/sub/../.. / +norm_abs /dir /dir +norm_abs /dir// /dir +norm_abs /./dir /dir +norm_abs /dir/. /dir +norm_abs /dir///./ /dir +norm_abs /dir//sub/.. /dir +norm_abs /dir/sub/../ /dir +norm_abs //dir/sub/../. /dir +norm_abs /dir/s1/../s2/ /dir/s2 +norm_abs /d1/s1///s2/..//../s3/ /d1/s3 +norm_abs /d1/s1//../s2/../../d2 /d2 +norm_abs /d1/.../d2 /d1/.../d2 +norm_abs /d1/..././../d2 /d1/d2 + +test_done diff --git a/test-path-utils.c b/test-path-utils.c new file mode 100644 index 0000000000..1bd43216f6 --- /dev/null +++ b/test-path-utils.c @@ -0,0 +1,13 @@ +#include "cache.h" + +int main(int argc, char **argv) +{ + if (argc == 3 && !strcmp(argv[1], "normalize_absolute_path")) { + char *buf = xmalloc(strlen(argv[2])+1); + int rv = normalize_absolute_path(buf, argv[2]); + assert(strlen(buf) == rv); + puts(buf); + } + + return 0; +} From d553e737897e8edbbc2092bf345fc58b2dae5251 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Mon, 19 May 2008 23:49:00 -0700 Subject: [PATCH 2/4] Fold test-absolute-path into test-path-utils Signed-off-by: David Reiss Signed-off-by: Junio C Hamano --- .gitignore | 1 - Makefile | 2 +- t/t0000-basic.sh | 8 ++++---- test-absolute-path.c | 11 ----------- test-path-utils.c | 8 ++++++++ 5 files changed, 13 insertions(+), 17 deletions(-) delete mode 100644 test-absolute-path.c diff --git a/.gitignore b/.gitignore index c54c473e94..31ea9f13ba 100644 --- a/.gitignore +++ b/.gitignore @@ -142,7 +142,6 @@ git-write-tree git-core-*/?* gitk-wish gitweb/gitweb.cgi -test-absolute-path test-chmtime test-date test-delta diff --git a/Makefile b/Makefile index ada85686ea..c1903b68a8 100644 --- a/Makefile +++ b/Makefile @@ -1186,7 +1186,7 @@ endif ### Testing rules -TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X test-path-utils$X +TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X all:: $(TEST_PROGRAMS) diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 690f80ab27..d7cbc5c6da 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -301,14 +301,14 @@ test_expect_success 'absolute path works as expected' ' mkdir third && dir="$(cd .git; pwd -P)" && dir2=third/../second/other/.git && - test "$dir" = "$(test-absolute-path $dir2)" && + test "$dir" = "$(test-path-utils make_absolute_path $dir2)" && file="$dir"/index && - test "$file" = "$(test-absolute-path $dir2/index)" && + test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" && basename=blub && - test "$dir/$basename" = "$(cd .git && test-absolute-path "$basename")" && + test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" && ln -s ../first/file .git/syml && sym="$(cd first; pwd -P)"/file && - test "$sym" = "$(test-absolute-path "$dir2/syml")" + test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")" ' test_expect_success 'very long name in the index handled sanely' ' diff --git a/test-absolute-path.c b/test-absolute-path.c deleted file mode 100644 index c959ea20d3..0000000000 --- a/test-absolute-path.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "cache.h" - -int main(int argc, char **argv) -{ - while (argc > 1) { - puts(make_absolute_path(argv[1])); - argc--; - argv++; - } - return 0; -} diff --git a/test-path-utils.c b/test-path-utils.c index 1bd43216f6..842b58018f 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -9,5 +9,13 @@ int main(int argc, char **argv) puts(buf); } + if (argc >= 2 && !strcmp(argv[1], "make_absolute_path")) { + while (argc > 2) { + puts(make_absolute_path(argv[2])); + argc--; + argv++; + } + } + return 0; } From 0454dd93bfb2334355ec62fff670d8c6cb3570a1 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Mon, 19 May 2008 23:49:26 -0700 Subject: [PATCH 3/4] Add support for GIT_CEILING_DIRECTORIES Make git recognize a new environment variable that prevents it from chdir'ing up into specified directories when looking for a GIT_DIR. Useful for avoiding slow network directories. For example, I use git in an environment where homedirs are automounted and "ls /home/nonexistent" takes about 9 seconds. Setting GIT_CEILING_DIRS="/home" allows "git help -a" (for bash completion) and "git symbolic-ref" (for my shell prompt) to run in a reasonable time. Signed-off-by: David Reiss Signed-off-by: Junio C Hamano --- Documentation/git.txt | 8 ++ cache.h | 2 + path.c | 43 +++++++++++ setup.c | 24 +++--- t/t0060-path-utils.sh | 47 ++++++++++++ t/t1504-ceiling-dirs.sh | 163 ++++++++++++++++++++++++++++++++++++++++ t/test-lib.sh | 1 + test-path-utils.c | 5 ++ 8 files changed, 282 insertions(+), 11 deletions(-) create mode 100755 t/t1504-ceiling-dirs.sh diff --git a/Documentation/git.txt b/Documentation/git.txt index adcd3e00b2..4ffe802371 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -415,6 +415,14 @@ git so take care if using Cogito etc. This can also be controlled by the '--work-tree' command line option and the core.worktree configuration variable. +'GIT_CEILING_DIRECTORIES':: + This should be a colon-separated list of absolute paths. + If set, it is a list of directories that git should not chdir + up into while looking for a repository directory. + It will not exclude the current working directory or + a GIT_DIR set on the command line or in the environment. + (Useful for excluding slow-loading network directories.) + git Commits ~~~~~~~~~~~ 'GIT_AUTHOR_NAME':: diff --git a/cache.h b/cache.h index 88c390d9f1..833f4cd982 100644 --- a/cache.h +++ b/cache.h @@ -300,6 +300,7 @@ static inline enum object_type object_type(unsigned int mode) #define CONFIG_ENVIRONMENT "GIT_CONFIG" #define CONFIG_LOCAL_ENVIRONMENT "GIT_CONFIG_LOCAL" #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH" +#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" #define GITATTRIBUTES_FILE ".gitattributes" #define INFOATTRIBUTES_FILE "info/attributes" #define ATTRIBUTE_MACRO_PREFIX "[attr]" @@ -515,6 +516,7 @@ static inline int is_absolute_path(const char *path) } const char *make_absolute_path(const char *path); int normalize_absolute_path(char *buf, const char *path); +int longest_ancestor_length(const char *path, const char *prefix_list); /* 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 7175a06ed8..0c4330486b 100644 --- a/path.c +++ b/path.c @@ -410,3 +410,46 @@ int normalize_absolute_path(char *buf, const char *path) *dst = '\0'; return dst - buf; } + +/* + * path = Canonical absolute path + * prefix_list = Colon-separated list of absolute paths + * + * Determines, for each path in parent_list, whether the "prefix" really + * is an ancestor directory of path. Returns the length of the longest + * ancestor directory, excluding any trailing slashes, or -1 if no prefix + * is an ancestor. (Note that this means 0 is returned if prefix_list is + * "/".) "/foo" is not considered an ancestor of "/foobar". Directories + * are not considered to be their own ancestors. path must be in a + * canonical form: empty components, or "." or ".." components are not + * allowed. prefix_list may be null, which is like "". + */ +int longest_ancestor_length(const char *path, const char *prefix_list) +{ + char buf[PATH_MAX+1]; + const char *ceil, *colon; + int len, max_len = -1; + + if (prefix_list == NULL || !strcmp(path, "/")) + return -1; + + for (colon = ceil = prefix_list; *colon; ceil = colon+1) { + for (colon = ceil; *colon && *colon != ':'; colon++); + len = colon - ceil; + if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil)) + continue; + strlcpy(buf, ceil, len+1); + len = normalize_absolute_path(buf, buf); + /* Strip "trailing slashes" from "/". */ + if (len == 1) + len = 0; + + if (!strncmp(path, buf, len) && + path[len] == '/' && + len > max_len) { + max_len = len; + } + } + + return max_len; +} diff --git a/setup.c b/setup.c index b8fd476395..c14b10636f 100644 --- a/setup.c +++ b/setup.c @@ -359,10 +359,11 @@ const char *read_gitfile_gently(const char *path) const char *setup_git_directory_gently(int *nongit_ok) { const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT); + const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT); static char cwd[PATH_MAX+1]; const char *gitdirenv; const char *gitfile_dir; - int len, offset; + int len, offset, ceil_offset; /* * Let's assume that we are in a git repository. @@ -414,6 +415,8 @@ const char *setup_git_directory_gently(int *nongit_ok) if (!getcwd(cwd, sizeof(cwd)-1)) die("Unable to read current working directory"); + ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs); + /* * Test in the following order (relative to the cwd): * - .git (file containing "gitdir: ") @@ -444,17 +447,16 @@ const char *setup_git_directory_gently(int *nongit_ok) return NULL; } chdir(".."); - do { - if (!offset) { - if (nongit_ok) { - if (chdir(cwd)) - die("Cannot come back to cwd"); - *nongit_ok = 1; - return NULL; - } - die("Not a git repository"); + while (--offset > ceil_offset && cwd[offset] != '/'); + if (offset <= ceil_offset) { + if (nongit_ok) { + if (chdir(cwd)) + die("Cannot come back to cwd"); + *nongit_ok = 1; + return NULL; } - } while (cwd[--offset] != '/'); + die("Not a git repository"); + } } inside_git_dir = 0; diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index 9076b3bd81..6e7501f352 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -12,6 +12,11 @@ norm_abs() { "test \$(test-path-utils normalize_absolute_path '$1') = '$2'" } +ancestor() { + test_expect_success "longest ancestor" \ + "test \$(test-path-utils longest_ancestor_length '$1' '$2') = '$3'" +} + norm_abs "" / norm_abs / / norm_abs // / @@ -37,4 +42,46 @@ norm_abs /d1/s1//../s2/../../d2 /d2 norm_abs /d1/.../d2 /d1/.../d2 norm_abs /d1/..././../d2 /d1/d2 +ancestor / "" -1 +ancestor / / -1 +ancestor /foo "" -1 +ancestor /foo : -1 +ancestor /foo ::. -1 +ancestor /foo ::..:: -1 +ancestor /foo / 0 +ancestor /foo /fo -1 +ancestor /foo /foo -1 +ancestor /foo /foo/ -1 +ancestor /foo /bar -1 +ancestor /foo /bar/ -1 +ancestor /foo /foo/bar -1 +ancestor /foo /foo:/bar/ -1 +ancestor /foo /foo/:/bar/ -1 +ancestor /foo /foo::/bar/ -1 +ancestor /foo /:/foo:/bar/ 0 +ancestor /foo /foo:/:/bar/ 0 +ancestor /foo /:/bar/:/foo 0 +ancestor /foo/bar "" -1 +ancestor /foo/bar / 0 +ancestor /foo/bar /fo -1 +ancestor /foo/bar foo -1 +ancestor /foo/bar /foo 4 +ancestor /foo/bar /foo/ 4 +ancestor /foo/bar /foo/ba -1 +ancestor /foo/bar /:/fo 0 +ancestor /foo/bar /foo:/foo/ba 4 +ancestor /foo/bar /bar -1 +ancestor /foo/bar /bar/ -1 +ancestor /foo/bar /fo: -1 +ancestor /foo/bar :/fo -1 +ancestor /foo/bar /foo:/bar/ 4 +ancestor /foo/bar /:/foo:/bar/ 4 +ancestor /foo/bar /foo:/:/bar/ 4 +ancestor /foo/bar /:/bar/:/fo 0 +ancestor /foo/bar /:/bar/ 0 +ancestor /foo/bar :://foo/. 4 +ancestor /foo/bar :://foo/.:: 4 +ancestor /foo/bar //foo/./::/bar 4 +ancestor /foo/bar ::/bar -1 + test_done diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh new file mode 100755 index 0000000000..91b704a3a4 --- /dev/null +++ b/t/t1504-ceiling-dirs.sh @@ -0,0 +1,163 @@ +#!/bin/sh + +test_description='test GIT_CEILING_DIRECTORIES' +. ./test-lib.sh + +test_prefix() { + test_expect_success "$1" \ + "test '$2' = \"\$(git rev-parse --show-prefix)\"" +} + +test_fail() { + test_expect_code 128 "$1: prefix" \ + "git rev-parse --show-prefix" +} + +TRASH_ROOT="$(pwd)" +ROOT_PARENT=$(dirname "$TRASH_ROOT") + + +unset GIT_CEILING_DIRECTORIES +test_prefix no_ceil "" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix ceil_empty "" + +GIT_CEILING_DIRECTORIES="$ROOT_PARENT" +test_prefix ceil_at_parent "" + +GIT_CEILING_DIRECTORIES="$ROOT_PARENT/" +test_prefix ceil_at_parent_slash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_prefix ceil_at_trash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_prefix ceil_at_trash_slash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +test_prefix ceil_at_sub "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" +test_prefix ceil_at_sub_slash "" + + +mkdir -p sub/dir || exit 1 +cd sub/dir || exit 1 + +unset GIT_CEILING_DIRECTORIES +test_prefix subdir_no_ceil "sub/dir/" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix subdir_ceil_empty "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_fail subdir_ceil_at_trash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_fail subdir_ceil_at_trash_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +test_fail subdir_ceil_at_sub + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" +test_fail subdir_ceil_at_sub_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir" +test_prefix subdir_ceil_at_subdir "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir/" +test_prefix subdir_ceil_at_subdir_slash "sub/dir/" + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su" +test_prefix subdir_ceil_at_su "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/" +test_prefix subdir_ceil_at_su_slash "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di" +test_prefix subdir_ceil_at_sub_di "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di" +test_prefix subdir_ceil_at_sub_di_slash "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi" +test_prefix subdir_ceil_at_subdi "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi" +test_prefix subdir_ceil_at_subdi_slash "sub/dir/" + + +GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub" +test_fail second_of_two + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:bar" +test_fail first_of_two + +GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub:bar" +test_fail second_of_three + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +GIT_DIR=../../.git +export GIT_DIR +test_prefix git_dir_specified "" +unset GIT_DIR + + +cd ../.. || exit 1 +mkdir -p s/d || exit 1 +cd s/d || exit 1 + +unset GIT_CEILING_DIRECTORIES +test_prefix sd_no_ceil "s/d/" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix sd_ceil_empty "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_fail sd_ceil_at_trash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_fail sd_ceil_at_trash_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s" +test_fail sd_ceil_at_s + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/" +test_fail sd_ceil_at_s_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d" +test_prefix sd_ceil_at_sd "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d/" +test_prefix sd_ceil_at_sd_slash "s/d/" + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su" +test_prefix sd_ceil_at_su "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/" +test_prefix sd_ceil_at_su_slash "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di" +test_prefix sd_ceil_at_s_di "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di" +test_prefix sd_ceil_at_s_di_slash "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi" +test_prefix sd_ceil_at_sdi "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi" +test_prefix sd_ceil_at_sdi_slash "s/d/" + + +test_done diff --git a/t/test-lib.sh b/t/test-lib.sh index 5002fb04b5..c3a3167382 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -35,6 +35,7 @@ unset GIT_WORK_TREE unset GIT_EXTERNAL_DIFF unset GIT_INDEX_FILE unset GIT_OBJECT_DIRECTORY +unset GIT_CEILING_DIRECTORIES unset SHA1_FILE_DIRECTORIES unset SHA1_FILE_DIRECTORY GIT_MERGE_VERBOSITY=5 diff --git a/test-path-utils.c b/test-path-utils.c index 842b58018f..a0bcb0e210 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -17,5 +17,10 @@ int main(int argc, char **argv) } } + if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) { + int len = longest_ancestor_length(argv[2], argv[3]); + printf("%d\n", len); + } + return 0; } From 450f437fb0fe276a6e946c281c768118e39dc9e7 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Mon, 19 May 2008 23:49:34 -0700 Subject: [PATCH 4/4] Eliminate an unnecessary chdir("..") In the case where setup_git_directory_gently fails, avoid the last chdir("..") by moving it after the ceil_offset check. Signed-off-by: David Reiss Signed-off-by: Junio C Hamano --- setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.c b/setup.c index c14b10636f..045ca20b32 100644 --- a/setup.c +++ b/setup.c @@ -446,7 +446,6 @@ const char *setup_git_directory_gently(int *nongit_ok) check_repository_format_gently(nongit_ok); return NULL; } - chdir(".."); while (--offset > ceil_offset && cwd[offset] != '/'); if (offset <= ceil_offset) { if (nongit_ok) { @@ -457,6 +456,7 @@ const char *setup_git_directory_gently(int *nongit_ok) } die("Not a git repository"); } + chdir(".."); } inside_git_dir = 0;