comparison mercurial/obsutil.py @ 33274:68f3e819d41d

obsolete: closest divergent support Add a closest argument to successorssets changing the definition of latest successors. With "closest=false" (current behavior), latest successors are "leafs" on the obsmarker graph. They don't have any successor and are known locally. With "closest=true", latest successors are the closest locally-known changesets that are visible in the repository or repoview. Closest successors can be then obsolete, orphan. This will be used in a later patch to show the closest successor of changesets with the successorssets template.
author Boris Feld <boris.feld@octobus.net>
date Fri, 30 Jun 2017 15:27:19 +0200
parents df90f4d6c609
children 888f24810ea2
comparison
equal deleted inserted replaced
33273:5724aaa99dd6 33274:68f3e819d41d
309 continue 309 continue
310 if set(succsmarkers(node)).issubset(addedmarkers): 310 if set(succsmarkers(node)).issubset(addedmarkers):
311 obsoleted.add(rev) 311 obsoleted.add(rev)
312 return obsoleted 312 return obsoleted
313 313
314 def successorssets(repo, initialnode, cache=None): 314 def successorssets(repo, initialnode, closest=False, cache=None):
315 """Return set of all latest successors of initial nodes 315 """Return set of all latest successors of initial nodes
316 316
317 The successors set of a changeset A are the group of revisions that succeed 317 The successors set of a changeset A are the group of revisions that succeed
318 A. It succeeds A as a consistent whole, each revision being only a partial 318 A. It succeeds A as a consistent whole, each revision being only a partial
319 replacement. The successors set contains non-obsolete changesets only. 319 replacement. By default, the successors set contains non-obsolete
320 changesets only, walking the obsolescence graph until reaching a leaf. If
321 'closest' is set to True, closest successors-sets are return (the
322 obsolescence walk stops on known changesets).
320 323
321 This function returns the full list of successor sets which is why it 324 This function returns the full list of successor sets which is why it
322 returns a list of tuples and not just a single tuple. Each tuple is a valid 325 returns a list of tuples and not just a single tuple. Each tuple is a valid
323 successors set. Note that (A,) may be a valid successors set for changeset A 326 successors set. Note that (A,) may be a valid successors set for changeset A
324 (see below). 327 (see below).
339 set will contain itself only, i.e. [(A,)]. 342 set will contain itself only, i.e. [(A,)].
340 343
341 Finally, final successors unknown locally are considered to be pruned 344 Finally, final successors unknown locally are considered to be pruned
342 (pruned: obsoleted without any successors). (Final: successors not affected 345 (pruned: obsoleted without any successors). (Final: successors not affected
343 by markers). 346 by markers).
347
348 The 'closest' mode respect the repoview filtering. For example, without
349 filter it will stop at the first locally known changeset, with 'visible'
350 filter it will stop on visible changesets).
344 351
345 The optional `cache` parameter is a dictionary that may contains 352 The optional `cache` parameter is a dictionary that may contains
346 precomputed successors sets. It is meant to reuse the computation of a 353 precomputed successors sets. It is meant to reuse the computation of a
347 previous call to `successorssets` when multiple calls are made at the same 354 previous call to `successorssets` when multiple calls are made at the same
348 time. The cache dictionary is updated in place. The caller is responsible 355 time. The cache dictionary is updated in place. The caller is responsible
349 for its life span. Code that makes multiple calls to `successorssets` 356 for its life span. Code that makes multiple calls to `successorssets`
350 *should* use this cache mechanism or risk a performance hit. 357 *should* use this cache mechanism or risk a performance hit.
358
359 Since results are different depending of the 'closest' most, the same cache
360 cannot be reused for both mode.
351 """ 361 """
352 362
353 succmarkers = repo.obsstore.successors 363 succmarkers = repo.obsstore.successors
354 364
355 # Stack of nodes we search successors sets for 365 # Stack of nodes we search successors sets for
392 # 402 #
393 # There are four possible outcomes: 403 # There are four possible outcomes:
394 # 404 #
395 # 1) We already know the successors sets of CURRENT: 405 # 1) We already know the successors sets of CURRENT:
396 # -> mission accomplished, pop it from the stack. 406 # -> mission accomplished, pop it from the stack.
397 # 2) Node is not obsolete: 407 # 2) Stop the walk:
398 # -> the node is its own successors sets. Add it to the cache. 408 # default case: Node is not obsolete
409 # closest case: Node is known at this repo filter level
410 # -> the node is its own successors sets. Add it to the cache.
399 # 3) We do not know successors set of direct successors of CURRENT: 411 # 3) We do not know successors set of direct successors of CURRENT:
400 # -> We add those successors to the stack. 412 # -> We add those successors to the stack.
401 # 4) We know successors sets of all direct successors of CURRENT: 413 # 4) We know successors sets of all direct successors of CURRENT:
402 # -> We can compute CURRENT successors set and add it to the 414 # -> We can compute CURRENT successors set and add it to the
403 # cache. 415 # cache.
404 # 416 #
405 current = toproceed[-1] 417 current = toproceed[-1]
418
419 # case 2 condition is a bit hairy because of closest,
420 # we compute it on its own
421 case2condition = ((current not in succmarkers)
422 or (closest and current != initialnode
423 and current in repo))
424
406 if current in cache: 425 if current in cache:
407 # case (1): We already know the successors sets 426 # case (1): We already know the successors sets
408 stackedset.remove(toproceed.pop()) 427 stackedset.remove(toproceed.pop())
409 elif current not in succmarkers: 428 elif case2condition:
410 # case (2): The node is not obsolete. 429 # case (2): end of walk.
411 if current in repo: 430 if current in repo:
412 # We have a valid last successors. 431 # We have a valid successors.
413 cache[current] = [(current,)] 432 cache[current] = [(current,)]
414 else: 433 else:
415 # Final obsolete version is unknown locally. 434 # Final obsolete version is unknown locally.
416 # Do not count that as a valid successors 435 # Do not count that as a valid successors
417 cache[current] = [] 436 cache[current] = []