diff options
author | nulltoken <emeric.fermas@gmail.com> | 2012-05-01 15:57:45 +0400 |
---|---|---|
committer | nulltoken <emeric.fermas@gmail.com> | 2012-06-07 23:27:30 +0400 |
commit | edebceffef1d661d073b9961d13042007325832d (patch) | |
tree | 9884986782471e303f5b1f5386192b751cf57feb /src/reset.c | |
parent | 4c977a61e598f2230e9902aa80cfea8e89d94f88 (diff) |
Add git_reset()
Currently supports Soft and Mixed modes.
Diffstat (limited to 'src/reset.c')
-rw-r--r-- | src/reset.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/reset.c b/src/reset.c new file mode 100644 index 000000000..14f7a236a --- /dev/null +++ b/src/reset.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "common.h" +#include "commit.h" +#include "tag.h" +#include "git2/reset.h" + +#define ERROR_MSG "Cannot perform reset" + +static int reset_error_invalid(const char *msg) +{ + giterr_set(GITERR_INVALID, "%s - %s", ERROR_MSG, msg); + return -1; +} + +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; +} |