You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Rake -n does not mark dependents for Execution #92
The problem seems to stem from the fact that the internal function out_of_date? (in file_task.rb) does not take into account when a file should have updated its timestamp (but didn't, because this is a dry-run).
Even though it knows it must update both fileB and fileC
fileC task should only be executed if fileB changed. So how can rake know that fileB is going to change without actually executing fileB task (given it's a dry-run)?
I think rake cannot know if fileB is going to have it's file timestamp updated or not, that depends on what the actual fileB file task does in the block implementation, which is never executed in a dry-run.
I think I've always assumed that if the code for building fileB does not change its timestamp (so as to be more recent than fileC), then rake would assume that there was an error and fail loudly.
If this check was in place, then it wouldn't be a problem for the dry-run to print this:
because the semantics would be the following: "fileC will be run as long as there is no problem when building fileB". This is already true if the fileB task raises an exception (in which case the fileC task will not be executed).
In fact, whenever there is more than one line such as ** Execute (dry run) <something> in the dry-run output, we can never be sure if all of them will be executed. If any task fails with an exception, rake correctly stops all following executions, even the ones that are completely unrelated to it. There is always the implicit assumption of May execute for all but the first occurrence of Execute.
But then, all of this would require rake to actually fail on error (instead of failing silently) when its file tasks fail to update the timestamp from the dependent to a value that is more recent than the one of the target. Would this be feasible to implement? Maybe there's a downside I'm not seeing?
I think I've always assumed that if the code for building fileB does not change its timestamp (so as to be more recent than fileC), then rake would assume that there was an error and fail loudly.
Whether rake should or should not raise an error if the file task doesn't update the file as part of the file task execution seems like an interesting but separate discussion to me.
Back to the original issue about dry-runs, it seems like, as of today, rake doesn't assume anything about what fileB task does when it's executed. User is free to implement it in any way it likes. rake is agnostic about that. So that means, as per the actual situation, the dry-run cannot assume fileC is going to be executed, just based on the fact that fileB file task is going to be executed, right?
Well, whenever there are two tasks marked for execution, we can never know if the second one will ever execute. Even if we run $ rake fileB fileC we are not guaranteed that the fileC task will be executed (it won't if fileB fails with an exception). But still, rake -n will show both as marked for execution, because under normal circumstances, both should be executed. So I agree that we cannot assume that fileC will be executed, but I will say this assumption is always true whenever we have more than 1 task marked for execution.
The reason why mentioned my assumption of rake raising an error is that any other solution would require silent failure (I think). For example, if fileB does not update the timestamp then either:
a) Rake will try to build fileC anyway (silently ignore the fact that fileB failed). I think nobody wants this option.
b) Rake will silently skip the target fileC, and users will think that the build worked even though it didn't.
c) Rake will fail with an error saying that fileB was built with a timestamp that is older than the one in fileC.
If we go for option (c), then I don't see any problem in saying both ** Execute fileB and ** Execute fileC, because under normal circumstances both will be executed. And under exceptional circumstances, rake will stop on the first error, regardless of whether the error occurred inside fileB or it was an error in the timestamp of fileB.
Maybe there's an option (d) that I'm missing? Or maybe options (a) or (b) are better than I think?
Side note:
[...] as of today, rake doesn't assume anything about what fileB task does when it's executed. User is free to implement it in any way it likes. rake is agnostic about that.
Actually, I think rake does assume that file tasks update the timestamps. That's why it will not run fileB if it thinks the timestamp is already fine. Basically, the main assumption rake makes about file tasks would be that they update the timestamp for the given file. Timestamps are important for rake, which is also why it will not run fileC if the timestamp of fileB is not updated, in options (b) and (c) above.
Implementation of the task, including the update of the file timestamp it's up to the user, plus rake doesn't assume anything about the implementation of the task as of now.
So I agree that we cannot assume that fileC will be executed
Cool, we agree on that 👍
So if we cannot assume that fileC will be executed, wouldn't be misleading to include
rake doesn't assume anything about the implementation of the task as of now
Rake does assume that file tasks update the timestamps. That's why it will not run fileB if it thinks the timestamp is already fine. This is the main assumption behind Makefiles, and is the expected behavior of the file method. If the file method were not supposed to be used for timestamp-related tasks, then I would say that the current documentation on rake is very misleading. But I think we can agree that the point of file is to represent a file-building task that relies on timestamps. That's an assumption that's made by both make and rake's file method.
So if we cannot assume that fileC will be executed, wouldn't be misleading to include
** Execute (dry run) fileC
in the output of the dry-run?
Whenever there are two tasks marked for execution, we can never know if the second one will ever execute. Even if we run $ rake fileB fileC we are not guaranteed that the fileC task will be executed (it won't if fileB fails with an exception). But still, rake -n will show both as marked for execution, because under normal circumstances, both should be executed.
Should rake -n be modified so as to never ever show more than one line containing Execute, so as to avoid a literal interpretation that this Execute necessarily means that this taks will be executed no matter what? I wouldn't say so. I'd say it's implicit that any failure in the chain will stop the execution of further tasks, so it's a bug if rake currently does not show everything that will be executed. This bug makes rake -n extremely misleading (we cannot rely on it to know what tasks will actually be called), and prevents any scripting of its output to predict what tasks will actually be executed.
"rake -n shows everything that will be executed when required." defines the behavior for me. Maybe the documentation needs to be more specific for file tasks to help beginners which never used make or similar before…
Activity
grzuy commentedon Feb 7, 2018
fileCtask should only be executed iffileBchanged. So how can rake know thatfileBis going to change without actually executingfileBtask (given it's a dry-run)?grzuy commentedon Feb 7, 2018
I think rake cannot know if fileB is going to have it's file timestamp updated or not, that depends on what the actual
fileBfile task does in the block implementation, which is never executed in a dry-run.So at most, rake can say something like
Or maybe i am missing something.
dry-run smarter about potential file task executions. Fixes ruby#92
dry-run also smart about 2-level nesting of potential file task execu…
Make dry-run smart about potential file task executions. Fixes ruby#92
Make dry-run smart about potential file task executions. Fixes ruby#92
Make dry-run smart about potential file task executions. Fixes ruby#92
silvioricardoc commentedon Feb 8, 2018
I think I've always assumed that if the code for building
fileBdoes not change its timestamp (so as to be more recent thanfileC), then rake would assume that there was an error and fail loudly.If this check was in place, then it wouldn't be a problem for the dry-run to print this:
because the semantics would be the following: "
fileCwill be run as long as there is no problem when buildingfileB". This is already true if thefileBtask raises an exception (in which case thefileCtask will not be executed).In fact, whenever there is more than one line such as
** Execute (dry run) <something>in the dry-run output, we can never be sure if all of them will be executed. If any task fails with an exception, rake correctly stops all following executions, even the ones that are completely unrelated to it. There is always the implicit assumption ofMay executefor all but the first occurrence ofExecute.But then, all of this would require rake to actually fail on error (instead of failing silently) when its
filetasks fail to update the timestamp from the dependent to a value that is more recent than the one of the target. Would this be feasible to implement? Maybe there's a downside I'm not seeing?grzuy commentedon Feb 8, 2018
Hi Silvio, thanks for responding.
Whether rake should or should not raise an error if the file task doesn't update the file as part of the file task execution seems like an interesting but separate discussion to me.
Back to the original issue about
dry-runs, it seems like, as of today, rake doesn't assume anything about whatfileBtask does when it's executed. User is free to implement it in any way it likes. rake is agnostic about that. So that means, as per the actual situation, the dry-run cannot assumefileCis going to be executed, just based on the fact thatfileBfile task is going to be executed, right?silvioricardoc commentedon Feb 9, 2018
Well, whenever there are two tasks marked for execution, we can never know if the second one will ever execute. Even if we run
$ rake fileB fileCwe are not guaranteed that thefileCtask will be executed (it won't iffileBfails with an exception). But still,rake -nwill show both as marked for execution, because under normal circumstances, both should be executed. So I agree that we cannot assume thatfileCwill be executed, but I will say this assumption is always true whenever we have more than 1 task marked for execution.The reason why mentioned my assumption of rake raising an error is that any other solution would require silent failure (I think). For example, if
fileBdoes not update the timestamp then either:a) Rake will try to build
fileCanyway (silently ignore the fact thatfileBfailed). I think nobody wants this option.b) Rake will silently skip the target
fileC, and users will think that the build worked even though it didn't.c) Rake will fail with an error saying that
fileBwas built with a timestamp that is older than the one infileC.If we go for option (c), then I don't see any problem in saying both
** Execute fileBand** Execute fileC, because under normal circumstances both will be executed. And under exceptional circumstances, rake will stop on the first error, regardless of whether the error occurred insidefileBor it was an error in the timestamp offileB.Maybe there's an option (d) that I'm missing? Or maybe options (a) or (b) are better than I think?
Side note:
Actually, I think rake does assume that file tasks update the timestamps. That's why it will not run
fileBif it thinks the timestamp is already fine. Basically, the main assumption rake makes aboutfiletasks would be that they update the timestamp for the given file. Timestamps are important for rake, which is also why it will not runfileCif the timestamp offileBis not updated, in options (b) and (c) above.grzuy commentedon Feb 20, 2018
Keep in mind
fileCwon't run also iffileBfile task has a conditional implementation, and the condition returnsfalse. E.g.Implementation of the task, including the update of the file timestamp it's up to the user, plus rake doesn't assume anything about the implementation of the task as of now.
Cool, we agree on that 👍
So if we cannot assume that
fileCwill be executed, wouldn't be misleading to includein the output of the dry-run?
silvioricardoc commentedon Feb 21, 2018
Rake does assume that file tasks update the timestamps. That's why it will not run
fileBif it thinks the timestamp is already fine. This is the main assumption behind Makefiles, and is the expected behavior of thefilemethod. If thefilemethod were not supposed to be used for timestamp-related tasks, then I would say that the current documentation on rake is very misleading. But I think we can agree that the point offileis to represent a file-building task that relies on timestamps. That's an assumption that's made by bothmakeand rake'sfilemethod.Whenever there are two tasks marked for execution, we can never know if the second one will ever execute. Even if we run
$ rake fileB fileCwe are not guaranteed that thefileCtask will be executed (it won't iffileBfails with an exception). But still,rake -nwill show both as marked for execution, because under normal circumstances, both should be executed.Should
rake -nbe modified so as to never ever show more than one line containingExecute, so as to avoid a literal interpretation that thisExecutenecessarily means that this taks will be executed no matter what? I wouldn't say so. I'd say it's implicit that any failure in the chain will stop the execution of further tasks, so it's a bug if rake currently does not show everything that will be executed. This bug makesrake -nextremely misleading (we cannot rely on it to know what tasks will actually be called), and prevents any scripting of its output to predict what tasks will actually be executed.mblumtritt commentedon Feb 22, 2018
"
rake -nshows everything that will be executed when required." defines the behavior for me. Maybe the documentation needs to be more specific for file tasks to help beginners which never usedmakeor similar before…