Merge pull request #1174 from nulltoken/topic/soft_reset_with_index_conflicts Prevent soft reset when index contains conflicts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
diff --git a/.gitignore b/.gitignore
index b81a1b1..0289813 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/tests-clar/clar.suite
+/tests-clar/clar.suite.rule
/tests-clar/.clarcache
/apidocs
/trash-*.exe
diff --git a/src/reset.c b/src/reset.c
index 784094a..04b0863 100644
--- a/src/reset.c
+++ b/src/reset.c
@@ -15,12 +15,6 @@
#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;
-}
-
static int update_head(git_repository *repo, git_object *commit)
{
int error;
@@ -68,7 +62,7 @@ int git_reset(
git_object *commit = NULL;
git_index *index = NULL;
git_tree *tree = NULL;
- int error = -1;
+ int error;
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
assert(repo && target);
@@ -76,29 +70,33 @@ int git_reset(
|| reset_type == GIT_RESET_MIXED
|| reset_type == GIT_RESET_HARD);
- if (git_object_owner(target) != repo)
- return reset_error_invalid("The given target does not belong to this repository.");
+ 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
- && git_repository__ensure_not_bare(
+ && (error = git_repository__ensure_not_bare(
repo,
- reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard") < 0)
- return GIT_EBAREREPO;
+ reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0)
+ return error;
- if (git_object_peel(&commit, target, GIT_OBJ_COMMIT) < 0) {
- reset_error_invalid("The given target does not resolve to a commit");
+ if ((error = git_object_peel(&commit, target, GIT_OBJ_COMMIT)) < 0)
goto cleanup;
- }
- if (reset_type == GIT_RESET_SOFT && (git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE)) {
- giterr_set(GITERR_OBJECT, "%s (soft) while in the middle of a merge.", ERROR_MSG);
- error = GIT_EUNMERGED;
+ if ((error = git_repository_index(&index, repo)) < 0)
goto cleanup;
- }
- //TODO: Check for unmerged entries
+ 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) while in the middle of a merge.", ERROR_MSG);
+ error = GIT_EUNMERGED;
+ goto cleanup;
+ }
- if (update_head(repo, commit) < 0)
+ if ((error = update_head(repo, commit)) < 0)
goto cleanup;
if (reset_type == GIT_RESET_SOFT) {
@@ -106,28 +104,17 @@ int git_reset(
goto cleanup;
}
- if (git_commit_tree(&tree, (git_commit *)commit) < 0) {
- giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the commit tree.", ERROR_MSG);
+ if ((error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
goto cleanup;
- }
- if (git_repository_index(&index, repo) < 0) {
- giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the index.", ERROR_MSG);
+ if ((error = git_index_read_tree(index, tree)) < 0)
goto cleanup;
- }
- if (git_index_read_tree(index, tree) < 0) {
- giterr_set(GITERR_INDEX, "%s - Failed to update the index.", ERROR_MSG);
+ if ((error = git_index_write(index)) < 0)
goto cleanup;
- }
-
- if (git_index_write(index) < 0) {
- giterr_set(GITERR_INDEX, "%s - Failed to write the index.", ERROR_MSG);
- goto cleanup;
- }
if ((error = git_repository_merge_cleanup(repo)) < 0) {
- giterr_set(GITERR_INDEX, "%s - Failed to clean up merge data.", ERROR_MSG);
+ giterr_set(GITERR_REPOSITORY, "%s - Failed to clean up merge data.", ERROR_MSG);
goto cleanup;
}
@@ -138,12 +125,7 @@ int git_reset(
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
- if (git_checkout_index(repo, NULL, &opts) < 0) {
- giterr_set(GITERR_INDEX, "%s - Failed to checkout the index.", ERROR_MSG);
- goto cleanup;
- }
-
- error = 0;
+ error = git_checkout_index(repo, NULL, &opts);
cleanup:
git_object_free(commit);
diff --git a/tests-clar/reset/soft.c b/tests-clar/reset/soft.c
index 9ebd637..884697c 100644
--- a/tests-clar/reset/soft.c
+++ b/tests-clar/reset/soft.c
@@ -130,3 +130,28 @@ void test_reset_soft__fails_when_merging(void)
git_buf_free(&merge_head_path);
}
+
+void test_reset_soft__fails_when_index_contains_conflicts_independently_of_MERGE_HEAD_file_existence(void)
+{
+ git_index *index;
+ git_reference *head;
+ git_buf merge_head_path = GIT_BUF_INIT;
+
+ cl_git_sandbox_cleanup();
+
+ repo = cl_git_sandbox_init("mergedrepo");
+
+ cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
+ cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path)));
+ git_buf_free(&merge_head_path);
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_assert_equal_i(true, git_index_has_conflicts(index));
+ git_index_free(index);
+
+ cl_git_pass(git_repository_head(&head, repo));
+ cl_git_pass(git_reference_peel(&target, head, GIT_OBJ_COMMIT));
+ git_reference_free(head);
+
+ cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT));
+}