Refactor skipping DOS drive prefixes

Junio Hamano pointed out that there is an implicit assumption in pretty
much all the code calling has_dos_drive_prefix(): it assumes that the
DOS drive prefix is always two bytes long.

While this assumption is pretty safe, we can still make the code more
readable and less error-prone by introducing a function that skips the
DOS drive prefix safely.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin
2016-01-06 14:46:10 +01:00
parent 5c016356a3
commit 560b1947ca
5 changed files with 28 additions and 22 deletions

View File

@@ -4,9 +4,7 @@
char *gitbasename (char *path)
{
const char *base;
/* Skip over the disk name in MSDOS pathnames. */
if (has_dos_drive_prefix(path))
path += 2;
skip_dos_drive_prefix(&path);
for (base = path; *path; path++) {
if (is_dir_sep(*path))
base = path + 1;

View File

@@ -1981,26 +1981,22 @@ pid_t waitpid(pid_t pid, int *status, int options)
int mingw_offset_1st_component(const char *path)
{
int offset = 0;
if (has_dos_drive_prefix(path))
offset = 2;
char *pos = (char *)path;
/* unc paths */
else if (is_dir_sep(path[0]) && is_dir_sep(path[1])) {
if (!skip_dos_drive_prefix(&pos) &&
is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
/* skip server name */
char *pos = strpbrk(path + 2, "\\/");
pos = strpbrk(pos + 2, "\\/");
if (!pos)
return 0; /* Error: malformed unc path */
do {
pos++;
} while (*pos && !is_dir_sep(*pos));
offset = pos - path;
}
return offset + is_dir_sep(path[offset]);
return pos + is_dir_sep(*pos) - path;
}
int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)

View File

@@ -383,7 +383,15 @@ HANDLE winansi_get_osfhandle(int fd);
* git specific compatibility
*/
#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
#define has_dos_drive_prefix(path) \
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
static inline int mingw_skip_dos_drive_prefix(char **path)
{
int ret = has_dos_drive_prefix(*path);
*path += ret;
return ret;
}
#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
static inline char *mingw_find_last_dir_sep(const char *path)
{

View File

@@ -335,6 +335,14 @@ static inline int git_has_dos_drive_prefix(const char *path)
#define has_dos_drive_prefix git_has_dos_drive_prefix
#endif
#ifndef skip_dos_drive_prefix
static inline int git_skip_dos_drive_prefix(const char **path)
{
return 0;
}
#define skip_dos_drive_prefix git_skip_dos_drive_prefix
#endif
#ifndef is_dir_sep
static inline int git_is_dir_sep(int c)
{

14
path.c
View File

@@ -782,13 +782,10 @@ const char *relative_path(const char *in, const char *prefix,
else if (!prefix_len)
return in;
if (have_same_root(in, prefix)) {
if (have_same_root(in, prefix))
/* bypass dos_drive, for "c:" is identical to "C:" */
if (has_dos_drive_prefix(in)) {
i = 2;
j = 2;
}
} else {
i = j = has_dos_drive_prefix(in);
else {
return in;
}
@@ -943,11 +940,10 @@ const char *remove_leading_path(const char *in, const char *prefix)
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
{
char *dst0;
int i;
if (has_dos_drive_prefix(src)) {
for (i = has_dos_drive_prefix(src); i > 0; i--)
*dst++ = *src++;
*dst++ = *src++;
}
dst0 = dst;
if (is_dir_sep(*src)) {