Add git_tag_foreach
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
diff --git a/include/git2/tag.h b/include/git2/tag.h
index aab4b77..08504ae 100644
--- a/include/git2/tag.h
+++ b/include/git2/tag.h
@@ -277,6 +277,21 @@ GIT_EXTERN(int) git_tag_list_match(
const char *pattern,
git_repository *repo);
+
+typedef int (*git_tag_foreach_cb)(const char *name, git_oid *oid, void *data);
+/**
+ * Call callback `cb' for each tag in the repository
+ *
+ * @param repo Repository
+ * @param cb Callback function
+ * @param cb_data Pointer to callback data (optional)
+ */
+GIT_EXTERN(int) git_tag_foreach(
+ git_repository *repo,
+ git_tag_foreach_cb cb,
+ void *cb_data);
+
+
/**
* Recursively peel a tag until a non tag git_object
* is met
diff --git a/src/tag.c b/src/tag.c
index ae9d0a8..56f84a8 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -393,20 +393,51 @@ int git_tag__parse(git_tag *tag, git_odb_object *obj)
}
typedef struct {
- git_vector *taglist;
- const char *pattern;
+ git_repository *repo;
+ git_tag_foreach_cb cb;
+ void *cb_data;
+} tag_cb_data;
+
+static int tags_cb(const char *ref, void *data)
+{
+ git_oid oid;
+ tag_cb_data *d = (tag_cb_data *)data;
+
+ if (git__prefixcmp(ref, GIT_REFS_TAGS_DIR) != 0)
+ return 0; /* no tag */
+
+ if (git_reference_name_to_oid(&oid, d->repo, ref) < 0)
+ return -1;
+
+ return d->cb(ref, &oid, d->cb_data);
+}
+
+int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data)
+{
+ tag_cb_data data;
+
+ assert(repo && cb);
+
+ data.cb = cb;
+ data.cb_data = cb_data;
+ data.repo = repo;
+
+ return git_reference_foreach(repo, GIT_REF_OID | GIT_REF_PACKED,
+ &tags_cb, &data);
+}
+
+typedef struct {
+ git_vector *taglist;
+ const char *pattern;
} tag_filter_data;
#define GIT_REFS_TAGS_DIR_LEN strlen(GIT_REFS_TAGS_DIR)
-static int tag_list_cb(const char *tag_name, void *payload)
+static int tag_list_cb(const char *tag_name, git_oid *oid, void *data)
{
- tag_filter_data *filter;
-
- if (git__prefixcmp(tag_name, GIT_REFS_TAGS_DIR) != 0)
- return 0;
+ tag_filter_data *filter = (tag_filter_data *)data;
+ GIT_UNUSED(oid);
- filter = (tag_filter_data *)payload;
if (!*filter->pattern || p_fnmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == 0)
return git_vector_insert(filter->taglist, git__strdup(tag_name + GIT_REFS_TAGS_DIR_LEN));
@@ -427,7 +458,7 @@ int git_tag_list_match(git_strarray *tag_names, const char *pattern, git_reposit
filter.taglist = &taglist;
filter.pattern = pattern;
- error = git_reference_foreach(repo, GIT_REF_OID|GIT_REF_PACKED, &tag_list_cb, (void *)&filter);
+ error = git_tag_foreach(repo, &tag_list_cb, (void *)&filter);
if (error < 0) {
git_vector_free(&taglist);
return -1;