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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 4ffc5ce..da55eaa 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 8e29655..16bd741 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;
}