[PATCH 10/40] Windows: Treat Windows style path names.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



GIT's guts work with a forward slash as a path separators. We do not change
that. Rather we make sure that only "normalized" paths enter the depths
of the machinery.

We have to translate backslashes to forward slashes in the prefix and in
command line arguments. Fortunately, all of them are passed through
functions in setup.c.

Signed-off-by: Johannes Sixt <johannes.sixt@xxxxxxxxxx>
---
 cache.h           |    4 +++
 compat/mingw.c    |   16 ++++++++++++++
 git-compat-util.h |    3 ++
 setup.c           |   59 +++++++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/cache.h b/cache.h
index e1000bc..3e4e10a 100644
--- a/cache.h
+++ b/cache.h
@@ -441,7 +441,11 @@ int safe_create_leading_directories(char *path);
 char *enter_repo(char *path, int strict);
 static inline int is_absolute_path(const char *path)
 {
+#ifndef __MINGW32__
 	return path[0] == '/';
+#else
+	return path[0] == '/' || (path[0] && path[1] == ':');
+#endif
 }
 const char *make_absolute_path(const char *path);
 
diff --git a/compat/mingw.c b/compat/mingw.c
index 733ef87..71bca96 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -60,6 +60,22 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
 	return result;
 }
 
+#undef getcwd
+char *mingw_getcwd(char *pointer, int len)
+{
+	char *ret = getcwd(pointer, len);
+	if (!ret)
+		return ret;
+	if (pointer[0] != 0 && pointer[1] == ':') {
+		int i;
+		for (i = 2; pointer[i]; i++)
+			/* Thanks, Bill. You'll burn in hell for that. */
+			if (pointer[i] == '\\')
+				pointer[i] = '/';
+	}
+	return ret;
+}
+
 #undef rename
 int mingw_rename(const char *pold, const char *pnew)
 {
diff --git a/git-compat-util.h b/git-compat-util.h
index f44a287..3b57464 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -592,6 +592,9 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out);
 int mingw_open (const char *filename, int oflags, ...);
 #define open mingw_open
 
+char *mingw_getcwd(char *pointer, int len);
+#define getcwd mingw_getcwd
+
 int mingw_rename(const char*, const char*);
 #define rename mingw_rename
 
diff --git a/setup.c b/setup.c
index dc247a8..77cc461 100644
--- a/setup.c
+++ b/setup.c
@@ -4,13 +4,26 @@
 static int inside_git_dir = -1;
 static int inside_work_tree = -1;
 
+#ifdef __MINGW32__
+static inline int is_dir_sep(char c) { return c == '/' || c == '\\'; }
+#else
+static inline int is_dir_sep(char c) { return c == '/'; }
+#endif
+
 static int sanitary_path_copy(char *dst, const char *src)
 {
 	char *dst0 = dst;
 
-	if (*src == '/') {
+#ifdef __MINGW32__
+	if (isalpha(*src) && src[1] == ':') {
+		*dst++ = *src++;
+		*dst++ = *src++;
+		dst0 = dst;
+	}
+#endif
+	if (is_dir_sep(*src)) {
 		*dst++ = '/';
-		while (*src == '/')
+		while (is_dir_sep(*src))
 			src++;
 	}
 
@@ -32,9 +45,12 @@ static int sanitary_path_copy(char *dst, const char *src)
 				src++;
 				break;
 			case '/':
+#ifdef __MINGW32__
+			case '\\':
+#endif
 				/* (2) */
 				src += 2;
-				while (*src == '/')
+				while (is_dir_sep(*src))
 					src++;
 				continue;
 			case '.':
@@ -44,9 +60,12 @@ static int sanitary_path_copy(char *dst, const char *src)
 					src += 2;
 					goto up_one;
 				case '/':
+#ifdef __MINGW32__
+				case '\\':
+#endif
 					/* (4) */
 					src += 3;
-					while (*src == '/')
+					while (is_dir_sep(*src))
 						src++;
 					goto up_one;
 				}
@@ -54,11 +73,11 @@ static int sanitary_path_copy(char *dst, const char *src)
 		}
 
 		/* copy up to the next '/', and eat all '/' */
-		while ((c = *src++) != '\0' && c != '/')
+		while ((c = *src++) != '\0' && !is_dir_sep(c))
 			*dst++ = c;
-		if (c == '/') {
-			*dst++ = c;
-			while (c == '/')
+		if (is_dir_sep(c)) {
+			*dst++ = '/';
+			while (is_dir_sep(c))
 				c = *src++;
 			src--;
 		} else if (!c)
@@ -77,7 +96,7 @@ static int sanitary_path_copy(char *dst, const char *src)
 			if (dst <= dst0)
 				break;
 			c = *dst--;
-			if (c == '/') {
+			if (c == '/') {	/* MinGW: cannot be '\\' anymore */
 				dst += 2;
 				break;
 			}
@@ -126,10 +145,23 @@ const char *prefix_path(const char *prefix, int len, const char *path)
 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
 {
 	static char path[PATH_MAX];
+#ifndef __MINGW32__
 	if (!pfx || !*pfx || is_absolute_path(arg))
 		return arg;
 	memcpy(path, pfx, pfx_len);
 	strcpy(path + pfx_len, arg);
+#else
+	char *p;
+	/* don't add prefix to absolute paths, but still replace '\' by '/' */
+	if (is_absolute_path(arg))
+		pfx_len = 0;
+	else
+		memcpy(path, pfx, pfx_len);
+	strcpy(path + pfx_len, arg);
+	for (p = path + pfx_len; *p; p++)
+		if (*p == '\\')
+			*p = '/';
+#endif
 	return path;
 }
 
@@ -322,6 +354,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	static char cwd[PATH_MAX+1];
 	const char *gitdirenv;
 	int len, offset;
+	int minoffset = 0;
 
 	/*
 	 * If GIT_DIR is set explicitly, we're not going
@@ -364,6 +397,10 @@ const char *setup_git_directory_gently(int *nongit_ok)
 
 	if (!getcwd(cwd, sizeof(cwd)-1))
 		die("Unable to read current working directory");
+#ifdef __MINGW32__
+	if (cwd[1] == ':')
+		minoffset = 2;
+#endif
 
 	/*
 	 * Test in the following order (relative to the cwd):
@@ -388,7 +425,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 		}
 		chdir("..");
 		do {
-			if (!offset) {
+			if (offset <= minoffset) {
 				if (nongit_ok) {
 					if (chdir(cwd))
 						die("Cannot come back to cwd");
@@ -397,7 +434,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 				}
 				die("Not a git repository");
 			}
-		} while (cwd[--offset] != '/');
+		} while (offset > minoffset && cwd[--offset] != '/');
 	}
 
 	inside_git_dir = 0;
-- 
1.5.4.1.126.ge5a7d

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux