Skip to content

Commit 2f36eed

Browse files
dschogitster
authored andcommitted
Refactor skipping DOS drive prefixes
Junio noticed that there is an implicit assumption in pretty much all the code calling has_dos_drive_prefix(): it forces all of its callsites to hardcode the knowledge 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. While at it, we change the has_dos_drive_prefix() return value: it now returns the number of bytes to be skipped if there is a DOS drive prefix. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 833e482 commit 2f36eed

File tree

5 files changed

+28
-22
lines changed

5 files changed

+28
-22
lines changed

compat/basename.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
char *gitbasename (char *path)
55
{
66
const char *base;
7-
/* Skip over the disk name in MSDOS pathnames. */
8-
if (has_dos_drive_prefix(path))
9-
path += 2;
7+
skip_dos_drive_prefix(&path);
108
for (base = path; *path; path++) {
119
if (is_dir_sep(*path))
1210
base = path + 1;

compat/mingw.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,26 +1917,22 @@ pid_t waitpid(pid_t pid, int *status, int options)
19171917

19181918
int mingw_offset_1st_component(const char *path)
19191919
{
1920-
int offset = 0;
1921-
if (has_dos_drive_prefix(path))
1922-
offset = 2;
1920+
char *pos = (char *)path;
19231921

19241922
/* unc paths */
1925-
else if (is_dir_sep(path[0]) && is_dir_sep(path[1])) {
1926-
1923+
if (!skip_dos_drive_prefix(&pos) &&
1924+
is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
19271925
/* skip server name */
1928-
char *pos = strpbrk(path + 2, "\\/");
1926+
pos = strpbrk(pos + 2, "\\/");
19291927
if (!pos)
19301928
return 0; /* Error: malformed unc path */
19311929

19321930
do {
19331931
pos++;
19341932
} while (*pos && !is_dir_sep(*pos));
1935-
1936-
offset = pos - path;
19371933
}
19381934

1939-
return offset + is_dir_sep(path[offset]);
1935+
return pos + is_dir_sep(*pos) - path;
19401936
}
19411937

19421938
int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)

compat/mingw.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,15 @@ HANDLE winansi_get_osfhandle(int fd);
358358
* git specific compatibility
359359
*/
360360

361-
#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
361+
#define has_dos_drive_prefix(path) \
362+
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
363+
static inline int mingw_skip_dos_drive_prefix(char **path)
364+
{
365+
int ret = has_dos_drive_prefix(*path);
366+
*path += ret;
367+
return ret;
368+
}
369+
#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
362370
#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
363371
static inline char *mingw_find_last_dir_sep(const char *path)
364372
{

git-compat-util.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,14 @@ static inline int git_has_dos_drive_prefix(const char *path)
335335
#define has_dos_drive_prefix git_has_dos_drive_prefix
336336
#endif
337337

338+
#ifndef skip_dos_drive_prefix
339+
static inline int git_skip_dos_drive_prefix(char **path)
340+
{
341+
return 0;
342+
}
343+
#define skip_dos_drive_prefix git_skip_dos_drive_prefix
344+
#endif
345+
338346
#ifndef is_dir_sep
339347
static inline int git_is_dir_sep(int c)
340348
{

path.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -544,13 +544,10 @@ const char *relative_path(const char *in, const char *prefix,
544544
else if (!prefix_len)
545545
return in;
546546

547-
if (have_same_root(in, prefix)) {
547+
if (have_same_root(in, prefix))
548548
/* bypass dos_drive, for "c:" is identical to "C:" */
549-
if (has_dos_drive_prefix(in)) {
550-
i = 2;
551-
j = 2;
552-
}
553-
} else {
549+
i = j = has_dos_drive_prefix(in);
550+
else {
554551
return in;
555552
}
556553

@@ -703,11 +700,10 @@ const char *remove_leading_path(const char *in, const char *prefix)
703700
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
704701
{
705702
char *dst0;
703+
int i;
706704

707-
if (has_dos_drive_prefix(src)) {
705+
for (i = has_dos_drive_prefix(src); i > 0; i--)
708706
*dst++ = *src++;
709-
*dst++ = *src++;
710-
}
711707
dst0 = dst;
712708

713709
if (is_dir_sep(*src)) {

0 commit comments

Comments
 (0)