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; }
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; }
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); }
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; }
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; }
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); }
/** * 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); }
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)); }
/** * 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; }