All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks
@ 2012-10-28 16:16 Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 1/8] Introduce new static function real_path_internal() Michael Haggerty
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty

v4 of the series; see the cover letter for v3 [1] for more editorial
comments.

Changes since v3:

* For "test-path-utils longest_ancestor_length", normalize all of the
  paths using normalize_path_copy() to counteract the path mangling
  carried out by bash on Windows.  (Thanks to Johannes Sixt for his
  helpful advice.)

* Rebased onto a more recent master.

[1] http://thread.gmane.org/gmane.comp.version-control.git/208102

Michael Haggerty (8):
  Introduce new static function real_path_internal()
  real_path_internal(): add comment explaining use of cwd
  Introduce new function real_path_if_valid()
  longest_ancestor_length(): use string_list_split()
  longest_ancestor_length(): take a string_list argument for prefixes
  longest_ancestor_length(): require prefix list entries to be
    normalized
  setup_git_directory_gently_1(): resolve symlinks in ceiling paths
  string_list_longest_prefix(): remove function

 Documentation/technical/api-string-list.txt |   8 ---
 abspath.c                                   | 105 ++++++++++++++++++++++------
 cache.h                                     |   3 +-
 path.c                                      |  46 ++++++------
 setup.c                                     |  34 ++++++++-
 string-list.c                               |  20 ------
 string-list.h                               |   8 ---
 t/t0060-path-utils.sh                       |  41 ++++-------
 t/t0063-string-list.sh                      |  30 --------
 test-path-utils.c                           |  51 +++++++++++++-
 test-string-list.c                          |  20 ------
 11 files changed, 202 insertions(+), 164 deletions(-)

-- 
1.8.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v4 1/8] Introduce new static function real_path_internal()
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 2/8] real_path_internal(): add comment explaining use of cwd Michael Haggerty
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty

It accepts a new parameter, die_on_error.  If die_on_error is false,
it simply cleans up after itself and returns NULL rather than dying.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 abspath.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 72 insertions(+), 21 deletions(-)

diff --git a/abspath.c b/abspath.c
index 05f2d79..a7ab8e9 100644
--- a/abspath.c
+++ b/abspath.c
@@ -15,15 +15,26 @@ int is_directory(const char *path)
 #define MAXDEPTH 5
 
 /*
- * Use this to get the real path, i.e. resolve links. If you want an
- * absolute path but don't mind links, use absolute_path.
+ * Return the real path (i.e., absolute path, with symlinks resolved
+ * and extra slashes removed) equivalent to the specified path.  (If
+ * you want an absolute path but don't mind links, use
+ * absolute_path().)  The return value is a pointer to a static
+ * buffer.
+ *
+ * The input and all intermediate paths must be shorter than MAX_PATH.
+ * The directory part of path (i.e., everything up to the last
+ * dir_sep) must denote a valid, existing directory, but the last
+ * component need not exist.  If die_on_error is set, then die with an
+ * informative error message if there is a problem.  Otherwise, return
+ * NULL on errors (without generating any output).
  *
  * If path is our buffer, then return path, as it's already what the
  * user wants.
  */
-const char *real_path(const char *path)
+static const char *real_path_internal(const char *path, int die_on_error)
 {
 	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+	char *retval = NULL;
 	char cwd[1024] = "";
 	int buf_index = 1;
 
@@ -35,11 +46,19 @@ const char *real_path(const char *path)
 	if (path == buf || path == next_buf)
 		return path;
 
-	if (!*path)
-		die("The empty string is not a valid path");
+	if (!*path) {
+		if (die_on_error)
+			die("The empty string is not a valid path");
+		else
+			goto error_out;
+	}
 
-	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-		die ("Too long path: %.*s", 60, path);
+	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
+		if (die_on_error)
+			die("Too long path: %.*s", 60, path);
+		else
+			goto error_out;
+	}
 
 	while (depth--) {
 		if (!is_directory(buf)) {
@@ -54,20 +73,36 @@ const char *real_path(const char *path)
 		}
 
 		if (*buf) {
-			if (!*cwd && !getcwd(cwd, sizeof(cwd)))
-				die_errno ("Could not get current working directory");
+			if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
+				if (die_on_error)
+					die_errno("Could not get current working directory");
+				else
+					goto error_out;
+			}
 
-			if (chdir(buf))
-				die_errno ("Could not switch to '%s'", buf);
+			if (chdir(buf)) {
+				if (die_on_error)
+					die_errno("Could not switch to '%s'", buf);
+				else
+					goto error_out;
+			}
+		}
+		if (!getcwd(buf, PATH_MAX)) {
+			if (die_on_error)
+				die_errno("Could not get current working directory");
+			else
+				goto error_out;
 		}
