summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJameson Miller <jamill@microsoft.com>2013-03-01 11:07:53 -0500
committerJameson Miller <jamill@microsoft.com>2013-03-01 14:56:09 -0500
commit926acbcf8ed80a69ab82f3d14e90dabeca9af07d (patch)
tree550f4e6314038033bbbced49b5934e1706405278 /src
parentcc427158d4fafa26e3d2d9f69da51a1a8d8a92d4 (diff)
downloadlibgit2-926acbcf8ed80a69ab82f3d14e90dabeca9af07d.tar.gz
Clone should not delete directories it did not create
Diffstat (limited to 'src')
-rw-r--r--src/clone.c11
-rw-r--r--src/fileops.c35
-rw-r--r--src/fileops.h10
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.