##// END OF EJS Templates
perf-helper: add a small extension with revsets to select repository subset...
marmoute -
r47500:cb70dabe default
parent child Browse files
Show More
@@ -0,0 +1,94 b''
1 """revset to select sample of repository
2
3 Hopefully this is useful to create interesting discovery cases.
4 """
5
6 import collections
7 import random
8
9 from mercurial.i18n import _
10
11 from mercurial import (
12 registrar,
13 revset,
14 revsetlang,
15 smartset,
16 )
17
18 revsetpredicate = registrar.revsetpredicate()
19
20
21 @revsetpredicate(b'scratch(REVS, <count>, [seed])')
22 def scratch(repo, subset, x):
23 """randomly remove <count> revision from the repository top
24
25 This subset is created by recursively picking changeset starting from the
26 heads. It can be summarized using the following algorithm::
27
28 selected = set()
29 for i in range(<count>):
30 unselected = repo.revs("not <selected>")
31 candidates = repo.revs("heads(<unselected>)")
32 pick = random.choice(candidates)
33 selected.add(pick)
34 """
35 m = _(b"scratch expects revisions, count argument and an optional seed")
36 args = revsetlang.getargs(x, 2, 3, m)
37 if len(args) == 2:
38 x, n = args
39 rand = random
40 elif len(args) == 3:
41 x, n, seed = args
42 seed = revsetlang.getinteger(seed, _(b"seed should be a number"))
43 rand = random.Random(seed)
44 else:
45 assert False
46
47 n = revsetlang.getinteger(n, _(b"scratch expects a number"))
48
49 selected = set()
50 heads = set()
51 children_count = collections.defaultdict(lambda: 0)
52 parents = repo.changelog._uncheckedparentrevs
53
54 baseset = revset.getset(repo, smartset.fullreposet(repo), x)
55 baseset.sort()
56 for r in baseset:
57 heads.add(r)
58
59 p1, p2 = parents(r)
60 if p1 >= 0:
61 heads.discard(p1)
62 children_count[p1] += 1
63 if p2 >= 0:
64 heads.discard(p2)
65 children_count[p2] += 1
66
67 for h in heads:
68 assert children_count[h] == 0
69
70 selected = set()
71 for x in range(n):
72 if not heads:
73 break
74 pick = rand.choice(list(heads))
75 heads.remove(pick)
76 assert pick not in selected
77 selected.add(pick)
78 p1, p2 = parents(pick)
79 if p1 in children_count:
80 assert p1 in children_count
81 children_count[p1] -= 1
82 assert children_count[p1] >= 0
83 if children_count[p1] == 0:
84 assert p1 not in selected, (r, p1)
85 heads.add(p1)
86 if p2 in children_count:
87 assert p2 in children_count
88 children_count[p2] -= 1
89 assert children_count[p2] >= 0
90 if children_count[p2] == 0:
91 assert p2 not in selected, (r, p2)
92 heads.add(p2)
93
94 return smartset.baseset(selected) & subset
General Comments 0
You need to be logged in to leave comments. Login now