diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2012-10-28 17:16:26 +0100 |
---|---|---|
committer | Jeff King <peff@peff.net> | 2012-10-29 02:34:58 -0400 |
commit | 1b77d83cab798668d8a54a05b3fa0262486f7dfc (patch) | |
tree | 4fb68b8b55c5e54486adc75c8a6a31ea9d081cf4 | |
parent | 9e2326c7e1efb1ae42b17e3fa38c16711a8d0bd8 (diff) | |
download | git-1b77d83cab798668d8a54a05b3fa0262486f7dfc.tar.gz git-1b77d83cab798668d8a54a05b3fa0262486f7dfc.tar.xz |
setup_git_directory_gently_1(): resolve symlinks in ceiling paths
longest_ancestor_length() relies on a textual comparison of directory
parts to find the part of path that overlaps with one of the paths in
prefix_list. But this doesn't work if any of the prefixes involves a
symbolic link, because the directories will look different even though
they might logically refer to the same directory. So canonicalize the
paths listed in GIT_CEILING_DIRECTORIES using real_path_if_valid()
before passing them to longest_ancestor_length(). (Also rename
normalize_ceiling_entry() to canonicalize_ceiling_entry() to reflect
the change.)
path is already in canonical form, so doesn't need to be canonicalized
again.
This fixes some problems with using GIT_CEILING_DIRECTORIES that
contains paths involving symlinks, including t4035 if run with --root
set to a path involving symlinks.
Please note that test t0060 is *not* changed analogously, because that
would make the test suite results dependent on the contents of the
local root directory. However, real_path() is already tested
independently, and the "ancestor" tests cover the non-normalization
aspects of longest_ancestor_length(), so coverage remains sufficient.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Jeff King <peff@peff.net>
-rw-r--r-- | setup.c | 26 |
1 files changed, 13 insertions, 13 deletions
@@ -622,24 +622,23 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_ } /* - * A "string_list_each_func_t" function that normalizes an entry from - * GIT_CEILING_DIRECTORIES or discards it if unusable. + * A "string_list_each_func_t" function that canonicalizes an entry + * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or + * discards it if unusable. */ -static int normalize_ceiling_entry(struct string_list_item *item, void *unused) +static int canonicalize_ceiling_entry(struct string_list_item *item, + void *unused) { - const char *ceil = item->string; - int len = strlen(ceil); - char buf[PATH_MAX+1]; + char *ceil = item->string; + const char *real_path; - if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil)) + if (!*ceil || !is_absolute_path(ceil)) return 0; - if (normalize_path_copy(buf, ceil) < 0) + real_path = real_path_if_valid(ceil); + if (!real_path) return 0; - len = strlen(buf); - if (len > 1 && buf[len-1] == '/') - buf[--len] = '\0'; free(item->string); - item->string = xstrdup(buf); + item->string = xstrdup(real_path); return 1; } @@ -681,7 +680,8 @@ static const char *setup_git_directory_gently_1(int *nongit_ok) if (env_ceiling_dirs) { string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1); - filter_string_list(&ceiling_dirs, 0, normalize_ceiling_entry, NULL); + filter_string_list(&ceiling_dirs, 0, + canonicalize_ceiling_entry, NULL); ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs); string_list_clear(&ceiling_dirs, 0); } |