diff --git a/src/Cake.Cli/Cake.Cli.csproj b/src/Cake.Cli/Cake.Cli.csproj
new file mode 100644
index 0000000000..7ab9b4723e
--- /dev/null
+++ b/src/Cake.Cli/Cake.Cli.csproj
@@ -0,0 +1,25 @@
+
+
+ Cake.Cli
+ netstandard2.0;net5.0
+ Library
+ AnyCpu
+ true
+
+
+
+
+ The Cake CLI library.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Cake.Cli/Features/InfoFeature.cs b/src/Cake.Cli/Features/InfoFeature.cs
new file mode 100644
index 0000000000..70b0abacb4
--- /dev/null
+++ b/src/Cake.Cli/Features/InfoFeature.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Cake.Core;
+
+namespace Cake.Cli
+{
+ ///
+ /// Represents a feature that writes information about Cake to the console.
+ ///
+ public interface ICakeInfoFeature
+ {
+ ///
+ /// Runs the feature.
+ ///
+ /// The console to write to.
+ void Run(IConsole console);
+ }
+
+ ///
+ /// Writes information about Cake to the console.
+ ///
+ public sealed class InfoFeature : ICakeInfoFeature
+ {
+ private readonly IVersionResolver _resolver;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The version resolver.
+ public InfoFeature(IVersionResolver resolver)
+ {
+ _resolver = resolver;
+ }
+
+ ///
+ public void Run(IConsole console)
+ {
+ var version = _resolver.GetVersion();
+ var product = _resolver.GetProductVersion();
+
+ console.WriteLine();
+ console.WriteLine(@" +## #;;'");
+ console.WriteLine(@" #;;# .+;;;;+,");
+ console.WriteLine(@" '+;;#;,+';;;;;'#.");
+ console.WriteLine(@" ++'''';;;;;;;;;;# ;#;");
+ console.WriteLine(@" ##';;;;++'+#;;;;;'. `#:");
+ console.WriteLine(@" ;# '+'';;;;;;;;;'#` #.");
+ console.WriteLine(@" `#, .'++;;;;;':..........#");
+ console.WriteLine(@" '+ `.........';;;;':.........#");
+ console.WriteLine(@" #..................+;;;;;':........#");
+ console.WriteLine(@" #..................#';;;;;'+''''''.#");
+ console.WriteLine(@" #.......,:;''''''''##';;;;;'+'''''#,");
+ console.WriteLine(@" #''''''''''''''''''###';;;;;;+''''#");
+ console.WriteLine(@" #''''''''''''''''''####';;;;;;#'''#");
+ console.WriteLine(@" #''''''''''''''''''#####';;;;;;#''#");
+ console.WriteLine(@" #''''''''''''''''''######';;;;;;#'#");
+ console.WriteLine(@" #''''''''''''''''''#######';;;;;;##");
+ console.WriteLine(@" #''''''''''''''''''########';;;;;;#");
+ console.WriteLine(@" #''''''''''''++####+;#######';;;;;;#");
+ console.WriteLine(@" #+####':,` ,#####';;;;;;'");
+ console.WriteLine(@" +##'''''+.");
+
+ console.ForegroundColor = System.ConsoleColor.Yellow;
+ console.WriteLine(@" ___ _ ___ _ _ _ ");
+ console.WriteLine(@" / __\__ _| | _____ / __\_ _(_) | __| |");
+ console.WriteLine(@" / / / _` | |/ / _ \/__\// | | | | |/ _` |");
+ console.WriteLine(@"/ /___ (_| | < __/ \/ \ |_| | | | (_| |");
+ console.WriteLine(@"\____/\__,_|_|\_\___\_____/\__,_|_|_|\__,_|");
+ console.ResetColor();
+
+ console.WriteLine();
+ console.WriteLine(@"Version: {0}", version);
+ console.WriteLine(@"Details: {0}", string.Join("\n ", product.Split('/')));
+ console.WriteLine();
+ }
+ }
+}
diff --git a/src/Cake.Cli/Features/VersionFeature.cs b/src/Cake.Cli/Features/VersionFeature.cs
new file mode 100644
index 0000000000..fc71345b5c
--- /dev/null
+++ b/src/Cake.Cli/Features/VersionFeature.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Cake.Core;
+
+namespace Cake.Cli
+{
+ ///
+ /// Represents a feature that writes the Cake version to the console.
+ ///
+ public interface ICakeVersionFeature
+ {
+ ///
+ /// Writes the Cake version to the console.
+ ///
+ /// The console to write to.
+ void Run(IConsole console);
+ }
+
+ ///
+ /// Writes the Cake version to the console.
+ ///
+ public sealed class VersionFeature : ICakeVersionFeature
+ {
+ private readonly IVersionResolver _resolver;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The version resolver.
+ public VersionFeature(IVersionResolver resolver)
+ {
+ _resolver = resolver;
+ }
+
+ ///
+ public void Run(IConsole console)
+ {
+ if (console is null)
+ {
+ throw new ArgumentNullException(nameof(console));
+ }
+
+ console.WriteLine(_resolver.GetVersion());
+ }
+ }
+}
diff --git a/src/Cake/Features/Introspection/VersionResolver.cs b/src/Cake.Cli/Features/VersionResolver.cs
similarity index 62%
rename from src/Cake/Features/Introspection/VersionResolver.cs
rename to src/Cake.Cli/Features/VersionResolver.cs
index 1a9dfad55a..cc91351749 100644
--- a/src/Cake/Features/Introspection/VersionResolver.cs
+++ b/src/Cake.Cli/Features/VersionResolver.cs
@@ -3,20 +3,37 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Reflection;
-namespace Cake.Features.Introspection
+namespace Cake.Cli
{
+ ///
+ /// Represents a version resolver.
+ ///
public interface IVersionResolver
{
+ ///
+ /// Gets the version.
+ ///
+ /// The version.
string GetVersion();
+
+ ///
+ /// Gets the product version.
+ ///
+ /// The product version.
string GetProductVersion();
}
+ ///
+ /// The Cake version resolver.
+ ///
public sealed class VersionResolver : IVersionResolver
{
+ ///
public string GetVersion()
{
- var assembly = typeof(Program).Assembly;
+ var assembly = Assembly.GetEntryAssembly();
var version = FileVersionInfo.GetVersionInfo(assembly.Location).Comments;
if (string.IsNullOrWhiteSpace(version))
@@ -27,9 +44,10 @@ public string GetVersion()
return version;
}
+ ///
public string GetProductVersion()
{
- var assembly = typeof(Program).Assembly;
+ var assembly = Assembly.GetEntryAssembly();
var version = FileVersionInfo.GetVersionInfo(assembly.Location).ProductVersion;
if (string.IsNullOrWhiteSpace(version))
diff --git a/src/Cake.Cli/Hosts/BuildScriptHost.cs b/src/Cake.Cli/Hosts/BuildScriptHost.cs
new file mode 100644
index 0000000000..ba7e6c9151
--- /dev/null
+++ b/src/Cake.Cli/Hosts/BuildScriptHost.cs
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading.Tasks;
+using Cake.Core;
+using Cake.Core.Diagnostics;
+using Cake.Core.Scripting;
+
+namespace Cake.Cli
+{
+ ///
+ /// The script host used to execute Cake scripts.
+ ///
+ public sealed class BuildScriptHost : BuildScriptHost
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The engine.
+ /// The execution strategy.
+ /// The context.
+ /// The report printer.
+ /// The log.
+ public BuildScriptHost(
+ ICakeEngine engine,
+ IExecutionStrategy executionStrategy,
+ ICakeContext context,
+ ICakeReportPrinter reportPrinter,
+ ICakeLog log) : base(engine, executionStrategy, context, reportPrinter, log)
+ {
+ }
+ }
+
+ ///
+ /// The script host used to execute Cake scripts.
+ ///
+ /// The context type.
+ public class BuildScriptHost : ScriptHost
+ where TContext : ICakeContext
+ {
+ private readonly ICakeReportPrinter _reportPrinter;
+ private readonly ICakeLog _log;
+ private readonly IExecutionStrategy _executionStrategy;
+ private readonly TContext _context;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The engine.
+ /// The execution strategy.
+ /// The context.
+ /// The report printer.
+ /// The log.
+ public BuildScriptHost(
+ ICakeEngine engine,
+ IExecutionStrategy executionStrategy,
+ TContext context,
+ ICakeReportPrinter reportPrinter,
+ ICakeLog log) : base(engine, context)
+ {
+ _executionStrategy = executionStrategy;
+ _context = context;
+ _reportPrinter = reportPrinter;
+ _log = log;
+ }
+
+ ///
+ public override async Task RunTargetAsync(string target)
+ {
+ Settings.SetTarget(target);
+
+ var report = await Engine.RunTargetAsync(_context, _executionStrategy, Settings).ConfigureAwait(false);
+ if (report != null && !report.IsEmpty)
+ {
+ _reportPrinter.Write(report);
+ }
+
+ return report;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Cake/Features/Building/Hosts/DescriptionScriptHost.cs b/src/Cake.Cli/Hosts/DescriptionScriptHost.cs
similarity index 95%
rename from src/Cake/Features/Building/Hosts/DescriptionScriptHost.cs
rename to src/Cake.Cli/Hosts/DescriptionScriptHost.cs
index 1f8f6fb3b1..a6845ed13e 100644
--- a/src/Cake/Features/Building/Hosts/DescriptionScriptHost.cs
+++ b/src/Cake.Cli/Hosts/DescriptionScriptHost.cs
@@ -8,12 +8,12 @@
using Cake.Core;
using Cake.Core.Scripting;
-namespace Cake.Features.Building.Hosts
+namespace Cake.Cli
{
///
/// The script host used for showing task descriptions.
///
- public sealed class DescriptionScriptHost : ScriptHost
+ public class DescriptionScriptHost : ScriptHost
{
private readonly IConsole _console;
private readonly Dictionary _descriptions;
diff --git a/src/Cake/Features/Building/Hosts/DryRunExecutionStrategy.cs b/src/Cake.Cli/Hosts/DryRunExecutionStrategy.cs
similarity index 98%
rename from src/Cake/Features/Building/Hosts/DryRunExecutionStrategy.cs
rename to src/Cake.Cli/Hosts/DryRunExecutionStrategy.cs
index aab1a5a0b0..e8331f2334 100644
--- a/src/Cake/Features/Building/Hosts/DryRunExecutionStrategy.cs
+++ b/src/Cake.Cli/Hosts/DryRunExecutionStrategy.cs
@@ -7,7 +7,7 @@
using Cake.Core;
using Cake.Core.Diagnostics;
-namespace Cake.Features.Building.Hosts
+namespace Cake.Cli
{
internal sealed class DryRunExecutionStrategy : IExecutionStrategy
{
diff --git a/src/Cake/Features/Building/Hosts/DryRunScriptHost.cs b/src/Cake.Cli/Hosts/DryRunScriptHost.cs
similarity index 67%
rename from src/Cake/Features/Building/Hosts/DryRunScriptHost.cs
rename to src/Cake.Cli/Hosts/DryRunScriptHost.cs
index e1b618dcce..92baff08ae 100644
--- a/src/Cake/Features/Building/Hosts/DryRunScriptHost.cs
+++ b/src/Cake.Cli/Hosts/DryRunScriptHost.cs
@@ -8,15 +8,13 @@
using Cake.Core.Diagnostics;
using Cake.Core.Scripting;
-namespace Cake.Features.Building.Hosts
+namespace Cake.Cli
{
///
/// The script host used to dry run Cake scripts.
///
- public sealed class DryRunScriptHost : ScriptHost
+ public sealed class DryRunScriptHost : DryRunScriptHost
{
- private readonly ICakeLog _log;
-
///
/// Initializes a new instance of the class.
///
@@ -24,6 +22,27 @@ public sealed class DryRunScriptHost : ScriptHost
/// The context.
/// The log.
public DryRunScriptHost(ICakeEngine engine, ICakeContext context, ICakeLog log)
+ : base(engine, context, log)
+ {
+ }
+ }
+
+ ///
+ /// The script host used to dry run Cake scripts.
+ ///
+ /// The context.
+ public class DryRunScriptHost : ScriptHost
+ where TContext : ICakeContext
+ {
+ private readonly ICakeLog _log;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The engine.
+ /// The context.
+ /// The log.
+ public DryRunScriptHost(ICakeEngine engine, TContext context, ICakeLog log)
: base(engine, context)
{
_log = log ?? throw new ArgumentNullException(nameof(log));
diff --git a/src/Cake/Features/Building/Hosts/TreeScriptHost.cs b/src/Cake.Cli/Hosts/TreeScriptHost.cs
similarity index 99%
rename from src/Cake/Features/Building/Hosts/TreeScriptHost.cs
rename to src/Cake.Cli/Hosts/TreeScriptHost.cs
index 76a5b7b322..b31048c201 100644
--- a/src/Cake/Features/Building/Hosts/TreeScriptHost.cs
+++ b/src/Cake.Cli/Hosts/TreeScriptHost.cs
@@ -10,7 +10,7 @@
using Cake.Core.Graph;
using Cake.Core.Scripting;
-namespace Cake.Features.Building.Hosts
+namespace Cake.Cli
{
///
/// The script host used for showing task descriptions.
diff --git a/src/Cake/Infrastructure/Converters/FilePathConverter.cs b/src/Cake.Cli/Infrastructure/FilePathConverter.cs
similarity index 51%
rename from src/Cake/Infrastructure/Converters/FilePathConverter.cs
rename to src/Cake.Cli/Infrastructure/FilePathConverter.cs
index c5697d1415..f8932244f2 100644
--- a/src/Cake/Infrastructure/Converters/FilePathConverter.cs
+++ b/src/Cake.Cli/Infrastructure/FilePathConverter.cs
@@ -7,10 +7,14 @@
using System.Globalization;
using Cake.Core.IO;
-namespace Cake.Infrastructure.Converters
+namespace Cake.Cli
{
+ ///
+ /// A type converter for .
+ ///
public sealed class FilePathConverter : TypeConverter
{
+ ///
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string stringValue)
@@ -21,4 +25,21 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
throw new NotSupportedException("Can't convert value to file path.");
}
}
+
+ ///
+ /// A type converter for .
+ ///
+ public sealed class DirectoryPathConverter : TypeConverter
+ {
+ ///
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ if (value is string stringValue)
+ {
+ return new DirectoryPath(stringValue);
+ }
+
+ throw new NotSupportedException("Can't convert value to file path.");
+ }
+ }
}
diff --git a/src/Cake/Infrastructure/Converters/VerbosityConverter.cs b/src/Cake.Cli/Infrastructure/VerbosityConverter.cs
similarity index 87%
rename from src/Cake/Infrastructure/Converters/VerbosityConverter.cs
rename to src/Cake.Cli/Infrastructure/VerbosityConverter.cs
index e229ea5648..7ee38940c6 100644
--- a/src/Cake/Infrastructure/Converters/VerbosityConverter.cs
+++ b/src/Cake.Cli/Infrastructure/VerbosityConverter.cs
@@ -9,12 +9,18 @@
using Cake.Core;
using Cake.Core.Diagnostics;
-namespace Cake.Infrastructure.Converters
+namespace Cake.Cli
{
+ ///
+ /// A type converter for .
+ ///
public sealed class VerbosityConverter : TypeConverter
{
private readonly Dictionary _lookup;
+ ///
+ /// Initializes a new instance of the class.
+ ///
public VerbosityConverter()
{
_lookup = new Dictionary(StringComparer.OrdinalIgnoreCase)
@@ -32,6 +38,7 @@ public VerbosityConverter()
};
}
+ ///
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string stringValue)
diff --git a/src/Cake.Core/Diagnostics/CakeDebugger.cs b/src/Cake.Core/Diagnostics/CakeDebugger.cs
index 8e9ed49987..263a1b0660 100644
--- a/src/Cake.Core/Diagnostics/CakeDebugger.cs
+++ b/src/Cake.Core/Diagnostics/CakeDebugger.cs
@@ -5,15 +5,26 @@
namespace Cake.Core.Diagnostics
{
- internal sealed class CakeDebugger : ICakeDebugger
+ ///
+ /// The Cake debugger.
+ ///
+ public sealed class CakeDebugger : ICakeDebugger
{
private readonly ICakeLog _log;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The log.
public CakeDebugger(ICakeLog log)
{
_log = log;
}
+ ///
+ /// Waits for a debugger to attach.
+ ///
+ /// The timeout.
public void WaitForAttach(TimeSpan timeout)
{
var processId = Process.GetCurrentProcess().Id;
diff --git a/src/Cake.Core/Graph/CakeGraph.cs b/src/Cake.Core/Graph/CakeGraph.cs
index 7e29e2e973..fcfbad6b30 100644
--- a/src/Cake.Core/Graph/CakeGraph.cs
+++ b/src/Cake.Core/Graph/CakeGraph.cs
@@ -11,7 +11,7 @@ namespace Cake.Core.Graph
///
/// Represents the Cake task graph.
///
- internal sealed class CakeGraph
+ public sealed class CakeGraph
{
private readonly List _nodes;
private readonly List _edges;
diff --git a/src/Cake.Core/Graph/CakeGraphBuilder.cs b/src/Cake.Core/Graph/CakeGraphBuilder.cs
index f91f7d9c09..0aa695fea3 100644
--- a/src/Cake.Core/Graph/CakeGraphBuilder.cs
+++ b/src/Cake.Core/Graph/CakeGraphBuilder.cs
@@ -10,7 +10,7 @@ namespace Cake.Core.Graph
///
/// Responsible for building the Cake task graph.
///
- internal static class CakeGraphBuilder
+ public static class CakeGraphBuilder
{
///
/// Builds a from the specified tasks.
diff --git a/src/Cake.Core/Graph/CakeGraphEdge.cs b/src/Cake.Core/Graph/CakeGraphEdge.cs
index f464f2a473..b54169a7c6 100644
--- a/src/Cake.Core/Graph/CakeGraphEdge.cs
+++ b/src/Cake.Core/Graph/CakeGraphEdge.cs
@@ -7,7 +7,7 @@ namespace Cake.Core.Graph
///
/// Represents an edge in a .
///
- internal sealed class CakeGraphEdge
+ public sealed class CakeGraphEdge
{
///
/// Gets the start node of the edge.
diff --git a/src/Cake.Core/Modules/CoreModule.cs b/src/Cake.Core/Modules/CoreModule.cs
index 0f612804fb..693bd4d5f1 100644
--- a/src/Cake.Core/Modules/CoreModule.cs
+++ b/src/Cake.Core/Modules/CoreModule.cs
@@ -33,6 +33,7 @@ public void Register(ICakeContainerRegistrar registrar)
registrar.RegisterType().As().Singleton();
registrar.RegisterType().As().Singleton();
registrar.RegisterType().As().As().Singleton();
+ registrar.RegisterType().As().Singleton();
// Environment
registrar.RegisterType().As().Singleton();
diff --git a/src/Cake.Core/Scripting/IScriptHost.cs b/src/Cake.Core/Scripting/IScriptHost.cs
index 8f650cb55a..c61660b21f 100644
--- a/src/Cake.Core/Scripting/IScriptHost.cs
+++ b/src/Cake.Core/Scripting/IScriptHost.cs
@@ -25,6 +25,11 @@ public interface IScriptHost
/// The registered tasks.
IReadOnlyList Tasks { get; }
+ ///
+ /// Gets the execution settings.
+ ///
+ ExecutionSettings Settings { get; }
+
///
/// Registers a new task.
///
diff --git a/src/Cake.Core/Scripting/ScriptHost.cs b/src/Cake.Core/Scripting/ScriptHost.cs
index d8161541f9..c8c9544474 100644
--- a/src/Cake.Core/Scripting/ScriptHost.cs
+++ b/src/Cake.Core/Scripting/ScriptHost.cs
@@ -36,16 +36,8 @@ public abstract class ScriptHost : IScriptHost
/// The context.
protected ScriptHost(ICakeEngine engine, ICakeContext context)
{
- if (engine == null)
- {
- throw new ArgumentNullException(nameof(engine));
- }
- if (context == null)
- {
- throw new ArgumentNullException(nameof(context));
- }
- Engine = engine;
- Context = context;
+ Engine = engine ?? throw new ArgumentNullException(nameof(engine));
+ Context = context ?? throw new ArgumentNullException(nameof(context));
Settings = new ExecutionSettings();
}
diff --git a/src/Cake.Frosting.Example/Cake.Frosting.Example.csproj b/src/Cake.Frosting.Example/Cake.Frosting.Example.csproj
index 7d8884ead1..c73cadaa6a 100644
--- a/src/Cake.Frosting.Example/Cake.Frosting.Example.csproj
+++ b/src/Cake.Frosting.Example/Cake.Frosting.Example.csproj
@@ -5,6 +5,7 @@
Exe
7
true
+ $(MSBuildProjectDirectory)..
diff --git a/src/Cake.Frosting.Example/Program.cs b/src/Cake.Frosting.Example/Program.cs
index 4bb5c1a948..0331c75490 100644
--- a/src/Cake.Frosting.Example/Program.cs
+++ b/src/Cake.Frosting.Example/Program.cs
@@ -2,28 +2,60 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace Cake.Frosting.Example
+using System.Threading.Tasks;
+using Cake.Core;
+using Cake.Core.Diagnostics;
+using Cake.Frosting;
+
+public static class Program
{
- public class Program
+ public static int Main(string[] args)
{
- public static int Main(string[] args)
- {
- // Create the host.
- var host = new CakeHostBuilder()
- .UseStartup()
- .WithArguments(args)
- .Build();
-
- // Run the host.
- return host.Run();
- }
+ return new CakeHost()
+ .UseContext()
+ .Run(args);
+ }
+}
+
+public class BuildContext : FrostingContext
+{
+ public bool Delay { get; set; }
+
+ public BuildContext(ICakeContext context)
+ : base(context)
+ {
+ Delay = context.Arguments.HasArgument("delay");
}
+}
- public class Startup : IFrostingStartup
+[TaskName("Hello")]
+public sealed class HelloTask : FrostingTask
+{
+ public override void Run(BuildContext context)
+ {
+ context.Log.Information("Hello");
+ }
+}
+
+[TaskName("World")]
+[IsDependentOn(typeof(HelloTask))]
+public sealed class WorldTask : AsyncFrostingTask
+{
+ // Tasks can be asynchronous
+ public override async Task RunAsync(BuildContext context)
{
- public void Configure(ICakeServices services)
+ if (context.Delay)
{
- services.UseContext();
+ context.Log.Information("Waiting...");
+ await Task.Delay(1500);
}
+
+ context.Log.Information("World");
}
+}
+
+[TaskName("Default")]
+[IsDependentOn(typeof(WorldTask))]
+public class DefaultTask : FrostingTask
+{
}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Example/Settings.cs b/src/Cake.Frosting.Example/Settings.cs
deleted file mode 100644
index d000f2f4bb..0000000000
--- a/src/Cake.Frosting.Example/Settings.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core;
-
-namespace Cake.Frosting.Example
-{
- public class Settings : FrostingContext
- {
- public bool Magic { get; set; }
-
- public Settings(ICakeContext context)
- : base(context)
- {
- // You could also use a CakeLifeTime
- // to provide a Setup method to setup the context.
- Magic = context.Arguments.HasArgument("magic");
- }
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Example/Tasks.cs b/src/Cake.Frosting.Example/Tasks.cs
deleted file mode 100644
index 8e3f75a94c..0000000000
--- a/src/Cake.Frosting.Example/Tasks.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Threading.Tasks;
-using Cake.Core;
-using Cake.Core.Diagnostics;
-
-namespace Cake.Frosting.Example
-{
- public sealed class Hello : FrostingTask
- {
- }
-
- [Dependency(typeof(Hello))]
- public sealed class World : AsyncFrostingTask
- {
- // Tasks can be asynchronous
- public override async Task RunAsync(Settings context)
- {
- context.Log.Information("About to do something expensive");
- await Task.Delay(1500);
- context.Log.Information("Done");
- }
- }
-
- [Dependency(typeof(World))]
- public sealed class Magic : FrostingTask
- {
- public override bool ShouldRun(Settings context)
- {
- // Don't run this task on OSX.
- return context.Environment.Platform.Family != PlatformFamily.OSX;
- }
-
- public override void Run(Settings context)
- {
- context.Log.Information("Value is: {0}", context.Magic);
- }
- }
-
- [TaskName("Default")]
- [Dependency(typeof(Magic))]
- public class DefaultTask : FrostingTask
- {
- }
-}
diff --git a/src/Cake.Frosting.Template/Cake.Frosting.Template.csproj b/src/Cake.Frosting.Template/Cake.Frosting.Template.csproj
index 205829e861..ff838c4e3e 100644
--- a/src/Cake.Frosting.Template/Cake.Frosting.Template.csproj
+++ b/src/Cake.Frosting.Template/Cake.Frosting.Template.csproj
@@ -1,4 +1,4 @@
-
+
Template
@@ -6,23 +6,25 @@
Cake.Frosting templates for the .NET SDK.
Cake.Frosting templates for the .NET SDK.
netcoreapp3.1
-
true
false
content
- NU5110;NU5111;NU5128
+ $(NoWarn);NU5110;NU5111;NU5128
+ true
-
-
-
+
+
+
+
+
diff --git a/src/Cake.Frosting.Template/build.ps1 b/src/Cake.Frosting.Template/build.ps1
deleted file mode 100644
index 90d183fc2c..0000000000
--- a/src/Cake.Frosting.Template/build.ps1
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env pwsh
-$DotNetInstallerUri = 'https://dot.net/v1/dotnet-install.ps1';
-$DotNetUnixInstallerUri = 'https://dot.net/v1/dotnet-install.sh'
-$DotNetChannel = 'LTS'
-$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
-
-[string] $DotNetVersion= ''
-foreach($line in Get-Content (Join-Path $PSScriptRoot 'build.config'))
-{
- if ($line -like 'DOTNET_VERSION=*') {
- $DotNetVersion =$line.SubString(15)
- }
-}
-
-
-if ([string]::IsNullOrEmpty($DotNetVersion)) {
- 'Failed to parse .NET Core SDK Version'
- exit 1
-}
-
-$DotNetInstallerUri = "https://dot.net/v1/dotnet-install.ps1";
-
-# Make sure tools folder exists
-$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
-$ToolPath = Join-Path $PSScriptRoot "tools"
-if (!(Test-Path $ToolPath)) {
- Write-Verbose "Creating tools directory..."
- New-Item -Path $ToolPath -Type directory | out-null
-}
-
-###########################################################################
-# INSTALL .NET CORE CLI
-###########################################################################
-
-Function Remove-PathVariable([string]$VariableToRemove)
-{
- $path = [Environment]::GetEnvironmentVariable("PATH", "User")
- $newItems = $path.Split(';') | Where-Object { $_.ToString() -inotlike $VariableToRemove }
- [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "User")
- $path = [Environment]::GetEnvironmentVariable("PATH", "Process")
- $newItems = $path.Split(';') | Where-Object { $_.ToString() -inotlike $VariableToRemove }
- [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "Process")
-}
-
-# Get .NET Core CLI path if installed.
-$FoundDotNetCliVersion = $null;
-if (Get-Command dotnet -ErrorAction SilentlyContinue) {
- $FoundDotNetCliVersion = dotnet --version;
-}
-
-if($FoundDotNetCliVersion -ne $DotNetVersion) {
- $InstallPath = Join-Path $PSScriptRoot ".dotnet"
- if (!(Test-Path $InstallPath)) {
- mkdir -Force $InstallPath | Out-Null;
- }
- (New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, "$InstallPath\dotnet-install.ps1");
- & $InstallPath\dotnet-install.ps1 -Version $DotNetVersion -InstallDir $InstallPath;
-
- Remove-PathVariable "$InstallPath"
- $env:PATH = "$InstallPath;$env:PATH"
- $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
- $env:DOTNET_CLI_TELEMETRY_OPTOUT=1
-}
-
-###########################################################################
-# RUN BUILD SCRIPT
-###########################################################################
-
-dotnet run --project build/Build.csproj -- $args
-exit $LASTEXITCODE;
\ No newline at end of file
diff --git a/src/Cake.Frosting.Template/build.sh b/src/Cake.Frosting.Template/build.sh
deleted file mode 100755
index bd9974b730..0000000000
--- a/src/Cake.Frosting.Template/build.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env bash
-# Define varibles
-SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-source $SCRIPT_DIR/build.config
-
-if [ "$DOTNET_VERSION" = "" ]; then
- echo "An error occured while parsing .NET Core SDK version."
- exit 1
-fi
-
-###########################################################################
-# INSTALL .NET CORE CLI
-###########################################################################
-
-export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
-export DOTNET_CLI_TELEMETRY_OPTOUT=1
-export DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0
-export DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2
-
-DOTNET_INSTALLED_VERSION=$(dotnet --version 2>&1)
-
-if [ "$DOTNET_VERSION" != "$DOTNET_INSTALLED_VERSION" ]; then
- echo "Installing .NET CLI..."
- if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then
- mkdir "$SCRIPT_DIR/.dotnet"
- fi
- curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" https://dot.net/v1/dotnet-install.sh
- bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --version $DOTNET_VERSION --install-dir .dotnet --no-path
- export PATH="$SCRIPT_DIR/.dotnet":$PATH
- export DOTNET_ROOT="$SCRIPT_DIR/.dotnet"
-fi
-
-###########################################################################
-# RUN BUILD SCRIPT
-###########################################################################
-
-echo "Running build script.."
-dotnet run --project ./build/Build.csproj -- "$@"
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build.ps1 b/src/Cake.Frosting.Template/templates/cakefrosting/build.ps1
new file mode 100644
index 0000000000..a7077190ae
--- /dev/null
+++ b/src/Cake.Frosting.Template/templates/cakefrosting/build.ps1
@@ -0,0 +1,2 @@
+dotnet run --project build/Build.csproj -- $args
+exit $LASTEXITCODE;
\ No newline at end of file
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build.sh b/src/Cake.Frosting.Template/templates/cakefrosting/build.sh
new file mode 100644
index 0000000000..dfd6b854b7
--- /dev/null
+++ b/src/Cake.Frosting.Template/templates/cakefrosting/build.sh
@@ -0,0 +1 @@
+dotnet run --project ./build/Build.csproj -- "$@"
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build/Build.csproj b/src/Cake.Frosting.Template/templates/cakefrosting/build/Build.csproj
index bdae2f0327..f4e23a563b 100644
--- a/src/Cake.Frosting.Template/templates/cakefrosting/build/Build.csproj
+++ b/src/Cake.Frosting.Template/templates/cakefrosting/build/Build.csproj
@@ -2,9 +2,7 @@
Exe
netcoreapp3.1
- true
-
- $(MSBuildProjectDirectory)
+ $(MSBuildProjectDirectory)..
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build/Context.cs b/src/Cake.Frosting.Template/templates/cakefrosting/build/Context.cs
deleted file mode 100644
index 2e70b09a50..0000000000
--- a/src/Cake.Frosting.Template/templates/cakefrosting/build/Context.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Cake.Core;
-using Cake.Frosting;
-
-public class Context : FrostingContext
-{
- public Context(ICakeContext context)
- : base(context)
- {
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build/Lifetime.cs b/src/Cake.Frosting.Template/templates/cakefrosting/build/Lifetime.cs
deleted file mode 100644
index 999f1e85ad..0000000000
--- a/src/Cake.Frosting.Template/templates/cakefrosting/build/Lifetime.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Cake.Common.Diagnostics;
-using Cake.Core;
-using Cake.Frosting;
-
-public sealed class Lifetime : FrostingLifetime
-{
- public override void Setup(Context context)
- {
- context.Information("Setting things up...");
- }
-
- public override void Teardown(Context context, ITeardownContext info)
- {
- context.Information("Tearing things down...");
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build/Program.cs b/src/Cake.Frosting.Template/templates/cakefrosting/build/Program.cs
index a5c08a1052..76a13189a0 100644
--- a/src/Cake.Frosting.Template/templates/cakefrosting/build/Program.cs
+++ b/src/Cake.Frosting.Template/templates/cakefrosting/build/Program.cs
@@ -1,24 +1,55 @@
using Cake.Core;
using Cake.Frosting;
-public class Program : IFrostingStartup
+public static class Program
{
public static int Main(string[] args)
{
- // Create the host.
- var host = new CakeHostBuilder()
- .WithArguments(args)
- .UseStartup()
- .Build();
+ return new CakeHost()
+ .UseContext()
+ .Run(args);
+ }
+}
+
+public class Settings : FrostingContext
+{
+ public bool Delay { get; set; }
+
+ public Settings(ICakeContext context)
+ : base(context)
+ {
+ Delay = context.Arguments.HasArgument("delay");
+ }
+}
- // Run the host.
- return host.Run();
+[TaskName("Hello")]
+public sealed class HelloTask : FrostingTask
+{
+ public override void Run(Settings context)
+ {
+ context.Log.Information("Hello");
}
+}
- public void Configure(ICakeServices services)
+[TaskName("World")]
+[IsDependentOn(typeof(HelloTask))]
+public sealed class WorldTask : AsyncFrostingTask
+{
+ // Tasks can be asynchronous
+ public override async Task RunAsync(Settings context)
{
- services.UseContext();
- services.UseLifetime();
- services.UseWorkingDirectory("..");
+ if (context.Delay)
+ {
+ context.Log.Information("Waiting...");
+ await Task.Delay(1500);
+ }
+
+ context.Log.Information("World");
}
+}
+
+[TaskName("Default")]
+[IsDependentOn(typeof(WorldTask))]
+public class DefaultTask : FrostingTask
+{
}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build/Tasks/Default.cs b/src/Cake.Frosting.Template/templates/cakefrosting/build/Tasks/Default.cs
deleted file mode 100644
index 7d2ab0b182..0000000000
--- a/src/Cake.Frosting.Template/templates/cakefrosting/build/Tasks/Default.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using Cake.Frosting;
-
-[Dependency(typeof(Hello))]
-public sealed class Default : FrostingTask
-{
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Template/templates/cakefrosting/build/Tasks/Hello.cs b/src/Cake.Frosting.Template/templates/cakefrosting/build/Tasks/Hello.cs
deleted file mode 100644
index e01777b78e..0000000000
--- a/src/Cake.Frosting.Template/templates/cakefrosting/build/Tasks/Hello.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Cake.Common.Diagnostics;
-using Cake.Frosting;
-
-[TaskName("Hello")]
-public sealed class Hello : FrostingTask
-{
- public override void Run(Context context)
- {
- context.Information("Hello World");
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Tests/Asserts/ExecptionAsserts.cs b/src/Cake.Frosting.Tests/Asserts/ExecptionAsserts.cs
deleted file mode 100644
index 56adc8c596..0000000000
--- a/src/Cake.Frosting.Tests/Asserts/ExecptionAsserts.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-
-// ReSharper disable once CheckNamespace
-namespace Xunit
-{
- public class AssertEx
- {
- public static void IsArgumentNullException(Exception exception, string parameterName)
- {
- Assert.IsType(exception);
- Assert.Equal(parameterName, ((ArgumentNullException)exception).ParamName);
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/CakeHostTests.cs b/src/Cake.Frosting.Tests/CakeHostTests.cs
new file mode 100644
index 0000000000..8fb0d43772
--- /dev/null
+++ b/src/Cake.Frosting.Tests/CakeHostTests.cs
@@ -0,0 +1,297 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Cake.Core;
+using Cake.Core.Diagnostics;
+using Cake.Core.Packaging;
+using Cake.Testing;
+using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
+using Xunit;
+
+namespace Cake.Frosting.Tests
+{
+ public sealed partial class CakeHostTests
+ {
+ [Fact]
+ public void Should_Set_Working_Directory_From_Options_If_Set()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+ fixture.Host.UseWorkingDirectory("./Foo");
+ fixture.FileSystem.CreateDirectory("/Working/Foo");
+
+ // When
+ fixture.Run();
+
+ // Then
+ Assert.Equal("/Working/Foo", fixture.Environment.WorkingDirectory.FullPath);
+ }
+
+ [Fact]
+ public void Should_Prefer_Working_Directory_From_Options_Over_Configuration()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+ fixture.FileSystem.CreateDirectory("/Working/Foo");
+ fixture.FileSystem.CreateDirectory("/Working/Bar");
+ fixture.Host.UseWorkingDirectory("./Foo");
+
+ // When
+ fixture.Run("-w", "./Bar");
+
+ // Then
+ Assert.Equal("/Working/Bar", fixture.Environment.WorkingDirectory.FullPath);
+ }
+
+ [Fact]
+ public void Should_Call_Setup_On_Registered_Setup_Lifetime()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ var lifetime = new FakeLifetime();
+ fixture.Host.ConfigureServices(services => services.AddSingleton(lifetime));
+
+ // When
+ var result = fixture.Run("--target", "dummytask");
+
+ // Then
+ Assert.Equal(0, result);
+ Assert.Equal(1, lifetime.SetupCount);
+ }
+
+ [Fact]
+ public void Should_Call_Teardown_On_Registered_Teardown_Lifetime()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ var lifetime = new FakeLifetime();
+ fixture.Host.ConfigureServices(services => services.AddSingleton(lifetime));
+
+ // When
+ var result = fixture.Run("--target", "dummytask");
+
+ // Then
+ Assert.Equal(0, result);
+ Assert.Equal(1, lifetime.TeardownCount);
+ }
+
+ [Fact]
+ public void Should_Call_Setup_On_Registered_Task_Lifetime()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ var lifetime = new FakeTaskLifetime();
+ fixture.Host.ConfigureServices(services => services.AddSingleton(lifetime));
+
+ // When
+ var result = fixture.Run("--target", "dummytask");
+
+ // Then
+ Assert.Equal(0, result);
+ Assert.Equal(1, lifetime.SetupCount);
+ }
+
+ [Fact]
+ public void Should_Call_Teardown_On_Registered_Task_Lifetime()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ var lifetime = new FakeTaskLifetime();
+ fixture.Host.ConfigureServices(services => services.AddSingleton(lifetime));
+
+ // When
+ var result = fixture.Run("--target", "dummytask");
+
+ // Then
+ Assert.Equal(0, result);
+ Assert.Equal(1, lifetime.TeardownCount);
+ }
+
+ [Fact]
+ public void Should_Execute_Tasks()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.Strategy = Substitute.For();
+ fixture.RegisterTask();
+
+ // When
+ var result = fixture.Run("--target", "dummytask");
+
+ // Then
+ fixture.Strategy
+ .Received(1)
+ .ExecuteAsync(Arg.Is(t => t.Name == "DummyTask"), Arg.Any());
+ }
+
+ [Fact]
+ public void Should_Not_Abort_Build_If_Task_That_Is_ContinueOnError_Throws()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ // When
+ var result = fixture.Run("--target", "ContinueOnErrorTask");
+
+ // Then
+ Assert.Equal(0, result);
+ }
+
+ [Fact]
+ public void Should_Abort_Build_If_Task_That_Is_Not_ContinueOnError_Throws()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ // When
+ var result = fixture.Run("--target", "ThrowingTask");
+
+ // Then
+ Assert.NotEqual(0, result);
+ }
+
+ [Fact]
+ public void Should_Execute_Tasks_In_Correct_Order()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+ fixture.RegisterTask();
+ fixture.RegisterTask();
+ fixture.Strategy = Substitute.For();
+
+ // When
+ fixture.Run("--target", "UnitTestsTask");
+
+ // Then
+ Received.InOrder(() =>
+ {
+ fixture.Strategy.ExecuteAsync(Arg.Is(t => t.Name == "CleanTask"), Arg.Any());
+ fixture.Strategy.ExecuteAsync(Arg.Is(t => t.Name == "BuildTask"), Arg.Any());
+ fixture.Strategy.ExecuteAsync(Arg.Is(t => t.Name == "UnitTestsTask"), Arg.Any());
+ });
+ }
+
+ [Fact]
+ public void Should_Throw_If_Dependency_Is_Not_A_Valid_Task()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+ fixture.Strategy = Substitute.For();
+
+ // When
+ var result = fixture.Run("--target", "InvalidDependencyTask");
+
+ // Then
+ Assert.NotEqual(0, result);
+ fixture.Log.Received(1).Error("Error: {0}", "The dependency 'DateTime' is not a valid task.");
+ }
+
+ [Fact]
+ public void Should_Return_Zero_On_Success()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ // When
+ var result = fixture.Run("--target", "dummytask");
+
+ // Then
+ Assert.Equal(0, result);
+ }
+
+ [Fact]
+ public void Should_Execute_OnError_Method_If_Run_Failed()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ // When
+ fixture.Run("--target", "OnErrorRunFailedTask");
+
+ // Then
+ fixture.Log.Received(1).Error("OnError: {0}", "An exception");
+ }
+
+ [Fact]
+ public void Should_Execute_OnError_Method_If_RunAsync_Failed()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ // When
+ fixture.Run("--target", "OnErrorRunAsyncFailedTask");
+
+ // Then
+ fixture.Log.Received(1).Error("OnError: {0}", "An exception");
+ }
+
+ [Fact]
+ public void Should_Not_Execute_OnError_Method_If_Run_Completed()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ // When
+ fixture.Run("--target", "OnErrorRunCompletedTask");
+
+ // Then
+ fixture.Log.DidNotReceive().Error("OnError: {0}", "An exception");
+ }
+
+ [Fact]
+ public void Should_Execute_Finally_Method_After_All_Methods()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.RegisterTask();
+
+ // When
+ fixture.Run("--target", "FinallyTask");
+
+ // Then
+ Received.InOrder(() =>
+ {
+ fixture.Log.Information("Run method called");
+ fixture.Log.Information("OnError method called");
+ fixture.Log.Information("Finally method called");
+ });
+ }
+
+ [Fact]
+ public void Should_Install_Tools()
+ {
+ // Given
+ var fixture = new CakeHostFixture();
+ fixture.Host.ConfigureServices(s => s.UseTool(new Uri("foo:?package=Bar")));
+ fixture.RegisterTask();
+
+ // When
+ var result = fixture.Run("--target", "dummytask");
+
+ // Then
+ fixture.Installer.Received(1).Install(
+ Arg.Is(p => p.OriginalString == "foo:?package=Bar"));
+ }
+ }
+}
diff --git a/src/Cake.Frosting.Tests/Data/DummyModule.cs b/src/Cake.Frosting.Tests/Data/DummyModule.cs
deleted file mode 100644
index 0a15b0b158..0000000000
--- a/src/Cake.Frosting.Tests/Data/DummyModule.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core.Composition;
-
-namespace Cake.Frosting.Tests.Data
-{
- public class DummyModule : ICakeModule
- {
- public sealed class DummyModuleSentinel
- {
- }
-
- public void Register(ICakeContainerRegistrar registrar)
- {
- registrar.RegisterType();
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Data/DummyPackageInstaller.cs b/src/Cake.Frosting.Tests/Data/DummyPackageInstaller.cs
deleted file mode 100644
index 7ebc1e7722..0000000000
--- a/src/Cake.Frosting.Tests/Data/DummyPackageInstaller.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using Cake.Core.IO;
-using Cake.Core.Packaging;
-
-namespace Cake.Frosting.Tests.Data
-{
- public class DummyPackageInstaller : IPackageInstaller
- {
- public bool CanInstall(PackageReference package, PackageType type)
- {
- return true;
- }
-
- public IReadOnlyCollection Install(PackageReference package, PackageType type, DirectoryPath path)
- {
- return new List();
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Data/DummyStartup.cs b/src/Cake.Frosting.Tests/Data/DummyStartup.cs
deleted file mode 100644
index cdda2b4a0e..0000000000
--- a/src/Cake.Frosting.Tests/Data/DummyStartup.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core.Composition;
-
-namespace Cake.Frosting.Tests.Data
-{
- public sealed class DummyStartup : IFrostingStartup
- {
- public sealed class DummyStartupSentinel
- {
- }
-
- public void Configure(ICakeServices services)
- {
- services.RegisterType();
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/NoContinueOnErrorTask.cs b/src/Cake.Frosting.Tests/Data/Tasks/NoContinueOnErrorTask.cs
deleted file mode 100644
index 82ac81d6e8..0000000000
--- a/src/Cake.Frosting.Tests/Data/Tasks/NoContinueOnErrorTask.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using Cake.Core;
-
-namespace Cake.Frosting.Tests.Data.Tasks
-{
- [TaskName("No-Continue-On-Error")]
- public sealed class NoContinueOnErrorTask : FrostingTask
- {
- public override void Run(ICakeContext context)
- {
- throw new InvalidOperationException();
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Extensions/CakeEngineExtensions.cs b/src/Cake.Frosting.Tests/Extensions/CakeEngineExtensions.cs
deleted file mode 100644
index 940160b915..0000000000
--- a/src/Cake.Frosting.Tests/Extensions/CakeEngineExtensions.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Linq;
-using Cake.Core;
-
-// ReSharper disable once CheckNamespace
-namespace Cake.Frosting.Testing
-{
- public static class CakeEngineExtensions
- {
- public static bool IsTaskRegistered(this ICakeEngine engine, string name)
- {
- return engine.Tasks.Any(e => e.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Fakes/FakeLifetime.cs b/src/Cake.Frosting.Tests/Fakes/FakeLifetime.cs
index 89ba358b98..b185ced0c9 100644
--- a/src/Cake.Frosting.Tests/Fakes/FakeLifetime.cs
+++ b/src/Cake.Frosting.Tests/Fakes/FakeLifetime.cs
@@ -4,25 +4,21 @@
using Cake.Core;
-namespace Cake.Frosting.Tests.Fakes
+namespace Cake.Frosting.Tests
{
public sealed class FakeLifetime : FrostingLifetime
{
- public bool CalledSetup { get; private set; }
- public bool CalledTeardown { get; private set; }
+ public int SetupCount { get; set; }
+ public int TeardownCount { get; set; }
public override void Setup(ICakeContext context)
{
- CalledSetup = true;
+ SetupCount++;
}
public override void Teardown(ICakeContext context, ITeardownContext info)
{
- CalledTeardown = true;
- }
-
- public sealed class WithoutOverrides : FrostingLifetime
- {
+ TeardownCount++;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Cake.Frosting.Tests/Fakes/FakeTaskLifetime.cs b/src/Cake.Frosting.Tests/Fakes/FakeTaskLifetime.cs
index f642339e20..a1bec3b5af 100644
--- a/src/Cake.Frosting.Tests/Fakes/FakeTaskLifetime.cs
+++ b/src/Cake.Frosting.Tests/Fakes/FakeTaskLifetime.cs
@@ -4,25 +4,21 @@
using Cake.Core;
-namespace Cake.Frosting.Tests.Fakes
+namespace Cake.Frosting.Tests
{
public sealed class FakeTaskLifetime : FrostingTaskLifetime
{
- public bool CalledSetup { get; private set; }
- public bool CalledTeardown { get; private set; }
+ public int SetupCount { get; set; }
+ public int TeardownCount { get; set; }
public override void Setup(ICakeContext context, ITaskSetupContext info)
{
- CalledSetup = true;
+ SetupCount++;
}
public override void Teardown(ICakeContext context, ITaskTeardownContext info)
{
- CalledTeardown = true;
- }
-
- public sealed class WithoutOverrides : FrostingTaskLifetime
- {
+ TeardownCount++;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Cake.Frosting.Tests/Fakes/NullConsole.cs b/src/Cake.Frosting.Tests/Fakes/NullConsole.cs
deleted file mode 100644
index bc70b429cc..0000000000
--- a/src/Cake.Frosting.Tests/Fakes/NullConsole.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using Cake.Core;
-
-namespace Cake.Frosting.Tests.Fakes
-{
- internal sealed class NullConsole : IConsole
- {
- public void Write(string format, params object[] arg)
- {
- }
-
- public void WriteLine(string format, params object[] arg)
- {
- }
-
- public void WriteError(string format, params object[] arg)
- {
- }
-
- public void WriteErrorLine(string format, params object[] arg)
- {
- }
-
- public void ResetColor()
- {
- }
-
- public ConsoleColor ForegroundColor { get; set; }
- public ConsoleColor BackgroundColor { get; set; }
- public bool SupportAnsiEscapeCodes => false;
- }
-}
diff --git a/src/Cake.Frosting.Tests/Fixtures/CakeHostBuilderFixture.cs b/src/Cake.Frosting.Tests/Fixtures/CakeHostBuilderFixture.cs
deleted file mode 100644
index 029fdb8c30..0000000000
--- a/src/Cake.Frosting.Tests/Fixtures/CakeHostBuilderFixture.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Reflection;
-using Cake.Core;
-using Cake.Core.Composition;
-using Cake.Core.Diagnostics;
-using Cake.Core.IO;
-using Cake.Frosting.Tests.Fakes;
-using Cake.Testing;
-using NSubstitute;
-
-namespace Cake.Frosting.Tests.Fixtures
-{
- public class CakeHostBuilderFixture
- {
- public CakeHostBuilder Builder { get; set; }
-
- public FakeFileSystem FileSystem { get; set; }
- public ICakeEnvironment Environment { get; set; }
- public ICakeEngine Engine { get; set; }
- public ICakeLog Log { get; set; }
- public ICakeDataService Data { get; set; }
- public IExecutionStrategy Strategy { get; set; }
- public IToolInstaller Installer { get; set; }
- public CakeHostOptions Options { get; set; }
-
- public CakeHostBuilderFixture()
- {
- Builder = new CakeHostBuilder();
- Environment = FakeEnvironment.CreateUnixEnvironment();
-
- FileSystem = new FakeFileSystem(Environment);
- FileSystem.CreateDirectory("/Working");
-
- Log = Substitute.For();
- Data = Substitute.For();
- Engine = new CakeEngine(Data, Log);
- Installer = Substitute.For();
- Options = new CakeHostOptions();
- }
-
- public ICakeHost Build()
- {
- // Replace registrations with more suitable ones.
- Builder.ConfigureServices(s => s.RegisterType().As());
- Builder.ConfigureServices(s => s.RegisterInstance(Environment).As());
- Builder.ConfigureServices(s => s.RegisterInstance(FileSystem).As());
- Builder.ConfigureServices(s => s.RegisterInstance(Engine).As());
- Builder.ConfigureServices(s => s.RegisterInstance(Log).As());
- Builder.ConfigureServices(s => s.RegisterInstance(Installer).As());
- Builder.ConfigureServices(s => s.RegisterInstance(Options).As());
-
- if (Strategy != null)
- {
- Builder.ConfigureServices(services => services.RegisterInstance(Strategy).As());
- }
-
- Builder.ConfigureServices(s => s.RegisterInstance(Options).AsSelf().Singleton());
-
- return Builder.Build();
- }
-
- public int Run()
- {
- return Build().Run();
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Fixtures/CakeHostBuilderFixtureExtensions.cs b/src/Cake.Frosting.Tests/Fixtures/CakeHostBuilderFixtureExtensions.cs
deleted file mode 100644
index 8ba1ad164d..0000000000
--- a/src/Cake.Frosting.Tests/Fixtures/CakeHostBuilderFixtureExtensions.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core;
-using Cake.Core.Composition;
-using Cake.Frosting.Tests.Data;
-using Cake.Frosting.Tests.Fakes;
-using NSubstitute;
-
-namespace Cake.Frosting.Tests.Fixtures
-{
- internal static class CakeHostBuilderFixtureExtensions
- {
- public static CakeHostBuilderFixture RegisterDefaultTask(this CakeHostBuilderFixture fixture)
- {
- fixture.RegisterTask();
- fixture.Options.Target = typeof(DummyTask).Name;
- return fixture;
- }
-
- public static CakeHostBuilderFixture RegisterTask(this CakeHostBuilderFixture fixture)
- where T : IFrostingTask
- {
- fixture.Builder.ConfigureServices(services => services.RegisterType().As());
- return fixture;
- }
-
- public static FakeLifetime RegisterLifetimeSubstitute(this CakeHostBuilderFixture fixture)
- {
- var lifetime = new FakeLifetime();
- return fixture.RegisterLifetimeSubstitute(lifetime);
- }
-
- public static T RegisterLifetimeSubstitute(this CakeHostBuilderFixture fixture, T lifetime)
- where T : class, IFrostingLifetime
- {
- fixture.Builder.ConfigureServices(s => s.RegisterInstance(lifetime).As());
- return lifetime;
- }
-
- public static FakeTaskLifetime RegisterTaskLifetimeSubstitute(this CakeHostBuilderFixture fixture)
- {
- var lifetime = new FakeTaskLifetime();
- return fixture.RegisterTaskLifetimeSubstitute(lifetime);
- }
-
- public static T RegisterTaskLifetimeSubstitute(this CakeHostBuilderFixture fixture, T lifetime)
- where T : class, IFrostingTaskLifetime
- {
- fixture.Builder.ConfigureServices(s => s.RegisterInstance(lifetime).As());
- return lifetime;
- }
-
- public static void UseExecutionStrategySubstitute(this CakeHostBuilderFixture fixture)
- {
- fixture.Strategy = Substitute.For();
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Fixtures/CakeHostFixture.cs b/src/Cake.Frosting.Tests/Fixtures/CakeHostFixture.cs
new file mode 100644
index 0000000000..1d81522b7c
--- /dev/null
+++ b/src/Cake.Frosting.Tests/Fixtures/CakeHostFixture.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Cake.Core;
+using Cake.Core.Diagnostics;
+using Cake.Core.IO;
+using Cake.Testing;
+using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
+
+namespace Cake.Frosting.Tests
+{
+ public sealed class CakeHostFixture
+ {
+ public CakeHost Host { get; set; }
+ public FakeEnvironment Environment { get; set; }
+ public FakeFileSystem FileSystem { get; set; }
+ public FakeConsole Console { get; set; }
+ public ICakeLog Log { get; set; }
+ public IExecutionStrategy Strategy { get; set; }
+ public IToolInstaller Installer { get; set; }
+
+ public CakeHostFixture()
+ {
+ Host = new CakeHost();
+ Environment = FakeEnvironment.CreateUnixEnvironment();
+ Console = new FakeConsole();
+ Log = Substitute.For();
+ Installer = Substitute.For();
+
+ FileSystem = new FakeFileSystem(Environment);
+ FileSystem.CreateDirectory("/Working");
+
+ Host.ConfigureServices(services => services.AddSingleton(FileSystem));
+ Host.ConfigureServices(services => services.AddSingleton(Environment));
+ Host.ConfigureServices(services => services.AddSingleton(Console));
+ Host.ConfigureServices(services => services.AddSingleton(Log));
+ Host.ConfigureServices(services => services.AddSingleton(Installer));
+ }
+
+ public void RegisterTask()
+ where T : class, IFrostingTask
+ {
+ Host.ConfigureServices(services => services.AddSingleton());
+ }
+
+ public int Run(params string[] args)
+ {
+ if (Strategy != null)
+ {
+ Host.ConfigureServices(services => services.AddSingleton(Strategy));
+ }
+
+ return Host.Run(args);
+ }
+ }
+}
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/BuildTask.cs b/src/Cake.Frosting.Tests/Tasks/BuildTask.cs
similarity index 75%
rename from src/Cake.Frosting.Tests/Data/Tasks/BuildTask.cs
rename to src/Cake.Frosting.Tests/Tasks/BuildTask.cs
index 0146d021da..3f5c9ae0ed 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/BuildTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/BuildTask.cs
@@ -4,10 +4,9 @@
using Cake.Core;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [TaskName("Build")]
- [Dependency(typeof(CleanTask))]
+ [IsDependentOn(typeof(CleanTask))]
public sealed class BuildTask : FrostingTask
{
}
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/CleanTask.cs b/src/Cake.Frosting.Tests/Tasks/CleanTask.cs
similarity index 82%
rename from src/Cake.Frosting.Tests/Data/Tasks/CleanTask.cs
rename to src/Cake.Frosting.Tests/Tasks/CleanTask.cs
index 82c63e0830..57b0a35ba1 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/CleanTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/CleanTask.cs
@@ -4,9 +4,8 @@
using Cake.Core;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [TaskName("Clean")]
public sealed class CleanTask : FrostingTask
{
}
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/ContinueOnErrorTask.cs b/src/Cake.Frosting.Tests/Tasks/ContinueOnErrorTask.cs
similarity index 67%
rename from src/Cake.Frosting.Tests/Data/Tasks/ContinueOnErrorTask.cs
rename to src/Cake.Frosting.Tests/Tasks/ContinueOnErrorTask.cs
index 42288429e1..804fcd279c 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/ContinueOnErrorTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/ContinueOnErrorTask.cs
@@ -5,10 +5,9 @@
using System;
using Cake.Core;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
[ContinueOnError]
- [TaskName("Continue-On-Error")]
public sealed class ContinueOnErrorTask : FrostingTask
{
public override void Run(ICakeContext context)
@@ -16,4 +15,12 @@ public override void Run(ICakeContext context)
throw new InvalidOperationException();
}
}
+
+ public sealed class ThrowingTask : FrostingTask
+ {
+ public override void Run(ICakeContext context)
+ {
+ throw new InvalidOperationException();
+ }
+ }
}
diff --git a/src/Cake.Frosting.Tests/Data/DummyTask.cs b/src/Cake.Frosting.Tests/Tasks/DummyTask.cs
similarity index 74%
rename from src/Cake.Frosting.Tests/Data/DummyTask.cs
rename to src/Cake.Frosting.Tests/Tasks/DummyTask.cs
index 450ea455fb..16ef2aa90f 100644
--- a/src/Cake.Frosting.Tests/Data/DummyTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/DummyTask.cs
@@ -4,9 +4,12 @@
using Cake.Core;
-namespace Cake.Frosting.Tests.Data
+namespace Cake.Frosting.Tests
{
public sealed class DummyTask : FrostingTask
{
+ public override void Run(ICakeContext context)
+ {
+ }
}
}
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/FinallyTask.cs b/src/Cake.Frosting.Tests/Tasks/FinallyTask.cs
similarity index 92%
rename from src/Cake.Frosting.Tests/Data/Tasks/FinallyTask.cs
rename to src/Cake.Frosting.Tests/Tasks/FinallyTask.cs
index 8f992cb55a..7b9924c275 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/FinallyTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/FinallyTask.cs
@@ -6,9 +6,8 @@
using Cake.Core;
using Cake.Core.Diagnostics;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [TaskName("Finally")]
public sealed class FinallyTask : FrostingTask
{
public override void Run(ICakeContext context)
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/InvalidDependencyTask.cs b/src/Cake.Frosting.Tests/Tasks/InvalidDependencyTask.cs
similarity index 81%
rename from src/Cake.Frosting.Tests/Data/Tasks/InvalidDependencyTask.cs
rename to src/Cake.Frosting.Tests/Tasks/InvalidDependencyTask.cs
index 9ca93bdceb..94be68e2a1 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/InvalidDependencyTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/InvalidDependencyTask.cs
@@ -5,9 +5,9 @@
using System;
using Cake.Core;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [Dependency(typeof(DateTime))]
+ [IsDependentOn(typeof(DateTime))]
public sealed class InvalidDependencyTask : FrostingTask
{
}
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunAsyncFailedTask.cs b/src/Cake.Frosting.Tests/Tasks/OnErrorRunAsyncFailedTask.cs
similarity index 71%
rename from src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunAsyncFailedTask.cs
rename to src/Cake.Frosting.Tests/Tasks/OnErrorRunAsyncFailedTask.cs
index dbc804f0eb..dd69f69f57 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunAsyncFailedTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/OnErrorRunAsyncFailedTask.cs
@@ -7,19 +7,18 @@
using Cake.Core;
using Cake.Core.Diagnostics;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [TaskName("On-Error-RunAsync-Failed")]
public sealed class OnErrorRunAsyncFailedTask : AsyncFrostingTask
{
public override Task RunAsync(ICakeContext context)
{
- throw new InvalidOperationException("On test exception");
+ throw new InvalidOperationException("An exception");
}
public override void OnError(Exception exception, ICakeContext context)
{
- context.Log.Error("An error has occurred. {0}", exception.Message);
+ context.Log.Error("OnError: {0}", exception.Message);
}
}
}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunCompletedTask.cs b/src/Cake.Frosting.Tests/Tasks/OnErrorRunCompletedTask.cs
similarity index 78%
rename from src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunCompletedTask.cs
rename to src/Cake.Frosting.Tests/Tasks/OnErrorRunCompletedTask.cs
index 0b4644ba37..7317219df2 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunCompletedTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/OnErrorRunCompletedTask.cs
@@ -6,9 +6,8 @@
using Cake.Core;
using Cake.Core.Diagnostics;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [TaskName("On-Error-Run-Completed")]
public sealed class OnErrorRunCompletedTask : FrostingTask
{
public override void Run(ICakeContext context)
@@ -17,7 +16,7 @@ public override void Run(ICakeContext context)
public override void OnError(Exception exception, ICakeContext context)
{
- context.Log.Error("OnErrorRunCompletedTask Exception");
+ context.Log.Error("OnError: {0}", exception.Message);
}
}
}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunFailedTask.cs b/src/Cake.Frosting.Tests/Tasks/OnErrorRunFailedTask.cs
similarity index 69%
rename from src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunFailedTask.cs
rename to src/Cake.Frosting.Tests/Tasks/OnErrorRunFailedTask.cs
index 4ed64a2492..fac264d101 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/OnErrorRunFailedTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/OnErrorRunFailedTask.cs
@@ -6,19 +6,18 @@
using Cake.Core;
using Cake.Core.Diagnostics;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [TaskName("On-Error-Run-Failed")]
public sealed class OnErrorRunFailedTask : FrostingTask
{
public override void Run(ICakeContext context)
{
- throw new InvalidOperationException("On test exception");
+ throw new InvalidOperationException("An exception");
}
public override void OnError(Exception exception, ICakeContext context)
{
- context.Log.Error("An error has occurred. {0}", exception.Message);
+ context.Log.Error("OnError: {0}", exception.Message);
}
}
}
\ No newline at end of file
diff --git a/src/Cake.Frosting.Tests/Data/Tasks/UnitTestsTask.cs b/src/Cake.Frosting.Tests/Tasks/UnitTestsTask.cs
similarity index 73%
rename from src/Cake.Frosting.Tests/Data/Tasks/UnitTestsTask.cs
rename to src/Cake.Frosting.Tests/Tasks/UnitTestsTask.cs
index b6e5a8c0ad..53c73cb7cf 100644
--- a/src/Cake.Frosting.Tests/Data/Tasks/UnitTestsTask.cs
+++ b/src/Cake.Frosting.Tests/Tasks/UnitTestsTask.cs
@@ -4,10 +4,9 @@
using Cake.Core;
-namespace Cake.Frosting.Tests.Data.Tasks
+namespace Cake.Frosting.Tests
{
- [TaskName("Run-Unit-Tests")]
- [Dependency(typeof(BuildTask))]
+ [IsDependentOn(typeof(BuildTask))]
public sealed class UnitTestsTask : FrostingTask
{
}
diff --git a/src/Cake.Frosting.Tests/Unit/CakeHostBuilderTests.cs b/src/Cake.Frosting.Tests/Unit/CakeHostBuilderTests.cs
deleted file mode 100644
index f82e30d650..0000000000
--- a/src/Cake.Frosting.Tests/Unit/CakeHostBuilderTests.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core.Composition;
-using Cake.Frosting.Tests.Fixtures;
-using NSubstitute;
-using Xunit;
-
-namespace Cake.Frosting.Tests.Unit
-{
- public sealed class CakeHostBuilderTests
- {
- public sealed class TheConfigureServicesMethod
- {
- [Fact]
- public void Should_Replace_Default_Registrations()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- var host = Substitute.For();
- fixture.Builder.ConfigureServices(services => services.RegisterInstance(host).As());
-
- // When
- var result = fixture.Build();
-
- // Then
- Assert.Same(host, result);
- }
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Unit/CakeHostTests.cs b/src/Cake.Frosting.Tests/Unit/CakeHostTests.cs
deleted file mode 100644
index 1b92202cef..0000000000
--- a/src/Cake.Frosting.Tests/Unit/CakeHostTests.cs
+++ /dev/null
@@ -1,414 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using Cake.Core;
-using Cake.Core.Diagnostics;
-using Cake.Core.Packaging;
-using Cake.Frosting.Testing;
-using Cake.Frosting.Tests.Data.Tasks;
-using Cake.Frosting.Tests.Fakes;
-using Cake.Frosting.Tests.Fixtures;
-using Cake.Testing;
-using NSubstitute;
-using Xunit;
-
-namespace Cake.Frosting.Tests.Unit
-{
- public sealed class CakeHostTests
- {
- [Fact]
- public void Should_Set_Log_Verbosity_From_Options()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.Options.Verbosity = Verbosity.Diagnostic;
-
- // When
- fixture.Run();
-
- // Then
- Assert.Equal(Verbosity.Diagnostic, fixture.Log.Verbosity);
- }
-
- [Fact]
- public void Should_Set_Working_Directory_From_Options_If_Set()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.FileSystem.CreateDirectory("/Working/Foo");
- fixture.Options.WorkingDirectory = "./Foo";
-
- // When
- fixture.Run();
-
- // Then
- Assert.Equal("/Working/Foo", fixture.Environment.WorkingDirectory.FullPath);
- }
-
- [Fact]
- public void Should_Use_Working_Directory_From_Service_Configuration_If_Set()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.FileSystem.CreateDirectory("/Working/Foo");
- fixture.Builder.ConfigureServices(s => s.UseWorkingDirectory("./Foo"));
-
- // When
- fixture.Run();
-
- // Then
- Assert.Equal("/Working/Foo", fixture.Environment.WorkingDirectory.FullPath);
- }
-
- [Fact]
- public void Should_Prefer_Working_Directory_From_Options_Over_Configuration()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.FileSystem.CreateDirectory("/Working/Foo");
- fixture.FileSystem.CreateDirectory("/Working/Bar");
- fixture.Options.WorkingDirectory = "./Bar";
- fixture.Builder.ConfigureServices(s => s.UseWorkingDirectory("./Foo"));
-
- // When
- fixture.Run();
-
- // Then
- Assert.Equal("/Working/Bar", fixture.Environment.WorkingDirectory.FullPath);
- }
-
- [Fact]
- public void Should_Register_Tasks_With_Engine()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
-
- // When
- fixture.Run();
-
- // Then
- Assert.True(fixture.Engine.IsTaskRegistered("DummyTask"));
- }
-
- [Fact]
- public void Should_Call_Setup_On_Registered_Lifetime()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- var lifetime = fixture.RegisterDefaultTask()
- .RegisterLifetimeSubstitute();
-
- // When
- fixture.Run();
-
- // Then
- Assert.True(lifetime.CalledSetup);
- }
-
- [Fact]
- public void Should_Not_Call_Setup_On_Registered_Lifetime_If_Not_Overridden()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.RegisterLifetimeSubstitute(new FakeLifetime.WithoutOverrides());
- fixture.UseExecutionStrategySubstitute();
-
- // When
- fixture.Run();
-
- // Then
- fixture.Strategy.Received(0).PerformSetup(
- Arg.Any>(),
- Arg.Any());
- }
-
- [Fact]
- public void Should_Call_Teardown_On_Registered_Lifetime()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- var lifetime = fixture.RegisterDefaultTask()
- .RegisterLifetimeSubstitute();
-
- // When
- fixture.Run();
-
- // Then
- Assert.True(lifetime.CalledTeardown);
- }
-
- [Fact]
- public void Should_Not_Call_Teardown_On_Registered_Lifetime_If_Not_Overridden()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.RegisterLifetimeSubstitute(new FakeLifetime.WithoutOverrides());
- fixture.UseExecutionStrategySubstitute();
-
- // When
- fixture.Run();
-
- // Then
- fixture.Strategy.Received(0).PerformTeardown(
- Arg.Any>(),
- Arg.Any());
- }
-
- [Fact]
- public void Should_Call_Setup_On_Registered_Task_Lifetime()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- var lifetime = fixture.RegisterDefaultTask()
- .RegisterTaskLifetimeSubstitute();
-
- // When
- fixture.Run();
-
- // Then
- Assert.True(lifetime.CalledSetup);
- }
-
- [Fact]
- public void Should_Not_Call_Setup_On_Registered_Task_Lifetime_If_Not_Overridden()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.RegisterTaskLifetimeSubstitute(new FakeTaskLifetime.WithoutOverrides());
- fixture.UseExecutionStrategySubstitute();
-
- // When
- fixture.Run();
-
- // Then
- fixture.Strategy.Received(0).PerformTaskSetup(
- Arg.Any>(),
- Arg.Any());
- }
-
- [Fact]
- public void Should_Call_Teardown_On_Registered_Task_Lifetime()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- var lifetime = fixture.RegisterDefaultTask()
- .RegisterTaskLifetimeSubstitute();
-
- // When
- fixture.Run();
-
- // Then
- Assert.True(lifetime.CalledTeardown);
- }
-
- [Fact]
- public void Should_Not_Call_Teardown_On_Registered_Task_Lifetime_If_Not_Overridden()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.RegisterTaskLifetimeSubstitute(new FakeTaskLifetime.WithoutOverrides());
- fixture.UseExecutionStrategySubstitute();
-
- // When
- fixture.Run();
-
- // Then
- fixture.Strategy.Received(0).PerformTaskTeardown(
- Arg.Any>(),
- Arg.Any());
- }
-
- [Fact]
- public void Should_Execute_Tasks()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
- fixture.UseExecutionStrategySubstitute();
-
- // When
- fixture.Run();
-
- // Then
- fixture.Strategy.Received(1).ExecuteAsync(Arg.Is(t => t.Name == "DummyTask"), Arg.Any());
- }
-
- [Fact]
- public void Should_Not_Abort_Build_If_Task_That_Is_ContinueOnError_Throws()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.Options.Target = "Continue-On-Error";
-
- // When
- var result = fixture.Run();
-
- // Then
- Assert.Equal(0, result);
- }
-
- [Fact]
- public void Should_Abort_Build_If_Task_That_Is_Not_ContinueOnError_Throws()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.Options.Target = "No-Continue-On-Error";
-
- // When
- var result = fixture.Run();
-
- // Then
- Assert.NotEqual(0, result);
- }
-
- [Fact]
- public void Should_Execute_Tasks_In_Correct_Order()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.RegisterTask();
- fixture.RegisterTask();
- fixture.UseExecutionStrategySubstitute();
- fixture.Options.Target = "Run-Unit-Tests";
-
- // When
- fixture.Run();
-
- // Then
- Received.InOrder(() =>
- {
- fixture.Strategy.ExecuteAsync(Arg.Is(t => t.Name == "Clean"), Arg.Any());
- fixture.Strategy.ExecuteAsync(Arg.Is(t => t.Name == "Build"), Arg.Any());
- fixture.Strategy.ExecuteAsync(Arg.Is(t => t.Name == "Run-Unit-Tests"), Arg.Any());
- });
- }
-
- [Fact]
- public void Should_Throw_If_Dependency_Is_Not_A_Valid_Task()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.UseExecutionStrategySubstitute();
- fixture.Options.Target = "InvalidDependencyTask";
-
- // When
- var result = fixture.Run();
-
- // Then
- Assert.Equal(1, result);
- fixture.Log.Received(1).Write(
- Verbosity.Quiet, LogLevel.Error,
- "Error: {0}", "The dependency 'DateTime' is not a valid task.");
- }
-
- [Fact]
- public void Should_Return_Zero_On_Success()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterDefaultTask();
-
- // When
- var result = fixture.Run();
-
- // Then
- Assert.Equal(0, result);
- }
-
- [Fact]
- public void Should_Execute_OnError_Method_If_Run_Failed()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.Options.Target = "On-Error-Run-Failed";
-
- // When
- fixture.Run();
-
- // Then
- fixture.Log.Received(1).Error("An error has occurred. {0}", "On test exception");
- }
-
- [Fact]
- public void Should_Execute_OnError_Method_If_RunAsync_Failed()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.Options.Target = "On-Error-RunAsync-Failed";
-
- // When
- fixture.Run();
-
- // Then
- fixture.Log.Received(1).Error("An error has occurred. {0}", "On test exception");
- }
-
- [Fact]
- public void Should_Not_Execute_OnError_Method_If_Run_Completed()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.Options.Target = "On-Error-Run-Completed";
-
- // When
- fixture.Run();
-
- // Then
- fixture.Log.DidNotReceive().Error("OnErrorRunCompletedTask Exception");
- }
-
- [Fact]
- public void Should_Execute_Finally_Method_After_All_Methods()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.RegisterTask();
- fixture.Options.Target = "Finally";
-
- // When
- fixture.Run();
-
- // Then
- Received.InOrder(() =>
- {
- fixture.Log.Information("Run method called");
- fixture.Log.Information("OnError method called");
- fixture.Log.Information("Finally method called");
- });
- }
-
- [Fact]
- public void Should_Install_Tools()
- {
- // Given
- var fixture = new CakeHostBuilderFixture();
- fixture.Builder.ConfigureServices(s => s.UseTool(new Uri("foo:?package=Bar")));
- fixture.RegisterDefaultTask();
-
- // When
- fixture.Run();
-
- // Then
- fixture.Installer.Received(1).Install(Arg.Is(
- p => p.OriginalString == "foo:?package=Bar"));
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Unit/CakeOptionsTests.cs b/src/Cake.Frosting.Tests/Unit/CakeOptionsTests.cs
deleted file mode 100644
index e8ff568717..0000000000
--- a/src/Cake.Frosting.Tests/Unit/CakeOptionsTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core.Diagnostics;
-using Xunit;
-
-namespace Cake.Frosting.Tests.Unit
-{
- public sealed class CakeOptionsTests
- {
- public sealed class TheConstructor
- {
- [Fact]
- public void Should_Set_Arguments_To_Empty_Dictionary()
- {
- // Given
- var options = new CakeHostOptions();
-
- // When
- var result = options.Arguments;
-
- // Then
- Assert.NotNull(result);
- }
-
- [Fact]
- public void Should_Set_Working_Directory_To_Default_Value()
- {
- // Given
- var options = new CakeHostOptions();
-
- // When
- var result = options.WorkingDirectory;
-
- // Then
- Assert.Null(result);
- }
-
- [Fact]
- public void Should_Set_Target_To_Default_Value()
- {
- // Given
- var options = new CakeHostOptions();
-
- // When
- var result = options.Target;
-
- // Then
- Assert.Equal("Default", result);
- }
-
- [Fact]
- public void Should_Set_Verbosity_To_Default_Value()
- {
- // Given
- var options = new CakeHostOptions();
-
- // When
- var result = options.Verbosity;
-
- // Then
- Assert.Equal(Verbosity.Normal, result);
- }
-
- [Fact]
- public void Should_Set_Command_To_Default_Value()
- {
- // Given
- var options = new CakeHostOptions();
-
- // When
- var result = options.Command;
-
- // Then
- Assert.Equal(CakeHostCommand.Run, result);
- }
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Unit/Extensions/CakeHostBuilderExtensionsTests.cs b/src/Cake.Frosting.Tests/Unit/Extensions/CakeHostBuilderExtensionsTests.cs
deleted file mode 100644
index cdb27b4437..0000000000
--- a/src/Cake.Frosting.Tests/Unit/Extensions/CakeHostBuilderExtensionsTests.cs
+++ /dev/null
@@ -1,195 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core.Diagnostics;
-using Cake.Frosting.Tests.Data;
-using NSubstitute;
-using Xunit;
-
-namespace Cake.Frosting.Tests.Unit.Extensions
-{
- public sealed class CakeHostBuilderExtensionsTests
- {
- public sealed class TheUseStartupExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Builder_Reference_Is_Null()
- {
- // Given
- ICakeHostBuilder builder = null;
-
- // When
- var result = Record.Exception(() => builder.UseStartup());
-
- // Then
- AssertEx.IsArgumentNullException(result, "builder");
- }
-
- [Fact]
- public void Should_Run_Startup()
- {
- // Given
- var builder = Substitute.For();
- var services = Substitute.For();
- builder.ConfigureServices(Arg.Invoke(services));
-
- // When
- builder.UseStartup();
-
- // Then
- services.RegisterType(typeof(DummyStartup.DummyStartupSentinel));
- }
- }
-
- public sealed class TheWithArgumentsMethod
- {
- [Fact]
- public void Should_Throw_If_Builder_Reference_Is_Null()
- {
- // Given
- ICakeHostBuilder builder = null;
-
- // When
- var result = Record.Exception(() => builder.WithArguments(new string[] { }));
-
- // Then
- AssertEx.IsArgumentNullException(result, "builder");
- }
-
- [Theory]
- [InlineData("--v=quiet", Verbosity.Quiet)]
- [InlineData("--v=minimal", Verbosity.Minimal)]
- [InlineData("--v=normal", Verbosity.Normal)]
- [InlineData("--v=verbose", Verbosity.Verbose)]
- [InlineData("--v=diagnostic", Verbosity.Diagnostic)]
- [InlineData("--v=q", Verbosity.Quiet)]
- [InlineData("--v=m", Verbosity.Minimal)]
- [InlineData("--v=n", Verbosity.Normal)]
- [InlineData("--v=v", Verbosity.Verbose)]
- [InlineData("--v=d", Verbosity.Diagnostic)]
- [InlineData("--verbosity=quiet", Verbosity.Quiet)]
- [InlineData("--verbosity=minimal", Verbosity.Minimal)]
- [InlineData("--verbosity=normal", Verbosity.Normal)]
- [InlineData("--verbosity=verbose", Verbosity.Verbose)]
- [InlineData("--verbosity=diagnostic", Verbosity.Diagnostic)]
- [InlineData("--verbosity=q", Verbosity.Quiet)]
- [InlineData("--verbosity=m", Verbosity.Minimal)]
- [InlineData("--verbosity=n", Verbosity.Normal)]
- [InlineData("--verbosity=v", Verbosity.Verbose)]
- [InlineData("--verbosity=d", Verbosity.Diagnostic)]
- [InlineData("-v=quiet", Verbosity.Quiet)]
- [InlineData("-v=minimal", Verbosity.Minimal)]
- [InlineData("-v=normal", Verbosity.Normal)]
- [InlineData("-v=verbose", Verbosity.Verbose)]
- [InlineData("-v=diagnostic", Verbosity.Diagnostic)]
- [InlineData("-v=q", Verbosity.Quiet)]
- [InlineData("-v=m", Verbosity.Minimal)]
- [InlineData("-v=n", Verbosity.Normal)]
- [InlineData("-v=v", Verbosity.Verbose)]
- [InlineData("-v=d", Verbosity.Diagnostic)]
- [InlineData("-verbosity=quiet", Verbosity.Quiet)]
- [InlineData("-verbosity=minimal", Verbosity.Minimal)]
- [InlineData("-verbosity=normal", Verbosity.Normal)]
- [InlineData("-verbosity=verbose", Verbosity.Verbose)]
- [InlineData("-verbosity=diagnostic", Verbosity.Diagnostic)]
- [InlineData("-verbosity=q", Verbosity.Quiet)]
- [InlineData("-verbosity=m", Verbosity.Minimal)]
- [InlineData("-verbosity=n", Verbosity.Normal)]
- [InlineData("-verbosity=v", Verbosity.Verbose)]
- [InlineData("-verbosity=d", Verbosity.Diagnostic)]
- public void Should_Parse_Verbosity(string args, Verbosity expected)
- {
- // Given
- var builder = Substitute.For();
- var services = Substitute.For();
- builder.ConfigureServices(Arg.Invoke(services));
-
- // When
- builder.WithArguments(new[] { args });
-
- // Then
- services.Received(1).RegisterInstance(
- Arg.Is(o => o.Verbosity == expected));
- }
-
- [Theory]
- [InlineData("--help")]
- [InlineData("--h")]
- [InlineData("-help")]
- [InlineData("-h")]
- public void Should_Parse_Show_Help(string args)
- {
- // Given
- var builder = Substitute.For();
- var services = Substitute.For();
- builder.ConfigureServices(Arg.Invoke(services));
-
- // When
- builder.WithArguments(new[] { args });
-
- // Then
- services.Received(1).RegisterInstance(
- Arg.Is(o => o.Command == CakeHostCommand.Help));
- }
-
- [Theory]
- [InlineData("--version")]
- [InlineData("-version")]
- public void Should_Parse_Show_Version(string args)
- {
- // Given
- var builder = Substitute.For();
- var services = Substitute.For();
- builder.ConfigureServices(Arg.Invoke(services));
-
- // When
- builder.WithArguments(new[] { args });
-
- // Then
- services.Received(1).RegisterInstance(
- Arg.Is(o => o.Command == CakeHostCommand.Version));
- }
-
- [Theory]
- [InlineData("--target=Test1", "Test1")]
- [InlineData("--t=Test2", "Test2")]
- [InlineData("-target=Test1", "Test1")]
- [InlineData("-t=Test2", "Test2")]
- public void Should_Parse_Target(string args, string expected)
- {
- // Given
- var builder = Substitute.For();
- var services = Substitute.For();
- builder.ConfigureServices(Arg.Invoke(services));
-
- // When
- builder.WithArguments(new[] { args });
-
- // Then
- services.Received(1).RegisterInstance(
- Arg.Is(o => o.Target == expected));
- }
-
- [Theory]
- [InlineData("--w=Test1", "Test1")]
- [InlineData("--working=Test2", "Test2")]
- [InlineData("-w=Test1", "Test1")]
- [InlineData("-working=Test2", "Test2")]
- public void Should_Parse_Working_Directory(string args, string expected)
- {
- // Given
- var builder = Substitute.For();
- var services = Substitute.For();
- builder.ConfigureServices(Arg.Invoke(services));
-
- // When
- builder.WithArguments(new[] { args });
-
- // Then
- services.Received(1).RegisterInstance(
- Arg.Is(o => o.WorkingDirectory.FullPath == expected));
- }
- }
- }
-}
diff --git a/src/Cake.Frosting.Tests/Unit/Extensions/CakeServicesExtensionsTests.cs b/src/Cake.Frosting.Tests/Unit/Extensions/CakeServicesExtensionsTests.cs
deleted file mode 100644
index 90b1f8cf72..0000000000
--- a/src/Cake.Frosting.Tests/Unit/Extensions/CakeServicesExtensionsTests.cs
+++ /dev/null
@@ -1,269 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Reflection;
-using Cake.Core.Composition;
-using Cake.Core.Packaging;
-using Cake.Frosting.Tests.Data;
-using NSubstitute;
-using Xunit;
-
-namespace Cake.Frosting.Tests.Unit.Extensions
-{
- public sealed class CakeServicesExtensionsTests
- {
- public sealed class TheUseContextExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Services_Reference_Is_Null()
- {
- // Given
- ICakeServices services = null;
-
- // When
- var result = Record.Exception(() => services.UseContext());
-
- // Then
- AssertEx.IsArgumentNullException(result, "services");
- }
-
- [Fact]
- public void Should_Register_The_Context()
- {
- // Given
- var services = Substitute.For();
- var builder = Substitute.For();
- services.RegisterType(Arg.Any()).Returns(builder); // Return a builder object when registering
- builder.AsSelf().Returns(builder); // Return same builder object when chaining
- builder.As(Arg.Any()).Returns(builder); // Return same builder object when chaining
-
- // When
- services.UseContext();
-
- // Then
- Received.InOrder(() =>
- {
- services.RegisterType();
- builder.AsSelf();
- builder.As();
- builder.Singleton();
- });
- }
- }
-
- public sealed class TheUseLifetimeExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Services_Reference_Is_Null()
- {
- // Given
- ICakeServices services = null;
-
- // When
- var result = Record.Exception(() => services.UseLifetime());
-
- // Then
- AssertEx.IsArgumentNullException(result, "services");
- }
-
- [Fact]
- public void Should_Register_The_Lifetime()
- {
- // Given
- var services = Substitute.For();
- var builder = Substitute.For();
- services.RegisterType(Arg.Any()).Returns(builder); // Return a builder object when registering
- builder.As(Arg.Any()).Returns(builder); // Return same builder object when chaining
-
- // When
- services.UseLifetime();
-
- // Then
- Received.InOrder(() =>
- {
- services.RegisterType();
- builder.As();
- builder.Singleton();
- });
- }
- }
-
- public sealed class TheUseTaskLifetimeExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Services_Reference_Is_Null()
- {
- // Given
- ICakeServices services = null;
-
- // When
- var result = Record.Exception(() => services.UseTaskLifetime());
-
- // Then
- AssertEx.IsArgumentNullException(result, "services");
- }
-
- [Fact]
- public void Should_Register_The_Lifetime()
- {
- // Given
- var services = Substitute.For();
- var builder = Substitute.For();
- services.RegisterType(Arg.Any()).Returns(builder); // Return a builder object when registering
- builder.As(Arg.Any()).Returns(builder); // Return same builder object when chaining
-
- // When
- services.UseTaskLifetime();
-
- // Then
- Received.InOrder(() =>
- {
- services.RegisterType();
- builder.As();
- builder.Singleton();
- });
- }
- }
-
- public sealed class TheUseAssemblyExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Services_Reference_Is_Null()
- {
- // Given
- ICakeServices services = null;
- var assembly = typeof(DateTime).GetTypeInfo().Assembly;
-
- // When
- var result = Record.Exception(() => services.UseAssembly(assembly));
-
- // Then
- AssertEx.IsArgumentNullException(result, "services");
- }
-
- [Fact]
- public void Should_Register_The_Assembly()
- {
- // Given
- var services = Substitute.For();
- var builder = Substitute.For();
- services.RegisterInstance(Arg.Any()).Returns(builder); // Return a builder object when registering
- builder.As(Arg.Any()).Returns(builder); // Return same builder object when chaining
-
- // When
- services.UseAssembly(typeof(DateTime).GetTypeInfo().Assembly);
-
- // Then
- Received.InOrder(() =>
- {
- services.RegisterInstance(Arg.Any());
- builder.Singleton();
- });
- }
- }
-
- public sealed class TheUseModuleExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Services_Reference_Is_Null()
- {
- // Given
- ICakeServices services = null;
-
- // When
- var result = Record.Exception(() => services.UseModule());
-
- // Then
- AssertEx.IsArgumentNullException(result, "services");
- }
-
- [Fact]
- public void Should_Create_Module_And_Call_Registration()
- {
- // Given
- var services = Substitute.For();
-
- // When
- services.UseModule();
-
- // Then
- services.Received(1).RegisterType(typeof(DummyModule.DummyModuleSentinel));
- }
- }
-
- public sealed class TheUsePackageInstallerExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Services_Reference_Is_Null()
- {
- // Given
- ICakeServices services = null;
-
- // When
- var result = Record.Exception(() => services.UsePackageInstaller());
-
- // Then
- AssertEx.IsArgumentNullException(result, "services");
- }
-
- [Fact]
- public void Should_Register_The_Package_Installer()
- {
- // Given
- var services = Substitute.For();
- var builder = Substitute.For();
- services.RegisterType(Arg.Any()).Returns(builder); // Return a builder object when registering
- builder.As(Arg.Any()).Returns(builder); // Return same builder object when chaining
-
- // When
- services.UsePackageInstaller();
-
- // Then
- Received.InOrder(() =>
- {
- services.RegisterType();
- builder.As();
- builder.Singleton();
- });
- }
- }
-
- public sealed class TheUseToolExtensionMethod
- {
- [Fact]
- public void Should_Throw_If_Services_Reference_Is_Null()
- {
- // Given
- ICakeServices services = null;
-
- // When
- var result = Record.Exception(() => services.UseTool(new Uri("nuget:?package=Foo")));
-
- // Then
- AssertEx.IsArgumentNullException(result, "services");
- }
-
- [Fact]
- public void Should_Register_The_PackageReference()
- {
- // Given
- var services = Substitute.For();
- var builder = Substitute.For();
- services.RegisterInstance(Arg.Any()).Returns(builder); // Return a builder object when registering
- builder.As(Arg.Any()).Returns(builder); // Return same builder object when chaining
-
- // When
- services.UseTool(new Uri("nuget:?package=Foo"));
-
- // Then
- Received.InOrder(() =>
- {
- services.RegisterInstance(Arg.Is(
- r => r.OriginalString == "nuget:?package=Foo"));
- });
- }
- }
- }
-}
diff --git a/src/Cake.Frosting/Abstractions/ICakeHost.cs b/src/Cake.Frosting/Abstractions/ICakeHost.cs
deleted file mode 100644
index f39aaf6993..0000000000
--- a/src/Cake.Frosting/Abstractions/ICakeHost.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// ReSharper disable once CheckNamespace
-namespace Cake.Frosting
-{
- ///
- /// Represents a configured Cake host.
- ///
- public interface ICakeHost
- {
- ///
- /// Runs the configured Cake host.
- ///
- /// An exit code indicating success or failure.
- int Run();
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting/Abstractions/ICakeHostBuilder.cs b/src/Cake.Frosting/Abstractions/ICakeHostBuilder.cs
deleted file mode 100644
index 8aeaac8707..0000000000
--- a/src/Cake.Frosting/Abstractions/ICakeHostBuilder.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-
-// ReSharper disable once CheckNamespace
-namespace Cake.Frosting
-{
- ///
- /// Represents a builder for .
- ///
- public interface ICakeHostBuilder
- {
- ///
- /// Adds a delegate for configuring additional services for the host.
- ///
- /// A delegate for configuring the .
- /// The same instance so that multiple calls can be chained.
- ICakeHostBuilder ConfigureServices(Action configureServices);
-
- ///
- /// Builds the required services and an using the specified options.
- ///
- /// The built .
- ICakeHost Build();
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting/Abstractions/ICakeServices.cs b/src/Cake.Frosting/Abstractions/ICakeServices.cs
deleted file mode 100644
index cffeaf1798..0000000000
--- a/src/Cake.Frosting/Abstractions/ICakeServices.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Cake.Core.Composition;
-
-// ReSharper disable once CheckNamespace
-namespace Cake.Frosting
-{
- ///
- /// Represents a collection of service registrations.
- ///
- ///
- public interface ICakeServices : ICakeContainerRegistrar
- {
- }
-}
\ No newline at end of file
diff --git a/src/Cake.Frosting/Abstractions/ICakeTaskFinder.cs b/src/Cake.Frosting/Abstractions/ICakeTaskFinder.cs
deleted file mode 100644
index a36bfe08da..0000000000
--- a/src/Cake.Frosting/Abstractions/ICakeTaskFinder.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-
-// ReSharper disable once CheckNamespace
-namespace Cake.Frosting
-{
- ///
- /// Represents Frosting's task finder mechanism.
- ///
- public interface ICakeTaskFinder
- {
- ///
- /// Gets all task types present in the provided assemblies.
- ///
- /// The assemblies.
- /// An array of task types.
- Type[] GetTasks(IEnumerable assemblies);
- }
-}
diff --git a/src/Cake.Frosting/Annotations/ContinueOnErrorAttribute.cs b/src/Cake.Frosting/Annotations/ContinueOnErrorAttribute.cs
index 965e91b09a..37ab2c6eb7 100644
--- a/src/Cake.Frosting/Annotations/ContinueOnErrorAttribute.cs
+++ b/src/Cake.Frosting/Annotations/ContinueOnErrorAttribute.cs
@@ -4,7 +4,6 @@
using System;
-// ReSharper disable once CheckNamespace
namespace Cake.Frosting
{
///
diff --git a/src/Cake.Frosting/Annotations/DependencyAttribute.cs b/src/Cake.Frosting/Annotations/DependencyAttribute.cs
index 850cc42bac..8afe6bfd49 100644
--- a/src/Cake.Frosting/Annotations/DependencyAttribute.cs
+++ b/src/Cake.Frosting/Annotations/DependencyAttribute.cs
@@ -4,15 +4,14 @@
using System;
-// ReSharper disable once CheckNamespace
namespace Cake.Frosting
{
///
/// Represents a dependency.
///
- ///
+ ///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
- public sealed class DependencyAttribute : Attribute
+ public sealed class DependencyAttribute : Attribute, ITaskDependency
{
///
/// Gets the depdendency task type.
diff --git a/src/Cake.Frosting/Annotations/IsDependeeOfAttribute.cs b/src/Cake.Frosting/Annotations/IsDependeeOfAttribute.cs
new file mode 100644
index 0000000000..a55870a415
--- /dev/null
+++ b/src/Cake.Frosting/Annotations/IsDependeeOfAttribute.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Cake.Frosting
+{
+ ///
+ /// Represents a reverse dependency.
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public sealed class IsDependeeOfAttribute : Attribute, IReverseTaskDependency
+ {
+ ///
+ /// Gets the reverse dependency task type.
+ ///
+ /// The reverse dependency task type.
+ public Type Task { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The reverse dependency type.
+ public IsDependeeOfAttribute(Type type)
+ {
+ Task = type;
+ }
+ }
+}
diff --git a/src/Cake.Frosting/Annotations/IsDependentOnAttribute.cs b/src/Cake.Frosting/Annotations/IsDependentOnAttribute.cs
new file mode 100644
index 0000000000..08cb51b52c
--- /dev/null
+++ b/src/Cake.Frosting/Annotations/IsDependentOnAttribute.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Cake.Frosting
+{
+ ///
+ /// Represents a dependency.
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public sealed class IsDependentOnAttribute : Attribute, ITaskDependency
+ {
+ ///
+ /// Gets the dependency task type.
+ ///
+ /// The dependency task type.
+ public Type Task { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The dependency type.
+ public IsDependentOnAttribute(Type type)
+ {
+ Task = type;
+ }
+ }
+}
diff --git a/src/Cake.Frosting/Annotations/ReverseDependencyAttribute.cs b/src/Cake.Frosting/Annotations/ReverseDependencyAttribute.cs
new file mode 100644
index 0000000000..e02e871302
--- /dev/null
+++ b/src/Cake.Frosting/Annotations/ReverseDependencyAttribute.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Cake.Frosting
+{
+ ///
+ /// Represents a reverse dependency.
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public sealed class ReverseDependencyAttribute : Attribute, IReverseTaskDependency
+ {
+ ///
+ /// Gets the reverse dependency task type.
+ ///
+ /// The reverse dependency task type.
+ public Type Task { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The reverse dependency type.
+ public ReverseDependencyAttribute(Type type)
+ {
+ Task = type;
+ }
+ }
+}
diff --git a/src/Cake.Frosting/Annotations/TaskDescriptionAttribute.cs b/src/Cake.Frosting/Annotations/TaskDescriptionAttribute.cs
new file mode 100644
index 0000000000..1129ed7d5f
--- /dev/null
+++ b/src/Cake.Frosting/Annotations/TaskDescriptionAttribute.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Cake.Frosting
+{
+ ///
+ /// Represents a task description.
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
+ public sealed class TaskDescriptionAttribute : Attribute
+ {
+ ///
+ /// Gets the task description.
+ ///
+ public string Description { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The task description.
+ public TaskDescriptionAttribute(string description)
+ {
+ Description = description;
+ }
+ }
+}
diff --git a/src/Cake.Frosting/Annotations/TaskNameAttribute.cs b/src/Cake.Frosting/Annotations/TaskNameAttribute.cs
index 9694d689ac..b748c7bf2e 100644
--- a/src/Cake.Frosting/Annotations/TaskNameAttribute.cs
+++ b/src/Cake.Frosting/Annotations/TaskNameAttribute.cs
@@ -4,7 +4,6 @@
using System;
-// ReSharper disable once CheckNamespace
namespace Cake.Frosting
{
///
@@ -15,15 +14,14 @@ namespace Cake.Frosting
public sealed class TaskNameAttribute : Attribute
{
///
- /// Gets the name of the task.
+ /// Gets the task name.
///
- /// The name.
public string Name { get; }
///
/// Initializes a new instance of the class.
///
- /// The name of the task.
+ /// The task name.
public TaskNameAttribute(string name)
{
Name = name;
diff --git a/src/Cake.Frosting/AsyncFrostingTask.cs b/src/Cake.Frosting/AsyncFrostingTask.cs
index 29cdff57c5..13eb3b90ce 100644
--- a/src/Cake.Frosting/AsyncFrostingTask.cs
+++ b/src/Cake.Frosting/AsyncFrostingTask.cs
@@ -3,10 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Cake.Core;
-using Cake.Frosting.Internal;
namespace Cake.Frosting
{
@@ -55,6 +53,10 @@ public virtual bool ShouldRun(T context)
/// The context.
public virtual void OnError(Exception exception, T context)
{
+ if (exception is null)
+ {
+ throw new ArgumentNullException(nameof(exception));
+ }
}
///
@@ -65,35 +67,51 @@ public virtual void Finally(T context)
{
}
- [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Explicit implementation.")]
+ ///
Task IFrostingTask.RunAsync(ICakeContext context)
{
- Guard.ArgumentNotNull(context, nameof(context));
+ if (context is null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
return RunAsync((T)context);
}
- [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Explicit implementation.")]
+ ///
bool IFrostingTask.ShouldRun(ICakeContext context)
{
- Guard.ArgumentNotNull(context, nameof(context));
+ if (context is null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
return ShouldRun((T)context);
}
- [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Explicit implementation.")]
+ ///
void IFrostingTask.OnError(Exception exception, ICakeContext context)
{
- Guard.ArgumentNotNull(exception, nameof(exception));
- Guard.ArgumentNotNull(context, nameof(context));
+ if (exception is null)
+ {
+ throw new ArgumentNullException(nameof(exception));
+ }
+
+ if (context is null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
OnError(exception, (T)context);
}
- [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Explicit implementation.")]
+ ///
void IFrostingTask.Finally(ICakeContext context)
{
- Guard.ArgumentNotNull(context, nameof(context));
+ if (context is null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
Finally((T)context);
}
diff --git a/src/Cake.Frosting/Cake.Frosting.csproj b/src/Cake.Frosting/Cake.Frosting.csproj
index fde2234469..23fb3e0622 100644
--- a/src/Cake.Frosting/Cake.Frosting.csproj
+++ b/src/Cake.Frosting/Cake.Frosting.csproj
@@ -8,7 +8,12 @@
+
+
+
+
+
diff --git a/src/Cake.Frosting/CakeHost.cs b/src/Cake.Frosting/CakeHost.cs
index 72ee2c98d7..ac747d80b5 100644
--- a/src/Cake.Frosting/CakeHost.cs
+++ b/src/Cake.Frosting/CakeHost.cs
@@ -4,123 +4,168 @@
using System;
using System.Collections.Generic;
-using System.Linq;
+using System.Reflection;
+using Cake.Cli;
+using Cake.Common.Modules;
using Cake.Core;
+using Cake.Core.Configuration;
using Cake.Core.Diagnostics;
-using Cake.Core.IO;
-using Cake.Core.Packaging;
+using Cake.Core.Modules;
using Cake.Frosting.Internal;
-using Cake.Frosting.Internal.Commands;
-using Cake.Frosting.Internal.Composition;
+using Cake.NuGet;
+using Microsoft.Extensions.DependencyInjection;
+using Spectre.Cli;
namespace Cake.Frosting
{
- internal sealed class CakeHost : ICakeHost
+ ///
+ /// The Cake host.
+ ///
+ public sealed class CakeHost
{
- private readonly CakeHostOptions _options;
- private readonly IFileSystem _fileSystem;
- private readonly IFrostingContext _context;
- private readonly IEnumerable _tasks;
- private readonly IFrostingLifetime _lifetime;
- private readonly IFrostingTaskLifetime _taskLifetime;
- private readonly ICakeEnvironment _environment;
- private readonly ICakeEngine _engine;
- private readonly ICakeLog _log;
- private readonly IToolInstaller _installer;
- private readonly List _tools;
- private readonly CommandFactory _commandFactory;
- private readonly WorkingDirectory _workingDirectory;
- private readonly EngineInitializer _engineInitializer;
-
- // ReSharper disable once NotAccessedField.Local
- private readonly Container _container;
-
- public CakeHost(IFrostingContext context, Container container, CakeHostOptions options,
- IFileSystem fileSystem, ICakeEnvironment environment, ICakeEngine engine, ICakeLog log,
- IToolInstaller installer, IEnumerable tools,
- EngineInitializer engineInitializer, CommandFactory commandFactory,
- WorkingDirectory workingDirectory = null, IEnumerable tasks = null,
- IFrostingLifetime lifetime = null, IFrostingTaskLifetime taskLifetime = null)
+ private readonly IServiceCollection _services;
+ private readonly List _assemblies;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public CakeHost()
+ {
+ _services = CreateServiceCollection();
+ _assemblies = new List
+ {
+ Assembly.GetEntryAssembly()
+ };
+ }
+
+ ///
+ /// Creates a .
+ ///
+ /// The created .
+ public static CakeHost Create()
+ {
+ return new CakeHost();
+ }
+
+ ///
+ /// Registers an assembly which will be used to find tasks.
+ ///
+ /// The assembly.
+ /// The same instance so that multiple calls can be chained.
+ public CakeHost AddAssembly(Assembly assembly)
+ {
+ _assemblies.Add(assembly);
+ return this;
+ }
+
+ ///
+ /// Adds a delegate for configuring additional services for the host.
+ ///
+ /// A delegate for configuring the .
+ /// The same instance so that multiple calls can be chained.
+ public CakeHost ConfigureServices(Action services)
{
- Guard.ArgumentNotNull(context, nameof(context));
- Guard.ArgumentNotNull(container, nameof(container));
- Guard.ArgumentNotNull(options, nameof(options));
- Guard.ArgumentNotNull(fileSystem, nameof(fileSystem));
- Guard.ArgumentNotNull(environment, nameof(environment));
- Guard.ArgumentNotNull(engine, nameof(engine));
- Guard.ArgumentNotNull(log, nameof(log));
- Guard.ArgumentNotNull(engineInitializer, nameof(engineInitializer));
- Guard.ArgumentNotNull(commandFactory, nameof(commandFactory));
-
- // Mandatory arguments.
- _context = context;
- _container = container;
- _options = options;
- _fileSystem = fileSystem;
- _environment = environment;
- _engine = engine;
- _log = log;
- _installer = installer;
- _tools = new List(tools ?? Enumerable.Empty());
- _engineInitializer = engineInitializer;
- _commandFactory = commandFactory;
-
- // Optional arguments.
- _workingDirectory = workingDirectory;
- _tasks = tasks;
- _lifetime = lifetime;
- _taskLifetime = taskLifetime;
+ services(_services);
+ return this;
}
- public int Run()
+ ///
+ /// Runs the build with the specified arguments.
+ ///
+ /// The arguments.
+ /// The exit code.
+ public int Run(IEnumerable args)
{
- try
+ RegisterTasks(_assemblies);
+
+ // Register all the user's registrations
+ var registrar = new TypeRegistrar();
+ registrar.RegisterInstance(typeof(IServiceCollection), _services);
+
+ // Run the application
+ var app = new CommandApp(registrar);
+ app.Configure(config =>
{
- // Update the log verbosity.
- _log.Verbosity = _options.Verbosity;
+ config.ValidateExamples();
- // Set the working directory.
- _environment.WorkingDirectory = GetWorkingDirectory();
- _log.Debug("Working directory: {0}", _environment.WorkingDirectory.FullPath);
+ // Top level examples.
+ config.AddExample(new[] { string.Empty });
+ config.AddExample(new[] { "--verbosity", "quiet" });
+ config.AddExample(new[] { "--tree" });
+ });
- // Install tools.
- if (_tools.Count > 0)
- {
- _log.Verbose("Installing tools...");
- foreach (var tool in _tools)
- {
- _installer.Install(tool);
- }
- }
+ return app.Run(args);
+ }
- // Initialize the engine and register everything.
- _engineInitializer.Initialize(_engine, _context, _tasks, _lifetime, _taskLifetime);
+ private ServiceCollection CreateServiceCollection()
+ {
+ var services = new ServiceCollection();
- // Get the command and execute.
- var command = _commandFactory.GetCommand(_options);
- var result = command.ExecuteAsync(_engine, _options).GetAwaiter().GetResult();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
- // Return success.
- return result ? 0 : 1;
- }
- catch (Exception exception)
+ services.AddSingleton>();
+ services.AddSingleton>();
+ services.AddSingleton();
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+
+ services.AddSingleton();
+
+ services.UseModule();
+ services.UseModule();
+ services.UseModule