Fixes an issue when downgrading a revision where dependencies
are duplicated (e.g. by specifying the down_revision in depends_on).
This causes the down migrations to fail to remove the head, which is
caught by an assertion.
Added logic to de-duplicate the entries in _normalized_down_revisions
and _all_down_revisions without altering revision order.
This change revises the previous approach taken in
8d5a9a1b0d32fff5726010afffa48cc0fb738238 to address the problem
more generally outside of the topological algorithm.
Fixes: #843
Change-Id: I3517fb102b38c783c9a61bfb8dabc02c1fc89c4b
candidate_rev = id_to_rev[candidate]
- # immediate ancestor nodes, use a set to uniquify
- _u = set()
heads_to_add = [
r
for r in candidate_rev._normalized_down_revisions
- if r in todo
- and r not in current_heads
- and r not in _u
- and (_u.add(r) or True)
+ if r in todo and r not in current_heads
]
if not heads_to_add:
@property
def _all_down_revisions(self):
- return (
+ return util.dedupe_tuple(
util.to_tuple(self.down_revision, default=())
+ self._resolved_dependencies
)
that are still dependencies of ancestors.
"""
- return (
+ return util.dedupe_tuple(
util.to_tuple(self.down_revision, default=())
+ self._normalized_resolved_dependencies
)
Revision("b2", "b1", dependencies="a3"),
Revision("b3", "b2"),
Revision("b4", "b3", dependencies="a3"),
- Revision("b5", "b4"),
+ Revision("b5", "b4", dependencies="b4"),
]
)
# "a3" is not included because ancestor b2 is also dependent
eq_(b4._normalized_down_revisions, ("b3",))
+ def test_dupe_dependency(self):
+ b5 = self.map.get_revision("b5")
+ eq_(b5._all_down_revisions, ("b4",))
+ eq_(b5._normalized_down_revisions, ("b4",))
+
def test_branch_traversal(self):
self._assert_iteration(
"b4",
set(["a2"]),
)
+ def test_traverse_down(self):
+ self._assert_downgrade(
+ self.a1.revision,
+ self.a2.revision,
+ [self.down_(self.a2)],
+ set(["a1"]),
+ )
+
class DependsOnBranchTestFour(MigrationTest):
@classmethod