-		if (!getcwd(buf, PATH_MAX))
-			die_errno ("Could not get current working directory");
 
 		if (last_elem) {
 			size_t len = strlen(buf);
-			if (len + strlen(last_elem) + 2 > PATH_MAX)
-				die ("Too long path name: '%s/%s'",
-						buf, last_elem);
+			if (len + strlen(last_elem) + 2 > PATH_MAX) {
+				if (die_on_error)
+					die("Too long path name: '%s/%s'",
+					    buf, last_elem);
+				else
+					goto error_out;
+			}
 			if (len && !is_dir_sep(buf[len-1]))
 				buf[len++] = '/';
 			strcpy(buf + len, last_elem);
@@ -77,10 +112,18 @@ const char *real_path(const char *path)
 
 		if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
 			ssize_t len = readlink(buf, next_buf, PATH_MAX);
-			if (len < 0)
-				die_errno ("Invalid symlink '%s'", buf);
-			if (PATH_MAX <= len)
-				die("symbolic link too long: %s", buf);
+			if (len < 0) {
+				if (die_on_error)
+					die_errno("Invalid symlink '%s'", buf);
+				else
+					goto error_out;
+			}
+			if (PATH_MAX <= len) {
+				if (die_on_error)
+					die("symbolic link too long: %s", buf);
+				else
+					goto error_out;
+			}
 			next_buf[len] = '\0';
 			buf = next_buf;
 			buf_index = 1 - buf_index;
@@ -89,10 +132,18 @@ const char *real_path(const char *path)
 			break;
 	}
 
+	retval = buf;
+error_out:
+	free(last_elem);
 	if (*cwd && chdir(cwd))
 		die_errno ("Could not change back to '%s'", cwd);
 
-	return buf;
+	return retval;
+}
+
+const char *real_path(const char *path)
+{
+	return real_path_internal(path, 1);
 }
 
 static const char *get_pwd_cwd(void)
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 2/8] real_path_internal(): add comment explaining use of cwd
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 1/8] Introduce new static function real_path_internal() Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 3/8] Introduce new function real_path_if_valid() Michael Haggerty
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty


Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 abspath.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/abspath.c b/abspath.c
index a7ab8e9..f8a526f 100644
--- a/abspath.c
+++ b/abspath.c
@@ -35,7 +35,14 @@ static const char *real_path_internal(const char *path, int die_on_error)
 {
 	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
 	char *retval = NULL;
+
+	/*
+	 * If we have to temporarily chdir(), store the original CWD
+	 * here so that we can chdir() back to it at the end of the
+	 * function:
+	 */
 	char cwd[1024] = "";
+
 	int buf_index = 1;
 
 	int depth = MAXDEPTH;
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 3/8] Introduce new function real_path_if_valid()
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 1/8] Introduce new static function real_path_internal() Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 2/8] real_path_internal(): add comment explaining use of cwd Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 4/8] longest_ancestor_length(): use string_list_split() Michael Haggerty
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty

The function is like real_path(), except that it returns NULL on error
instead of dying.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 abspath.c | 5 +++++
 cache.h   | 1 +
 2 files changed, 6 insertions(+)

diff --git a/abspath.c b/abspath.c
index f8a526f..40cdc46 100644
--- a/abspath.c
+++ b/abspath.c
@@ -153,6 +153,11 @@ const char *real_path(const char *path)
 	return real_path_internal(path, 1);
 }
 
+const char *real_path_if_valid(const char *path)
+{
+	return real_path_internal(path, 0);
+}
+
 static const char *get_pwd_cwd(void)
 {
 	static char cwd[PATH_MAX + 1];
diff --git a/cache.h b/cache.h
index a58df84..b0d75bc 100644
--- a/cache.h
+++ b/cache.h
@@ -714,6 +714,7 @@ static inline int is_absolute_path(const char *path)
 }
 int is_directory(const char *);
 const char *real_path(const char *path);
+const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
 const char *relative_path(const char *abs, const char *base);
 int normalize_path_copy(char *dst, const char *src);
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 4/8] longest_ancestor_length(): use string_list_split()
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
                   ` (2 preceding siblings ...)
  2012-10-28 16:16 ` [PATCH v4 3/8] Introduce new function real_path_if_valid() Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 5/8] longest_ancestor_length(): take a string_list argument for prefixes Michael Haggerty
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty


Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 path.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/path.c b/path.c
index cbbdf7d..f455e8e 100644
--- a/path.c
+++ b/path.c
@@ -12,6 +12,7 @@
  */
 #include "cache.h"
 #include "strbuf.h"
