-
Notifications
You must be signed in to change notification settings - Fork 445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
many: detect local source changes #2167
Changes from 7 commits
77481b3
d64fe62
f1779f5
46bfd96
f6946f6
5a43815
e95e7e1
3885d28
841378c
6cc1d79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -184,34 +184,56 @@ def run(self, step: steps.Step, part_names=None): | |
# already been built --elopio - 20170713 | ||
pluginhandler.check_for_collisions(self.config.all_parts) | ||
for part in parts: | ||
dirty_report = self._cache.get_dirty_report( | ||
part, current_step) | ||
if dirty_report: | ||
self._handle_dirty( | ||
part, current_step, dirty_report, cli_config) | ||
elif self._cache.has_step_run(part, current_step): | ||
# By default, if a step has already run, don't run it | ||
# again. However, automatically clean and re-run the | ||
# step if all the following conditions apply: | ||
# | ||
# 1. The step is the exact step that was requested | ||
# (not an earlier one) | ||
# 2. The part was explicitly specified | ||
if (part_names and current_step == step and | ||
part.name in part_names): | ||
getattr(self, '_re{}'.format( | ||
current_step.name))(part) | ||
else: | ||
notify_part_progress( | ||
part, | ||
'Skipping {}'.format(current_step.name), | ||
'(already ran)') | ||
else: | ||
getattr(self, '_run_{}'.format( | ||
current_step.name))(part) | ||
self._handle_step( | ||
part_names, part, step, current_step, cli_config) | ||
|
||
self._create_meta(step, processed_part_names) | ||
|
||
def _handle_step(self, requested_part_names: Sequence[str], | ||
part: pluginhandler.PluginHandler, | ||
requested_step: steps.Step, | ||
current_step: steps.Step, cli_config) -> None: | ||
# If this step hasn't yet run, all we need to do is run it | ||
if not self._cache.has_step_run(part, current_step): | ||
getattr(self, '_run_{}'.format(current_step.name))(part) | ||
return | ||
|
||
# Alright, this step has already run. In that case, a few different | ||
# things need to happen: | ||
|
||
# 1. By default, if a step has already run, don't run it again. | ||
# However, automatically clean and re-run the step if all the | ||
# following conditions apply: | ||
# | ||
# 1.1. The step is the exact step that was requested (not an | ||
# earlier one). | ||
# 1.2. The part was explicitly specified. | ||
if (requested_part_names and current_step == requested_step and | ||
part.name in requested_part_names): | ||
getattr(self, '_re{}'.format(current_step.name))(part) | ||
return | ||
|
||
# 2. If a step has already run, it might be dirty, in which case we | ||
# need to clean and run it again. | ||
dirty_report = self._cache.get_dirty_report(part, current_step) | ||
if dirty_report: | ||
self._handle_dirty(part, current_step, dirty_report, cli_config) | ||
return | ||
|
||
# 3. If a step has already run, it might be outdated, in which case we | ||
# need to update it (without cleaning if possible). | ||
outdated_report = self._cache.get_outdated_report( | ||
part, current_step) | ||
if outdated_report: | ||
self._handle_outdated( | ||
part, current_step, outdated_report, cli_config) | ||
return | ||
|
||
# 4. The step has already run, and is up-to-date, no need to run it | ||
# again. | ||
notify_part_progress( | ||
part, 'Skipping {}'.format(current_step.name), '(already ran)') | ||
|
||
def _run_pull(self, part): | ||
self._run_step(step=steps.PULL, part=part, progress='Pulling') | ||
|
||
|
@@ -244,7 +266,8 @@ def _reprime(self, part, hint=''): | |
self._rerun_step( | ||
step=steps.PRIME, part=part, progress='Re-priming', hint=hint) | ||
|
||
def _run_step(self, *, step: steps.Step, part, progress, hint=''): | ||
def _prepare_step(self, *, step: steps.Step, | ||
part: pluginhandler.PluginHandler): | ||
common.reset_env() | ||
all_dependencies = self.parts_config.get_dependencies(part.name) | ||
|
||
|
@@ -277,11 +300,18 @@ def _run_step(self, *, step: steps.Step, part, progress, hint=''): | |
|
||
part = _replace_in_part(part) | ||
|
||
def _run_step(self, *, step: steps.Step, part, progress, hint=''): | ||
self._prepare_step(step=step, part=part) | ||
|
||
notify_part_progress(part, progress, hint) | ||
getattr(part, step.name)() | ||
|
||
# We know we just ran this step, so rather than check, manually twiddle | ||
# the cache | ||
self._complete_step(part, step) | ||
|
||
def _complete_step(self, part, step): | ||
self._cache.clear_step(part, step) | ||
self._cache.add_step_run(part, step) | ||
self.steps_were_run = True | ||
|
||
|
@@ -316,6 +346,28 @@ def _handle_dirty(self, part, step, dirty_report, cli_config): | |
getattr(self, '_re{}'.format(step.name))(part, hint='({})'.format( | ||
dirty_report.get_summary())) | ||
|
||
def _handle_outdated(self, part, step, outdated_report, cli_config): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as handle_dirty, can this take a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the introduction of the outdated concept, I think this is just another case of dirty. Can we add more precise qualifiers like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me give you my thought process. A step (for a specific part) can be in one of two states:
Both 2.2 and 2.3 are caused by something, which needs to be recorded somewhere so we can tell the user what it was. We do that with the
(1) isn't a big deal, we can figure that one out. The word "outdated" could be used to refer to both situations, I suppose. (2) we can probably solve by keeping things similar to how they are today, but have a master class composed of both a dirty and outdated report, and take action appropriately. That at least gives us a single report to deal with in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did not say combine them, I just meant that "dirty" and "outdated" are easier to confuse and that we should narrow the scope of what it means down. Your thought process is from the point of view of the action wrt lifecycle and my mind is trending towards the state of things (why is it dirty/outdated) whilst the report comes from a component that does not determine the future actions. These two terms lead to confusions, is this dirty because it is outdated (so far that has been our logic, right?). The what is outdated is what I am asking to more clearly state in the method calls, checks and class names. But yeah, by no means, unless it gets converted into the state class merge these two. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are really stuck with the names, I have added a couple more comments that would satisfy me. My intention was that from the names of variables and classes it was crystal clear what it meant without having to read the code, I can compromise with a bit more documentation under the internal class names and methods called. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that this should be cleaned up, but as we discussed on the call, let's see if we can get this PR in a decent state with docs and then take another pass (in another PR) at improving it further. |
||
dirty_action = cli_config.get_outdated_step_action() | ||
if not step.clean_if_dirty: | ||
if dirty_action == config.OutdatedStepAction.ERROR: | ||
raise errors.StepOutdatedError( | ||
step=step, part=part.name, outdated_report=outdated_report) | ||
|
||
update_function = getattr(part, 'update_{}'.format(step.name), None) | ||
if update_function: | ||
self._prepare_step(step=step, part=part) | ||
notify_part_progress( | ||
part, 'Updating {} step for'.format(step.name), '({})'.format( | ||
outdated_report.get_summary())) | ||
update_function() | ||
|
||
# We know we just ran this step, so rather than check, manually | ||
# twiddle the cache | ||
self._complete_step(part, step) | ||
else: | ||
getattr(self, '_re{}'.format(step.name))(part, '({})'.format( | ||
outdated_report.get_summary())) | ||
|
||
|
||
def notify_part_progress(part, progress, hint='', debug=False): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is old, but what is the difference? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just keep it green 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm afraid I'm not clear on what you're saying, here. Are you asking me to change something? |
||
if debug: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of multiple returns here, it seems this could be handled very well with
elif
and a finalelse
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're fetching reports before checking them, which is heavy to do upfront if we don't actually need to, so it doesn't fit particularly well within an if/elif unless we want to nest within
else
s.