diff options
author | Junio C Hamano <gitster@pobox.com> | 2017-06-05 09:18:11 +0900 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-06-05 09:18:11 +0900 |
commit | 711a11c301dafe84389624f009a2abfb7da5d83f (patch) | |
tree | 9a0b0317a7516cb09b3cc2cb7f14b1ca31f674ed /ref-filter.c | |
parent | 53083f8547cd45cdfabcf2f1bd21461cd6769189 (diff) | |
parent | f23092f19e73f5d8c3480ef02104af627a90361f (diff) | |
download | git-711a11c301dafe84389624f009a2abfb7da5d83f.tar.gz |
Merge branch 'mh/packed-ref-store-prep'
The implementation of "ref" API around the "packed refs" have been
cleaned up, in preparation for further changes.
* mh/packed-ref-store-prep: (25 commits)
cache_ref_iterator_begin(): avoid priming unneeded directories
ref-filter: limit traversal to prefix
create_ref_entry(): remove `check_name` option
refs_ref_iterator_begin(): handle `GIT_REF_PARANOIA`
read_packed_refs(): report unexpected fopen() failures
read_packed_refs(): do more of the work of reading packed refs
get_packed_ref_cache(): assume "packed-refs" won't change while locked
should_pack_ref(): new function, extracted from `files_pack_refs()`
ref_update_reject_duplicates(): add a sanity check
ref_update_reject_duplicates(): use `size_t` rather than `int`
ref_update_reject_duplicates(): expose function to whole refs module
ref_transaction_prepare(): new optional step for reference updates
ref_transaction_commit(): check for valid `transaction->state`
files_transaction_cleanup(): new helper function
files_ref_store: put the packed files lock directly in this struct
files-backend: move `lock` member to `files_ref_store`
lockfile: add a new method, is_lock_file_locked()
ref_store: take a `msg` parameter when deleting references
refs: use `size_t` indexes when iterating over ref transaction updates
refs_ref_iterator_begin(): don't check prefixes redundantly
...
Diffstat (limited to 'ref-filter.c')
-rw-r--r-- | ref-filter.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/ref-filter.c b/ref-filter.c index af5c0edb48..ab32bc9c31 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -1672,6 +1672,68 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname) } /* + * Find the longest prefix of pattern we can pass to + * `for_each_fullref_in()`, namely the part of pattern preceding the + * first glob character. (Note that `for_each_fullref_in()` is + * perfectly happy working with a prefix that doesn't end at a + * pathname component boundary.) + */ +static void find_longest_prefix(struct strbuf *out, const char *pattern) +{ + const char *p; + + for (p = pattern; *p && !is_glob_special(*p); p++) + ; + + strbuf_add(out, pattern, p - pattern); +} + +/* + * This is the same as for_each_fullref_in(), but it tries to iterate + * only over the patterns we'll care about. Note that it _doesn't_ do a full + * pattern match, so the callback still has to match each ref individually. + */ +static int for_each_fullref_in_pattern(struct ref_filter *filter, + each_ref_fn cb, + void *cb_data, + int broken) +{ + struct strbuf prefix = STRBUF_INIT; + int ret; + + if (!filter->match_as_path) { + /* + * in this case, the patterns are applied after + * prefixes like "refs/heads/" etc. are stripped off, + * so we have to look at everything: + */ + return for_each_fullref_in("", cb, cb_data, broken); + } + + if (!filter->name_patterns[0]) { + /* no patterns; we have to look at everything */ + return for_each_fullref_in("", cb, cb_data, broken); + } + + if (filter->name_patterns[1]) { + /* + * multiple patterns; in theory this could still work as long + * as the patterns are disjoint. We'd just make multiple calls + * to for_each_ref(). But if they're not disjoint, we'd end up + * reporting the same ref multiple times. So let's punt on that + * for now. + */ + return for_each_fullref_in("", cb, cb_data, broken); + } + + find_longest_prefix(&prefix, filter->name_patterns[0]); + + ret = for_each_fullref_in(prefix.buf, cb, cb_data, broken); + strbuf_release(&prefix); + return ret; +} + +/* * Given a ref (sha1, refname), check if the ref belongs to the array * of sha1s. If the given ref is a tag, check if the given tag points * at one of the sha1s in the given sha1 array. @@ -1917,7 +1979,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int else if (filter->kind == FILTER_REFS_TAGS) ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata, broken); else if (filter->kind & FILTER_REFS_ALL) - ret = for_each_fullref_in("", ref_filter_handler, &ref_cbdata, broken); + ret = for_each_fullref_in_pattern(filter, ref_filter_handler, &ref_cbdata, broken); if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD)) head_ref(ref_filter_handler, &ref_cbdata); } |