Commit 09e8de0f by Vicent Marti

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.
parent 051d6915
...@@ -241,6 +241,29 @@ GIT_EXTERN(int) git_reference_packall(git_repository *repo); ...@@ -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); 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 GIT_END_DECL
#endif #endif
...@@ -606,10 +606,12 @@ cleanup: ...@@ -606,10 +606,12 @@ cleanup:
struct dirent_list_data { struct dirent_list_data {
git_vector ref_list;
git_repository *repo; git_repository *repo;
size_t repo_path_len; size_t repo_path_len;
unsigned int list_flags; unsigned int list_flags;
int (*callback)(const char *, void *);
void *callback_payload;
}; };
static int _dirent_loose_listall(void *_data, char *full_path) static int _dirent_loose_listall(void *_data, char *full_path)
...@@ -625,10 +627,12 @@ 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) git_hashtable_lookup(data->repo->references.packfile, file_path) != NULL)
return GIT_SUCCESS; return GIT_SUCCESS;
if ((data->list_flags & loose_guess_rtype(full_path)) == 0) if (data->list_flags != GIT_REF_LISTALL) {
return GIT_SUCCESS; /* we are filtering out this reference */ 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) static int _dirent_loose_load(void *data, char *full_path)
...@@ -1402,47 +1406,67 @@ int git_reference_packall(git_repository *repo) ...@@ -1402,47 +1406,67 @@ int git_reference_packall(git_repository *repo)
return packed_write(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; int error;
struct dirent_list_data data; struct dirent_list_data data;
char refs_path[GIT_PATH_MAX]; 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 */ /* list all the packed references first */
if (list_flags & GIT_REF_PACKED) { if (list_flags & GIT_REF_PACKED) {
const char *ref_name; const char *ref_name;
void *_unused; void *_unused;
if ((error = packed_load(repo)) < GIT_SUCCESS) { if ((error = packed_load(repo)) < GIT_SUCCESS)
git_vector_free(&data.ref_list);
return error; return error;
}
GIT_HASHTABLE_FOREACH(repo->references.packfile, ref_name, _unused, 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 /* now list the loose references, trying not to
* duplicate the ref names already in the packed-refs file */ * 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); 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) { if (error < GIT_SUCCESS) {
git_vector_free(&data.ref_list); git_vector_free(&ref_list);
return error; return error;
} }
array->strings = (char **)data.ref_list.contents; array->strings = (char **)ref_list.contents;
array->count = data.ref_list.length; array->count = ref_list.length;
return GIT_SUCCESS; return GIT_SUCCESS;
} }
......
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