compat: make p_realpath Windows implementation be a bit more POSIX compliant and fail if the provided path does not lead to an existing entry
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
diff --git a/src/path.c b/src/path.c
index ccf80ed..9f31676 100644
--- a/src/path.c
+++ b/src/path.c
@@ -205,9 +205,13 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base)
}
if (p_realpath(path, buf) == NULL) {
+ /* giterr_set resets the errno when dealing with a GITERR_OS kind of error */
+ int error = (errno == ENOENT || errno == ENOTDIR) ? GIT_ENOTFOUND : -1;
giterr_set(GITERR_OS, "Failed to resolve path '%s'", path);
+
git_buf_clear(path_out);
- return (errno == ENOENT || errno == ENOTDIR) ? GIT_ENOTFOUND : -1;
+
+ return error;
}
return git_buf_sets(path_out, buf);
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 6172918..10de70d 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -326,7 +326,7 @@ int p_hide_directory__w32(const char *path)
char *p_realpath(const char *orig_path, char *buffer)
{
- int ret;
+ int ret, buffer_sz = 0;
wchar_t* orig_path_w = gitwin_to_utf16(orig_path);
wchar_t* buffer_w = (wchar_t*)git__malloc(GIT_PATH_MAX * sizeof(wchar_t));
@@ -336,13 +336,14 @@ char *p_realpath(const char *orig_path, char *buffer)
ret = GetFullPathNameW(orig_path_w, GIT_PATH_MAX, buffer_w, NULL);
git__free(orig_path_w);
- if (!ret || ret > GIT_PATH_MAX) {
+ /* According to MSDN, a return value equals to zero means a failure. */
+ if (ret == 0 || ret > GIT_PATH_MAX) {
buffer = NULL;
goto done;
}
if (buffer == NULL) {
- int buffer_sz = WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, NULL, 0, NULL, NULL);
+ buffer_sz = WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, NULL, 0, NULL, NULL);
if (!buffer_sz ||
!(buffer = (char *)git__malloc(buffer_sz)) ||
@@ -350,10 +351,22 @@ char *p_realpath(const char *orig_path, char *buffer)
{
git__free(buffer);
buffer = NULL;
+ goto done;
}
} else {
- if (!WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, GIT_PATH_MAX, NULL, NULL))
+ if (!WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, GIT_PATH_MAX, NULL, NULL)) {
buffer = NULL;
+ goto done;
+ }
+ }
+
+ if (!git_path_exists(buffer))
+ {
+ if (buffer_sz > 0)
+ git__free(buffer);
+
+ buffer = NULL;
+ errno = ENOENT;
}
done:
diff --git a/tests-clar/core/path.c b/tests-clar/core/path.c
index f02e0f7..d826612 100644
--- a/tests-clar/core/path.c
+++ b/tests-clar/core/path.c
@@ -405,3 +405,16 @@ void test_core_path__12_offset_to_path_root(void)
cl_assert(git_path_root("//computername") == -1);
#endif
}
+
+#define NON_EXISTING_FILEPATH "i_hope_i_do_not_exist"
+
+void test_core_path__13_cannot_prettify_a_non_existing_file(void)
+{
+ git_buf p = GIT_BUF_INIT;
+
+ cl_must_pass(git_path_exists(NON_EXISTING_FILEPATH) == false);
+ cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH, NULL));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL));
+
+ git_buf_free(&p);
+}