##// END OF EJS Templates
discovery: slowly increase sampling size...
marmoute -
r42546:dbd0fcca default
parent child Browse files
Show More
@@ -1,436 +1,439
1 1 # setdiscovery.py - improved discovery of common nodeset for mercurial
2 2 #
3 3 # Copyright 2010 Benoit Boissinot <bboissin@gmail.com>
4 4 # and Peter Arrenbrecht <peter@arrenbrecht.ch>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8 """
9 9 Algorithm works in the following way. You have two repository: local and
10 10 remote. They both contains a DAG of changelists.
11 11
12 12 The goal of the discovery protocol is to find one set of node *common*,
13 13 the set of nodes shared by local and remote.
14 14
15 15 One of the issue with the original protocol was latency, it could
16 16 potentially require lots of roundtrips to discover that the local repo was a
17 17 subset of remote (which is a very common case, you usually have few changes
18 18 compared to upstream, while upstream probably had lots of development).
19 19
20 20 The new protocol only requires one interface for the remote repo: `known()`,
21 21 which given a set of changelists tells you if they are present in the DAG.
22 22
23 23 The algorithm then works as follow:
24 24
25 25 - We will be using three sets, `common`, `missing`, `unknown`. Originally
26 26 all nodes are in `unknown`.
27 27 - Take a sample from `unknown`, call `remote.known(sample)`
28 28 - For each node that remote knows, move it and all its ancestors to `common`
29 29 - For each node that remote doesn't know, move it and all its descendants
30 30 to `missing`
31 31 - Iterate until `unknown` is empty
32 32
33 33 There are a couple optimizations, first is instead of starting with a random
34 34 sample of missing, start by sending all heads, in the case where the local
35 35 repo is a subset, you computed the answer in one round trip.
36 36
37 37 Then you can do something similar to the bisecting strategy used when
38 38 finding faulty changesets. Instead of random samples, you can try picking
39 39 nodes that will maximize the number of nodes that will be
40 40 classified with it (since all ancestors or descendants will be marked as well).
41 41 """
42 42
43 43 from __future__ import absolute_import
44 44
45 45 import collections
46 46 import random
47 47
48 48 from .i18n import _
49 49 from .node import (
50 50 nullid,
51 51 nullrev,
52 52 )
53 53 from . import (
54 54 error,
55 55 util,
56 56 )
57 57
58 58 def _updatesample(revs, heads, sample, parentfn, quicksamplesize=0):
59 59 """update an existing sample to match the expected size
60 60
61 61 The sample is updated with revs exponentially distant from each head of the
62 62 <revs> set. (H~1, H~2, H~4, H~8, etc).
63 63
64 64 If a target size is specified, the sampling will stop once this size is
65 65 reached. Otherwise sampling will happen until roots of the <revs> set are
66 66 reached.
67 67
68 68 :revs: set of revs we want to discover (if None, assume the whole dag)
69 69 :heads: set of DAG head revs
70 70 :sample: a sample to update
71 71 :parentfn: a callable to resolve parents for a revision
72 72 :quicksamplesize: optional target size of the sample"""
73 73 dist = {}
74 74 visit = collections.deque(heads)
75 75 seen = set()
76 76 factor = 1
77 77 while visit:
78 78 curr = visit.popleft()
79 79 if curr in seen:
80 80 continue
81 81 d = dist.setdefault(curr, 1)
82 82 if d > factor:
83 83 factor *= 2
84 84 if d == factor:
85 85 sample.add(curr)
86 86 if quicksamplesize and (len(sample) >= quicksamplesize):
87 87 return
88 88 seen.add(curr)
89 89
90 90 for p in parentfn(curr):
91 91 if p != nullrev and (not revs or p in revs):
92 92 dist.setdefault(p, d + 1)
93 93 visit.append(p)
94 94
95 95 def _limitsample(sample, desiredlen):
96 96 """return a random subset of sample of at most desiredlen item"""
97 97 if len(sample) > desiredlen:
98 98 sample = set(random.sample(sample, desiredlen))
99 99 return sample
100 100
101 101 class partialdiscovery(object):
102 102 """an object representing ongoing discovery
103 103
104 104 Feed with data from the remote repository, this object keep track of the
105 105 current set of changeset in various states:
106 106
107 107 - common: revs also known remotely
108 108 - undecided: revs we don't have information on yet
109 109 - missing: revs missing remotely
110 110 (all tracked revisions are known locally)
111 111 """
112 112
113 113 def __init__(self, repo, targetheads):
114 114 self._repo = repo
115 115 self._targetheads = targetheads
116 116 self._common = repo.changelog.incrementalmissingrevs()
117 117 self._undecided = None
118 118 self.missing = set()
119 119 self._childrenmap = None
120 120
121 121 def addcommons(self, commons):
122 122 """register nodes known as common"""
123 123 self._common.addbases(commons)
124 124 if self._undecided is not None:
125 125 self._common.removeancestorsfrom(self._undecided)
126 126
127 127 def addmissings(self, missings):
128 128 """register some nodes as missing"""
129 129 newmissing = self._repo.revs('%ld::%ld', missings, self.undecided)
130 130 if newmissing:
131 131 self.missing.update(newmissing)
132 132 self.undecided.difference_update(newmissing)
133 133
134 134 def addinfo(self, sample):
135 135 """consume an iterable of (rev, known) tuples"""
136 136 common = set()
137 137 missing = set()
138 138 for rev, known in sample:
139 139 if known:
140 140 common.add(rev)
141 141 else:
142 142 missing.add(rev)
143 143 if common:
144 144 self.addcommons(common)
145 145 if missing:
146 146 self.addmissings(missing)
147 147
148 148 def hasinfo(self):
149 149 """return True is we have any clue about the remote state"""
150 150 return self._common.hasbases()
151 151
152 152 def iscomplete(self):
153 153 """True if all the necessary data have been gathered"""
154 154 return self._undecided is not None and not self._undecided
155 155
156 156 @property
157 157 def undecided(self):
158 158 if self._undecided is not None:
159 159 return self._undecided
160 160 self._undecided = set(self._common.missingancestors(self._targetheads))
161 161 return self._undecided
162 162
163 163 def stats(self):
164 164 return {
165 165 'undecided': len(self.undecided),
166 166 }
167 167
168 168 def commonheads(self):
169 169 """the heads of the known common set"""
170 170 # heads(common) == heads(common.bases) since common represents
171 171 # common.bases and all its ancestors
172 172 return self._common.basesheads()
173 173
174 174 def _parentsgetter(self):
175 175 getrev = self._repo.changelog.index.__getitem__
176 176 def getparents(r):
177 177 return getrev(r)[5:7]
178 178 return getparents
179 179
180 180 def _childrengetter(self):
181 181
182 182 if self._childrenmap is not None:
183 183 # During discovery, the `undecided` set keep shrinking.
184 184 # Therefore, the map computed for an iteration N will be
185 185 # valid for iteration N+1. Instead of computing the same
186 186 # data over and over we cached it the first time.
187 187 return self._childrenmap.__getitem__
188 188
189 189 # _updatesample() essentially does interaction over revisions to look
190 190 # up their children. This lookup is expensive and doing it in a loop is
191 191 # quadratic. We precompute the children for all relevant revisions and
192 192 # make the lookup in _updatesample() a simple dict lookup.
193 193 self._childrenmap = children = {}
194 194
195 195 parentrevs = self._parentsgetter()
196 196 revs = self.undecided
197 197
198 198 for rev in sorted(revs):
199 199 # Always ensure revision has an entry so we don't need to worry
200 200 # about missing keys.
201 201 children[rev] = []
202 202 for prev in parentrevs(rev):
203 203 if prev == nullrev:
204 204 continue
205 205 c = children.get(prev)
206 206 if c is not None:
207 207 c.append(rev)
208 208 return children.__getitem__
209 209
210 210 def takequicksample(self, headrevs, size):
211 211 """takes a quick sample of size <size>
212 212
213 213 It is meant for initial sampling and focuses on querying heads and close
214 214 ancestors of heads.
215 215
216 216 :headrevs: set of head revisions in local DAG to consider
217 217 :size: the maximum size of the sample"""
218 218 revs = self.undecided
219 219 if len(revs) <= size:
220 220 return list(revs)
221 221 sample = set(self._repo.revs('heads(%ld)', revs))
222 222
223 223 if len(sample) >= size:
224 224 return _limitsample(sample, size)
225 225
226 226 _updatesample(None, headrevs, sample, self._parentsgetter(),
227 227 quicksamplesize=size)
228 228 return sample
229 229
230 230 def takefullsample(self, headrevs, size):
231 231 revs = self.undecided
232 232 if len(revs) <= size:
233 233 return list(revs)
234 234 repo = self._repo
235 235 sample = set(repo.revs('heads(%ld)', revs))
236 236 parentrevs = self._parentsgetter()
237 237
238 238 # update from heads
239 239 revsheads = sample.copy()
240 240 _updatesample(revs, revsheads, sample, parentrevs)
241 241
242 242 # update from roots
243 243 revsroots = set(repo.revs('roots(%ld)', revs))
244 244
245 245 childrenrevs = self._childrengetter()
246 246
247 247 _updatesample(revs, revsroots, sample, childrenrevs)
248 248 assert sample
249 249 sample = _limitsample(sample, size)
250 250 if len(sample) < size:
251 251 more = size - len(sample)
252 252 sample.update(random.sample(list(revs - sample), more))
253 253 return sample
254 254
255 255 def findcommonheads(ui, local, remote,
256 256 initialsamplesize=100,
257 257 fullsamplesize=200,
258 258 abortwhenunrelated=True,
259 ancestorsof=None):
259 ancestorsof=None,
260 samplegrowth=1.05):
260 261 '''Return a tuple (common, anyincoming, remoteheads) used to identify
261 262 missing nodes from or in remote.
262 263 '''
263 264 start = util.timer()
264 265
265 266 roundtrips = 0
266 267 cl = local.changelog
267 268 clnode = cl.node
268 269 clrev = cl.rev
269 270
270 271 if ancestorsof is not None:
271 272 ownheads = [clrev(n) for n in ancestorsof]
272 273 else:
273 274 ownheads = [rev for rev in cl.headrevs() if rev != nullrev]
274 275
275 276 # early exit if we know all the specified remote heads already
276 277 ui.debug("query 1; heads\n")
277 278 roundtrips += 1
278 279 # We also ask remote about all the local heads. That set can be arbitrarily
279 280 # large, so we used to limit it size to `initialsamplesize`. We no longer
280 281 # do as it proved counter productive. The skipped heads could lead to a
281 282 # large "undecided" set, slower to be clarified than if we asked the
282 283 # question for all heads right away.
283 284 #
284 285 # We are already fetching all server heads using the `heads` commands,
285 286 # sending a equivalent number of heads the other way should not have a
286 287 # significant impact. In addition, it is very likely that we are going to
287 288 # have to issue "known" request for an equivalent amount of revisions in
288 289 # order to decide if theses heads are common or missing.
289 290 #
290 291 # find a detailled analysis below.
291 292 #
292 293 # Case A: local and server both has few heads
293 294 #
294 295 # Ownheads is below initialsamplesize, limit would not have any effect.
295 296 #
296 297 # Case B: local has few heads and server has many
297 298 #
298 299 # Ownheads is below initialsamplesize, limit would not have any effect.
299 300 #
300 301 # Case C: local and server both has many heads
301 302 #
302 303 # We now transfert some more data, but not significantly more than is
303 304 # already transfered to carry the server heads.
304 305 #
305 306 # Case D: local has many heads, server has few
306 307 #
307 308 # D.1 local heads are mostly known remotely
308 309 #
309 310 # All the known head will have be part of a `known` request at some
310 311 # point for the discovery to finish. Sending them all earlier is
311 312 # actually helping.
312 313 #
313 314 # (This case is fairly unlikely, it requires the numerous heads to all
314 315 # be merged server side in only a few heads)
315 316 #
316 317 # D.2 local heads are mostly missing remotely
317 318 #
318 319 # To determine that the heads are missing, we'll have to issue `known`
319 320 # request for them or one of their ancestors. This amount of `known`
320 321 # request will likely be in the same order of magnitude than the amount
321 322 # of local heads.
322 323 #
323 324 # The only case where we can be more efficient using `known` request on
324 325 # ancestors are case were all the "missing" local heads are based on a
325 326 # few changeset, also "missing". This means we would have a "complex"
326 327 # graph (with many heads) attached to, but very independant to a the
327 328 # "simple" graph on the server. This is a fairly usual case and have
328 329 # not been met in the wild so far.
329 330 if remote.limitedarguments:
330 331 sample = _limitsample(ownheads, initialsamplesize)
331 332 # indices between sample and externalized version must match
332 333 sample = list(sample)
333 334 else:
334 335 sample = ownheads
335 336
336 337 with remote.commandexecutor() as e:
337 338 fheads = e.callcommand('heads', {})
338 339 fknown = e.callcommand('known', {
339 340 'nodes': [clnode(r) for r in sample],
340 341 })
341 342
342 343 srvheadhashes, yesno = fheads.result(), fknown.result()
343 344
344 345 if cl.tip() == nullid:
345 346 if srvheadhashes != [nullid]:
346 347 return [nullid], True, srvheadhashes
347 348 return [nullid], False, []
348 349
349 350 # start actual discovery (we note this before the next "if" for
350 351 # compatibility reasons)
351 352 ui.status(_("searching for changes\n"))
352 353
353 354 knownsrvheads = [] # revnos of remote heads that are known locally
354 355 for node in srvheadhashes:
355 356 if node == nullid:
356 357 continue
357 358
358 359 try:
359 360 knownsrvheads.append(clrev(node))
360 361 # Catches unknown and filtered nodes.
361 362 except error.LookupError:
362 363 continue
363 364
364 365 if len(knownsrvheads) == len(srvheadhashes):
365 366 ui.debug("all remote heads known locally\n")
366 367 return srvheadhashes, False, srvheadhashes
367 368
368 369 if len(sample) == len(ownheads) and all(yesno):
369 370 ui.note(_("all local heads known remotely\n"))
370 371 ownheadhashes = [clnode(r) for r in ownheads]
371 372 return ownheadhashes, True, srvheadhashes
372 373
373 374 # full blown discovery
374 375
375 376 disco = partialdiscovery(local, ownheads)
376 377 # treat remote heads (and maybe own heads) as a first implicit sample
377 378 # response
378 379 disco.addcommons(knownsrvheads)
379 380 disco.addinfo(zip(sample, yesno))
380 381
381 382 full = False
382 383 progress = ui.makeprogress(_('searching'), unit=_('queries'))
383 384 while not disco.iscomplete():
384 385
385 386 if full or disco.hasinfo():
386 387 if full:
387 388 ui.note(_("sampling from both directions\n"))
388 389 else:
389 390 ui.debug("taking initial sample\n")
390 391 samplefunc = disco.takefullsample
391 392 targetsize = fullsamplesize
393 if not remote.limitedarguments:
394 fullsamplesize = int(fullsamplesize * samplegrowth)
392 395 else:
393 396 # use even cheaper initial sample
394 397 ui.debug("taking quick initial sample\n")
395 398 samplefunc = disco.takequicksample
396 399 targetsize = initialsamplesize
397 400 sample = samplefunc(ownheads, targetsize)
398 401
399 402 roundtrips += 1
400 403 progress.update(roundtrips)
401 404 stats = disco.stats()
402 405 ui.debug("query %i; still undecided: %i, sample size is: %i\n"
403 406 % (roundtrips, stats['undecided'], len(sample)))
404 407
405 408 # indices between sample and externalized version must match
406 409 sample = list(sample)
407 410
408 411 with remote.commandexecutor() as e:
409 412 yesno = e.callcommand('known', {
410 413 'nodes': [clnode(r) for r in sample],
411 414 }).result()
412 415
413 416 full = True
414 417
415 418 disco.addinfo(zip(sample, yesno))
416 419
417 420 result = disco.commonheads()
418 421 elapsed = util.timer() - start
419 422 progress.complete()
420 423 ui.debug("%d total queries in %.4fs\n" % (roundtrips, elapsed))
421 424 msg = ('found %d common and %d unknown server heads,'
422 425 ' %d roundtrips in %.4fs\n')
423 426 missing = set(result) - set(knownsrvheads)
424 427 ui.log('discovery', msg, len(result), len(missing), roundtrips,
425 428 elapsed)
426 429
427 430 if not result and srvheadhashes != [nullid]:
428 431 if abortwhenunrelated:
429 432 raise error.Abort(_("repository is unrelated"))
430 433 else:
431 434 ui.warn(_("warning: repository is unrelated\n"))
432 435 return ({nullid}, True, srvheadhashes,)
433 436
434 437 anyincoming = (srvheadhashes != [nullid])
435 438 result = {clnode(r) for r in result}
436 439 return result, anyincoming, srvheadhashes
@@ -1,1118 +1,1118
1 1
2 2 Function to test discovery between two repos in both directions, using both the local shortcut
3 3 (which is currently not activated by default) and the full remotable protocol:
4 4
5 5 $ testdesc() { # revs_a, revs_b, dagdesc
6 6 > if [ -d foo ]; then rm -rf foo; fi
7 7 > hg init foo
8 8 > cd foo
9 9 > hg debugbuilddag "$3"
10 10 > hg clone . a $1 --quiet
11 11 > hg clone . b $2 --quiet
12 12 > echo
13 13 > echo "% -- a -> b tree"
14 14 > hg -R a debugdiscovery b --verbose --old
15 15 > echo
16 16 > echo "% -- a -> b set"
17 17 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true
18 18 > echo
19 19 > echo "% -- a -> b set (tip only)"
20 20 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true --rev tip
21 21 > echo
22 22 > echo "% -- b -> a tree"
23 23 > hg -R b debugdiscovery a --verbose --old
24 24 > echo
25 25 > echo "% -- b -> a set"
26 26 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true
27 27 > echo
28 28 > echo "% -- b -> a set (tip only)"
29 29 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true --rev tip
30 30 > cd ..
31 31 > }
32 32
33 33
34 34 Small superset:
35 35
36 36 $ testdesc '-ra1 -ra2' '-rb1 -rb2 -rb3' '
37 37 > +2:f +1:a1:b1
38 38 > <f +4 :a2
39 39 > +5 :b2
40 40 > <f +3 :b3'
41 41
42 42 % -- a -> b tree
43 43 comparing with b
44 44 searching for changes
45 45 unpruned common: 01241442b3c2 66f7d451a68b b5714e113bc0
46 46 elapsed time: * seconds (glob)
47 47 heads summary:
48 48 total common heads: 2
49 49 also local heads: 2
50 50 also remote heads: 1
51 51 both: 1
52 52 local heads: 2
53 53 common: 2
54 54 missing: 0
55 55 remote heads: 3
56 56 common: 1
57 57 unknown: 2
58 58 local changesets: 7
59 59 common: 7
60 60 missing: 0
61 61 common heads: 01241442b3c2 b5714e113bc0
62 62
63 63 % -- a -> b set
64 64 comparing with b
65 65 query 1; heads
66 66 searching for changes
67 67 all local heads known remotely
68 68 elapsed time: * seconds (glob)
69 69 heads summary:
70 70 total common heads: 2
71 71 also local heads: 2
72 72 also remote heads: 1
73 73 both: 1
74 74 local heads: 2
75 75 common: 2
76 76 missing: 0
77 77 remote heads: 3
78 78 common: 1
79 79 unknown: 2
80 80 local changesets: 7
81 81 common: 7
82 82 missing: 0
83 83 common heads: 01241442b3c2 b5714e113bc0
84 84
85 85 % -- a -> b set (tip only)
86 86 comparing with b
87 87 query 1; heads
88 88 searching for changes
89 89 all local heads known remotely
90 90 elapsed time: * seconds (glob)
91 91 heads summary:
92 92 total common heads: 1
93 93 also local heads: 1
94 94 also remote heads: 0
95 95 both: 0
96 96 local heads: 2
97 97 common: 1
98 98 missing: 1
99 99 remote heads: 3
100 100 common: 0
101 101 unknown: 3
102 102 local changesets: 7
103 103 common: 6
104 104 missing: 1
105 105 common heads: b5714e113bc0
106 106
107 107 % -- b -> a tree
108 108 comparing with a
109 109 searching for changes
110 110 unpruned common: 01241442b3c2 b5714e113bc0
111 111 elapsed time: * seconds (glob)
112 112 heads summary:
113 113 total common heads: 2
114 114 also local heads: 1
115 115 also remote heads: 2
116 116 both: 1
117 117 local heads: 3
118 118 common: 1
119 119 missing: 2
120 120 remote heads: 2
121 121 common: 2
122 122 unknown: 0
123 123 local changesets: 15
124 124 common: 7
125 125 missing: 8
126 126 common heads: 01241442b3c2 b5714e113bc0
127 127
128 128 % -- b -> a set
129 129 comparing with a
130 130 query 1; heads
131 131 searching for changes
132 132 all remote heads known locally
133 133 elapsed time: * seconds (glob)
134 134 heads summary:
135 135 total common heads: 2
136 136 also local heads: 1
137 137 also remote heads: 2
138 138 both: 1
139 139 local heads: 3
140 140 common: 1
141 141 missing: 2
142 142 remote heads: 2
143 143 common: 2
144 144 unknown: 0
145 145 local changesets: 15
146 146 common: 7
147 147 missing: 8
148 148 common heads: 01241442b3c2 b5714e113bc0
149 149
150 150 % -- b -> a set (tip only)
151 151 comparing with a
152 152 query 1; heads
153 153 searching for changes
154 154 all remote heads known locally
155 155 elapsed time: * seconds (glob)
156 156 heads summary:
157 157 total common heads: 2
158 158 also local heads: 1
159 159 also remote heads: 2
160 160 both: 1
161 161 local heads: 3
162 162 common: 1
163 163 missing: 2
164 164 remote heads: 2
165 165 common: 2
166 166 unknown: 0
167 167 local changesets: 15
168 168 common: 7
169 169 missing: 8
170 170 common heads: 01241442b3c2 b5714e113bc0
171 171
172 172
173 173 Many new:
174 174
175 175 $ testdesc '-ra1 -ra2' '-rb' '
176 176 > +2:f +3:a1 +3:b
177 177 > <f +30 :a2'
178 178
179 179 % -- a -> b tree
180 180 comparing with b
181 181 searching for changes
182 182 unpruned common: bebd167eb94d
183 183 elapsed time: * seconds (glob)
184 184 heads summary:
185 185 total common heads: 1
186 186 also local heads: 1
187 187 also remote heads: 0
188 188 both: 0
189 189 local heads: 2
190 190 common: 1
191 191 missing: 1
192 192 remote heads: 1
193 193 common: 0
194 194 unknown: 1
195 195 local changesets: 35
196 196 common: 5
197 197 missing: 30
198 198 common heads: bebd167eb94d
199 199
200 200 % -- a -> b set
201 201 comparing with b
202 202 query 1; heads
203 203 searching for changes
204 204 taking initial sample
205 205 searching: 2 queries
206 206 query 2; still undecided: 29, sample size is: 29
207 207 2 total queries in *.????s (glob)
208 208 elapsed time: * seconds (glob)
209 209 heads summary:
210 210 total common heads: 1
211 211 also local heads: 1
212 212 also remote heads: 0
213 213 both: 0
214 214 local heads: 2
215 215 common: 1
216 216 missing: 1
217 217 remote heads: 1
218 218 common: 0
219 219 unknown: 1
220 220 local changesets: 35
221 221 common: 5
222 222 missing: 30
223 223 common heads: bebd167eb94d
224 224
225 225 % -- a -> b set (tip only)
226 226 comparing with b
227 227 query 1; heads
228 228 searching for changes
229 229 taking quick initial sample
230 230 searching: 2 queries
231 231 query 2; still undecided: 31, sample size is: 31
232 232 2 total queries in *.????s (glob)
233 233 elapsed time: * seconds (glob)
234 234 heads summary:
235 235 total common heads: 1
236 236 also local heads: 0
237 237 also remote heads: 0
238 238 both: 0
239 239 local heads: 2
240 240 common: 0
241 241 missing: 2
242 242 remote heads: 1
243 243 common: 0
244 244 unknown: 1
245 245 local changesets: 35
246 246 common: 2
247 247 missing: 33
248 248 common heads: 66f7d451a68b
249 249
250 250 % -- b -> a tree
251 251 comparing with a
252 252 searching for changes
253 253 unpruned common: 66f7d451a68b bebd167eb94d
254 254 elapsed time: * seconds (glob)
255 255 heads summary:
256 256 total common heads: 1
257 257 also local heads: 0
258 258 also remote heads: 1
259 259 both: 0
260 260 local heads: 1
261 261 common: 0
262 262 missing: 1
263 263 remote heads: 2
264 264 common: 1
265 265 unknown: 1
266 266 local changesets: 8
267 267 common: 5
268 268 missing: 3
269 269 common heads: bebd167eb94d
270 270
271 271 % -- b -> a set
272 272 comparing with a
273 273 query 1; heads
274 274 searching for changes
275 275 taking initial sample
276 276 searching: 2 queries
277 277 query 2; still undecided: 2, sample size is: 2
278 278 2 total queries in *.????s (glob)
279 279 elapsed time: * seconds (glob)
280 280 heads summary:
281 281 total common heads: 1
282 282 also local heads: 0
283 283 also remote heads: 1
284 284 both: 0
285 285 local heads: 1
286 286 common: 0
287 287 missing: 1
288 288 remote heads: 2
289 289 common: 1
290 290 unknown: 1
291 291 local changesets: 8
292 292 common: 5
293 293 missing: 3
294 294 common heads: bebd167eb94d
295 295
296 296 % -- b -> a set (tip only)
297 297 comparing with a
298 298 query 1; heads
299 299 searching for changes
300 300 taking initial sample
301 301 searching: 2 queries
302 302 query 2; still undecided: 2, sample size is: 2
303 303 2 total queries in *.????s (glob)
304 304 elapsed time: * seconds (glob)
305 305 heads summary:
306 306 total common heads: 1
307 307 also local heads: 0
308 308 also remote heads: 1
309 309 both: 0
310 310 local heads: 1
311 311 common: 0
312 312 missing: 1
313 313 remote heads: 2
314 314 common: 1
315 315 unknown: 1
316 316 local changesets: 8
317 317 common: 5
318 318 missing: 3
319 319 common heads: bebd167eb94d
320 320
321 321 Both sides many new with stub:
322 322
323 323 $ testdesc '-ra1 -ra2' '-rb' '
324 324 > +2:f +2:a1 +30 :b
325 325 > <f +30 :a2'
326 326
327 327 % -- a -> b tree
328 328 comparing with b
329 329 searching for changes
330 330 unpruned common: 2dc09a01254d
331 331 elapsed time: * seconds (glob)
332 332 heads summary:
333 333 total common heads: 1
334 334 also local heads: 1
335 335 also remote heads: 0
336 336 both: 0
337 337 local heads: 2
338 338 common: 1
339 339 missing: 1
340 340 remote heads: 1
341 341 common: 0
342 342 unknown: 1
343 343 local changesets: 34
344 344 common: 4
345 345 missing: 30
346 346 common heads: 2dc09a01254d
347 347
348 348 % -- a -> b set
349 349 comparing with b
350 350 query 1; heads
351 351 searching for changes
352 352 taking initial sample
353 353 searching: 2 queries
354 354 query 2; still undecided: 29, sample size is: 29
355 355 2 total queries in *.????s (glob)
356 356 elapsed time: * seconds (glob)
357 357 heads summary:
358 358 total common heads: 1
359 359 also local heads: 1
360 360 also remote heads: 0
361 361 both: 0
362 362 local heads: 2
363 363 common: 1
364 364 missing: 1
365 365 remote heads: 1
366 366 common: 0
367 367 unknown: 1
368 368 local changesets: 34
369 369 common: 4
370 370 missing: 30
371 371 common heads: 2dc09a01254d
372 372
373 373 % -- a -> b set (tip only)
374 374 comparing with b
375 375 query 1; heads
376 376 searching for changes
377 377 taking quick initial sample
378 378 searching: 2 queries
379 379 query 2; still undecided: 31, sample size is: 31
380 380 2 total queries in *.????s (glob)
381 381 elapsed time: * seconds (glob)
382 382 heads summary:
383 383 total common heads: 1
384 384 also local heads: 0
385 385 also remote heads: 0
386 386 both: 0
387 387 local heads: 2
388 388 common: 0
389 389 missing: 2
390 390 remote heads: 1
391 391 common: 0
392 392 unknown: 1
393 393 local changesets: 34
394 394 common: 2
395 395 missing: 32
396 396 common heads: 66f7d451a68b
397 397
398 398 % -- b -> a tree
399 399 comparing with a
400 400 searching for changes
401 401 unpruned common: 2dc09a01254d 66f7d451a68b
402 402 elapsed time: * seconds (glob)
403 403 heads summary:
404 404 total common heads: 1
405 405 also local heads: 0
406 406 also remote heads: 1
407 407 both: 0
408 408 local heads: 1
409 409 common: 0
410 410 missing: 1
411 411 remote heads: 2
412 412 common: 1
413 413 unknown: 1
414 414 local changesets: 34
415 415 common: 4
416 416 missing: 30
417 417 common heads: 2dc09a01254d
418 418
419 419 % -- b -> a set
420 420 comparing with a
421 421 query 1; heads
422 422 searching for changes
423 423 taking initial sample
424 424 searching: 2 queries
425 425 query 2; still undecided: 29, sample size is: 29
426 426 2 total queries in *.????s (glob)
427 427 elapsed time: * seconds (glob)
428 428 heads summary:
429 429 total common heads: 1
430 430 also local heads: 0
431 431 also remote heads: 1
432 432 both: 0
433 433 local heads: 1
434 434 common: 0
435 435 missing: 1
436 436 remote heads: 2
437 437 common: 1
438 438 unknown: 1
439 439 local changesets: 34
440 440 common: 4
441 441 missing: 30
442 442 common heads: 2dc09a01254d
443 443
444 444 % -- b -> a set (tip only)
445 445 comparing with a
446 446 query 1; heads
447 447 searching for changes
448 448 taking initial sample
449 449 searching: 2 queries
450 450 query 2; still undecided: 29, sample size is: 29
451 451 2 total queries in *.????s (glob)
452 452 elapsed time: * seconds (glob)
453 453 heads summary:
454 454 total common heads: 1
455 455 also local heads: 0
456 456 also remote heads: 1
457 457 both: 0
458 458 local heads: 1
459 459 common: 0
460 460 missing: 1
461 461 remote heads: 2
462 462 common: 1
463 463 unknown: 1
464 464 local changesets: 34
465 465 common: 4
466 466 missing: 30
467 467 common heads: 2dc09a01254d
468 468
469 469
470 470 Both many new:
471 471
472 472 $ testdesc '-ra' '-rb' '
473 473 > +2:f +30 :b
474 474 > <f +30 :a'
475 475
476 476 % -- a -> b tree
477 477 comparing with b
478 478 searching for changes
479 479 unpruned common: 66f7d451a68b
480 480 elapsed time: * seconds (glob)
481 481 heads summary:
482 482 total common heads: 1
483 483 also local heads: 0
484 484 also remote heads: 0
485 485 both: 0
486 486 local heads: 1
487 487 common: 0
488 488 missing: 1
489 489 remote heads: 1
490 490 common: 0
491 491 unknown: 1
492 492 local changesets: 32
493 493 common: 2
494 494 missing: 30
495 495 common heads: 66f7d451a68b
496 496
497 497 % -- a -> b set
498 498 comparing with b
499 499 query 1; heads
500 500 searching for changes
501 501 taking quick initial sample
502 502 searching: 2 queries
503 503 query 2; still undecided: 31, sample size is: 31
504 504 2 total queries in *.????s (glob)
505 505 elapsed time: * seconds (glob)
506 506 heads summary:
507 507 total common heads: 1
508 508 also local heads: 0
509 509 also remote heads: 0
510 510 both: 0
511 511 local heads: 1
512 512 common: 0
513 513 missing: 1
514 514 remote heads: 1
515 515 common: 0
516 516 unknown: 1
517 517 local changesets: 32
518 518 common: 2
519 519 missing: 30
520 520 common heads: 66f7d451a68b
521 521
522 522 % -- a -> b set (tip only)
523 523 comparing with b
524 524 query 1; heads
525 525 searching for changes
526 526 taking quick initial sample
527 527 searching: 2 queries
528 528 query 2; still undecided: 31, sample size is: 31
529 529 2 total queries in *.????s (glob)
530 530 elapsed time: * seconds (glob)
531 531 heads summary:
532 532 total common heads: 1
533 533 also local heads: 0
534 534 also remote heads: 0
535 535 both: 0
536 536 local heads: 1
537 537 common: 0
538 538 missing: 1
539 539 remote heads: 1
540 540 common: 0
541 541 unknown: 1
542 542 local changesets: 32
543 543 common: 2
544 544 missing: 30
545 545 common heads: 66f7d451a68b
546 546
547 547 % -- b -> a tree
548 548 comparing with a
549 549 searching for changes
550 550 unpruned common: 66f7d451a68b
551 551 elapsed time: * seconds (glob)
552 552 heads summary:
553 553 total common heads: 1
554 554 also local heads: 0
555 555 also remote heads: 0
556 556 both: 0
557 557 local heads: 1
558 558 common: 0
559 559 missing: 1
560 560 remote heads: 1
561 561 common: 0
562 562 unknown: 1
563 563 local changesets: 32
564 564 common: 2
565 565 missing: 30
566 566 common heads: 66f7d451a68b
567 567
568 568 % -- b -> a set
569 569 comparing with a
570 570 query 1; heads
571 571 searching for changes
572 572 taking quick initial sample
573 573 searching: 2 queries
574 574 query 2; still undecided: 31, sample size is: 31
575 575 2 total queries in *.????s (glob)
576 576 elapsed time: * seconds (glob)
577 577 heads summary:
578 578 total common heads: 1
579 579 also local heads: 0
580 580 also remote heads: 0
581 581 both: 0
582 582 local heads: 1
583 583 common: 0
584 584 missing: 1
585 585 remote heads: 1
586 586 common: 0
587 587 unknown: 1
588 588 local changesets: 32
589 589 common: 2
590 590 missing: 30
591 591 common heads: 66f7d451a68b
592 592
593 593 % -- b -> a set (tip only)
594 594 comparing with a
595 595 query 1; heads
596 596 searching for changes
597 597 taking quick initial sample
598 598 searching: 2 queries
599 599 query 2; still undecided: 31, sample size is: 31
600 600 2 total queries in *.????s (glob)
601 601 elapsed time: * seconds (glob)
602 602 heads summary:
603 603 total common heads: 1
604 604 also local heads: 0
605 605 also remote heads: 0
606 606 both: 0
607 607 local heads: 1
608 608 common: 0
609 609 missing: 1
610 610 remote heads: 1
611 611 common: 0
612 612 unknown: 1
613 613 local changesets: 32
614 614 common: 2
615 615 missing: 30
616 616 common heads: 66f7d451a68b
617 617
618 618
619 619 Both many new skewed:
620 620
621 621 $ testdesc '-ra' '-rb' '
622 622 > +2:f +30 :b
623 623 > <f +50 :a'
624 624
625 625 % -- a -> b tree
626 626 comparing with b
627 627 searching for changes
628 628 unpruned common: 66f7d451a68b
629 629 elapsed time: * seconds (glob)
630 630 heads summary:
631 631 total common heads: 1
632 632 also local heads: 0
633 633 also remote heads: 0
634 634 both: 0
635 635 local heads: 1
636 636 common: 0
637 637 missing: 1
638 638 remote heads: 1
639 639 common: 0
640 640 unknown: 1
641 641 local changesets: 52
642 642 common: 2
643 643 missing: 50
644 644 common heads: 66f7d451a68b
645 645
646 646 % -- a -> b set
647 647 comparing with b
648 648 query 1; heads
649 649 searching for changes
650 650 taking quick initial sample
651 651 searching: 2 queries
652 652 query 2; still undecided: 51, sample size is: 51
653 653 2 total queries in *.????s (glob)
654 654 elapsed time: * seconds (glob)
655 655 heads summary:
656 656 total common heads: 1
657 657 also local heads: 0
658 658 also remote heads: 0
659 659 both: 0
660 660 local heads: 1
661 661 common: 0
662 662 missing: 1
663 663 remote heads: 1
664 664 common: 0
665 665 unknown: 1
666 666 local changesets: 52
667 667 common: 2
668 668 missing: 50
669 669 common heads: 66f7d451a68b
670 670
671 671 % -- a -> b set (tip only)
672 672 comparing with b
673 673 query 1; heads
674 674 searching for changes
675 675 taking quick initial sample
676 676 searching: 2 queries
677 677 query 2; still undecided: 51, sample size is: 51
678 678 2 total queries in *.????s (glob)
679 679 elapsed time: * seconds (glob)
680 680 heads summary:
681 681 total common heads: 1
682 682 also local heads: 0
683 683 also remote heads: 0
684 684 both: 0
685 685 local heads: 1
686 686 common: 0
687 687 missing: 1
688 688 remote heads: 1
689 689 common: 0
690 690 unknown: 1
691 691 local changesets: 52
692 692 common: 2
693 693 missing: 50
694 694 common heads: 66f7d451a68b
695 695
696 696 % -- b -> a tree
697 697 comparing with a
698 698 searching for changes
699 699 unpruned common: 66f7d451a68b
700 700 elapsed time: * seconds (glob)
701 701 heads summary:
702 702 total common heads: 1
703 703 also local heads: 0
704 704 also remote heads: 0
705 705 both: 0
706 706 local heads: 1
707 707 common: 0
708 708 missing: 1
709 709 remote heads: 1
710 710 common: 0
711 711 unknown: 1
712 712 local changesets: 32
713 713 common: 2
714 714 missing: 30
715 715 common heads: 66f7d451a68b
716 716
717 717 % -- b -> a set
718 718 comparing with a
719 719 query 1; heads
720 720 searching for changes
721 721 taking quick initial sample
722 722 searching: 2 queries
723 723 query 2; still undecided: 31, sample size is: 31
724 724 2 total queries in *.????s (glob)
725 725 elapsed time: * seconds (glob)
726 726 heads summary:
727 727 total common heads: 1
728 728 also local heads: 0
729 729 also remote heads: 0
730 730 both: 0
731 731 local heads: 1
732 732 common: 0
733 733 missing: 1
734 734 remote heads: 1
735 735 common: 0
736 736 unknown: 1
737 737 local changesets: 32
738 738 common: 2
739 739 missing: 30
740 740 common heads: 66f7d451a68b
741 741
742 742 % -- b -> a set (tip only)
743 743 comparing with a
744 744 query 1; heads
745 745 searching for changes
746 746 taking quick initial sample
747 747 searching: 2 queries
748 748 query 2; still undecided: 31, sample size is: 31
749 749 2 total queries in *.????s (glob)
750 750 elapsed time: * seconds (glob)
751 751 heads summary:
752 752 total common heads: 1
753 753 also local heads: 0
754 754 also remote heads: 0
755 755 both: 0
756 756 local heads: 1
757 757 common: 0
758 758 missing: 1
759 759 remote heads: 1
760 760 common: 0
761 761 unknown: 1
762 762 local changesets: 32
763 763 common: 2
764 764 missing: 30
765 765 common heads: 66f7d451a68b
766 766
767 767
768 768 Both many new on top of long history:
769 769
770 770 $ testdesc '-ra' '-rb' '
771 771 > +1000:f +30 :b
772 772 > <f +50 :a'
773 773
774 774 % -- a -> b tree
775 775 comparing with b
776 776 searching for changes
777 777 unpruned common: 7ead0cba2838
778 778 elapsed time: * seconds (glob)
779 779 heads summary:
780 780 total common heads: 1
781 781 also local heads: 0
782 782 also remote heads: 0
783 783 both: 0
784 784 local heads: 1
785 785 common: 0
786 786 missing: 1
787 787 remote heads: 1
788 788 common: 0
789 789 unknown: 1
790 790 local changesets: 1050
791 791 common: 1000
792 792 missing: 50
793 793 common heads: 7ead0cba2838
794 794
795 795 % -- a -> b set
796 796 comparing with b
797 797 query 1; heads
798 798 searching for changes
799 799 taking quick initial sample
800 800 searching: 2 queries
801 801 query 2; still undecided: 1049, sample size is: 11
802 802 sampling from both directions
803 803 searching: 3 queries
804 804 query 3; still undecided: 31, sample size is: 31
805 805 3 total queries in *.????s (glob)
806 806 elapsed time: * seconds (glob)
807 807 heads summary:
808 808 total common heads: 1
809 809 also local heads: 0
810 810 also remote heads: 0
811 811 both: 0
812 812 local heads: 1
813 813 common: 0
814 814 missing: 1
815 815 remote heads: 1
816 816 common: 0
817 817 unknown: 1
818 818 local changesets: 1050
819 819 common: 1000
820 820 missing: 50
821 821 common heads: 7ead0cba2838
822 822
823 823 % -- a -> b set (tip only)
824 824 comparing with b
825 825 query 1; heads
826 826 searching for changes
827 827 taking quick initial sample
828 828 searching: 2 queries
829 829 query 2; still undecided: 1049, sample size is: 11
830 830 sampling from both directions
831 831 searching: 3 queries
832 832 query 3; still undecided: 31, sample size is: 31
833 833 3 total queries in *.????s (glob)
834 834 elapsed time: * seconds (glob)
835 835 heads summary:
836 836 total common heads: 1
837 837 also local heads: 0
838 838 also remote heads: 0
839 839 both: 0
840 840 local heads: 1
841 841 common: 0
842 842 missing: 1
843 843 remote heads: 1
844 844 common: 0
845 845 unknown: 1
846 846 local changesets: 1050
847 847 common: 1000
848 848 missing: 50
849 849 common heads: 7ead0cba2838
850 850
851 851 % -- b -> a tree
852 852 comparing with a
853 853 searching for changes
854 854 unpruned common: 7ead0cba2838
855 855 elapsed time: * seconds (glob)
856 856 heads summary:
857 857 total common heads: 1
858 858 also local heads: 0
859 859 also remote heads: 0
860 860 both: 0
861 861 local heads: 1
862 862 common: 0
863 863 missing: 1
864 864 remote heads: 1
865 865 common: 0
866 866 unknown: 1
867 867 local changesets: 1030
868 868 common: 1000
869 869 missing: 30
870 870 common heads: 7ead0cba2838
871 871
872 872 % -- b -> a set
873 873 comparing with a
874 874 query 1; heads
875 875 searching for changes
876 876 taking quick initial sample
877 877 searching: 2 queries
878 878 query 2; still undecided: 1029, sample size is: 11
879 879 sampling from both directions
880 880 searching: 3 queries
881 881 query 3; still undecided: 15, sample size is: 15
882 882 3 total queries in *.????s (glob)
883 883 elapsed time: * seconds (glob)
884 884 heads summary:
885 885 total common heads: 1
886 886 also local heads: 0
887 887 also remote heads: 0
888 888 both: 0
889 889 local heads: 1
890 890 common: 0
891 891 missing: 1
892 892 remote heads: 1
893 893 common: 0
894 894 unknown: 1
895 895 local changesets: 1030
896 896 common: 1000
897 897 missing: 30
898 898 common heads: 7ead0cba2838
899 899
900 900 % -- b -> a set (tip only)
901 901 comparing with a
902 902 query 1; heads
903 903 searching for changes
904 904 taking quick initial sample
905 905 searching: 2 queries
906 906 query 2; still undecided: 1029, sample size is: 11
907 907 sampling from both directions
908 908 searching: 3 queries
909 909 query 3; still undecided: 15, sample size is: 15
910 910 3 total queries in *.????s (glob)
911 911 elapsed time: * seconds (glob)
912 912 heads summary:
913 913 total common heads: 1
914 914 also local heads: 0
915 915 also remote heads: 0
916 916 both: 0
917 917 local heads: 1
918 918 common: 0
919 919 missing: 1
920 920 remote heads: 1
921 921 common: 0
922 922 unknown: 1
923 923 local changesets: 1030
924 924 common: 1000
925 925 missing: 30
926 926 common heads: 7ead0cba2838
927 927
928 928
929 929 One with >200 heads. We now switch to send them all in the initial roundtrip, but still do sampling for the later request.
930 930
931 931 $ hg init manyheads
932 932 $ cd manyheads
933 933 $ echo "+300:r @a" >dagdesc
934 934 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
935 935 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
936 936 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
937 937 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
938 938 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
939 939 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
940 940 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
941 941 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
942 942 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
943 943 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
944 944 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
945 945 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
946 946 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
947 947 $ echo "@b *r+3" >>dagdesc # one more head
948 948 $ hg debugbuilddag <dagdesc
949 949 reading DAG from stdin
950 950
951 951 $ hg heads -t --template . | wc -c
952 952 \s*261 (re)
953 953
954 954 $ hg clone -b a . a
955 955 adding changesets
956 956 adding manifests
957 957 adding file changes
958 958 added 1340 changesets with 0 changes to 0 files (+259 heads)
959 959 new changesets 1ea73414a91b:1c51e2c80832
960 960 updating to branch a
961 961 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
962 962 $ hg clone -b b . b
963 963 adding changesets
964 964 adding manifests
965 965 adding file changes
966 966 added 304 changesets with 0 changes to 0 files
967 967 new changesets 1ea73414a91b:513314ca8b3a
968 968 updating to branch b
969 969 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
970 970
971 971 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true
972 972 comparing with b
973 973 query 1; heads
974 974 searching for changes
975 975 taking quick initial sample
976 976 searching: 2 queries
977 977 query 2; still undecided: 1080, sample size is: 100
978 978 sampling from both directions
979 979 searching: 3 queries
980 980 query 3; still undecided: 980, sample size is: 200
981 981 sampling from both directions
982 982 searching: 4 queries
983 query 4; still undecided: \d+, sample size is: 200 (re)
983 query 4; still undecided: 435, sample size is: 210
984 984 sampling from both directions
985 985 searching: 5 queries
986 query 5; still undecided: 195, sample size is: 195
986 query 5; still undecided: 185, sample size is: 185
987 987 5 total queries in *.????s (glob)
988 988 elapsed time: * seconds (glob)
989 989 heads summary:
990 990 total common heads: 1
991 991 also local heads: 0
992 992 also remote heads: 0
993 993 both: 0
994 994 local heads: 260
995 995 common: 0
996 996 missing: 260
997 997 remote heads: 1
998 998 common: 0
999 999 unknown: 1
1000 1000 local changesets: 1340
1001 1001 common: 300
1002 1002 missing: 1040
1003 1003 common heads: 3ee37d65064a
1004 1004 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true --rev tip
1005 1005 comparing with b
1006 1006 query 1; heads
1007 1007 searching for changes
1008 1008 taking quick initial sample
1009 1009 searching: 2 queries
1010 1010 query 2; still undecided: 303, sample size is: 9
1011 1011 sampling from both directions
1012 1012 searching: 3 queries
1013 1013 query 3; still undecided: 3, sample size is: 3
1014 1014 3 total queries in *.????s (glob)
1015 1015 elapsed time: * seconds (glob)
1016 1016 heads summary:
1017 1017 total common heads: 1
1018 1018 also local heads: 0
1019 1019 also remote heads: 0
1020 1020 both: 0
1021 1021 local heads: 260
1022 1022 common: 0
1023 1023 missing: 260
1024 1024 remote heads: 1
1025 1025 common: 0
1026 1026 unknown: 1
1027 1027 local changesets: 1340
1028 1028 common: 300
1029 1029 missing: 1040
1030 1030 common heads: 3ee37d65064a
1031 1031
1032 1032 Test actual protocol when pulling one new head in addition to common heads
1033 1033
1034 1034 $ hg clone -U b c
1035 1035 $ hg -R c id -ir tip
1036 1036 513314ca8b3a
1037 1037 $ hg -R c up -qr default
1038 1038 $ touch c/f
1039 1039 $ hg -R c ci -Aqm "extra head"
1040 1040 $ hg -R c id -i
1041 1041 e64a39e7da8b
1042 1042
1043 1043 $ hg serve -R c -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1044 1044 $ cat hg.pid >> $DAEMON_PIDS
1045 1045
1046 1046 $ hg -R b incoming http://localhost:$HGPORT/ -T '{node|short}\n'
1047 1047 comparing with http://localhost:$HGPORT/
1048 1048 searching for changes
1049 1049 e64a39e7da8b
1050 1050
1051 1051 $ killdaemons.py
1052 1052 $ cut -d' ' -f6- access.log | grep -v cmd=known # cmd=known uses random sampling
1053 1053 "GET /?cmd=capabilities HTTP/1.1" 200 -
1054 1054 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D513314ca8b3ae4dac8eec56966265b00fcf866db x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1055 1055 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:$USUAL_BUNDLE_CAPS$&cg=1&common=513314ca8b3ae4dac8eec56966265b00fcf866db&heads=e64a39e7da8b0d54bc63e81169aff001c13b3477 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1056 1056 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1057 1057 $ cat errors.log
1058 1058
1059 1059 $ cd ..
1060 1060
1061 1061
1062 1062 Issue 4438 - test coverage for 3ef893520a85 issues.
1063 1063
1064 1064 $ mkdir issue4438
1065 1065 $ cd issue4438
1066 1066 #if false
1067 1067 generate new bundles:
1068 1068 $ hg init r1
1069 1069 $ for i in `"$PYTHON" $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
1070 1070 $ hg clone -q r1 r2
1071 1071 $ for i in `"$PYTHON" $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
1072 1072 $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change
1073 1073 $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg
1074 1074 $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg
1075 1075 #else
1076 1076 use existing bundles:
1077 1077 $ hg init r1
1078 1078 $ hg -R r1 -q unbundle $TESTDIR/bundles/issue4438-r1.hg
1079 1079 $ hg -R r1 -q up
1080 1080 $ hg init r2
1081 1081 $ hg -R r2 -q unbundle $TESTDIR/bundles/issue4438-r2.hg
1082 1082 $ hg -R r2 -q up
1083 1083 #endif
1084 1084
1085 1085 Set iteration order could cause wrong and unstable results - fixed in 73cfaa348650:
1086 1086
1087 1087 $ hg -R r1 outgoing r2 -T'{rev} '
1088 1088 comparing with r2
1089 1089 searching for changes
1090 1090 101 102 103 104 105 106 107 108 109 110 (no-eol)
1091 1091
1092 1092 The case where all the 'initialsamplesize' samples already were common would
1093 1093 give 'all remote heads known locally' without checking the remaining heads -
1094 1094 fixed in 86c35b7ae300:
1095 1095
1096 1096 $ cat >> $TESTTMP/unrandomsample.py << EOF
1097 1097 > import random
1098 1098 > def sample(population, k):
1099 1099 > return sorted(population)[:k]
1100 1100 > random.sample = sample
1101 1101 > EOF
1102 1102
1103 1103 $ cat >> r1/.hg/hgrc << EOF
1104 1104 > [extensions]
1105 1105 > unrandomsample = $TESTTMP/unrandomsample.py
1106 1106 > EOF
1107 1107
1108 1108 $ hg -R r1 outgoing r2 -T'{rev} ' --config extensions.blackbox= \
1109 1109 > --config blackbox.track='command commandfinish discovery'
1110 1110 comparing with r2
1111 1111 searching for changes
1112 1112 101 102 103 104 105 106 107 108 109 110 (no-eol)
1113 1113 $ hg -R r1 --config extensions.blackbox= blackbox --config blackbox.track=
1114 1114 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> serve --cmdserver chgunix * (glob) (chg !)
1115 1115 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* (glob)
1116 1116 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> found 101 common and 1 unknown server heads, 1 roundtrips in *.????s (glob)
1117 1117 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* exited 0 after *.?? seconds (glob)
1118 1118 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now