+#include "string-list.h"
 
 static char bad_path[] = "/bad-path/";
 
@@ -582,20 +583,22 @@ int normalize_path_copy(char *dst, const char *src)
  */
 int longest_ancestor_length(const char *path, const char *prefix_list)
 {
+	struct string_list prefixes = STRING_LIST_INIT_DUP;
 	char buf[PATH_MAX+1];
-	const char *ceil, *colon;
-	int len, max_len = -1;
+	int i, 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 != PATH_SEP; colon++);
-		len = colon - ceil;
+	string_list_split(&prefixes, prefix_list, PATH_SEP, -1);
+
+	for (i = 0; i < prefixes.nr; i++) {
+		const char *ceil = prefixes.items[i].string;
+		int len = strlen(ceil);
+
 		if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
 			continue;
-		strlcpy(buf, ceil, len+1);
-		if (normalize_path_copy(buf, buf) < 0)
+		if (normalize_path_copy(buf, ceil) < 0)
 			continue;
 		len = strlen(buf);
 		if (len > 0 && buf[len-1] == '/')
@@ -608,6 +611,7 @@ int longest_ancestor_length(const char *path, const char *prefix_list)
 		}
 	}
 
+	string_list_clear(&prefixes, 0);
 	return max_len;
 }
 
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 5/8] longest_ancestor_length(): take a string_list argument for prefixes
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
                   ` (3 preceding siblings ...)
  2012-10-28 16:16 ` [PATCH v4 4/8] longest_ancestor_length(): use string_list_split() Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 6/8] longest_ancestor_length(): require prefix list entries to be normalized Michael Haggerty
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty

Change longest_ancestor_length() to take the prefixes argument as a
string_list rather than as a colon-separated string.  This will make
it easier for the caller to alter the entries before calling
longest_ancestor_length().

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 cache.h           |  2 +-
 path.c            | 22 +++++++++-------------
 setup.c           | 11 +++++++++--
 test-path-utils.c |  8 +++++++-
 4 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/cache.h b/cache.h
index b0d75bc..8103385 100644
--- a/cache.h
+++ b/cache.h
@@ -718,7 +718,7 @@ const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
 const char *relative_path(const char *abs, const char *base);
 int normalize_path_copy(char *dst, const char *src);
-int longest_ancestor_length(const char *path, const char *prefix_list);
+int longest_ancestor_length(const char *path, struct string_list *prefixes);
 char *strip_path_suffix(const char *path, const char *suffix);
 int daemon_avoid_alias(const char *path);
 int offset_1st_component(const char *path);
diff --git a/path.c b/path.c
index f455e8e..b80d2e6 100644
--- a/path.c
+++ b/path.c
@@ -570,30 +570,27 @@ int normalize_path_copy(char *dst, const char *src)
 
 /*
  * path = Canonical absolute path
- * prefix_list = Colon-separated list of absolute paths
+ * prefixes = string_list containing absolute paths
  *
- * Determines, for each path in prefix_list, whether the "prefix" really
+ * Determines, for each path in prefixes, 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
+ * is an ancestor.  (Note that this means 0 is returned if prefixes 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 "".
+ * allowed.  Empty strings in prefixes are ignored.
  */
-int longest_ancestor_length(const char *path, const char *prefix_list)
+int longest_ancestor_length(const char *path, struct string_list *prefixes)
 {
-	struct string_list prefixes = STRING_LIST_INIT_DUP;
 	char buf[PATH_MAX+1];
 	int i, max_len = -1;
 
-	if (prefix_list == NULL || !strcmp(path, "/"))
+	if (!strcmp(path, "/"))
 		return -1;
 
-	string_list_split(&prefixes, prefix_list, PATH_SEP, -1);
-
-	for (i = 0; i < prefixes.nr; i++) {
-		const char *ceil = prefixes.items[i].string;
+	for (i = 0; i < prefixes->nr; i++) {
+		const char *ceil = prefixes->items[i].string;
 		int len = strlen(ceil);
 
 		if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
@@ -611,7 +608,6 @@ int longest_ancestor_length(const char *path, const char *prefix_list)
 		}
 	}
 
-	string_list_clear(&prefixes, 0);
 	return max_len;
 }
 
