refdb.c 5.1 KB
Newer Older
1 2 3 4 5 6 7
/*
 * Copyright (C) the libgit2 contributors. All rights reserved.
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

8
#include "refdb.h"
9

10 11 12
#include "git2/object.h"
#include "git2/refs.h"
#include "git2/refdb.h"
13 14
#include "git2/sys/refdb_backend.h"

15 16
#include "hash.h"
#include "refs.h"
17
#include "reflog.h"
18
#include "posix.h"
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

int git_refdb_new(git_refdb **out, git_repository *repo)
{
	git_refdb *db;

	assert(out && repo);

	db = git__calloc(1, sizeof(*db));
	GITERR_CHECK_ALLOC(db);

	db->repo = repo;

	*out = db;
	GIT_REFCOUNT_INC(db);
	return 0;
}

int git_refdb_open(git_refdb **out, git_repository *repo)
{
	git_refdb *db;
	git_refdb_backend *dir;

	assert(out && repo);

	*out = NULL;

	if (git_refdb_new(&db, repo) < 0)
		return -1;

	/* Add the default (filesystem) backend */
49
	if (git_refdb_backend_fs(&dir, repo) < 0) {
50 51 52 53 54 55 56 57 58 59 60
		git_refdb_free(db);
		return -1;
	}

	db->repo = repo;
	db->backend = dir;

	*out = db;
	return 0;
}

61
static void refdb_free_backend(git_refdb *db)
62
{
63 64
	if (db->backend)
		db->backend->free(db->backend);
65
}
66

67 68 69
int git_refdb_set_backend(git_refdb *db, git_refdb_backend *backend)
{
	refdb_free_backend(db);
70 71 72 73 74 75 76 77
	db->backend = backend;

	return 0;
}

int git_refdb_compress(git_refdb *db)
{
	assert(db);
78

79
	if (db->backend->compress)
80
		return db->backend->compress(db->backend);
81

82 83 84
	return 0;
}

Vicent Marti committed
85
void git_refdb__free(git_refdb *db)
86
{
87
	refdb_free_backend(db);
88
	git__memzero(db, sizeof(*db));
89 90 91
	git__free(db);
}

92 93 94 95 96
void git_refdb_free(git_refdb *db)
{
	if (db == NULL)
		return;

Vicent Marti committed
97
	GIT_REFCOUNT_DEC(db, git_refdb__free);
98 99
}

100 101 102 103 104 105 106 107 108
int git_refdb_exists(int *exists, git_refdb *refdb, const char *ref_name)
{
	assert(exists && refdb && refdb->backend);

	return refdb->backend->exists(exists, refdb->backend, ref_name);
}

int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
{
109 110 111
	git_reference *ref;
	int error;

112
	assert(db && db->backend && out && ref_name);
113

114 115 116 117 118 119
	error = db->backend->lookup(&ref, db->backend, ref_name);
	if (error < 0)
		return error;

	GIT_REFCOUNT_INC(db);
	ref->db = db;
120

121 122
	*out = ref;
	return 0;
123 124
}

125
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
126
{
127 128
	int error;

129
	if (!db->backend || !db->backend->iterator) {
130
		giterr_set(GITERR_REFERENCE, "this backend doesn't support iterators");
131 132 133
		return -1;
	}

134 135
	if ((error = db->backend->iterator(out, db->backend, glob)) < 0)
		return error;
136

137 138 139
	GIT_REFCOUNT_INC(db);
	(*out)->db = db;

140 141 142
	return 0;
}

143
int git_refdb_iterator_next(git_reference **out, git_reference_iterator *iter)
144
{
145
	int error;
146

147 148
	if ((error = iter->next(out, iter)) < 0)
		return error;
149

150 151
	GIT_REFCOUNT_INC(iter->db);
	(*out)->db = iter->db;
152 153 154 155

	return 0;
}

156
int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter)
157
{
158
	return iter->next_name(out, iter);
159 160 161 162
}

void git_refdb_iterator_free(git_reference_iterator *iter)
{
Vicent Marti committed
163
	GIT_REFCOUNT_DEC(iter->db, git_refdb__free);
164
	iter->free(iter);
165 166
}

167
int git_refdb_write(git_refdb *db, git_reference *ref, int force, const git_signature *who, const char *message, const git_oid *old_id, const char *old_target)
168 169
{
	assert(db && db->backend);
Vicent Marti committed
170 171 172 173

	GIT_REFCOUNT_INC(db);
	ref->db = db;

174
	return db->backend->write(db->backend, ref, force, who, message, old_id, old_target);
Vicent Marti committed
175 176 177 178 179 180 181
}

int git_refdb_rename(
	git_reference **out,
	git_refdb *db,
	const char *old_name,
	const char *new_name,
182
	int force,
183
	const git_signature *who,
184
	const char *message)
Vicent Marti committed
185 186 187 188
{
	int error;

	assert(db && db->backend);
189
	error = db->backend->rename(out, db->backend, old_name, new_name, force, who, message);
Vicent Marti committed
190 191 192 193 194 195 196 197 198
	if (error < 0)
		return error;

	if (out) {
		GIT_REFCOUNT_INC(db);
		(*out)->db = db;
	}

	return 0;
199 200
}

201
int git_refdb_delete(struct git_refdb *db, const char *ref_name, const git_oid *old_id, const char *old_target)
202 203
{
	assert(db && db->backend);
204
	return db->backend->del(db->backend, ref_name, old_id, old_target);
205
}
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

int git_refdb_reflog_read(git_reflog **out, git_refdb *db,  const char *name)
{
	int error;

	assert(db && db->backend);

	if ((error = db->backend->reflog_read(out, db->backend, name)) < 0)
		return error;

	GIT_REFCOUNT_INC(db);
	(*out)->db = db;

	return 0;
}
221

222 223 224 225 226 227 228
int git_refdb_has_log(git_refdb *db, const char *refname)
{
	assert(db && refname);

	return db->backend->has_log(db->backend, refname);
}

229 230 231 232 233 234
int git_refdb_ensure_log(git_refdb *db, const char *refname)
{
	assert(db && refname);

	return db->backend->ensure_log(db->backend, refname);
}
235

236
int git_refdb_init_backend(git_refdb_backend *backend, unsigned int version)
237
{
238 239 240
	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
		backend, version, git_refdb_backend, GIT_REFDB_BACKEND_INIT);
	return 0;
241
}
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

int git_refdb_lock(void **payload, git_refdb *db, const char *refname)
{
	assert(payload && db && refname);

	if (!db->backend->lock) {
		giterr_set(GITERR_REFERENCE, "backend does not support locking");
		return -1;
	}

	return db->backend->lock(payload, db->backend, refname);
}

int git_refdb_unlock(git_refdb *db, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message)
{
	assert(db);

	return db->backend->unlock(db->backend, payload, success, update_reflog, ref, sig, message);
}