Skip to content

Commit a0f142a

Browse files
committed
Merge branch 'patriksvensson-feature/GH-2094' into develop
* patriksvensson-feature/GH-2094: (GH-2094) Allow no dependecy exec of single task * fixes #2094
2 parents cf913cf + 0e06dea commit a0f142a

File tree

15 files changed

+355
-114
lines changed

15 files changed

+355
-114
lines changed

src/Cake.Core.Tests/Fixtures/ScriptHostFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public ScriptHostFixture()
4949
Context.Log.Returns(Log);
5050

5151
Engine = Substitute.For<ICakeEngine>();
52-
Engine.RunTargetAsync(Context, Arg.Any<IExecutionStrategy>(), Arg.Any<string>())
52+
Engine.RunTargetAsync(Context, Arg.Any<IExecutionStrategy>(), Arg.Any<ExecutionSettings>())
5353
.Returns(new CakeReport());
5454
}
5555

src/Cake.Core.Tests/Unit/CakeEngineTests.cs

Lines changed: 202 additions & 78 deletions
Large diffs are not rendered by default.

src/Cake.Core/CakeEngine.cs

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,17 @@ public void RegisterTaskTeardownAction<TData>(Action<ITaskTeardownContext, TData
179179
/// </summary>
180180
/// <param name="context">The context.</param>
181181
/// <param name="strategy">The execution strategy.</param>
182-
/// <param name="target">The target to run.</param>
182+
/// <param name="settings">The execution settings.</param>
183183
/// <returns>The resulting report.</returns>
184-
public async Task<CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, string target)
184+
public async Task<CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, ExecutionSettings settings)
185185
{
186-
if (target == null)
186+
if (settings == null)
187187
{
188-
throw new ArgumentNullException(nameof(target));
188+
throw new ArgumentNullException(nameof(settings));
189+
}
190+
if (string.IsNullOrWhiteSpace(settings.Target))
191+
{
192+
throw new ArgumentException("No target specified.", nameof(settings));
189193
}
190194

191195
if (strategy == null)
@@ -200,6 +204,7 @@ public async Task<CakeReport> RunTargetAsync(ICakeContext context, IExecutionStr
200204
var graph = CakeGraphBuilder.Build(_tasks);
201205

202206
// Make sure target exist.
207+
var target = settings.Target;
203208
if (!graph.Exist(target))
204209
{
205210
const string format = "The target '{0}' was not found.";
@@ -228,26 +233,18 @@ public async Task<CakeReport> RunTargetAsync(ICakeContext context, IExecutionStr
228233

229234
PerformSetup(strategy, context, targetNode, orderedTasks, stopWatch, report);
230235

231-
foreach (var task in orderedTasks)
236+
if (settings.Exclusive)
232237
{
233-
// Is this the current target?
234-
var isTarget = task.Name.Equals(target, StringComparison.OrdinalIgnoreCase);
235-
236-
// Should we execute the task?
237-
var skipped = false;
238-
foreach (var criteria in task.Criterias)
239-
{
240-
if (!ShouldTaskExecute(context, task, criteria, isTarget))
241-
{
242-
SkipTask(context, strategy, task, report, criteria);
243-
skipped = true;
244-
break;
245-
}
246-
}
247-
248-
if (!skipped)
238+
// Execute only the target task.
239+
var task = _tasks.FirstOrDefault(x => x.Name.Equals(settings.Target, StringComparison.OrdinalIgnoreCase));
240+
await RunTask(context, strategy, task, target, stopWatch, report);
241+
}
242+
else
243+
{
244+
// Execute all scheduled tasks.
245+
foreach (var task in orderedTasks)
249246
{
250-
await ExecuteTaskAsync(context, strategy, stopWatch, task, report).ConfigureAwait(false);
247+
await RunTask(context, strategy, task, target, stopWatch, report);
251248
}
252249
}
253250

@@ -265,6 +262,29 @@ public async Task<CakeReport> RunTargetAsync(ICakeContext context, IExecutionStr
265262
}
266263
}
267264

265+
private async Task RunTask(ICakeContext context, IExecutionStrategy strategy, CakeTask task, string target, Stopwatch stopWatch, CakeReport report)
266+
{
267+
// Is this the current target?
268+
var isTarget = task.Name.Equals(target, StringComparison.OrdinalIgnoreCase);
269+
270+
// Should we execute the task?
271+
var skipped = false;
272+
foreach (var criteria in task.Criterias)
273+
{
274+
if (!ShouldTaskExecute(context, task, criteria, isTarget))
275+
{
276+
SkipTask(context, strategy, task, report, criteria);
277+
skipped = true;
278+
break;
279+
}
280+
}
281+
282+
if (!skipped)
283+
{
284+
await ExecuteTaskAsync(context, strategy, stopWatch, task, report).ConfigureAwait(false);
285+
}
286+
}
287+
268288
private void PerformSetup(IExecutionStrategy strategy, ICakeContext context, CakeTask targetTask,
269289
CakeTask[] tasks, Stopwatch stopWatch, CakeReport report)
270290
{
@@ -283,8 +303,7 @@ private void PerformSetup(IExecutionStrategy strategy, ICakeContext context, Cak
283303
}
284304
}
285305

286-
private static bool ShouldTaskExecute(ICakeContext context, CakeTask task, CakeTaskCriteria criteria,
287-
bool isTarget)
306+
private static bool ShouldTaskExecute(ICakeContext context, CakeTask task, CakeTaskCriteria criteria, bool isTarget)
288307
{
289308
if (!criteria.Predicate(context))
290309
{

src/Cake.Core/ExecutionSettings.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace Cake.Core
6+
{
7+
/// <summary>
8+
/// Contains settings related to execution of the script.
9+
/// </summary>
10+
public sealed class ExecutionSettings
11+
{
12+
/// <summary>
13+
/// Gets the target to be executed.
14+
/// </summary>
15+
public string Target { get; private set; }
16+
17+
/// <summary>
18+
/// Gets a value indicating whether or not to use the target exclusively.
19+
/// </summary>
20+
public bool Exclusive { get; private set; }
21+
22+
/// <summary>
23+
/// Sets the target to be executed.
24+
/// </summary>
25+
/// <param name="target">The target.</param>
26+
/// <returns>The same <see cref="ExecutionSettings"/> instance so that multiple calls can be chained.</returns>
27+
public ExecutionSettings SetTarget(string target)
28+
{
29+
Target = target;
30+
return this;
31+
}
32+
33+
/// <summary>
34+
/// Whether or not to use the target exclusively.
35+
/// </summary>
36+
/// <returns>The same <see cref="ExecutionSettings"/> instance so that multiple calls can be chained.</returns>
37+
public ExecutionSettings UseExclusiveTarget()
38+
{
39+
Exclusive = true;
40+
return this;
41+
}
42+
}
43+
}

src/Cake.Core/ICakeEngine.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ public interface ICakeEngine
8181
/// </summary>
8282
/// <param name="context">The context.</param>
8383
/// <param name="strategy">The execution strategy.</param>
84-
/// <param name="target">The target to run.</param>
84+
/// <param name="settings">The execution settings.</param>
8585
/// <returns>The resulting report.</returns>
86-
Task<CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, string target);
86+
Task<CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, ExecutionSettings settings);
8787

8888
/// <summary>
8989
/// Allows registration of an action that's executed before each task is run.

src/Cake.Core/Scripting/ScriptHost.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ public abstract class ScriptHost : IScriptHost
2626
/// <value>The context.</value>
2727
public ICakeContext Context { get; }
2828

29+
/// <summary>
30+
/// Gets the settings.
31+
/// </summary>
32+
/// <value>The settings.</value>
33+
public ExecutionSettings Settings { get; }
34+
2935
/// <summary>
3036
/// Initializes a new instance of the <see cref="ScriptHost"/> class.
3137
/// </summary>
@@ -43,6 +49,7 @@ protected ScriptHost(ICakeEngine engine, ICakeContext context)
4349
}
4450
Engine = engine;
4551
Context = context;
52+
Settings = new ExecutionSettings();
4653
}
4754

4855
/// <summary>

src/Cake.Tests/Unit/Arguments/ArgumentParserTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,23 @@ public void Can_Parse_Bootstrap(string input, bool expected)
580580
// Then
581581
Assert.Equal(expected, result.Bootstrap);
582582
}
583+
584+
[Theory]
585+
[InlineData("--exclusive", true)]
586+
[InlineData("--exclusive=true", true)]
587+
[InlineData("--exclusive=false", false)]
588+
public void Can_Parse_Exclusive(string input, bool expected)
589+
{
590+
// Given
591+
var fixture = new ArgumentParserFixture();
592+
var parser = new ArgumentParser(fixture.Log, fixture.VerbosityParser);
593+
594+
// When
595+
var result = parser.Parse(new[] { "build.cake", input });
596+
597+
// Then
598+
Assert.Equal(expected, result.Exclusive);
599+
}
583600
}
584601
}
585602
}

