On Wed, Sep 05, 2012 at 08:23:58PM -0700, Junio C Hamano wrote:
> Nguyen Thai Ngoc Duy <[email protected]> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html