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