Commit ec24e542 by Vicent Marti

What are the chances, really

parent 56960b83
...@@ -308,7 +308,8 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref); ...@@ -308,7 +308,8 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
*/ */
GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo); GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo);
typedef int (*git_reference_foreach_cb)(const char *refname, void *payload); typedef int (*git_reference_foreach_cb)(git_reference *reference, void *payload);
typedef int (*git_reference_foreach_name_cb)(const char *name, void *payload);
/** /**
* Perform a callback on each reference in the repository. * Perform a callback on each reference in the repository.
...@@ -328,6 +329,11 @@ GIT_EXTERN(int) git_reference_foreach( ...@@ -328,6 +329,11 @@ GIT_EXTERN(int) git_reference_foreach(
git_reference_foreach_cb callback, git_reference_foreach_cb callback,
void *payload); void *payload);
GIT_EXTERN(int) git_reference_foreach_name(
git_repository *repo,
git_reference_foreach_name_cb callback,
void *payload);
/** /**
* Free the given reference. * Free the given reference.
* *
...@@ -378,6 +384,8 @@ GIT_EXTERN(int) git_reference_iterator_glob_new( ...@@ -378,6 +384,8 @@ GIT_EXTERN(int) git_reference_iterator_glob_new(
*/ */
GIT_EXTERN(int) git_reference_next(git_reference **out, git_reference_iterator *iter); GIT_EXTERN(int) git_reference_next(git_reference **out, git_reference_iterator *iter);
GIT_EXTERN(int) git_reference_next_name(const char **out, git_reference_iterator *iter);
/** /**
* Free the iterator and its associated resources * Free the iterator and its associated resources
* *
...@@ -406,7 +414,7 @@ GIT_EXTERN(void) git_reference_iterator_free(git_reference_iterator *iter); ...@@ -406,7 +414,7 @@ GIT_EXTERN(void) git_reference_iterator_free(git_reference_iterator *iter);
GIT_EXTERN(int) git_reference_foreach_glob( GIT_EXTERN(int) git_reference_foreach_glob(
git_repository *repo, git_repository *repo,
const char *glob, const char *glob,
git_reference_foreach_cb callback, git_reference_foreach_name_cb callback,
void *payload); void *payload);
/** /**
......
...@@ -33,8 +33,27 @@ GIT_BEGIN_DECL ...@@ -33,8 +33,27 @@ GIT_BEGIN_DECL
* and assign `iter->parent.backend` to your `git_refdb_backend`. * and assign `iter->parent.backend` to your `git_refdb_backend`.
*/ */
struct git_reference_iterator { struct git_reference_iterator {
git_refdb_backend *backend; git_refdb *db;
char *glob;
/**
* Return the current reference and advance the iterator.
*/
int (*next)(
git_reference **ref,
git_reference_iterator *iter);
/**
* Return the name of the current reference and advance the iterator
*/
int (*next_name)(
const char **ref_name,
git_reference_iterator *iter);
/**
* Free the iterator
*/
void (*free)(
git_reference_iterator *iter);
}; };
/** An instance for a custom backend */ /** An instance for a custom backend */
...@@ -66,35 +85,9 @@ struct git_refdb_backend { ...@@ -66,35 +85,9 @@ struct git_refdb_backend {
*/ */
int (*iterator)( int (*iterator)(
git_reference_iterator **iter, git_reference_iterator **iter,
struct git_refdb_backend *backend);
/**
* Allocate a glob-filtering iterator object for the backend.
*
* A refdb implementation may provide this function. If it's
* not available, the glob matching will be done by the frontend.
*/
int (*iterator_glob)(
git_reference_iterator **iter,
struct git_refdb_backend *backend, struct git_refdb_backend *backend,
const char *glob); const char *glob);
/**
* Return the current value and advance the iterator.
*
* A refdb implementation must provide this function.
*/
int (*next)(
git_reference **ref,
git_reference_iterator *iter);
/**
* Free the iterator
*
* A refdb implementation must provide this function.
*/
void (*iterator_free)(
git_reference_iterator *iter);
/* /*
* Writes the given reference to the refdb. A refdb implementation * Writes the given reference to the refdb. A refdb implementation
* must provide this function. * must provide this function.
......
...@@ -241,7 +241,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) ...@@ -241,7 +241,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
} }
/* Not master. Check all the other refs. */ /* Not master. Check all the other refs. */
if (git_reference_foreach( if (git_reference_foreach_name(
repo, repo,
reference_matches_remote_head, reference_matches_remote_head,
&head_info) < 0) &head_info) < 0)
......
...@@ -114,99 +114,65 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name) ...@@ -114,99 +114,65 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
assert(db && db->backend && out && ref_name); assert(db && db->backend && out && ref_name);
if (!(error = db->backend->lookup(&ref, db->backend, ref_name))) { error = db->backend->lookup(&ref, db->backend, ref_name);
ref->db = db; if (error < 0)
*out = ref; return error;
} else {
*out = NULL; GIT_REFCOUNT_INC(db);
} ref->db = db;
return error; *out = ref;
return 0;
} }
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db) int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
{ {
if (!db->backend || !db->backend->iterator) { if (!db->backend || !db->backend->iterator) {
giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators"); giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators");
return -1; return -1;
} }
if (db->backend->iterator(out, db->backend) < 0) if (db->backend->iterator(out, db->backend, glob) < 0)
return -1; return -1;
GIT_REFCOUNT_INC(db);
(*out)->db = db;
return 0; return 0;
} }
int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob) int git_refdb_iterator_next(git_reference **out, git_reference_iterator *iter)
{ {
if (!db->backend) { int error;
giterr_set(GITERR_REFERENCE, "There are no backends loaded");
return -1;
}
if (db->backend->iterator_glob)
return db->backend->iterator_glob(out, db->backend, glob);
/* If the backend doesn't support glob-filtering themselves, we have to do it */ if ((error = iter->next(out, iter)) < 0)
if (db->backend->iterator(out, db->backend) < 0) return error;
return -1;
(*out)->glob = git__strdup(glob); GIT_REFCOUNT_INC(iter->db);
if (!(*out)->glob) { (*out)->db = iter->db;
db->backend->iterator_free(*out);
return -1;
}
return 0; return 0;
} }
int git_refdb_next(git_reference **out, git_reference_iterator *iter) int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter)
{ {
int error; return iter->next_name(out, iter);
if (!iter->glob) {
if ((error = iter->backend->next(out, iter)) < 0)
return error;
(*out)->db = iter->backend;
return 0;
}
/* If the iterator has a glob, we need to filter */
while ((error = iter->backend->next(out, iter)) == 0) {
if (!p_fnmatch(iter->glob, (*out)->name, 0)) {
(*out)->db = iter->backend;
return 0;
}
git_reference_free(*out);
}
return error;
} }
void git_refdb_iterator_free(git_reference_iterator *iter) void git_refdb_iterator_free(git_reference_iterator *iter)
{ {
git__free(iter->glob); GIT_REFCOUNT_DEC(iter->db, refdb_free);
iter->backend->iterator_free(iter); iter->free(iter);
} }
struct glob_cb_data {
const char *glob;
git_reference_foreach_cb callback;
void *payload;
};
int git_refdb_write(git_refdb *db, const git_reference *ref) int git_refdb_write(git_refdb *db, const git_reference *ref)
{ {
assert(db && db->backend); assert(db && db->backend);
return db->backend->write(db->backend, ref); return db->backend->write(db->backend, ref);
} }
int git_refdb_delete(struct git_refdb *db, const git_reference *ref) int git_refdb_delete(struct git_refdb *db, const git_reference *ref)
{ {
assert(db && db->backend); assert(db && db->backend);
return db->backend->delete(db->backend, ref); return db->backend->delete(db->backend, ref);
} }
...@@ -26,13 +26,12 @@ int git_refdb_lookup( ...@@ -26,13 +26,12 @@ int git_refdb_lookup(
git_refdb *refdb, git_refdb *refdb,
const char *ref_name); const char *ref_name);
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db); int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob);
int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob); int git_refdb_iterator_next(git_reference **out, git_reference_iterator *iter);
int git_refdb_next(git_reference **out, git_reference_iterator *iter); int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter);
void git_refdb_iterator_free(git_reference_iterator *iter); void git_refdb_iterator_free(git_reference_iterator *iter);
int git_refdb_write(git_refdb *refdb, const git_reference *ref); int git_refdb_write(git_refdb *refdb, const git_reference *ref);
int git_refdb_delete(git_refdb *refdb, const git_reference *ref); int git_refdb_delete(git_refdb *refdb, const git_reference *ref);
#endif #endif
...@@ -556,34 +556,12 @@ static int refdb_fs_backend__lookup( ...@@ -556,34 +556,12 @@ static int refdb_fs_backend__lookup(
typedef struct { typedef struct {
git_reference_iterator parent; git_reference_iterator parent;
char *glob;
git_vector loose; git_vector loose;
unsigned int loose_pos; unsigned int loose_pos;
khiter_t packed_pos; khiter_t packed_pos;
} refdb_fs_iter; } refdb_fs_iter;
static int iter_load_loose_paths(refdb_fs_iter *iter);
static int refdb_fs_backend__iterator(git_reference_iterator **out, git_refdb_backend *_backend)
{
refdb_fs_iter *iter;
refdb_fs_backend *backend;
assert(_backend);
backend = (refdb_fs_backend *)_backend;
if (packed_load(backend) < 0)
return -1;
iter = git__calloc(1, sizeof(refdb_fs_iter));
GITERR_CHECK_ALLOC(iter);
iter->parent.backend = _backend;
iter_load_loose_paths(iter);
*out = (git_reference_iterator *)iter;
return 0;
}
static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
{ {
refdb_fs_iter *iter = (refdb_fs_iter *) _iter; refdb_fs_iter *iter = (refdb_fs_iter *) _iter;
...@@ -595,14 +573,14 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) ...@@ -595,14 +573,14 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
} }
git_vector_free(&iter->loose); git_vector_free(&iter->loose);
git__free(iter->glob);
git__free(iter); git__free(iter);
} }
static int iter_load_loose_paths(refdb_fs_iter *iter) static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
{ {
refdb_fs_backend *backend = (refdb_fs_backend *) iter->parent.backend;
git_strmap *packfile = backend->refcache.packfile; git_strmap *packfile = backend->refcache.packfile;
git_buf path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
git_iterator *fsit; git_iterator *fsit;
const git_index_entry *entry = NULL; const git_index_entry *entry = NULL;
...@@ -624,7 +602,8 @@ static int iter_load_loose_paths(refdb_fs_iter *iter) ...@@ -624,7 +602,8 @@ static int iter_load_loose_paths(refdb_fs_iter *iter)
git_buf_puts(&path, entry->path); git_buf_puts(&path, entry->path);
ref_name = git_buf_cstr(&path); ref_name = git_buf_cstr(&path);
if (git__suffixcmp(ref_name, ".lock") == 0) { if (git__suffixcmp(ref_name, ".lock") == 0 ||
(iter->glob && p_fnmatch(iter->glob, ref_name, 0) != 0)) {
git_iterator_advance(NULL, fsit); git_iterator_advance(NULL, fsit);
continue; continue;
} }
...@@ -645,10 +624,11 @@ static int iter_load_loose_paths(refdb_fs_iter *iter) ...@@ -645,10 +624,11 @@ static int iter_load_loose_paths(refdb_fs_iter *iter)
return 0; return 0;
} }
static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_iter) static int refdb_fs_backend__iterator_next(
git_reference **out, git_reference_iterator *_iter)
{ {
refdb_fs_iter *iter = (refdb_fs_iter *)_iter; refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.backend; refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend;
git_strmap *packfile = backend->refcache.packfile; git_strmap *packfile = backend->refcache.packfile;
while (iter->loose_pos < iter->loose.length) { while (iter->loose_pos < iter->loose.length) {
...@@ -660,19 +640,23 @@ static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_ ...@@ -660,19 +640,23 @@ static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_
giterr_clear(); giterr_clear();
} }
if (iter->packed_pos < kh_end(packfile)) { while (iter->packed_pos < kh_end(packfile)) {
struct packref *ref = NULL; struct packref *ref = NULL;
do { while (!kh_exist(packfile, iter->packed_pos)) {
while (!kh_exist(packfile, iter->packed_pos)) {
iter->packed_pos++;
if (iter->packed_pos == kh_end(packfile))
return GIT_ITEROVER;
}
ref = kh_val(packfile, iter->packed_pos);
iter->packed_pos++; iter->packed_pos++;
} while (ref->flags & PACKREF_SHADOWED); if (iter->packed_pos == kh_end(packfile))
return GIT_ITEROVER;
}
ref = kh_val(packfile, iter->packed_pos);
iter->packed_pos++;
if (ref->flags & PACKREF_SHADOWED)
continue;
if (iter->glob && p_fnmatch(iter->glob, ref->name, 0) != 0)
continue;
*out = git_reference__alloc(ref->name, &ref->oid, &ref->peel); *out = git_reference__alloc(ref->name, &ref->oid, &ref->peel);
if (*out == NULL) if (*out == NULL)
...@@ -684,6 +668,74 @@ static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_ ...@@ -684,6 +668,74 @@ static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_
return GIT_ITEROVER; return GIT_ITEROVER;
} }
static int refdb_fs_backend__iterator_next_name(
const char **out, git_reference_iterator *_iter)
{
refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend;
git_strmap *packfile = backend->refcache.packfile;
while (iter->loose_pos < iter->loose.length) {
const char *path = git_vector_get(&iter->loose, iter->loose_pos++);
if (git_strmap_exists(packfile, path))
continue;
*out = path;
return 0;
}
while (iter->packed_pos < kh_end(packfile)) {
while (!kh_exist(packfile, iter->packed_pos)) {
iter->packed_pos++;
if (iter->packed_pos == kh_end(packfile))
return GIT_ITEROVER;
}
*out = kh_key(packfile, iter->packed_pos);
iter->packed_pos++;
if (iter->glob && p_fnmatch(iter->glob, *out, 0) != 0)
continue;
return 0;
}
return GIT_ITEROVER;
}
static int refdb_fs_backend__iterator(
git_reference_iterator **out, git_refdb_backend *_backend, const char *glob)
{
refdb_fs_iter *iter;
refdb_fs_backend *backend;
assert(_backend);
backend = (refdb_fs_backend *)_backend;
if (packed_load(backend) < 0)
return -1;
iter = git__calloc(1, sizeof(refdb_fs_iter));
GITERR_CHECK_ALLOC(iter);
if (glob != NULL)
iter->glob = git__strdup(glob);
iter->parent.next = refdb_fs_backend__iterator_next;
iter->parent.next_name = refdb_fs_backend__iterator_next_name;
iter->parent.free = refdb_fs_backend__iterator_free;
if (iter_load_loose_paths(backend, iter) < 0) {
refdb_fs_backend__iterator_free((git_reference_iterator *)iter);
return -1;
}
*out = (git_reference_iterator *)iter;
return 0;
}
static int loose_write(refdb_fs_backend *backend, const git_reference *ref) static int loose_write(refdb_fs_backend *backend, const git_reference *ref)
{ {
git_filebuf file = GIT_FILEBUF_INIT; git_filebuf file = GIT_FILEBUF_INIT;
...@@ -1118,8 +1170,6 @@ int git_refdb_backend_fs( ...@@ -1118,8 +1170,6 @@ int git_refdb_backend_fs(
backend->parent.exists = &refdb_fs_backend__exists; backend->parent.exists = &refdb_fs_backend__exists;
backend->parent.lookup = &refdb_fs_backend__lookup; backend->parent.lookup = &refdb_fs_backend__lookup;
backend->parent.iterator = &refdb_fs_backend__iterator; backend->parent.iterator = &refdb_fs_backend__iterator;
backend->parent.next = &refdb_fs_backend__next;
backend->parent.iterator_free = &refdb_fs_backend__iterator_free;
backend->parent.write = &refdb_fs_backend__write; backend->parent.write = &refdb_fs_backend__write;
backend->parent.delete = &refdb_fs_backend__delete; backend->parent.delete = &refdb_fs_backend__delete;
backend->parent.compress = &refdb_fs_backend__compress; backend->parent.compress = &refdb_fs_backend__compress;
......
...@@ -104,20 +104,20 @@ struct reference_available_t { ...@@ -104,20 +104,20 @@ struct reference_available_t {
int available; int available;
}; };
static int _reference_available_cb(const char *ref, void *data) static int _reference_available_cb(const char *refname, void *data)
{ {
struct reference_available_t *d; struct reference_available_t *d;
assert(ref && data); assert(refname && data);
d = (struct reference_available_t *)data; d = (struct reference_available_t *)data;
if (!d->old_ref || strcmp(d->old_ref, ref)) { if (!d->old_ref || strcmp(d->old_ref, refname)) {
size_t reflen = strlen(ref); size_t reflen = strlen(refname);
size_t newlen = strlen(d->new_ref); size_t newlen = strlen(d->new_ref);
size_t cmplen = reflen < newlen ? reflen : newlen; size_t cmplen = reflen < newlen ? reflen : newlen;
const char *lead = reflen < newlen ? d->new_ref : ref; const char *lead = reflen < newlen ? d->new_ref : refname;
if (!strncmp(d->new_ref, ref, cmplen) && lead[cmplen] == '/') { if (!strncmp(d->new_ref, refname, cmplen) && lead[cmplen] == '/') {
d->available = 0; d->available = 0;
return -1; return -1;
} }
...@@ -126,6 +126,9 @@ static int _reference_available_cb(const char *ref, void *data) ...@@ -126,6 +126,9 @@ static int _reference_available_cb(const char *ref, void *data)
return 0; return 0;
} }
/**
* TODO: this should be part of the FS backend
*/
static int reference_path_available( static int reference_path_available(
git_repository *repo, git_repository *repo,
const char *ref, const char *ref,
...@@ -138,8 +141,7 @@ static int reference_path_available( ...@@ -138,8 +141,7 @@ static int reference_path_available(
data.old_ref = old_ref; data.old_ref = old_ref;
data.available = 1; data.available = 1;
error = git_reference_foreach( error = git_reference_foreach_name(repo, _reference_available_cb, (void *)&data);
repo, _reference_available_cb, (void *)&data);
if (error < 0) if (error < 0)
return error; return error;
...@@ -430,6 +432,7 @@ static int reference__create( ...@@ -430,6 +432,7 @@ static int reference__create(
ref = git_reference__alloc_symbolic(name, symbolic); ref = git_reference__alloc_symbolic(name, symbolic);
} }
/* TODO: this needs to be written more explicitly */
GITERR_CHECK_ALLOC(ref); GITERR_CHECK_ALLOC(ref);
ref->db = refdb; ref->db = refdb;
...@@ -558,6 +561,7 @@ int git_reference_rename( ...@@ -558,6 +561,7 @@ int git_reference_rename(
if (result == NULL) if (result == NULL)
return -1; return -1;
/* TODO: this is bad */
result->db = ref->db; result->db = ref->db;
/* Check if we have to update HEAD. */ /* Check if we have to update HEAD. */
...@@ -623,14 +627,69 @@ int git_reference_foreach( ...@@ -623,14 +627,69 @@ int git_reference_foreach(
void *payload) void *payload)
{ {
git_reference_iterator *iter; git_reference_iterator *iter;
const char *name; git_reference *ref;
int error; int error;
if (git_reference_iterator_new(&iter, repo) < 0) if (git_reference_iterator_new(&iter, repo) < 0)
return -1; return -1;
while ((error = git_reference_next(&name, iter)) == 0) { while ((error = git_reference_next(&ref, iter)) == 0) {
if (callback(name, payload)) { if (callback(ref, payload)) {
error = GIT_EUSER;
goto out;
}
}
if (error == GIT_ITEROVER)
error = 0;
out:
git_reference_iterator_free(iter);
return error;
}
int git_reference_foreach_name(
git_repository *repo,
git_reference_foreach_name_cb callback,
void *payload)
{
git_reference_iterator *iter;
const char *refname;
int error;
if (git_reference_iterator_new(&iter, repo) < 0)
return -1;
while ((error = git_reference_next_name(&refname, iter)) == 0) {
if (callback(refname, payload)) {
error = GIT_EUSER;
goto out;
}
}
if (error == GIT_ITEROVER)
error = 0;
out:
git_reference_iterator_free(iter);
return error;
}
int git_reference_foreach_glob(
git_repository *repo,
const char *glob,
git_reference_foreach_name_cb callback,
void *payload)
{
git_reference_iterator *iter;
const char *refname;
int error;
if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
return -1;
while ((error = git_reference_next_name(&refname, iter)) == 0) {
if (callback(refname, payload)) {
error = GIT_EUSER; error = GIT_EUSER;
goto out; goto out;
} }
...@@ -651,22 +710,28 @@ int git_reference_iterator_new(git_reference_iterator **out, git_repository *rep ...@@ -651,22 +710,28 @@ int git_reference_iterator_new(git_reference_iterator **out, git_repository *rep
if (git_repository_refdb__weakptr(&refdb, repo) < 0) if (git_repository_refdb__weakptr(&refdb, repo) < 0)
return -1; return -1;
return git_refdb_iterator(out, refdb); return git_refdb_iterator(out, refdb, NULL);
} }
int git_reference_iterator_glob_new(git_reference_iterator **out, git_repository *repo, const char *glob) int git_reference_iterator_glob_new(
git_reference_iterator **out, git_repository *repo, const char *glob)
{ {
git_refdb *refdb; git_refdb *refdb;
if (git_repository_refdb__weakptr(&refdb, repo) < 0) if (git_repository_refdb__weakptr(&refdb, repo) < 0)
return -1; return -1;
return git_refdb_iterator_glob(out, refdb, glob); return git_refdb_iterator(out, refdb, glob);
} }
int git_reference_next(git_reference **out, git_reference_iterator *iter) int git_reference_next(git_reference **out, git_reference_iterator *iter)
{ {
return git_refdb_next(out, iter); return git_refdb_iterator_next(out, iter);
}
int git_reference_next_name(const char **out, git_reference_iterator *iter)
{
return git_refdb_iterator_next_name(out, iter);
} }
void git_reference_iterator_free(git_reference_iterator *iter) void git_reference_iterator_free(git_reference_iterator *iter)
...@@ -693,7 +758,7 @@ int git_reference_list( ...@@ -693,7 +758,7 @@ int git_reference_list(
if (git_vector_init(&ref_list, 8, NULL) < 0) if (git_vector_init(&ref_list, 8, NULL) < 0)
return -1; return -1;
if (git_reference_foreach( if (git_reference_foreach_name(
repo, &cb__reflist_add, (void *)&ref_list) < 0) { repo, &cb__reflist_add, (void *)&ref_list) < 0) {
git_vector_free(&ref_list); git_vector_free(&ref_list);
return -1; return -1;
...@@ -991,34 +1056,6 @@ int git_reference__update_terminal( ...@@ -991,34 +1056,6 @@ int git_reference__update_terminal(
return reference__update_terminal(repo, ref_name, oid, 0); return reference__update_terminal(repo, ref_name, oid, 0);
} }
int git_reference_foreach_glob(
git_repository *repo,
const char *glob,
git_reference_foreach_cb callback,
void *payload)
{
git_reference_iterator *iter;
const char *name;
int error;
if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
return -1;
while ((error = git_reference_next(&name, iter)) == 0) {
if (callback(name, payload)) {
error = GIT_EUSER;
goto out;
}
}
if (error == GIT_ITEROVER)
error = 0;
out:
git_reference_iterator_free(iter);
return error;
}
int git_reference_has_log( int git_reference_has_log(
git_reference *ref) git_reference *ref)
{ {
......
...@@ -1473,12 +1473,14 @@ static int at_least_one_cb(const char *refname, void *payload) ...@@ -1473,12 +1473,14 @@ static int at_least_one_cb(const char *refname, void *payload)
static int repo_contains_no_reference(git_repository *repo) static int repo_contains_no_reference(git_repository *repo)
{ {
int error = git_reference_foreach(repo, at_least_one_cb, NULL); int error = git_reference_foreach_name(repo, &at_least_one_cb, NULL);
if (error == GIT_EUSER) if (error == GIT_EUSER)
return 0; return 0;
if (!error) if (!error)
return 1; return 1;
return error; return error;
} }
......
...@@ -440,7 +440,7 @@ int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data) ...@@ -440,7 +440,7 @@ int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data)
data.cb_data = cb_data; data.cb_data = cb_data;
data.repo = repo; data.repo = repo;
return git_reference_foreach(repo, &tags_cb, &data); return git_reference_foreach_name(repo, &tags_cb, &data);
} }
typedef struct { typedef struct {
......
#include "clar_libgit2.h"
#include "buffer.h"
#include "posix.h"
#include "path.h"
#include "refs.h"
#include "testdb.h"
#define TEST_REPO_PATH "testrepo"
static git_repository *repo;
int unlink_ref(void *payload, git_buf *file)
{
GIT_UNUSED(payload);
return p_unlink(git_buf_cstr(file));
}
int empty(void *payload, git_buf *file)
{
GIT_UNUSED(payload);
GIT_UNUSED(file);
return -1;
}
int ref_file_foreach(git_repository *repo, int (* cb)(void *payload, git_buf *filename))
{
const char *repo_path;
git_buf repo_refs_dir = GIT_BUF_INIT;
int error = 0;
repo_path = git_repository_path(repo);
git_buf_joinpath(&repo_refs_dir, repo_path, "HEAD");
if (git_path_exists(git_buf_cstr(&repo_refs_dir)) &&
cb(NULL, &repo_refs_dir) < 0)
return -1;
git_buf_joinpath(&repo_refs_dir, repo_path, "refs");
git_buf_joinpath(&repo_refs_dir, git_buf_cstr(&repo_refs_dir), "heads");
if (git_path_direach(&repo_refs_dir, cb, NULL) != 0)
return -1;
git_buf_joinpath(&repo_refs_dir, repo_path, "packed-refs");
if (git_path_exists(git_buf_cstr(&repo_refs_dir)) &&
cb(NULL, &repo_refs_dir) < 0)
return -1;
git_buf_free(&repo_refs_dir);
return error;
}
void test_refdb_inmemory__initialize(void)
{
git_buf repo_refs_dir = GIT_BUF_INIT;
git_refdb *refdb;
git_refdb_backend *refdb_backend;
repo = cl_git_sandbox_init(TEST_REPO_PATH);
cl_git_pass(git_repository_refdb(&refdb, repo));
cl_git_pass(refdb_backend_test(&refdb_backend, repo));
cl_git_pass(git_refdb_set_backend(refdb, refdb_backend));
ref_file_foreach(repo, unlink_ref);
git_buf_free(&repo_refs_dir);
git_refdb_free(refdb);
}
void test_refdb_inmemory__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_refdb_inmemory__doesnt_write_ref_file(void)
{
git_reference *ref;
git_oid oid;
cl_git_pass(git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
cl_git_pass(git_reference_create(&ref, repo, GIT_REFS_HEADS_DIR "test1", &oid, 0));
ref_file_foreach(repo, empty);
git_reference_free(ref);
}
void test_refdb_inmemory__read(void)
{
git_reference *write1, *write2, *write3, *read1, *read2, *read3;
git_oid oid1, oid2, oid3;
cl_git_pass(git_oid_fromstr(&oid1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
cl_git_pass(git_reference_create(&write1, repo, GIT_REFS_HEADS_DIR "test1", &oid1, 0));
cl_git_pass(git_oid_fromstr(&oid2, "e90810b8df3e80c413d903f631643c716887138d"));
cl_git_pass(git_reference_create(&write2, repo, GIT_REFS_HEADS_DIR "test2", &oid2, 0));
cl_git_pass(git_oid_fromstr(&oid3, "763d71aadf09a7951596c9746c024e7eece7c7af"));
cl_git_pass(git_reference_create(&write3, repo, GIT_REFS_HEADS_DIR "test3", &oid3, 0));
cl_git_pass(git_reference_lookup(&read1, repo, GIT_REFS_HEADS_DIR "test1"));
cl_assert(strcmp(git_reference_name(read1), git_reference_name(write1)) == 0);
cl_assert(git_oid_cmp(git_reference_target(read1), git_reference_target(write1)) == 0);
cl_git_pass(git_reference_lookup(&read2, repo, GIT_REFS_HEADS_DIR "test2"));
cl_assert(strcmp(git_reference_name(read2), git_reference_name(write2)) == 0);
cl_assert(git_oid_cmp(git_reference_target(read2), git_reference_target(write2)) == 0);
cl_git_pass(git_reference_lookup(&read3, repo, GIT_REFS_HEADS_DIR "test3"));
cl_assert(strcmp(git_reference_name(read3), git_reference_name(write3)) == 0);
cl_assert(git_oid_cmp(git_reference_target(read3), git_reference_target(write3)) == 0);
git_reference_free(write1);
git_reference_free(write2);
git_reference_free(write3);
git_reference_free(read1);
git_reference_free(read2);
git_reference_free(read3);
}
int foreach_test(const char *ref_name, void *payload)
{
git_reference *ref;
git_oid expected;
size_t *i = payload;
cl_git_pass(git_reference_lookup(&ref, repo, ref_name));
if (*i == 0)
cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
else if (*i == 1)
cl_git_pass(git_oid_fromstr(&expected, "e90810b8df3e80c413d903f631643c716887138d"));
else if (*i == 2)
cl_git_pass(git_oid_fromstr(&expected, "763d71aadf09a7951596c9746c024e7eece7c7af"));
cl_assert(git_oid_cmp(&expected, git_reference_target(ref)) == 0);
++(*i);
git_reference_free(ref);
return 0;
}
void test_refdb_inmemory__foreach(void)
{
git_reference *write1, *write2, *write3;
git_oid oid1, oid2, oid3;
size_t i = 0;
cl_git_pass(git_oid_fromstr(&oid1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
cl_git_pass(git_reference_create(&write1, repo, GIT_REFS_HEADS_DIR "test1", &oid1, 0));
cl_git_pass(git_oid_fromstr(&oid2, "e90810b8df3e80c413d903f631643c716887138d"));
cl_git_pass(git_reference_create(&write2, repo, GIT_REFS_HEADS_DIR "test2", &oid2, 0));
cl_git_pass(git_oid_fromstr(&oid3, "763d71aadf09a7951596c9746c024e7eece7c7af"));
cl_git_pass(git_reference_create(&write3, repo, GIT_REFS_HEADS_DIR "test3", &oid3, 0));
cl_git_pass(git_reference_foreach(repo,foreach_test, &i));
cl_assert_equal_i(3, (int)i);
git_reference_free(write1);
git_reference_free(write2);
git_reference_free(write3);
}
int delete_test(const char *ref_name, void *payload)
{
git_reference *ref;
git_oid expected;
size_t *i = payload;
cl_git_pass(git_reference_lookup(&ref, repo, ref_name));
cl_git_pass(git_oid_fromstr(&expected, "e90810b8df3e80c413d903f631643c716887138d"));
cl_assert(git_oid_cmp(&expected, git_reference_target(ref)) == 0);
++(*i);
git_reference_free(ref);
return 0;
}
void test_refdb_inmemory__delete(void)
{
git_reference *write1, *write2, *write3;
git_oid oid1, oid2, oid3;
size_t i = 0;
cl_git_pass(git_oid_fromstr(&oid1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
cl_git_pass(git_reference_create(&write1, repo, GIT_REFS_HEADS_DIR "test1", &oid1, 0));
cl_git_pass(git_oid_fromstr(&oid2, "e90810b8df3e80c413d903f631643c716887138d"));
cl_git_pass(git_reference_create(&write2, repo, GIT_REFS_HEADS_DIR "test2", &oid2, 0));
cl_git_pass(git_oid_fromstr(&oid3, "763d71aadf09a7951596c9746c024e7eece7c7af"));
cl_git_pass(git_reference_create(&write3, repo, GIT_REFS_HEADS_DIR "test3", &oid3, 0));
git_reference_delete(write1);
git_reference_free(write1);
git_reference_delete(write3);
git_reference_free(write3);
cl_git_pass(git_reference_foreach(repo, delete_test, &i));
cl_assert_equal_i(1, (int)i);
git_reference_free(write2);
}
...@@ -112,55 +112,6 @@ static int refdb_test_backend__lookup( ...@@ -112,55 +112,6 @@ static int refdb_test_backend__lookup(
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
} }
typedef struct {
git_reference_iterator parent;
size_t i;
} refdb_test_iter;
static int refdb_test_backend__iterator(git_reference_iterator **out, git_refdb_backend *_backend)
{
refdb_test_iter *iter;
GIT_UNUSED(_backend);
iter = git__calloc(1, sizeof(refdb_test_iter));
GITERR_CHECK_ALLOC(iter);
iter->parent.backend = _backend;
iter->i = 0;
*out = (git_reference_iterator *) iter;
return 0;
}
static int refdb_test_backend__next(git_reference **out, git_reference_iterator *_iter)
{
refdb_test_entry *entry;
refdb_test_backend *backend = (refdb_test_backend *) _iter->backend;
refdb_test_iter *iter = (refdb_test_iter *) _iter;
entry = git_vector_get(&backend->refs, iter->i);
if (!entry)
return GIT_ITEROVER;
if (entry->type == GIT_REF_OID) {
*out = git_reference__alloc(entry->name, &entry->target.oid, NULL);
} else if (entry->type == GIT_REF_SYMBOLIC) {
*out = git_reference__alloc_symbolic(entry->name, entry->target.symbolic);
} else {
return -1;
}
iter->i++;
return 0;
}
static void refdb_test_backend__iterator_free(git_reference_iterator *iter)
{
git__free(iter);
}
static void refdb_test_entry_free(refdb_test_entry *entry) static void refdb_test_entry_free(refdb_test_entry *entry)
{ {
if (entry->type == GIT_REF_SYMBOLIC) if (entry->type == GIT_REF_SYMBOLIC)
...@@ -222,9 +173,6 @@ int refdb_backend_test( ...@@ -222,9 +173,6 @@ int refdb_backend_test(
backend->parent.exists = &refdb_test_backend__exists; backend->parent.exists = &refdb_test_backend__exists;
backend->parent.lookup = &refdb_test_backend__lookup; backend->parent.lookup = &refdb_test_backend__lookup;
backend->parent.iterator = &refdb_test_backend__iterator;
backend->parent.next = &refdb_test_backend__next;
backend->parent.iterator_free = &refdb_test_backend__iterator_free;
backend->parent.write = &refdb_test_backend__write; backend->parent.write = &refdb_test_backend__write;
backend->parent.delete = &refdb_test_backend__delete; backend->parent.delete = &refdb_test_backend__delete;
backend->parent.free = &refdb_test_backend__free; backend->parent.free = &refdb_test_backend__free;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment