From 2b5af615e1f4344f6073d0ddf3e83256d9a8d58f Mon Sep 17 00:00:00 2001 From: nulltoken Date: Thu, 7 Jul 2011 13:47:45 +0200 Subject: [PATCH] tag: add pattern based retrieval of list of tag names --- include/git2/tag.h | 23 +++++++++++++++++++++++ src/tag.c | 32 ++++++++++++++++++++++++++++---- tests/t08-tag.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/include/git2/tag.h b/include/git2/tag.h index 15635cce2..71b27bb3e 100644 --- a/include/git2/tag.h +++ b/include/git2/tag.h @@ -235,6 +235,29 @@ GIT_EXTERN(int) git_tag_list( git_strarray *tag_names, git_repository *repo); +/** + * Fill a list with all the tags in the Repository + * which name match a defined pattern + * + * If an empty pattern is provided, all the tags + * will be returned. + * + * The string array will be filled with the names of the + * matching tags; these values are owned by the user and + * should be free'd manually when no longer needed, using + * `git_strarray_free`. + * + * @param tag_names Pointer to a git_strarray structure where + * the tag names will be stored + * @param pattern Standard fnmatch pattern + * @param repo Repository where to find the tags + * @return 0 on success; error code otherwise + */ +GIT_EXTERN(int) git_tag_list_match( + git_strarray *tag_names, + const char *pattern, + git_repository *repo); + /** @} */ GIT_END_DECL #endif diff --git a/src/tag.c b/src/tag.c index de70c50ae..f508fb7e2 100644 --- a/src/tag.c +++ b/src/tag.c @@ -364,23 +364,42 @@ int git_tag__parse(git_tag *tag, git_odb_object *obj) return parse_tag_buffer(tag, obj->raw.data, (char *)obj->raw.data + obj->raw.len); } +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) { - if (git__prefixcmp(tag_name, GIT_REFS_TAGS_DIR) == 0) - return git_vector_insert((git_vector *)payload, git__strdup(tag_name)); + tag_filter_data *filter; + + if (git__prefixcmp(tag_name, GIT_REFS_TAGS_DIR) != 0) + return GIT_SUCCESS; + + filter = (tag_filter_data *)payload; + if (!*filter->pattern || p_fnmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == GIT_SUCCESS) + return git_vector_insert(filter->taglist, git__strdup(tag_name)); return GIT_SUCCESS; } -int git_tag_list(git_strarray *tag_names, git_repository *repo) +int git_tag_list_match(git_strarray *tag_names, const char *pattern, git_repository *repo) { int error; + tag_filter_data filter; git_vector taglist; + assert(tag_names && repo && pattern); + if (git_vector_init(&taglist, 8, NULL) < GIT_SUCCESS) return GIT_ENOMEM; - error = git_reference_foreach(repo, GIT_REF_OID|GIT_REF_PACKED, &tag_list_cb, (void *)&taglist); + filter.taglist = &taglist; + filter.pattern = pattern; + + error = git_reference_foreach(repo, GIT_REF_OID|GIT_REF_PACKED, &tag_list_cb, (void *)&filter); if (error < GIT_SUCCESS) { git_vector_free(&taglist); return git__rethrow(error, "Failed to list tags"); @@ -390,3 +409,8 @@ int git_tag_list(git_strarray *tag_names, git_repository *repo) tag_names->count = taglist.length; return GIT_SUCCESS; } + +int git_tag_list(git_strarray *tag_names, git_repository *repo) +{ + return git_tag_list_match(tag_names, "", repo); +} \ No newline at end of file diff --git a/tests/t08-tag.c b/tests/t08-tag.c index 64a939f0e..aeff8b360 100644 --- a/tests/t08-tag.c +++ b/tests/t08-tag.c @@ -77,6 +77,35 @@ BEGIN_TEST(read1, "list all tag names from the repository") git_repository_free(repo); END_TEST +static int ensure_tag_pattern_match(git_repository *repo, const char *pattern, const size_t expected_matches) +{ + git_strarray tag_list; + int error = GIT_SUCCESS; + + if ((error = git_tag_list_match(&tag_list, pattern, repo)) < GIT_SUCCESS) + goto exit; + + if (tag_list.count != expected_matches) + error = GIT_ERROR; + +exit: + git_strarray_free(&tag_list); + return error; +} + +BEGIN_TEST(read2, "list all tag names from the repository matching a specified pattern") + git_repository *repo; + must_pass(git_repository_open(&repo, REPOSITORY_FOLDER)); + must_pass(ensure_tag_pattern_match(repo, "", 3)); + must_pass(ensure_tag_pattern_match(repo, "*", 3)); + must_pass(ensure_tag_pattern_match(repo, "t*", 1)); + must_pass(ensure_tag_pattern_match(repo, "*b", 2)); + must_pass(ensure_tag_pattern_match(repo, "e", 0)); + must_pass(ensure_tag_pattern_match(repo, "e90810b", 1)); + must_pass(ensure_tag_pattern_match(repo, "e90810[ab]", 1)); + git_repository_free(repo); +END_TEST + #define TAGGER_NAME "Vicent Marti" #define TAGGER_EMAIL "vicent@github.com" @@ -222,6 +251,8 @@ END_TEST BEGIN_SUITE(tag) ADD_TEST(read0); ADD_TEST(read1); + ADD_TEST(read2); + ADD_TEST(write0); ADD_TEST(write2); ADD_TEST(write3);