mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-04 02:25:44 +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 {
|
||||
git_refdb_backend *backend;
|
||||
char *glob;
|
||||
};
|
||||
|
||||
/** An instance for a custom backend */
|
||||
@ -67,6 +68,17 @@ struct git_refdb_backend {
|
||||
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,
|
||||
const char *glob);
|
||||
|
||||
/**
|
||||
* Return the current value and advance the iterator.
|
||||
*
|
||||
|
42
src/refdb.c
42
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)
|
||||
{
|
||||
git_reference_iterator *iter;
|
||||
|
||||
if (!db->backend || !db->backend->iterator) {
|
||||
giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (db->backend->iterator(&iter, db->backend) < 0) {
|
||||
git__free(iter);
|
||||
if (db->backend->iterator(out, db->backend) < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
*out = iter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_refdb_next(const char **out, git_reference_iterator *iter)
|
||||
{
|
||||
return iter->backend->next(out, iter);
|
||||
int error;
|
||||
|
||||
if (!iter->glob)
|
||||
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)
|
||||
{
|
||||
git__free(iter->glob);
|
||||
iter->backend->iterator_free(iter);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ int git_refdb_lookup(
|
||||
const char *ref_name);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return git_refdb_next(out, iter);
|
||||
@ -928,13 +938,10 @@ int git_reference_foreach_glob(
|
||||
const char *name;
|
||||
int error;
|
||||
|
||||
if (git_reference_iterator_new(&iter, repo) < 0)
|
||||
if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
|
||||
return -1;
|
||||
|
||||
while ((error = git_reference_next(&name, iter)) == 0) {
|
||||
if (p_fnmatch(glob, name, 0))
|
||||
continue;
|
||||
|
||||
if (callback(name, payload)) {
|
||||
error = GIT_EUSER;
|
||||
goto out;
|
||||
|
@ -123,7 +123,7 @@ static int refdb_test_backend__iterator(git_reference_iterator **out, git_refdb_
|
||||
|
||||
GIT_UNUSED(_backend);
|
||||
|
||||
iter = git__malloc(sizeof(refdb_test_iter));
|
||||
iter = git__calloc(1, sizeof(refdb_test_iter));
|
||||
GITERR_CHECK_ALLOC(iter);
|
||||
|
||||
iter->parent.backend = _backend;
|
||||
|
Loading…
Reference in New Issue
Block a user