Example #1
0
static int rebase_check_versions(const git_rebase_options *given_opts)
{
	GITERR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options");

	if (given_opts)
		GITERR_CHECK_VERSION(&given_opts->checkout_options, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options");

	return 0;
}
Example #2
0
static int add_backend_internal(
	git_odb *odb, git_odb_backend *backend,
	int priority, bool is_alternate, ino_t disk_inode)
{
	backend_internal *internal;

	assert(odb && backend);

	GITERR_CHECK_VERSION(backend, GIT_ODB_BACKEND_VERSION, "git_odb_backend");

	/* Check if the backend is already owned by another ODB */
	assert(!backend->odb || backend->odb == odb);

	internal = (backend_internal*) git__malloc(sizeof(backend_internal));
	GITERR_CHECK_ALLOC(internal);

	internal->backend = backend;
	internal->priority = priority;
	internal->is_alternate = is_alternate;
	internal->disk_inode = disk_inode;

	if (git_vector_insert(&odb->backends, internal) < 0) {
		git__free(internal);
		return -1;
	}

	git_vector_sort(&odb->backends);
	internal->backend->odb = odb;
	return 0;
}
Example #3
0
int git_rebase_init(
	git_rebase **out,
	git_repository *repo,
	const git_annotated_commit *branch,
	const git_annotated_commit *upstream,
	const git_annotated_commit *onto,
	const git_signature *signature,
	const git_rebase_options *given_opts)
{
	git_rebase *rebase = NULL;
	git_rebase_options opts;
	git_reference *head_ref = NULL;
	git_buf reflog = GIT_BUF_INIT;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
	int error;

	assert(repo && branch && (upstream || onto));

	*out = NULL;

	GITERR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options");

	if (!onto)
		onto = upstream;

	checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;

	if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 ||
		(error = git_repository__ensure_not_bare(repo, "rebase")) < 0 ||
		(error = rebase_ensure_not_in_progress(repo)) < 0 ||
		(error = rebase_ensure_not_dirty(repo)) < 0)
		return error;

	rebase = git__calloc(1, sizeof(git_rebase));
	GITERR_CHECK_ALLOC(rebase);

	if ((error = rebase_init(rebase, repo, branch, upstream, onto, &opts)) < 0 ||
		(error = rebase_setupfiles(rebase)) < 0 ||
		(error = git_buf_printf(&reflog,
			"rebase: checkout %s", rebase_onto_name(onto))) < 0 ||
		(error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE,
			git_annotated_commit_id(onto), 1, signature, reflog.ptr)) < 0 ||
		(error = git_checkout_head(repo, &checkout_opts)) < 0)
		goto done;

	*out = rebase;

