void test_clone_nonetwork__do_not_clean_existing_directory(void) { /* Clone should not remove the directory if it already exists, but * Should clean up entries it creates. */ p_mkdir("./foo", GIT_DIR_MODE); cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); cl_assert(git_path_is_empty_dir("./foo")); /* Try again with a bare repository. */ g_options.bare = true; cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); cl_assert(git_path_is_empty_dir("./foo")); }
void test_checkout_tree__can_continue_when_dir_in_use(void) { #ifdef GIT_WIN32 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid oid; git_object *obj = NULL; opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES; cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); cl_assert(git_path_isfile("testrepo/a/b.txt")); git_object_free(obj); cl_git_pass(p_chdir("testrepo/a")); cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/master")); cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); cl_git_pass(p_chdir("../..")); cl_assert(git_path_is_empty_dir("testrepo/a")); git_object_free(obj); #endif }
static bool path_is_okay(const char *path) { /* The path must either not exist, or be an empty directory */ if (!git_path_exists(path)) return true; if (!git_path_is_empty_dir(path)) { giterr_set(GITERR_INVALID, "'%s' exists and is not an empty directory", path); return false; } return true; }
int git_clone( git_repository **out, const char *url, const char *local_path, const git_clone_options *_options) { int retcode = GIT_ERROR; git_repository *repo = NULL; git_remote *origin; git_clone_options options = GIT_CLONE_OPTIONS_INIT; int remove_directory_on_failure = 0; assert(out && url && local_path); if (_options) memcpy(&options, _options, sizeof(git_clone_options)); GITERR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { giterr_set(GITERR_INVALID, "'%s' exists and is not an empty directory", local_path); 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, options.bare)) < 0) return retcode; if ((retcode = create_and_configure_origin(&origin, repo, url, &options)) < 0) goto cleanup; retcode = git_clone_into(repo, origin, &options.checkout_opts, options.checkout_branch); git_remote_free(origin); if (retcode < 0) goto cleanup; *out = repo; return 0; cleanup: git_repository_free(repo); if (remove_directory_on_failure) git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); else git_futils_cleanupdir_r(local_path); return retcode; }
int git_clone( git_repository **out, const char *url, const char *local_path, const git_clone_options *_options) { int error = 0; git_repository *repo = NULL; git_remote *origin; git_clone_options options = GIT_CLONE_OPTIONS_INIT; uint32_t rmdir_flags = GIT_RMDIR_REMOVE_FILES; git_repository_create_cb repository_cb; assert(out && url && local_path); if (_options) memcpy(&options, _options, sizeof(git_clone_options)); GITERR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { giterr_set(GITERR_INVALID, "'%s' exists and is not an empty directory", local_path); return GIT_EEXISTS; } /* Only remove the root directory on failure if we create it */ if (git_path_exists(local_path)) rmdir_flags |= GIT_RMDIR_SKIP_ROOT; if (options.repository_cb) repository_cb = options.repository_cb; else repository_cb = default_repository_create; if ((error = repository_cb(&repo, local_path, options.bare, options.repository_cb_payload)) < 0) return error; if (!(error = create_and_configure_origin(&origin, repo, url, &options))) { int clone_local = git_clone__should_clone_local(url, options.local); int link = options.local != GIT_CLONE_LOCAL_NO_LINKS; if (clone_local == 1) error = clone_local_into( repo, origin, &options.checkout_opts, options.checkout_branch, link, options.signature); else if (clone_local == 0) error = clone_into( repo, origin, &options.checkout_opts, options.checkout_branch, options.signature); else error = -1; git_remote_free(origin); } if (error != 0) { git_error_state last_error = {0}; giterr_capture(&last_error, error); git_repository_free(repo); repo = NULL; (void)git_futils_rmdir_r(local_path, NULL, rmdir_flags); giterr_restore(&last_error); } *out = repo; return error; }