mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 06:20:56 +00:00
Merge pull request #4111 from pks-t/pks/dos-prefix
dirname with DOS prefixes
This commit is contained in:
commit
683ff4f323
71
src/path.c
71
src/path.c
@ -110,6 +110,34 @@ Exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine if the path is a Windows prefix and, if so, returns
|
||||||
|
* its actual lentgh. If it is not a prefix, returns -1.
|
||||||
|
*/
|
||||||
|
static int win32_prefix_length(const char *path, int len)
|
||||||
|
{
|
||||||
|
#ifndef GIT_WIN32
|
||||||
|
GIT_UNUSED(path);
|
||||||
|
GIT_UNUSED(len);
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return
|
||||||
|
* 'C:/' here
|
||||||
|
*/
|
||||||
|
if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path))
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similarly checks if we're dealing with a network computer name
|
||||||
|
* '//computername/.git' will return '//computername/'
|
||||||
|
*/
|
||||||
|
if (looks_like_network_computer_name(path, len))
|
||||||
|
return len;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Based on the Android implementation, BSD licensed.
|
* Based on the Android implementation, BSD licensed.
|
||||||
* Check http://android.git.kernel.org/
|
* Check http://android.git.kernel.org/
|
||||||
@ -117,7 +145,7 @@ Exit:
|
|||||||
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 result, 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') {
|
||||||
@ -131,6 +159,11 @@ 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) {
|
||||||
|
is_prefix = 1;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the start of the dir */
|
/* Find the start of the dir */
|
||||||
while (endp > path && *endp != '/')
|
while (endp > path && *endp != '/')
|
||||||
endp--;
|
endp--;
|
||||||
@ -146,35 +179,23 @@ 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) {
|
||||||
|
is_prefix = 1;
|
||||||
|
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);
|
||||||
|
|
||||||
#ifdef GIT_WIN32
|
|
||||||
/* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return
|
|
||||||
'C:/' here */
|
|
||||||
|
|
||||||
if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) {
|
|
||||||
len = 3;
|
|
||||||
goto Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Similarly checks if we're dealing with a network computer name
|
|
||||||
'//computername/.git' will return '//computername/' */
|
|
||||||
|
|
||||||
if (looks_like_network_computer_name(path, len)) {
|
|
||||||
len++;
|
|
||||||
goto Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
result = len;
|
if (buffer) {
|
||||||
|
if (git_buf_set(buffer, path, len) < 0)
|
||||||
|
return -1;
|
||||||
|
if (is_prefix && git_buf_putc(buffer, '/') < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer != NULL && git_buf_set(buffer, path, len) < 0)
|
return len;
|
||||||
return -1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,8 +89,12 @@ void test_core_path__00_dirname(void)
|
|||||||
check_dirname(REP16("/abc"), REP15("/abc"));
|
check_dirname(REP16("/abc"), REP15("/abc"));
|
||||||
|
|
||||||
#ifdef GIT_WIN32
|
#ifdef GIT_WIN32
|
||||||
|
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/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");
|
||||||
|
@ -199,3 +199,12 @@ void test_repo_discover__discovery_starting_at_file_succeeds(void)
|
|||||||
|
|
||||||
ensure_repository_discover(SUB_REPOSITORY_FOLDER "/file", ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
|
ensure_repository_discover(SUB_REPOSITORY_FOLDER "/file", ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_repo_discover__discovery_starting_at_system_root_causes_no_hang(void)
|
||||||
|
{
|
||||||
|
#ifdef GIT_WIN32
|
||||||
|
git_buf out = GIT_BUF_INIT;
|
||||||
|
cl_git_fail(git_repository_discover(&out, "C:/", 0, NULL));
|
||||||
|
cl_git_fail(git_repository_discover(&out, "//localhost/", 0, NULL));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
0
tests/resources/testrepo.git/index
Normal file → Executable file
0
tests/resources/testrepo.git/index
Normal file → Executable file
Loading…
Reference in New Issue
Block a user