@matheusbsbs / matheus-bagliano / commits / 25fe217b86
Fork 0

Windows: Treat Windows style path names.

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. A macro has_dos_drive_path() is defined that checks whether a path begins with a drive letter+colon combination. This predicate is always false on Unix. Another macro is_dir_sep() abstracts that a backslash is also a directory separator on Windows. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>

Johannes Sixt committed Mar 5, 2008 at 21:51 UTC 25fe217b86ca40c53e710d776e120dfa0d81f60b
5 files changed +67 -15
cache.h
+1 -1
@@ -521,7 +521,7 @@ int safe_create_leading_directories(char *path);
521 char *enter_repo(char *path, int strict);
522 static inline int is_absolute_path(const char *path)
523 {
524 - return path[0] == '/';
524 + return path[0] == '/' || has_dos_drive_prefix(path);
525 }
526 const char *make_absolute_path(const char *path);
527 const char *make_nonrelative_path(const char *path);
compat/mingw.c
+13
@@ -40,6 +40,19 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
40 return result;
41 }
42
43 +#undef getcwd
44 +char *mingw_getcwd(char *pointer, int len)
45 +{
46 + int i;
47 + char *ret = getcwd(pointer, len);
48 + if (!ret)
49 + return ret;
50 + for (i = 0; pointer[i]; i++)
51 + if (pointer[i] == '\\')
52 + pointer[i] = '/';
53 + return ret;
54 +}
55 +
56 struct passwd *getpwuid(int uid)
57 {
58 static struct passwd p;
compat/mingw.h
+9
@@ -133,8 +133,17 @@ struct passwd *getpwuid(int uid);
133 int setitimer(int type, struct itimerval *in, struct itimerval *out);
134 int sigaction(int sig, struct sigaction *in, struct sigaction *out);
135
136 +/*
137 + * replacements of existing functions
138 + */
139 +
140 +char *mingw_getcwd(char *pointer, int len);
141 +#define getcwd mingw_getcwd
142 +
143 /*
144 * git specific compatibility
145 */
146
147 +#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
148 +#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
149 #define PATH_SEP ';'
git-compat-util.h
+8
@@ -114,6 +114,14 @@
114 #define PATH_SEP ':'
115 #endif
116
117 +#ifndef has_dos_drive_prefix
118 +#define has_dos_drive_prefix(path) 0
119 +#endif
120 +
121 +#ifndef is_dir_sep
122 +#define is_dir_sep(c) ((c) == '/')
123 +#endif
124 +
125 #ifdef __GNUC__
126 #define NORETURN __attribute__((__noreturn__))
127 #else
setup.c
+36 -14
@@ -6,11 +6,17 @@ static int inside_work_tree = -1;
6
7 static int sanitary_path_copy(char *dst, const char *src)
8 {
9 - char *dst0 = dst;
9 + char *dst0;
10
11 - if (*src == '/') {
11 + if (has_dos_drive_prefix(src)) {
12 + *dst++ = *src++;
13 + *dst++ = *src++;
14 + }
15 + dst0 = dst;
16 +
17 + if (is_dir_sep(*src)) {
18 *dst++ = '/';
13 - while (*src == '/')
19 + while (is_dir_sep(*src))
20 src++;
21 }
22
@@ -29,10 +35,10 @@ static int sanitary_path_copy(char *dst, const char *src)
35 if (!src[1]) {
36 /* (1) */
37 src++;
32 - } else if (src[1] == '/') {
38 + } else if (is_dir_sep(src[1])) {
39 /* (2) */
40 src += 2;
35 - while (*src == '/')
41 + while (is_dir_sep(*src))
42 src++;
43 continue;
44 } else if (src[1] == '.') {
@@ -40,10 +46,10 @@ static int sanitary_path_copy(char *dst, const char *src)
46 /* (3) */
47 src += 2;
48 goto up_one;
43 - } else if (src[2] == '/') {
49 + } else if (is_dir_sep(src[2])) {
50 /* (4) */
51 src += 3;
46 - while (*src == '/')
52 + while (is_dir_sep(*src))
53 src++;
54 goto up_one;
55 }
@@ -51,11 +57,11 @@ static int sanitary_path_copy(char *dst, const char *src)
57 }
58
59 /* copy up to the next '/', and eat all '/' */
54 - while ((c = *src++) != '\0' && c != '/')
60 + while ((c = *src++) != '\0' && !is_dir_sep(c))
61 *dst++ = c;
56 - if (c == '/') {
57 - *dst++ = c;
58 - while (c == '/')
62 + if (is_dir_sep(c)) {
63 + *dst++ = '/';
64 + while (is_dir_sep(c))
65 c = *src++;
66 src--;
67 } else if (!c)
@@ -74,7 +80,7 @@ static int sanitary_path_copy(char *dst, const char *src)
80 if (dst <= dst0)
81 break;
82 c = *dst--;
77 - if (c == '/') {
83 + if (c == '/') { /* MinGW: cannot be '\\' anymore */
84 dst += 2;
85 break;
86 }
@@ -123,10 +129,23 @@ const char *prefix_path(const char *prefix, int len, const char *path)
129 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
130 {
131 static char path[PATH_MAX];
132 +#ifndef __MINGW32__
133 if (!pfx || !*pfx || is_absolute_path(arg))
134 return arg;
135 memcpy(path, pfx, pfx_len);
136 strcpy(path + pfx_len, arg);
137 +#else
138 + char *p;
139 + /* don't add prefix to absolute paths, but still replace '\' by '/' */
140 + if (is_absolute_path(arg))
141 + pfx_len = 0;
142 + else
143 + memcpy(path, pfx, pfx_len);
144 + strcpy(path + pfx_len, arg);
145 + for (p = path + pfx_len; *p; p++)
146 + if (*p == '\\')
147 + *p = '/';
148 +#endif
149 return path;
150 }
151
@@ -360,6 +379,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
379 const char *gitdirenv;
380 const char *gitfile_dir;
381 int len, offset;
382 + int minoffset = 0;
383
384 /*
385 * Let's assume that we are in a git repository.
@@ -410,6 +430,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
430
431 if (!getcwd(cwd, sizeof(cwd)-1))
432 die("Unable to read current working directory");
433 + if (has_dos_drive_prefix(cwd))
434 + minoffset = 2;
435
436 /*
437 * Test in the following order (relative to the cwd):
@@ -442,7 +464,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
464 }
465 chdir("..");
466 do {
445 - if (!offset) {
467 + if (offset <= minoffset) {
468 if (nongit_ok) {
469 if (chdir(cwd))
470 die("Cannot come back to cwd");
@@ -451,7 +473,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
473 }
474 die("Not a git repository");
475 }
454 - } while (cwd[--offset] != '/');
476 + } while (offset > minoffset && cwd[--offset] != '/');
477 }
478
479 inside_git_dir = 0;