1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
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 #ifndef INCLUDE_sys_git_refdb_backend_h__
8 #define INCLUDE_sys_git_refdb_backend_h__
9 
10 #include "git2/common.h"
11 #include "git2/types.h"
12 #include "git2/oid.h"
13 
14 /**
15  * @file git2/refdb_backend.h
16  * @brief Git custom refs backend functions
17  * @defgroup git_refdb_backend Git custom refs backend API
18  * @ingroup Git
19  * @{
20  */
21 GIT_BEGIN_DECL
22 
23 
24 /**
25  * Every backend's iterator must have a pointer to itself as the first
26  * element, so the API can talk to it. You'd define your iterator as
27  *
28  *     struct my_iterator {
29  *             git_reference_iterator parent;
30  *             ...
31  *     }
32  *
33  * and assign `iter->parent.backend` to your `git_refdb_backend`.
34  */
35 struct git_reference_iterator {
36 	git_refdb *db;
37 
38 	/**
39 	 * Return the current reference and advance the iterator.
40 	 */
41 	int GIT_CALLBACK(next)(
42 		git_reference **ref,
43 		git_reference_iterator *iter);
44 
45 	/**
46 	 * Return the name of the current reference and advance the iterator
47 	 */
48 	int GIT_CALLBACK(next_name)(
49 		const char **ref_name,
50 		git_reference_iterator *iter);
51 
52 	/**
53 	 * Free the iterator
54 	 */
55 	void GIT_CALLBACK(free)(
56 		git_reference_iterator *iter);
57 };
58 
59 /** An instance for a custom backend */
60 struct git_refdb_backend {
61 	unsigned int version; /**< The backend API version */
62 
63 	/**
64 	 * Queries the refdb backend for the existence of a reference.
65 	 *
66 	 * A refdb implementation must provide this function.
67 	 *
68 	 * @arg exists The implementation shall set this to `0` if a ref does
69 	 *             not exist, otherwise to `1`.
70 	 * @arg ref_name The reference's name that should be checked for
71 	 *               existence.
72 	 * @return `0` on success, a negative error value code.
73 	 */
74 	int GIT_CALLBACK(exists)(
75 		int *exists,
76 		git_refdb_backend *backend,
77 		const char *ref_name);
78 
79 	/**
80 	 * Queries the refdb backend for a given reference.
81 	 *
82 	 * A refdb implementation must provide this function.
83 	 *
84 	 * @arg out The implementation shall set this to the allocated
85 	 *          reference, if it could be found, otherwise to `NULL`.
86 	 * @arg ref_name The reference's name that should be checked for
87 	 *               existence.
88 	 * @return `0` on success, `GIT_ENOTFOUND` if the reference does
89 	 *         exist, otherwise a negative error code.
90 	 */
91 	int GIT_CALLBACK(lookup)(
92 		git_reference **out,
93 		git_refdb_backend *backend,
94 		const char *ref_name);
95 
96 	/**
97 	 * Allocate an iterator object for the backend.
98 	 *
99 	 * A refdb implementation must provide this function.
100 	 *
101 	 * @arg out The implementation shall set this to the allocated
102 	 *          reference iterator. A custom structure may be used with an
103 	 *          embedded `git_reference_iterator` structure. Both `next`
104 	 *          and `next_name` functions of `git_reference_iterator` need
105 	 *          to be populated.
106 	 * @arg glob A pattern to filter references by. If given, the iterator
107 	 *           shall only return references that match the glob when
108 	 *           passed to `wildmatch`.
109 	 * @return `0` on success, otherwise a negative error code.
110 	 */
111 	int GIT_CALLBACK(iterator)(
112 		git_reference_iterator **iter,
113 		struct git_refdb_backend *backend,
114 		const char *glob);
115 
116 	/**
117 	 * Writes the given reference to the refdb.
118 	 *
119 	 * A refdb implementation must provide this function.
120 	 *
121 	 * @arg ref The reference to persist. May either be a symbolic or
122 	 *          direct reference.
123 	 * @arg force Whether to write the reference if a reference with the
124 	 *            same name already exists.
125 	 * @arg who The person updating the reference. Shall be used to create
126 	 *          a reflog entry.
127 	 * @arg message The message detailing what kind of reference update is
128 	 *              performed. Shall be used to create a reflog entry.
129 	 * @arg old If not `NULL` and `force` is not set, then the
130 	 *          implementation needs to ensure that the reference is currently at
131 	 *          the given OID before writing the new value. If both `old`
132 	 *          and `old_target` are `NULL`, then the reference should not
133 	 *          exist at the point of writing.
134 	 * @arg old_target If not `NULL` and `force` is not set, then the
135 	 *                 implementation needs to ensure that the symbolic
136 	 *                 reference is currently at the given target before
137 	 *                 writing the new value. If both `old` and
138 	 *                 `old_target` are `NULL`, then the reference should
139 	 *                 not exist at the point of writing.
140 	 * @return `0` on success, otherwise a negative error code.
141 	 */
142 	int GIT_CALLBACK(write)(git_refdb_backend *backend,
143 		     const git_reference *ref, int force,
144 		     const git_signature *who, const char *message,
145 		     const git_oid *old, const char *old_target);
146 
147 	/**
148 	 * Rename a reference in the refdb.
149 	 *
150 	 * A refdb implementation must provide this function.
151 	 *
152 	 * @arg out The implementation shall set this to the newly created
153 	 *          reference or `NULL` on error.
154 	 * @arg old_name The current name of the reference that is to be renamed.
155 	 * @arg new_name The new name that the old reference shall be renamed to.
156 	 * @arg force Whether to write the reference if a reference with the
157 	 *            target name already exists.
158 	 * @arg who The person updating the reference. Shall be used to create
159 	 *          a reflog entry.
160 	 * @arg message The message detailing what kind of reference update is
161 	 *              performed. Shall be used to create a reflog entry.
162 	 * @return `0` on success, otherwise a negative error code.
163 	 */
164 	int GIT_CALLBACK(rename)(
165 		git_reference **out, git_refdb_backend *backend,
166 		const char *old_name, const char *new_name, int force,
167 		const git_signature *who, const char *message);
168 
169 	/**
170 	 * Deletes the given reference from the refdb.
171 	 *
172 	 * If it exists, its reflog should be deleted as well.
173 	 *
174 	 * A refdb implementation must provide this function.
175 	 *
176 	 * @arg ref_name The name of the reference name that shall be deleted.
177 	 * @arg old_id If not `NULL` and `force` is not set, then the
178 	 *             implementation needs to ensure that the reference is currently at
179 	 *             the given OID before writing the new value.
180 	 * @arg old_target If not `NULL` and `force` is not set, then the
181 	 *                 implementation needs to ensure that the symbolic
182 	 *                 reference is currently at the given target before
183 	 *                 writing the new value.
184 	 * @return `0` on success, otherwise a negative error code.
185 	 */
186 	int GIT_CALLBACK(del)(git_refdb_backend *backend, const char *ref_name, const git_oid *old_id, const char *old_target);
187 
188 	/**
189 	 * Suggests that the given refdb compress or optimize its references.
190 	 *
191 	 * This mechanism is implementation specific. For on-disk reference
192 	 * databases, this may pack all loose references.
193 	 *
194 	 * A refdb implementation may provide this function; if it is not
195 	 * provided, nothing will be done.
196 	 *
197 	 * @return `0` on success a negative error code otherwise
198 	 */
199 	int GIT_CALLBACK(compress)(git_refdb_backend *backend);
200 
201 	/**
202 	 * Query whether a particular reference has a log (may be empty)
203 	 *
204 	 * Shall return 1 if it has a reflog, 0 it it doesn't and negative in
205 	 * case an error occurred.
206 	 *
207 	 * A refdb implementation must provide this function.
208 	 *
209 	 * @return `0` on success, `1` if the reflog for the given reference
210 	 *         exists, a negative error code otherwise
211 	 */
212 	int GIT_CALLBACK(has_log)(git_refdb_backend *backend, const char *refname);
213 
214 	/**
215 	 * Make sure a particular reference will have a reflog which
216 	 * will be appended to on writes.
217 	 *
218 	 * A refdb implementation must provide this function.
219 	 *
220 	 * @return `0` on success, a negative error code otherwise
221 	 */
222 	int GIT_CALLBACK(ensure_log)(git_refdb_backend *backend, const char *refname);
223 
224 	/**
225 	 * Frees any resources held by the refdb (including the `git_refdb_backend`
226 	 * itself).
227 	 *
228 	 * A refdb backend implementation must provide this function.
229 	 */
230 	void GIT_CALLBACK(free)(git_refdb_backend *backend);
231 
232 	/**
233 	 * Read the reflog for the given reference name.
234 	 *
235 	 * A refdb implementation must provide this function.
236 	 *
237 	 * @return `0` on success, a negative error code otherwise
238 	 */
239 	int GIT_CALLBACK(reflog_read)(git_reflog **out, git_refdb_backend *backend, const char *name);
240 
241 	/**
242 	 * Write a reflog to disk.
243 	 *
244 	 * A refdb implementation must provide this function.
245 	 *
246 	 * @arg reflog The complete reference log for a given reference. Note
247 	 *             that this may contain entries that have already been
248 	 *             written to disk.
249 	 * @return `0` on success, a negative error code otherwise
250 	 */
251 	int GIT_CALLBACK(reflog_write)(git_refdb_backend *backend, git_reflog *reflog);
252 
253 	/**
254 	 * Rename a reflog.
255 	 *
256 	 * A refdb implementation must provide this function.
257 	 *
258 	 * @arg old_name The name of old reference whose reflog shall be renamed from.
259 	 * @arg new_name The name of new reference whose reflog shall be renamed to.
260 	 * @return `0` on success, a negative error code otherwise
261 	 */
262 	int GIT_CALLBACK(reflog_rename)(git_refdb_backend *_backend, const char *old_name, const char *new_name);
263 
264 	/**
265 	 * Remove a reflog.
266 	 *
267 	 * A refdb implementation must provide this function.
268 	 *
269 	 * @arg name The name of the reference whose reflog shall be deleted.
270 	 * @return `0` on success, a negative error code otherwise
271 	 */
272 	int GIT_CALLBACK(reflog_delete)(git_refdb_backend *backend, const char *name);
273 
274 	/**
275 	 * Lock a reference.
276 	 *
277 	 * A refdb implementation may provide this function; if it is not
278 	 * provided, the transaction API will fail to work.
279 	 *
280 	 * @arg payload_out Opaque parameter that will be passed verbosely to
281 	 *                  `unlock`.
282 	 * @arg refname Reference that shall be locked.
283 	 * @return `0` on success, a negative error code otherwise
284 	 */
285 	int GIT_CALLBACK(lock)(void **payload_out, git_refdb_backend *backend, const char *refname);
286 
287 	/**
288 	 * Unlock a reference.
289 	 *
290 	 * Only one of target or symbolic_target will be set.
291 	 * `success` will be true if the reference should be update, false if
292 	 * the lock must be discarded.
293 	 *
294 	 * A refdb implementation must provide this function if a `lock`
295 	 * implementation is provided.
296 	 *
297 	 * @arg payload The payload returned by `lock`.
298 	 * @arg success `1` if a reference should be updated, `2` if
299 	 *              a reference should be deleted, `0` if the lock must be
300 	 *              discarded.
301 	 * @arg update_reflog `1` in case the reflog should be updated, `0`
302 	 *                    otherwise.
303 	 * @arg ref The reference which should be unlocked.
304 	 * @arg who The person updating the reference. Shall be used to create
305 	 *          a reflog entry in case `update_reflog` is set.
306 	 * @arg message The message detailing what kind of reference update is
307 	 *              performed. Shall be used to create a reflog entry in
308 	 *              case `update_reflog` is set.
309 	 * @return `0` on success, a negative error code otherwise
310 	 */
311 	int GIT_CALLBACK(unlock)(git_refdb_backend *backend, void *payload, int success, int update_reflog,
312 		      const git_reference *ref, const git_signature *sig, const char *message);
313 };
314 
315 #define GIT_REFDB_BACKEND_VERSION 1
316 #define GIT_REFDB_BACKEND_INIT {GIT_REFDB_BACKEND_VERSION}
317 
318 /**
319  * Initializes a `git_refdb_backend` with default values. Equivalent to
320  * creating an instance with GIT_REFDB_BACKEND_INIT.
321  *
322  * @param backend the `git_refdb_backend` struct to initialize
323  * @param version Version of struct; pass `GIT_REFDB_BACKEND_VERSION`
324  * @return Zero on success; -1 on failure.
325  */
326 GIT_EXTERN(int) git_refdb_init_backend(
327 	git_refdb_backend *backend,
328 	unsigned int version);
329 
330 /**
331  * Constructors for default filesystem-based refdb backend
332  *
333  * Under normal usage, this is called for you when the repository is
334  * opened / created, but you can use this to explicitly construct a
335  * filesystem refdb backend for a repository.
336  *
337  * @param backend_out Output pointer to the git_refdb_backend object
338  * @param repo Git repository to access
339  * @return 0 on success, <0 error code on failure
340  */
341 GIT_EXTERN(int) git_refdb_backend_fs(
342 	git_refdb_backend **backend_out,
343 	git_repository *repo);
344 
345 /**
346  * Sets the custom backend to an existing reference DB
347  *
348  * The `git_refdb` will take ownership of the `git_refdb_backend` so you
349  * should NOT free it after calling this function.
350  *
351  * @param refdb database to add the backend to
352  * @param backend pointer to a git_refdb_backend instance
353  * @return 0 on success; error code otherwise
354  */
355 GIT_EXTERN(int) git_refdb_set_backend(
356 	git_refdb *refdb,
357 	git_refdb_backend *backend);
358 
359 GIT_END_DECL
360 
361 #endif
362