Mercurial > hg
changeset 23342:f710644e1ce9
ancestor: add a way to remove ancestors of bases from a given set
This and missingancestors can share state, which will turn out to be perfect
for set discovery.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Fri, 14 Nov 2014 19:40:30 -0800 |
parents | bcc3012f8477 |
children | f8a2647fe020 |
files | mercurial/ancestor.py tests/test-ancestor.py |
diffstat | 2 files changed, 50 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/ancestor.py Fri Nov 14 17:21:00 2014 -0800 +++ b/mercurial/ancestor.py Fri Nov 14 19:40:30 2014 -0800 @@ -154,6 +154,32 @@ '''grow the ancestor set by adding new bases''' self.bases.update(newbases) + def removeancestorsfrom(self, revs): + '''remove all ancestors of bases from the set revs (in place)''' + bases = self.bases + pfunc = self.pfunc + revs.difference_update(bases) + # nullrev is always an ancestor + revs.discard(nullrev) + if not revs: + return + # anything in revs > start is definitely not an ancestor of bases + # revs <= start needs to be investigated + start = max(bases) + keepcount = sum(1 for r in revs if r > start) + if len(revs) == keepcount: + # no revs to consider + return + + for curr in xrange(start, min(revs) - 1, -1): + if curr not in bases: + continue + revs.discard(curr) + bases.update(pfunc(curr)) + if len(revs) == keepcount: + # no more potential revs to discard + break + def missingancestors(self, revs): '''return all the ancestors of revs that are not ancestors of self.bases
--- a/tests/test-ancestor.py Fri Nov 14 17:21:00 2014 -0800 +++ b/tests/test-ancestor.py Fri Nov 14 19:40:30 2014 -0800 @@ -47,6 +47,11 @@ self.bases = set(bases) def addbases(self, newbases): self.bases.update(newbases) + def removeancestorsfrom(self, revs): + for base in self.bases: + if base != nullrev: + revs.difference_update(self.ancs[base]) + revs.discard(nullrev) def missingancestors(self, revs): res = set() for rev in revs: @@ -98,18 +103,31 @@ # reference slow algorithm naiveinc = naiveincrementalmissingancestors(ancs, bases) seq = [] + revs = [] for _ in xrange(inccount): if rng.random() < 0.2: newbases = samplerevs(graphnodes) seq.append(('addbases', newbases)) inc.addbases(newbases) naiveinc.addbases(newbases) - revs = samplerevs(graphnodes) - seq.append(('missingancestors', revs)) - h = inc.missingancestors(revs) - r = naiveinc.missingancestors(revs) - if h != r: - err(seed, graph, bases, seq, h, r) + if rng.random() < 0.4: + # larger set so that there are more revs to remove from + revs = samplerevs(graphnodes, mu=1.5) + seq.append(('removeancestorsfrom', revs)) + hrevs = set(revs) + rrevs = set(revs) + inc.removeancestorsfrom(hrevs) + naiveinc.removeancestorsfrom(rrevs) + if hrevs != rrevs: + err(seed, graph, bases, seq, sorted(hrevs), + sorted(rrevs)) + else: + revs = samplerevs(graphnodes) + seq.append(('missingancestors', revs)) + h = inc.missingancestors(revs) + r = naiveinc.missingancestors(revs) + if h != r: + err(seed, graph, bases, seq, h, r) # graph is a dict of child->parent adjacency lists for this graph: # o 13