vcsreplicator: use `phaseroots` integer keys directly instead of implicit enumeration (Bug 1727344) r=zeid
authorConnor Sheehan <>
Tue, 24 Aug 2021 16:03:49 +0000
changeset 7725 46841c29ca44f651eda9ab2ff77adcbaa6238ff6
parent 7724 b9a13f98f0cf6d8533e67f63430a6409f673d0c8
child 7726 177006efefb39dca50b218119cdb14d69c000085
push id3863
push dateTue, 24 Aug 2021 16:05:52 +0000
treeherderversion-control-tools@177006efefb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
vcsreplicator: use `phaseroots` integer keys directly instead of implicit enumeration (Bug 1727344) r=zeid Mercurial internals formerly defined phases via an expansion of `range(3)`, mapping the phases to each integer. Internally the integers are used so the phases have an order (ie `draft < public`), but these phases are mapped to names that we use in the Mercurial command line. At some point new phases were added with their own unique values that break the `range(3)` standard. In `vcsreplicator` we would read the `phaseroots` dict and enumerate the keys to determine which phases are present on a given repo, however the presence of the new phases breaks this assumption. Since the `phaseroots` object is aleady a mapping of the phase integer representation to revision hash, we should use the keys of the `phaseroots` mapping directly to determine which phases are found on a given repo. Depends on D123481 Differential Revision:
--- a/pylib/vcsreplicator/vcsreplicator/
+++ b/pylib/vcsreplicator/vcsreplicator/
@@ -175,19 +175,22 @@ def phase_heads_handler(op, inpart):
         return _ORIG_PHASE_HEADS_HANDLER(op, inpart)
     # Else this looks like a push without a changegroup. (A phase only push.)
     # We monkeypatch the function for handling phase updates to record what
     # changes were made. Then we convert the changes into pushkey messages.
     # We make assumptions later that we only update from the draft phase. Double
     # check that the source repo doesn't have any secret, etc phase roots.
-    seen_phases = set(i for i, v
-                      in enumerate(op.repo.unfiltered()._phasecache.phaseroots)
-                      if v)
+    seen_phases = set(
+        phase
+        for phase, roots in
+        op.repo.unfiltered()._phasecache.phaseroots.items()
+        if roots
+    )
     supported_phases = {phases.public, phases.draft}
     if seen_phases - supported_phases:
         raise error.Abort(_(b'only draft and public phases are supported'))
     moves = {}
     def wrapped_advanceboundary(orig, repo, tr, targetphase, nodes):