diff --git a/setup.c b/setup.c
index 3a1b2fd..b4cd356 100644
--- a/setup.c
+++ b/setup.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "dir.h"
+#include "string-list.h"
 
 static int inside_git_dir = -1;
 static int inside_work_tree = -1;
@@ -627,10 +628,11 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
 static const char *setup_git_directory_gently_1(int *nongit_ok)
 {
 	const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
+	struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
 	static char cwd[PATH_MAX+1];
 	const char *gitdirenv, *ret;
 	char *gitfile;
-	int len, offset, offset_parent, ceil_offset;
+	int len, offset, offset_parent, ceil_offset = -1;
 	dev_t current_device = 0;
 	int one_filesystem = 1;
 
@@ -655,7 +657,12 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
 	if (gitdirenv)
 		return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
 
-	ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
+	if (env_ceiling_dirs) {
+		string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
+		ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
+		string_list_clear(&ceiling_dirs, 0);
+	}
+
 	if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
 		ceil_offset = 1;
 
diff --git a/test-path-utils.c b/test-path-utils.c
index 3bc20e9..acb0560 100644
--- a/test-path-utils.c
+++ b/test-path-utils.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "string-list.h"
 
 int main(int argc, char **argv)
 {
@@ -30,7 +31,12 @@ int main(int argc, char **argv)
 	}
 
 	if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
-		int len = longest_ancestor_length(argv[2], argv[3]);
+		int len;
+		struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
+
+		string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
+		len = longest_ancestor_length(argv[2], &ceiling_dirs);
+		string_list_clear(&ceiling_dirs, 0);
 		printf("%d\n", len);
 		return 0;
 	}
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 6/8] longest_ancestor_length(): require prefix list entries to be normalized
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
                   ` (4 preceding siblings ...)
  2012-10-28 16:16 ` [PATCH v4 5/8] longest_ancestor_length(): take a string_list argument for prefixes Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  2012-10-30 18:23   ` Ramsay Jones
  2012-10-28 16:16 ` [PATCH v4 7/8] setup_git_directory_gently_1(): resolve symlinks in ceiling paths Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 8/8] string_list_longest_prefix(): remove function Michael Haggerty
  7 siblings, 1 reply; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty

Move the responsibility for normalizing prefixes from
longest_ancestor_length() to its callers. Use slightly different
normalizations at the two callers:

In setup_git_directory_gently_1(), use the old normalization, which
ignores paths that are not usable.  In the next commit we will change
this caller to also resolve symlinks in the paths from
GIT_CEILING_DIRECTORIES as part of the normalization.

In "test-path-utils longest_ancestor_length", use the old
normalization, but die() if any paths are unusable.  Also change t0060
to only pass normalized paths to the test program (no empty entries or
non-absolute paths, strip trailing slashes from the paths, and remove
tests that thereby become redundant).

The point of this change is to reduce the scope of the ancestor_length
tests in t0060 from testing normalization+longest_prefix to testing
only mostly longest_prefix.  This is necessary because when
setup_git_directory_gently_1() starts resolving symlinks as part of
its normalization, it will not be reasonable to do the same in the
test suite, because that would make the test results depend on the
contents of the root directory of the filesystem on which the test is
run.  HOWEVER: under Windows, bash mangles arguments that look like
absolute POSIX paths into DOS paths.  So we have to retain the level
of normalization done by normalize_path_copy() to convert the
bash-mangled DOS paths (which contain backslashes) into paths that use
forward slashes.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 path.c                | 26 +++++++++++---------------
 setup.c               | 23 +++++++++++++++++++++++
 t/t0060-path-utils.sh | 41 +++++++++++++----------------------------
 test-path-utils.c     | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 91 insertions(+), 44 deletions(-)

diff --git a/path.c b/path.c
index b80d2e6..d3d3f8b 100644
--- a/path.c
+++ b/path.c
@@ -570,20 +570,20 @@ int normalize_path_copy(char *dst, const char *src)
 
 /*
  * path = Canonical absolute path
- * prefixes = string_list containing absolute paths
+ * prefixes = string_list containing normalized, absolute paths without
+ * trailing slashes (except for the root directory, which is denoted by "/").
  *
- * Determines, for each path in prefixes, whether the "prefix" really
+ * Determines, for each path in prefixes, whether the "prefix"
  * 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 prefixes 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.  Empty strings in prefixes are ignored.
+ * allowed.
  */
 int longest_ancestor_length(const char *path, struct string_list *prefixes)
 {
-	char buf[PATH_MAX+1];
 	int i, max_len = -1;
 
 	if (!strcmp(path, "/"))
@@ -593,19 +593,15 @@ int longest_ancestor_length(const char *path, struct string_list *prefixes)
 		const char *ceil = prefixes->items[i].string;
 		int len = strlen(ceil);
 
-		if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
-			continue;
-		if (normalize_path_copy(buf, ceil) < 0)
-			continue;
-		len = strlen(buf);
-		if (len > 0 && buf[len-1] == '/')
-			buf[--len] = '\0';
+		if (len == 1 && ceil[0] == '/')
+			len = 0; /* root matches anything, with length 0 */
+		else if (!strncmp(path, ceil, len) && path[len] == '/')
+			; /* match of length len */
+		else
+			continue; /* no match */
 
-		if (!strncmp(path, buf, len) &&
-		    path[len] == '/' &&
-		    len > max_len) {
+		if (len > max_len)
 			max_len = len;
-		}
 	}
 
 	return max_len;
