On Wed, Sep 05, 2012 at 08:23:58PM -0700, Junio C Hamano wrote: > Nguyen Thai Ngoc Duy <pclouds@xxxxxxxxx> writes: > > > diff --git a/path.c b/path.c > > index 66acd24..ad2881c 100644 > > --- a/path.c > > +++ b/path.c > > @@ -503,6 +503,10 @@ int normalize_path_copy(char *dst, const char *src) > > *dst++ = *src++; > > *dst++ = *src++; > > } > > +#ifdef WIN32 > > + else if (src[0] == '/' && src[1] == '/') > > + *dst++ = *src++; > > +#endif > > The two-byte copy we see above the context is conditional on a nice > abstraction "has_dos_drive_prefix()" so that we do not have to > suffer from these ugly ifdefs. Could we do something similar? Just an idea. We could unify "[a-z]:" and "//host" into "dos root" concept. That would teach other code paths about UNC paths too. Replace has_dos_drive_prefix() with has_dos_root_prefix(). Because the root component's length is not fixed, offset_1st_component() should be used instead of hard coding "2". Something like this. Totally untested. -- 8< -- diff --git a/cache.h b/cache.h index 67f28b4..7946489 100644 --- a/cache.h +++ b/cache.h @@ -711,7 +711,7 @@ extern char *expand_user_path(const char *path); const char *enter_repo(const char *path, int strict); static inline int is_absolute_path(const char *path) { - return is_dir_sep(path[0]) || has_dos_drive_prefix(path); + return is_dir_sep(path[0]) || has_dos_root_prefix(path); } int is_directory(const char *); const char *real_path(const char *path); @@ -721,7 +721,7 @@ int normalize_path_copy(char *dst, const char *src); int longest_ancestor_length(const char *path, const char *prefix_list); char *strip_path_suffix(const char *path, const char *suffix); int daemon_avoid_alias(const char *path); -int offset_1st_component(const char *path); +int offset_1st_component(const char *path, int keep_root); /* object replacement */ #define READ_SHA1_FILE_REPLACE 1 diff --git a/compat/basename.c b/compat/basename.c index d8f8a3c..178b60d 100644 --- a/compat/basename.c +++ b/compat/basename.c @@ -5,8 +5,7 @@ char *gitbasename (char *path) { const char *base; /* Skip over the disk name in MSDOS pathnames. */ - if (has_dos_drive_prefix(path)) - path += 2; + path += offset_1st_component(path, 0); for (base = path; *path; path++) { if (is_dir_sep(*path)) base = path + 1; diff --git a/compat/mingw.h b/compat/mingw.h index 61a6521..1ca3e19 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -302,7 +302,9 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format * git specific compatibility */ -#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':') +#define has_dos_root_prefix(path) \ + ((is_dir_sep[(path)[0]] && is_dir_sep[(path)[1]]) \ + || (isalpha(*(path)) && (path)[1] == ':')) #define is_dir_sep(c) ((c) == '/' || (c) == '\\') static inline char *mingw_find_last_dir_sep(const char *path) { diff --git a/connect.c b/connect.c index 55a85ad..3d9f7fe 100644 --- a/connect.c +++ b/connect.c @@ -521,7 +521,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig, end = host; path = strchr(end, c); - if (path && !has_dos_drive_prefix(end)) { + if (path && (!isalpha(*end) || end[1] != ':')) { if (c == ':') { protocol = PROTO_SSH; *path++ = '\0'; diff --git a/git-compat-util.h b/git-compat-util.h index 35b095e..c6656e2 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -216,8 +216,8 @@ extern char *gitbasename(char *); #define STRIP_EXTENSION "" #endif -#ifndef has_dos_drive_prefix -#define has_dos_drive_prefix(path) 0 +#ifndef has_dos_root_prefix +#define has_dos_root_prefix(path) 0 #endif #ifndef is_dir_sep diff --git a/path.c b/path.c index 66acd24..0e4e2d7 100644 --- a/path.c +++ b/path.c @@ -498,11 +498,12 @@ const char *relative_path(const char *abs, const char *base) int normalize_path_copy(char *dst, const char *src) { char *dst0; + int i, len; - if (has_dos_drive_prefix(src)) { + len = offset_1st_component(src, 1); + for (i = 0; i < len; i++) *dst++ = *src++; - *dst++ = *src++; - } + dst0 = dst; if (is_dir_sep(*src)) { @@ -702,9 +703,18 @@ int daemon_avoid_alias(const char *p) } } -int offset_1st_component(const char *path) +int offset_1st_component(const char *path, int keep_root) { - if (has_dos_drive_prefix(path)) - return 2 + is_dir_sep(path[2]); - return is_dir_sep(path[0]); + if (has_dos_root_prefix(path)) { + if (path[1] == ':') + return 2 + (keep_root ? 0 : is_dir_sep(path[2])); + else { + const char *s = strchr(path + 2, '/'); + /* //host is considered a "drive" */ + if (s) + return s - path + (keep_root ? 0 : 1); + } + } + + return keep_root ? 0 : is_dir_sep(path[0]); } diff --git a/read-cache.c b/read-cache.c index 2f8159f..d4d339a 100644 --- a/read-cache.c +++ b/read-cache.c @@ -755,7 +755,7 @@ int verify_path(const char *path) { char c; - if (has_dos_drive_prefix(path)) + if (has_dos_root_prefix(path)) return 0; goto inside; diff --git a/setup.c b/setup.c index 9139bee..e010cf8 100644 --- a/setup.c +++ b/setup.c @@ -26,7 +26,7 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path) if (!work_tree) goto error_out; len = strlen(work_tree); - root_len = offset_1st_component(work_tree); + root_len = offset_1st_component(work_tree, 0); total = strlen(sanitized) + 1; if (strncmp(sanitized, work_tree, len) || (len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) { @@ -587,7 +587,7 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi if (offset != len) { if (chdir(cwd)) die_errno("Cannot come back to cwd"); - root_len = offset_1st_component(cwd); + root_len = offset_1st_component(cwd, 0); cwd[offset > root_len ? offset : root_len] = '\0'; set_git_dir(cwd); } @@ -654,7 +654,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok) return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok); ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs); - if (ceil_offset < 0 && has_dos_drive_prefix(cwd)) + if (ceil_offset < 0 && has_dos_root_prefix(cwd)) ceil_offset = 1; /* diff --git a/sha1_file.c b/sha1_file.c index af5cfbd..21ce020 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -102,7 +102,7 @@ int mkdir_in_gitdir(const char *path) int safe_create_leading_directories(char *path) { - char *pos = path + offset_1st_component(path); + char *pos = path + offset_1st_component(path, 0); struct stat st; while (pos) { diff --git a/transport.c b/transport.c index 1811b50..5141e8f 100644 --- a/transport.c +++ b/transport.c @@ -869,7 +869,7 @@ static int is_local(const char *url) const char *colon = strchr(url, ':'); const char *slash = strchr(url, '/'); return !colon || (slash && slash < colon) || - has_dos_drive_prefix(url); + has_dos_root_prefix(url); } static int is_file(const char *url) -- 8< -- -- 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