]> git.proxmox.com Git - libgit2.git/blame - src/reset.c
Add BD on ca-certificates
[libgit2.git] / src / reset.c
CommitLineData
edebceff 1/*
359fc2d2 2 * Copyright (C) the libgit2 contributors. All rights reserved.
edebceff 3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8#include "common.h"
eae0bfdc 9
edebceff 10#include "commit.h"
11#include "tag.h"
632d8b23 12#include "merge.h"
a0c34c94 13#include "diff.h"
62d38a1d 14#include "annotated_commit.h"
edebceff 15#include "git2/reset.h"
ee8bb8ba 16#include "git2/checkout.h"
632d8b23 17#include "git2/merge.h"
d00d5464 18#include "git2/refs.h"
edebceff 19
20#define ERROR_MSG "Cannot perform reset"
21
a0c34c94 22int git_reset_default(
23 git_repository *repo,
eae0bfdc
PP
24 const git_object *target,
25 const git_strarray* pathspecs)
a0c34c94 26{
27 git_object *commit = NULL;
28 git_tree *tree = NULL;
3ff1d123 29 git_diff *diff = NULL;
a0c34c94 30 git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
10672e3e 31 size_t i, max_i;
a0c34c94 32 git_index_entry entry;
33 int error;
34 git_index *index = NULL;
35
1fed6b07 36 assert(pathspecs != NULL && pathspecs->count > 0);
a0c34c94 37
38 memset(&entry, 0, sizeof(git_index_entry));
39
40 if ((error = git_repository_index(&index, repo)) < 0)
41 goto cleanup;
42
43 if (target) {
44 if (git_object_owner(target) != repo) {
ac3d33df 45 git_error_set(GIT_ERROR_OBJECT,
a0c34c94 46 "%s_default - The given target does not belong to this repository.", ERROR_MSG);
47 return -1;
48 }
49
ac3d33df 50 if ((error = git_object_peel(&commit, target, GIT_OBJECT_COMMIT)) < 0 ||
a0c34c94 51 (error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
52 goto cleanup;
53 }
54
55 opts.pathspec = *pathspecs;
56 opts.flags = GIT_DIFF_REVERSE;
57
58 if ((error = git_diff_tree_to_index(
59 &diff, repo, tree, index, &opts)) < 0)
60 goto cleanup;
61
10672e3e
RB
62 for (i = 0, max_i = git_diff_num_deltas(diff); i < max_i; ++i) {
63 const git_diff_delta *delta = git_diff_get_delta(diff, i);
64
a0c34c94 65 assert(delta->status == GIT_DELTA_ADDED ||
66 delta->status == GIT_DELTA_MODIFIED ||
7c948014 67 delta->status == GIT_DELTA_CONFLICTED ||
a0c34c94 68 delta->status == GIT_DELTA_DELETED);
69
bd101a7e
RB
70 error = git_index_conflict_remove(index, delta->old_file.path);
71 if (error < 0) {
72 if (delta->status == GIT_DELTA_ADDED && error == GIT_ENOTFOUND)
ac3d33df 73 git_error_clear();
bd101a7e
RB
74 else
75 goto cleanup;
76 }
77
a0c34c94 78 if (delta->status == GIT_DELTA_DELETED) {
79 if ((error = git_index_remove(index, delta->old_file.path, 0)) < 0)
80 goto cleanup;
81 } else {
82 entry.mode = delta->new_file.mode;
9950bb4e 83 git_oid_cpy(&entry.id, &delta->new_file.id);
a0c34c94 84 entry.path = (char *)delta->new_file.path;
85
86 if ((error = git_index_add(index, &entry)) < 0)
87 goto cleanup;
88 }
89 }
90
91 error = git_index_write(index);
92
93cleanup:
94 git_object_free(commit);
95 git_tree_free(tree);
96 git_index_free(index);
3ff1d123 97 git_diff_free(diff);
a0c34c94 98
99 return error;
100}
101
62d38a1d 102static int reset(
edebceff 103 git_repository *repo,
eae0bfdc 104 const git_object *target,
62d38a1d 105 const char *to,
586be3b8 106 git_reset_t reset_type,
649834fd 107 const git_checkout_options *checkout_opts)
edebceff 108{
edebceff 109 git_object *commit = NULL;
110 git_index *index = NULL;
111 git_tree *tree = NULL;
bfe7d7de 112 int error = 0;
6affd71f 113 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
23a17803 114 git_buf log_message = GIT_BUF_INIT;
edebceff 115
116 assert(repo && target);
edebceff 117
b8add6c4
SS
118 if (checkout_opts)
119 opts = *checkout_opts;
120
9a0d5904 121 if (git_object_owner(target) != repo) {
ac3d33df 122 git_error_set(GIT_ERROR_OBJECT,
9a0d5904 123 "%s - The given target does not belong to this repository.", ERROR_MSG);
124 return -1;
125 }
edebceff 126
bfe7d7de
RB
127 if (reset_type != GIT_RESET_SOFT &&
128 (error = git_repository__ensure_not_bare(repo,
9a0d5904 129 reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0)
bfe7d7de 130 return error;
edebceff 131
ac3d33df 132 if ((error = git_object_peel(&commit, target, GIT_OBJECT_COMMIT)) < 0 ||
bfe7d7de
RB
133 (error = git_repository_index(&index, repo)) < 0 ||
134 (error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
632d8b23 135 goto cleanup;
632d8b23 136
bfe7d7de 137 if (reset_type == GIT_RESET_SOFT &&
9a0d5904 138 (git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE ||
bfe7d7de
RB
139 git_index_has_conflicts(index)))
140 {
ac3d33df 141 git_error_set(GIT_ERROR_OBJECT, "%s (soft) in the middle of a merge", ERROR_MSG);
bfe7d7de 142 error = GIT_EUNMERGED;
edebceff 143 goto cleanup;
144 }
145
62d38a1d 146 if ((error = git_buf_printf(&log_message, "reset: moving to %s", to)) < 0)
23a17803 147 return error;
586be3b8 148
bfe7d7de 149 if (reset_type == GIT_RESET_HARD) {
465c3b38 150 /* overwrite working directory with the new tree */
2461e0d2 151 opts.checkout_strategy = GIT_CHECKOUT_FORCE;
edebceff 152
bfe7d7de
RB
153 if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0)
154 goto cleanup;
632d8b23
ET
155 }
156
465c3b38
CMN
157 /* move HEAD to the new target */
158 if ((error = git_reference__update_terminal(repo, GIT_HEAD_FILE,
159 git_object_id(commit), NULL, git_buf_cstr(&log_message))) < 0)
160 goto cleanup;
161
bfe7d7de
RB
162 if (reset_type > GIT_RESET_SOFT) {
163 /* reset index to the target content */
ee8bb8ba 164
d01fe380 165 if ((error = git_index_read_tree(index, tree)) < 0 ||
bfe7d7de
RB
166 (error = git_index_write(index)) < 0)
167 goto cleanup;
c214fa1c 168
bab0b9f2 169 if ((error = git_repository_state_cleanup(repo)) < 0) {
ac3d33df 170 git_error_set(GIT_ERROR_INDEX, "%s - failed to clean up merge data", ERROR_MSG);
bfe7d7de
RB
171 goto cleanup;
172 }
173 }
edebceff 174
175cleanup:
d8057a5b 176 git_object_free(commit);
edebceff 177 git_index_free(index);
178 git_tree_free(tree);
ac3d33df 179 git_buf_dispose(&log_message);
edebceff 180
181 return error;
182}
62d38a1d
CMN
183
184int git_reset(
185 git_repository *repo,
eae0bfdc 186 const git_object *target,
62d38a1d 187 git_reset_t reset_type,
649834fd 188 const git_checkout_options *checkout_opts)
62d38a1d
CMN
189{
190 return reset(repo, target, git_oid_tostr_s(git_object_id(target)), reset_type, checkout_opts);
191}
192
193int git_reset_from_annotated(
194 git_repository *repo,
eae0bfdc 195 const git_annotated_commit *commit,
62d38a1d 196 git_reset_t reset_type,
649834fd 197 const git_checkout_options *checkout_opts)
62d38a1d 198{
d5592378 199 return reset(repo, (git_object *) commit->commit, commit->description, reset_type, checkout_opts);
62d38a1d 200}