mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 17:12:51 +00:00
New external API method: git_reference_listcb
List all the references in the repository, calling a custom callback for each one. The listed references may be filtered by type, or using a bitwise OR of several types. Use the magic value `GIT_REF_LISTALL` to obtain all references, including packed ones. The `callback` function will be called for each of the references in the repository, and will receive the name of the reference and the `payload` value passed to this method.
This commit is contained in:
parent
051d6915d7
commit
09e8de0f38
@ -241,6 +241,29 @@ GIT_EXTERN(int) git_reference_packall(git_repository *repo);
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags);
|
||||
|
||||
|
||||
/**
|
||||
* List all the references in the repository, calling a custom
|
||||
* callback for each one.
|
||||
*
|
||||
* The listed references may be filtered by type, or using
|
||||
* a bitwise OR of several types. Use the magic value
|
||||
* `GIT_REF_LISTALL` to obtain all references, including
|
||||
* packed ones.
|
||||
*
|
||||
* The `callback` function will be called for each of the references
|
||||
* in the repository, and will receive the name of the reference and
|
||||
* the `payload` value passed to this method.
|
||||
*
|
||||
* @param repo Repository where to find the refs
|
||||
* @param list_flags Filtering flags for the reference
|
||||
* listing.
|
||||
* @param callback Function which will be called for every listed ref
|
||||
* @param payload Additional data to pass to the callback
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_listcb(git_repository *repo, unsigned int list_flags, int (*callback)(const char *, void *), void *payload);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
62
src/refs.c
62
src/refs.c
@ -606,10 +606,12 @@ cleanup:
|
||||
|
||||
|
||||
struct dirent_list_data {
|
||||
git_vector ref_list;
|
||||
git_repository *repo;
|
||||
size_t repo_path_len;
|
||||
unsigned int list_flags;
|
||||
|
||||
int (*callback)(const char *, void *);
|
||||
void *callback_payload;
|
||||
};
|
||||
|
||||
static int _dirent_loose_listall(void *_data, char *full_path)
|
||||
@ -625,10 +627,12 @@ static int _dirent_loose_listall(void *_data, char *full_path)
|
||||
git_hashtable_lookup(data->repo->references.packfile, file_path) != NULL)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
if (data->list_flags != GIT_REF_LISTALL) {
|
||||
if ((data->list_flags & loose_guess_rtype(full_path)) == 0)
|
||||
return GIT_SUCCESS; /* we are filtering out this reference */
|
||||
}
|
||||
|
||||
return git_vector_insert(&data->ref_list, git__strdup(file_path));
|
||||
return data->callback(file_path, data->callback_payload);
|
||||
}
|
||||
|
||||
static int _dirent_loose_load(void *data, char *full_path)
|
||||
@ -1402,47 +1406,67 @@ int git_reference_packall(git_repository *repo)
|
||||
return packed_write(repo);
|
||||
}
|
||||
|
||||
int git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags)
|
||||
int git_reference_listcb(git_repository *repo, unsigned int list_flags, int (*callback)(const char *, void *), void *payload)
|
||||
{
|
||||
int error;
|
||||
struct dirent_list_data data;
|
||||
char refs_path[GIT_PATH_MAX];
|
||||
|
||||
array->strings = NULL;
|
||||
array->count = 0;
|
||||
|
||||
git_vector_init(&data.ref_list, 8, NULL);
|
||||
data.repo_path_len = strlen(repo->path_repository);
|
||||
data.list_flags = list_flags;
|
||||
data.repo = repo;
|
||||
|
||||
/* list all the packed references first */
|
||||
if (list_flags & GIT_REF_PACKED) {
|
||||
const char *ref_name;
|
||||
void *_unused;
|
||||
|
||||
if ((error = packed_load(repo)) < GIT_SUCCESS) {
|
||||
git_vector_free(&data.ref_list);
|
||||
if ((error = packed_load(repo)) < GIT_SUCCESS)
|
||||
return error;
|
||||
}
|
||||
|
||||
GIT_HASHTABLE_FOREACH(repo->references.packfile, ref_name, _unused,
|
||||
git_vector_insert(&data.ref_list, git__strdup(ref_name));
|
||||
if ((error = callback(ref_name, payload)) < GIT_SUCCESS)
|
||||
return error;
|
||||
);
|
||||
}
|
||||
|
||||
/* now list the loose references, trying not to
|
||||
* duplicate the ref names already in the packed-refs file */
|
||||
|
||||
data.repo_path_len = strlen(repo->path_repository);
|
||||
data.list_flags = list_flags;
|
||||
data.repo = repo;
|
||||
data.callback = callback;
|
||||
data.callback_payload = payload;
|
||||
|
||||
|
||||
git__joinpath(refs_path, repo->path_repository, GIT_REFS_DIR);
|
||||
error = gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
|
||||
return gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
|
||||
}
|
||||
|
||||
int cb__reflist_add(const char *ref, void *data)
|
||||
{
|
||||
return git_vector_insert((git_vector *)data, git__strdup(ref));
|
||||
}
|
||||
|
||||
int git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags)
|
||||
{
|
||||
int error;
|
||||
git_vector ref_list;
|
||||
|
||||
assert(array && repo);
|
||||
|
||||
array->strings = NULL;
|
||||
array->count = 0;
|
||||
|
||||
if (git_vector_init(&ref_list, 8, NULL) < GIT_SUCCESS)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
error = git_reference_listcb(repo, list_flags, &cb__reflist_add, (void *)&ref_list);
|
||||
|
||||
if (error < GIT_SUCCESS) {
|
||||
git_vector_free(&data.ref_list);
|
||||
git_vector_free(&ref_list);
|
||||
return error;
|
||||
}
|
||||
|
||||
array->strings = (char **)data.ref_list.contents;
|
||||
array->count = data.ref_list.length;
|
||||
array->strings = (char **)ref_list.contents;
|
||||
array->count = ref_list.length;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user