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