Commit 2c0cdc3a86acd917087937f6348062b3951217b5

Russell Belfer 2012-05-08T10:40:01

Merge pull request #674 from nulltoken/topic/GIT_ENOTFOUND Improve the interop with bindings

diff --git a/src/object.c b/src/object.c
index e02bd69..02be5da 100644
--- a/src/object.c
+++ b/src/object.c
@@ -150,8 +150,8 @@ int git_object_lookup_prefix(
 
 	if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
 		git_odb_object_free(odb_obj);
-		giterr_set(GITERR_INVALID, "The given type does not match the type on the ODB");
-		return -1;
+		giterr_set(GITERR_ODB, "The given type does not match the type on the ODB");
+		return GIT_ENOTFOUND;
 	}
 
 	type = odb_obj->raw.type;
diff --git a/src/path.c b/src/path.c
index 703f43a..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) ? GIT_ENOTFOUND : -1;
+		
+		return error;
 	}
 
 	return git_buf_sets(path_out, buf);
diff --git a/src/remote.c b/src/remote.c
index 98c2569..6a1390d 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -102,24 +102,28 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
 	remote->name = git__strdup(name);
 	GITERR_CHECK_ALLOC(remote->name);
 
-	if (git_vector_init(&remote->refs, 32, NULL) < 0)
-		return -1;
-
-	if (git_buf_printf(&buf, "remote.%s.url", name) < 0)
-		return -1;
+	if (git_vector_init(&remote->refs, 32, NULL) < 0) {
+		error = -1;
+		goto cleanup;
+	}
 
-	if (git_config_get_string(config, git_buf_cstr(&buf), &val) < 0) {
+	if (git_buf_printf(&buf, "remote.%s.url", name) < 0) {
 		error = -1;
 		goto cleanup;
 	}
 
+	if ((error = git_config_get_string(config, git_buf_cstr(&buf), &val)) < 0)
+		goto cleanup;
+
 	remote->repo = repo;
 	remote->url = git__strdup(val);
 	GITERR_CHECK_ALLOC(remote->url);
 
 	git_buf_clear(&buf);
-	if (git_buf_printf(&buf, "remote.%s.fetch", name) < 0)
-		return -1;
+	if (git_buf_printf(&buf, "remote.%s.fetch", name) < 0) {
+		error = -1;
+		goto cleanup;
+	}
 
 	error = parse_remote_refspec(config, &remote->fetch, git_buf_cstr(&buf));
 	if (error == GIT_ENOTFOUND)
@@ -131,8 +135,10 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
 	}
 
 	git_buf_clear(&buf);
-	if (git_buf_printf(&buf, "remote.%s.push", name) < 0)
-		return -1;
+	if (git_buf_printf(&buf, "remote.%s.push", name) < 0) {
+		error = -1;
+		goto cleanup;
+	}
 
 	error = parse_remote_refspec(config, &remote->push, git_buf_cstr(&buf));
 	if (error == GIT_ENOTFOUND)
diff --git a/src/repository.c b/src/repository.c
index d4de381..ea96737 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -397,13 +397,14 @@ int git_repository_discover(
 {
 	git_buf path = GIT_BUF_INIT;
 	uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
+	int error;
 
 	assert(start_path && repository_path && size > 0);
 
 	*repository_path = '\0';
 
-	if (find_repo(&path, NULL, start_path, flags, ceiling_dirs) < 0)
-		return -1;
+	if ((error = find_repo(&path, NULL, start_path, flags, ceiling_dirs)) < 0)
+		return error != GIT_ENOTFOUND ? -1 : error;
 
 	if (size < (size_t)(path.size + 1)) {
 		giterr_set(GITERR_REPOSITORY,
diff --git a/src/status.c b/src/status.c
index ff8535c..546dc86 100644
--- a/src/status.c
+++ b/src/status.c
@@ -340,17 +340,17 @@ int git_status_file(
 	assert(status_flags && repo && path);
 
 	if ((workdir = git_repository_workdir(repo)) == NULL) {
-		giterr_set(GITERR_OS, "Cannot get file status from bare repo");
-		return GIT_ENOTFOUND;
+		giterr_set(GITERR_INVALID, "Cannot get file status from bare repo");
+		return -1;
 	}
 
 	if (git_buf_joinpath(&temp_path, workdir, path) < 0)
 		return -1;
 
 	if (git_path_isdir(temp_path.ptr)) {
-		giterr_set(GITERR_OS, "Cannot get file status for directory '%s'", temp_path.ptr);
+		giterr_set(GITERR_INVALID, "Cannot get file status for directory '%s'", temp_path.ptr);
 		git_buf_free(&temp_path);
-		return GIT_ENOTFOUND;
+		return -1;
 	}
 
 	e = status_entry_new(NULL, path);
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);
+}
diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c
index 766a461..f03d983 100644
--- a/tests-clar/network/remotes.c
+++ b/tests-clar/network/remotes.c
@@ -153,3 +153,8 @@ void test_network_remotes__list(void)
 
 	git_config_free(cfg);
 }
+
+void test_network_remotes__loading_a_missing_remote_returns_ENOTFOUND(void)
+{
+	cl_assert_equal_i(GIT_ENOTFOUND, git_remote_load(&_remote, _repo, "just-left-few-minutes-ago"));
+}
diff --git a/tests-clar/object/lookup.c b/tests-clar/object/lookup.c
new file mode 100644
index 0000000..4db2ecf
--- /dev/null
+++ b/tests-clar/object/lookup.c
@@ -0,0 +1,35 @@
+#include "clar_libgit2.h"
+
+#include "repository.h"
+
+static git_repository *g_repo;
+
+void test_object_lookup__initialize(void)
+{
+   cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
+}
+
+void test_object_lookup__cleanup(void)
+{
+   git_repository_free(g_repo);
+}
+
+void test_object_lookup__looking_up_an_exisiting_object_by_its_wrong_type_returns_ENOTFOUND(void)
+{
+	const char *commit = "e90810b8df3e80c413d903f631643c716887138d";
+	git_oid oid;
+	git_object *object;
+
+	cl_git_pass(git_oid_fromstr(&oid, commit));
+	cl_assert_equal_i(GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_TAG));
+}
+
+void test_object_lookup__looking_up_a_non_exisiting_object_returns_ENOTFOUND(void)
+{
+	const char *unknown = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
+	git_oid oid;
+	git_object *object;
+
+	cl_git_pass(git_oid_fromstr(&oid, unknown));
+	cl_assert_equal_i(GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_ANY));
+}
diff --git a/tests-clar/repo/discover.c b/tests-clar/repo/discover.c
index 6b17d6d..b3d639b 100644
--- a/tests-clar/repo/discover.c
+++ b/tests-clar/repo/discover.c
@@ -82,7 +82,7 @@ void test_repo_discover__0(void)
 	append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER);
 	ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
 
