summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-03-25 23:53:38 +0200
committerVicent Marti <tanoku@gmail.com>2011-03-25 23:53:38 +0200
commit09e8de0f38ed8f28c02e5a3fa987cbb74e98a671 (patch)
treecc296d1beb507b92fc305a36ad1da8ec03e1535a
parent051d6915d70e6fec597fe1bfdee2870561f523d1 (diff)
downloadlibgit2-09e8de0f38ed8f28c02e5a3fa987cbb74e98a671.tar.gz
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.
-rw-r--r--include/git2/refs.h23
-rw-r--r--src/refs.c66
2 files changed, 68 insertions, 21 deletions
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 4ffc5ce5b..da55eaa3b 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -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
diff --git a/src/refs.c b/src/refs.c
index 8e2965528..16bd74149 100644
--- a/src/refs.c
+++ b/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 & loose_guess_rtype(full_path)) == 0)
- return GIT_SUCCESS; /* we are filtering out this reference */
+ 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;
}