Commit 9e8d75c7 by Patrick Steinhardt

path: ensure dirname on Win32 prefix always has a trailing '/'

When calling `git_path_dirname_r` on a Win32 prefix, e.g. a drive
or network share prefix, we always want to return the trailing
'/'. This does not work currently when passing in a path like
'C:', where the '/' would not be appended correctly.

Fix this by appending a '/' if we try to normalize a Win32 prefix
and there is no trailing '/'.
parent 5d59520c
...@@ -125,14 +125,14 @@ static int win32_prefix_length(const char *path, int len) ...@@ -125,14 +125,14 @@ static int win32_prefix_length(const char *path, int len)
* 'C:/' here * 'C:/' here
*/ */
if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path))
return 3; return 2;
/* /*
* Similarly checks if we're dealing with a network computer name * Similarly checks if we're dealing with a network computer name
* '//computername/.git' will return '//computername/' * '//computername/.git' will return '//computername/'
*/ */
if (looks_like_network_computer_name(path, len)) if (looks_like_network_computer_name(path, len))
return len + 1; return len;
#endif #endif
return -1; return -1;
...@@ -145,7 +145,7 @@ static int win32_prefix_length(const char *path, int len) ...@@ -145,7 +145,7 @@ static int win32_prefix_length(const char *path, int len)
int git_path_dirname_r(git_buf *buffer, const char *path) int git_path_dirname_r(git_buf *buffer, const char *path)
{ {
const char *endp; const char *endp;
int len; int is_prefix = 0, len;
/* Empty or NULL string gets treated as "." */ /* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') { if (path == NULL || *path == '\0') {
...@@ -159,8 +159,10 @@ int git_path_dirname_r(git_buf *buffer, const char *path) ...@@ -159,8 +159,10 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
while (endp > path && *endp == '/') while (endp > path && *endp == '/')
endp--; endp--;
if ((len = win32_prefix_length(path, endp - path + 1)) > 0) if ((len = win32_prefix_length(path, endp - path + 1)) > 0) {
is_prefix = 1;
goto Exit; goto Exit;
}
/* Find the start of the dir */ /* Find the start of the dir */
while (endp > path && *endp != '/') while (endp > path && *endp != '/')
...@@ -177,15 +179,21 @@ int git_path_dirname_r(git_buf *buffer, const char *path) ...@@ -177,15 +179,21 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
endp--; endp--;
} while (endp > path && *endp == '/'); } while (endp > path && *endp == '/');
if ((len = win32_prefix_length(path, endp - path + 1)) > 0) if ((len = win32_prefix_length(path, endp - path + 1)) > 0) {
is_prefix = 1;
goto Exit; goto Exit;
}
/* Cast is safe because max path < max int */ /* Cast is safe because max path < max int */
len = (int)(endp - path + 1); len = (int)(endp - path + 1);
Exit: Exit:
if (buffer != NULL && git_buf_set(buffer, path, len) < 0) if (buffer) {
if (git_buf_set(buffer, path, len) < 0)
return -1; return -1;
if (is_prefix && git_buf_putc(buffer, '/') < 0)
return -1;
}
return len; return len;
} }
......
...@@ -90,9 +90,11 @@ void test_core_path__00_dirname(void) ...@@ -90,9 +90,11 @@ void test_core_path__00_dirname(void)
#ifdef GIT_WIN32 #ifdef GIT_WIN32
check_dirname("C:/", "C:/"); check_dirname("C:/", "C:/");
check_dirname("C:", "C:/");
check_dirname("C:/path/", "C:/"); check_dirname("C:/path/", "C:/");
check_dirname("C:/path", "C:/"); check_dirname("C:/path", "C:/");
check_dirname("//computername/", "//computername/"); check_dirname("//computername/", "//computername/");
check_dirname("//computername", "//computername/");
check_dirname("//computername/path/", "//computername/"); check_dirname("//computername/path/", "//computername/");
check_dirname("//computername/path", "//computername/"); check_dirname("//computername/path", "//computername/");
check_dirname("//computername/sub/path/", "//computername/sub"); check_dirname("//computername/sub/path/", "//computername/sub");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment