90 for p in parentfn(curr): |
90 for p in parentfn(curr): |
91 if p != nullrev and (not revs or p in revs): |
91 if p != nullrev and (not revs or p in revs): |
92 dist.setdefault(p, d + 1) |
92 dist.setdefault(p, d + 1) |
93 visit.append(p) |
93 visit.append(p) |
94 |
94 |
95 def _limitsample(sample, desiredlen): |
95 def _limitsample(sample, desiredlen, randomize=True): |
96 """return a random subset of sample of at most desiredlen item""" |
96 """return a random subset of sample of at most desiredlen item. |
97 if len(sample) > desiredlen: |
97 |
98 sample = set(random.sample(sample, desiredlen)) |
98 If randomize is False, though, a deterministic subset is returned. |
99 return sample |
99 This is meant for integration tests. |
|
100 """ |
|
101 if len(sample) <= desiredlen: |
|
102 return sample |
|
103 if randomize: |
|
104 return set(random.sample(sample, desiredlen)) |
|
105 sample = list(sample) |
|
106 sample.sort() |
|
107 return set(sample[:desiredlen]) |
100 |
108 |
101 class partialdiscovery(object): |
109 class partialdiscovery(object): |
102 """an object representing ongoing discovery |
110 """an object representing ongoing discovery |
103 |
111 |
104 Feed with data from the remote repository, this object keep track of the |
112 Feed with data from the remote repository, this object keep track of the |
108 - undecided: revs we don't have information on yet |
116 - undecided: revs we don't have information on yet |
109 - missing: revs missing remotely |
117 - missing: revs missing remotely |
110 (all tracked revisions are known locally) |
118 (all tracked revisions are known locally) |
111 """ |
119 """ |
112 |
120 |
113 def __init__(self, repo, targetheads, respectsize): |
121 def __init__(self, repo, targetheads, respectsize, randomize=True): |
114 self._repo = repo |
122 self._repo = repo |
115 self._targetheads = targetheads |
123 self._targetheads = targetheads |
116 self._common = repo.changelog.incrementalmissingrevs() |
124 self._common = repo.changelog.incrementalmissingrevs() |
117 self._undecided = None |
125 self._undecided = None |
118 self.missing = set() |
126 self.missing = set() |
119 self._childrenmap = None |
127 self._childrenmap = None |
120 self._respectsize = respectsize |
128 self._respectsize = respectsize |
|
129 self.randomize = randomize |
121 |
130 |
122 def addcommons(self, commons): |
131 def addcommons(self, commons): |
123 """register nodes known as common""" |
132 """register nodes known as common""" |
124 self._common.addbases(commons) |
133 self._common.addbases(commons) |
125 if self._undecided is not None: |
134 if self._undecided is not None: |
220 if len(revs) <= size: |
229 if len(revs) <= size: |
221 return list(revs) |
230 return list(revs) |
222 sample = set(self._repo.revs('heads(%ld)', revs)) |
231 sample = set(self._repo.revs('heads(%ld)', revs)) |
223 |
232 |
224 if len(sample) >= size: |
233 if len(sample) >= size: |
225 return _limitsample(sample, size) |
234 return _limitsample(sample, size, randomize=self.randomize) |
226 |
235 |
227 _updatesample(None, headrevs, sample, self._parentsgetter(), |
236 _updatesample(None, headrevs, sample, self._parentsgetter(), |
228 quicksamplesize=size) |
237 quicksamplesize=size) |
229 return sample |
238 return sample |
230 |
239 |
247 assert sample |
256 assert sample |
248 |
257 |
249 if not self._respectsize: |
258 if not self._respectsize: |
250 size = max(size, min(len(revsroots), len(revsheads))) |
259 size = max(size, min(len(revsroots), len(revsheads))) |
251 |
260 |
252 sample = _limitsample(sample, size) |
261 sample = _limitsample(sample, size, randomize=self.randomize) |
253 if len(sample) < size: |
262 if len(sample) < size: |
254 more = size - len(sample) |
263 more = size - len(sample) |
255 sample.update(random.sample(list(revs - sample), more)) |
264 takefrom = list(revs - sample) |
|
265 if self.randomize: |
|
266 sample.update(random.sample(takefrom, more)) |
|
267 else: |
|
268 takefrom.sort() |
|
269 sample.update(takefrom[:more]) |
256 return sample |
270 return sample |
257 |
271 |
258 def findcommonheads(ui, local, remote, |
272 def findcommonheads(ui, local, remote, |
259 initialsamplesize=100, |
273 initialsamplesize=100, |
260 fullsamplesize=200, |
274 fullsamplesize=200, |