-	cl_git_fail(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
+	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
 
 	cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
 	cl_git_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
@@ -117,7 +117,7 @@ void test_repo_discover__0(void)
 	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
 	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
 	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
-	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
+	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
 
 	append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
 	ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
@@ -125,9 +125,9 @@ void test_repo_discover__0(void)
 	//this must pass as ceiling_directories cannot predent the current
 	//working directory to be checked
 	cl_git_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
-	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
-	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
-	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
+	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
+	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
+	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
 
 	//.gitfile redirection should not be affected by ceiling directories
 	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path);
@@ -135,7 +135,7 @@ void test_repo_discover__0(void)
 	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
 	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path);
 
-	cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
+	cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, GIT_DIRREMOVAL_FILES_AND_DIRS));
 	git_repository_free(repo);
 	git_buf_free(&ceiling_dirs_buf);
 }
diff --git a/tests-clar/repo/open.c b/tests-clar/repo/open.c
index 1813887..2924663 100644
--- a/tests-clar/repo/open.c
+++ b/tests-clar/repo/open.c
@@ -7,7 +7,7 @@ void test_repo_open__cleanup(void)
 	cl_git_sandbox_cleanup();
 
 	if (git_path_isdir("alternate"))
-		git_futils_rmdir_r("alternate", 1);
+		git_futils_rmdir_r("alternate", GIT_DIRREMOVAL_FILES_AND_DIRS);
 }
 
 void test_repo_open__bare_empty_repo(void)
@@ -202,8 +202,8 @@ void test_repo_open__bad_gitlinks(void)
 		cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL));
 	}
 
-	git_futils_rmdir_r("invalid", 1);
-	git_futils_rmdir_r("invalid2", 1);
+	git_futils_rmdir_r("invalid", GIT_DIRREMOVAL_FILES_AND_DIRS);
+	git_futils_rmdir_r("invalid2", GIT_DIRREMOVAL_FILES_AND_DIRS);
 }
 
 #ifdef GIT_WIN32
@@ -274,3 +274,9 @@ void test_repo_open__win32_path(void)
 	git_buf_free(&winpath);
 #endif
 }
+
+void test_repo_open__opening_a_non_existing_repository_returns_ENOTFOUND(void)
+{
+	git_repository *repo;
+	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_open(&repo, "i-do-not/exist"));
+}
\ No newline at end of file
diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c
index 8f48cf1..2a647ff 100644
--- a/tests-clar/status/worktree.c
+++ b/tests-clar/status/worktree.c
@@ -275,6 +275,7 @@ void test_status_worktree__single_folder(void)
 
 	error = git_status_file(&status_flags, repo, "subdir");
 	cl_git_fail(error);
+	cl_assert(error != GIT_ENOTFOUND);
 }
 
 
@@ -384,3 +385,18 @@ void test_status_worktree__issue_592_5(void)
 
 	git_buf_free(&path);
 }
+
+void test_status_worktree__cannot_retrieve_the_status_of_a_bare_repository(void)
+{
+	git_repository *repo;
+	int error, status = 0;
+
+	cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+	error = git_status_file(&status, repo, "dummy");
+
+	cl_git_fail(error);
+	cl_assert(error != GIT_ENOTFOUND);
+
+	git_repository_free(repo);
+}
\ No newline at end of file