diff --git a/setup.c b/setup.c
index b4cd356..df97ad3 100644
--- a/setup.c
+++ b/setup.c
@@ -622,6 +622,28 @@ 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.
+ */
+static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
+{
+	const char *ceil = item->string;
+	int len = strlen(ceil);
+	char buf[PATH_MAX+1];
+
+	if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
+		return 0;
+	if (normalize_path_copy(buf, ceil) < 0)
+		return 0;
+	len = strlen(buf);
+	if (len > 1 && buf[len-1] == '/')
+		buf[--len] = '\0';
+	free(item->string);
+	item->string = xstrdup(buf);
+	return 1;
+}
+
+/*
  * We cannot decide in this function whether we are in the work tree or
  * not, since the config can only be read _after_ this function was called.
  */
@@ -659,6 +681,7 @@ 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);
 		ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
 		string_list_clear(&ceiling_dirs, 0);
 	}
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 4ef2345..09a42a4 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -93,47 +93,32 @@ norm_path /d1/s1//../s2/../../d2 /d2 POSIX
 norm_path /d1/.../d2 /d1/.../d2 POSIX
 norm_path /d1/..././../d2 /d1/d2 POSIX
 
-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 /foo:/bar -1
+ancestor /foo /:/foo:/bar 0
+ancestor /foo /foo:/:/bar 0
+ancestor /foo /:/bar:/foo 0
 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
+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:/bar 4
+ancestor /foo/bar /bar -1
 
 test_expect_success 'strip_path_suffix' '
 	test c:/msysgit = $(test-path-utils strip_path_suffix \
diff --git a/test-path-utils.c b/test-path-utils.c
index acb0560..0092cbf 100644
--- a/test-path-utils.c
+++ b/test-path-utils.c
@@ -1,6 +1,33 @@
 #include "cache.h"
 #include "string-list.h"
 
+/*
+ * A "string_list_each_func_t" function that normalizes an entry from
+ * GIT_CEILING_DIRECTORIES.  If the path is unusable for some reason,
+ * die with an explanation.
+ */
+static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
+{
+	const char *ceil = item->string;
+	int len = strlen(ceil);
+	char buf[PATH_MAX+1];
+
+	if (len == 0)
+		die("Empty path is not supported");
+	if (len > PATH_MAX)
+		die("Path \"%s\" is too long", ceil);
+	if (!is_absolute_path(ceil))
+		die("Path \"%s\" is not absolute", ceil);
+	if (normalize_path_copy(buf, ceil) < 0)
+		die("Path \"%s\" could not be normalized", ceil);
+	len = strlen(buf);
+	if (len > 1 && buf[len-1] == '/')
+		die("Normalized path \"%s\" ended with slash", buf);
+	free(item->string);
+	item->string = xstrdup(buf);
+	return 1;
+}
+
 int main(int argc, char **argv)
 {
 	if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
@@ -33,10 +60,26 @@ int main(int argc, char **argv)
 	if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
 		int len;
 		struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
+		char *path = xstrdup(argv[2]);
 
+		/*
+		 * We have to normalize the arguments because under
+		 * Windows, bash mangles arguments that look like
+		 * absolute POSIX paths or colon-separate lists of
+		 * absolute POSIX paths into DOS paths (e.g.,
+		 * "/foo:/foo/bar" might be converted to
+		 * "D:\Src\msysgit\foo;D:\Src\msysgit\foo\bar"),
+		 * whereas longest_ancestor_length() requires paths
+		 * that use forward slashes.
+		 */
+		if (normalize_path_copy(path, path))
+			die("Path \"%s\" could not be normalized", argv[2]);
 		string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
-		len = longest_ancestor_length(argv[2], &ceiling_dirs);
+		filter_string_list(&ceiling_dirs, 0,
+				   normalize_ceiling_entry, NULL);
+		len = longest_ancestor_length(path, &ceiling_dirs);
 		string_list_clear(&ceiling_dirs, 0);
+		free(path);
 		printf("%d\n", len);
 		return 0;
 	}
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 7/8] setup_git_directory_gently_1(): resolve symlinks in ceiling paths
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
                   ` (5 preceding siblings ...)
  2012-10-28 16:16 ` [PATCH v4 6/8] longest_ancestor_length(): require prefix list entries to be normalized Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  2012-10-28 16:16 ` [PATCH v4 8/8] string_list_longest_prefix(): remove function Michael Haggerty
  7 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty

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>
---
 setup.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/setup.c b/setup.c
index df97ad3..f108c4b 100644
--- a/setup.c
+++ b/setup.c
@@ -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);
 	}
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v4 8/8] string_list_longest_prefix(): remove function
  2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
                   ` (6 preceding siblings ...)
  2012-10-28 16:16 ` [PATCH v4 7/8] setup_git_directory_gently_1(): resolve symlinks in ceiling paths Michael Haggerty
@ 2012-10-28 16:16 ` Michael Haggerty
  7 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-10-28 16:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git,
	Michael Haggerty

