Commit 5d59520ccd4816080e68b5a3057653c15f3d6816

Patrick Steinhardt 2017-02-07T20:30:11

path: get correct dirname for Windows root Getting the dirname of a filesystem root should return the filesystem root itself. E.g. the dirname of "/" is always "/". On Windows, we emulate this behavior and as such, we should return e.g. "C:/" if calling dirname on "C:/". But we currently fail to do so and instead return ".", as we do not check if we actually have a Windows prefix before stripping off the last directory component. Fix this by calling out to `win32_prefix_length` immediately after stripping trailing slashes, returning early if we have a prefix.

diff --git a/src/path.c b/src/path.c
index 0e9e04d..3c78c8b 100644
--- a/src/path.c
+++ b/src/path.c
@@ -159,6 +159,9 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
 	while (endp > path && *endp == '/')
 		endp--;
 
+	if ((len = win32_prefix_length(path, endp - path + 1)) > 0)
+		goto Exit;
+
 	/* Find the start of the dir */
 	while (endp > path && *endp != '/')
 		endp--;
diff --git a/tests/core/path.c b/tests/core/path.c
index 71c6eda..eaaaf72 100644
--- a/tests/core/path.c
+++ b/tests/core/path.c
@@ -89,8 +89,10 @@ void test_core_path__00_dirname(void)
 	check_dirname(REP16("/abc"), REP15("/abc"));
 
 #ifdef GIT_WIN32
+	check_dirname("C:/", "C:/");
 	check_dirname("C:/path/", "C:/");
 	check_dirname("C:/path", "C:/");
+	check_dirname("//computername/", "//computername/");
 	check_dirname("//computername/path/", "//computername/");
 	check_dirname("//computername/path", "//computername/");
 	check_dirname("//computername/sub/path/", "//computername/sub");