dispatch: implement method of saving/restoring all steps scheduling.
Imagine this scenario, steps A, B and C are scheduled to be executed in
that order. Based on a user's choice A decides to skip_step(B) and then
the user presses "back" during C. This will take us back to A, but
previously the state of step B would stay 'skipped'. Instead, it is
desirable upon going back to have all the steps in the same scheduling
state as they were when the original step was first entered.
This patch addresses that by having each step store a dictionary of
scheduling changes that happened during that step (a mapping from a step
name to the tuple (from_state, to_state). It is therefore always possible
to reconstruct the original state.
+ def track_sched(self, step, s_from, s_to):
+ if step in self.changes:
+ s_from = self.changes[step][0]
+ self.changes[step] = (s_from, s_to)
class Dispatcher(object):
@@ -129,6 +140,7 @@ class Dispatcher(object):
self.anaconda = anaconda
self.anaconda.dir = DISPATCH_FORWARD
self.step = None # name of the current step
+ self.stop = False
# step dictionary mapping step names to step objects
self.steps = indexed_dict.IndexedDict()
# Note that not only a subset of the steps is executed for a particular
@@ -187,12 +199,38 @@ class Dispatcher(object):
self.steps[name] = Step(name, target)
def _advance_step(self):
- i = self._step_index()
- self.step = self.steps[i + 1].name
+ if self.step is None:
+ # initialization
+ log.info("dispatch: resetting to the first step.")
+ self.step = self.steps[0].name
+ elif self._step_index() < len(self.steps) - 1:
+ i = self._step_index()
+ if self.dir == DISPATCH_BACK:
+ # revert whatever changed in the current step
+ self._revert_scheduling(self.step)
+ self.step = self.steps[i + self.dir].name
+ if self.dir == DISPATCH_BACK:
+ # revert whatever changed in the step we moved back to
+ self._revert_scheduling(self.step)
+ else:
+ # advancing from the last step
+ self.step = "_invalid_"
+ self.stop = True
+
+ def _revert_scheduling(self, reverted_step):
+ for (step, (s_from, s_to)) in self.steps[reverted_step].changes.items():
+ self.steps[step].revert_sched(s_from, s_to)
+ self.steps[reverted_step].changes = {}
+ def _track_scheduling(self, changes):
+ if self.step is not None:
+ # store the changes into the current step
+ step = self.steps[self.step]
+ map(lambda c: step.track_sched(*c), changes)
+
@property
def dir(self):
return self.anaconda.dir
@@ -205,7 +243,8 @@ class Dispatcher(object):
self.anaconda.dir = dir
def step_disabled(self, step):
""" True if step is not yet scheduled to be run or will never be run
@@ -253,24 +294,21 @@ class Dispatcher(object):
Step.SCHED_DONE]