Esempio n. 1
0
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;
}
Esempio n. 2
0
static int setup_remotes_and_fetch(
		git_repository *repo,
		const char *url,
		const git_clone_options *options)
{
	int retcode = GIT_ERROR;
	git_remote *origin;

	/* Construct an origin remote */
	if (!create_and_configure_origin(&origin, repo, url, options)) {
		git_remote_set_update_fetchhead(origin, 0);

		/* Connect and download everything */
		if (!git_remote_connect(origin, GIT_DIRECTION_FETCH)) {
			if (!(retcode = git_remote_download(origin, options->fetch_progress_cb,
						options->fetch_progress_payload))) {
				/* Create "origin/foo" branches for all remote branches */
				if (!git_remote_update_tips(origin)) {
					/* Point HEAD to the requested branch */
					if (options->checkout_branch) {
						if (!update_head_to_branch(repo, options))
							retcode = 0;
					}
					/* Point HEAD to the same ref as the remote's head */
					else if (!update_head_to_remote(repo, origin)) {
						retcode = 0;
					}
				}
			}
			git_remote_disconnect(origin);
		}
		git_remote_free(origin);
	}

	return retcode;
}
Esempio n. 3
0
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;
}