Skip to content

Commit 5d4ef17

Browse files
committed
Merge branch 'mh/maint-ceil-absolute' into maint
* mh/maint-ceil-absolute: Provide a mechanism to turn off symlink resolution in ceiling paths
2 parents 80659ff + 7ec30aa commit 5d4ef17

File tree

3 files changed

+52
-16
lines changed

3 files changed

+52
-16
lines changed

Documentation/git.txt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -674,12 +674,19 @@ git so take care if using Cogito etc.
674674
The '--namespace' command-line option also sets this value.
675675

676676
'GIT_CEILING_DIRECTORIES'::
677-
This should be a colon-separated list of absolute paths.
678-
If set, it is a list of directories that git should not chdir
679-
up into while looking for a repository directory.
680-
It will not exclude the current working directory or
681-
a GIT_DIR set on the command line or in the environment.
682-
(Useful for excluding slow-loading network directories.)
677+
This should be a colon-separated list of absolute paths. If
678+
set, it is a list of directories that git should not chdir up
679+
into while looking for a repository directory (useful for
680+
excluding slow-loading network directories). It will not
681+
exclude the current working directory or a GIT_DIR set on the
682+
command line or in the environment. Normally, Git has to read
683+
the entries in this list and resolve any symlink that
684+
might be present in order to compare them with the current
685+
directory. However, if even this access is slow, you
686+
can add an empty entry to the list to tell Git that the
687+
subsequent entries are not symlinks and needn't be resolved;
688+
e.g.,
689+
'GIT_CEILING_DIRECTORIES=/maybe/symlink::/very/slow/non/symlink'.
683690

684691
'GIT_DISCOVERY_ACROSS_FILESYSTEM'::
685692
When run in a directory that does not have ".git" repository

setup.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -624,22 +624,32 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
624624
/*
625625
* A "string_list_each_func_t" function that canonicalizes an entry
626626
* from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or
627-
* discards it if unusable.
627+
* discards it if unusable. The presence of an empty entry in
628+
* GIT_CEILING_DIRECTORIES turns off canonicalization for all
629+
* subsequent entries.
628630
*/
629631
static int canonicalize_ceiling_entry(struct string_list_item *item,
630-
void *unused)
632+
void *cb_data)
631633
{
634+
int *empty_entry_found = cb_data;
632635
char *ceil = item->string;
633-
const char *real_path;
634636

635-
if (!*ceil || !is_absolute_path(ceil))
637+
if (!*ceil) {
638+
*empty_entry_found = 1;
636639
return 0;
637-
real_path = real_path_if_valid(ceil);
638-
if (!real_path)
640+
} else if (!is_absolute_path(ceil)) {
639641
return 0;
640-
free(item->string);
641-
item->string = xstrdup(real_path);
642-
return 1;
642+
} else if (*empty_entry_found) {
643+
/* Keep entry but do not canonicalize it */
644+
return 1;
645+
} else {
646+
const char *real_path = real_path_if_valid(ceil);
647+
if (!real_path)
648+
return 0;
649+
free(item->string);
650+
item->string = xstrdup(real_path);
651+
return 1;
652+
}
643653
}
644654

645655
/*
@@ -679,9 +689,11 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
679689
return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
680690

681691
if (env_ceiling_dirs) {
692+
int empty_entry_found = 0;
693+
682694
string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
683695
filter_string_list(&ceiling_dirs, 0,
684-
canonicalize_ceiling_entry, NULL);
696+
canonicalize_ceiling_entry, &empty_entry_found);
685697
ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
686698
string_list_clear(&ceiling_dirs, 0);
687699
}

t/t1504-ceiling-dirs.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ test_prefix ceil_at_sub ""
4444
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
4545
test_prefix ceil_at_sub_slash ""
4646

47+
if test_have_prereq SYMLINKS
48+
then
49+
ln -s sub top
50+
fi
4751

4852
mkdir -p sub/dir || exit 1
4953
cd sub/dir || exit 1
@@ -68,6 +72,19 @@ test_fail subdir_ceil_at_sub
6872
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
6973
test_fail subdir_ceil_at_sub_slash
7074

75+
if test_have_prereq SYMLINKS
76+
then
77+
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/top"
78+
test_fail subdir_ceil_at_top
79+
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/top/"
80+
test_fail subdir_ceil_at_top_slash
81+
82+
GIT_CEILING_DIRECTORIES=":$TRASH_ROOT/top"
83+
test_prefix subdir_ceil_at_top_no_resolve "sub/dir/"
84+
GIT_CEILING_DIRECTORIES=":$TRASH_ROOT/top/"
85+
test_prefix subdir_ceil_at_top_slash_no_resolve "sub/dir/"
86+
fi
87+
7188
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir"
7289
test_prefix subdir_ceil_at_subdir "sub/dir/"
7390

0 commit comments

Comments
 (0)