This function was added in f103f95b11d087f07c0c48bf784cd9197e18f203 in
the erroneous expectation that it would be used in the
reimplementation of longest_ancestor_length().  But it turned out to
be easier to use a function specialized for comparing path prefixes
(i.e., one that knows about slashes and root paths) than to prepare
the paths in such a way that a generic string prefix comparison
function can be used.  So delete string_list_longest_prefix() and its
documentation and test cases.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 Documentation/technical/api-string-list.txt |  8 --------
 string-list.c                               | 20 -------------------
 string-list.h                               |  8 --------
 t/t0063-string-list.sh                      | 30 -----------------------------
 test-string-list.c                          | 20 -------------------
 5 files changed, 86 deletions(-)

diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 94d7a2b..618400d 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -75,14 +75,6 @@ Functions
 	to be deleted.  Preserve the order of the items that are
 	retained.
 
-`string_list_longest_prefix`::
-
-	Return the longest string within a string_list that is a
-	prefix (in the sense of prefixcmp()) of the specified string,
-	or NULL if no such prefix exists.  This function does not
-	require the string_list to be sorted (it does a linear
-	search).
-
 `print_string_list`::
 
 	Dump a string_list to stdout, useful mainly for debugging purposes. It
diff --git a/string-list.c b/string-list.c
index c54b816..decfa74 100644
--- a/string-list.c
+++ b/string-list.c
@@ -136,26 +136,6 @@ void filter_string_list(struct string_list *list, int free_util,
 	list->nr = dst;
 }
 
