diff --git a/GitReleaseManager.yaml b/GitReleaseManager.yaml index c49d99b24d..caea43a267 100644 --- a/GitReleaseManager.yaml +++ b/GitReleaseManager.yaml @@ -2,4 +2,6 @@ issue-labels-include: - Bug - Feature - Improvement -- Documentation \ No newline at end of file +- Documentation +issue-labels-exclude: +- Build \ No newline at end of file diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 177e41bce6..1fecea2da6 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,28 @@ +### New on 0.13.0 (Released 2016/06/07) + +* DotNetCoreTest() alias calls DotNetCoreRun() +* Fix DotNet CLI multi-arguments +* Cannot parse AssemblyInfo.cs files generated by MonoDevelop +* Cake.Core.Tooling.ToolRepository.Register(FilePath) path not validated +* Problems using XmlPeek and XmlPoke in XML files with DOCTYPE +* MakeNSIS() does not support filepath for scripts with blanks in path name +* Custom command line switches can't contain spaces in value +* Signtool: Add support for description URL (/du) +* Support uploading test results XML to AppVeyor +* Add support for the vstest.console.exe unit test runner +* Add Module Support +* Add setter for Verbosity in ICakeLog +* Add support for additional arguments to DotNetCoreExecute and DotNetCoreRun +* Allow setting boolean values for built in Cake arguments +* Add DevelopmentDependency to NuGetPackSettings +* Project parser should support TargetFrameworkProfile +* Add tests for Project Parser +* Cake.Core.Tooling namespace isn't documented +* Incorrect documentation in obsolete attribute +* Correct documentation for ILMerge +* Add Summary Documentation for all aliases + + ### New on 0.12.0 (Released 2016/05/25) * Fix globalization & white space issue diff --git a/build.cake b/build.cake index f126e3cf2f..8dffbc598f 100644 --- a/build.cake +++ b/build.cake @@ -23,7 +23,7 @@ bool publishingError = false; // SETUP / TEARDOWN /////////////////////////////////////////////////////////////////////////////// -Setup(() => +Setup(context => { parameters.SetBuildVersion( BuildVersion.CalculatingSemanticVersion( @@ -44,7 +44,7 @@ Setup(() => BuildPackages.GetPackages( nugetRooPath: parameters.Paths.Directories.NugetRoot, semVersion: parameters.Version.SemVersion, - packageIds: new [] { "Cake", "Cake.Core", "Cake.Common", "Cake.Testing", "Cake.NuGet" }, + packageIds: new [] { "Cake", "Cake.Core", "Cake.Common", "Cake.Testing" }, chocolateyPackageIds: new [] { "cake.portable" } ) ); diff --git a/build/parameters.cake b/build/parameters.cake index 8fa4aba9eb..8c03ffdfa9 100644 --- a/build/parameters.cake +++ b/build/parameters.cake @@ -56,7 +56,7 @@ public class BuildParameters IsLocalBuild = buildSystem.IsLocalBuild, IsRunningOnUnix = context.IsRunningOnUnix(), IsRunningOnWindows = context.IsRunningOnWindows(), - IsRunningOnAppVeyor = context.IsRunningOnWindows(), + IsRunningOnAppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor, IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest, IsMainCakeRepo = StringComparer.OrdinalIgnoreCase.Equals("cake-build/cake", buildSystem.AppVeyor.Environment.Repository.Name), IsMainCakeBranch = StringComparer.OrdinalIgnoreCase.Equals("main", buildSystem.AppVeyor.Environment.Repository.Branch), diff --git a/nuspec/Cake.Common.nuspec b/nuspec/Cake.Common.nuspec index 0018536985..3778af9264 100644 --- a/nuspec/Cake.Common.nuspec +++ b/nuspec/Cake.Common.nuspec @@ -1,6 +1,6 @@ - + Cake.Common 0.0.0 Patrik Svensson diff --git a/nuspec/Cake.NuGet.nuspec b/nuspec/Cake.NuGet.nuspec deleted file mode 100644 index 13c8fe2cc7..0000000000 --- a/nuspec/Cake.NuGet.nuspec +++ /dev/null @@ -1,26 +0,0 @@ - - - - Cake.NuGet - 0.0.0 - Patrik Svensson - Patrik Svensson - Cake (C# Make) is a build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages. - Provides aliases (extension methods on Cake context) that support CI, build, unit tests, zip, signing, etc. for Cake. - https://github.com/cake-build/cake/blob/develop/LICENSE - https://github.com/cake-build/cake - https://raw.githubusercontent.com/cake-build/graphics/master/png/cake-medium.png - false - Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park and contributors - Cake Script Build - - - - - - - - - - - \ No newline at end of file diff --git a/src/Cake.Common.Tests/Cake.Common.Tests.csproj b/src/Cake.Common.Tests/Cake.Common.Tests.csproj index 49abd5650d..7a0c54df05 100644 --- a/src/Cake.Common.Tests/Cake.Common.Tests.csproj +++ b/src/Cake.Common.Tests/Cake.Common.Tests.csproj @@ -71,6 +71,7 @@ + @@ -100,6 +101,7 @@ + @@ -217,6 +219,7 @@ + @@ -308,6 +311,7 @@ + diff --git a/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs b/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs index 11a125000f..fab9b36477 100644 --- a/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs @@ -43,6 +43,11 @@ public AssemblyInfoParserFixture() CreateAssemblyInfo = true; } + public void WithAssemblyInfoContents(string assemblyInfoContents) + { + FileSystem.CreateFile("/Working/output.cs").SetContent(assemblyInfoContents); + } + public AssemblyInfoParseResult Parse() { if (CreateAssemblyInfo && Path != null) diff --git a/src/Cake.Common.Tests/Fixtures/Solution/Project/ProjectParserFixture.cs b/src/Cake.Common.Tests/Fixtures/Solution/Project/ProjectParserFixture.cs new file mode 100644 index 0000000000..fc7ee8b46f --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Solution/Project/ProjectParserFixture.cs @@ -0,0 +1,51 @@ +using Cake.Common.Solution.Project; +using Cake.Common.Tests.Properties; +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Testing; +using NSubstitute; + +namespace Cake.Common.Tests.Fixtures.Solution.Project +{ + internal sealed class ProjectParserFixture + { + public ProjectParserFixture() + { + ProjFilePath = "/Working/Cake.Sample.csproj"; + Pattern = "/Working/Cake.*.csproj"; + + var environment = FakeEnvironment.CreateUnixEnvironment(); + Environment = environment; + var fileSystem = new FakeFileSystem(environment); + fileSystem.CreateFile(ProjFilePath.FullPath).SetContent(Resources.Csproj_ProjectFile); + fileSystem.CreateFile("/Working/Cake.Incomplete.csproj").SetContent(Resources.Csproj_IncompleteFile); + FileSystem = fileSystem; + + Globber = Substitute.For(); + Globber.GetFiles(Pattern).Returns(new FilePath[] { "/Working/Cake.Sample.csproj", "/Working/Cake.Incomplete.csproj" }); + + Log = Substitute.For(); + } + + public ICakeEnvironment Environment { get; set; } + + public ProjectParserResult Parse() + { + var parser = new ProjectParser(FileSystem, Environment); + return parser.Parse(ProjFilePath); + } + + public ProjectParserResult ParseIncomplete() + { + var parser = new ProjectParser(FileSystem, Environment); + return parser.Parse("/Working/Cake.Incomplete.csproj"); + } + + public string Pattern { get; set; } + public IFileSystem FileSystem { get; set; } + public IGlobber Globber { get; set; } + public ICakeLog Log { get; set; } + public FilePath ProjFilePath { get; set; } + } +} diff --git a/src/Cake.Common.Tests/Fixtures/Tools/VSTestRunnerFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/VSTestRunnerFixture.cs new file mode 100644 index 0000000000..94b16aef0c --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Tools/VSTestRunnerFixture.cs @@ -0,0 +1,30 @@ +using Cake.Common.Tools.VSTest; +using Cake.Core.IO; +using Cake.Testing.Fixtures; +using System.Collections.Generic; + +namespace Cake.Common.Tests.Fixtures.Tools +{ + internal sealed class VSTestRunnerFixture : ToolFixture + { + public IEnumerable AssemblyPaths { get; set; } + + public VSTestRunnerFixture() + : base("vstest.console.exe") + { + AssemblyPaths = new[] { new FilePath("./Test1.dll") }; + Environment.SetSpecialPath(SpecialPath.ProgramFilesX86, "/ProgramFilesX86"); + } + + protected override FilePath GetDefaultToolPath(string toolFilename) + { + return new FilePath("/ProgramFilesX86/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe"); + } + + protected override void RunTool() + { + var tool = new VSTestRunner(FileSystem, Environment, ProcessRunner, Tools); + tool.Run(AssemblyPaths, Settings); + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/XmlPeekAliasesFixture.cs b/src/Cake.Common.Tests/Fixtures/XmlPeekAliasesFixture.cs index d2b6788ba3..2a71aca657 100644 --- a/src/Cake.Common.Tests/Fixtures/XmlPeekAliasesFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/XmlPeekAliasesFixture.cs @@ -14,7 +14,7 @@ internal sealed class XmlPeekAliasesFixture public FilePath XmlPath { get; set; } public XmlPeekSettings Settings { get; set; } - public XmlPeekAliasesFixture(bool xmlExists = true) + public XmlPeekAliasesFixture(bool xmlExists = true, bool xmlWithDtd = false) { Settings = new XmlPeekSettings(); @@ -24,7 +24,8 @@ public XmlPeekAliasesFixture(bool xmlExists = true) if (xmlExists) { - var xmlFile = fileSystem.CreateFile("/Working/web.config").SetContent(Resources.XmlPeek_Xml); + string content = xmlWithDtd ? Resources.XmlPeek_Xml_Dtd : Resources.XmlPeek_Xml; + var xmlFile = fileSystem.CreateFile("/Working/web.config").SetContent(content); XmlPath = xmlFile.Path; } diff --git a/src/Cake.Common.Tests/Fixtures/XmlPokeFixture.cs b/src/Cake.Common.Tests/Fixtures/XmlPokeFixture.cs index 42128e53b7..5bfa33f153 100644 --- a/src/Cake.Common.Tests/Fixtures/XmlPokeFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/XmlPokeFixture.cs @@ -17,7 +17,7 @@ internal sealed class XmlPokeFixture public FilePath XmlPath { get; set; } public XmlPokeSettings Settings { get; set; } - public XmlPokeFixture(bool xmlExists = true) + public XmlPokeFixture(bool xmlExists = true, bool xmlWithDtd = false) { Settings = new XmlPokeSettings(); @@ -27,7 +27,8 @@ public XmlPokeFixture(bool xmlExists = true) if (xmlExists) { - var xmlFile = fileSystem.CreateFile("/Working/web.config").SetContent(Resources.XmlPoke_Xml); + string content = xmlWithDtd ? Resources.XmlPoke_Xml_Dtd : Resources.XmlPoke_Xml; + var xmlFile = fileSystem.CreateFile("/Working/web.config").SetContent(content); XmlPath = xmlFile.Path; } @@ -43,6 +44,11 @@ public void Poke(string xpath, string value) XmlPokeAliases.XmlPoke(Context, XmlPath, xpath, value, Settings); } + public string PokeString(string xml, string xpath, string value) + { + return XmlPokeAliases.XmlPokeString(Context, xml, xpath, value, Settings); + } + public bool TestIsValue(string xpath, string value) { var xmlString = new StreamReader(FileSystem.GetFile(XmlPath).OpenRead()).ReadToEnd(); @@ -52,7 +58,7 @@ public bool TestIsValue(string xpath, string value) public bool TestIsValue(string xml, string xpath, string value) { using (var reader = new StringReader(xml)) - using (var xmlReader = XmlReader.Create(reader)) + using (var xmlReader = XmlReader.Create(reader, GetXmlReaderSettings(Settings))) { var document = new XmlDocument(); @@ -78,7 +84,7 @@ public bool TestIsRemoved(string xpath) public bool TestIsRemoved(string xml, string xpath) { using (var reader = new StringReader(xml)) - using (var xmlReader = XmlReader.Create(reader)) + using (var xmlReader = XmlReader.Create(reader, GetXmlReaderSettings(Settings))) { var document = new XmlDocument(); @@ -94,5 +100,18 @@ public bool TestIsRemoved(string xml, string xpath) return nodes != null && nodes.Count == 0; } } + + /// + /// Gets a XmlReaderSettings from a XmlPokeSettings + /// + /// The xml reader settings. + /// Additional settings to tweak Xml Poke behavior. + private static XmlReaderSettings GetXmlReaderSettings(XmlPokeSettings settings) + { + var xmlReaderSettings = new XmlReaderSettings(); + xmlReaderSettings.DtdProcessing = (DtdProcessing)settings.DtdProcessing; + + return xmlReaderSettings; + } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Properties/Resources.Designer.cs b/src/Cake.Common.Tests/Properties/Resources.Designer.cs index 6fdc564c6a..6e6a4f02e3 100644 --- a/src/Cake.Common.Tests/Properties/Resources.Designer.cs +++ b/src/Cake.Common.Tests/Properties/Resources.Designer.cs @@ -145,6 +145,34 @@ internal static string ChocolateyNuspec_NoMetadataValues_WithoutNamespaces { } } + /// + /// Looks up a localized string similar to <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + /// <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + /// <PropertyGroup> + /// <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> + /// <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + /// <Platform Condition=" '$(Platform)' == [rest of string was truncated]";. + /// + internal static string Csproj_IncompleteFile { + get { + return ResourceManager.GetString("Csproj_IncompleteFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + /// <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + /// <PropertyGroup> + /// <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> + /// <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + /// <Platform Condition=" '$(Platform)' == [rest of string was truncated]";. + /// + internal static string Csproj_ProjectFile { + get { + return ResourceManager.GetString("Csproj_ProjectFile", resourceCulture); + } + } + /// /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> ///<DuplicatesReport ToolsVersion="103.0"> @@ -229,6 +257,26 @@ internal static string InspectCodeReportWithViolations { } } + /// + /// Looks up a localized string similar to using System.Reflection; + ///using System.Runtime.CompilerServices; + /// + ///// Information about this assembly is defined by the following attributes. + ///// Change them to the values specific to your project. + /// + ///[assembly: AssemblyTitle ("MonoDevelopAssemblyTitle")] + ///[assembly: AssemblyDescription ("MonoDevelopAssemblyDescription")] + ///[assembly: AssemblyConfiguration ("MonoDevelopConfiguration")] + ///[assembly: AssemblyCompany ("MonoDevelopCompany")] + ///[assembly: AssemblyProduct ("MonoDevelopProduct")] + ///[assembly: Assembl [rest of string was truncated]";. + /// + internal static string MonoDevelopAssemblyInfo { + get { + return ResourceManager.GetString("MonoDevelopAssemblyInfo", resourceCulture); + } + } + /// /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> ///<package xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> @@ -281,7 +329,7 @@ internal static string Nuspec_Metadata_WithDependencies { /// <licenseUrl>https://license.com</licenseUrl> /// <projectUrl>https://project.com</projectUrl> /// <iconUrl>https://icon.com</iconUrl> - /// <requireLicenseAcceptance>true</requireLicenseA [rest of string was truncated]";. + /// <developmentDependency>true</developmentDepende [rest of string was truncated]";. /// internal static string Nuspec_Metadata_WithoutNamespaces { get { @@ -303,7 +351,7 @@ internal static string Nuspec_Metadata_WithoutNamespaces { /// <licenseUrl>https://license.com</licenseUrl> /// <projectUrl>https://project.com</projectUrl> /// <iconUrl>https://icon.com</iconUrl> - /// <requireLicenseAcceptance>true</requireLicenseA [rest of string was truncated]";. + /// <developmentDependency>true</developmentDepende [rest of string was truncated]";. /// internal static string Nuspec_Metadata_WithoutNamespaces_WithDependencies { get { @@ -381,6 +429,26 @@ internal static string Nuspec_ProjectFile { } } + /// + /// Looks up a localized string similar to using System.Reflection; + ///using System.Runtime.CompilerServices; + /// + ///// Information about this assembly is defined by the following attributes. + ///// Change them to the values specific to your project. + /// + ///[assembly: AssemblyTitle("VisualStudioAssemblyTitle")] + ///[assembly: AssemblyDescription("VisualStudioAssemblyDescription")] + ///[assembly: AssemblyConfiguration("VisualStudioConfiguration")] + ///[assembly: AssemblyCompany("VisualStudioCompany")] + ///[assembly: AssemblyProduct("VisualStudioProduct")] + ///[assembly: Assembl [rest of string was truncated]";. + /// + internal static string VisualStudioAssemblyInfo { + get { + return ResourceManager.GetString("VisualStudioAssemblyInfo", resourceCulture); + } + } + /// /// Looks up a localized string similar to <?xml version="1.0"?> ///<doc> @@ -419,6 +487,23 @@ internal static string XmlPeek_Xml { } } + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8"?> + ///<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + ///<plist version="1.0"> + ///<dict> + /// <key>CFBundleDisplayName</key> + /// <string>Cake</string> + ///</dict> + ///</plist> + ///. + /// + internal static string XmlPeek_Xml_Dtd { + get { + return ResourceManager.GetString("XmlPeek_Xml_Dtd", resourceCulture); + } + } + /// /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> ///<configuration> @@ -434,6 +519,22 @@ internal static string XmlPoke_Xml { } } + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8"?> + ///<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + ///<plist version="1.0"> + ///<dict> + /// <key>CFBundleDisplayName</key> + /// <string>Cake</string> + ///</dict> + ///</plist>. + /// + internal static string XmlPoke_Xml_Dtd { + get { + return ResourceManager.GetString("XmlPoke_Xml_Dtd", resourceCulture); + } + } + /// /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?><html><body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE"><div style="background-color:teal;color:white;padding:4px"><span style="font-weight:bold">Belgian Waffles /// - diff --git a/src/Cake.Common.Tests/Properties/Resources.resx b/src/Cake.Common.Tests/Properties/Resources.resx index 259b5fc960..4ca8c85492 100644 --- a/src/Cake.Common.Tests/Properties/Resources.resx +++ b/src/Cake.Common.Tests/Properties/Resources.resx @@ -294,6 +294,7 @@ Line #3]]></releaseNotes> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> <iconUrl>https://icon.com</iconUrl> + <developmentDependency>true</developmentDependency> <requireLicenseAcceptance>true</requireLicenseAcceptance> <copyright>The copyright</copyright> <releaseNotes><![CDATA[Line #1 @@ -323,6 +324,7 @@ Line #3]]></releaseNotes> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> <iconUrl>https://icon.com</iconUrl> + <developmentDependency>true</developmentDependency> <requireLicenseAcceptance>true</requireLicenseAcceptance> <copyright>The copyright</copyright> <releaseNotes><![CDATA[Line #1 @@ -356,6 +358,7 @@ Line #3]]></releaseNotes> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> <iconUrl>https://icon.com</iconUrl> + <developmentDependency>true</developmentDependency> <requireLicenseAcceptance>true</requireLicenseAcceptance> <copyright>The copyright</copyright> <releaseNotes><![CDATA[Line #1 @@ -385,6 +388,7 @@ Line #3]]></releaseNotes> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> <iconUrl>https://icon.com</iconUrl> + <developmentDependency>true</developmentDependency> <requireLicenseAcceptance>true</requireLicenseAcceptance> <copyright>The copyright</copyright> <releaseNotes><![CDATA[Line #1 @@ -520,6 +524,17 @@ Line #3]]></releaseNotes> </appSettings> </configuration> + + <?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDisplayName</key> + <string>Cake</string> +</dict> +</plist> + + <?xml version="1.0" encoding="utf-8" ?> <configuration> @@ -531,6 +546,17 @@ Line #3]]></releaseNotes> </configuration> + + <?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDisplayName</key> + <string>Cake</string> +</dict> +</plist> + + <?xml version="1.0" encoding="utf-8"?><html><body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE"><div style="background-color:teal;color:white;padding:4px"><span style="font-weight:bold">Belgian Waffles - @@ -659,4 +685,143 @@ Line #3]]></releaseNotes> --> </Project> + + <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{864BC2C5-0E27-47EC-B103-0AC11FE40C5B}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Cake.Common</RootNamespace> + <AssemblyName>Cake.Common</AssemblyName> + <DefaultLanguage>en-US</DefaultLanguage> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Class1.cs" /> + </ItemGroup> + <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> +</Project> + + + <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{864BC2C5-0E27-47EC-B103-0AC11FE40C5B}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Cake.Common</RootNamespace> + <AssemblyName>Cake.Common</AssemblyName> + <DefaultLanguage>en-US</DefaultLanguage> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <TargetFrameworkProfile>Profile111</TargetFrameworkProfile> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Class1.cs" /> + </ItemGroup> + <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> +</Project> + + + using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("MonoDevelopAssemblyTitle")] +[assembly: AssemblyDescription ("MonoDevelopAssemblyDescription")] +[assembly: AssemblyConfiguration ("MonoDevelopConfiguration")] +[assembly: AssemblyCompany ("MonoDevelopCompany")] +[assembly: AssemblyProduct ("MonoDevelopProduct")] +[assembly: AssemblyCopyright ("MonoDevelopCopyright")] +[assembly: AssemblyTrademark ("MonoDevelopTrademark")] +[assembly: AssemblyCulture ("en-US")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.14")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + + + using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("VisualStudioAssemblyTitle")] +[assembly: AssemblyDescription("VisualStudioAssemblyDescription")] +[assembly: AssemblyConfiguration("VisualStudioConfiguration")] +[assembly: AssemblyCompany("VisualStudioCompany")] +[assembly: AssemblyProduct("VisualStudioProduct")] +[assembly: AssemblyCopyright("VisualStudioCopyright")] +[assembly: AssemblyTrademark("VisualStudioTrademark")] +[assembly: AssemblyCulture("en-US")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.13")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Build/AppVeyor/AppVeyorProviderTests.cs b/src/Cake.Common.Tests/Unit/Build/AppVeyor/AppVeyorProviderTests.cs index 0ba7f2c7ae..160f9ac4f7 100644 --- a/src/Cake.Common.Tests/Unit/Build/AppVeyor/AppVeyorProviderTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/AppVeyor/AppVeyorProviderTests.cs @@ -198,5 +198,37 @@ public void Should_Update_Build_Version() Arg.Is(p => p.Arguments.Render() == "UpdateBuild -Version \"build-123\"")); } } + + public sealed class TheUploadTestResultsMethod + { + [Fact] + public void Should_Throw_If_Path_Is_Null() + { + // Given + var fixture = new AppVeyorFixture(); + var appVeyor = fixture.CreateAppVeyorService(); + + // When + var result = Record.Exception(() => appVeyor.UploadTestResults(null, AppVeyorTestResultsType.XUnit)); + + // Then + Assert.IsArgumentNullException(result, "path"); + } + + [Fact] + public void Should_Throw_If_Not_Running_On_AppVeyor() + { + // Given + var fixture = new AppVeyorFixture(); + var appVeyor = fixture.CreateAppVeyorService(); + + // When + var result = Record.Exception(() => appVeyor.UploadTestResults("./file.xml", AppVeyorTestResultsType.XUnit)); + + // Then + Assert.IsExceptionWithMessage(result, + "The current build is not running on AppVeyor."); + } + } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Solution/Project/ProjectParserTests.cs b/src/Cake.Common.Tests/Unit/Solution/Project/ProjectParserTests.cs new file mode 100644 index 0000000000..b4c8ce9605 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Solution/Project/ProjectParserTests.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Cake.Common.Solution.Project; +using Cake.Common.Tests.Fixtures.Solution.Project; +using Cake.Core; +using Cake.Core.IO; +using NSubstitute; +using Xunit; + +namespace Cake.Common.Tests.Unit.Solution.Project +{ + public sealed class ProjectParserTests + { + public sealed class TheConstructor + { + [Fact] + public void Should_Throw_If_File_System_Is_Null() + { + // Given + var environment = Substitute.For(); + + // When + var result = Record.Exception(() => new ProjectParser(null, environment)); + + // Then + Assert.IsArgumentNullException(result, "fileSystem"); + } + + [Fact] + public void Should_Throw_If_Environment_Is_Null() + { + // Given + var fileSystem = Substitute.For(); + + // When + var result = Record.Exception(() => new ProjectParser(fileSystem, null)); + + // Then + Assert.IsArgumentNullException(result, "environment"); + } + } + + public sealed class TheParseMethod + { + + [Fact] + public void Should_Return_Parser_Result() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.NotNull(result); + } + + [Fact] + public void Should_Parse_Framework_Version() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.TargetFrameworkVersion, "v4.5"); + } + + [Fact] + public void Should_Parse_Framework_Profile() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal("Profile111", result.TargetFrameworkProfile); + } + + [Fact] + public void Should_Return_Null_When_Profile_Not_Defined() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.ParseIncomplete(); + + // Then + Assert.NotNull(result); + Assert.Null(result.TargetFrameworkProfile); + } + + [Fact] + public void Should_Parse_Assembly_Name() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.AssemblyName, "Cake.Common"); + } + + [Fact] + public void Should_Parse_Namespace() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.RootNameSpace, "Cake.Common"); + } + + [Fact] + public void Should_Parse_Output_Type() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.OutputType, "Library"); + } + + [Fact] + public void Should_Parse_Configuration() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.Configuration, "Debug"); + } + + [Fact] + public void Should_Parse_Platform() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.Platform, "AnyCPU"); + } + + [Fact] + public void Should_Return_Correct_File_Count() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(2, result.Files.Count); + } + + [Fact] + public void Should_Return_Valid_Guid() + { + // Given + var fixture = new ProjectParserFixture(); + + // When + var result = fixture.Parse(); + + // Then + Guid projectGuid; + var parseResult = Guid.TryParseExact(result.ProjectGuid, "B", out projectGuid); + Assert.True(parseResult); + } + } + } +} diff --git a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs index dd54ea7089..c95ac362c5 100644 --- a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs +++ b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs @@ -2,6 +2,7 @@ using System.Linq; using Cake.Common.Solution.Project.Properties; using Cake.Common.Tests.Fixtures; +using Cake.Common.Tests.Properties; using Cake.Core; using Cake.Core.IO; using NSubstitute; @@ -305,6 +306,48 @@ public void Should_Read_AssemblyVersion(string value, string expected) // Then Assert.Equal(expected, result.AssemblyVersion); } + + [Fact] + public void Should_Correctly_Parse_VisualStudio_AssemblyInfo_File() + { + // Given + var fixture = new AssemblyInfoParserFixture(); + fixture.CreateAssemblyInfo = false; + fixture.WithAssemblyInfoContents(Resources.VisualStudioAssemblyInfo.NormalizeLineEndings()); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.Title, "VisualStudioAssemblyTitle"); + Assert.Equal(result.Description, "VisualStudioAssemblyDescription"); + Assert.Equal(result.Configuration, "VisualStudioConfiguration"); + Assert.Equal(result.Company, "VisualStudioCompany"); + Assert.Equal(result.Product, "VisualStudioProduct"); + Assert.Equal(result.Copyright, "VisualStudioCopyright"); + Assert.Equal(result.Trademark, "VisualStudioTrademark"); + } + + [Fact] + public void Should_Correctly_Parse_MonoDevelop_AssemblyInfo_File() + { + // Given + var fixture = new AssemblyInfoParserFixture(); + fixture.CreateAssemblyInfo = false; + fixture.WithAssemblyInfoContents(Resources.MonoDevelopAssemblyInfo.NormalizeLineEndings()); + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(result.Title, "MonoDevelopAssemblyTitle"); + Assert.Equal(result.Description, "MonoDevelopAssemblyDescription"); + Assert.Equal(result.Configuration, "MonoDevelopConfiguration"); + Assert.Equal(result.Company, "MonoDevelopCompany"); + Assert.Equal(result.Product, "MonoDevelopProduct"); + Assert.Equal(result.Copyright, "MonoDevelopCopyright"); + Assert.Equal(result.Trademark, "MonoDevelopTrademark"); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs index 6bd2af4192..971eaa102e 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs @@ -89,7 +89,7 @@ public void Should_Add_Additional_Arguments() { // Given var fixture = new DotNetCoreBuilderFixture(); - fixture.Settings.Frameworks = new[] { "net451", "dnxcore50" }; + fixture.Settings.Framework = "net451"; fixture.Settings.Runtime = "runtime1"; fixture.Settings.Configuration = "Release"; fixture.Settings.VersionSuffix = "rc1"; @@ -99,7 +99,7 @@ public void Should_Add_Additional_Arguments() var result = fixture.Run(); // Then - Assert.Equal("build ./src/* --runtime runtime1 --framework \"net451;dnxcore50\" --configuration Release --version-suffix rc1", result.Args); + Assert.Equal("build ./src/* --runtime runtime1 --framework net451 --configuration Release --version-suffix rc1", result.Args); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs index 1b5db25b62..b82f8e0265 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs @@ -85,7 +85,7 @@ public void Should_Add_Settings() { // Given var fixture = new DotNetCoreRestorerFixture(); - fixture.Settings.Source = "https://www.example.com/source"; + fixture.Settings.Sources = new[] { "https://www.example.com/source1", "https://www.example.com/source2" }; fixture.Settings.FallbackSources = new[] { "https://www.example.com/fallback1", "https://www.example.com/fallback2" }; fixture.Settings.Quiet = true; fixture.Settings.NoCache = true; @@ -101,15 +101,18 @@ public void Should_Add_Settings() var result = fixture.Run(); // Then - Assert.Equal("restore" + - " --packages \"/Working/packages\"" + - " --source https://www.example.com/source" + - " --fallbacksource \"https://www.example.com/fallback1;https://www.example.com/fallback2\"" + - " --configfile \"/Working/NuGet.config\"" + - " --infer-runtimes \"runtime1;runtime2\"" + - " --quiet --no-cache --disable-parallel --ignore-failed-sources --force-english-output" + + Assert.Equal("restore" + + " --packages \"/Working/packages\"" + + " --source \"https://www.example.com/source1\"" + + " --source \"https://www.example.com/source2\"" + + " --fallbacksource \"https://www.example.com/fallback1\"" + + " --fallbacksource \"https://www.example.com/fallback2\"" + + " --configfile \"/Working/NuGet.config\"" + + " --infer-runtimes \"runtime1\"" + + " --infer-runtimes \"runtime2\"" + + " --quiet --no-cache --disable-parallel --ignore-failed-sources --force-english-output" + " --verbosity Information", result.Args); } } } -} +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs index be93b54247..7d9cc3da70 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs @@ -73,12 +73,12 @@ public void Should_Add_Path_Arguments() // Given var fixture = new DotNetCoreRunnerFixture(); fixture.Project = "./tools/tool/"; - fixture.Arguments = "--args"; + fixture.Arguments = "--args=\"value\""; // When var result = fixture.Run(); // Then - Assert.Equal("run --project \"./tools/tool/\" -- \"--args\"", result.Args); + Assert.Equal("run --project \"./tools/tool/\" -- --args=\"value\"", result.Args); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/NSIS/MakeNSISRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/NSIS/MakeNSISRunnerTests.cs index 19eea12865..5ff71d912a 100644 --- a/src/Cake.Common.Tests/Unit/Tools/NSIS/MakeNSISRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/NSIS/MakeNSISRunnerTests.cs @@ -158,7 +158,7 @@ public void Should_Add_Defines_To_Arguments_If_Provided() var result = fixture.Run(); // Then - Assert.Equal("/DFoo=Bar /DTest /DTest2 /Working/Test.nsi", result.Args); + Assert.Equal("/DFoo=Bar /DTest /DTest2 \"/Working/Test.nsi\"", result.Args); } [Fact] @@ -172,7 +172,7 @@ public void Should_Add_NoChangeDirectory_To_Arguments_If_Provided() var result = fixture.Run(); // Then - Assert.Equal("/NOCD /Working/Test.nsi", result.Args); + Assert.Equal("/NOCD \"/Working/Test.nsi\"", result.Args); } [Fact] @@ -186,7 +186,7 @@ public void Should_Add_NoConfig_To_Arguments_If_Provided() var result = fixture.Run(); // Then - Assert.Equal("/NOCONFIG /Working/Test.nsi", result.Args); + Assert.Equal("/NOCONFIG \"/Working/Test.nsi\"", result.Args); } } } diff --git a/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs b/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs index 9206233427..21f49fbc1a 100644 --- a/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs @@ -296,6 +296,7 @@ public void Should_Add_Metadata_Element_To_Nuspec_If_Missing() fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); fixture.Settings.IconUrl = new Uri("https://icon.com"); + fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; fixture.Settings.Copyright = "The copyright"; fixture.Settings.ReleaseNotes = new[] { "Line #1", "Line #2", "Line #3" }; @@ -326,6 +327,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec() fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); fixture.Settings.IconUrl = new Uri("https://icon.com"); + fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; fixture.Settings.Copyright = "The copyright"; fixture.Settings.ReleaseNotes = new[] { "Line #1", "Line #2", "Line #3" }; @@ -357,6 +359,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_Without_Namespaces() fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); fixture.Settings.IconUrl = new Uri("https://icon.com"); + fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; fixture.Settings.Copyright = "The copyright"; fixture.Settings.ReleaseNotes = new[] { "Line #1", "Line #2", "Line #3" }; @@ -387,6 +390,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_With_Files() fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); fixture.Settings.IconUrl = new Uri("https://icon.com"); + fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; fixture.Settings.Copyright = "The copyright"; fixture.Settings.ReleaseNotes = new[] { "Line #1", "Line #2", "Line #3" }; @@ -430,6 +434,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_With_Files_Without_Namespac fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); fixture.Settings.IconUrl = new Uri("https://icon.com"); + fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; fixture.Settings.Copyright = "The copyright"; fixture.Settings.ReleaseNotes = new[] { "Line #1", "Line #2", "Line #3" }; diff --git a/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs index 8b8b7330f4..60fb7364b0 100644 --- a/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs @@ -1,4 +1,5 @@ -using Cake.Common.Tests.Fixtures.Tools; +using System; +using Cake.Common.Tests.Fixtures.Tools; using Cake.Core; using Cake.Testing; using Xunit; @@ -245,6 +246,20 @@ public void Should_Call_Sign_Tool_With_Correct_Parameters_With_Description() Assert.Equal("SIGN /t \"https://t.com/\" /f \"/Working/cert.pfx\" /p secret /d \"DescriptionTest\" \"/Working/a.dll\"", result.Args); } + [Fact] + public void Should_Call_Sign_Tool_With_Correct_Parameters_With_DescriptionUri() + { + // Given + var fixture = new SignToolSignRunnerFixture(); + fixture.Settings.DescriptionUri = new Uri("https://example.com"); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("SIGN /t \"https://t.com/\" /f \"/Working/cert.pfx\" /p secret /du \"https://example.com/\" \"/Working/a.dll\"", result.Args); + } + [Fact] public void Should_Call_Sign_Tool_With_Correct_Parameters_With_Thumbprint() { diff --git a/src/Cake.Common.Tests/Unit/Tools/VSTest/VSTestRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/VSTest/VSTestRunnerTests.cs new file mode 100644 index 0000000000..869de3207d --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Tools/VSTest/VSTestRunnerTests.cs @@ -0,0 +1,244 @@ +using Cake.Common.Tests.Fixtures.Tools; +using Cake.Common.Tools.VSTest; +using Cake.Core; +using Cake.Core.IO; +using Cake.Testing; +using Cake.Testing.Xunit; +using Xunit; + +namespace Cake.Common.Tests.Unit.Tools.VSTest +{ + public sealed class VSTestRunnerTests + { + [Fact] + public void Should_Throw_If_Assembly_Path_Is_Null() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.AssemblyPaths = null; + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + Assert.IsArgumentNullException(result, "assemblyPaths"); + } + + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings = null; + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + Assert.IsArgumentNullException(result, "settings"); + } + + [Fact] + public void Should_Throw_If_Tool_Path_Was_Not_Found() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.GivenDefaultToolDoNotExist(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + Assert.IsType(result); + Assert.Equal("VSTest: Could not locate executable.", result.Message); + } + + [Theory] + [InlineData("/bin/VSTest/vstest.console.exe", "/bin/VSTest/vstest.console.exe")] + [InlineData("./tools/VSTest/vstest.console.exe", "/Working/tools/VSTest/vstest.console.exe")] + public void Should_Use_VSTest_From_Tool_Path_If_Provided(string toolPath, string expected) + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.ToolPath = toolPath; + fixture.GivenSettingsToolPathExist(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Path.FullPath); + } + + [WindowsTheory] + [InlineData("C:/VSTest/vstest.console.exe", "C:/VSTest/vstest.console.exe")] + public void Should_Use_VSTest_From_Tool_Path_If_Provided_On_Windows(string toolPath, string expected) + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.ToolPath = toolPath; + fixture.GivenSettingsToolPathExist(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Path.FullPath); + } + + [Theory] + [InlineData("/ProgramFilesX86/Microsoft Visual Studio 15.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFilesX86/Microsoft Visual Studio 14.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFilesX86/Microsoft Visual Studio 12.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFilesX86/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + public void Should_Use_Available_Tool_Path(string existingToolPath) + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.GivenDefaultToolDoNotExist(); + fixture.FileSystem.CreateFile(existingToolPath); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(existingToolPath, result.Path.FullPath); + } + + [Fact] + public void Should_Set_Working_Directory() + { + // Given + var fixture = new VSTestRunnerFixture(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/Working", result.Process.WorkingDirectory.FullPath); + } + + [Fact] + public void Should_Throw_If_Process_Was_Not_Started() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.GivenProcessCannotStart(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + Assert.IsType(result); + Assert.Equal("VSTest: Process was not started.", result.Message); + } + + [Fact] + public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.GivenProcessExitsWithCode(1); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + Assert.IsType(result); + Assert.Equal("VSTest: Process returned an error (exit code 1).", result.Message); + } + + [Fact] + public void Should_Not_Use_Isolation_By_Default() + { + // Given + var fixture = new VSTestRunnerFixture(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("\"/Working/Test1.dll\"", result.Args); + } + + [Fact] + public void Should_Use_Isolation_If_Enabled_In_Settings() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.InIsolation = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("\"/Working/Test1.dll\" /InIsolation", result.Args); + } + + [Fact] + public void Should_Use_Logger_If_Provided() + { + //Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.Logger = VSTestLogger.Trx; + + //When + var result = fixture.Run(); + + Assert.Equal("\"/Working/Test1.dll\" /Logger:trx", result.Args); + } + + [Fact] + public void Should_Use_SettingsFile_If_Provided() + { + //Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.SettingsFile = new FilePath("Local.RunSettings"); + + //When + var result = fixture.Run(); + + Assert.Equal("\"/Working/Test1.dll\" /Settings:Local.RunSettings", result.Args); + } + + [Fact] + public void Should_Use_PlatformArchitecture_If_Provided() + { + //Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.PlatformArchitecture = VSTestPlatform.x64; + + //When + var result = fixture.Run(); + + Assert.Equal("\"/Working/Test1.dll\" /Platform:x64", result.Args); + } + + [Fact] + public void Should_Use_FrameworkVersion_If_Provided() + { + //Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.FrameworkVersion = VSTestFrameworkVersion.NET40; + + //When + var result = fixture.Run(); + + Assert.Equal("\"/Working/Test1.dll\" /Framework:Framework40", result.Args); + } + + [Fact] + public void Should_Add_FilePath_For_Each_Assembly() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.AssemblyPaths = new[] { new FilePath("./Test1.dll"), new FilePath("./Test2.dll") }; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("\"/Working/Test1.dll\" \"/Working/Test2.dll\"", result.Args); + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/XML/XmlPeekAliasesTests.cs b/src/Cake.Common.Tests/Unit/XML/XmlPeekAliasesTests.cs index 785edeef65..431abafef8 100644 --- a/src/Cake.Common.Tests/Unit/XML/XmlPeekAliasesTests.cs +++ b/src/Cake.Common.Tests/Unit/XML/XmlPeekAliasesTests.cs @@ -1,5 +1,6 @@ using System.IO; using Cake.Common.Tests.Fixtures; +using Cake.Common.Xml; using Xunit; namespace Cake.Common.Tests.Unit.XML @@ -47,6 +48,19 @@ public void Should_Throw_If_No_Xpath() // Then Assert.IsArgumentNullException(result, "xpath"); } + + [Fact] + public void Should_Throw_If_File_Has_Dtd() + { + // Given + var fixture = new XmlPeekAliasesFixture(xmlWithDtd: true); + + // When + var result = Record.Exception(() => fixture.Peek("CFBundleDisplayName")); + + // Then + Assert.IsType(result); + } [Fact] public void Should_Get_Attribute_Value() @@ -73,6 +87,20 @@ public void Should_Get_Node_Value() // Then Assert.Equal("test value", result); } + + [Fact] + public void Should_Get_Node_Value_From_File_With_Dtd() + { + // Given + var fixture = new XmlPeekAliasesFixture(xmlWithDtd:true); + fixture.Settings.DtdProcessing = XmlDtdProcessing.Parse; + + // When + var result = fixture.Peek("/plist/dict/key/text()"); + + // Then + Assert.Equal("CFBundleDisplayName", result); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/XML/XmlPokeTests.cs b/src/Cake.Common.Tests/Unit/XML/XmlPokeTests.cs index d4dcaa30b4..5db46ab373 100644 --- a/src/Cake.Common.Tests/Unit/XML/XmlPokeTests.cs +++ b/src/Cake.Common.Tests/Unit/XML/XmlPokeTests.cs @@ -1,6 +1,9 @@ using System.IO; using Cake.Common.Tests.Fixtures; +using Cake.Common.Xml; using Xunit; +using Cake.Common.Tests.Properties; +using System.Text; namespace Cake.Common.Tests.Unit.XML { @@ -47,6 +50,32 @@ public void Should_Throw_If_No_Xpath() // Then Assert.IsArgumentNullException(result, "xpath"); } + + [Fact] + public void Should_Throw_If_Xml_File_Has_Dtd() + { + // Given + var fixture = new XmlPokeFixture(xmlWithDtd: true); + + // When + var result = Record.Exception(() => fixture.Poke("/plist/dict/string/text()","")); + + // Then + Assert.IsType(result); + } + + [Fact] + public void Should_Throw_If_Xml_String_Has_Dtd() + { + // Given + var fixture = new XmlPokeFixture(xmlExists:false); + + // When + var result = Record.Exception(() => fixture.PokeString(Resources.XmlPoke_Xml_Dtd, "/plist/dict/string/text()","")); + + // Then + Assert.IsType(result); + } } public sealed class Transform @@ -61,9 +90,9 @@ public void Should_Change_Attribute() fixture.Poke("/configuration/appSettings/add[@key = 'server']/@value", "productionhost.somecompany.com"); // Then - fixture.TestIsValue( + Assert.True(fixture.TestIsValue( "/configuration/appSettings/add[@key = 'server']/@value", - "productionhost.somecompany.com"); + "productionhost.somecompany.com")); } [Fact] @@ -76,8 +105,24 @@ public void Should_Remove_Attribute() fixture.Poke("/configuration/appSettings/add[@key = 'server']", null); // Then - fixture.TestIsRemoved( - "/configuration/appSettings/add[@key = 'server']"); + Assert.True(fixture.TestIsRemoved( + "/configuration/appSettings/add[@key = 'server']")); + } + + [Fact] + public void Should_Change_Attribute_From_Xml_File_With_Dtd() + { + // Given + var fixture = new XmlPokeFixture(xmlWithDtd:true); + fixture.Settings.DtdProcessing = XmlDtdProcessing.Parse; + + // When + fixture.Poke("/plist/dict/string", "Cake Version"); + + // Then + Assert.True(fixture.TestIsValue( + "/plist/dict/string/text()", + "Cake Version")); } } } diff --git a/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs b/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs index e853260e28..43c55d420e 100644 --- a/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs +++ b/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs @@ -1,4 +1,7 @@ using System; +using System.Globalization; +using System.IO; +using System.Net.Http; using Cake.Common.Build.AppVeyor.Data; using Cake.Core; using Cake.Core.IO; @@ -87,6 +90,39 @@ public void UploadArtifact(FilePath path) _processRunner.Start("appveyor", new ProcessSettings { Arguments = arguments }); } + /// + /// Uploads test results XML file to AppVeyor. Results type can be one of the following: mstest, xunit, nunit, nunit3, junit. + /// + /// The file path of the test results XML to upload. + /// The results type. Can be mstest, xunit, nunit, nunit3 or junit. + public void UploadTestResults(FilePath path, AppVeyorTestResultsType resultsType) + { + if (path == null) + { + throw new ArgumentNullException("path"); + } + + if (!IsRunningOnAppVeyor) + { + throw new CakeException("The current build is not running on AppVeyor."); + } + + var baseUri = _environment.GetEnvironmentVariable("APPVEYOR_URL").TrimEnd('/'); + + if (string.IsNullOrWhiteSpace(baseUri)) + { + throw new CakeException("Failed to get AppVeyor API url."); + } + + var url = string.Format(CultureInfo.InvariantCulture, "{0}/api/testresults/{1}/{2}", baseUri, resultsType, Environment.JobId); + + using (var stream = File.OpenRead(path.FullPath)) + using (var client = new HttpClient()) + { + client.PostAsync(url, new StreamContent(stream)).Wait(); + } + } + /// /// Updates the build version. /// diff --git a/src/Cake.Common/Build/AppVeyor/AppVeyorTestResultsType.cs b/src/Cake.Common/Build/AppVeyor/AppVeyorTestResultsType.cs new file mode 100644 index 0000000000..6a09d1cdab --- /dev/null +++ b/src/Cake.Common/Build/AppVeyor/AppVeyorTestResultsType.cs @@ -0,0 +1,33 @@ +namespace Cake.Common.Build.AppVeyor +{ + /// + /// Provides the known values for the AppVeyor test results types. + /// + public enum AppVeyorTestResultsType + { + /// + /// MSTest test results. + /// + MSTest, + + /// + /// XUnit test results. + /// + XUnit, + + /// + /// NUnit test results. + /// + NUnit, + + /// + /// NUnit v3 test results. + /// + NUnit3, + + /// + /// JUnit test results. + /// + JUnit + } +} diff --git a/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs b/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs index 8ce5cb86d9..ffdc84cdd0 100644 --- a/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs +++ b/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs @@ -30,6 +30,13 @@ public interface IAppVeyorProvider /// The file path of the artifact to upload. void UploadArtifact(FilePath path); + /// + /// Uploads test results XML file to AppVeyor. Results type can be one of the following: mstest, xunit, nunit, nunit3, junit. + /// + /// The file path of the test results XML to upload. + /// The results type. Can be mstest, xunit, nunit, nunit3 or junit. + void UploadTestResults(FilePath path, AppVeyorTestResultsType resultsType); + /// /// Updates the build version. /// diff --git a/src/Cake.Common/Build/BuildSystemAliases.cs b/src/Cake.Common/Build/BuildSystemAliases.cs index f6ece79f03..821f7448c8 100644 --- a/src/Cake.Common/Build/BuildSystemAliases.cs +++ b/src/Cake.Common/Build/BuildSystemAliases.cs @@ -60,6 +60,8 @@ public static BuildSystem BuildSystem(this ICakeContext context) /// The context. /// A instance. [CakePropertyAlias(Cache = true)] + [CakeNamespaceImport("Cake.Common.Build.AppVeyor")] + [CakeNamespaceImport("Cake.Common.Build.AppVeyor.Data")] public static IAppVeyorProvider AppVeyor(this ICakeContext context) { if (context == null) diff --git a/src/Cake.Common/Cake.Common.csproj b/src/Cake.Common/Cake.Common.csproj index f056d3a0c6..d9817d0d79 100644 --- a/src/Cake.Common/Cake.Common.csproj +++ b/src/Cake.Common/Cake.Common.csproj @@ -53,6 +53,7 @@ + @@ -362,6 +363,12 @@ + + + + + + @@ -402,6 +409,7 @@ + diff --git a/src/Cake.Common/Solution/Project/ProjectParser.cs b/src/Cake.Common/Solution/Project/ProjectParser.cs index 4ca5e0a1a7..fddb1642e1 100644 --- a/src/Cake.Common/Solution/Project/ProjectParser.cs +++ b/src/Cake.Common/Solution/Project/ProjectParser.cs @@ -100,6 +100,10 @@ from propertyGroup in project.Elements(ProjectXElement.PropertyGroup) TargetFrameworkVersion = propertyGroup .Elements(ProjectXElement.TargetFrameworkVersion) .Select(targetFrameworkVersion => targetFrameworkVersion.Value) + .FirstOrDefault(), + TargetFrameworkProfile = propertyGroup + .Elements(ProjectXElement.TargetFrameworkProfile) + .Select(targetFrameworkProfile => targetFrameworkProfile.Value) .FirstOrDefault() }).FirstOrDefault(); @@ -138,6 +142,7 @@ from include in element.Attributes("Include") projectProperties.RootNameSpace, projectProperties.AssemblyName, projectProperties.TargetFrameworkVersion, + projectProperties.TargetFrameworkProfile, projectFiles); } } diff --git a/src/Cake.Common/Solution/Project/ProjectParserResult.cs b/src/Cake.Common/Solution/Project/ProjectParserResult.cs index e1349d9c51..96ebfe01ca 100644 --- a/src/Cake.Common/Solution/Project/ProjectParserResult.cs +++ b/src/Cake.Common/Solution/Project/ProjectParserResult.cs @@ -15,6 +15,7 @@ public sealed class ProjectParserResult private readonly string _rootNameSpace; private readonly string _assemblyName; private readonly string _targetFrameworkVersion; + private readonly string _targetFrameworkProfile; private readonly ICollection _files; /// @@ -80,6 +81,15 @@ public string TargetFrameworkVersion get { return _targetFrameworkVersion; } } + /// + /// Gets the compiler target framework profile. + /// + /// The target framework profile. + public string TargetFrameworkProfile + { + get { return _targetFrameworkProfile; } + } + /// /// Gets the project content files. /// @@ -99,6 +109,7 @@ public ICollection Files /// The default root namespace. /// Gets the build target assembly name. /// The compiler framework version. + /// The compiler framework profile. /// The project content files. public ProjectParserResult( string configuration, @@ -108,6 +119,7 @@ public ProjectParserResult( string rootNameSpace, string assemblyName, string targetFrameworkVersion, + string targetFrameworkProfile, IEnumerable files) { _configuration = configuration; @@ -117,6 +129,7 @@ public ProjectParserResult( _rootNameSpace = rootNameSpace; _assemblyName = assemblyName; _targetFrameworkVersion = targetFrameworkVersion; + _targetFrameworkProfile = targetFrameworkProfile; _files = files.ToList().AsReadOnly(); } } diff --git a/src/Cake.Common/Solution/Project/ProjectXElement.cs b/src/Cake.Common/Solution/Project/ProjectXElement.cs index f7354f35cc..d992289b78 100644 --- a/src/Cake.Common/Solution/Project/ProjectXElement.cs +++ b/src/Cake.Common/Solution/Project/ProjectXElement.cs @@ -57,6 +57,11 @@ internal static class ProjectXElement /// internal const string TargetFrameworkVersion = "{" + XmlNamespace + "}TargetFrameworkVersion"; + /// + /// Gets the namespace for the target framework version element. + /// + internal const string TargetFrameworkProfile = "{" + XmlNamespace + "}TargetFrameworkProfile"; + /// /// Gets the namespace for the configuration element. /// diff --git a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs index 90f76804b7..16f1606f67 100644 --- a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs +++ b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs @@ -14,8 +14,8 @@ namespace Cake.Common.Solution.Project.Properties /// public sealed class AssemblyInfoParser { - private const string NonQuotedPattern = @"^\s*\[assembly: {0}\((?.*)\)"; - private const string QuotedPattern = @"^\s*\[assembly: {0}\(""(?.*)""\)"; + private const string NonQuotedPattern = @"^\s*\[assembly: {0} ?\((?.*)\)"; + private const string QuotedPattern = @"^\s*\[assembly: {0} ?\(""(?.*)""\)"; private const string DefaultVersion = "1.0.0.0"; private readonly IFileSystem _fileSystem; diff --git a/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs b/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs index ad2157af6d..164bdef6a5 100644 --- a/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs +++ b/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs @@ -15,7 +15,12 @@ namespace Cake.Common.Tools.Chocolatey { /// - /// Contains functionality for working with Chocolatey. + /// Contains functionality for working with Chocolatey. + /// + /// In order to use the commands for this alias, Chocolatey will require to be installed on the machine where the build script + /// is being run. See this page for details on how + /// Chocolatey can be installed. + /// /// [CakeAliasCategory("Chocolatey")] public static class ChocolateyAliases diff --git a/src/Cake.Common/Tools/DNU/DNUAliases.cs b/src/Cake.Common/Tools/DNU/DNUAliases.cs index ff66f4c2ad..724d792d72 100644 --- a/src/Cake.Common/Tools/DNU/DNUAliases.cs +++ b/src/Cake.Common/Tools/DNU/DNUAliases.cs @@ -2,6 +2,7 @@ using Cake.Common.Tools.DNU.Build; using Cake.Common.Tools.DNU.Pack; using Cake.Common.Tools.DNU.Restore; +using Cake.Common.Tools.DotNetCore; using Cake.Core; using Cake.Core.Annotations; using Cake.Core.IO; @@ -10,6 +11,7 @@ namespace Cake.Common.Tools.DNU { /// /// Contains functionality for working with the DNU Utility. + /// These aliases have been marked as Obsolete. Use the instead. /// [CakeAliasCategory("DNU")] public static class DNUAliases diff --git a/src/Cake.Common/Tools/DotCover/DotCoverAliases.cs b/src/Cake.Common/Tools/DotCover/DotCoverAliases.cs index 5828537932..86fa683078 100644 --- a/src/Cake.Common/Tools/DotCover/DotCoverAliases.cs +++ b/src/Cake.Common/Tools/DotCover/DotCoverAliases.cs @@ -8,7 +8,14 @@ namespace Cake.Common.Tools.DotCover { /// - /// Contains functionality related to DotCover. + /// Contains functionality related to DotCover. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the appropriate settings class: + /// + /// #tool "nuget:?package=JetBrains.dotCover.CommandLineTools" + /// + /// /// [CakeAliasCategory("DotCover")] public static class DotCoverAliases diff --git a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs index 158976d7b4..4fbfb4d71b 100644 --- a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs @@ -29,9 +29,9 @@ public sealed class DotNetCoreBuildSettings : DotNetCoreSettings public string Configuration { get; set; } /// - /// Gets or sets specific frameworks to compile. + /// Gets or sets the specific framework to compile. /// - public ICollection Frameworks { get; set; } + public string Framework { get; set; } /// /// Gets or sets the value that defines what `*` should be replaced with in version field in project.json. diff --git a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs index f1fb852f4f..24850d7424 100644 --- a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs +++ b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs @@ -80,11 +80,11 @@ private ProcessArgumentBuilder GetArguments(string project, DotNetCoreBuildSetti builder.Append(settings.Runtime); } - // Frameworks - if (settings.Frameworks != null && settings.Frameworks.Count > 0) + // Framework + if (!string.IsNullOrEmpty(settings.Framework)) { builder.Append("--framework"); - builder.AppendQuoted(string.Join(";", settings.Frameworks)); + builder.Append(settings.Framework); } // Configuration diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs index 0cd06d037b..f22a7bf9eb 100644 --- a/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs @@ -13,7 +13,12 @@ namespace Cake.Common.Tools.DotNetCore { /// - /// Contains functionality for working with the .NET Core CLI. + /// Contains functionality related to .NET Core CLI. + /// + /// In order to use the commands for this alias, the .Net Core CLI tools will need to be installed on the machine where + /// the Cake script is being executed. See this page for information + /// on how to install. + /// /// [CakeAliasCategory("DotNetCore")] public static class DotNetCoreAliases @@ -50,7 +55,7 @@ public static void DotNetCoreExecute(this ICakeContext context, FilePath assembl [CakeMethodAlias] [CakeAliasCategory("Execute")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Execute")] - public static void DotNetCoreExecute(this ICakeContext context, FilePath assemblyPath, string arguments) + public static void DotNetCoreExecute(this ICakeContext context, FilePath assemblyPath, ProcessArgumentBuilder arguments) { context.DotNetCoreExecute(assemblyPath, arguments, null); } @@ -75,7 +80,7 @@ public static void DotNetCoreExecute(this ICakeContext context, FilePath assembl [CakeMethodAlias] [CakeAliasCategory("Execute")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Execute")] - public static void DotNetCoreExecute(this ICakeContext context, FilePath assemblyPath, string arguments, DotNetCoreSettings settings) + public static void DotNetCoreExecute(this ICakeContext context, FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetCoreSettings settings) { if (context == null) { @@ -358,7 +363,7 @@ public static void DotNetCoreRun(this ICakeContext context, string project) [CakeMethodAlias] [CakeAliasCategory("Run")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Run")] - public static void DotNetCoreRun(this ICakeContext context, string project, string arguments) + public static void DotNetCoreRun(this ICakeContext context, string project, ProcessArgumentBuilder arguments) { context.DotNetCoreRun(project, arguments, null); } @@ -384,7 +389,7 @@ public static void DotNetCoreRun(this ICakeContext context, string project, stri [CakeMethodAlias] [CakeAliasCategory("Run")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Run")] - public static void DotNetCoreRun(this ICakeContext context, string project, string arguments, DotNetCoreRunSettings settings) + public static void DotNetCoreRun(this ICakeContext context, string project, ProcessArgumentBuilder arguments, DotNetCoreRunSettings settings) { if (context == null) { @@ -469,7 +474,7 @@ public static void DotNetCorePublish(this ICakeContext context, string project, [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Test")] public static void DotNetCoreTest(this ICakeContext context) { - context.DotNetCoreRun(null, null); + context.DotNetCoreTest(null, null); } /// diff --git a/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs b/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs index 0f10631814..2e65b154a0 100644 --- a/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs +++ b/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs @@ -34,7 +34,7 @@ public DotNetCoreExecutor( /// The assembly path. /// The arguments. /// The settings. - public void Execute(FilePath assemblyPath, string arguments, DotNetCoreSettings settings) + public void Execute(FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetCoreSettings settings) { if (assemblyPath == null) { @@ -48,16 +48,16 @@ public void Execute(FilePath assemblyPath, string arguments, DotNetCoreSettings Run(settings, GetArguments(assemblyPath, arguments, settings)); } - private ProcessArgumentBuilder GetArguments(FilePath assemblyPath, string arguments, DotNetCoreSettings settings) + private ProcessArgumentBuilder GetArguments(FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetCoreSettings settings) { var builder = CreateArgumentBuilder(settings); assemblyPath = assemblyPath.IsRelative ? assemblyPath.MakeAbsolute(_environment) : assemblyPath; builder.Append(assemblyPath.FullPath); - if (!string.IsNullOrEmpty(arguments)) + if (!arguments.IsNullOrEmpty()) { - builder.Append(arguments); + arguments.CopyTo(builder); } return builder; diff --git a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs index 6ed1f4e7d9..5b742ca4b7 100644 --- a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs @@ -9,9 +9,9 @@ namespace Cake.Common.Tools.DotNetCore.Restore public sealed class DotNetCoreRestoreSettings : DotNetCoreSettings { /// - /// Gets or sets the specified NuGet package source to use during the restore. + /// Gets or sets the specified NuGet package sources to use during the restore. /// - public string Source { get; set; } + public ICollection Sources { get; set; } /// /// Gets or sets the NuGet configuration file to use. @@ -63,4 +63,4 @@ public sealed class DotNetCoreRestoreSettings : DotNetCoreSettings /// public DotNetCoreRestoreVerbosity? Verbosity { get; set; } } -} +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs index 2ccb034f49..8030c5ed98 100644 --- a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs +++ b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs @@ -62,18 +62,24 @@ private ProcessArgumentBuilder GetArguments(string root, DotNetCoreRestoreSettin builder.AppendQuoted(settings.PackagesDirectory.MakeAbsolute(_environment).FullPath); } - // Source - if (!string.IsNullOrEmpty(settings.Source)) + // Sources + if (settings.Sources != null) { - builder.Append("--source"); - builder.Append(settings.Source); + foreach (var source in settings.Sources) + { + builder.Append("--source"); + builder.AppendQuoted(source); + } } // List of fallback package sources - if (settings.FallbackSources != null && settings.FallbackSources.Count > 0) + if (settings.FallbackSources != null) { - builder.Append("--fallbacksource"); - builder.AppendQuoted(string.Join(";", settings.FallbackSources)); + foreach (var source in settings.FallbackSources) + { + builder.Append("--fallbacksource"); + builder.AppendQuoted(source); + } } // Config file @@ -84,10 +90,13 @@ private ProcessArgumentBuilder GetArguments(string root, DotNetCoreRestoreSettin } // List of runtime identifiers - if (settings.InferRuntimes != null && settings.InferRuntimes.Count > 0) + if (settings.InferRuntimes != null) { - builder.Append("--infer-runtimes"); - builder.AppendQuoted(string.Join(";", settings.InferRuntimes)); + foreach (var runtime in settings.InferRuntimes) + { + builder.Append("--infer-runtimes"); + builder.AppendQuoted(runtime); + } } // Quiet @@ -130,4 +139,4 @@ private ProcessArgumentBuilder GetArguments(string root, DotNetCoreRestoreSettin return builder; } } -} +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs b/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs index 78718d233b..f5a5d30415 100644 --- a/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs +++ b/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs @@ -31,7 +31,7 @@ public DotNetCoreRunner( /// The target project path. /// The arguments. /// The settings. - public void Run(string project, string arguments, DotNetCoreRunSettings settings) + public void Run(string project, ProcessArgumentBuilder arguments, DotNetCoreRunSettings settings) { if (settings == null) { @@ -41,7 +41,7 @@ public void Run(string project, string arguments, DotNetCoreRunSettings settings Run(settings, GetArguments(project, arguments, settings)); } - private ProcessArgumentBuilder GetArguments(string project, string arguments, DotNetCoreRunSettings settings) + private ProcessArgumentBuilder GetArguments(string project, ProcessArgumentBuilder arguments, DotNetCoreRunSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -68,10 +68,11 @@ private ProcessArgumentBuilder GetArguments(string project, string arguments, Do builder.Append(settings.Configuration); } - if (!string.IsNullOrEmpty(arguments)) + // Arguments + if (!arguments.IsNullOrEmpty()) { builder.Append("--"); - builder.AppendQuoted(arguments); + arguments.CopyTo(builder); } return builder; diff --git a/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs b/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs index ef9990e5fa..bb5f6a8ac7 100644 --- a/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs +++ b/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs @@ -9,7 +9,14 @@ namespace Cake.Common.Tools.DupFinder { /// - /// Contains functionality related to ReSharper's duplication finder + /// Contains functionality related to ReSharper's dupFinder tool. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=JetBrains.ReSharper.CommandLineTools" + /// + /// /// [CakeAliasCategory("ReSharper")] public static class DupFinderAliases diff --git a/src/Cake.Common/Tools/Fixie/FixieAliases.cs b/src/Cake.Common/Tools/Fixie/FixieAliases.cs index 2a9ca1a1c4..8aa259c0e6 100644 --- a/src/Cake.Common/Tools/Fixie/FixieAliases.cs +++ b/src/Cake.Common/Tools/Fixie/FixieAliases.cs @@ -9,7 +9,14 @@ namespace Cake.Common.Tools.Fixie { /// - /// Contains functionality related to running Fixie tests. + /// Contains functionality related to running Fixie tests. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=Fixie" + /// + /// /// [CakeAliasCategory("Fixie")] public static class FixieAliases diff --git a/src/Cake.Common/Tools/GitLink/GitLinkAliases.cs b/src/Cake.Common/Tools/GitLink/GitLinkAliases.cs index c7dda3c705..7e4a7fae7b 100644 --- a/src/Cake.Common/Tools/GitLink/GitLinkAliases.cs +++ b/src/Cake.Common/Tools/GitLink/GitLinkAliases.cs @@ -6,7 +6,14 @@ namespace Cake.Common.Tools.GitLink { /// - /// Contains functionality for working with GitLink. + /// Contains functionality related to GitLink. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=gitlink" + /// + /// /// [CakeAliasCategory("GitTools")] public static class GitLinkAliases diff --git a/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs b/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs index c087c0d808..b24c76de37 100644 --- a/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs +++ b/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs @@ -11,7 +11,14 @@ namespace Cake.Common.Tools.GitReleaseManager { /// - /// Contains functionality for working with GitReleaseManager. + /// Contains functionality related to GitReleaseManager. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the appropriate settings class: + /// + /// #tool "nuget:?package=gitreleasemanager" + /// + /// /// [CakeAliasCategory("GitReleaseManager")] public static class GitReleaseManagerAliases @@ -249,7 +256,7 @@ public static void GitReleaseManagerPublish(this ICakeContext context, string us { throw new ArgumentNullException("context"); } - + var publisher = new GitReleaseManagerPublisher(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); publisher.Publish(userName, password, owner, repository, tagName, settings); } @@ -305,7 +312,7 @@ public static void GitReleaseManagerExport(this ICakeContext context, string use { throw new ArgumentNullException("context"); } - + var publisher = new GitReleaseManagerExporter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); publisher.Export(userName, password, owner, repository, fileOutputPath, settings); } diff --git a/src/Cake.Common/Tools/GitReleaseNotes/GitReleaseNotesAliases.cs b/src/Cake.Common/Tools/GitReleaseNotes/GitReleaseNotesAliases.cs index 09d303b4fb..1c1ea35716 100644 --- a/src/Cake.Common/Tools/GitReleaseNotes/GitReleaseNotesAliases.cs +++ b/src/Cake.Common/Tools/GitReleaseNotes/GitReleaseNotesAliases.cs @@ -6,7 +6,14 @@ namespace Cake.Common.Tools.GitReleaseNotes { /// - /// Contains functionality related to GitReleaseNotes + /// Contains functionality related to GitReleaseNotes. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=GitReleaseNotes" + /// + /// /// [CakeAliasCategory("GitReleaseNotes")] public static class GitReleaseNotesAliases diff --git a/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs b/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs index 6ca69d737a..76ec0b7446 100644 --- a/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs +++ b/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs @@ -5,9 +5,14 @@ namespace Cake.Common.Tools.GitVersion { /// - /// Contains functionality related to GitVersion. - /// GitVersion Documentation - /// GitVersion NuGet Package + /// Contains functionality related to GitVersion. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=GitVersion.CommandLine" + /// + /// /// [CakeAliasCategory("GitVersion")] public static class GitVersionAliases diff --git a/src/Cake.Common/Tools/ILMerge/ILMergeAliases.cs b/src/Cake.Common/Tools/ILMerge/ILMergeAliases.cs index f085df95d6..7add66fb3b 100644 --- a/src/Cake.Common/Tools/ILMerge/ILMergeAliases.cs +++ b/src/Cake.Common/Tools/ILMerge/ILMergeAliases.cs @@ -7,11 +7,12 @@ namespace Cake.Common.Tools.ILMerge { /// - /// Contains functionality related to ILMerge. + /// Contains functionality related to ILMerge. /// - /// In order to use the commands for this alias, include the following in your build.cake file to download and install from NuGet.org, or specify the ToolPath within the ILMergeSettings class: + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: /// - /// #tool "nuget:?package=ILRepack" + /// #tool "nuget:?package=ilmerge" /// /// /// diff --git a/src/Cake.Common/Tools/ILRepack/ILRepackAliases.cs b/src/Cake.Common/Tools/ILRepack/ILRepackAliases.cs index 87439b63a6..de9785edaa 100644 --- a/src/Cake.Common/Tools/ILRepack/ILRepackAliases.cs +++ b/src/Cake.Common/Tools/ILRepack/ILRepackAliases.cs @@ -7,9 +7,10 @@ namespace Cake.Common.Tools.ILRepack { /// - /// Contains functionality related to ILRepack. + /// Contains functionality related to ILRepack. /// - /// In order to use the commands for this alias, include the following in your build.cake file to download and install from NuGet.org, or specify the ToolPath within the ILRepackSettings class: + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: /// /// #tool "nuget:?package=ILRepack" /// diff --git a/src/Cake.Common/Tools/InspectCode/InspectCodeAliases.cs b/src/Cake.Common/Tools/InspectCode/InspectCodeAliases.cs index 08d60f99fc..7f0c4b2dfa 100644 --- a/src/Cake.Common/Tools/InspectCode/InspectCodeAliases.cs +++ b/src/Cake.Common/Tools/InspectCode/InspectCodeAliases.cs @@ -6,7 +6,14 @@ namespace Cake.Common.Tools.InspectCode { /// - /// Contains functionality related to Resharper's code inspection. + /// Contains functionality related to ReSharper's InspectCode tool. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=JetBrains.ReSharper.CommandLineTools" + /// + /// /// [CakeAliasCategory("ReSharper")] public static class InspectCodeAliases diff --git a/src/Cake.Common/Tools/MSBuild/MSBuildAliases.cs b/src/Cake.Common/Tools/MSBuild/MSBuildAliases.cs index a45949baa8..f9714d01ee 100644 --- a/src/Cake.Common/Tools/MSBuild/MSBuildAliases.cs +++ b/src/Cake.Common/Tools/MSBuild/MSBuildAliases.cs @@ -6,7 +6,11 @@ namespace Cake.Common.Tools.MSBuild { /// - /// Contains functionality related to MSBuild. + /// Contains functionality related to MSBuild. + /// + /// In order to use the commands for this alias, MSBuild will already have to be installed on the machine the Cake Script + /// is being executed. + /// /// [CakeAliasCategory("MSBuild")] public static class MSBuildAliases diff --git a/src/Cake.Common/Tools/MSTest/MSTestAliases.cs b/src/Cake.Common/Tools/MSTest/MSTestAliases.cs index 5dd004f663..e0e1465761 100644 --- a/src/Cake.Common/Tools/MSTest/MSTestAliases.cs +++ b/src/Cake.Common/Tools/MSTest/MSTestAliases.cs @@ -9,7 +9,12 @@ namespace Cake.Common.Tools.MSTest { /// - /// Contains functionality related to running MSTest unit tests. + /// Contains functionality related to running MSTest unit tests. + /// + /// In order to use the commands for this alias, MSTest will need to be installed on the machine where + /// the Cake script is being executed. This is typically achieved by having either Visual Studio installed, or by + /// using the Micrsoft Build Tools, for example, for 2015. + /// /// [CakeAliasCategory("MSTest")] public static class MSTestAliases diff --git a/src/Cake.Common/Tools/NSIS/MakeNSISRunner.cs b/src/Cake.Common/Tools/NSIS/MakeNSISRunner.cs index 50e3630382..472d98828b 100644 --- a/src/Cake.Common/Tools/NSIS/MakeNSISRunner.cs +++ b/src/Cake.Common/Tools/NSIS/MakeNSISRunner.cs @@ -92,8 +92,8 @@ private ProcessArgumentBuilder GetArguments(FilePath scriptFile, MakeNSISSetting builder.Append("/NOCONFIG"); } - // Script file - builder.Append(scriptFile.MakeAbsolute(_environment).FullPath); + // Quoted Script file + builder.AppendQuoted(scriptFile.MakeAbsolute(_environment).FullPath); return builder; } diff --git a/src/Cake.Common/Tools/NSIS/NSISAliases.cs b/src/Cake.Common/Tools/NSIS/NSISAliases.cs index a4751058b2..ea73ea65fa 100644 --- a/src/Cake.Common/Tools/NSIS/NSISAliases.cs +++ b/src/Cake.Common/Tools/NSIS/NSISAliases.cs @@ -6,7 +6,12 @@ namespace Cake.Common.Tools.NSIS { /// - /// Contains functionality related to running NSIS. + /// Contains functionality related to NSIS. + /// + /// In order to use the commands for this alias, NSIS will need to be installed on the machine where + /// the Cake script is being executed. See this page for information + /// on how to download/install. + /// /// [CakeAliasCategory("NSIS")] // ReSharper disable once InconsistentNaming diff --git a/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs b/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs index e85a56eba2..894da623d8 100644 --- a/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs +++ b/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs @@ -9,7 +9,14 @@ namespace Cake.Common.Tools.NUnit { /// - /// Contains functionality related to running NUnit v2 and v3 unit tests. + /// Contains functionality related to running NUnit v2 and v3 unit tests. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=NUnit.ConsoleRunner" + /// + /// /// [CakeAliasCategory("NUnit v3")] public static class NUnit3Aliases diff --git a/src/Cake.Common/Tools/NUnit/NUnitAliases.cs b/src/Cake.Common/Tools/NUnit/NUnitAliases.cs index 20f9cee948..4daa3b26e2 100644 --- a/src/Cake.Common/Tools/NUnit/NUnitAliases.cs +++ b/src/Cake.Common/Tools/NUnit/NUnitAliases.cs @@ -9,7 +9,14 @@ namespace Cake.Common.Tools.NUnit { /// - /// Contains functionality related to running NUnit unit tests. + /// Contains functionality related to running NUnit tests. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=NUnit.Runners&version=2.6.4" + /// + /// /// [CakeAliasCategory("NUnit")] public static class NUnitAliases @@ -49,7 +56,7 @@ public static void NUnit(this ICakeContext context, string pattern) /// /// /// NUnit("./src/UnitTests/*.dll", new NUnitSettings { - /// Timeout = 4000, + /// Timeout = 4000, /// StopOnError = true /// }); /// diff --git a/src/Cake.Common/Tools/NuGet/NuGetAliases.cs b/src/Cake.Common/Tools/NuGet/NuGetAliases.cs index f7c419f744..aa5256521a 100644 --- a/src/Cake.Common/Tools/NuGet/NuGetAliases.cs +++ b/src/Cake.Common/Tools/NuGet/NuGetAliases.cs @@ -16,8 +16,12 @@ namespace Cake.Common.Tools.NuGet { /// - /// Contains functionality for working with NuGet. + /// Contains functionality for working with NuGet. /// + /// + /// Since Cake requires NuGet to be available very early in the build pipeline, we recommend that NuGet is made + /// available via the Cake BootStrapper. + /// [CakeAliasCategory("NuGet")] public static class NuGetAliases { @@ -693,7 +697,7 @@ public static void NuGetInstallFromConfig(this ICakeContext context, FilePath pa /// /// /// var packageConfigs = GetFiles("./**/packages.config"); - /// + /// /// NuGetInstallFromConfig(packageConfigs); /// /// @@ -744,7 +748,7 @@ public static void NuGetInstallFromConfig(this ICakeContext context, FilePath pa /// /// /// var packageConfigs = GetFiles("./**/packages.config"); - /// + /// /// NuGetInstallFromConfig(packageConfigs, new NuGetInstallSettings { /// ExcludeVersion = true, /// OutputDirectory = "./tools" @@ -894,7 +898,7 @@ public static void NuGetUpdate(this ICakeContext context, FilePath targetFile) /// /// /// var targets = GetFiles("./**/packages.config"); - /// + /// /// NuGetUpdate(targets); /// /// @@ -944,7 +948,7 @@ public static void NuGetUpdate(this ICakeContext context, FilePath targetFile, N /// /// /// var targets = GetFiles("./**/packages.config"); - /// + /// /// NuGetUpdate(targets, new NuGetUpdateSettings { /// Prerelease = true, /// }); diff --git a/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs b/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs index e4135f550b..84c78f2025 100644 --- a/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs +++ b/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs @@ -127,6 +127,14 @@ public sealed class NuGetPackSettings : ToolSettings /// The package tags. public ICollection Tags { get; set; } + /// + /// Gets or sets a value indicating whether this package should be marked as a development dependency. + /// + /// + /// true if a development dependency; otherwise, false. + /// + public bool DevelopmentDependency { get; set; } + /// /// Gets or sets a value indicating whether users has to accept the package license. /// diff --git a/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs b/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs index 1e113a9f21..231d12d640 100644 --- a/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs +++ b/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs @@ -28,6 +28,7 @@ static NuspecTransformer() { "licenseUrl", settings => ToString(settings.LicenseUrl) }, { "projectUrl", settings => ToString(settings.ProjectUrl) }, { "iconUrl", settings => ToString(settings.IconUrl) }, + { "developmentDependency", settings => ToString(settings.DevelopmentDependency) }, { "requireLicenseAcceptance", settings => ToString(settings.RequireLicenseAcceptance) }, { "copyright", settings => ToString(settings.Copyright) }, { "releaseNotes", settings => ToMultiLineString(settings.ReleaseNotes) }, diff --git a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs index 5aa843cf3e..1c250dbbfa 100644 --- a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs +++ b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs @@ -5,7 +5,14 @@ namespace Cake.Common.Tools.OctopusDeploy { /// - /// Contains functionality for working with Octopus Deploy. + /// Contains functionality related to Octopus Deploy. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the appropriate settings class: + /// + /// #tool "nuget:?package=OctopusTools" + /// + /// /// [CakeAliasCategory("Octopus Deploy")] public static class OctopusDeployAliases diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverAliases.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverAliases.cs index 719a0e7c4e..68a0d483f9 100644 --- a/src/Cake.Common/Tools/OpenCover/OpenCoverAliases.cs +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverAliases.cs @@ -6,7 +6,14 @@ namespace Cake.Common.Tools.OpenCover { /// - /// Contains functionality related to OpenCover. + /// Contains functionality related to OpenCover. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=OpenCover" + /// + /// /// [CakeAliasCategory("OpenCover")] public static class OpenCoverAliases diff --git a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs index 1925070193..2dc2fe6f6a 100644 --- a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs +++ b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs @@ -7,7 +7,14 @@ namespace Cake.Common.Tools.ReportGenerator { /// - /// Contains functionality related to ReportGenerator. + /// Contains functionality related to ReportGenerator. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=ReportGenerator" + /// + /// /// [CakeAliasCategory("ReportGenerator")] public static class ReportGeneratorAliases diff --git a/src/Cake.Common/Tools/ReportUnit/ReportUnitAliases.cs b/src/Cake.Common/Tools/ReportUnit/ReportUnitAliases.cs index c200e1decb..2450ad7488 100644 --- a/src/Cake.Common/Tools/ReportUnit/ReportUnitAliases.cs +++ b/src/Cake.Common/Tools/ReportUnit/ReportUnitAliases.cs @@ -6,7 +6,14 @@ namespace Cake.Common.Tools.ReportUnit { /// - /// Contains functionality related to ReportUnit. + /// Contains functionality related to ReportUnit. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=ReportUnit" + /// + /// /// [CakeAliasCategory("ReportUnit")] public static class ReportUnitAliases diff --git a/src/Cake.Common/Tools/Roundhouse/RoundhouseAliases.cs b/src/Cake.Common/Tools/Roundhouse/RoundhouseAliases.cs index 86b39f236a..8f8169f503 100644 --- a/src/Cake.Common/Tools/Roundhouse/RoundhouseAliases.cs +++ b/src/Cake.Common/Tools/Roundhouse/RoundhouseAliases.cs @@ -5,7 +5,14 @@ namespace Cake.Common.Tools.Roundhouse { /// - /// Contains functionality to execute Roundhouse tasks. + /// Contains functionality related to RoundhousE. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=roundhouse" + /// + /// /// [CakeAliasCategory("Roundhouse")] public static class RoundhouseAliases diff --git a/src/Cake.Common/Tools/SignTool/SignToolSignAliases.cs b/src/Cake.Common/Tools/SignTool/SignToolSignAliases.cs index 674ff66271..17514b7246 100644 --- a/src/Cake.Common/Tools/SignTool/SignToolSignAliases.cs +++ b/src/Cake.Common/Tools/SignTool/SignToolSignAliases.cs @@ -8,7 +8,11 @@ namespace Cake.Common.Tools.SignTool { /// - /// Contains functionality related to signing assemblies with PFX certificates. + /// Contains functionality related to signing assemblies with PFX certificates using SignTool. + /// + /// In order to use the commands for this alias, SignTool will need to be installed on the machine where + /// the Cake script is being executed. This is typically achieved by installing the correct Windows SDK. + /// /// [CakeAliasCategoryAttribute("Signing")] public static class SignToolSignAliases diff --git a/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs b/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs index 88a2476eef..22fa8159b9 100644 --- a/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs +++ b/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs @@ -169,6 +169,13 @@ private ProcessArgumentBuilder GetArguments(FilePath assemblyPath, SignToolSignS builder.AppendQuoted(settings.Description); } + // Signed content expanded description URL. + if (settings.DescriptionUri != null) + { + builder.Append("/du"); + builder.AppendQuoted(settings.DescriptionUri.AbsoluteUri); + } + // Target Assembly to sign. builder.AppendQuoted(assemblyPath.MakeAbsolute(_environment).FullPath); diff --git a/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs b/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs index 811401a7e5..420e1afcd6 100644 --- a/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs +++ b/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs @@ -33,5 +33,10 @@ public sealed class SignToolSignSettings : ToolSettings /// Gets or sets the signed content's description. /// public string Description { get; set; } + + /// + /// Gets or sets the signed content's expanded description URL. + /// + public Uri DescriptionUri { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/SpecFlow/SpecFlowAliases.cs b/src/Cake.Common/Tools/SpecFlow/SpecFlowAliases.cs index 9c2d63f546..996485ab61 100644 --- a/src/Cake.Common/Tools/SpecFlow/SpecFlowAliases.cs +++ b/src/Cake.Common/Tools/SpecFlow/SpecFlowAliases.cs @@ -8,7 +8,14 @@ namespace Cake.Common.Tools.SpecFlow { /// - /// Contains functionality for working with SpecFlow. + /// Contains functionality related to SpecFlow. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the appropriate settings class: + /// + /// #tool "nuget:?package=SpecFlow" + /// + /// /// [CakeAliasCategory("SpecFlow")] public static class SpecFlowAliases diff --git a/src/Cake.Common/Tools/TextTransform/TextTransformAliases.cs b/src/Cake.Common/Tools/TextTransform/TextTransformAliases.cs index 51ef1c6cef..30cde84da2 100644 --- a/src/Cake.Common/Tools/TextTransform/TextTransformAliases.cs +++ b/src/Cake.Common/Tools/TextTransform/TextTransformAliases.cs @@ -6,7 +6,14 @@ namespace Cake.Common.Tools.TextTransform { /// - /// Contains functionality related to transforming templates + /// Contains functionality related to TextTransform. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=Mono.TextTransform" + /// + /// /// [CakeAliasCategory("Text")] public static class TextTransformAliases diff --git a/src/Cake.Common/Tools/VSTest/VSTestAliases.cs b/src/Cake.Common/Tools/VSTest/VSTestAliases.cs new file mode 100644 index 0000000000..e7ef4f0a37 --- /dev/null +++ b/src/Cake.Common/Tools/VSTest/VSTestAliases.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Cake.Core; +using Cake.Core.Annotations; +using Cake.Core.Diagnostics; +using Cake.Core.IO; + +namespace Cake.Common.Tools.VSTest +{ + /// + /// Contains functionality related to running VSTest unit tests. + /// + [CakeAliasCategory("VSTest")] + public static class VSTestAliases + { + /// + /// Runs all VSTest unit tests in the assemblies matching the specified pattern. + /// + /// + /// + /// VSTest("./Tests/*.UnitTests.dll"); + /// + /// + /// The context. + /// The pattern. + [CakeMethodAlias] + public static void VSTest(this ICakeContext context, string pattern) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + var assemblies = context.Globber.GetFiles(pattern).ToArray(); + if (assemblies.Length == 0) + { + context.Log.Verbose("The provided pattern did not match any files."); + return; + } + + VSTest(context, assemblies); + } + + /// + /// Runs all VSTest unit tests in the assemblies matching the specified pattern. + /// + /// + /// + /// VSTest("./Tests/*.UnitTests.dll", new VSTestSettings() { Logger = VSTestLogger.Trx }); + /// + /// + /// The context. + /// The pattern. + /// The settings. + [CakeMethodAlias] + public static void VSTest(this ICakeContext context, string pattern, VSTestSettings settings) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + var assemblies = context.Globber.GetFiles(pattern).ToArray(); + if (assemblies.Length == 0) + { + context.Log.Verbose("The provided pattern did not match any files."); + return; + } + + VSTest(context, assemblies, settings); + } + + /// + /// Runs all VSTest unit tests in the specified assemblies. + /// + /// + /// + /// var paths = new List<FilePath>() { "./assemblydir1", "./assemblydir2" }; + /// VSTest(paths); + /// + /// + /// The context. + /// The assembly paths. + [CakeMethodAlias] + public static void VSTest(this ICakeContext context, IEnumerable assemblyPaths) + { + VSTest(context, assemblyPaths, new VSTestSettings()); + } + + /// + /// Runs all VSTest unit tests in the specified assemblies. + /// + /// + /// + /// var paths = new List<FilePath>() { "./assemblydir1", "./assemblydir2" }; + /// VSTest(paths, new VSTestSettings() { InIsolation = true }); + /// + /// + /// The context. + /// The assembly paths. + /// The settings. + [CakeMethodAlias] + public static void VSTest(this ICakeContext context, IEnumerable assemblyPaths, VSTestSettings settings) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + if (assemblyPaths == null) + { + throw new ArgumentNullException("assemblyPaths"); + } + + var runner = new VSTestRunner(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + runner.Run(assemblyPaths, settings); + } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/VSTest/VSTestFrameworkVersion.cs b/src/Cake.Common/Tools/VSTest/VSTestFrameworkVersion.cs new file mode 100644 index 0000000000..cd9bc5df2d --- /dev/null +++ b/src/Cake.Common/Tools/VSTest/VSTestFrameworkVersion.cs @@ -0,0 +1,28 @@ +namespace Cake.Common.Tools.VSTest +{ + /// + /// Target .NET Framework version to be used for test execution. + /// + public enum VSTestFrameworkVersion + { + /// + /// Use default .NET Framework version. + /// + Default, + + /// + /// .NET Framework version: 3.5. + /// + NET35, + + /// + /// .NET Framework version: 4.0. + /// + NET40, + + /// + /// .NET Framework version: 4.5. + /// + NET45 + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/VSTest/VSTestLogger.cs b/src/Cake.Common/Tools/VSTest/VSTestLogger.cs new file mode 100644 index 0000000000..6bd3a47298 --- /dev/null +++ b/src/Cake.Common/Tools/VSTest/VSTestLogger.cs @@ -0,0 +1,18 @@ +namespace Cake.Common.Tools.VSTest +{ + /// + /// Loggers available for outputting test results. + /// + public enum VSTestLogger + { + /// + /// No logging of test results. + /// + None, + + /// + /// Log results to a Visual Studio test results file. + /// + Trx + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/VSTest/VSTestPlatform.cs b/src/Cake.Common/Tools/VSTest/VSTestPlatform.cs new file mode 100644 index 0000000000..73e02cfdcb --- /dev/null +++ b/src/Cake.Common/Tools/VSTest/VSTestPlatform.cs @@ -0,0 +1,31 @@ +namespace Cake.Common.Tools.VSTest +{ + /// + /// Target platform architecture to be used for test execution. + /// + public enum VSTestPlatform + { + /// + /// Use default platform architecture. + /// + Default, + + /// + /// Platform architecture: x86. + /// + // ReSharper disable once InconsistentNaming + x86, + + /// + /// Platform architecture: x64. + /// + // ReSharper disable once InconsistentNaming + x64, + + /// + /// Platform architecture: ARM. + /// + // ReSharper disable once InconsistentNaming + ARM + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/VSTest/VSTestRunner.cs b/src/Cake.Common/Tools/VSTest/VSTestRunner.cs new file mode 100644 index 0000000000..b24f7f4710 --- /dev/null +++ b/src/Cake.Common/Tools/VSTest/VSTestRunner.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Cake.Core; +using Cake.Core.IO; +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.VSTest +{ + /// + /// The VSTest unit test runner. + /// Used by Visual Studio 2012 and newer. + /// + public sealed class VSTestRunner : Tool + { + private readonly IFileSystem _fileSystem; + private readonly ICakeEnvironment _environment; + + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The environment. + /// The process runner. + /// The tool servce. + public VSTestRunner(IFileSystem fileSystem, + ICakeEnvironment environment, + IProcessRunner processRunner, + IToolLocator toolLocator) + : base(fileSystem, environment, processRunner, toolLocator) + { + _fileSystem = fileSystem; + _environment = environment; + } + + /// + /// Runs the tests in the specified assembly. + /// + /// The assembly path. + /// The settings. + public void Run(IEnumerable assemblyPaths, VSTestSettings settings) + { + if (assemblyPaths == null) + { + throw new ArgumentNullException("assemblyPaths"); + } + if (settings == null) + { + throw new ArgumentNullException("settings"); + } + + base.Run(settings, GetArguments(assemblyPaths, settings)); + } + + private ProcessArgumentBuilder GetArguments(IEnumerable assemblyPaths, VSTestSettings settings) + { + var builder = new ProcessArgumentBuilder(); + + // Add the assembly to build. + foreach (var assemblyPath in assemblyPaths) + { + builder.Append(assemblyPath.MakeAbsolute(_environment).FullPath.Quote()); + } + + if (settings.SettingsFile != null) + { + builder.Append(string.Format(CultureInfo.InvariantCulture, "/Settings:{0}", settings.SettingsFile)); + } + + if (settings.InIsolation) + { + builder.Append("/InIsolation"); + } + + if (settings.PlatformArchitecture != VSTestPlatform.Default) + { + builder.Append(string.Format(CultureInfo.InvariantCulture, "/Platform:{0}", settings.PlatformArchitecture)); + } + + if (settings.FrameworkVersion != VSTestFrameworkVersion.Default) + { + builder.Append(string.Format(CultureInfo.InvariantCulture, "/Framework:{0}", settings.FrameworkVersion.ToString().Replace("NET", "Framework"))); + } + + if (settings.Logger == VSTestLogger.Trx) + { + builder.Append("/Logger:trx"); + } + + return builder; + } + + /// + /// Gets the name of the tool. + /// + /// The tool name. + protected override string GetToolName() + { + return "VSTest"; + } + + /// + /// Gets the possible names of the tool executable. + /// + /// The tool executable name. + protected override IEnumerable GetToolExecutableNames() + { + return Enumerable.Empty(); + } + + /// + /// Gets alternative file paths which the tool may exist in + /// + /// The settings. + /// The default tool path. + protected override IEnumerable GetAlternativeToolPaths(VSTestSettings settings) + { + foreach (var version in new[] { "15.0", "14.0", "12.0", "11.0" }) + { + var path = GetToolPath(version); + if (_fileSystem.Exist(path)) + { + yield return path; + } + } + } + + private FilePath GetToolPath(string version) + { + var programFiles = _environment.GetSpecialPath(SpecialPath.ProgramFilesX86); + var root = programFiles.Combine(string.Concat("Microsoft Visual Studio ", version, "/Common7/IDE/CommonExtensions/Microsoft/TestWindow")); + return root.CombineWithFilePath("vstest.console.exe"); + } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/VSTest/VSTestSettings.cs b/src/Cake.Common/Tools/VSTest/VSTestSettings.cs new file mode 100644 index 0000000000..ba491da42c --- /dev/null +++ b/src/Cake.Common/Tools/VSTest/VSTestSettings.cs @@ -0,0 +1,41 @@ +using Cake.Core.IO; +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.VSTest +{ + /// + /// Contains settings used by . + /// + public sealed class VSTestSettings : ToolSettings + { + /// + /// Gets or sets the settings filename to be used to control additional settings such as data collectors. + /// + public FilePath SettingsFile { get; set; } + + /// + /// Gets or sets a value indicating whether to run tests within the vstest.console.exe process. + /// This makes vstest.console.exe process less likely to be stopped on an error in the tests, but tests might run slower. + /// Defaults to false. + /// + /// + /// true if running in isolation; otherwise, false. + /// + public bool InIsolation { get; set; } + + /// + /// Gets or sets the target platform architecture to be used for test execution. + /// + public VSTestPlatform PlatformArchitecture { get; set; } + + /// + /// Gets or sets the target .NET Framework version to be used for test execution. + /// + public VSTestFrameworkVersion FrameworkVersion { get; set; } + + /// + /// Gets or sets the logger to use for test results. + /// + public VSTestLogger Logger { get; set; } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/WiX/WiXAliases.cs b/src/Cake.Common/Tools/WiX/WiXAliases.cs index 87d4c0a563..65c11df856 100644 --- a/src/Cake.Common/Tools/WiX/WiXAliases.cs +++ b/src/Cake.Common/Tools/WiX/WiXAliases.cs @@ -9,7 +9,14 @@ namespace Cake.Common.Tools.WiX { /// - /// Contains functionality related to running WiX tools. + /// Contains functionality related to WiX. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the appropriate settings class: + /// + /// #tool "nuget:?package=WiX.Toolset" + /// + /// /// [CakeAliasCategory("WiX")] public static class WiXAliases @@ -23,7 +30,7 @@ public static class WiXAliases /// Architecture = Architecture.X64, /// Verbose = true /// }; - /// WiXCandle("./src/*.wxs", settings); + /// WiXCandle("./src/*.wxs", settings); /// /// /// The context. @@ -58,7 +65,7 @@ public static void WiXCandle(this ICakeContext context, string pattern, CandleSe /// Architecture = Architecture.X64, /// Verbose = true /// }; - /// WiXCandle(files, settings); + /// WiXCandle(files, settings); /// /// /// The context. @@ -85,7 +92,7 @@ public static void WiXCandle(this ICakeContext context, IEnumerable so /// LightSettings settings = new LightSettings { /// RawArguments = "-O1 -pedantic -v" /// }; - /// WiXLight("./src/*.wixobj", settings); + /// WiXLight("./src/*.wixobj", settings); /// /// /// The context. @@ -119,7 +126,7 @@ public static void WiXLight(this ICakeContext context, string pattern, LightSett /// LightSettings settings = new LightSettings { /// RawArguments = "-O1 -pedantic -v" /// }; - /// WiXLight(files, settings); + /// WiXLight(files, settings); /// /// /// The context. diff --git a/src/Cake.Common/Tools/XBuild/XBuildAliases.cs b/src/Cake.Common/Tools/XBuild/XBuildAliases.cs index d78977b7dc..be9a059abb 100644 --- a/src/Cake.Common/Tools/XBuild/XBuildAliases.cs +++ b/src/Cake.Common/Tools/XBuild/XBuildAliases.cs @@ -6,7 +6,11 @@ namespace Cake.Common.Tools.XBuild { /// - /// Contains functionality related to XBuild. + /// Contains functionality related to XBuild. + /// + /// In order to use the commands for this alias, XBuild (which is part of Mono) will already have to be installed on the machine the + /// Cake Script is being executed. + /// /// [CakeAliasCategory("XBuild")] public static class XBuildAliases diff --git a/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs b/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs index 42bab36009..e4c083d435 100644 --- a/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs +++ b/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs @@ -9,7 +9,14 @@ namespace Cake.Common.Tools.XUnit { /// - /// Contains functionality related to running xUnit.net tests. + /// Contains functionality related to running xunit tests. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=xunit.runner.console" + /// + /// /// [CakeAliasCategory("xUnit v2")] public static class XUnit2Aliases diff --git a/src/Cake.Common/Tools/XUnit/XUnitAliases.cs b/src/Cake.Common/Tools/XUnit/XUnitAliases.cs index 4987134310..2be32ab08a 100644 --- a/src/Cake.Common/Tools/XUnit/XUnitAliases.cs +++ b/src/Cake.Common/Tools/XUnit/XUnitAliases.cs @@ -8,7 +8,14 @@ namespace Cake.Common.Tools.XUnit { /// - /// Contains functionality related to running xUnit.net tests. + /// Contains functionality related to running xunit tests. + /// + /// In order to use the commands for this alias, include the following in your build.cake file to download and + /// install from NuGet.org, or specify the ToolPath within the class: + /// + /// #tool "nuget:?package=xunit.runners&version=1.9.2" + /// + /// /// [CakeAliasCategory("xUnit")] public static class XUnitAliases diff --git a/src/Cake.Common/Xml/XmlDtdProcessing.cs b/src/Cake.Common/Xml/XmlDtdProcessing.cs new file mode 100644 index 0000000000..ab045a7ddc --- /dev/null +++ b/src/Cake.Common/Xml/XmlDtdProcessing.cs @@ -0,0 +1,25 @@ +namespace Cake.Common.Xml +{ + /// + /// Speficies how will an XmlReader handle DTDs in the XML document. + /// + public enum XmlDtdProcessing + { + /// + /// The XmlReader will throw an exception when it finds a 'DOCTYPE' markup. + /// + Prohibit, + + /// + /// The DTD will be ignored. Any reference to a general entity in the XML document + /// will cause an exception (except for the predefined entities < > & " and '). + /// The DocumentType node will not be reported. + /// + Ignore, + + /// + /// The DTD will be parsed and fully processed (entities expanded, default attributes added etc.) + /// + Parse, + } +} \ No newline at end of file diff --git a/src/Cake.Common/Xml/XmlPeekAliases.cs b/src/Cake.Common/Xml/XmlPeekAliases.cs index cd30e89a0f..5ca488f96e 100644 --- a/src/Cake.Common/Xml/XmlPeekAliases.cs +++ b/src/Cake.Common/Xml/XmlPeekAliases.cs @@ -71,15 +71,20 @@ public static string XmlPeek(this ICakeContext context, FilePath filePath, strin { throw new ArgumentNullException("filePath"); } + + if (settings == null) + { + throw new ArgumentNullException("settings"); + } var file = context.FileSystem.GetFile(filePath); if (!file.Exists) { throw new FileNotFoundException("Source File not found.", file.Path.FullPath); } - + using (var fileStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None)) - using (var xmlReader = XmlReader.Create(fileStream)) + using (var xmlReader = XmlReader.Create(fileStream, GetXmlReaderSettings(settings))) { var xmlValue = XmlPeek(xmlReader, xpath, settings); if (xmlValue == null) @@ -128,5 +133,17 @@ private static string XmlPeek(XmlReader source, string xpath, XmlPeekSettings se return node != null ? node.Value : null; } + + /// + /// Gets a XmlReaderSettings from a XmlPeekSettings + /// + /// The xml reader settings. + /// Additional settings to tweak Xml Peek behavior. + private static XmlReaderSettings GetXmlReaderSettings(XmlPeekSettings settings) + { + var xmlReaderSettings = new XmlReaderSettings(); + xmlReaderSettings.DtdProcessing = (DtdProcessing)settings.DtdProcessing; + return xmlReaderSettings; + } } } \ No newline at end of file diff --git a/src/Cake.Common/Xml/XmlPeekSettings.cs b/src/Cake.Common/Xml/XmlPeekSettings.cs index 59f1af3a1c..30d8bab739 100644 --- a/src/Cake.Common/Xml/XmlPeekSettings.cs +++ b/src/Cake.Common/Xml/XmlPeekSettings.cs @@ -17,6 +17,11 @@ public sealed class XmlPeekSettings /// public bool PreserveWhitespace { get; set; } + /// + /// Gets or sets a value that determines the processing of DTDs. + /// + public XmlDtdProcessing DtdProcessing { get; set; } + /// /// Initializes a new instance of the class. /// @@ -24,6 +29,7 @@ public XmlPeekSettings() { PreserveWhitespace = true; Namespaces = new Dictionary(); + DtdProcessing = XmlDtdProcessing.Prohibit; } } } \ No newline at end of file diff --git a/src/Cake.Common/Xml/XmlPokeAliases.cs b/src/Cake.Common/Xml/XmlPokeAliases.cs index c28a33c828..153f01bc53 100644 --- a/src/Cake.Common/Xml/XmlPokeAliases.cs +++ b/src/Cake.Common/Xml/XmlPokeAliases.cs @@ -225,6 +225,11 @@ public static void XmlPoke(this ICakeContext context, FilePath filePath, string throw new ArgumentNullException("filePath"); } + if (settings == null) + { + throw new ArgumentNullException("settings"); + } + var file = context.FileSystem.GetFile(filePath); if (!file.Exists) { @@ -234,7 +239,7 @@ public static void XmlPoke(this ICakeContext context, FilePath filePath, string using (var memoryStream = new MemoryStream()) { using (var fileStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None)) - using (var xmlReader = XmlReader.Create(fileStream)) + using (var xmlReader = XmlReader.Create(fileStream, GetXmlReaderSettings(settings))) using (var xmlWriter = XmlWriter.Create(memoryStream)) { XmlPoke(xmlReader, xmlWriter, xpath, value, settings); @@ -495,7 +500,7 @@ public static string XmlPokeString(this ICakeContext context, string sourceXml, using (var resultStream = new MemoryStream()) using (var fileReader = new StringReader(sourceXml)) - using (var xmlReader = XmlReader.Create(fileReader)) + using (var xmlReader = XmlReader.Create(fileReader, GetXmlReaderSettings(settings))) using (var xmlWriter = XmlWriter.Create(resultStream)) { XmlPoke(xmlReader, xmlWriter, xpath, value, settings); @@ -571,5 +576,18 @@ private static void XmlPoke(XmlReader source, XmlWriter destination, string xpat document.Save(destination); } + + /// + /// Gets a XmlReaderSettings from a XmlPokeSettings + /// + /// The xml reader settings. + /// Additional settings to tweak Xml Poke behavior. + private static XmlReaderSettings GetXmlReaderSettings(XmlPokeSettings settings) + { + var xmlReaderSettings = new XmlReaderSettings(); + xmlReaderSettings.DtdProcessing = (DtdProcessing)settings.DtdProcessing; + + return xmlReaderSettings; + } } } \ No newline at end of file diff --git a/src/Cake.Common/Xml/XmlPokeSettings.cs b/src/Cake.Common/Xml/XmlPokeSettings.cs index e616024f42..a8c058cb72 100644 --- a/src/Cake.Common/Xml/XmlPokeSettings.cs +++ b/src/Cake.Common/Xml/XmlPokeSettings.cs @@ -23,6 +23,11 @@ public sealed class XmlPokeSettings /// public Encoding Encoding { get; set; } + /// + /// Gets or sets a value that determines the processing of DTDs. + /// + public XmlDtdProcessing DtdProcessing { get; set; } + /// /// Initializes a new instance of the class. /// @@ -31,6 +36,7 @@ public XmlPokeSettings() PreserveWhitespace = true; Namespaces = new Dictionary(); Encoding = Encoding.UTF8; + DtdProcessing = XmlDtdProcessing.Prohibit; } } } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Cake.Core.Tests.csproj b/src/Cake.Core.Tests/Cake.Core.Tests.csproj index 719330522f..0a49891583 100644 --- a/src/Cake.Core.Tests/Cake.Core.Tests.csproj +++ b/src/Cake.Core.Tests/Cake.Core.Tests.csproj @@ -77,6 +77,7 @@ + diff --git a/src/Cake.Core.Tests/Unit/Annotations/CakeModuleAttributeTests.cs b/src/Cake.Core.Tests/Unit/Annotations/CakeModuleAttributeTests.cs new file mode 100644 index 0000000000..4f71691cfb --- /dev/null +++ b/src/Cake.Core.Tests/Unit/Annotations/CakeModuleAttributeTests.cs @@ -0,0 +1,18 @@ +using Cake.Core.Annotations; +using Xunit; + +namespace Cake.Core.Tests.Unit.Annotations +{ + public sealed class CakeModuleAttributeTests + { + [Fact] + public void Should_Throw_If_Module_Type_Is_Null() + { + // Given, When + var result = Record.Exception(() => new CakeModuleAttribute(null)); + + // Then + Assert.IsArgumentNullException(result, "moduleType"); + } + } +} diff --git a/src/Cake.Core.Tests/Unit/Diagnostics/LogExtensionsTests.cs b/src/Cake.Core.Tests/Unit/Diagnostics/LogExtensionsTests.cs index 72241f1d7f..6bdf46fec5 100644 --- a/src/Cake.Core.Tests/Unit/Diagnostics/LogExtensionsTests.cs +++ b/src/Cake.Core.Tests/Unit/Diagnostics/LogExtensionsTests.cs @@ -7,30 +7,17 @@ public class LogExtensionsTests { private sealed class TestLog : ICakeLog { - private Verbosity _verbosity; - private LogLevel _level; - private string _message; + public Verbosity Verbosity { get; set; } - public Verbosity Verbosity - { - get { return _verbosity; } - } + public LogLevel Level { get; private set; } - public LogLevel Level - { - get { return _level; } - } - - public string Message - { - get { return _message; } - } + public string Message { get; private set; } public void Write(Verbosity verbosity, LogLevel level, string format, params object[] args) { - _verbosity = verbosity; - _level = level; - _message = string.Format(format, args); + Verbosity = verbosity; + Level = level; + Message = string.Format(format, args); } } diff --git a/src/Cake.Core/Annotations/CakeModuleAttribute.cs b/src/Cake.Core/Annotations/CakeModuleAttribute.cs new file mode 100644 index 0000000000..48f529916d --- /dev/null +++ b/src/Cake.Core/Annotations/CakeModuleAttribute.cs @@ -0,0 +1,36 @@ +using System; + +namespace Cake.Core.Annotations +{ + /// + /// An attribute used to identify a module implementation in an assembly. + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] + public sealed class CakeModuleAttribute : Attribute + { + private readonly Type _moduleType; + + /// + /// Gets the module type. + /// + /// The module type. + public Type ModuleType + { + get { return _moduleType; } + } + + /// + /// Initializes a new instance of the class. + /// + /// The module type. + public CakeModuleAttribute(Type moduleType) + { + if (moduleType == null) + { + throw new ArgumentNullException("moduleType"); + } + + _moduleType = moduleType; + } + } +} diff --git a/src/Cake.Core/Cake.Core.csproj b/src/Cake.Core/Cake.Core.csproj index e628d318d5..2354c238c6 100644 --- a/src/Cake.Core/Cake.Core.csproj +++ b/src/Cake.Core/Cake.Core.csproj @@ -55,6 +55,10 @@ + + + + @@ -163,6 +167,7 @@ + diff --git a/src/Cake.Core/Composition/ICakeContainerRegistry.cs b/src/Cake.Core/Composition/ICakeContainerRegistry.cs new file mode 100644 index 0000000000..32bf5f4c55 --- /dev/null +++ b/src/Cake.Core/Composition/ICakeContainerRegistry.cs @@ -0,0 +1,29 @@ +namespace Cake.Core.Composition +{ + /// + /// Represents a container registry used to register types and instances with Cake. + /// + public interface ICakeContainerRegistry + { + /// + /// Registers the specified module with the container registry. + /// + /// The module to register. + void RegisterModule(ICakeModule module); + + /// + /// Registers a type with the container registry. + /// + /// The implementation type to register. + /// A registration builder used to configure the registration. + ICakeRegistrationBuilder RegisterType(); + + /// + /// Registers an instance with the container registry. + /// + /// The instance type. + /// The instance to register. + /// A registration builder used to configure the registration. + ICakeRegistrationBuilder RegisterInstance(T instance); + } +} \ No newline at end of file diff --git a/src/Cake.Core/Composition/ICakeModule.cs b/src/Cake.Core/Composition/ICakeModule.cs new file mode 100644 index 0000000000..e6a011d52e --- /dev/null +++ b/src/Cake.Core/Composition/ICakeModule.cs @@ -0,0 +1,15 @@ +namespace Cake.Core.Composition +{ + /// + /// Represents a module responsible for + /// registering types and instances. + /// + public interface ICakeModule + { + /// + /// Performs custom registrations in the provided registry. + /// + /// The container registry. + void Register(ICakeContainerRegistry registry); + } +} diff --git a/src/Cake.Core/Composition/ICakeRegistrationBuilder.cs b/src/Cake.Core/Composition/ICakeRegistrationBuilder.cs new file mode 100644 index 0000000000..de3440a033 --- /dev/null +++ b/src/Cake.Core/Composition/ICakeRegistrationBuilder.cs @@ -0,0 +1,36 @@ +namespace Cake.Core.Composition +{ + /// + /// Represents a registration builder for a specific type. + /// + /// The type to configure. + public interface ICakeRegistrationBuilder + { + /// + /// Adds a registration type to the configuration. + /// + /// The registration type. + /// The same instance so that multiple calls can be chained. + ICakeRegistrationBuilder As(); + + /// + /// Adds a registration type that matches the implementation type. + /// + /// The same instance so that multiple calls can be chained. + ICakeRegistrationBuilder AsSelf(); + + /// + /// Configure the component so that every dependent component + /// gets the same, shared instance. This is the default lifetime scope. + /// + /// The same instance so that multiple calls can be chained. + ICakeRegistrationBuilder Singleton(); + + /// + /// Configure the component so that every dependent component + /// gets a new, unique instance. + /// + /// The same instance so that multiple calls can be chained. + ICakeRegistrationBuilder Transient(); + } +} \ No newline at end of file diff --git a/src/Cake.Core/Diagnostics/ICakeLog.cs b/src/Cake.Core/Diagnostics/ICakeLog.cs index 3a5042f138..5fbdbe95ca 100644 --- a/src/Cake.Core/Diagnostics/ICakeLog.cs +++ b/src/Cake.Core/Diagnostics/ICakeLog.cs @@ -6,10 +6,10 @@ public interface ICakeLog { /// - /// Gets the verbosity. + /// Gets or sets the verbosity. /// /// The verbosity. - Verbosity Verbosity { get; } + Verbosity Verbosity { get; set; } /// /// Writes the text representation of the specified array of objects to the diff --git a/src/Cake.Core/Diagnostics/NullLog.cs b/src/Cake.Core/Diagnostics/NullLog.cs index 53a20b6508..b07d070316 100644 --- a/src/Cake.Core/Diagnostics/NullLog.cs +++ b/src/Cake.Core/Diagnostics/NullLog.cs @@ -6,12 +6,13 @@ public sealed class NullLog : ICakeLog { /// - /// Gets the verbosity. + /// Gets or sets the verbosity. /// /// The verbosity. public Verbosity Verbosity { get { return Verbosity.Quiet; } + set { } } /// diff --git a/src/Cake.Core/Extensions/ProcessArgumentListExtensions.cs b/src/Cake.Core/Extensions/ProcessArgumentListExtensions.cs index 0daae556e8..e1ecf7a06b 100644 --- a/src/Cake.Core/Extensions/ProcessArgumentListExtensions.cs +++ b/src/Cake.Core/Extensions/ProcessArgumentListExtensions.cs @@ -380,5 +380,39 @@ public static ProcessArgumentBuilder AppendQuotedSecret(this ProcessArgumentBuil } return builder; } + + /// + /// Indicates whether a is null or renders empty. + /// + /// The builder. + /// true if refers to a null or empty ; + /// false if the refers to non null or empty + public static bool IsNullOrEmpty(this ProcessArgumentBuilder builder) + { + return builder == null || builder.Count == 0 || string.IsNullOrEmpty(builder.Render()); + } + + /// + /// Copies all the arguments of the source to target . + /// + /// The argument builder to copy from.. + /// The argument builder to copy to. + public static void CopyTo(this ProcessArgumentBuilder source, ProcessArgumentBuilder target) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + + if (target == null) + { + throw new ArgumentNullException("target"); + } + + foreach (var token in source) + { + target.Append(token); + } + } } } diff --git a/src/Cake.Core/IO/ProcessArgumentBuilder.cs b/src/Cake.Core/IO/ProcessArgumentBuilder.cs index 0143045a89..b9b494de94 100644 --- a/src/Cake.Core/IO/ProcessArgumentBuilder.cs +++ b/src/Cake.Core/IO/ProcessArgumentBuilder.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections; +using System.Collections.Generic; using System.Linq; using System.Text; using Cake.Core.IO.Arguments; @@ -8,10 +10,18 @@ namespace Cake.Core.IO /// /// Utility for building process arguments. /// - public sealed class ProcessArgumentBuilder + public sealed class ProcessArgumentBuilder : IReadOnlyCollection { private readonly List _tokens; + /// + /// Gets the number of arguments contained in the . + /// + public int Count + { + get { return _tokens.Count; } + } + /// /// Initializes a new instance of the class. /// @@ -103,5 +113,15 @@ public static ProcessArgumentBuilder FromString(string value) builder.Append(new TextArgument(value)); return builder; } + + IEnumerator IEnumerable.GetEnumerator() + { + return _tokens.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_tokens).GetEnumerator(); + } } } \ No newline at end of file diff --git a/src/Cake.Core/Modules/CoreModule.cs b/src/Cake.Core/Modules/CoreModule.cs new file mode 100644 index 0000000000..9d01dd102b --- /dev/null +++ b/src/Cake.Core/Modules/CoreModule.cs @@ -0,0 +1,46 @@ +using Cake.Core.Composition; +using Cake.Core.IO; +using Cake.Core.IO.NuGet; +using Cake.Core.Scripting; +using Cake.Core.Scripting.Analysis; +using Cake.Core.Tooling; + +namespace Cake.Core.Modules +{ + /// + /// The module responsible for registering + /// default types in the Cake.Core assembly. + /// + public sealed class CoreModule : ICakeModule + { + /// + /// Performs custom registrations in the provided registry. + /// + /// The container registry. + public void Register(ICakeContainerRegistry registry) + { + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + + // IO + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + + // Tooling + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + + // Scripting + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + } + } +} diff --git a/src/Cake.Core/Properties/Namespaces.cs b/src/Cake.Core/Properties/Namespaces.cs index 87eaccd586..8daf09d280 100644 --- a/src/Cake.Core/Properties/Namespaces.cs +++ b/src/Cake.Core/Properties/Namespaces.cs @@ -119,12 +119,26 @@ internal class NamespaceDoc } } +// ReSharper disable once CheckNamespace +namespace Cake.Core.Tooling +{ + /// + /// This namespace contain base classes + /// and functionality related to tooling. + /// + [CompilerGenerated] + internal class NamespaceDoc + { + } +} + // ReSharper disable once CheckNamespace namespace Cake.Core.Utilities { /// /// This namespace contain base classes /// and functionality related to tooling. + /// The content in this namespace has been obsoleted. /// [CompilerGenerated] internal class NamespaceDoc diff --git a/src/Cake.Core/Tooling/Tool.cs b/src/Cake.Core/Tooling/Tool.cs index 2d4355d65d..af6cce8907 100644 --- a/src/Cake.Core/Tooling/Tool.cs +++ b/src/Cake.Core/Tooling/Tool.cs @@ -26,7 +26,7 @@ public abstract class Tool where TSettings : ToolSettings /// The environment. /// The process runner. /// The globber. - [Obsolete("Please use Tool(IFileSystem, ICakeEnvironment, IProcessRunner, IToolService) instead.")] + [Obsolete("Please use Tool(IFileSystem, ICakeEnvironment, IProcessRunner, IToolLocator) instead.")] protected Tool(IFileSystem fileSystem, ICakeEnvironment environment, IProcessRunner processRunner, IGlobber globber) : this(fileSystem, environment, processRunner, (IToolLocator)null) { diff --git a/src/Cake.Core/Tooling/ToolRepository.cs b/src/Cake.Core/Tooling/ToolRepository.cs index 06ba01d870..274656ad00 100644 --- a/src/Cake.Core/Tooling/ToolRepository.cs +++ b/src/Cake.Core/Tooling/ToolRepository.cs @@ -31,6 +31,11 @@ public ToolRepository(ICakeEnvironment environment) /// The path to register. public void Register(FilePath path) { + if (path == null) + { + throw new ArgumentNullException("path"); + } + path = path.MakeAbsolute(_environment); var filename = path.GetFilename(); diff --git a/src/Cake.NuGet/Cake.NuGet.csproj b/src/Cake.NuGet/Cake.NuGet.csproj index da131358a4..d58d74c803 100644 --- a/src/Cake.NuGet/Cake.NuGet.csproj +++ b/src/Cake.NuGet/Cake.NuGet.csproj @@ -68,6 +68,7 @@ + @@ -87,8 +88,7 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. diff --git a/src/Cake.NuGet/NuGetModule.cs b/src/Cake.NuGet/NuGetModule.cs new file mode 100644 index 0000000000..ef1afa37e2 --- /dev/null +++ b/src/Cake.NuGet/NuGetModule.cs @@ -0,0 +1,30 @@ +using Cake.Core.Composition; +using Cake.Core.Packaging; + +namespace Cake.NuGet +{ + /// + /// The module responsible for registering + /// default types in the Cake.NuGet assembly. + /// + public sealed class NuGetModule : ICakeModule + { + /// + /// Performs custom registrations in the provided registry. + /// + /// The container registry. + public void Register(ICakeContainerRegistry registry) + { + // NuGet addins support + registry.RegisterType().As().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + + // URI resource support. + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + } + } +} diff --git a/src/Cake.Testing/FakeLog.cs b/src/Cake.Testing/FakeLog.cs index 4d38a62c6d..c60d876542 100644 --- a/src/Cake.Testing/FakeLog.cs +++ b/src/Cake.Testing/FakeLog.cs @@ -9,6 +9,7 @@ namespace Cake.Testing public sealed class FakeLog : ICakeLog { private readonly List _entries; + private Verbosity _verbosity; /// /// Gets the messages. @@ -25,15 +26,17 @@ public IReadOnlyList Entries public FakeLog() { _entries = new List(); + _verbosity = Verbosity.Quiet; } /// - /// Gets the verbosity. + /// Gets or sets the verbosity. /// /// The verbosity. public Verbosity Verbosity { - get { return Verbosity.Quiet; } + get { return _verbosity; } + set { _verbosity = value; } } /// diff --git a/src/Cake.Tests/Cake.Tests.csproj b/src/Cake.Tests/Cake.Tests.csproj index 972d59b8f2..66bbb94831 100644 --- a/src/Cake.Tests/Cake.Tests.csproj +++ b/src/Cake.Tests/Cake.Tests.csproj @@ -72,6 +72,8 @@ + + Code diff --git a/src/Cake.Tests/Fixtures/CakeApplicationFixture.cs b/src/Cake.Tests/Fixtures/CakeApplicationFixture.cs index dee5b39fc9..25094da8ef 100644 --- a/src/Cake.Tests/Fixtures/CakeApplicationFixture.cs +++ b/src/Cake.Tests/Fixtures/CakeApplicationFixture.cs @@ -1,13 +1,11 @@ using Cake.Commands; using Cake.Core.Diagnostics; -using Cake.Diagnostics; using NSubstitute; namespace Cake.Tests.Fixtures { internal sealed class CakeApplicationFixture { - public IVerbosityAwareLog Log { get; set; } public ICommandFactory CommandFactory { get; set; } public CakeOptions Options { get; set; } @@ -17,13 +15,12 @@ public CakeApplicationFixture() Options = new CakeOptions(); Options.Verbosity = Verbosity.Diagnostic; - Log = Substitute.For(); CommandFactory = Substitute.For(); } public CakeApplication CreateApplication() { - return new CakeApplication(Log, CommandFactory); + return new CakeApplication(CommandFactory); } public int RunApplication() diff --git a/src/Cake.Tests/Unit/Arguments/ArgumentParserTests.cs b/src/Cake.Tests/Unit/Arguments/ArgumentParserTests.cs index 52628ad762..8306ce907a 100644 --- a/src/Cake.Tests/Unit/Arguments/ArgumentParserTests.cs +++ b/src/Cake.Tests/Unit/Arguments/ArgumentParserTests.cs @@ -218,9 +218,13 @@ public void Can_Parse_Script(string input) } [Theory] - [InlineData("-showdescription")] - [InlineData("-s")] - public void Can_Parse_ShowDescription(string input) + [InlineData("-showdescription", true)] + [InlineData("-showdescription=true", true)] + [InlineData("-showdescription=false", false)] + [InlineData("-s", true)] + [InlineData("-s=true", true)] + [InlineData("-s=false", false)] + public void Can_Parse_ShowDescription(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -230,14 +234,20 @@ public void Can_Parse_ShowDescription(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.ShowDescription); + Assert.Equal(expected, result.ShowDescription); } [Theory] - [InlineData("-dryrun")] - [InlineData("-noop")] - [InlineData("-whatif")] - public void Can_Parse_DryRun(string input) + [InlineData("-dryrun", true)] + [InlineData("-dryrun=true", true)] + [InlineData("-dryrun=false", false)] + [InlineData("-noop", true)] + [InlineData("-noop=true", true)] + [InlineData("-noop=false", false)] + [InlineData("-whatif", true)] + [InlineData("-whatif=true", true)] + [InlineData("-whatif=false", false)] + public void Can_Parse_DryRun(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -247,13 +257,15 @@ public void Can_Parse_DryRun(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.PerformDryRun); + Assert.Equal(expected, result.PerformDryRun); } [Theory] - [InlineData("-help")] - [InlineData("-?")] - public void Can_Parse_Help(string input) + [InlineData("-help", true)] + [InlineData("-help=true", true)] + [InlineData("-help=false", false)] + [InlineData("-?", true)] + public void Can_Parse_Help(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -263,13 +275,17 @@ public void Can_Parse_Help(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.ShowHelp); + Assert.Equal(expected, result.ShowHelp); } [Theory] - [InlineData("-version")] - [InlineData("-ver")] - public void Can_Parse_Version(string input) + [InlineData("-version", true)] + [InlineData("-version=true", true)] + [InlineData("-version=false", false)] + [InlineData("-ver", true)] + [InlineData("-ver=true", true)] + [InlineData("-ver=false", false)] + public void Can_Parse_Version(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -279,13 +295,17 @@ public void Can_Parse_Version(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.ShowVersion); + Assert.Equal(expected, result.ShowVersion); } [Theory] - [InlineData("-debug")] - [InlineData("-d")] - public void Can_Parse_Debug(string input) + [InlineData("-debug", true)] + [InlineData("-debug=true", true)] + [InlineData("-debug=false", false)] + [InlineData("-d", true)] + [InlineData("-d=true", true)] + [InlineData("-d=false", false)] + public void Can_Parse_Debug(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -295,7 +315,7 @@ public void Can_Parse_Debug(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.PerformDebug); + Assert.Equal(expected, result.PerformDebug); } } @@ -364,11 +384,6 @@ public void Should_Return_Error_If_Multiple_Arguments_With_The_Same_Name_Exist() [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)] public void Can_Parse_Verbosity(string input, Verbosity value) { // Given @@ -385,8 +400,6 @@ public void Can_Parse_Verbosity(string input, Verbosity value) [Theory] [InlineData("--verbosity=lol", "The value 'lol' is not a valid verbosity.")] [InlineData("--verbosity=", "The value '' is not a valid verbosity.")] - [InlineData("-v=lol", "The value 'lol' is not a valid verbosity.")] - [InlineData("-v=", "The value '' is not a valid verbosity.")] public void Should_Throw_If_Parsing_Invalid_Verbosity(string verbosity, string expected) { // Given @@ -420,9 +433,10 @@ public void Can_Parse_Script(string input) } [Theory] - [InlineData("--showdescription")] - [InlineData("-s")] - public void Can_Parse_ShowDescription(string input) + [InlineData("--showdescription", true)] + [InlineData("--showdescription=true", true)] + [InlineData("--showdescription=false", false)] + public void Can_Parse_ShowDescription(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -432,14 +446,20 @@ public void Can_Parse_ShowDescription(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.ShowDescription); + Assert.Equal(expected, result.ShowDescription); } [Theory] - [InlineData("--dryrun")] - [InlineData("--noop")] - [InlineData("--whatif")] - public void Can_Parse_DryRun(string input) + [InlineData("--dryrun", true)] + [InlineData("--dryrun=true", true)] + [InlineData("--dryrun=false", false)] + [InlineData("--noop", true)] + [InlineData("--noop=true", true)] + [InlineData("--noop=false", false)] + [InlineData("--whatif", true)] + [InlineData("--whatif=true", true)] + [InlineData("--whatif=false", false)] + public void Can_Parse_DryRun(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -449,13 +469,14 @@ public void Can_Parse_DryRun(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.PerformDryRun); + Assert.Equal(expected, result.PerformDryRun); } [Theory] - [InlineData("--help")] - [InlineData("-?")] - public void Can_Parse_Help(string input) + [InlineData("--help", true)] + [InlineData("--help=true", true)] + [InlineData("--help=false", false)] + public void Can_Parse_Help(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -465,13 +486,17 @@ public void Can_Parse_Help(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.ShowHelp); + Assert.Equal(expected, result.ShowHelp); } [Theory] - [InlineData("--version")] - [InlineData("--ver")] - public void Can_Parse_Version(string input) + [InlineData("--version", true)] + [InlineData("--version=true", true)] + [InlineData("--version=false", false)] + [InlineData("--ver", true)] + [InlineData("--ver=true", true)] + [InlineData("--ver=false", false)] + public void Can_Parse_Version(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -481,13 +506,14 @@ public void Can_Parse_Version(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.ShowVersion); + Assert.Equal(expected, result.ShowVersion); } [Theory] - [InlineData("--debug")] - [InlineData("-d")] - public void Can_Parse_Debug(string input) + [InlineData("--debug", true)] + [InlineData("--debug=true", true)] + [InlineData("--debug=false", false)] + public void Can_Parse_Debug(string input, bool expected) { // Given var fixture = new ArgumentParserFixture(); @@ -497,7 +523,7 @@ public void Can_Parse_Debug(string input) var result = parser.Parse(new[] { "build.csx", input }); // Then - Assert.Equal(true, result.PerformDebug); + Assert.Equal(expected, result.PerformDebug); } } } diff --git a/src/Cake.Tests/Unit/Arguments/ArgumentTokenizerTests.cs b/src/Cake.Tests/Unit/Arguments/ArgumentTokenizerTests.cs index 58447dfa63..c9240251d4 100644 --- a/src/Cake.Tests/Unit/Arguments/ArgumentTokenizerTests.cs +++ b/src/Cake.Tests/Unit/Arguments/ArgumentTokenizerTests.cs @@ -81,6 +81,22 @@ public void Should_Parse_Multiple_Mixed_Arguments() Assert.Equal("-verbosity", result[2]); Assert.Equal("\"diagnostic\"", result[3]); } + + [Fact] + public void Should_Parse_Part_That_Contains_Quotes_With_Space_In_It() + { + // Given + const string input = @"cake.exe build.cake -target=""te st"""; + + // When + var result = ArgumentTokenizer.Tokenize(input).ToArray(); + + // Then + Assert.Equal(3, result.Length); + Assert.Equal("cake.exe", result[0]); + Assert.Equal("build.cake", result[1]); + Assert.Equal("-target=\"te st\"", result[2]); + } } } } \ No newline at end of file diff --git a/src/Cake.Tests/Unit/CakeApplicationTests.cs b/src/Cake.Tests/Unit/CakeApplicationTests.cs index 72e069c623..2c0c7b59d9 100644 --- a/src/Cake.Tests/Unit/CakeApplicationTests.cs +++ b/src/Cake.Tests/Unit/CakeApplicationTests.cs @@ -10,20 +10,6 @@ public sealed class CakeApplicationTests { public sealed class TheConstructor { - [Fact] - public void Should_Throw_If_Log_Is_Null() - { - // Given - var fixture = new CakeApplicationFixture(); - fixture.Log = null; - - // When - var result = Record.Exception(() => fixture.CreateApplication()); - - // Then - Assert.IsArgumentNullException(result, "log"); - } - [Fact] public void Should_Throw_If_Command_Factory_Is_Null() { @@ -55,19 +41,6 @@ public void Should_Throw_If_Options_Are_Null() Assert.IsArgumentNullException(result, "options"); } - [Fact] - public void Should_Set_Verbosity_If_Options_Are_Not_Null() - { - // Given - var fixture = new CakeApplicationFixture(); - - // When - fixture.RunApplication(); - - // Then - fixture.Log.Received(1).SetVerbosity(Verbosity.Diagnostic); - } - [Fact] public void Should_Return_Success_If_No_Exception_Was_Thrown() { diff --git a/src/Cake.Tests/Unit/CakeContainerBuilderTests.cs b/src/Cake.Tests/Unit/CakeContainerBuilderTests.cs new file mode 100644 index 0000000000..3685f072b0 --- /dev/null +++ b/src/Cake.Tests/Unit/CakeContainerBuilderTests.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using System.Linq; +using Autofac; +using Cake.Core; +using Cake.Testing; +using Xunit; + +namespace Cake.Tests.Unit +{ + public sealed class CakeContainerBuilderTests + { + public sealed class TheBuildMethod + { + [Fact] + public void Should_Resolve_Last_Registration_Of_Type_When_Requesting_Single_Registration() + { + // Given + var builder = new CakeContainerBuilder(); + builder.Registry.RegisterType().As().Singleton(); + builder.Registry.RegisterType().As().Singleton(); + var container = builder.Build(); + + // When + var result = container.Resolve(); + + // Then + Assert.IsType(result); + } + + [Fact] + public void Should_Resolve_Last_Registration_Of_Type_When_Requesting_Enumerable_Of_Registration() + { + // Given + var builder = new CakeContainerBuilder(); + builder.Registry.RegisterType().As().Singleton(); + builder.Registry.RegisterType().As().Singleton(); + var container = builder.Build(); + + // When + var result = container.Resolve>().ToList(); + + // Then + Assert.Equal(2, result.Count); + Assert.True(result.Any(instance => instance is CakeConsole)); + Assert.True(result.Any(instance => instance is FakeConsole)); + } + + [Fact] + public void Should_Resolve_The_Same_Instance_When_Resolving_Type_Registered_As_Singleton_Twice() + { + // Given + var builder = new CakeContainerBuilder(); + builder.Registry.RegisterType().Singleton(); + var container = builder.Build(); + + // When + var first = container.Resolve(); + var second = container.Resolve(); + + // Then + Assert.Same(first, second); + } + + [Fact] + public void Should_Resolve_Different_Instances_When_Resolving_Type_Registered_As_Transient_Twice() + { + // Given + var builder = new CakeContainerBuilder(); + builder.Registry.RegisterType().Transient(); + var container = builder.Build(); + + // When + var first = container.Resolve(); + var second = container.Resolve(); + + // Then + Assert.NotSame(first, second); + } + } + } +} diff --git a/src/Cake.Tests/Unit/Composition/ContainerRegistrationBuilderTests.cs b/src/Cake.Tests/Unit/Composition/ContainerRegistrationBuilderTests.cs new file mode 100644 index 0000000000..55936a68f8 --- /dev/null +++ b/src/Cake.Tests/Unit/Composition/ContainerRegistrationBuilderTests.cs @@ -0,0 +1,81 @@ +using System.Linq; +using Cake.Composition; +using Cake.Core.Diagnostics; +using Cake.Diagnostics; +using Xunit; + +namespace Cake.Tests.Unit.Composition +{ + public sealed class ContainerRegistrationBuilderTests + { + public sealed class TheAsMethod + { + [Fact] + public void Should_Add_Registration_Type() + { + // Given + var registration = new ContainerRegistration(typeof(CakeBuildLog)); + var builder = new ContainerRegistrationBuilder(registration); + + // When + builder.As(); + + // Then + Assert.Equal(1, registration.RegistrationTypes.Count); + Assert.Equal(typeof(ICakeLog), registration.RegistrationTypes.First()); + } + } + + public sealed class TheAsSelfMethod + { + [Fact] + public void Should_Add_Registration_Type() + { + // Given + var registration = new ContainerRegistration(typeof(CakeBuildLog)); + var builder = new ContainerRegistrationBuilder(registration); + + // When + builder.AsSelf(); + + // Then + Assert.Equal(1, registration.RegistrationTypes.Count); + Assert.Equal(typeof(CakeBuildLog), registration.RegistrationTypes.First()); + } + } + + public sealed class TheSingletonMethod + { + [Fact] + public void Should_Set_Lifetime() + { + // Given + var registration = new ContainerRegistration(typeof(CakeBuildLog)); + var builder = new ContainerRegistrationBuilder(registration); + + // When + builder.Singleton(); + + // Then + Assert.True(registration.IsSingleton); + } + } + + public sealed class TheTransientMethod + { + [Fact] + public void Should_Set_Lifetime() + { + // Given + var registration = new ContainerRegistration(typeof(CakeBuildLog)); + var builder = new ContainerRegistrationBuilder(registration); + + // When + builder.Transient(); + + // Then + Assert.False(registration.IsSingleton); + } + } + } +} diff --git a/src/Cake.Tests/Unit/Composition/ContainerRegistryTests.cs b/src/Cake.Tests/Unit/Composition/ContainerRegistryTests.cs new file mode 100644 index 0000000000..fcb3f9fcbc --- /dev/null +++ b/src/Cake.Tests/Unit/Composition/ContainerRegistryTests.cs @@ -0,0 +1,67 @@ +using Cake.Composition; +using Cake.Core.Composition; +using NSubstitute; +using Xunit; + +namespace Cake.Tests.Unit.Composition +{ + public sealed class ContainerRegistryTests + { + public sealed class TheRegisterModuleMethod + { + [Fact] + public void Should_Call_The_Modules_Register_Method() + { + // Given + var module = Substitute.For(); + var registry = new ContainerRegistry(); + + // When + registry.RegisterModule(module); + + // Then + module.Received(1).Register( + Arg.Is(registry)); + } + } + + public sealed class TheRegisterTypeMethod + { + [Fact] + public void Should_Create_Type_Registration_As_Singleton_By_Default() + { + // Given + var registry = new ContainerRegistry(); + + // When + registry.RegisterType(); + + // Then + Assert.Equal(1, registry.Registrations.Count); + Assert.Equal(typeof(CakeConsole), registry.Registrations[0].ImplementationType); + Assert.Null(registry.Registrations[0].Instance); + Assert.True(registry.Registrations[0].IsSingleton); + } + } + + public sealed class TheRegisterInstanceMethod + { + [Fact] + public void Should_Create_Instance_Registration_As_Singleton_By_Default() + { + // Given + var registry = new ContainerRegistry(); + var instance = new CakeConsole(); + + // When + registry.RegisterInstance(instance); + + // Then + Assert.Equal(1, registry.Registrations.Count); + Assert.Equal(typeof(CakeConsole), registry.Registrations[0].ImplementationType); + Assert.Equal(instance, registry.Registrations[0].Instance); + Assert.True(registry.Registrations[0].IsSingleton); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Tests/packages.config b/src/Cake.Tests/packages.config index cf262fec70..18da215da3 100644 --- a/src/Cake.Tests/packages.config +++ b/src/Cake.Tests/packages.config @@ -1,5 +1,6 @@  + diff --git a/src/Cake.sln.DotSettings b/src/Cake.sln.DotSettings index 01148905a7..4815547c78 100644 --- a/src/Cake.sln.DotSettings +++ b/src/Cake.sln.DotSettings @@ -2,6 +2,7 @@ ERROR DO_NOT_SHOW ERROR + DO_NOT_SHOW DO_NOT_SHOW DO_NOT_SHOW ERROR diff --git a/src/Cake/Arguments/ArgumentParser.cs b/src/Cake/Arguments/ArgumentParser.cs index 5c05a64cb0..174f18680a 100644 --- a/src/Cake/Arguments/ArgumentParser.cs +++ b/src/Cake/Arguments/ArgumentParser.cs @@ -114,15 +114,7 @@ private bool ParseOption(string arg, CakeOptions options) value = arg.Substring(separatorIndex + 1); } - if (value.Length > 2) - { - if (value[0] == '\"' && value[value.Length - 1] == '\"') - { - value = value.Substring(1, value.Length - 2); - } - } - - return ParseOption(name, value, options); + return ParseOption(name, value.UnQuote(), options); } private bool ParseOption(string name, string value, CakeOptions options) @@ -142,32 +134,32 @@ private bool ParseOption(string name, string value, CakeOptions options) if (name.Equals("showdescription", StringComparison.OrdinalIgnoreCase) || name.Equals("s", StringComparison.OrdinalIgnoreCase)) { - options.ShowDescription = true; + options.ShowDescription = ParseBooleanValue(value); } if (name.Equals("dryrun", StringComparison.OrdinalIgnoreCase) || name.Equals("noop", StringComparison.OrdinalIgnoreCase) || name.Equals("whatif", StringComparison.OrdinalIgnoreCase)) { - options.PerformDryRun = true; + options.PerformDryRun = ParseBooleanValue(value); } if (name.Equals("help", StringComparison.OrdinalIgnoreCase) || name.Equals("?", StringComparison.OrdinalIgnoreCase)) { - options.ShowHelp = true; + options.ShowHelp = ParseBooleanValue(value); } if (name.Equals("version", StringComparison.OrdinalIgnoreCase) || name.Equals("ver", StringComparison.OrdinalIgnoreCase)) { - options.ShowVersion = true; + options.ShowVersion = ParseBooleanValue(value); } if (name.Equals("debug", StringComparison.OrdinalIgnoreCase) || name.Equals("d", StringComparison.OrdinalIgnoreCase)) { - options.PerformDebug = true; + options.PerformDebug = ParseBooleanValue(value); } if (options.Arguments.ContainsKey(name)) @@ -179,5 +171,23 @@ private bool ParseOption(string name, string value, CakeOptions options) options.Arguments.Add(name, value); return true; } + + private static bool ParseBooleanValue(string value) + { + value = (value ?? string.Empty).UnQuote(); + if (string.IsNullOrWhiteSpace(value)) + { + return true; + } + if (value.Equals("true", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (value.Equals("false", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + throw new InvalidOperationException("Argument value is not a valid boolean value."); + } } } \ No newline at end of file diff --git a/src/Cake/Arguments/ArgumentTokenizer.cs b/src/Cake/Arguments/ArgumentTokenizer.cs index 850f2d9ca8..3018fa6bfd 100644 --- a/src/Cake/Arguments/ArgumentTokenizer.cs +++ b/src/Cake/Arguments/ArgumentTokenizer.cs @@ -55,11 +55,18 @@ private static string Read(StringReader reader) accumulator.Append((char)reader.Read()); while (reader.Peek() != -1) { - if ((char)reader.Peek() == ' ') + if ((char)reader.Peek() == '\"') + { + accumulator.Append(ReadQuote(reader)); + } + else if ((char)reader.Peek() == ' ') { break; } - accumulator.Append((char)reader.Read()); + else + { + accumulator.Append((char)reader.Read()); + } } return accumulator.ToString(); } diff --git a/src/Cake/Autofac/ArgumentsModule.cs b/src/Cake/Autofac/ArgumentsModule.cs deleted file mode 100644 index 891ff625d4..0000000000 --- a/src/Cake/Autofac/ArgumentsModule.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Autofac; -using Cake.Core; - -namespace Cake.Autofac -{ - internal sealed class ArgumentsModule : Module - { - private readonly CakeOptions _options; - - public ArgumentsModule(CakeOptions options) - { - _options = options; - } - - protected override void Load(ContainerBuilder builder) - { - builder.RegisterInstance(_options).As(); - builder.RegisterType().As().SingleInstance(); - } - } -} diff --git a/src/Cake/Autofac/CakeModule.cs b/src/Cake/Autofac/CakeModule.cs index 4fca457b48..387032a64b 100644 --- a/src/Cake/Autofac/CakeModule.cs +++ b/src/Cake/Autofac/CakeModule.cs @@ -60,7 +60,7 @@ protected override void Load(ContainerBuilder builder) builder.RegisterType().As().SingleInstance(); builder.RegisterType().SingleInstance(); builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); builder.RegisterType().SingleInstance(); builder.RegisterType().As().SingleInstance(); diff --git a/src/Cake/Cake.csproj b/src/Cake/Cake.csproj index f60e7dae1c..853d7f799e 100644 --- a/src/Cake/Cake.csproj +++ b/src/Cake/Cake.csproj @@ -123,9 +123,15 @@ Code - - - + + + + + + + + + Code @@ -154,7 +160,6 @@ - @@ -191,7 +196,7 @@ - + @@ -229,6 +234,7 @@ false + diff --git a/src/Cake/CakeApplication.cs b/src/Cake/CakeApplication.cs index be6f08ce6a..05ab4291d0 100644 --- a/src/Cake/CakeApplication.cs +++ b/src/Cake/CakeApplication.cs @@ -9,28 +9,20 @@ namespace Cake /// internal sealed class CakeApplication { - private readonly IVerbosityAwareLog _log; private readonly ICommandFactory _commandFactory; /// /// Initializes a new instance of the class. /// - /// The log. /// The command factory. public CakeApplication( - IVerbosityAwareLog log, ICommandFactory commandFactory) { - if (log == null) - { - throw new ArgumentNullException("log"); - } if (commandFactory == null) { throw new ArgumentNullException("commandFactory"); } - _log = log; _commandFactory = commandFactory; } @@ -46,9 +38,6 @@ public int Run(CakeOptions options) throw new ArgumentNullException("options"); } - // Set verbosity. - _log.SetVerbosity(options.Verbosity); - // Create the correct command and execute it. var command = CreateCommand(options); var result = command.Execute(options); diff --git a/src/Cake/CakeContainerBuilder.cs b/src/Cake/CakeContainerBuilder.cs new file mode 100644 index 0000000000..6cd7c42e05 --- /dev/null +++ b/src/Cake/CakeContainerBuilder.cs @@ -0,0 +1,88 @@ +using Autofac; +using Autofac.Builder; +using Cake.Composition; +using Cake.Core.Composition; + +namespace Cake +{ + internal sealed class CakeContainerBuilder + { + private readonly ContainerRegistry _registry; + + public ICakeContainerRegistry Registry + { + get { return _registry; } + } + + public CakeContainerBuilder() + { + _registry = new ContainerRegistry(); + } + + public IContainer Build() + { + var builder = new ContainerBuilder(); + AddRegistrations(builder); + return builder.Build(); + } + + public void Update(IContainer container) + { + var builder = new ContainerBuilder(); + AddRegistrations(builder); + builder.Update(container); + } + + private void AddRegistrations(ContainerBuilder builder) + { + foreach (var registration in _registry.Registrations) + { + if (registration.Instance != null) + { + // Register instance. + var result = builder.RegisterInstance(registration.Instance); + SetRegistrationTypes(result, registration); + SetLifetime(result, registration); + } + else + { + // Register type. + var result = builder.RegisterType(registration.ImplementationType); + SetRegistrationTypes(result, registration); + SetLifetime(result, registration); + } + } + } + + private static void SetRegistrationTypes( + IRegistrationBuilder builder, + ContainerRegistration registration) + { + if (registration.RegistrationTypes.Count > 0) + { + foreach (var type in registration.RegistrationTypes) + { + builder.As(type); + } + } + else + { + builder.As(registration.ImplementationType); + } + } + + private static void SetLifetime( + IRegistrationBuilder builder, + ContainerRegistration registration) + { + if (registration.IsSingleton) + { + builder.SingleInstance(); + } + else + { + builder.InstancePerDependency(); + } + } + } +} diff --git a/src/Cake/Composition/ContainerRegistration.cs b/src/Cake/Composition/ContainerRegistration.cs new file mode 100644 index 0000000000..e9d0ff400f --- /dev/null +++ b/src/Cake/Composition/ContainerRegistration.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; + +namespace Cake.Composition +{ + internal sealed class ContainerRegistration + { + private readonly Type _implementationType; + private readonly List _registrationTypes; + private readonly object _instance; + private bool _isSingleton; + + public Type ImplementationType + { + get { return _implementationType; } + } + + public ICollection RegistrationTypes + { + get { return _registrationTypes; } + } + + public object Instance + { + get { return _instance; } + } + + public bool IsSingleton + { + get { return _isSingleton; } + internal set { _isSingleton = value; } + } + + public ContainerRegistration(Type implementationType, object instance = null) + { + _implementationType = implementationType; + _registrationTypes = new List(); + _instance = instance; + _isSingleton = true; + } + } +} diff --git a/src/Cake/Composition/ContainerRegistrationBuilder.cs b/src/Cake/Composition/ContainerRegistrationBuilder.cs new file mode 100644 index 0000000000..54f2931977 --- /dev/null +++ b/src/Cake/Composition/ContainerRegistrationBuilder.cs @@ -0,0 +1,43 @@ +using Cake.Core.Composition; + +namespace Cake.Composition +{ + internal sealed class ContainerRegistrationBuilder : ICakeRegistrationBuilder + { + private readonly ContainerRegistration _registration; + + public ContainerRegistration Registration + { + get { return _registration; } + } + + public ContainerRegistrationBuilder(ContainerRegistration registration) + { + _registration = registration; + } + + public ICakeRegistrationBuilder As() + { + _registration.RegistrationTypes.Add(typeof(TRegistrationType)); + return this; + } + + public ICakeRegistrationBuilder AsSelf() + { + _registration.RegistrationTypes.Add(typeof(T)); + return this; + } + + public ICakeRegistrationBuilder Singleton() + { + _registration.IsSingleton = true; + return this; + } + + public ICakeRegistrationBuilder Transient() + { + _registration.IsSingleton = false; + return this; + } + } +} diff --git a/src/Cake/Composition/ContainerRegistry.cs b/src/Cake/Composition/ContainerRegistry.cs new file mode 100644 index 0000000000..05935e1846 --- /dev/null +++ b/src/Cake/Composition/ContainerRegistry.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using Cake.Core.Composition; + +namespace Cake.Composition +{ + internal sealed class ContainerRegistry : ICakeContainerRegistry + { + private readonly List _registrations; + + public IReadOnlyList Registrations + { + get { return _registrations; } + } + + public ContainerRegistry() + { + _registrations = new List(); + } + + public void RegisterModule(ICakeModule module) + { + module.Register(this); + } + + public ICakeRegistrationBuilder RegisterType() + { + var registration = new ContainerRegistration(typeof(TImplementationType)); + _registrations.Add(registration); + return new ContainerRegistrationBuilder(registration); + } + + public ICakeRegistrationBuilder RegisterInstance(TImplementationType instance) + { + var registration = new ContainerRegistration(typeof(TImplementationType), instance); + _registrations.Add(registration); + return new ContainerRegistrationBuilder(registration); + } + } +} \ No newline at end of file diff --git a/src/Cake/Composition/ModuleLoader.cs b/src/Cake/Composition/ModuleLoader.cs new file mode 100644 index 0000000000..ab25d0286a --- /dev/null +++ b/src/Cake/Composition/ModuleLoader.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Autofac; +using Cake.Core.Composition; +using Cake.Core.Configuration; +using Cake.Core.Diagnostics; +using Cake.Core.IO; + +namespace Cake.Composition +{ + internal sealed class ModuleLoader + { + private readonly ModuleSearcher _searcher; + private readonly ICakeLog _log; + private readonly ICakeConfiguration _configuration; + + public ModuleLoader(ModuleSearcher searcher, ICakeLog log, ICakeConfiguration configuration) + { + _searcher = searcher; + _log = log; + _configuration = configuration; + } + + public void LoadModules(IContainer container, CakeOptions options) + { + var root = GetModulePath(options); + var moduleTypes = _searcher.Search(root); + if (moduleTypes.Count > 0) + { + using (var temporaryContainer = container.BeginLifetimeScope()) + { + // Register modules in the temporary container. + RegisterExternalModules(moduleTypes, temporaryContainer); + + // Now let the modules register their types. + var builder = new CakeContainerBuilder(); + foreach (var module in temporaryContainer.Resolve>()) + { + builder.Registry.RegisterModule(module); + } + builder.Update(container); + } + } + } + + private DirectoryPath GetModulePath(CakeOptions options) + { + var root = _configuration.GetValue(Constants.Paths.Modules); + if (string.IsNullOrWhiteSpace(root)) + { + return options.Script.GetDirectory().Combine("tools/modules"); + } + return new DirectoryPath(root); + } + + private void RegisterExternalModules(IEnumerable moduleTypes, ILifetimeScope scope) + { + var builder = new ContainerBuilder(); + foreach (var moduleType in moduleTypes) + { + _log.Debug("Registering module {0}...", moduleType.FullName); + builder.RegisterType(moduleType).As().SingleInstance(); + } + builder.Update(scope.ComponentRegistry); + } + } +} diff --git a/src/Cake/Composition/ModuleSearcher.cs b/src/Cake/Composition/ModuleSearcher.cs new file mode 100644 index 0000000000..f4cd739525 --- /dev/null +++ b/src/Cake/Composition/ModuleSearcher.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Cake.Core; +using Cake.Core.Annotations; +using Cake.Core.Composition; +using Cake.Core.Diagnostics; +using Cake.Core.IO; + +namespace Cake.Composition +{ + internal sealed class ModuleSearcher + { + private readonly IFileSystem _fileSystem; + private readonly ICakeEnvironment _environment; + private readonly ICakeLog _log; + + public ModuleSearcher(IFileSystem fileSystem, ICakeEnvironment environment, ICakeLog log) + { + _fileSystem = fileSystem; + _environment = environment; + _log = log; + } + + public IReadOnlyList Search(DirectoryPath path) + { + path = path.MakeAbsolute(_environment); + var root = _fileSystem.GetDirectory(path); + if (!root.Exists) + { + _log.Debug("Module directory does not exist."); + return new Type[] { }; + } + + var result = new List(); + var files = root.GetFiles("Cake.*.Module.dll", SearchScope.Recursive); + foreach (var file in files) + { + if (ShouldLoadModule(file.Path)) + { + var module = LoadModule(file.Path); + if (module != null) + { + result.Add(module); + } + } + } + + return result; + } + + private static bool ShouldLoadModule(FilePath path) + { + try + { + AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve; + var assembly = Assembly.ReflectionOnlyLoadFrom(path.FullPath); + var attributes = CustomAttributeData.GetCustomAttributes(assembly); + foreach (var attribute in attributes) + { + if (attribute.AttributeType.FullName == typeof(CakeModuleAttribute).FullName) + { + return true; + } + } + return false; + } + finally + { + // Unregister reflection-only assembly resolve. + AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= CurrentDomain_ReflectionOnlyAssemblyResolve; + } + } + + private static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args) + { + return Assembly.ReflectionOnlyLoad(args.Name); + } + + private Type LoadModule(FilePath path) + { + var assembly = Assembly.LoadFrom(path.FullPath); + + var attribute = assembly.GetCustomAttributes().FirstOrDefault(); + if (attribute == null) + { + _log.Warning("The assembly '{0}' does not have module metadata.", path.FullPath); + return null; + } + + if (!typeof(ICakeModule).IsAssignableFrom(attribute.ModuleType)) + { + _log.Warning("The module type '{0}' is not an actual module.", attribute.ModuleType.FullName); + return attribute.ModuleType; + } + + return attribute.ModuleType; + } + } +} diff --git a/src/Cake/Constants.cs b/src/Cake/Constants.cs index 5896f061d2..25cb507b00 100644 --- a/src/Cake/Constants.cs +++ b/src/Cake/Constants.cs @@ -6,5 +6,10 @@ public static class Roslyn { public const string NuGetSource = "Roslyn_NuGetSource"; } + + public static class Paths + { + public const string Modules = "Paths_Modules"; + } } } diff --git a/src/Cake/Diagnostics/CakeBuildLog.cs b/src/Cake/Diagnostics/CakeBuildLog.cs index e891c767b6..70cbdc5f2c 100644 --- a/src/Cake/Diagnostics/CakeBuildLog.cs +++ b/src/Cake/Diagnostics/CakeBuildLog.cs @@ -6,13 +6,13 @@ namespace Cake.Diagnostics { - internal sealed class CakeBuildLog : IVerbosityAwareLog + internal sealed class CakeBuildLog : ICakeLog { private readonly IConsole _console; private readonly object _lock; private readonly IDictionary _palettes; - public Verbosity Verbosity { get; private set; } + public Verbosity Verbosity { get; set; } public CakeBuildLog(IConsole console, Verbosity verbosity = Verbosity.Normal) { @@ -62,11 +62,6 @@ public void Write(Verbosity verbosity, LogLevel level, string format, params obj } } - public void SetVerbosity(Verbosity verbosity) - { - Verbosity = verbosity; - } - private void SetPalette(FormatToken token, ConsolePalette palette) { var property = token as PropertyToken; diff --git a/src/Cake/Diagnostics/IVerbosityAware.cs b/src/Cake/Diagnostics/IVerbosityAware.cs deleted file mode 100644 index d820cb06e9..0000000000 --- a/src/Cake/Diagnostics/IVerbosityAware.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Cake.Core.Diagnostics; - -namespace Cake.Diagnostics -{ - /// - /// Represents a verbosity aware log. - /// - public interface IVerbosityAwareLog : ICakeLog - { - /// - /// Sets the verbosity. - /// - /// The desired verbosity. - void SetVerbosity(Verbosity verbosity); - } -} \ No newline at end of file diff --git a/src/Cake/Modules/ArgumentsModule.cs b/src/Cake/Modules/ArgumentsModule.cs new file mode 100644 index 0000000000..12c59fd156 --- /dev/null +++ b/src/Cake/Modules/ArgumentsModule.cs @@ -0,0 +1,21 @@ +using Cake.Core; +using Cake.Core.Composition; + +namespace Cake.Modules +{ + internal sealed class ArgumentsModule : ICakeModule + { + private readonly CakeOptions _options; + + public ArgumentsModule(CakeOptions options) + { + _options = options; + } + + public void Register(ICakeContainerRegistry registry) + { + registry.RegisterInstance(_options).As(); + registry.RegisterType().As().Singleton(); + } + } +} diff --git a/src/Cake/Modules/CakeModule.cs b/src/Cake/Modules/CakeModule.cs new file mode 100644 index 0000000000..3a6a9ce00e --- /dev/null +++ b/src/Cake/Modules/CakeModule.cs @@ -0,0 +1,50 @@ +using Cake.Arguments; +using Cake.Commands; +using Cake.Composition; +using Cake.Core; +using Cake.Core.Composition; +using Cake.Core.Configuration; +using Cake.Core.Diagnostics; +using Cake.Diagnostics; +using Cake.Scripting; + +namespace Cake.Modules +{ + internal sealed class CakeModule : ICakeModule + { + public void Register(ICakeContainerRegistry registry) + { + // Core services. + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + + // Modules + registry.RegisterType().Singleton(); + registry.RegisterType().Singleton(); + + // Configuration + registry.RegisterType().Singleton(); + + // Cake services. + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().Singleton(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().Singleton(); + registry.RegisterType().As().Singleton(); + + // Scripting + registry.RegisterType().Singleton(); + registry.RegisterType().Singleton(); + registry.RegisterType().Singleton(); + + // Register commands. + registry.RegisterType().AsSelf().Transient(); + registry.RegisterType().AsSelf().Transient(); + registry.RegisterType().AsSelf().Transient(); + registry.RegisterType().AsSelf().Transient(); + registry.RegisterType().AsSelf().Transient(); + registry.RegisterType().AsSelf().Transient(); + } + } +} diff --git a/src/Cake/Autofac/ConfigurationModule.cs b/src/Cake/Modules/ConfigurationModule.cs similarity index 70% rename from src/Cake/Autofac/ConfigurationModule.cs rename to src/Cake/Modules/ConfigurationModule.cs index 88a8322ef1..57f3400bba 100644 --- a/src/Cake/Autofac/ConfigurationModule.cs +++ b/src/Cake/Modules/ConfigurationModule.cs @@ -1,10 +1,11 @@ using System.Diagnostics; using Autofac; +using Cake.Core.Composition; using Cake.Core.Configuration; -namespace Cake.Autofac +namespace Cake.Modules { - internal sealed class ConfigurationModule : Module + internal sealed class ConfigurationModule : ICakeModule { private readonly CakeConfigurationProvider _provider; private readonly CakeOptions _options; @@ -15,11 +16,11 @@ public ConfigurationModule(IContainer container, CakeOptions options) _options = options; } - protected override void Load(ContainerBuilder builder) + public void Register(ICakeContainerRegistry registry) { var configuration = _provider.CreateConfiguration(_options.Arguments); Debug.Assert(configuration != null, "Configuration should not be null."); - builder.RegisterInstance(configuration).As(); + registry.RegisterInstance(configuration).As(); } } } diff --git a/src/Cake/Autofac/ScriptingModule.cs b/src/Cake/Modules/ScriptingModule.cs similarity index 55% rename from src/Cake/Autofac/ScriptingModule.cs rename to src/Cake/Modules/ScriptingModule.cs index 0011c8898d..7f71eedcfe 100644 --- a/src/Cake/Autofac/ScriptingModule.cs +++ b/src/Cake/Modules/ScriptingModule.cs @@ -1,14 +1,14 @@ using System; -using Autofac; +using Cake.Core.Composition; using Cake.Core.Scripting; using Cake.Scripting.Mono; using Cake.Scripting.Roslyn; using Cake.Scripting.Roslyn.Nightly; using Cake.Scripting.Roslyn.Stable; -namespace Cake.Autofac +namespace Cake.Modules { - internal sealed class ScriptingModule : Module + internal sealed class ScriptingModule : ICakeModule { private readonly CakeOptions _options; @@ -17,7 +17,7 @@ public ScriptingModule(CakeOptions options) _options = options ?? new CakeOptions(); } - protected override void Load(ContainerBuilder builder) + public void Register(ICakeContainerRegistry registry) { // Are we running on Mono? var mono = Type.GetType("Mono.Runtime") != null; @@ -33,24 +33,24 @@ protected override void Load(ContainerBuilder builder) if (mono) { // Mono compiler - builder.RegisterType().As().SingleInstance(); + registry.RegisterType().As().Singleton(); } else { // Roslyn - builder.RegisterType().As().SingleInstance(); + registry.RegisterType().As().Singleton(); if (_options.Arguments.ContainsKey("debug")) { // Debug - builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); } else { // Default - builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); + registry.RegisterType().As().Singleton(); + registry.RegisterType().As().Singleton(); } } } diff --git a/src/Cake/Program.cs b/src/Cake/Program.cs index 5257e36078..7984ae7b8b 100644 --- a/src/Cake/Program.cs +++ b/src/Cake/Program.cs @@ -2,9 +2,12 @@ using System.Linq; using Autofac; using Cake.Arguments; -using Cake.Autofac; +using Cake.Composition; using Cake.Core.Diagnostics; +using Cake.Core.Modules; using Cake.Diagnostics; +using Cake.Modules; +using Cake.NuGet; namespace Cake { @@ -29,8 +32,10 @@ public static int Main() .Skip(1) // Skip executable. .ToArray(); - var builder = new ContainerBuilder(); - builder.RegisterModule(); + var builder = new CakeContainerBuilder(); + builder.Registry.RegisterModule(new CakeModule()); + builder.Registry.RegisterModule(new CoreModule()); + builder.Registry.RegisterModule(new NuGetModule()); // Build the container. using (var container = builder.Build()) @@ -42,13 +47,20 @@ public static int Main() var parser = container.Resolve(); var options = parser.Parse(args); + // Set verbosity. + log.Verbosity = options.Verbosity; + // Rebuild the container. - builder = new ContainerBuilder(); - builder.RegisterModule(new ArgumentsModule(options)); - builder.RegisterModule(new ConfigurationModule(container, options)); - builder.RegisterModule(new ScriptingModule(options)); + builder = new CakeContainerBuilder(); + builder.Registry.RegisterModule(new ArgumentsModule(options)); + builder.Registry.RegisterModule(new ConfigurationModule(container, options)); + builder.Registry.RegisterModule(new ScriptingModule(options)); builder.Update(container); + // Load all modules. + var loader = container.Resolve(); + loader.LoadModules(container, options); + // Resolve and run the application. var application = container.Resolve(); return application.Run(options); diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 8ef4e4f82f..dae3f42dad 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -6,8 +6,8 @@ using System.Reflection; [assembly: AssemblyProduct("Cake")] -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-beta.1+0.Branch.release/0.12.0.Sha.db292d321378109991d7dbb9c78aec6dd7b7ebf5")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-beta.1+0.Branch.release/0.13.0.Sha.cb8b8acaee3dd90cb1a0e21fc079b4e65690750d")] [assembly: AssemblyCopyright("Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park and contributors")] diff --git a/tools/packages.config b/tools/packages.config index 4e71544125..b219d066d0 100644 --- a/tools/packages.config +++ b/tools/packages.config @@ -1,4 +1,4 @@ - +