diff options
author | Jameson Miller <jamill@microsoft.com> | 2013-03-01 11:07:53 -0500 |
---|---|---|
committer | Jameson Miller <jamill@microsoft.com> | 2013-03-01 14:56:09 -0500 |
commit | 926acbcf8ed80a69ab82f3d14e90dabeca9af07d (patch) | |
tree | 550f4e6314038033bbbced49b5934e1706405278 /src | |
parent | cc427158d4fafa26e3d2d9f69da51a1a8d8a92d4 (diff) | |
download | libgit2-926acbcf8ed80a69ab82f3d14e90dabeca9af07d.tar.gz |
Clone should not delete directories it did not create
Diffstat (limited to 'src')
-rw-r--r-- | src/clone.c | 11 | ||||
-rw-r--r-- | src/fileops.c | 35 | ||||
-rw-r--r-- | src/fileops.h | 10 |
3 files changed, 54 insertions, 2 deletions
diff --git a/src/clone.c b/src/clone.c index 409a77f92..0bbccd44b 100644 --- a/src/clone.c +++ b/src/clone.c @@ -429,6 +429,7 @@ int git_clone( int retcode = GIT_ERROR; git_repository *repo = NULL; git_clone_options normOptions; + int remove_directory_on_failure = 0; assert(out && url && local_path); @@ -439,11 +440,19 @@ int git_clone( return GIT_ERROR; } + /* Only remove the directory on failure if we create it */ + remove_directory_on_failure = !git_path_exists(local_path); + if (!(retcode = git_repository_init(&repo, local_path, normOptions.bare))) { if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) { /* Failed to fetch; clean up */ git_repository_free(repo); - git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); + + if (remove_directory_on_failure) + git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); + else + git_futils_cleanupdir_r(local_path); + } else { *out = repo; retcode = 0; diff --git a/src/fileops.c b/src/fileops.c index 3531e75b8..6429e55b4 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -519,6 +519,41 @@ int git_futils_rmdir_r( return error; } +int git_futils_cleanupdir_r(const char *path) +{ + int error; + git_buf fullpath = GIT_BUF_INIT; + futils__rmdir_data data; + + if ((error = git_buf_put(&fullpath, path, strlen(path)) < 0)) + goto clean_up; + + data.base = ""; + data.baselen = 0; + data.flags = GIT_RMDIR_REMOVE_FILES; + data.error = 0; + + if (!git_path_exists(path)) { + giterr_set(GITERR_OS, "Path does not exist: %s" , path); + error = GIT_ERROR; + goto clean_up; + } + + if (!git_path_isdir(path)) { + giterr_set(GITERR_OS, "Path is not a directory: %s" , path); + error = GIT_ERROR; + goto clean_up; + } + + error = git_path_direach(&fullpath, futils__rmdir_recurs_foreach, &data); + if (error == GIT_EUSER) + error = data.error; + +clean_up: + git_buf_free(&fullpath); + return error; +} + int git_futils_find_system_file(git_buf *path, const char *filename) { #ifdef GIT_WIN32 diff --git a/src/fileops.h b/src/fileops.h index 5495b12cd..f01f22706 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -128,7 +128,7 @@ typedef enum { /** * Remove path and any files and directories beneath it. * - * @param path Path to to top level directory to process. + * @param path Path to the top level directory to process. * @param base Root for relative path. * @param flags Combination of git_futils_rmdir_flags values * @return 0 on success; -1 on error. @@ -136,6 +136,14 @@ typedef enum { extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags); /** + * Remove all files and directories beneath the specified path. + * + * @param path Path to the top level directory to process. + * @return 0 on success; -1 on error. + */ +extern int git_futils_cleanupdir_r(const char *path); + +/** * Create and open a temporary file with a `_git2_` suffix. * Writes the filename into path_out. * @return On success, an open file descriptor, else an error code < 0. |