static int mne_git_get_tag_tree(git_tree **tag_tree, git_reference **tag_ref, const char *ref_name) { int err = git_reference_lookup(tag_ref, repo, ref_name); mne_check_error("git_reference_lookup()", err, __FILE__, __LINE__); const git_oid *tag_oid = git_reference_oid(*tag_ref); assert(tag_oid != NULL); git_tag *tag; err = git_tag_lookup(&tag, repo, tag_oid); const git_oid *tag_commit_oid; if (err == GIT_ENOTFOUND) { /* Not a tag, must be a commit. */ tag_commit_oid = tag_oid; } else { err = mne_git_get_tag_commit_oid(&tag_commit_oid, tag); git_tag_free(tag); if (err != GIT_OK) return err; } git_commit *tag_commit; err = git_commit_lookup(&tag_commit, repo, tag_commit_oid); mne_check_error("git_commit_lookup()", err, __FILE__, __LINE__); err = git_commit_tree(tag_tree, tag_commit); mne_check_error("git_commit_tree()", err, __FILE__, __LINE__); git_commit_free(tag_commit); return MNE_GIT_OK; }
/* Can remove a note from a commit */ void test_notes_notes__can_remove_a_note_from_commit(void) { git_oid oid, notes_commit_oid; git_note *note = NULL; git_commit *existing_notes_commit; git_reference *ref; cl_git_pass(git_oid_fromstr(&oid, "4a202b346bb0fb0db7eff3cffeb3c70babbd2045")); cl_git_pass(git_note_commit_create(¬es_commit_oid, NULL, _repo, NULL, _sig, _sig, &oid, "I decorate 4a20\n", 0)); git_commit_lookup(&existing_notes_commit, _repo, ¬es_commit_oid); cl_assert(existing_notes_commit); cl_git_pass(git_note_commit_remove(¬es_commit_oid, _repo, existing_notes_commit, _sig, _sig, &oid)); /* remove_from_commit will not update any ref, * so we must manually create the ref, that points to the commit */ cl_git_pass(git_reference_create(&ref, _repo, "refs/notes/i-can-see-dead-notes", ¬es_commit_oid, 0, NULL)); cl_git_fail(git_note_read(¬e, _repo, "refs/notes/i-can-see-dead-notes", &oid)); git_commit_free(existing_notes_commit); git_reference_free(ref); git_note_free(note); }
int git_note_create( git_oid *out, git_repository *repo, const git_signature *author, const git_signature *committer, const char *notes_ref, const git_oid *oid, const char *note, int allow_note_overwrite) { int error; char *target = NULL; git_commit *commit = NULL; git_tree *tree = NULL; target = git_oid_allocfmt(oid); GITERR_CHECK_ALLOC(target); error = retrieve_note_tree_and_commit(&tree, &commit, repo, ¬es_ref); if (error < 0 && error != GIT_ENOTFOUND) goto cleanup; error = note_write(out, repo, author, committer, notes_ref, note, tree, target, &commit, allow_note_overwrite); cleanup: git__free(target); git_commit_free(commit); git_tree_free(tree); return error; }
void test_checkout_index__options_dir_modes(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; struct stat st; git_oid oid; git_commit *commit; mode_t um; if (!cl_is_chmod_supported()) return; cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); reset_index_to_treeish((git_object *)commit); opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING; opts.dir_mode = 0701; cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); /* umask will influence actual directory creation mode */ (void)p_umask(um = p_umask(022)); cl_git_pass(p_stat("./testrepo/a", &st)); /* Haiku & Hurd use other mode bits, so we must mask them out */ cl_assert_equal_i_fmt(st.st_mode & (S_IFMT | 07777), (GIT_FILEMODE_TREE | 0701) & ~um, "%07o"); /* File-mode test, since we're on the 'dir' branch */ cl_git_pass(p_stat("./testrepo/a/b.txt", &st)); cl_assert_equal_i_fmt(st.st_mode & (S_IFMT | 07777), GIT_FILEMODE_BLOB_EXECUTABLE & ~um, "%07o"); git_commit_free(commit); }
/* Test that we can create a note from a commit, given an existing commit */ void test_notes_notes__can_create_a_note_from_commit_given_an_existing_commit(void) { git_oid oid; git_oid notes_commit_out; git_commit *existing_notes_commit = NULL; git_reference *ref; static struct note_create_payload can_create_a_note_from_commit_given_an_existing_commit[] = { { "1c9b1bc36730582a42d56eeee0dc58673d7ae869", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", 0 }, { "1aaf94147c21f981e0a20bf57b89137c5a6aae52", "9fd738e8f7967c078dceed8190330fc8648ee56a", 0 }, { NULL, NULL, 0 } }; cl_git_pass(git_oid_fromstr(&oid, "4a202b346bb0fb0db7eff3cffeb3c70babbd2045")); cl_git_pass(git_note_commit_create(¬es_commit_out, NULL, _repo, NULL, _sig, _sig, &oid, "I decorate 4a20\n", 0)); cl_git_pass(git_oid_fromstr(&oid, "9fd738e8f7967c078dceed8190330fc8648ee56a")); git_commit_lookup(&existing_notes_commit, _repo, ¬es_commit_out); cl_assert(existing_notes_commit); cl_git_pass(git_note_commit_create(¬es_commit_out, NULL, _repo, existing_notes_commit, _sig, _sig, &oid, "I decorate 9fd7\n", 0)); /* create_from_commit will not update any ref, * so we must manually create the ref, that points to the commit */ cl_git_pass(git_reference_create(&ref, _repo, "refs/notes/i-can-see-dead-notes", ¬es_commit_out, 0, NULL)); cl_git_pass(git_note_foreach(_repo, "refs/notes/i-can-see-dead-notes", note_list_create_cb, &can_create_a_note_from_commit_given_an_existing_commit)); assert_notes_seen(can_create_a_note_from_commit_given_an_existing_commit, 2); git_commit_free(existing_notes_commit); git_reference_free(ref); }
void test_merge_workdir_submodules__update_delete_conflict(void) { git_reference *our_ref, *their_ref; git_commit *our_commit; git_annotated_commit *their_head; git_index *index; struct merge_index_entry merge_index_entries[] = { { 0100644, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", 0, ".gitmodules" }, { 0100644, "5887a5e516c53bd58efb0f02ec6aa031b6fe9ad7", 0, "file1.txt" }, { 0100644, "4218670ab81cc219a9f94befb5c5dad90ec52648", 0, "file2.txt" }, { 0160000, "d3d806a4bef96889117fd7ebac0e3cb5ec152932", 1, "submodule"}, { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 3, "submodule" }, }; cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_DELETE_BRANCH)); cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref))); cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL)); cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH)); cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref)); cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_head, 1, NULL, NULL)); cl_git_pass(git_repository_index(&index, repo)); cl_assert(merge_test_index(index, merge_index_entries, 5)); git_index_free(index); git_annotated_commit_free(their_head); git_commit_free(our_commit); git_reference_free(their_ref); git_reference_free(our_ref); }
/* * call-seq: * branches.create(name, target, options = {}) -> branch * * Create a new branch with the given +name+, pointing to the +target+. * * +name+ needs to be a branch name, not an absolute reference path * (e.g. +development+ instead of +refs/heads/development+). * * +target+ needs to be an existing commit in the given repository. * * The following options can be passed in the +options+ Hash: * * :force :: * Overwrites the branch with the given +name+, if it already exists, * instead of raising an exception. * * If a branch with the given +name+ already exists and +:force+ is not +true+, * an exception will be raised. * * Returns a Rugged::Branch for the newly created branch. */ static VALUE rb_git_branch_collection_create(int argc, VALUE *argv, VALUE self) { VALUE rb_repo = rugged_owner(self), rb_name, rb_target, rb_options; git_repository *repo; git_reference *branch; git_commit *target; int error, force = 0; rb_scan_args(argc, argv, "20:", &rb_name, &rb_target, &rb_options); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Check_Type(rb_name, T_STRING); Check_Type(rb_target, T_STRING); if (!NIL_P(rb_options)) { force = RTEST(rb_hash_aref(rb_options, CSTR2SYM("force"))); } target = (git_commit *)rugged_object_get(repo, rb_target, GIT_OBJ_COMMIT); error = git_branch_create(&branch, repo, StringValueCStr(rb_name), target, force); git_commit_free(target); rugged_exception_check(error); return rugged_branch_new(rb_repo, branch); }
void test_merge_workdir_submodules__automerge(void) { git_reference *our_ref, *their_ref; git_commit *our_commit; git_annotated_commit *their_head; git_index *index; struct merge_index_entry merge_index_entries[] = { { 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" }, { 0100644, "950a663a6a7b2609eed1ed1ba9f41eb1a3192a9f", 0, "file1.txt" }, { 0100644, "343e660b9cb4bee5f407c2e33fcb9df24d9407a4", 0, "file2.txt" }, { 0160000, "d3d806a4bef96889117fd7ebac0e3cb5ec152932", 1, "submodule" }, { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 2, "submodule" }, { 0160000, "ae39c77c70cb6bad18bb471912460c4e1ba0f586", 3, "submodule" }, }; cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH)); cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref))); cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL)); cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER_BRANCH)); cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref)); cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_head, 1, NULL, NULL)); cl_git_pass(git_repository_index(&index, repo)); cl_assert(merge_test_index(index, merge_index_entries, 6)); git_index_free(index); git_annotated_commit_free(their_head); git_commit_free(our_commit); git_reference_free(their_ref); git_reference_free(our_ref); }
void test_merge_workdir_submodules__take_changed(void) { git_reference *our_ref, *their_ref; git_commit *our_commit; git_annotated_commit *their_head; git_index *index; struct merge_index_entry merge_index_entries[] = { { 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" }, { 0100644, "b438ff23300b2e0f80b84a6f30140dfa91e71423", 0, "file1.txt" }, { 0100644, "f27fbafdfa6693f8f7a5128506fe3e338dbfcad2", 0, "file2.txt" }, { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 0, "submodule" }, }; cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH)); cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref))); cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL)); cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER2_BRANCH)); cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref)); cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_head, 1, NULL, NULL)); cl_git_pass(git_repository_index(&index, repo)); cl_assert(merge_test_index(index, merge_index_entries, 4)); git_index_free(index); git_annotated_commit_free(their_head); git_commit_free(our_commit); git_reference_free(their_ref); git_reference_free(our_ref); }
void test_object_tag_read__parse(void) { // read and parse a tag from the repository git_tag *tag1, *tag2; git_commit *commit; git_oid id1, id2, id_commit; git_oid_fromstr(&id1, tag1_id); git_oid_fromstr(&id2, tag2_id); git_oid_fromstr(&id_commit, tagged_commit); cl_git_pass(git_tag_lookup(&tag1, g_repo, &id1)); cl_assert_equal_s(git_tag_name(tag1), "test"); cl_assert(git_tag_type(tag1) == GIT_OBJ_TAG); cl_git_pass(git_tag_target((git_object **)&tag2, tag1)); cl_assert(tag2 != NULL); cl_assert(git_oid_cmp(&id2, git_tag_id(tag2)) == 0); cl_git_pass(git_tag_target((git_object **)&commit, tag2)); cl_assert(commit != NULL); cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); git_tag_free(tag1); git_tag_free(tag2); git_commit_free(commit); }
void test_commit_commit__create_unexisting_update_ref(void) { git_oid oid; git_tree *tree; git_commit *commit; git_signature *s; git_reference *ref; git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); git_oid_fromstr(&oid, "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); cl_git_pass(git_tree_lookup(&tree, _repo, &oid)); cl_git_pass(git_signature_now(&s, "alice", "*****@*****.**")); cl_git_fail(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar")); cl_git_pass(git_commit_create(&oid, _repo, "refs/heads/foo/bar", s, s, NULL, "some msg", tree, 1, (const git_commit **) &commit)); /* fail because the parent isn't the tip of the branch anymore */ cl_git_fail(git_commit_create(&oid, _repo, "refs/heads/foo/bar", s, s, NULL, "some msg", tree, 1, (const git_commit **) &commit)); cl_git_pass(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar")); cl_assert(!git_oid_cmp(&oid, git_reference_target(ref))); git_tree_free(tree); git_commit_free(commit); git_signature_free(s); git_reference_free(ref); }
void test_object_tag_read__parse_without_tagger(void) { // read and parse a tag without a tagger field git_repository *bad_tag_repo; git_tag *bad_tag; git_commit *commit; git_oid id, id_commit; // TODO: This is a little messy cl_git_pass(git_repository_open(&bad_tag_repo, cl_fixture("bad_tag.git"))); git_oid_fromstr(&id, bad_tag_id); git_oid_fromstr(&id_commit, badly_tagged_commit); cl_git_pass(git_tag_lookup(&bad_tag, bad_tag_repo, &id)); cl_assert(bad_tag != NULL); cl_assert_equal_s(git_tag_name(bad_tag), "e90810b"); cl_assert(git_oid_cmp(&id, git_tag_id(bad_tag)) == 0); cl_assert(bad_tag->tagger == NULL); cl_git_pass(git_tag_target((git_object **)&commit, bad_tag)); cl_assert(commit != NULL); cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); git_tag_free(bad_tag); git_commit_free(commit); git_repository_free(bad_tag_repo); }
/* * Note: this test was flaky prior to fixing #4101 -- run it several * times to get a failure. The issues is that whether the fast * (stat-only) codepath is used inside stash's diff operation depends * on whether files are "racily clean", and there doesn't seem to be * an easy way to force the exact required state. */ void test_stash_save__untracked_regression(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; const char *paths[] = {"what", "where", "how", "why"}; git_reference *head; git_commit *head_commit; git_buf untracked_dir; const char* workdir = git_repository_workdir(repo); git_buf_init(&untracked_dir, 0); git_buf_printf(&untracked_dir, "%sz", workdir); cl_assert(!p_mkdir(untracked_dir.ptr, 0777)); cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)); opts.checkout_strategy = GIT_CHECKOUT_FORCE; opts.paths.strings = (char **)paths; opts.paths.count = 4; cl_git_pass(git_checkout_tree(repo, (git_object*)head_commit, &opts)); cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); assert_commit_message_contains("refs/stash", "WIP on master"); git_reference_free(head); git_commit_free(head_commit); git_buf_dispose(&untracked_dir); }
int git_commit_nth_gen_ancestor( git_commit **ancestor, const git_commit *commit, unsigned int n) { git_commit *current, *parent; int error; assert(ancestor && commit); current = (git_commit *)commit; if (n == 0) return git_commit_lookup( ancestor, commit->object.repo, git_object_id((const git_object *)commit)); while (n--) { error = git_commit_parent(&parent, (git_commit *)current, 0); if (current != commit) git_commit_free(current); if (error < 0) return error; current = parent; } *ancestor = parent; return 0; }
void test_checkout_index__options_dir_modes(void) { #ifndef GIT_WIN32 git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; struct stat st; git_oid oid; git_commit *commit; cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); reset_index_to_treeish((git_object *)commit); opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; opts.dir_mode = 0701; cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); cl_git_pass(p_stat("./testrepo/a", &st)); cl_assert_equal_i(st.st_mode & 0777, 0701); /* File-mode test, since we're on the 'dir' branch */ cl_git_pass(p_stat("./testrepo/a/b.txt", &st)); cl_assert_equal_i(st.st_mode & 0777, 0755); git_commit_free(commit); #endif }
void test_checkout_index__options_dir_modes(void) { #ifndef GIT_WIN32 git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; struct stat st; git_oid oid; git_commit *commit; mode_t um; cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); reset_index_to_treeish((git_object *)commit); opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; opts.dir_mode = 0701; cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); /* umask will influence actual directory creation mode */ (void)p_umask(um = p_umask(022)); cl_git_pass(p_stat("./testrepo/a", &st)); cl_assert_equal_i_fmt(st.st_mode, (GIT_FILEMODE_TREE | 0701) & ~um, "%07o"); /* File-mode test, since we're on the 'dir' branch */ cl_git_pass(p_stat("./testrepo/a/b.txt", &st)); cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_BLOB_EXECUTABLE, "%07o"); git_commit_free(commit); #endif }
int git_reference__update_for_commit( git_repository *repo, git_reference *ref, const char *ref_name, const git_oid *id, const git_signature *committer, const char *operation) { git_reference *ref_new = NULL; git_commit *commit = NULL; git_buf reflog_msg = GIT_BUF_INIT; int error; if ((error = git_commit_lookup(&commit, repo, id)) < 0 || (error = git_buf_printf(&reflog_msg, "%s%s: %s", operation ? operation : "commit", git_commit_parentcount(commit) == 0 ? " (initial)" : "", git_commit_summary(commit))) < 0) goto done; if (ref) error = git_reference_set_target( &ref_new, ref, id, committer, git_buf_cstr(&reflog_msg)); else error = git_reference__update_terminal( repo, ref_name, id, committer, git_buf_cstr(&reflog_msg)); done: git_reference_free(ref_new); git_buf_free(&reflog_msg); git_commit_free(commit); return error; }
static int create_branch( git_reference **branch, git_repository *repo, const git_oid *target, const char *name, const char *log_message) { git_commit *head_obj = NULL; git_reference *branch_ref = NULL; git_buf refname = GIT_BUF_INIT; int error; /* Find the target commit */ if ((error = git_commit_lookup(&head_obj, repo, target)) < 0) return error; /* Create the new branch */ if ((error = git_buf_printf(&refname, GIT_REFS_HEADS_DIR "%s", name)) < 0) return error; error = git_reference_create(&branch_ref, repo, git_buf_cstr(&refname), target, 0, log_message); git_buf_free(&refname); git_commit_free(head_obj); if (!error) *branch = branch_ref; else git_reference_free(branch_ref); return error; }
void test_merge_workdir_simple__binary(void) { git_oid our_oid, their_oid, our_file_oid; git_commit *our_commit; git_merge_head *their_head; const git_index_entry *binary_entry; struct merge_index_entry merge_index_entries[] = { { 0100644, "1c51d885170f57a0c4e8c69ff6363d91a5b51f85", 1, "binary" }, { 0100644, "23ed141a6ae1e798b2f721afedbe947c119111ba", 2, "binary" }, { 0100644, "836b8b82b26cab22eaaed8820877c76d6c8bca19", 3, "binary" }, }; cl_git_pass(git_oid_fromstr(&our_oid, "cc338e4710c9b257106b8d16d82f86458d5beaf1")); cl_git_pass(git_oid_fromstr(&their_oid, "ad01aebfdf2ac13145efafe3f9fcf798882f1730")); cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid)); cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL)); cl_git_pass(git_merge_head_from_id(&their_head, repo, &their_oid)); cl_git_pass(git_merge(repo, (const git_merge_head **)&their_head, 1, NULL, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 3)); cl_git_pass(git_index_add_bypath(repo_index, "binary")); cl_assert((binary_entry = git_index_get_bypath(repo_index, "binary", 0)) != NULL); cl_git_pass(git_oid_fromstr(&our_file_oid, "23ed141a6ae1e798b2f721afedbe947c119111ba")); cl_assert(git_oid_cmp(&binary_entry->id, &our_file_oid) == 0); git_merge_head_free(their_head); git_commit_free(our_commit); }
int git_rebase_abort(git_rebase *rebase) { git_reference *orig_head_ref = NULL; git_commit *orig_head_commit = NULL; int error; assert(rebase); if (rebase->inmemory) return 0; error = rebase->head_detached ? git_reference_create(&orig_head_ref, rebase->repo, GIT_HEAD_FILE, &rebase->orig_head_id, 1, "rebase: aborting") : git_reference_symbolic_create( &orig_head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1, "rebase: aborting"); if (error < 0) goto done; if ((error = git_commit_lookup( &orig_head_commit, rebase->repo, &rebase->orig_head_id)) < 0 || (error = git_reset(rebase->repo, (git_object *)orig_head_commit, GIT_RESET_HARD, &rebase->options.checkout_options)) < 0) goto done; error = rebase_cleanup(rebase); done: git_commit_free(orig_head_commit); git_reference_free(orig_head_ref); return error; }
int git_commit_nth_gen_ancestor( git_commit **ancestor, const git_commit *commit, unsigned int n) { git_commit *current, *parent = NULL; int error; assert(ancestor && commit); if (git_commit_dup(¤t, (git_commit *)commit) < 0) return -1; if (n == 0) { *ancestor = current; return 0; } while (n--) { error = git_commit_parent(&parent, current, 0); git_commit_free(current); if (error < 0) return error; current = parent; } *ancestor = parent; return 0; }
static int create_branch( git_reference **branch, git_repository *repo, const git_oid *target, const char *name, const git_signature *signature, const char *log_message) { git_commit *head_obj = NULL; git_reference *branch_ref = NULL; int error; /* Find the target commit */ if ((error = git_commit_lookup(&head_obj, repo, target)) < 0) return error; /* Create the new branch */ error = git_branch_create(&branch_ref, repo, name, head_obj, 0, signature, log_message); git_commit_free(head_obj); if (!error) *branch = branch_ref; else git_reference_free(branch_ref); return error; }
void test_diff_format_email__invalid_no(void) { git_oid oid; git_commit *commit = NULL; git_diff *diff = NULL; git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; git_buf buf = GIT_BUF_INIT; git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92"); cl_git_pass(git_commit_lookup(&commit, repo, &oid)); opts.id = git_commit_id(commit); opts.author = git_commit_author(commit); opts.summary = git_commit_summary(commit); opts.patch_no = 2; opts.total_patches = 1; cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); cl_git_fail(git_diff_format_email(&buf, diff, &opts)); cl_git_fail(git_diff_commit_as_email(&buf, repo, commit, 2, 1, 0, NULL)); cl_git_fail(git_diff_commit_as_email(&buf, repo, commit, 0, 0, 0, NULL)); git_diff_free(diff); git_commit_free(commit); git_buf_free(&buf); }
static void assert_email_match( const char *expected, const char *oidstr, git_diff_format_email_options *opts) { git_oid oid; git_commit *commit = NULL; git_diff *diff = NULL; git_buf buf = GIT_BUF_INIT; git_oid_fromstr(&oid, oidstr); cl_git_pass(git_commit_lookup(&commit, repo, &oid)); opts->id = git_commit_id(commit); opts->author = git_commit_author(commit); if (!opts->summary) opts->summary = git_commit_summary(commit); cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); cl_git_pass(git_diff_format_email(&buf, diff, opts)); cl_assert_equal_s(expected, git_buf_cstr(&buf)); git_buf_clear(&buf); cl_git_pass(git_diff_commit_as_email( &buf, repo, commit, 1, 1, opts->flags, NULL)); cl_assert_equal_s(expected, git_buf_cstr(&buf)); git_diff_free(diff); git_commit_free(commit); git_buf_free(&buf); }
/* git reset --hard 72333f47d4e83616630ff3b0ffe4c0faebcc3c45 * git revert --no-commit d1d403d22cbe24592d725f442835cf46fe60c8ac */ void test_revert_workdir__again_after_automerge(void) { git_commit *head, *commit; git_tree *reverted_tree; git_oid head_oid, revert_oid, reverted_tree_oid, reverted_commit_oid; git_signature *signature; struct merge_index_entry merge_index_entries[] = { { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 0, "file1.txt" }, { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" }, { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" }, { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" }, }; struct merge_index_entry second_revert_entries[] = { { 0100644, "3a3ef367eaf3fe79effbfb0a56b269c04c2b59fe", 1, "file1.txt" }, { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 2, "file1.txt" }, { 0100644, "747726e021bc5f44b86de60e3032fd6f9f1b8383", 3, "file1.txt" }, { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" }, { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" }, { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" }, }; git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45"); cl_git_pass(git_commit_lookup(&head, repo, &head_oid)); cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL)); git_oid_fromstr(&revert_oid, "d1d403d22cbe24592d725f442835cf46fe60c8ac"); cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid)); cl_git_pass(git_revert(repo, commit, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 4)); cl_git_pass(git_index_write_tree(&reverted_tree_oid, repo_index)); cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid)); cl_git_pass(git_signature_new(&signature, "Reverter", "*****@*****.**", time(NULL), 0)); cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&head)); cl_git_pass(git_revert(repo, commit, NULL)); cl_assert(merge_test_index(repo_index, second_revert_entries, 6)); git_signature_free(signature); git_tree_free(reverted_tree); git_commit_free(commit); git_commit_free(head); }
/* * revert the same commit twice (when the first reverts cleanly): * * git reset --hard 75ec9929465623f17ff3ad68c0438ea56faba815 * git revert 97e52d5e81f541080cd6b92829fb85bc4d81d90b */ void test_revert_workdir__again_after_edit_two(void) { git_buf diff_buf = GIT_BUF_INIT; git_config *config; git_oid head_commit_oid, revert_commit_oid; git_commit *head_commit, *revert_commit; struct merge_index_entry merge_index_entries[] = { { 0100644, "a8c86221b400b836010567cc3593db6e96c1a83a", 1, "file.txt" }, { 0100644, "46ff0854663aeb2182b9838c8da68e33ac23bc1e", 2, "file.txt" }, { 0100644, "21a96a98ed84d45866e1de6e266fd3a61a4ae9dc", 3, "file.txt" }, }; cl_git_pass(git_repository_config(&config, repo)); cl_git_pass(git_config_set_bool(config, "core.autocrlf", 0)); cl_git_pass(git_oid_fromstr(&head_commit_oid, "75ec9929465623f17ff3ad68c0438ea56faba815")); cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_oid)); cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD, NULL)); cl_git_pass(git_oid_fromstr(&revert_commit_oid, "97e52d5e81f541080cd6b92829fb85bc4d81d90b")); cl_git_pass(git_commit_lookup(&revert_commit, repo, &revert_commit_oid)); cl_git_pass(git_revert(repo, revert_commit, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 3)); cl_git_pass(git_futils_readbuffer(&diff_buf, "revert/file.txt")); cl_assert_equal_s( "a\n" \ "<<<<<<< HEAD\n" \ "=======\n" \ "a\n" \ ">>>>>>> parent of 97e52d5... Revert me\n" \ "a\n" \ "a\n" \ "a\n" \ "a\n" \ "ab", diff_buf.ptr); git_commit_free(revert_commit); git_commit_free(head_commit); git_config_free(config); git_buf_free(&diff_buf); }
/* * revert the same commit twice (when the first reverts cleanly): * * git reset --hard e34ef1a * git revert 71eb9c2 */ void test_revert_workdir__again_after_edit_two(void) { git_buf diff_buf = GIT_BUF_INIT; git_config *config; git_oid head_commit_oid, revert_commit_oid; git_commit *head_commit, *revert_commit; struct merge_index_entry merge_index_entries[] = { { 0100644, "1ff0c423042b46cb1d617b81efb715defbe8054d", 0, ".gitattributes" }, { 0100644, "1bc915c5cb7185a9438de28a7b1a7dfe8c01ee7f", 0, ".gitignore" }, { 0100644, "a8c86221b400b836010567cc3593db6e96c1a83a", 1, "file.txt" }, { 0100644, "46ff0854663aeb2182b9838c8da68e33ac23bc1e", 2, "file.txt" }, { 0100644, "21a96a98ed84d45866e1de6e266fd3a61a4ae9dc", 3, "file.txt" }, }; cl_git_pass(git_repository_config(&config, repo)); cl_git_pass(git_config_set_bool(config, "core.autocrlf", 0)); cl_git_pass(git_oid_fromstr(&head_commit_oid, "e34ef1afe54eb526fd92eec66084125f340f1d65")); cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_oid)); cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD, NULL, NULL, NULL)); cl_git_pass(git_oid_fromstr(&revert_commit_oid, "71eb9c2b53dbbf3c45fb28b27c850db4b7fb8011")); cl_git_pass(git_commit_lookup(&revert_commit, repo, &revert_commit_oid)); cl_git_pass(git_revert(repo, revert_commit, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 5)); cl_git_pass(git_futils_readbuffer(&diff_buf, "revert/file.txt")); cl_assert(strcmp(diff_buf.ptr, "a\n" \ "<<<<<<< HEAD\n" \ "=======\n" \ "a\n" \ ">>>>>>> parent of 71eb9c2... revert me\n" \ "a\n" \ "a\n" \ "a\n" \ "a\n" \ "ab\n") == 0); git_commit_free(revert_commit); git_commit_free(head_commit); git_config_free(config); git_buf_free(&diff_buf); }
static void test_copy_note( const git_rebase_options *opts, bool should_exist) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_annotated_commit *branch_head, *upstream_head; git_commit *branch_commit; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid note_id, commit_id; git_note *note = NULL; 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_reference_peel((git_object **)&branch_commit, branch_ref, GIT_OBJ_COMMIT)); /* Add a note to a commit */ cl_git_pass(git_note_create(¬e_id, repo, "refs/notes/test", git_commit_author(branch_commit), git_commit_committer(branch_commit), git_commit_id(branch_commit), "This is a commit note.", 0)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, opts)); 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_pass(git_rebase_finish(rebase, signature, opts)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); if (should_exist) { cl_git_pass(git_note_read(¬e, repo, "refs/notes/test", &commit_id)); cl_assert_equal_s("This is a commit note.", git_note_message(note)); } else { cl_git_fail(error = git_note_read(¬e, repo, "refs/notes/test", &commit_id)); cl_assert_equal_i(GIT_ENOTFOUND, error); } git_note_free(note); git_commit_free(branch_commit); git_annotated_commit_free(branch_head); git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); }
void test_rebase_merge__commit(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_oid commit_id, tree_id, parent_id; git_signature *author; git_commit *commit; git_reflog *reflog; const git_reflog_entry *reflog_entry; cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); 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)); cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); git_oid_fromstr(&parent_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); cl_assert_equal_i(1, git_commit_parentcount(commit)); cl_assert_equal_oid(&parent_id, git_commit_parent_id(commit, 0)); git_oid_fromstr(&tree_id, "4461379789c777d2a6c1f2ee0e9d6c86731b9992"); cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit)); cl_assert_equal_s(NULL, git_commit_message_encoding(commit)); cl_assert_equal_s("Modification 1 to beef\n", git_commit_message(commit)); cl_git_pass(git_signature_new(&author, "Edward Thomson", "*****@*****.**", 1405621769, 0-(4*60))); cl_assert(git_signature__equal(author, git_commit_author(commit))); cl_assert(git_signature__equal(signature, git_commit_committer(commit))); /* 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(&parent_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: Modification 1 to beef", git_reflog_entry_message(reflog_entry)); git_reflog_free(reflog); git_signature_free(author); git_commit_free(commit); git_annotated_commit_free(branch_head); git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); }
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; }