Add support for GIT_CEILING_DIRECTORIES
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.
---
Changed the name to GIT_CEILING_DIRECTORIES, according to Johannes's version.
Moved the "longest ancestor" function to path.c, for the same reason.
Added path normalization to longest_ancestor_length, per Junio's request.
Moved the tests out of setup.c and into a normal shell script test.
Added tests for a few edge cases per Junio's request. I only added them to the test of longest_ancestor_length rather than the full functional test, because the length is the only interesting input to the setup function.
Tried to simplify things as much as possible. The diff --stat for setup.c is 10 lines with git diff -b.
This version uses the original semantics. Git refuses to look for .git or object in any of the GIT_CEILING_DIRECTORIES when cd'ing up, but will always check the current directory, even if it is a ceiling dir. It remains possible for the root directory to be a git repo. I think this is a good compromise between usability and preventing users who forget about ceiling dirs from being surprised when they can "ls .git" but Git cannot find the repo. If others would prefer different semantics, I'm happy to change them.
I'm happy to help resolve conflicts with the msys branch, if someone wants to point me in the right direction. Or, if it is going to be merged soon, I can just wait and then rebase my changes on top of it.
And if the test suite takes too long, I'm fine commenting most of it out.
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
Documentation/git.txt +8 -0
@@ -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'::
cache.h +2 -0
@@ -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 *);
path.c +43 -0
46 lines not on this page · raw message
setup.c +13 -11
@@ -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: <path>")
@@ -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 ;
t/t0060-path-utils.sh +47 -0
57 lines not on this page · raw message
t/t1504-ceiling-dirs.sh new file +163 -0
163 lines not on this page · raw message
t/test-lib.sh +1 -0
@@ -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
test-path-utils.c +5 -0
@@ -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 ; }
Signature · 1 line
1.5.4