done:
	if (error < 0) {
		rebase_cleanup(rebase);
		git_rebase_free(rebase);
	}

	git_reference_free(head_ref);
	git_buf_free(&reflog);
	rebase_opts_free(&opts);

	return error;
}
Example #4
0
int git_revert(
	git_repository *repo,
	git_commit *commit,
	const git_revert_options *given_opts)
{
	git_revert_options opts;
	git_reference *our_ref = NULL;
	git_commit *our_commit = NULL;
	char commit_oidstr[GIT_OID_HEXSZ + 1];
	const char *commit_msg;
	git_buf their_label = GIT_BUF_INIT;
	git_index *index = NULL;
	git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
	int error;

	assert(repo && commit);

	GITERR_CHECK_VERSION(given_opts, GIT_REVERT_OPTIONS_VERSION, "git_revert_options");

	if ((error = git_repository__ensure_not_bare(repo, "revert")) < 0)
		return error;

	git_oid_fmt(commit_oidstr, git_commit_id(commit));
	commit_oidstr[GIT_OID_HEXSZ] = '\0';

	if ((commit_msg = git_commit_summary(commit)) == NULL) {
		error = -1;
		goto on_error;
	}

	if ((error = git_buf_printf(&their_label, "parent of %.7s... %s", commit_oidstr, commit_msg)) < 0 ||
		(error = revert_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 ||
		(error = git_indexwriter_init_for_operation(&indexwriter, repo, &opts.checkout_opts.checkout_strategy)) < 0 ||
		(error = write_revert_head(repo, commit_oidstr)) < 0 ||
		(error = write_merge_msg(repo, commit_oidstr, commit_msg)) < 0 ||
		(error = git_repository_head(&our_ref, repo)) < 0 ||
		(error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 ||
		(error = git_revert_commit(&index, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 ||
		(error = git_merge__check_result(repo, index)) < 0 ||
		(error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0 ||
		(error = git_checkout_index(repo, index, &opts.checkout_opts)) < 0 ||
		(error = git_indexwriter_commit(&indexwriter)) < 0)
		goto on_error;

	goto done;

on_error:
	revert_state_cleanup(repo);

done:
	git_indexwriter_cleanup(&indexwriter);
	git_index_free(index);
	git_commit_free(our_commit);
	git_reference_free(our_ref);
	git_buf_free(&their_label);

	return error;
}
Example #5
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;
}
Example #6
0
int git_cherry_pick(
    git_repository *repo,
    git_commit *commit,
    const git_cherry_pick_options *given_opts)
{
    git_cherry_pick_options opts;
    git_reference *our_ref = NULL;
    git_commit *our_commit = NULL;
    char commit_oidstr[GIT_OID_HEXSZ + 1];
    const char *commit_msg, *commit_summary;
    git_buf their_label = GIT_BUF_INIT;
    git_index *index_new = NULL;
    int error = 0;

    assert(repo && commit);

    GITERR_CHECK_VERSION(given_opts, GIT_CHERRY_PICK_OPTIONS_VERSION, "git_cherry_pick_options");

    if ((error = git_repository__ensure_not_bare(repo, "cherry-pick")) < 0)
        return error;

    if ((commit_msg = git_commit_message(commit)) == NULL ||
            (commit_summary = git_commit_summary(commit)) == NULL) {
        error = -1;
        goto on_error;
    }

    git_oid_nfmt(commit_oidstr, sizeof(commit_oidstr), git_commit_id(commit));

    if ((error = write_merge_msg(repo, commit_msg)) < 0 ||
            (error = git_buf_printf(&their_label, "%.7s... %s", commit_oidstr, commit_summary)) < 0 ||
            (error = cherry_pick_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 ||
            (error = write_cherry_pick_head(repo, commit_oidstr)) < 0 ||
            (error = git_repository_head(&our_ref, repo)) < 0 ||
            (error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 ||
            (error = git_cherry_pick_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 ||
            (error = git_merge__check_result(repo, index_new)) < 0 ||
            (error = git_merge__append_conflicts_to_merge_msg(repo, index_new)) < 0 ||
            (error = git_checkout_index(repo, index_new, &opts.checkout_opts)) < 0)
        goto on_error;
    goto done;

on_error:
    cherry_pick_state_cleanup(repo);

done:
    git_index_free(index_new);
    git_commit_free(our_commit);
    git_reference_free(our_ref);
    git_buf_free(&their_label);

    return error;
}
Example #7
0
int git_rebase_finish(
	git_rebase *rebase,
	const git_signature *signature,
	const git_rebase_options *given_opts)
{
	git_rebase_options opts;
	git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL;
	git_commit *terminal_commit = NULL;
	git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT;
	char onto[GIT_OID_HEXSZ];
	int error;

	assert(rebase);

	GITERR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options");

	if ((error = rebase_normalize_opts(rebase->repo, &opts, given_opts)) < 0)
		goto done;

	git_oid_fmt(onto, &rebase->onto_id);

	if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s",
			rebase->orig_head_name, GIT_OID_HEXSZ, onto)) < 0 ||
		(error = git_buf_printf(&head_msg, "rebase finished: returning to %s",
			rebase->orig_head_name)) < 0 ||
		(error = git_repository_head(&terminal_ref, rebase->repo)) < 0 ||
		(error = git_reference_peel((git_object **)&terminal_commit,
			terminal_ref, GIT_OBJ_COMMIT)) < 0 ||
		(error = git_reference_create_matching(&branch_ref,
			rebase->repo, rebase->orig_head_name, git_commit_id(terminal_commit), 1,
			&rebase->orig_head_id, branch_msg.ptr)) < 0 ||
		(error = git_reference_symbolic_create(&head_ref,
			rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
			head_msg.ptr)) < 0 ||
		(error = rebase_copy_notes(rebase, signature, &opts)) < 0)
		goto done;

	error = rebase_cleanup(rebase);

done:
	git_buf_free(&head_msg);
	git_buf_free(&branch_msg);
	git_commit_free(terminal_commit);
	git_reference_free(head_ref);
	git_reference_free(branch_ref);
	git_reference_free(terminal_ref);
	rebase_opts_free(&opts);

	return error;
}
Example #8
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_clone_options normOptions;
	int remove_directory_on_failure = 0;

	assert(out && url && local_path);

	normalize_options(&normOptions, options);
	GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options");

	if (!path_is_okay(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, normOptions.bare))) {
		if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) {
			/* Failed to fetch; clean up */
			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);

		} else {
			*out = repo;
			retcode = 0;
		}
	}

	if (!retcode && should_checkout(repo, normOptions.bare, &normOptions.checkout_opts))
		retcode = git_checkout_head(*out, &normOptions.checkout_opts);

	return retcode;
}
Example #9
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;
}