diff --git a/src/clone.c b/src/clone.c index 3f161c810..803338ebb 100644 --- a/src/clone.c +++ b/src/clone.c @@ -195,54 +195,14 @@ static int setup_remotes_and_fetch(git_repository *repo, /* TODO: p_opendir, p_closedir */ static bool path_is_okay(const char *path) { -#ifdef GIT_WIN32 - HANDLE hFind = INVALID_HANDLE_VALUE; - wchar_t *wbuf; - WIN32_FIND_DATAW ffd; -#else - DIR *dir = NULL; - struct dirent *e; -#endif - - bool retval = true; - /* The path must either not exist, or be an empty directory */ if (!git_path_exists(path)) return true; - - if (!git_path_isdir(path)) { + if (!git_path_is_empty_dir(path)) { giterr_set(GITERR_INVALID, "'%s' exists and is not an empty directory", path); return false; } - -#ifdef GIT_WIN32 - wbuf = gitwin_to_utf16(path); - gitwin_append_utf16(wbuf, "\\*", 2); - hFind = FindFirstFileW(wbuf, &ffd); - if (INVALID_HANDLE_VALUE != hFind) { - retval = false; - FindClose(hFind); - } - git__free(wbuf); -#else - dir = opendir(path); - if (!dir) { - giterr_set(GITERR_OS, "Couldn't open '%s'", path); - return false; - } - - while ((e = readdir(dir)) != NULL) { - if (!git_path_is_dot_or_dotdot(e->d_name)) { - giterr_set(GITERR_INVALID, - "'%s' exists and is not an empty directory", path); - retval = false; - break; - } - } - closedir(dir); -#endif - - return retval; + return true; } diff --git a/src/path.c b/src/path.c index 3de4b1100..e667ec357 100644 --- a/src/path.c +++ b/src/path.c @@ -389,6 +389,58 @@ bool git_path_isfile(const char *path) return S_ISREG(st.st_mode) != 0; } +#ifdef GIT_WIN32 + +bool git_path_is_empty_dir(const char *path) +{ + HANDLE hFind = INVALID_HANDLE_VALUE; + wchar_t *wbuf; + WIN32_FIND_DATAW ffd; + bool retval = true; + + if (!git_path_isdir(path)) return false; + + wbuf = gitwin_to_utf16(path); + gitwin_append_utf16(wbuf, "\\*", 2); + hFind = FindFirstFileW(wbuf, &ffd); + if (INVALID_HANDLE_VALUE != hFind) { + retval = false; + FindClose(hFind); + } + git__free(wbuf); + return retval; +} + +#else + +bool git_path_is_empty_dir(const char *path) +{ + DIR *dir = NULL; + struct dirent *e; + bool retval = true; + + if (!git_path_isdir(path)) return false; + + dir = opendir(path); + if (!dir) { + giterr_set(GITERR_OS, "Couldn't open '%s'", path); + return false; + } + + while ((e = readdir(dir)) != NULL) { + if (!git_path_is_dot_or_dotdot(e->d_name)) { + giterr_set(GITERR_INVALID, + "'%s' exists and is not an empty directory", path); + retval = false; + break; + } + } + closedir(dir); + + return retval; +} +#endif + int git_path_lstat(const char *path, struct stat *st) { int err = 0; diff --git a/src/path.h b/src/path.h index 76e01fc8f..116477043 100644 --- a/src/path.h +++ b/src/path.h @@ -80,7 +80,9 @@ extern int git_path_to_dir(git_buf *path); */ extern void git_path_string_to_dir(char* path, size_t size); -/* Taken from git.git */ +/** + * Taken from git.git; returns nonzero if the given path is "." or "..". + */ GIT_INLINE(int) git_path_is_dot_or_dotdot(const char *name) { return (name[0] == '.' && @@ -137,6 +139,11 @@ extern bool git_path_isdir(const char *path); */ extern bool git_path_isfile(const char *path); +/** + * Check if the given path is a directory, and is empty. + */ +extern bool git_path_is_empty_dir(const char *path); + /** * Stat a file and/or link and set error if needed. */ diff --git a/tests-clar/clone/clone.c b/tests-clar/clone/clone.c index b0c8479b4..49deeaae4 100644 --- a/tests-clar/clone/clone.c +++ b/tests-clar/clone/clone.c @@ -4,6 +4,8 @@ #include "repository.h" #define DO_LIVE_NETWORK_TESTS 0 +#define DO_LOCAL_TEST 0 +#define LIVE_REPO_URL "http://github.com/libgit2/node-gitteh" static git_repository *g_repo; @@ -77,7 +79,7 @@ void test_clone_clone__local(void) git_buf src = GIT_BUF_INIT; build_local_file_url(&src, cl_fixture("testrepo.git")); -#if DO_LIVE_NETWORK_TESTS +#if DO_LOCAL_TEST cl_git_pass(git_clone(&g_repo, git_buf_cstr(&src), "./local", NULL)); git_repository_free(g_repo); git_futils_rmdir_r("./local", GIT_DIRREMOVAL_FILES_AND_DIRS); @@ -94,10 +96,10 @@ void test_clone_clone__network_full(void) #if DO_LIVE_NETWORK_TESTS git_remote *origin; - cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/node-gitteh", "./attr", NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./test", NULL)); cl_assert(!git_repository_is_bare(g_repo)); cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - git_futils_rmdir_r("./attr", GIT_DIRREMOVAL_FILES_AND_DIRS); + git_futils_rmdir_r("./test", GIT_DIRREMOVAL_FILES_AND_DIRS); #endif } @@ -106,10 +108,10 @@ void test_clone_clone__network_bare(void) #if DO_LIVE_NETWORK_TESTS git_remote *origin; - cl_git_pass(git_clone_bare(&g_repo, "http://github.com/libgit2/node-gitteh", "attr", NULL)); + cl_git_pass(git_clone_bare(&g_repo, LIVE_REPO_URL, "test", NULL)); cl_assert(git_repository_is_bare(g_repo)); cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - git_futils_rmdir_r("./attr", GIT_DIRREMOVAL_FILES_AND_DIRS); + git_futils_rmdir_r("./test", GIT_DIRREMOVAL_FILES_AND_DIRS); #endif } @@ -119,25 +121,19 @@ void test_clone_clone__already_exists(void) #if DO_LIVE_NETWORK_TESTS /* Should pass with existing-but-empty dir */ p_mkdir("./foo", GIT_DIR_MODE); - cl_git_pass(git_clone(&g_repo, - "http://github.com/libgit2/libgit2.git", - "./foo", NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL)); git_repository_free(g_repo); g_repo = NULL; git_futils_rmdir_r("./foo", GIT_DIRREMOVAL_FILES_AND_DIRS); #endif /* Should fail with a file */ cl_git_mkfile("./foo", "Bar!"); - cl_git_fail(git_clone(&g_repo, - "http://github.com/libgit2/libgit2.git", - "./foo", NULL)); + cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL)); git_futils_rmdir_r("./foo", GIT_DIRREMOVAL_FILES_AND_DIRS); /* Should fail with existing-and-nonempty dir */ p_mkdir("./foo", GIT_DIR_MODE); cl_git_mkfile("./foo/bar", "Baz!"); - cl_git_fail(git_clone(&g_repo, - "https://github.com/libgit2/libgit2.git", - "./foo", NULL)); + cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL)); git_futils_rmdir_r("./foo", GIT_DIRREMOVAL_FILES_AND_DIRS); }