Skip to content

Commit 60cf6cd

Browse files
committed
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
2 parents 3edcc04 + a91aca4 commit 60cf6cd

2 files changed

Lines changed: 44 additions & 31 deletions

File tree

ref-filter.c

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "version.h"
1616
#include "trailer.h"
1717
#include "wt-status.h"
18+
#include "commit-slab.h"
1819

1920
static struct ref_msg {
2021
const char *gone;
@@ -1470,10 +1471,22 @@ static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom
14701471
*v = &ref->value[atom];
14711472
}
14721473

1474+
/*
1475+
* Unknown has to be "0" here, because that's the default value for
1476+
* contains_cache slab entries that have not yet been assigned.
1477+
*/
14731478
enum contains_result {
1474-
CONTAINS_UNKNOWN = -1,
1475-
CONTAINS_NO = 0,
1476-
CONTAINS_YES = 1
1479+
CONTAINS_UNKNOWN = 0,
1480+
CONTAINS_NO,
1481+
CONTAINS_YES
1482+
};
1483+
1484+
define_commit_slab(contains_cache, enum contains_result);
1485+
1486+
struct ref_filter_cbdata {
1487+
struct ref_array *array;
1488+
struct ref_filter *filter;
1489+
struct contains_cache contains_cache;
14771490
};
14781491

14791492
/*
@@ -1504,24 +1517,24 @@ static int in_commit_list(const struct commit_list *want, struct commit *c)
15041517
* Do not recurse to find out, though, but return -1 if inconclusive.
15051518
*/
15061519
static enum contains_result contains_test(struct commit *candidate,
1507-
const struct commit_list *want)
1520+
const struct commit_list *want,
1521+
struct contains_cache *cache)
15081522
{
1509-
/* was it previously marked as containing a want commit? */
1510-
if (candidate->object.flags & TMP_MARK)
1511-
return 1;
1512-
/* or marked as not possibly containing a want commit? */
1513-
if (candidate->object.flags & UNINTERESTING)
1514-
return 0;
1523+
enum contains_result *cached = contains_cache_at(cache, candidate);
1524+
1525+
/* If we already have the answer cached, return that. */
1526+
if (*cached)
1527+
return *cached;
1528+
15151529
/* or are we it? */
15161530
if (in_commit_list(want, candidate)) {
1517-
candidate->object.flags |= TMP_MARK;
1518-
return 1;
1531+
*cached = CONTAINS_YES;
1532+
return CONTAINS_YES;
15191533
}
15201534

1521-
if (parse_commit(candidate) < 0)
1522-
return 0;
1523-
1524-
return -1;
1535+
/* Otherwise, we don't know; prepare to recurse */
1536+
parse_commit_or_die(candidate);
1537+
return CONTAINS_UNKNOWN;
15251538
}
15261539

15271540
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
15321545
}
15331546

15341547
static enum contains_result contains_tag_algo(struct commit *candidate,
1535-
const struct commit_list *want)
1548+
const struct commit_list *want,
1549+
struct contains_cache *cache)
15361550
{
15371551
struct contains_stack contains_stack = { 0, 0, NULL };
1538-
int result = contains_test(candidate, want);
1552+
enum contains_result result = contains_test(candidate, want, cache);
15391553

15401554
if (result != CONTAINS_UNKNOWN)
15411555
return result;
@@ -1547,16 +1561,16 @@ static enum contains_result contains_tag_algo(struct commit *candidate,
15471561
struct commit_list *parents = entry->parents;
15481562

15491563
if (!parents) {
1550-
commit->object.flags |= UNINTERESTING;
1564+
*contains_cache_at(cache, commit) = CONTAINS_NO;
15511565
contains_stack.nr--;
15521566
}
15531567
/*
15541568
* If we just popped the stack, parents->item has been marked,
1555-
* therefore contains_test will return a meaningful 0 or 1.
1569+
* therefore contains_test will return a meaningful yes/no.
15561570
*/
1557-
else switch (contains_test(parents->item, want)) {
1571+
else switch (contains_test(parents->item, want, cache)) {
15581572
case CONTAINS_YES:
1559-
commit->object.flags |= TMP_MARK;
1573+
*contains_cache_at(cache, commit) = CONTAINS_YES;
15601574
contains_stack.nr--;
15611575
break;
15621576
case CONTAINS_NO:
@@ -1568,13 +1582,14 @@ static enum contains_result contains_tag_algo(struct commit *candidate,
15681582
}
15691583
}
15701584
free(contains_stack.contains_stack);
1571-
return contains_test(candidate, want);
1585+
return contains_test(candidate, want, cache);
15721586
}
15731587

1574-
static int commit_contains(struct ref_filter *filter, struct commit *commit)
1588+
static int commit_contains(struct ref_filter *filter, struct commit *commit,
1589+
struct contains_cache *cache)
15751590
{
15761591
if (filter->with_commit_tag_algo)
1577-
return contains_tag_algo(commit, filter->with_commit);
1592+
return contains_tag_algo(commit, filter->with_commit, cache) == CONTAINS_YES;
15781593
return is_descendant_of(commit, filter->with_commit);
15791594
}
15801595

@@ -1771,7 +1786,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
17711786
return 0;
17721787
/* We perform the filtering for the '--contains' option */
17731788
if (filter->with_commit &&
1774-
!commit_contains(filter, commit))
1789+
!commit_contains(filter, commit, &ref_cbdata->contains_cache))
17751790
return 0;
17761791
}
17771792

@@ -1871,6 +1886,8 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
18711886
broken = 1;
18721887
filter->kind = type & FILTER_REFS_KIND_MASK;
18731888

1889+
init_contains_cache(&ref_cbdata.contains_cache);
1890+
18741891
/* Simple per-ref filtering */
18751892
if (!filter->kind)
18761893
die("filter_refs: invalid type");
@@ -1893,6 +1910,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
18931910
head_ref(ref_filter_handler, &ref_cbdata);
18941911
}
18951912

1913+
clear_contains_cache(&ref_cbdata.contains_cache);
18961914

18971915
/* Filters that need revision walking */
18981916
if (filter->merge_commit)

ref-filter.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,6 @@ struct ref_filter {
7171
verbose;
7272
};
7373

74-
struct ref_filter_cbdata {
75-
struct ref_array *array;
76-
struct ref_filter *filter;
77-
};
78-
7974
/* Macros for checking --merged and --no-merged options */
8075
#define _OPT_MERGED_NO_MERGED(option, filter, h) \
8176
{ OPTION_CALLBACK, 0, option, (filter), N_("commit"), (h), \

0 commit comments

Comments
 (0)