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