int git_checkout_tree( git_repository *repo, git_object *treeish, git_checkout_opts *opts, git_indexer_stats *stats) { git_index *index = NULL; git_tree *tree = NULL; int error; assert(repo && treeish); if (git_object_peel((git_object **)&tree, treeish, GIT_OBJ_TREE) < 0) { giterr_set(GITERR_INVALID, "Provided treeish cannot be peeled into a tree."); return GIT_ERROR; } if ((error = git_repository_index(&index, repo)) < 0) goto cleanup; if ((error = git_index_read_tree(index, tree, NULL)) < 0) goto cleanup; if ((error = git_index_write(index)) < 0) goto cleanup; error = git_checkout_index(repo, opts, stats); cleanup: git_index_free(index); git_tree_free(tree); return error; }
void test_diff_index__not_in_head_conflicted(void) { const char *a_commit = "26a125ee1bf"; /* the current HEAD */ git_index_entry theirs = {{0}}; git_index *index; git_diff *diff; const git_diff_delta *delta; git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_index_read_tree(index, a)); theirs.path = "file_not_in_head"; theirs.mode = GIT_FILEMODE_BLOB; git_oid_fromstr(&theirs.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); cl_git_pass(git_index_conflict_add(index, NULL, NULL, &theirs)); cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, index, NULL)); cl_assert_equal_i(git_diff_num_deltas(diff), 1); delta = git_diff_get_delta(diff, 0); cl_assert_equal_i(delta->status, GIT_DELTA_CONFLICTED); git_diff_free(diff); git_index_free(index); git_tree_free(a); }
void test_index_racy__read_tree_clears_uptodate_bit(void) { git_index *index; git_tree *tree; const git_index_entry *entry; git_oid id; setup_uptodate_files(); cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_index_write_tree_to(&id, index, g_repo)); cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); cl_git_pass(git_index_read_tree(index, tree)); /* ensure that no files are uptodate */ cl_assert((entry = git_index_get_bypath(index, "A", 0))); cl_assert_equal_i(0, (entry->flags_extended & GIT_INDEX_ENTRY_UPTODATE)); cl_assert((entry = git_index_get_bypath(index, "B", 0))); cl_assert_equal_i(0, (entry->flags_extended & GIT_INDEX_ENTRY_UPTODATE)); cl_assert((entry = git_index_get_bypath(index, "C", 0))); cl_assert_equal_i(0, (entry->flags_extended & GIT_INDEX_ENTRY_UPTODATE)); git_tree_free(tree); git_index_free(index); }
void test_diff_index__to_index(void) { const char *a_commit = "26a125ee1bf"; /* the current HEAD */ git_tree *old_tree; git_index *old_index; git_index *new_index; git_diff *diff; diff_expects exp; cl_git_pass(git_index_new(&old_index)); old_tree = resolve_commit_oid_to_tree(g_repo, a_commit); cl_git_pass(git_index_read_tree(old_index, old_tree)); cl_git_pass(git_repository_index(&new_index, g_repo)); cl_git_pass(git_diff_index_to_index(&diff, g_repo, old_index, new_index, NULL)); memset(&exp, 0, sizeof(diff_expects)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(8, exp.files); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_CONFLICTED]); git_diff_free(diff); git_index_free(new_index); git_index_free(old_index); git_tree_free(old_tree); }
void test_object_tree_update__remove_all_entries(void) { git_oid tree_index_id, tree_updater_id, base_id; git_tree *base_tree; git_index *idx; const char *path1 = "subdir/subdir2/README"; const char *path2 = "subdir/subdir2/new.txt"; git_tree_update updates[] = { { GIT_TREE_UPDATE_REMOVE, {{0}}, GIT_FILEMODE_BLOB /* ignored */, path1}, { GIT_TREE_UPDATE_REMOVE, {{0}}, GIT_FILEMODE_BLOB /* ignored */, path2}, }; cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); /* Create it with an index */ cl_git_pass(git_index_new(&idx)); cl_git_pass(git_index_read_tree(idx, base_tree)); cl_git_pass(git_index_remove(idx, path1, 0)); cl_git_pass(git_index_remove(idx, path2, 0)); cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo)); git_index_free(idx); /* Perform the same operation via the tree updater */ cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 2, updates)); cl_assert_equal_oid(&tree_index_id, &tree_updater_id); git_tree_free(base_tree); }
void test_object_tree_update__replace_blob(void) { git_oid tree_index_id, tree_updater_id, base_id; git_tree *base_tree; git_index *idx; const char *path = "README"; git_index_entry entry = { {0} }; git_tree_update updates[] = { { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, path}, }; cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); /* Create it with an index */ cl_git_pass(git_index_new(&idx)); cl_git_pass(git_index_read_tree(idx, base_tree)); entry.path = path; cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92")); entry.mode = GIT_FILEMODE_BLOB; cl_git_pass(git_index_add(idx, &entry)); cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo)); git_index_free(idx); /* Perform the same operation via the tree updater */ cl_git_pass(git_oid_fromstr(&updates[0].id, "fa49b077972391ad58037050f2a75f74e3671e92")); cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 1, updates)); cl_assert_equal_oid(&tree_index_id, &tree_updater_id); git_tree_free(base_tree); }
void assert_conflict( const char *entry_path, const char *new_content, const char *parent_sha, const char *commit_sha) { git_index *index; git_object *hack_tree; git_reference *branch, *head; git_buf file_path = GIT_BUF_INIT; cl_git_pass(git_repository_index(&index, g_repo)); /* Create a branch pointing at the parent */ cl_git_pass(git_revparse_single(&g_object, g_repo, parent_sha)); cl_git_pass(git_branch_create(&branch, g_repo, "potential_conflict", (git_commit *)g_object, 0)); /* Make HEAD point to this branch */ cl_git_pass(git_reference_symbolic_create( &head, g_repo, "HEAD", git_reference_name(branch), 1, NULL)); git_reference_free(head); git_reference_free(branch); /* Checkout the parent */ g_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); /* Hack-ishy workaound to ensure *all* the index entries * match the content of the tree */ cl_git_pass(git_object_peel(&hack_tree, g_object, GIT_OBJ_TREE)); cl_git_pass(git_index_read_tree(index, (git_tree *)hack_tree)); git_object_free(hack_tree); git_object_free(g_object); g_object = NULL; /* Create a conflicting file */ cl_git_pass(git_buf_joinpath(&file_path, "./testrepo", entry_path)); cl_git_mkfile(git_buf_cstr(&file_path), new_content); git_buf_free(&file_path); /* Trying to checkout the original commit */ cl_git_pass(git_revparse_single(&g_object, g_repo, commit_sha)); g_opts.checkout_strategy = GIT_CHECKOUT_SAFE; cl_assert_equal_i( GIT_ECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); /* Stage the conflicting change */ cl_git_pass(git_index_add_bypath(index, entry_path)); cl_git_pass(git_index_write(index)); git_index_free(index); cl_assert_equal_i( GIT_ECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); }
void test_object_tree_update__add_blobs(void) { git_oid tree_index_id, tree_updater_id, base_id; git_tree *base_tree; git_index *idx; git_index_entry entry = { {0} }; int i; const char *paths[] = { "some/deep/path", "some/other/path", "a/path/elsewhere", }; git_tree_update updates[] = { { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[0]}, { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[1]}, { GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[2]}, }; cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b")); entry.mode = GIT_FILEMODE_BLOB; cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92")); for (i = 0; i < 3; i++) { cl_git_pass(git_oid_fromstr(&updates[i].id, "fa49b077972391ad58037050f2a75f74e3671e92")); } for (i = 0; i < 2; i++) { int j; /* Create it with an index */ cl_git_pass(git_index_new(&idx)); base_tree = NULL; if (i == 1) { cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id)); cl_git_pass(git_index_read_tree(idx, base_tree)); } for (j = 0; j < 3; j++) { entry.path = paths[j]; cl_git_pass(git_index_add(idx, &entry)); } cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo)); git_index_free(idx); /* Perform the same operations via the tree updater */ cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 3, updates)); cl_assert_equal_oid(&tree_index_id, &tree_updater_id); } git_tree_free(base_tree); }
static void reset_index_to_treeish(git_object *treeish) { git_object *tree; git_index *index; cl_git_pass(git_object_peel(&tree, treeish, GIT_OBJ_TREE)); cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_index_read_tree(index, (git_tree *)tree)); cl_git_pass(git_index_write(index)); git_object_free(tree); git_index_free(index); }
void test_checkout_index__target_directory_from_bare(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_index *index; git_object *head = NULL; checkout_counts cts; memset(&cts, 0, sizeof(cts)); test_checkout_index__cleanup(); g_repo = cl_git_sandbox_init("testrepo.git"); cl_assert(git_repository_is_bare(g_repo)); cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_revparse_single(&head, g_repo, "HEAD^{tree}")); cl_git_pass(git_index_read_tree(index, (const git_tree *)head)); cl_git_pass(git_index_write(index)); git_index_free(index); opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING; opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; opts.notify_cb = checkout_count_callback; opts.notify_payload = &cts; /* fail to checkout a bare repo */ cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); opts.target_directory = "alternative"; cl_assert(!git_path_isdir("alternative")); cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); cl_assert_equal_i(0, cts.n_untracked); cl_assert_equal_i(0, cts.n_ignored); cl_assert_equal_i(3, cts.n_updates); /* files will have been filtered if needed, so strip CR */ check_file_contents_nocr("./alternative/README", "hey there\n"); check_file_contents_nocr("./alternative/branch_file.txt", "hi\nbye!\n"); check_file_contents_nocr("./alternative/new.txt", "my new file\n"); cl_git_pass(git_futils_rmdir_r( "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); git_object_free(head); }
static void fill_index_wth_head_entries(git_repository *repo, git_index *index) { git_oid oid; git_commit *commit; git_tree *tree; cl_git_pass(git_reference_name_to_oid(&oid, repo, "HEAD")); cl_git_pass(git_commit_lookup(&commit, repo, &oid)); cl_git_pass(git_commit_tree(&tree, commit)); cl_git_pass(git_index_read_tree(index, tree)); cl_git_pass(git_index_write(index)); git_tree_free(tree); git_commit_free(commit); }
void test_index_read_index__maintains_stat_cache(void) { git_index *new_index; git_oid index_id; git_index_entry new_entry; const git_index_entry *e; git_tree *tree; size_t i; cl_assert_equal_i(4, git_index_entrycount(_index)); /* write-tree */ cl_git_pass(git_index_write_tree(&index_id, _index)); /* read-tree, then read index */ git_tree_lookup(&tree, _repo, &index_id); cl_git_pass(git_index_new(&new_index)); cl_git_pass(git_index_read_tree(new_index, tree)); git_tree_free(tree); /* add a new entry that will not have stat data */ memset(&new_entry, 0, sizeof(git_index_entry)); new_entry.path = "Hello"; git_oid_fromstr(&new_entry.id, "0123456789012345678901234567890123456789"); new_entry.file_size = 1234; new_entry.mode = 0100644; cl_git_pass(git_index_add(new_index, &new_entry)); cl_assert_equal_i(5, git_index_entrycount(new_index)); cl_git_pass(git_index_read_index(_index, new_index)); git_index_free(new_index); cl_assert_equal_i(5, git_index_entrycount(_index)); for (i = 0; i < git_index_entrycount(_index); i++) { e = git_index_get_byindex(_index, i); if (strcmp(e->path, "Hello") == 0) { cl_assert_equal_i(0, e->ctime.seconds); cl_assert_equal_i(0, e->mtime.seconds); } else { cl_assert(0 != e->ctime.seconds); cl_assert(0 != e->mtime.seconds); } } }
ERL_NIF_TERM geef_index_read_tree(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { geef_index *index; geef_object *tree; if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index)) return enif_make_badarg(env); if (!enif_get_resource(env, argv[0], geef_object_type, (void **) &tree)) return enif_make_badarg(env); if (git_index_read_tree(index->index, (git_tree *)tree->obj) < 0) return geef_error(env); return atoms.ok; }
/* * call-seq: * index.read_tree(tree) * * Clear the current index and start the index again on top of +tree+ * * Further index operations (+add+, +update+, +remove+, etc) will * be considered changes on top of +tree+. */ static VALUE rb_git_index_readtree(VALUE self, VALUE rb_tree) { git_index *index; git_tree *tree; int error; Data_Get_Struct(self, git_index, index); Data_Get_Struct(rb_tree, git_tree, tree); if (!rb_obj_is_kind_of(rb_tree, rb_cRuggedTree)) { rb_raise(rb_eTypeError, "A Rugged::Tree instance is required"); } error = git_index_read_tree(index, tree); rugged_exception_check(error); return Qnil; }
static bool roundtrip_with_read_index(const char *tree_idstr) { git_oid tree_id, new_tree_id; git_tree *tree; git_index *tree_index; cl_git_pass(git_oid_fromstr(&tree_id, tree_idstr)); cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id)); cl_git_pass(git_index_new(&tree_index)); cl_git_pass(git_index_read_tree(tree_index, tree)); cl_git_pass(git_index_read_index(_index, tree_index)); cl_git_pass(git_index_write_tree(&new_tree_id, _index)); git_tree_free(tree); git_index_free(tree_index); return git_oid_equal(&tree_id, &new_tree_id); }
static int commit_worktree( git_oid *w_commit_oid, git_index *index, const git_signature *stasher, const char *message, git_commit *i_commit, git_commit *b_commit, git_commit *u_commit) { int error = 0; git_tree *w_tree = NULL, *i_tree = NULL; const git_commit *parents[] = { NULL, NULL, NULL }; parents[0] = b_commit; parents[1] = i_commit; parents[2] = u_commit; if ((error = git_commit_tree(&i_tree, i_commit)) < 0) goto cleanup; if ((error = git_index_read_tree(index, i_tree)) < 0) goto cleanup; if ((error = build_workdir_tree(&w_tree, index, b_commit)) < 0) goto cleanup; error = git_commit_create( w_commit_oid, git_index_owner(index), NULL, stasher, stasher, NULL, message, w_tree, u_commit ? 3 : 2, parents); cleanup: git_tree_free(i_tree); git_tree_free(w_tree); return error; }
/* Test that reading and writing a tree is a no-op */ void test_index_read_tree__read_write_involution(void) { git_repository *repo; git_index *index; git_oid tree_oid; git_tree *tree; git_oid expected; p_mkdir("read_tree", 0700); cl_git_pass(git_repository_init(&repo, "./read_tree", 0)); cl_git_pass(git_repository_index(&index, repo)); cl_assert(git_index_entrycount(index) == 0); p_mkdir("./read_tree/abc", 0700); /* Sort order: '-' < '/' < '_' */ cl_git_mkfile("./read_tree/abc-d", NULL); cl_git_mkfile("./read_tree/abc/d", NULL); cl_git_mkfile("./read_tree/abc_d", NULL); cl_git_pass(git_index_add_bypath(index, "abc-d")); cl_git_pass(git_index_add_bypath(index, "abc_d")); cl_git_pass(git_index_add_bypath(index, "abc/d")); /* write-tree */ cl_git_pass(git_index_write_tree(&expected, index)); /* read-tree */ git_tree_lookup(&tree, repo, &expected); cl_git_pass(git_index_read_tree(index, tree)); git_tree_free(tree); cl_git_pass(git_index_write_tree(&tree_oid, index)); cl_assert_equal_oid(&expected, &tree_oid); git_index_free(index); git_repository_free(repo); cl_fixture_cleanup("read_tree"); }
PyObject * Index_read_tree(Index *self, PyObject *value) { git_oid oid; git_tree *tree = NULL; int err, need_free = 0; size_t len; len = py_oid_to_git_oid(value, &oid); if (len == 0) { Tree *py_tree; if (!PyObject_TypeCheck(value, &TreeType)) { return NULL; } PyErr_Clear(); py_tree = (Tree *) value; tree = py_tree->tree; } /* * if the user passed in an id but we're not associated with a * repo, we can't do anything */ if (tree == NULL && self->repo == NULL) { PyErr_SetString(PyExc_TypeError, "id given but no associated repository"); return NULL; } else if (tree == NULL) { need_free = 1; err = git_tree_lookup_prefix(&tree, self->repo->repo, &oid, len); if (err < 0) return Error_set(err); } err = git_index_read_tree(self->index, tree); if (need_free) git_tree_free(tree); if (err < 0) return Error_set(err); Py_RETURN_NONE; }
PyObject * Index_read_tree(Index *self, PyObject *value) { git_oid oid; git_tree *tree; int err, len; len = py_str_to_git_oid(value, &oid); if (len < 0) return NULL; err = git_tree_lookup_prefix(&tree, self->repo->repo, &oid, (unsigned int)len); if (err < 0) return Error_set(err); err = git_index_read_tree(self->index, tree); if (err < 0) return Error_set(err); Py_RETURN_NONE; }
void test_diff_iterator__index_handles_icase_range(void) { git_repository *repo; git_index *index; git_tree *head; repo = cl_git_sandbox_init("testrepo"); /* reset index to match HEAD */ cl_git_pass(git_repository_head_tree(&head, repo)); cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_index_read_tree(index, head)); cl_git_pass(git_index_write(index)); git_tree_free(head); git_index_free(index); /* do some ranged iterator checks toggling case sensitivity */ check_index_range(repo, "B", "C", false, 0); check_index_range(repo, "B", "C", true, 1); check_index_range(repo, "a", "z", false, 3); check_index_range(repo, "a", "z", true, 4); }
void test_index_read_index__read_and_writes(void) { git_oid tree_id, new_tree_id; git_tree *tree; git_index *tree_index, *new_index; cl_git_pass(git_oid_fromstr(&tree_id, "ae90f12eea699729ed24555e40b9fd669da12a12")); cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id)); cl_git_pass(git_index_new(&tree_index)); cl_git_pass(git_index_read_tree(tree_index, tree)); cl_git_pass(git_index_read_index(_index, tree_index)); cl_git_pass(git_index_write(_index)); cl_git_pass(git_index_open(&new_index, git_index_path(_index))); cl_git_pass(git_index_write_tree_to(&new_tree_id, new_index, _repo)); cl_assert_equal_oid(&tree_id, &new_tree_id); git_tree_free(tree); git_index_free(tree_index); git_index_free(new_index); }
int git_reset( git_repository *repo, const git_object *target, git_reset_type reset_type) { git_otype target_type = GIT_OBJ_BAD; git_object *commit = NULL; git_index *index = NULL; git_tree *tree = NULL; int error = -1; assert(repo && target); assert(reset_type == GIT_RESET_SOFT || reset_type == GIT_RESET_MIXED); if (git_object_owner(target) != repo) return reset_error_invalid("The given target does not belong to this repository."); if (reset_type == GIT_RESET_MIXED && git_repository_is_bare(repo)) return reset_error_invalid("Mixed reset is not allowed in a bare repository."); target_type = git_object_type(target); switch (target_type) { case GIT_OBJ_TAG: if (git_tag_peel(&commit, (git_tag *)target) < 0) goto cleanup; if (git_object_type(commit) != GIT_OBJ_COMMIT) { reset_error_invalid("The given target does not resolve to a commit."); goto cleanup; } break; case GIT_OBJ_COMMIT: commit = (git_object *)target; break; default: return reset_error_invalid("Only git_tag and git_commit objects are valid targets."); } //TODO: Check for unmerged entries if (git_reference__update(repo, git_object_id(commit), GIT_HEAD_FILE) < 0) goto cleanup; if (reset_type == GIT_RESET_SOFT) { error = 0; goto cleanup; } if (git_commit_tree(&tree, (git_commit *)commit) < 0) { giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the commit tree.", ERROR_MSG); goto cleanup; } if (git_repository_index(&index, repo) < 0) { giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the index.", ERROR_MSG); goto cleanup; } if (git_index_read_tree(index, tree) < 0) { giterr_set(GITERR_INDEX, "%s - Failed to update the index.", ERROR_MSG); goto cleanup; } if (git_index_write(index) < 0) { giterr_set(GITERR_INDEX, "%s - Failed to write the index.", ERROR_MSG); goto cleanup; } error = 0; cleanup: if (target_type == GIT_OBJ_TAG) git_object_free(commit); git_index_free(index); git_tree_free(tree); return error; }
static int reset( git_repository *repo, const git_object *target, const char *to, git_reset_t reset_type, const git_checkout_options *checkout_opts) { git_object *commit = NULL; git_index *index = NULL; git_tree *tree = NULL; int error = 0; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_buf log_message = GIT_BUF_INIT; assert(repo && target); if (checkout_opts) opts = *checkout_opts; if (git_object_owner(target) != repo) { giterr_set(GITERR_OBJECT, "%s - The given target does not belong to this repository.", ERROR_MSG); return -1; } if (reset_type != GIT_RESET_SOFT && (error = git_repository__ensure_not_bare(repo, reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0) return error; if ((error = git_object_peel(&commit, target, GIT_OBJECT_COMMIT)) < 0 || (error = git_repository_index(&index, repo)) < 0 || (error = git_commit_tree(&tree, (git_commit *)commit)) < 0) goto cleanup; if (reset_type == GIT_RESET_SOFT && (git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE || git_index_has_conflicts(index))) { giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge", ERROR_MSG); error = GIT_EUNMERGED; goto cleanup; } if ((error = git_buf_printf(&log_message, "reset: moving to %s", to)) < 0) return error; if (reset_type == GIT_RESET_HARD) { /* overwrite working directory with the new tree */ opts.checkout_strategy = GIT_CHECKOUT_FORCE; if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0) goto cleanup; } /* move HEAD to the new target */ if ((error = git_reference__update_terminal(repo, GIT_HEAD_FILE, git_object_id(commit), NULL, git_buf_cstr(&log_message))) < 0) goto cleanup; if (reset_type > GIT_RESET_SOFT) { /* reset index to the target content */ if ((error = git_index_read_tree(index, tree)) < 0 || (error = git_index_write(index)) < 0) goto cleanup; if ((error = git_repository_state_cleanup(repo)) < 0) { giterr_set(GITERR_INDEX, "%s - failed to clean up merge data", ERROR_MSG); goto cleanup; } } cleanup: git_object_free(commit); git_index_free(index); git_tree_free(tree); git_buf_dispose(&log_message); return error; }
int git_reset( git_repository *repo, git_object *target, git_reset_t reset_type) { git_object *commit = NULL; git_index *index = NULL; git_tree *tree = NULL; int error = 0; git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; assert(repo && target); if (git_object_owner(target) != repo) { giterr_set(GITERR_OBJECT, "%s - The given target does not belong to this repository.", ERROR_MSG); return -1; } if (reset_type != GIT_RESET_SOFT && (error = git_repository__ensure_not_bare(repo, reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0) return error; if ((error = git_object_peel(&commit, target, GIT_OBJ_COMMIT)) < 0 || (error = git_repository_index(&index, repo)) < 0 || (error = git_commit_tree(&tree, (git_commit *)commit)) < 0) goto cleanup; if (reset_type == GIT_RESET_SOFT && (git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE || git_index_has_conflicts(index))) { giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge.", ERROR_MSG); error = GIT_EUNMERGED; goto cleanup; } /* move HEAD to the new target */ if ((error = update_head(repo, commit)) < 0) goto cleanup; if (reset_type == GIT_RESET_HARD) { /* overwrite working directory with HEAD */ opts.checkout_strategy = GIT_CHECKOUT_FORCE; if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0) goto cleanup; } if (reset_type > GIT_RESET_SOFT) { /* reset index to the target content */ if ((error = git_index_read_tree(index, tree)) < 0 || (error = git_index_write(index)) < 0) goto cleanup; if ((error = git_repository_merge_cleanup(repo)) < 0) { giterr_set(GITERR_INDEX, "%s - failed to clean up merge data", ERROR_MSG); goto cleanup; } } cleanup: git_object_free(commit); git_index_free(index); git_tree_free(tree); return error; }
void Index::readTree(Tree& tree) { Exception::git2_assert(git_index_read_tree(data(), tree.data())); }
void test_index_read_index__handles_conflicts(void) { git_oid tree_id; git_tree *tree; git_index *index, *new_index; git_index_conflict_iterator *conflict_iterator; const git_index_entry *ancestor, *ours, *theirs; cl_git_pass(git_oid_fromstr(&tree_id, "ae90f12eea699729ed24555e40b9fd669da12a12")); cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id)); cl_git_pass(git_index_new(&index)); cl_git_pass(git_index_new(&new_index)); cl_git_pass(git_index_read_tree(index, tree)); cl_git_pass(git_index_read_tree(new_index, tree)); /* put some conflicts in only the old side, these should be removed */ add_conflicts(index, "orig_side-1.txt"); add_conflicts(index, "orig_side-2.txt"); /* put some conflicts in both indexes, these should be unchanged */ add_conflicts(index, "both_sides-1.txt"); add_conflicts(new_index, "both_sides-1.txt"); add_conflicts(index, "both_sides-2.txt"); add_conflicts(new_index, "both_sides-2.txt"); /* put some conflicts in the new index, these should be added */ add_conflicts(new_index, "new_side-1.txt"); add_conflicts(new_index, "new_side-2.txt"); cl_git_pass(git_index_read_index(index, new_index)); cl_git_pass(git_index_conflict_iterator_new(&conflict_iterator, index)); cl_git_pass(git_index_conflict_next( &ancestor, &ours, &theirs, conflict_iterator)); cl_assert_equal_s("both_sides-1.txt", ancestor->path); cl_assert_equal_s("both_sides-1.txt", ours->path); cl_assert_equal_s("both_sides-1.txt", theirs->path); cl_git_pass(git_index_conflict_next( &ancestor, &ours, &theirs, conflict_iterator)); cl_assert_equal_s("both_sides-2.txt", ancestor->path); cl_assert_equal_s("both_sides-2.txt", ours->path); cl_assert_equal_s("both_sides-2.txt", theirs->path); cl_git_pass(git_index_conflict_next( &ancestor, &ours, &theirs, conflict_iterator)); cl_assert_equal_s("new_side-1.txt", ancestor->path); cl_assert_equal_s("new_side-1.txt", ours->path); cl_assert_equal_s("new_side-1.txt", theirs->path); cl_git_pass(git_index_conflict_next( &ancestor, &ours, &theirs, conflict_iterator)); cl_assert_equal_s("new_side-2.txt", ancestor->path); cl_assert_equal_s("new_side-2.txt", ours->path); cl_assert_equal_s("new_side-2.txt", theirs->path); cl_git_fail_with(GIT_ITEROVER, git_index_conflict_next( &ancestor, &ours, &theirs, conflict_iterator)); git_index_conflict_iterator_free(conflict_iterator); git_tree_free(tree); git_index_free(new_index); git_index_free(index); }