src/Cake.Tests/Unit/Scripting/BuildScriptHostTests.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,26 @@ public async Task Should_Proxy_Call_To_Engine()
3030
host.RunTarget("Target");
3131

3232
// Then
33-
await engine.Received(1).RunTargetAsync(context, Arg.Any<DefaultExecutionStrategy>(), "Target");
33+
await engine.Received(1).RunTargetAsync(context,
34+
Arg.Any<DefaultExecutionStrategy>(),
35+
Arg.Is<ExecutionSettings>(e => e.Target == "Target"));
3436
}
3537

3638
[Fact]
3739
public async Task Should_Print_Report()
3840
{
3941
// Given
4042
var report = new CakeReport();
41-
report.Add("Target", TimeSpan.FromSeconds(1));
4243
var engine = Substitute.For<ICakeEngine>();
4344
var context = Substitute.For<ICakeContext>();
44-
engine.RunTargetAsync(context, Arg.Any<DefaultExecutionStrategy>(), "Target").Returns(Task.FromResult(report));
4545
var printer = Substitute.For<ICakeReportPrinter>();
4646
var log = Substitute.For<ICakeLog>();
4747
var host = new BuildScriptHost(engine, context, printer, log);
4848

49+
report.Add("Target", TimeSpan.FromSeconds(1));
50+
engine.RunTargetAsync(context, Arg.Any<DefaultExecutionStrategy>(), Arg.Any<ExecutionSettings>())
51+
.Returns(Task.FromResult(report));
52+
4953
// When
5054
await host.RunTargetAsync("Target");
5155

@@ -59,11 +63,13 @@ public async Task Should_Not_Print_Report_That_Is_Null()
5963
// Given
6064
var engine = Substitute.For<ICakeEngine>();
6165
var context = Substitute.For<ICakeContext>();
62-
engine.RunTargetAsync(context, Arg.Any<DefaultExecutionStrategy>(), Arg.Any<string>()).Returns(Task.FromResult((CakeReport)null));
6366
var printer = Substitute.For<ICakeReportPrinter>();
6467
var log = Substitute.For<ICakeLog>();
6568
var host = new BuildScriptHost(engine, context, printer, log);
6669

70+
engine.RunTargetAsync(context, Arg.Any<DefaultExecutionStrategy>(), Arg.Any<ExecutionSettings>())
71+
.Returns(Task.FromResult((CakeReport)null));
72+
6773
// When
6874
await host.RunTargetAsync("Target");
6975

@@ -77,11 +83,13 @@ public async Task Should_Not_Print_Empty_Report()
7783
// Given
7884
var engine = Substitute.For<ICakeEngine>();
7985
var context = Substitute.For<ICakeContext>();
80-
engine.RunTargetAsync(context, Arg.Any<DefaultExecutionStrategy>(), Arg.Any<string>()).Returns(Task.FromResult(new CakeReport()));
8186
var printer = Substitute.For<ICakeReportPrinter>();
8287
var log = Substitute.For<ICakeLog>();
8388
var host = new BuildScriptHost(engine, context, printer, log);
8489

90+
engine.RunTargetAsync(context, Arg.Any<DefaultExecutionStrategy>(), Arg.Any<ExecutionSettings>())
91+
.Returns(Task.FromResult(new CakeReport()));
92+
8593
// When
8694
await host.RunTargetAsync("Target");
8795

src/Cake.Tests/Unit/Scripting/DescriptionScriptHostTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public async Task Should_Not_Call_To_Engine()
7575
await engine.Received(0).RunTargetAsync(
7676
context,
7777
Arg.Any<DefaultExecutionStrategy>(),
78-
"Target");
78+
Arg.Is<ExecutionSettings>(e => e.Target == "Target"));
7979
}
8080
}
8181
}

src/Cake.Tests/Unit/Scripting/DryRunScriptHostTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ public void Should_Invoke_The_Engine_With_Correct_Execution_Strategy()
7272
host.RunTarget("TheTarget");
7373

7474
// Then
75-
engine.Received(1).RunTargetAsync(context, Arg.Any<DryRunExecutionStrategy>(), "TheTarget");
75+
engine.Received(1).RunTargetAsync(context,
76+
Arg.Any<DryRunExecutionStrategy>(),
77+
Arg.Is<ExecutionSettings>(e => e.Target == "TheTarget"));
7678
}
7779
}
7880
}

0 commit comments

Comments
 (0)