зеркало из https://github.com/microsoft/git.git
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>
This commit is contained in:
Родитель
4cd148d83f
Коммит
25fe217b86
2
cache.h
2
cache.h
|
@ -521,7 +521,7 @@ int safe_create_leading_directories(char *path);
|
||||||
char *enter_repo(char *path, int strict);
|
char *enter_repo(char *path, int strict);
|
||||||
static inline int is_absolute_path(const char *path)
|
static inline int is_absolute_path(const char *path)
|
||||||
{
|
{
|
||||||
return path[0] == '/';
|
return path[0] == '/' || has_dos_drive_prefix(path);
|
||||||
}
|
}
|
||||||
const char *make_absolute_path(const char *path);
|
const char *make_absolute_path(const char *path);
|
||||||
const char *make_nonrelative_path(const char *path);
|
const char *make_nonrelative_path(const char *path);
|
||||||
|
|
|
@ -40,6 +40,19 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef getcwd
|
||||||
|
char *mingw_getcwd(char *pointer, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *ret = getcwd(pointer, len);
|
||||||
|
if (!ret)
|
||||||
|
return ret;
|
||||||
|
for (i = 0; pointer[i]; i++)
|
||||||
|
if (pointer[i] == '\\')
|
||||||
|
pointer[i] = '/';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct passwd *getpwuid(int uid)
|
struct passwd *getpwuid(int uid)
|
||||||
{
|
{
|
||||||
static struct passwd p;
|
static struct passwd p;
|
||||||
|
|
|
@ -133,8 +133,17 @@ struct passwd *getpwuid(int uid);
|
||||||
int setitimer(int type, struct itimerval *in, struct itimerval *out);
|
int setitimer(int type, struct itimerval *in, struct itimerval *out);
|
||||||
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
|
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* replacements of existing functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *mingw_getcwd(char *pointer, int len);
|
||||||
|
#define getcwd mingw_getcwd
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* git specific compatibility
|
* git specific compatibility
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
|
||||||
|
#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
|
||||||
#define PATH_SEP ';'
|
#define PATH_SEP ';'
|
||||||
|
|
|
@ -114,6 +114,14 @@
|
||||||
#define PATH_SEP ':'
|
#define PATH_SEP ':'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef has_dos_drive_prefix
|
||||||
|
#define has_dos_drive_prefix(path) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef is_dir_sep
|
||||||
|
#define is_dir_sep(c) ((c) == '/')
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define NORETURN __attribute__((__noreturn__))
|
#define NORETURN __attribute__((__noreturn__))
|
||||||
#else
|
#else
|
||||||
|
|
50
setup.c
50
setup.c
|
@ -6,11 +6,17 @@ static int inside_work_tree = -1;
|
||||||
|
|
||||||
static int sanitary_path_copy(char *dst, const char *src)
|
static int sanitary_path_copy(char *dst, const char *src)
|
||||||
{
|
{
|
||||||
char *dst0 = dst;
|
char *dst0;
|
||||||
|
|
||||||
if (*src == '/') {
|
if (has_dos_drive_prefix(src)) {
|
||||||
|
*dst++ = *src++;
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
dst0 = dst;
|
||||||
|
|
||||||
|
if (is_dir_sep(*src)) {
|
||||||
*dst++ = '/';
|
*dst++ = '/';
|
||||||
while (*src == '/')
|
while (is_dir_sep(*src))
|
||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,10 +35,10 @@ static int sanitary_path_copy(char *dst, const char *src)
|
||||||
if (!src[1]) {
|
if (!src[1]) {
|
||||||
/* (1) */
|
/* (1) */
|
||||||
src++;
|
src++;
|
||||||
} else if (src[1] == '/') {
|
} else if (is_dir_sep(src[1])) {
|
||||||
/* (2) */
|
/* (2) */
|
||||||
src += 2;
|
src += 2;
|
||||||
while (*src == '/')
|
while (is_dir_sep(*src))
|
||||||
src++;
|
src++;
|
||||||
continue;
|
continue;
|
||||||
} else if (src[1] == '.') {
|
} else if (src[1] == '.') {
|
||||||
|
@ -40,10 +46,10 @@ static int sanitary_path_copy(char *dst, const char *src)
|
||||||
/* (3) */
|
/* (3) */
|
||||||
src += 2;
|
src += 2;
|
||||||
goto up_one;
|
goto up_one;
|
||||||
} else if (src[2] == '/') {
|
} else if (is_dir_sep(src[2])) {
|
||||||
/* (4) */
|
/* (4) */
|
||||||
src += 3;
|
src += 3;
|
||||||
while (*src == '/')
|
while (is_dir_sep(*src))
|
||||||
src++;
|
src++;
|
||||||
goto up_one;
|
goto up_one;
|
||||||
}
|
}
|
||||||
|
@ -51,11 +57,11 @@ static int sanitary_path_copy(char *dst, const char *src)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy up to the next '/', and eat all '/' */
|
/* copy up to the next '/', and eat all '/' */
|
||||||
while ((c = *src++) != '\0' && c != '/')
|
while ((c = *src++) != '\0' && !is_dir_sep(c))
|
||||||
*dst++ = c;
|
*dst++ = c;
|
||||||
if (c == '/') {
|
if (is_dir_sep(c)) {
|
||||||
*dst++ = c;
|
*dst++ = '/';
|
||||||
while (c == '/')
|
while (is_dir_sep(c))
|
||||||
c = *src++;
|
c = *src++;
|
||||||
src--;
|
src--;
|
||||||
} else if (!c)
|
} else if (!c)
|
||||||
|
@ -74,7 +80,7 @@ static int sanitary_path_copy(char *dst, const char *src)
|
||||||
if (dst <= dst0)
|
if (dst <= dst0)
|
||||||
break;
|
break;
|
||||||
c = *dst--;
|
c = *dst--;
|
||||||
if (c == '/') {
|
if (c == '/') { /* MinGW: cannot be '\\' anymore */
|
||||||
dst += 2;
|
dst += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -123,10 +129,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)
|
const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
|
||||||
{
|
{
|
||||||
static char path[PATH_MAX];
|
static char path[PATH_MAX];
|
||||||
|
#ifndef __MINGW32__
|
||||||
if (!pfx || !*pfx || is_absolute_path(arg))
|
if (!pfx || !*pfx || is_absolute_path(arg))
|
||||||
return arg;
|
return arg;
|
||||||
memcpy(path, pfx, pfx_len);
|
memcpy(path, pfx, pfx_len);
|
||||||
strcpy(path + pfx_len, arg);
|
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;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,6 +379,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
const char *gitdirenv;
|
const char *gitdirenv;
|
||||||
const char *gitfile_dir;
|
const char *gitfile_dir;
|
||||||
int len, offset;
|
int len, offset;
|
||||||
|
int minoffset = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let's assume that we are in a git repository.
|
* Let's assume that we are in a git repository.
|
||||||
|
@ -410,6 +430,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
|
|
||||||
if (!getcwd(cwd, sizeof(cwd)-1))
|
if (!getcwd(cwd, sizeof(cwd)-1))
|
||||||
die("Unable to read current working directory");
|
die("Unable to read current working directory");
|
||||||
|
if (has_dos_drive_prefix(cwd))
|
||||||
|
minoffset = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test in the following order (relative to the cwd):
|
* Test in the following order (relative to the cwd):
|
||||||
|
@ -442,7 +464,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
}
|
}
|
||||||
chdir("..");
|
chdir("..");
|
||||||
do {
|
do {
|
||||||
if (!offset) {
|
if (offset <= minoffset) {
|
||||||
if (nongit_ok) {
|
if (nongit_ok) {
|
||||||
if (chdir(cwd))
|
if (chdir(cwd))
|
||||||
die("Cannot come back to cwd");
|
die("Cannot come back to cwd");
|
||||||
|
@ -451,7 +473,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
}
|
}
|
||||||
die("Not a git repository");
|
die("Not a git repository");
|
||||||
}
|
}
|
||||||
} while (cwd[--offset] != '/');
|
} while (offset > minoffset && cwd[--offset] != '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
inside_git_dir = 0;
|
inside_git_dir = 0;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче