]>
Commit | Line | Data |
---|---|---|
27df4275 | 1 | /* |
359fc2d2 | 2 | * Copyright (C) the libgit2 contributors. All rights reserved. |
27df4275 | 3 | * |
bb742ede VM |
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. | |
27df4275 MS |
6 | */ |
7 | ||
8 | #include "reflog.h" | |
9 | #include "repository.h" | |
10 | #include "filebuf.h" | |
11 | #include "signature.h" | |
b976f3c2 | 12 | #include "refdb.h" |
27df4275 | 13 | |
b976f3c2 | 14 | #include <git2/sys/refdb_backend.h> |
27df4275 | 15 | |
b976f3c2 | 16 | git_reflog_entry *git_reflog_entry__alloc(void) |
27df4275 | 17 | { |
b976f3c2 | 18 | return git__calloc(1, sizeof(git_reflog_entry)); |
bd72425d | 19 | } |
27df4275 | 20 | |
b976f3c2 | 21 | void git_reflog_entry__free(git_reflog_entry *entry) |
40c75652 | 22 | { |
23 | git_signature_free(entry->committer); | |
97769280 | 24 | |
40c75652 | 25 | git__free(entry->msg); |
26 | git__free(entry); | |
27df4275 MS |
27 | } |
28 | ||
27df4275 MS |
29 | void git_reflog_free(git_reflog *reflog) |
30 | { | |
10c06114 | 31 | size_t i; |
27df4275 MS |
32 | git_reflog_entry *entry; |
33 | ||
d2aa6de7 | 34 | if (reflog == NULL) |
35 | return; | |
36 | ||
b976f3c2 CMN |
37 | if (reflog->db) |
38 | GIT_REFCOUNT_DEC(reflog->db, git_refdb__free); | |
39 | ||
27df4275 MS |
40 | for (i=0; i < reflog->entries.length; i++) { |
41 | entry = git_vector_get(&reflog->entries, i); | |
42 | ||
b976f3c2 | 43 | git_reflog_entry__free(entry); |
27df4275 MS |
44 | } |
45 | ||
46 | git_vector_free(&reflog->entries); | |
3286c408 VM |
47 | git__free(reflog->ref_name); |
48 | git__free(reflog); | |
27df4275 MS |
49 | } |
50 | ||
b976f3c2 | 51 | int git_reflog_read(git_reflog **reflog, git_repository *repo, const char *name) |
bd72425d | 52 | { |
b976f3c2 CMN |
53 | git_refdb *refdb; |
54 | int error; | |
bd72425d | 55 | |
b976f3c2 | 56 | assert(reflog && repo && name); |
27e3c583 | 57 | |
b976f3c2 | 58 | if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) |
27e3c583 | 59 | return error; |
c3be5c5a | 60 | |
b976f3c2 | 61 | return git_refdb_reflog_read(reflog, refdb, name); |
27df4275 MS |
62 | } |
63 | ||
bd72425d | 64 | int git_reflog_write(git_reflog *reflog) |
65 | { | |
b976f3c2 | 66 | git_refdb *db; |
bd72425d | 67 | |
b976f3c2 | 68 | assert(reflog && reflog->db); |
bd72425d | 69 | |
b976f3c2 CMN |
70 | db = reflog->db; |
71 | return db->backend->reflog_write(db->backend, reflog); | |
bd72425d | 72 | } |
73 | ||
0174794a | 74 | int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_signature *committer, const char *msg) |
27df4275 | 75 | { |
0174794a CMN |
76 | git_reflog_entry *entry; |
77 | const git_reflog_entry *previous; | |
78 | const char *newline; | |
62dd6d16 | 79 | |
0174794a | 80 | assert(reflog && new_oid && committer); |
40c75652 | 81 | |
0174794a CMN |
82 | entry = git__calloc(1, sizeof(git_reflog_entry)); |
83 | GITERR_CHECK_ALLOC(entry); | |
84 | ||
29be3a6d | 85 | if ((git_signature_dup(&entry->committer, committer)) < 0) |
0174794a | 86 | goto cleanup; |
40c75652 | 87 | |
0174794a CMN |
88 | if (msg != NULL) { |
89 | if ((entry->msg = git__strdup(msg)) == NULL) | |
90 | goto cleanup; | |
91 | ||
92 | newline = strchr(msg, '\n'); | |
93 | ||
94 | if (newline) { | |
95 | if (newline[1] != '\0') { | |
96 | giterr_set(GITERR_INVALID, "Reflog message cannot contain newline"); | |
97 | goto cleanup; | |
98 | } | |
99 | ||
100 | entry->msg[newline - msg] = '\0'; | |
101 | } | |
102 | } | |
103 | ||
104 | previous = git_reflog_entry_byindex(reflog, 0); | |
105 | ||
106 | if (previous == NULL) | |
107 | git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO); | |
108 | else | |
109 | git_oid_cpy(&entry->oid_old, &previous->oid_cur); | |
110 | ||
111 | git_oid_cpy(&entry->oid_cur, new_oid); | |
112 | ||
113 | if (git_vector_insert(&reflog->entries, entry) < 0) | |
114 | goto cleanup; | |
115 | ||
116 | return 0; | |
117 | ||
118 | cleanup: | |
119 | git_reflog_entry__free(entry); | |
120 | return -1; | |
27df4275 MS |
121 | } |
122 | ||
b976f3c2 | 123 | int git_reflog_rename(git_repository *repo, const char *old_name, const char *new_name) |
b7c93a66 | 124 | { |
b976f3c2 CMN |
125 | git_refdb *refdb; |
126 | int error; | |
b6bfd96f | 127 | |
b976f3c2 | 128 | if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) |
8a810441 | 129 | return -1; |
b7c93a66 | 130 | |
b976f3c2 | 131 | return refdb->backend->reflog_rename(refdb->backend, old_name, new_name); |
b7c93a66 MS |
132 | } |
133 | ||
b976f3c2 | 134 | int git_reflog_delete(git_repository *repo, const char *name) |
b7c93a66 | 135 | { |
b976f3c2 | 136 | git_refdb *refdb; |
a4c291ef | 137 | int error; |
b7c93a66 | 138 | |
b976f3c2 CMN |
139 | if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) |
140 | return -1; | |
b7c93a66 | 141 | |
b976f3c2 | 142 | return refdb->backend->reflog_delete(refdb->backend, name); |
b7c93a66 MS |
143 | } |
144 | ||
2508cc66 | 145 | size_t git_reflog_entrycount(git_reflog *reflog) |
27df4275 MS |
146 | { |
147 | assert(reflog); | |
2508cc66 | 148 | return reflog->entries.length; |
27df4275 MS |
149 | } |
150 | ||
20363d58 | 151 | const git_reflog_entry * git_reflog_entry_byindex(const git_reflog *reflog, size_t idx) |
a8122b5d | 152 | { |
27df4275 | 153 | assert(reflog); |
b15df1d9 | 154 | |
a8122b5d | 155 | if (idx >= reflog->entries.length) |
b15df1d9 | 156 | return NULL; |
157 | ||
a8122b5d RB |
158 | return git_vector_get( |
159 | &reflog->entries, reflog_inverse_index(idx, reflog->entries.length)); | |
27df4275 MS |
160 | } |
161 | ||
2508cc66 | 162 | const git_oid * git_reflog_entry_id_old(const git_reflog_entry *entry) |
27df4275 MS |
163 | { |
164 | assert(entry); | |
e7be57a9 | 165 | return &entry->oid_old; |
27df4275 MS |
166 | } |
167 | ||
2508cc66 | 168 | const git_oid * git_reflog_entry_id_new(const git_reflog_entry *entry) |
27df4275 MS |
169 | { |
170 | assert(entry); | |
e7be57a9 | 171 | return &entry->oid_cur; |
27df4275 MS |
172 | } |
173 | ||
2508cc66 | 174 | const git_signature * git_reflog_entry_committer(const git_reflog_entry *entry) |
27df4275 MS |
175 | { |
176 | assert(entry); | |
177 | return entry->committer; | |
178 | } | |
179 | ||
2508cc66 | 180 | const char * git_reflog_entry_message(const git_reflog_entry *entry) |
27df4275 MS |
181 | { |
182 | assert(entry); | |
183 | return entry->msg; | |
184 | } | |
59341a5d | 185 | |
0174794a | 186 | int git_reflog_drop(git_reflog *reflog, size_t idx, int rewrite_previous_entry) |
59341a5d | 187 | { |
0174794a CMN |
188 | size_t entrycount; |
189 | git_reflog_entry *entry, *previous; | |
59341a5d | 190 | |
0174794a | 191 | entrycount = git_reflog_entrycount(reflog); |
59341a5d | 192 | |
0174794a CMN |
193 | entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); |
194 | ||
195 | if (entry == NULL) { | |
31d5dce3 | 196 | giterr_set(GITERR_REFERENCE, "No reflog entry at index %"PRIuZ, idx); |
0174794a CMN |
197 | return GIT_ENOTFOUND; |
198 | } | |
199 | ||
200 | git_reflog_entry__free(entry); | |
201 | ||
202 | if (git_vector_remove( | |
203 | &reflog->entries, reflog_inverse_index(idx, entrycount)) < 0) | |
204 | return -1; | |
205 | ||
206 | if (!rewrite_previous_entry) | |
207 | return 0; | |
208 | ||
209 | /* No need to rewrite anything when removing the most recent entry */ | |
210 | if (idx == 0) | |
211 | return 0; | |
212 | ||
213 | /* Have the latest entry just been dropped? */ | |
214 | if (entrycount == 1) | |
215 | return 0; | |
216 | ||
217 | entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1); | |
218 | ||
219 | /* If the oldest entry has just been removed... */ | |
220 | if (idx == entrycount - 1) { | |
221 | /* ...clear the oid_old member of the "new" oldest entry */ | |
222 | if (git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO) < 0) | |
223 | return -1; | |
224 | ||
225 | return 0; | |
226 | } | |
227 | ||
228 | previous = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); | |
229 | git_oid_cpy(&entry->oid_old, &previous->oid_cur); | |
230 | ||
231 | return 0; | |
59341a5d | 232 | } |