-char *string_list_longest_prefix(const struct string_list *prefixes,
-				 const char *string)
-{
-	int i, max_len = -1;
-	char *retval = NULL;
-
-	for (i = 0; i < prefixes->nr; i++) {
-		char *prefix = prefixes->items[i].string;
-		if (!prefixcmp(string, prefix)) {
-			int len = strlen(prefix);
-			if (len > max_len) {
-				retval = prefix;
-				max_len = len;
-			}
-		}
-	}
-
-	return retval;
-}
-
 void string_list_clear(struct string_list *list, int free_util)
 {
 	if (list->items) {
diff --git a/string-list.h b/string-list.h
index 5efd07b..3a6a6dc 100644
--- a/string-list.h
+++ b/string-list.h
@@ -38,14 +38,6 @@ int for_each_string_list(struct string_list *list,
 void filter_string_list(struct string_list *list, int free_util,
 			string_list_each_func_t want, void *cb_data);
 
-/*
- * Return the longest string in prefixes that is a prefix (in the
- * sense of prefixcmp()) of string, or NULL if no such prefix exists.
- * This function does not require the string_list to be sorted (it
- * does a linear search).
- */
-char *string_list_longest_prefix(const struct string_list *prefixes, const char *string);
-
 
 /* Use these functions only on sorted lists: */
 int string_list_has_string(const struct string_list *list, const char *string);
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
index 41c8826..dbfc05e 100755
--- a/t/t0063-string-list.sh
+++ b/t/t0063-string-list.sh
@@ -17,14 +17,6 @@ test_split () {
 	"
 }
 
-test_longest_prefix () {
-	test "$(test-string-list longest_prefix "$1" "$2")" = "$3"
-}
-
-test_no_longest_prefix () {
-	test_must_fail test-string-list longest_prefix "$1" "$2"
-}
-
 test_split "foo:bar:baz" ":" "-1" <<EOF
 3
 [0]: "foo"
@@ -96,26 +88,4 @@ test_expect_success "test remove_duplicates" '
 	test a:b:c = "$(test-string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
 '
 
-test_expect_success "test longest_prefix" '
-	test_no_longest_prefix - '' &&
-	test_no_longest_prefix - x &&
-	test_longest_prefix "" x "" &&
-	test_longest_prefix x x x &&
-	test_longest_prefix "" foo "" &&
-	test_longest_prefix : foo "" &&
-	test_longest_prefix f foo f &&
-	test_longest_prefix foo foobar foo &&
-	test_longest_prefix foo foo foo &&
-	test_no_longest_prefix bar foo &&
-	test_no_longest_prefix bar:bar foo &&
-	test_no_longest_prefix foobar foo &&
-	test_longest_prefix foo:bar foo foo &&
-	test_longest_prefix foo:bar bar bar &&
-	test_longest_prefix foo::bar foo foo &&
-	test_longest_prefix foo:foobar foo foo &&
-	test_longest_prefix foobar:foo foo foo &&
-	test_longest_prefix foo: bar "" &&
-	test_longest_prefix :foo bar ""
-'
-
 test_done
diff --git a/test-string-list.c b/test-string-list.c
index 4693295..00ce6c9 100644
--- a/test-string-list.c
+++ b/test-string-list.c
@@ -97,26 +97,6 @@ int main(int argc, char **argv)
 		return 0;
 	}
 
-	if (argc == 4 && !strcmp(argv[1], "longest_prefix")) {
-		/* arguments: <colon-separated-prefixes>|- <string> */
-		struct string_list prefixes = STRING_LIST_INIT_DUP;
-		int retval;
-		const char *prefix_string = argv[2];
-		const char *string = argv[3];
-		const char *match;
-
-		parse_string_list(&prefixes, prefix_string);
-		match = string_list_longest_prefix(&prefixes, string);
-		if (match) {
-			printf("%s\n", match);
-			retval = 0;
-		}
-		else
-			retval = 1;
-		string_list_clear(&prefixes, 0);
-		return retval;
-	}
-
 	fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
 		argv[1] ? argv[1] : "(there was none)");
 	return 1;
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 6/8] longest_ancestor_length(): require prefix list entries to be normalized
  2012-10-28 16:16 ` [PATCH v4 6/8] longest_ancestor_length(): require prefix list entries to be normalized Michael Haggerty
@ 2012-10-30 18:23   ` Ramsay Jones
  2012-11-06  7:34     ` Michael Haggerty
  0 siblings, 1 reply; 11+ messages in thread
From: Ramsay Jones @ 2012-10-30 18:23 UTC (permalink / raw)
  To: Michael Haggerty
  Cc: Jeff King, Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt, git

Michael Haggerty wrote:
> Move the responsibility for normalizing prefixes from
> longest_ancestor_length() to its callers. Use slightly different
> normalizations at the two callers:
> 
> In setup_git_directory_gently_1(), use the old normalization, which
> ignores paths that are not usable.  In the next commit we will change
> this caller to also resolve symlinks in the paths from
> GIT_CEILING_DIRECTORIES as part of the normalization.
> 
> In "test-path-utils longest_ancestor_length", use the old
> normalization, but die() if any paths are unusable.  Also change t0060
> to only pass normalized paths to the test program (no empty entries or
> non-absolute paths, strip trailing slashes from the paths, and remove
> tests that thereby become redundant).
> 
> The point of this change is to reduce the scope of the ancestor_length
> tests in t0060 from testing normalization+longest_prefix to testing
> only mostly longest_prefix.  This is necessary because when
> setup_git_directory_gently_1() starts resolving symlinks as part of
> its normalization, it will not be reasonable to do the same in the
> test suite, because that would make the test results depend on the
> contents of the root directory of the filesystem on which the test is
> run.  HOWEVER: under Windows, bash mangles arguments that look like
> absolute POSIX paths into DOS paths.

Just to be clear, this is true for the MinGW port to Windows, but *not*
the cygwin port.
:-P

>                                      So we have to retain the level
> of normalization done by normalize_path_copy() to convert the
> bash-mangled DOS paths (which contain backslashes) into paths that use
> forward slashes.
> 
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
>  path.c                | 26 +++++++++++---------------
>  setup.c               | 23 +++++++++++++++++++++++
>  t/t0060-path-utils.sh | 41 +++++++++++++----------------------------
>  test-path-utils.c     | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>  4 files changed, 91 insertions(+), 44 deletions(-)
> 

[snip]

> diff --git a/test-path-utils.c b/test-path-utils.c
> index acb0560..0092cbf 100644
> --- a/test-path-utils.c
> +++ b/test-path-utils.c
> @@ -1,6 +1,33 @@
>  #include "cache.h"
>  #include "string-list.h"
>  
> +/*
> + * A "string_list_each_func_t" function that normalizes an entry from
> + * GIT_CEILING_DIRECTORIES.  If the path is unusable for some reason,
> + * die with an explanation.
> + */
> +static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
> +{
> +	const char *ceil = item->string;
> +	int len = strlen(ceil);
> +	char buf[PATH_MAX+1];
> +
> +	if (len == 0)
> +		die("Empty path is not supported");
> +	if (len > PATH_MAX)
> +		die("Path \"%s\" is too long", ceil);
> +	if (!is_absolute_path(ceil))
> +		die("Path \"%s\" is not absolute", ceil);
> +	if (normalize_path_copy(buf, ceil) < 0)
> +		die("Path \"%s\" could not be normalized", ceil);
> +	len = strlen(buf);
> +	if (len > 1 && buf[len-1] == '/')
> +		die("Normalized path \"%s\" ended with slash", buf);
> +	free(item->string);
> +	item->string = xstrdup(buf);
> +	return 1;
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
> @@ -33,10 +60,26 @@ int main(int argc, char **argv)
>  	if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
>  		int len;
>  		struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
> +		char *path = xstrdup(argv[2]);
>  
> +		/*
> +		 * We have to normalize the arguments because under
> +		 * Windows, bash mangles arguments that look like

ditto

> +		 * absolute POSIX paths or colon-separate lists of
> +		 * absolute POSIX paths into DOS paths (e.g.,
> +		 * "/foo:/foo/bar" might be converted to
> +		 * "D:\Src\msysgit\foo;D:\Src\msysgit\foo\bar"),
> +		 * whereas longest_ancestor_length() requires paths
> +		 * that use forward slashes.
> +		 */
> +		if (normalize_path_copy(path, path))
> +			die("Path \"%s\" could not be normalized", argv[2]);
>  		string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
> -		len = longest_ancestor_length(argv[2], &ceiling_dirs);
> +		filter_string_list(&ceiling_dirs, 0,
> +				   normalize_ceiling_entry, NULL);
> +		len = longest_ancestor_length(path, &ceiling_dirs);
>  		string_list_clear(&ceiling_dirs, 0);
> +		free(path);
>  		printf("%d\n", len);
>  		return 0;
>  	}


HTH

ATB,
Ramsay Jones

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v4 6/8] longest_ancestor_length(): require prefix list entries to be normalized
  2012-10-30 18:23   ` Ramsay Jones
