`for_each_glob_ref_in` has some code built into it that converts partial refs like 'heads/master' to their full qualified form 'refs/heads/master'. It also assume a trailing '/*' if no glob characters are present in the pattern. Extract that logic to its own function which can be reused elsewhere where the same behaviour is needed, and add an ENSURE_GLOB flag to toggle if a trailing '/*' is to be appended to the result. Signed-off-by: Kevin Daudt <me@xxxxxxxxx> Signed-off-by: Rafael Ascensão <rafa.almas@xxxxxxxxx> --- refs.c | 34 ++++++++++++++++++++-------------- refs.h | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/refs.c b/refs.c index c590a992f..1e74b48e6 100644 --- a/refs.c +++ b/refs.c @@ -369,32 +369,38 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data) return ret; } -int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, - const char *prefix, void *cb_data) +void normalize_glob_ref(struct strbuf *normalized_pattern, const char *prefix, + const char *pattern, int flags) { - struct strbuf real_pattern = STRBUF_INIT; - struct ref_filter filter; - int ret; - if (!prefix && !starts_with(pattern, "refs/")) - strbuf_addstr(&real_pattern, "refs/"); + strbuf_addstr(normalized_pattern, "refs/"); else if (prefix) - strbuf_addstr(&real_pattern, prefix); - strbuf_addstr(&real_pattern, pattern); + strbuf_addstr(normalized_pattern, prefix); + strbuf_addstr(normalized_pattern, pattern); - if (!has_glob_specials(pattern)) { + if (!has_glob_specials(pattern) && (flags & ENSURE_GLOB)) { /* Append implied '/' '*' if not present. */ - strbuf_complete(&real_pattern, '/'); + strbuf_complete(normalized_pattern, '/'); /* No need to check for '*', there is none. */ - strbuf_addch(&real_pattern, '*'); + strbuf_addch(normalized_pattern, '*'); } +} + +int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, + const char *prefix, void *cb_data) +{ + struct strbuf normalized_pattern = STRBUF_INIT; + struct ref_filter filter; + int ret; + + normalize_glob_ref(&normalized_pattern, prefix, pattern, ENSURE_GLOB); - filter.pattern = real_pattern.buf; + filter.pattern = normalized_pattern.buf; filter.fn = fn; filter.cb_data = cb_data; ret = for_each_ref(filter_refs, &filter); - strbuf_release(&real_pattern); + strbuf_release(&normalized_pattern); return ret; } diff --git a/refs.h b/refs.h index a02b628c8..9f9a8bb27 100644 --- a/refs.h +++ b/refs.h @@ -312,6 +312,22 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data); int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data); int for_each_rawref(each_ref_fn fn, void *cb_data); +/* + * Normalizes partial refs to their full qualified form. + * If prefix is NULL, will prepend 'refs/' to the pattern if it doesn't start + * with 'refs/'. Results in refs/<pattern> + * + * If prefix is not NULL will result in <prefix>/<pattern> + * + * If ENSURE_GLOB is set and no glob characters are found in the + * pattern, a trailing </><*> will be appended to the result. + * (<> characters to avoid breaking C comment syntax) + */ + +#define ENSURE_GLOB 1 +void normalize_glob_ref (struct strbuf *normalized_pattern, const char *prefix, + const char *pattern, int flags); + static inline const char *has_glob_specials(const char *pattern) { return strpbrk(pattern, "?*["); -- 2.15.0