Merge branch 'jk/ref-filter-flags-cleanup'
"git tag --contains" used to (ab)use the object bits to keep track of the state of object reachability without clearing them after use; this has been cleaned up and made to use the newer commit-slab facility. * jk/ref-filter-flags-cleanup: ref-filter: use separate cache for contains_tag_algo ref-filter: die on parse_commit errors ref-filter: use contains_result enum consistently ref-filter: move ref_cbdata definition into ref-filter.c
This commit is contained in:
commit
60cf6cd71a
70
ref-filter.c
70
ref-filter.c
@ -15,6 +15,7 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "trailer.h"
|
#include "trailer.h"
|
||||||
#include "wt-status.h"
|
#include "wt-status.h"
|
||||||
|
#include "commit-slab.h"
|
||||||
|
|
||||||
static struct ref_msg {
|
static struct ref_msg {
|
||||||
const char *gone;
|
const char *gone;
|
||||||
@ -1470,10 +1471,22 @@ static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom
|
|||||||
*v = &ref->value[atom];
|
*v = &ref->value[atom];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unknown has to be "0" here, because that's the default value for
|
||||||
|
* contains_cache slab entries that have not yet been assigned.
|
||||||
|
*/
|
||||||
enum contains_result {
|
enum contains_result {
|
||||||
CONTAINS_UNKNOWN = -1,
|
CONTAINS_UNKNOWN = 0,
|
||||||
CONTAINS_NO = 0,
|
CONTAINS_NO,
|
||||||
CONTAINS_YES = 1
|
CONTAINS_YES
|
||||||
|
};
|
||||||
|
|
||||||
|
define_commit_slab(contains_cache, enum contains_result);
|
||||||
|
|
||||||
|
struct ref_filter_cbdata {
|
||||||
|
struct ref_array *array;
|
||||||
|
struct ref_filter *filter;
|
||||||
|
struct contains_cache contains_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1504,24 +1517,24 @@ static int in_commit_list(const struct commit_list *want, struct commit *c)
|
|||||||
* Do not recurse to find out, though, but return -1 if inconclusive.
|
* Do not recurse to find out, though, but return -1 if inconclusive.
|
||||||
*/
|
*/
|
||||||
static enum contains_result contains_test(struct commit *candidate,
|
static enum contains_result contains_test(struct commit *candidate,
|
||||||
const struct commit_list *want)
|
const struct commit_list *want,
|
||||||
|
struct contains_cache *cache)
|
||||||
{
|
{
|
||||||
/* was it previously marked as containing a want commit? */
|
enum contains_result *cached = contains_cache_at(cache, candidate);
|
||||||
if (candidate->object.flags & TMP_MARK)
|
|
||||||
return 1;
|
/* If we already have the answer cached, return that. */
|
||||||
/* or marked as not possibly containing a want commit? */
|
if (*cached)
|
||||||
if (candidate->object.flags & UNINTERESTING)
|
return *cached;
|
||||||
return 0;
|
|
||||||
/* or are we it? */
|
/* or are we it? */
|
||||||
if (in_commit_list(want, candidate)) {
|
if (in_commit_list(want, candidate)) {
|
||||||
candidate->object.flags |= TMP_MARK;
|
*cached = CONTAINS_YES;
|
||||||
return 1;
|
return CONTAINS_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_commit(candidate) < 0)
|
/* Otherwise, we don't know; prepare to recurse */
|
||||||
return 0;
|
parse_commit_or_die(candidate);
|
||||||
|
return CONTAINS_UNKNOWN;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void push_to_contains_stack(struct commit *candidate, struct contains_stack *contains_stack)
|
static void push_to_contains_stack(struct commit *candidate, struct contains_stack *contains_stack)
|
||||||
@ -1532,10 +1545,11 @@ static void push_to_contains_stack(struct commit *candidate, struct contains_sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
static enum contains_result contains_tag_algo(struct commit *candidate,
|
static enum contains_result contains_tag_algo(struct commit *candidate,
|
||||||
const struct commit_list *want)
|
const struct commit_list *want,
|
||||||
|
struct contains_cache *cache)
|
||||||
{
|
{
|
||||||
struct contains_stack contains_stack = { 0, 0, NULL };
|
struct contains_stack contains_stack = { 0, 0, NULL };
|
||||||
int result = contains_test(candidate, want);
|
enum contains_result result = contains_test(candidate, want, cache);
|
||||||
|
|
||||||
if (result != CONTAINS_UNKNOWN)
|
if (result != CONTAINS_UNKNOWN)
|
||||||
return result;
|
return result;
|
||||||
@ -1547,16 +1561,16 @@ static enum contains_result contains_tag_algo(struct commit *candidate,
|
|||||||
struct commit_list *parents = entry->parents;
|
struct commit_list *parents = entry->parents;
|
||||||
|
|
||||||
if (!parents) {
|
if (!parents) {
|
||||||
commit->object.flags |= UNINTERESTING;
|
*contains_cache_at(cache, commit) = CONTAINS_NO;
|
||||||
contains_stack.nr--;
|
contains_stack.nr--;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we just popped the stack, parents->item has been marked,
|
* If we just popped the stack, parents->item has been marked,
|
||||||
* therefore contains_test will return a meaningful 0 or 1.
|
* therefore contains_test will return a meaningful yes/no.
|
||||||
*/
|
*/
|
||||||
else switch (contains_test(parents->item, want)) {
|
else switch (contains_test(parents->item, want, cache)) {
|
||||||
case CONTAINS_YES:
|
case CONTAINS_YES:
|
||||||
commit->object.flags |= TMP_MARK;
|
*contains_cache_at(cache, commit) = CONTAINS_YES;
|
||||||
contains_stack.nr--;
|
contains_stack.nr--;
|
||||||
break;
|
break;
|
||||||
case CONTAINS_NO:
|
case CONTAINS_NO:
|
||||||
@ -1568,13 +1582,14 @@ static enum contains_result contains_tag_algo(struct commit *candidate,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(contains_stack.contains_stack);
|
free(contains_stack.contains_stack);
|
||||||
return contains_test(candidate, want);
|
return contains_test(candidate, want, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int commit_contains(struct ref_filter *filter, struct commit *commit)
|
static int commit_contains(struct ref_filter *filter, struct commit *commit,
|
||||||
|
struct contains_cache *cache)
|
||||||
{
|
{
|
||||||
if (filter->with_commit_tag_algo)
|
if (filter->with_commit_tag_algo)
|
||||||
return contains_tag_algo(commit, filter->with_commit);
|
return contains_tag_algo(commit, filter->with_commit, cache) == CONTAINS_YES;
|
||||||
return is_descendant_of(commit, filter->with_commit);
|
return is_descendant_of(commit, filter->with_commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1771,7 +1786,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
|
|||||||
return 0;
|
return 0;
|
||||||
/* We perform the filtering for the '--contains' option */
|
/* We perform the filtering for the '--contains' option */
|
||||||
if (filter->with_commit &&
|
if (filter->with_commit &&
|
||||||
!commit_contains(filter, commit))
|
!commit_contains(filter, commit, &ref_cbdata->contains_cache))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1871,6 +1886,8 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
|
|||||||
broken = 1;
|
broken = 1;
|
||||||
filter->kind = type & FILTER_REFS_KIND_MASK;
|
filter->kind = type & FILTER_REFS_KIND_MASK;
|
||||||
|
|
||||||
|
init_contains_cache(&ref_cbdata.contains_cache);
|
||||||
|
|
||||||
/* Simple per-ref filtering */
|
/* Simple per-ref filtering */
|
||||||
if (!filter->kind)
|
if (!filter->kind)
|
||||||
die("filter_refs: invalid type");
|
die("filter_refs: invalid type");
|
||||||
@ -1893,6 +1910,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
|
|||||||
head_ref(ref_filter_handler, &ref_cbdata);
|
head_ref(ref_filter_handler, &ref_cbdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_contains_cache(&ref_cbdata.contains_cache);
|
||||||
|
|
||||||
/* Filters that need revision walking */
|
/* Filters that need revision walking */
|
||||||
if (filter->merge_commit)
|
if (filter->merge_commit)
|
||||||
|
@ -71,11 +71,6 @@ struct ref_filter {
|
|||||||
verbose;
|
verbose;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ref_filter_cbdata {
|
|
||||||
struct ref_array *array;
|
|
||||||
struct ref_filter *filter;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Macros for checking --merged and --no-merged options */
|
/* Macros for checking --merged and --no-merged options */
|
||||||
#define _OPT_MERGED_NO_MERGED(option, filter, h) \
|
#define _OPT_MERGED_NO_MERGED(option, filter, h) \
|
||||||
{ OPTION_CALLBACK, 0, option, (filter), N_("commit"), (h), \
|
{ OPTION_CALLBACK, 0, option, (filter), N_("commit"), (h), \
|
||||||
|
Loading…
Reference in New Issue
Block a user