@ 2012-11-06  7:34     ` Michael Haggerty
  0 siblings, 0 replies; 11+ messages in thread
From: Michael Haggerty @ 2012-11-06  7:34 UTC (permalink / raw)
  To: Ramsay Jones
  Cc: Jeff King, Junio C Hamano, Jiang Xin, Lea Wiemann, Johannes Sixt,
	git, David Aguilar

On 10/30/2012 07:23 PM, Ramsay Jones wrote:
> [...]
> Just to be clear, this is true for the MinGW port to Windows, but *not*
> the cygwin port.
>
> [...]
> 
> ditto

Thanks for clarifying these points.  It seems like this patch series is
not going to be usable (because of fears that it might cause performance
degradation in some as-yet-unexplained scenarios), but if that situation
seems to change then I will incorporate your corrections.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2012-11-06  7:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-28 16:16 [PATCH v4 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 1/8] Introduce new static function real_path_internal() Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 2/8] real_path_internal(): add comment explaining use of cwd Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 3/8] Introduce new function real_path_if_valid() Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 4/8] longest_ancestor_length(): use string_list_split() Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 5/8] longest_ancestor_length(): take a string_list argument for prefixes Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 6/8] longest_ancestor_length(): require prefix list entries to be normalized Michael Haggerty
2012-10-30 18:23   ` Ramsay Jones
2012-11-06  7:34     ` Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 7/8] setup_git_directory_gently_1(): resolve symlinks in ceiling paths Michael Haggerty
2012-10-28 16:16 ` [PATCH v4 8/8] string_list_longest_prefix(): remove function Michael Haggerty

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.