Devuan deployment of britney2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

129 lines
4.6 KiB

  1. class MigrationTransactionState(object):
  2. def __init__(self, suite_info, all_binaries, parent=None):
  3. self._suite_info = suite_info
  4. self._all_binaries = all_binaries
  5. self.parent_transaction = parent
  6. self._is_rolled_back = False
  7. self._is_committed = False
  8. self._undo_items = []
  9. self._pending_child = False
  10. if self.parent_transaction:
  11. # Transactions can only support one child transaction at a time
  12. assert not self.parent_transaction._pending_child
  13. self.parent_transaction._pending_child = True
  14. def add_undo_item(self, undo, updated_binaries):
  15. # We do not accept any changes to this transaction while it has a child transaction
  16. # (the undo code does not handle that case correctly)
  17. assert not self._pending_child
  18. self._assert_open_transaction()
  19. self._undo_items.append((undo, updated_binaries))
  20. def _assert_open_transaction(self):
  21. assert not self._is_rolled_back and not self._is_committed
  22. p = self.parent_transaction
  23. if p:
  24. p._assert_open_transaction()
  25. @property
  26. def undo_items(self):
  27. """Only needed by a _apply_item_to_target_suite for the "hint"-hint case"""
  28. yield from self._undo_items
  29. def commit(self):
  30. """Commit the transaction
  31. After this call, it is not possible to roll these changes
  32. back (except if there is a parent transaction, which can
  33. still be rolled back).
  34. """
  35. self._assert_open_transaction()
  36. self._is_committed = True
  37. if self.parent_transaction:
  38. self.parent_transaction._pending_child = False
  39. for undo_item in self._undo_items:
  40. self.parent_transaction.add_undo_item(*undo_item)
  41. def rollback(self):
  42. """Rollback all recorded changes by this transaction
  43. The parent transaction (if any) will remain unchanged
  44. """
  45. self._assert_open_transaction()
  46. self._is_rolled_back = True
  47. lundo = self._undo_items
  48. lundo.reverse()
  49. all_binary_packages = self._all_binaries
  50. target_suite = self._suite_info.target_suite
  51. sources_t = target_suite.sources
  52. binaries_t = target_suite.binaries
  53. provides_t = target_suite.provides_table
  54. # Historically, we have done the undo process in "4 steps"
  55. # with the rule that each step must be fully completed for
  56. # each undo-item before starting on the next.
  57. #
  58. # see commit:ef71f0e33a7c3d8ef223ec9ad5e9843777e68133 and
  59. # #624716 for the issues we had when we did not do this.
  60. #
  61. # Today, only STEP 2 and STEP 3 are known to potentially
  62. # clash. If there is a point in merging the loops/steps,
  63. # then it is now feasible.
  64. # STEP 1
  65. # undo all the changes for sources
  66. for (undo, updated_binaries) in lundo:
  67. for (k, v) in undo['sources'].items():
  68. if v is None:
  69. del sources_t[k]
  70. else:
  71. sources_t[k] = v
  72. # STEP 2
  73. # undo all new/updated binaries
  74. # Note this must be completed fully before starting STEP 3
  75. # as it potentially breaks STEP 3 if the two are interleaved.
  76. for (_, updated_binaries) in lundo:
  77. for pkg_id in updated_binaries:
  78. pkg_name, _, pkg_arch = pkg_id
  79. try:
  80. del binaries_t[pkg_arch][pkg_name]
  81. except KeyError:
  82. continue
  83. target_suite.remove_binary(pkg_id)
  84. # STEP 3
  85. # undo all other binary package changes (except virtual packages)
  86. for (undo, updated_binaries) in lundo:
  87. for p in undo['binaries']:
  88. binary, arch = p
  89. binaries_t_a = binaries_t[arch]
  90. pkgdata = all_binary_packages[undo['binaries'][p]]
  91. binaries_t_a[binary] = pkgdata
  92. target_suite.add_binary(pkgdata.pkg_id)
  93. # STEP 4
  94. # undo all changes to virtual packages
  95. for (undo, _) in lundo:
  96. for p, value in undo['virtual'].items():
  97. provided_pkg, arch = p
  98. if value is None:
  99. del provides_t[arch][provided_pkg]
  100. else:
  101. provides_t[arch][provided_pkg] = undo['virtual'][p]
  102. if self.parent_transaction:
  103. self.parent_transaction._pending_child = False
  104. @property
  105. def is_rolled_back(self):
  106. return self._is_rolled_back
  107. @property
  108. def is_committed(self):
  109. return self._is_committed