mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-04 19:50:19 +00:00
Introduce a glob-filtering iterator
If the backend doesn't provide support for it, the matching is done in refdb on top of a normal iterator.
This commit is contained in:
parent
9bd89d9622
commit
c58cac12c2
@ -30,10 +30,11 @@ GIT_BEGIN_DECL
|
|||||||
* ...
|
* ...
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* and assing `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_backend *backend;
|
||||||
|
char *glob;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An instance for a custom backend */
|
/** An instance for a custom backend */
|
||||||
@ -67,6 +68,17 @@ struct git_refdb_backend {
|
|||||||
git_reference_iterator **iter,
|
git_reference_iterator **iter,
|
||||||
struct git_refdb_backend *backend);
|
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,
|
||||||
|
const char *glob);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current value and advance the iterator.
|
* Return the current value and advance the iterator.
|
||||||
*
|
*
|
||||||
|
40
src/refdb.c
40
src/refdb.c
@ -126,29 +126,59 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, 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)
|
||||||
{
|
{
|
||||||
git_reference_iterator *iter;
|
|
||||||
|
|
||||||
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(&iter, db->backend) < 0) {
|
if (db->backend->iterator(out, db->backend) < 0)
|
||||||
git__free(iter);
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob)
|
||||||
|
{
|
||||||
|
if (!db->backend) {
|
||||||
|
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 (db->backend->iterator(out, db->backend) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
(*out)->glob = git__strdup(glob);
|
||||||
|
if (!(*out)->glob) {
|
||||||
|
db->backend->iterator_free(*out);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = iter;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_refdb_next(const char **out, git_reference_iterator *iter)
|
int git_refdb_next(const char **out, git_reference_iterator *iter)
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (!iter->glob)
|
||||||
return iter->backend->next(out, iter);
|
return iter->backend->next(out, iter);
|
||||||
|
|
||||||
|
/* If the iterator has a glob, we need to filter */
|
||||||
|
while ((error = iter->backend->next(out, iter)) == 0) {
|
||||||
|
if (!p_fnmatch(iter->glob, *out, 0))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_refdb_iterator_free(git_reference_iterator *iter)
|
void git_refdb_iterator_free(git_reference_iterator *iter)
|
||||||
{
|
{
|
||||||
|
git__free(iter->glob);
|
||||||
iter->backend->iterator_free(iter);
|
iter->backend->iterator_free(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ int git_refdb_lookup(
|
|||||||
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);
|
||||||
|
int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob);
|
||||||
int git_refdb_next(const char **out, git_reference_iterator *iter);
|
int git_refdb_next(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);
|
||||||
|
|
||||||
|
15
src/refs.c
15
src/refs.c
@ -593,6 +593,16 @@ int git_reference_iterator_new(git_reference_iterator **out, git_repository *rep
|
|||||||
return git_refdb_iterator(out, refdb);
|
return git_refdb_iterator(out, refdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_reference_iterator_glob_new(git_reference_iterator **out, git_repository *repo, const char *glob)
|
||||||
|
{
|
||||||
|
git_refdb *refdb;
|
||||||
|
|
||||||
|
if (git_repository_refdb__weakptr(&refdb, repo) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return git_refdb_iterator_glob(out, refdb, glob);
|
||||||
|
}
|
||||||
|
|
||||||
int git_reference_next(const char **out, git_reference_iterator *iter)
|
int git_reference_next(const char **out, git_reference_iterator *iter)
|
||||||
{
|
{
|
||||||
return git_refdb_next(out, iter);
|
return git_refdb_next(out, iter);
|
||||||
@ -928,13 +938,10 @@ int git_reference_foreach_glob(
|
|||||||
const char *name;
|
const char *name;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (git_reference_iterator_new(&iter, repo) < 0)
|
if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while ((error = git_reference_next(&name, iter)) == 0) {
|
while ((error = git_reference_next(&name, iter)) == 0) {
|
||||||
if (p_fnmatch(glob, name, 0))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (callback(name, payload)) {
|
if (callback(name, payload)) {
|
||||||
error = GIT_EUSER;
|
error = GIT_EUSER;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -123,7 +123,7 @@ static int refdb_test_backend__iterator(git_reference_iterator **out, git_refdb_
|
|||||||
|
|
||||||
GIT_UNUSED(_backend);
|
GIT_UNUSED(_backend);
|
||||||
|
|
||||||
iter = git__malloc(sizeof(refdb_test_iter));
|
iter = git__calloc(1, sizeof(refdb_test_iter));
|
||||||
GITERR_CHECK_ALLOC(iter);
|
GITERR_CHECK_ALLOC(iter);
|
||||||
|
|
||||||
iter->parent.backend = _backend;
|
iter->parent.backend = _backend;
|
||||||
|
Loading…
Reference in New Issue
Block a user