Exemplo n.º 1
0
static int rebase_init(
	git_rebase *rebase,
	git_repository *repo,
	const git_annotated_commit *branch,
	const git_annotated_commit *upstream,
	const git_annotated_commit *onto,
	const git_rebase_options *opts)
{
	git_buf state_path = GIT_BUF_INIT;
	int error;

	if ((error = git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR)) < 0)
		return error;

	rebase->repo = repo;
	rebase->type = GIT_REBASE_TYPE_MERGE;
	rebase->state_path = git_buf_detach(&state_path);
	rebase->orig_head_name = git__strdup(branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD);
	rebase->quiet = opts->quiet;

	git_oid_cpy(&rebase->orig_head_id, git_annotated_commit_id(branch));
	git_oid_cpy(&rebase->onto_id, git_annotated_commit_id(onto));

	if (!rebase->orig_head_name || !rebase->state_path)
		return -1;

	error = rebase_init_merge(rebase, repo, branch, upstream, onto);

	git_buf_free(&state_path);

	return error;
}
Exemplo n.º 2
0
static int rebase_init_merge(
	git_rebase *rebase,
	git_repository *repo,
	const git_annotated_commit *branch,
	const git_annotated_commit *upstream,
	const git_annotated_commit *onto)
{
	git_reference *head_ref = NULL;
	git_commit *onto_commit = NULL;
	git_buf reflog = GIT_BUF_INIT;
	git_buf state_path = GIT_BUF_INIT;
	int error;

	GIT_UNUSED(upstream);

	if ((error = git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR)) < 0)
		goto done;

	rebase->state_path = git_buf_detach(&state_path);
	GITERR_CHECK_ALLOC(rebase->state_path);

	if (branch->ref_name) {
		rebase->orig_head_name = git__strdup(branch->ref_name);
		GITERR_CHECK_ALLOC(rebase->orig_head_name);
	} else {
		rebase->head_detached = 1;
	}

	rebase->onto_name = git__strdup(rebase_onto_name(onto));
	GITERR_CHECK_ALLOC(rebase->onto_name);

	rebase->quiet = rebase->options.quiet;

	git_oid_cpy(&rebase->orig_head_id, git_annotated_commit_id(branch));
	git_oid_cpy(&rebase->onto_id, git_annotated_commit_id(onto));

	if ((error = rebase_setupfiles(rebase)) < 0 ||
		(error = git_buf_printf(&reflog,
			"rebase: checkout %s", rebase_onto_name(onto))) < 0 ||
		(error = git_commit_lookup(
			&onto_commit, repo, git_annotated_commit_id(onto))) < 0 ||
		(error = git_checkout_tree(repo,
			(git_object *)onto_commit, &rebase->options.checkout_options)) < 0 ||
		(error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE,
			git_annotated_commit_id(onto), 1, reflog.ptr)) < 0)
		goto done;

done:
	git_reference_free(head_ref);
	git_commit_free(onto_commit);
	git_buf_free(&reflog);
	git_buf_free(&state_path);

	return error;
}
Exemplo n.º 3
0
void test_rebase_merge__finish(void)
{
	git_rebase *rebase;
	git_reference *branch_ref, *upstream_ref, *head_ref;
	git_annotated_commit *branch_head, *upstream_head;
	git_rebase_operation *rebase_operation;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_oid commit_id;
	git_reflog *reflog;
	const git_reflog_entry *reflog_entry;
	int error;

	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;

	cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
	cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));

	cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
	cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));

	cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));

	cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
	cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
		NULL, NULL));

	cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts));
	cl_assert_equal_i(GIT_ITEROVER, error);

	cl_git_pass(git_rebase_finish(rebase, signature, NULL));

	cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));

	cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD"));
	cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head_ref));
	cl_assert_equal_s("refs/heads/gravy", git_reference_symbolic_target(head_ref));

	/* Make sure the reflogs are updated appropriately */
	cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));
	cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
	cl_assert_equal_oid(&commit_id, git_reflog_entry_id_old(reflog_entry));
	cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
	cl_assert_equal_s("rebase finished: returning to refs/heads/gravy", git_reflog_entry_message(reflog_entry));
	git_reflog_free(reflog);

	cl_git_pass(git_reflog_read(&reflog, repo, "refs/heads/gravy"));
	cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
	cl_assert_equal_oid(git_annotated_commit_id(branch_head), git_reflog_entry_id_old(reflog_entry));
	cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
	cl_assert_equal_s("rebase finished: refs/heads/gravy onto f87d14a4a236582a0278a916340a793714256864", git_reflog_entry_message(reflog_entry));

	git_reflog_free(reflog);
	git_annotated_commit_free(branch_head);
	git_annotated_commit_free(upstream_head);
	git_reference_free(head_ref);
	git_reference_free(branch_ref);
	git_reference_free(upstream_ref);
	git_rebase_free(rebase);
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
static int rebase_init_operations(
	git_rebase *rebase,
	git_repository *repo,
	const git_annotated_commit *branch,
	const git_annotated_commit *upstream,
	const git_annotated_commit *onto)
{
	git_revwalk *revwalk = NULL;
	git_commit *commit;
	git_oid id;
	bool merge;
	git_rebase_operation *operation;
	int error;

	if (!upstream)
		upstream = onto;

	if ((error = git_revwalk_new(&revwalk, rebase->repo)) < 0 ||
		(error = git_revwalk_push(revwalk, git_annotated_commit_id(branch))) < 0 ||
		(error = git_revwalk_hide(revwalk, git_annotated_commit_id(upstream))) < 0)
		goto done;

	git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME);

	while ((error = git_revwalk_next(&id, revwalk)) == 0) {
		if ((error = git_commit_lookup(&commit, repo, &id)) < 0)
			goto done;

		merge = (git_commit_parentcount(commit) > 1);
		git_commit_free(commit);

		if (merge)
			continue;

		operation = git_array_alloc(rebase->operations);
		operation->type = GIT_REBASE_OPERATION_PICK;
		git_oid_cpy((git_oid *)&operation->id, &id);
	}

	error = 0;

done:
	git_revwalk_free(revwalk);
	return error;
}
Exemplo n.º 6
0
static void test_abort(git_annotated_commit *branch, git_annotated_commit *onto)
{
	git_rebase *rebase;
	git_reference *head_ref, *branch_ref = NULL;
	git_signature *signature;
	git_status_list *statuslist;
	git_reflog *reflog;
	const git_reflog_entry *reflog_entry;

	cl_git_pass(git_rebase_open(&rebase, repo));
	cl_git_pass(git_signature_new(&signature, "Rebaser", "*****@*****.**", 1404157834, -400));
	cl_git_pass(git_rebase_abort(rebase, signature));

	cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));

	/* Make sure the refs are updated appropriately */
	cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD"));

	if (branch->ref_name == NULL)
		cl_assert_equal_oid(git_annotated_commit_id(branch), git_reference_target(head_ref));
	else {
		cl_assert_equal_s("refs/heads/beef", git_reference_symbolic_target(head_ref));
		cl_git_pass(git_reference_lookup(&branch_ref, repo, git_reference_symbolic_target(head_ref)));
		cl_assert_equal_oid(git_annotated_commit_id(branch), git_reference_target(branch_ref));
	}

	git_status_list_new(&statuslist, repo, NULL);
	cl_assert_equal_i(0, git_status_list_entrycount(statuslist));
	git_status_list_free(statuslist);

	/* Make sure the reflogs are updated appropriately */
	cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));

	cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
	cl_assert_equal_oid(git_annotated_commit_id(onto), git_reflog_entry_id_old(reflog_entry));
	cl_assert_equal_oid(git_annotated_commit_id(branch), git_reflog_entry_id_new(reflog_entry));
	cl_assert_equal_s("rebase: aborting", git_reflog_entry_message(reflog_entry));

	git_reflog_free(reflog);
	git_reference_free(head_ref);
	git_reference_free(branch_ref);
	git_signature_free(signature);
	git_rebase_free(rebase);
}
Exemplo n.º 7
0
/**
 * ggit_annotated_commit_get_id:
 * @annotated_commit: a #GgitAnnotatedCommit.
 *
 * Gets the commit ID that the given @annotated_commit refs to.
 *
 * Returns: (transfer full): the commit ID that the given @annotated_commit refs to.
 */
GgitOId *
ggit_annotated_commit_get_id (GgitAnnotatedCommit *annotated_commit)
{
	const git_oid *oid;

	g_return_val_if_fail (annotated_commit != NULL, NULL);

	oid = git_annotated_commit_id (annotated_commit->annotated_commit);

	return _ggit_oid_wrap ((git_oid *)oid);
}
Exemplo n.º 8
0
static int rebase_init_inmemory(
	git_rebase *rebase,
	git_repository *repo,
	const git_annotated_commit *branch,
	const git_annotated_commit *upstream,
	const git_annotated_commit *onto)
{
	GIT_UNUSED(branch);
	GIT_UNUSED(upstream);

	return git_commit_lookup(
		&rebase->last_commit, repo, git_annotated_commit_id(onto));
}
Exemplo n.º 9
0
/**
 * Perform a fast-forward merge
 *
 * @param merge_result S4 class git_merge_result
 * @param merge_head The merge head to fast-forward merge
 * @param repository The repository
 * @param log_message First part of the one line long message in the reflog
 * @return 0 on success, or error code
 */
static int git2r_fast_forward_merge(
    SEXP merge_result,
    const git_annotated_commit *merge_head,
    git_repository *repository,
    const char *log_message)
{
    int err;
    const git_oid *oid;
    git_buf buf = GIT_BUF_INIT;
    git_commit *commit = NULL;
    git_tree *tree = NULL;
    git_reference *reference = NULL;
    git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;

    oid = git_annotated_commit_id(merge_head);
    err = git_commit_lookup(&commit, repository, oid);
    if (err)
        goto cleanup;

    err = git_commit_tree(&tree, commit);
    if (err)
        goto cleanup;

    opts.checkout_strategy = GIT_CHECKOUT_SAFE;
    err = git_checkout_tree(repository, (git_object*)tree, &opts);
    if (err)
        goto cleanup;

    err = git_repository_head(&reference, repository);
    if (err) {
        if (GIT_ENOTFOUND != err)
            goto cleanup;
    }

    err = git_buf_printf(&buf, "%s: Fast-forward", log_message);
    if (err)
        goto cleanup;

    if (GIT_ENOTFOUND == err) {
        err = git_reference_create(
            &reference,
            repository,
            "HEAD",
            git_commit_id(commit),
            0, /* force */
            buf.ptr);
    } else {
        git_reference *target_ref = NULL;

        err = git_reference_set_target(
            &target_ref,
            reference,
            git_commit_id(commit),
            buf.ptr);

        if (target_ref)
            git_reference_free(target_ref);
    }

    SET_SLOT(
        merge_result,
        Rf_install("fast_forward"),
        ScalarLogical(1));

    SET_SLOT(
        merge_result,
        Rf_install("conflicts"),
        ScalarLogical(0));

cleanup:
    git_buf_free(&buf);

    if (commit)
        git_commit_free(commit);

    if (reference)
        git_reference_free(reference);

    if (tree)
        git_tree_free(tree);

    return err;
}