diff --git a/README.md b/README.md index 6342203..74ccb12 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Cake.DotNetTool.Module is a Module for Cake, which extends it with a new IPackag ## Chat Room -Come join in the conversation about Cake.DotNetTool.Module in our Gitter Chat Room +Come join in the conversation about Cake.DotNetTool.Module in our Gitter Chat Room. [![Join the chat at https://gitter.im/cake-contrib/Lobby](https://badges.gitter.im/cake-contrib/Lobby.svg)](https://gitter.im/cake-contrib/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) diff --git a/Source/Cake.DotNetTool.Module/DotNetToolOperation.cs b/Source/Cake.DotNetTool.Module/DotNetToolOperation.cs new file mode 100644 index 0000000..daee620 --- /dev/null +++ b/Source/Cake.DotNetTool.Module/DotNetToolOperation.cs @@ -0,0 +1,9 @@ +namespace Cake.DotNetTool.Module +{ + public enum DotNetToolOperation + { + Install, + Uninstall, + Update + } +} \ No newline at end of file diff --git a/Source/Cake.DotNetTool.Module/DotNetToolPackage.cs b/Source/Cake.DotNetTool.Module/DotNetToolPackage.cs new file mode 100644 index 0000000..3fb06d8 --- /dev/null +++ b/Source/Cake.DotNetTool.Module/DotNetToolPackage.cs @@ -0,0 +1,9 @@ +namespace Cake.DotNetTool.Module +{ + public sealed class DotNetToolPackage + { + public string Id { get; set; } + public string Version { get; set; } + public string ShortCode { get; set; } + } +} \ No newline at end of file diff --git a/Source/Cake.DotNetTool.Module/DotNetToolPackageInstaller.cs b/Source/Cake.DotNetTool.Module/DotNetToolPackageInstaller.cs index bc046e5..675477a 100644 --- a/Source/Cake.DotNetTool.Module/DotNetToolPackageInstaller.cs +++ b/Source/Cake.DotNetTool.Module/DotNetToolPackageInstaller.cs @@ -108,16 +108,42 @@ public IReadOnlyCollection Install(PackageReference package, PackageType } // First we need to check if the Tool is already installed - var installedToolNames = GetInstalledTools(toolLocation); + var installedTools = GetInstalledTools(toolLocation); _log.Debug("Checking for tool: {0}", package.Package.ToLowerInvariant()); - if(installedToolNames.Contains(package.Package.ToLowerInvariant())) + + var installedTool = installedTools.FirstOrDefault(t => t.Id.ToLowerInvariant() == package.Package.ToLowerInvariant()); + + if (installedTool != null) { - _log.Information("Tool {0} is already installed, so nothing to do here.", package.Package); + // The tool is already installed, so need to check if requested version is the same as + // what is already installed + string requestedVersion = null; + + if (package.Parameters.ContainsKey("version")) + { + requestedVersion = package.Parameters["version"].First(); + } + + if (requestedVersion == null) + { + _log.Warning("Tool {0} is already installed, and no specific version has been requested via pre-processor directive, so leaving current version installed.", package.Package); + } + else if (requestedVersion.ToLowerInvariant() != installedTool.Version.ToLowerInvariant()) + { + _log.Warning("Tool {0} is already installed, but a different version has been requested. Uninstall/install will now be performed...", package.Package); + RunDotNetTool(package, toolsFolderDirectoryPath, DotNetToolOperation.Uninstall); + RunDotNetTool(package, toolsFolderDirectoryPath, DotNetToolOperation.Install); + } + else + { + _log.Information("Tool {0} is already installed, with required version.", package.Package); + } } else { - InstallTool(package, toolsFolderDirectoryPath); + // The tool isn't already installed, go ahead and install it + RunDotNetTool(package, toolsFolderDirectoryPath, DotNetToolOperation.Install); } var result = _contentResolver.GetFiles(package, type); @@ -130,7 +156,7 @@ public IReadOnlyCollection Install(PackageReference package, PackageType return result; } - private List GetInstalledTools(string toolLocation) + private List GetInstalledTools(string toolLocation) { var toolLocationArgument = string.Empty; if(toolLocation != "global") @@ -144,7 +170,7 @@ private List GetInstalledTools(string toolLocation) if(!toolLocationDirectory.Exists) { _log.Debug("Specified installation location doesn't currently exist."); - return new List(); + return new List(); } } else @@ -162,7 +188,7 @@ private List GetInstalledTools(string toolLocation) isInstalledProcess.WaitForExit(); var installedTools = isInstalledProcess.GetStandardOutput().ToList(); - var installedToolNames = new List(); + var installedToolNames = new List(); string pattern = @"(?[^\s]+)\s+(?[^\s]+)\s+(?[^`s])"; @@ -171,7 +197,12 @@ private List GetInstalledTools(string toolLocation) foreach (Match match in Regex.Matches(installedTool, pattern, RegexOptions.IgnoreCase)) { _log.Debug("Adding tool {0}", match.Groups["packageName"].Value); - installedToolNames.Add(match.Groups["packageName"].Value); + installedToolNames.Add(new DotNetToolPackage + { + Id = match.Groups["packageName"].Value, + Version = match.Groups["packageVersion"].Value, + ShortCode = match.Groups["packageShortCode"].Value + }); } } @@ -179,14 +210,14 @@ private List GetInstalledTools(string toolLocation) return installedToolNames; } - private void InstallTool(PackageReference package, DirectoryPath toolsFolderDirectoryPath) + private void RunDotNetTool(PackageReference package, DirectoryPath toolsFolderDirectoryPath, DotNetToolOperation operation) { // Install the tool.... - _log.Debug("Installing dotnet tool: {0}...", package.Package); + _log.Debug("Running dotnet tool with operation {0}: {1}...", operation, package.Package); var process = _processRunner.Start( "dotnet", new ProcessSettings { - Arguments = GetArguments(package, _log, toolsFolderDirectoryPath), + Arguments = GetArguments(package, operation, _log, toolsFolderDirectoryPath), RedirectStandardOutput = true, Silent = _log.Verbosity < Verbosity.Diagnostic, NoWorkingDirectory = true }); @@ -201,14 +232,17 @@ private void InstallTool(PackageReference package, DirectoryPath toolsFolderDire _log.Verbose(Verbosity.Diagnostic, "Output:\r\n{0}", output); } } + private static ProcessArgumentBuilder GetArguments( PackageReference definition, + DotNetToolOperation operation, ICakeLog log, DirectoryPath toolDirectoryPath) { var arguments = new ProcessArgumentBuilder(); - arguments.Append("tool install"); + arguments.Append("tool"); + arguments.Append(Enum.GetName(typeof(DotNetToolOperation), operation).ToLowerInvariant()); arguments.AppendQuoted(definition.Package); if(definition.Parameters.ContainsKey("global")) @@ -221,61 +255,70 @@ private static ProcessArgumentBuilder GetArguments( arguments.AppendQuoted(toolDirectoryPath.FullPath); } - if (definition.Address != null) + if (operation != DotNetToolOperation.Uninstall) { - arguments.Append("--add-source"); - arguments.AppendQuoted(definition.Address.AbsoluteUri); - } + if (definition.Address != null) + { + arguments.Append("--add-source"); + arguments.AppendQuoted(definition.Address.AbsoluteUri); + } - // Version - if (definition.Parameters.ContainsKey("version")) - { - arguments.Append("--version"); - arguments.Append(definition.Parameters["version"].First()); - } + // Version + if (definition.Parameters.ContainsKey("version")) + { + arguments.Append("--version"); + arguments.Append(definition.Parameters["version"].First()); + } - // Config File - if(definition.Parameters.ContainsKey("configfile")) - { - arguments.Append("--config-file"); - arguments.AppendQuoted(definition.Parameters["configfile"].First()); - } + // Config File + if(definition.Parameters.ContainsKey("configfile")) + { + arguments.Append("--configfile"); + arguments.AppendQuoted(definition.Parameters["configfile"].First()); + } - // Framework - if (definition.Parameters.ContainsKey("framework")) - { - arguments.Append("--framework"); - arguments.Append(definition.Parameters["framework"].First()); - } + // Whether to ignore failed sources + if(definition.Parameters.ContainsKey("ignore-failed-sources")) + { + arguments.Append("--ignore-failed-sources"); + } - switch(log.Verbosity) - { - case Verbosity.Quiet: - arguments.Append("--verbosity"); - arguments.Append("quiet"); - break; - case Verbosity.Minimal: - arguments.Append("--verbosity"); - arguments.Append("minimal"); - break; - case Verbosity.Normal: - arguments.Append("--verbosity"); - arguments.Append("normal"); - break; - case Verbosity.Verbose: - arguments.Append("--verbosity"); - arguments.Append("detailed"); - break; - case Verbosity.Diagnostic: - arguments.Append("--verbosity"); - arguments.Append("diagnostic"); - break; - default: + // Framework + if (definition.Parameters.ContainsKey("framework")) + { + arguments.Append("--framework"); + arguments.Append(definition.Parameters["framework"].First()); + } + + switch(log.Verbosity) + { + case Verbosity.Quiet: + arguments.Append("--verbosity"); + arguments.Append("quiet"); + break; + case Verbosity.Minimal: + arguments.Append("--verbosity"); + arguments.Append("minimal"); + break; + case Verbosity.Normal: arguments.Append("--verbosity"); - arguments.Append("normal"); - break; + arguments.Append("normal"); + break; + case Verbosity.Verbose: + arguments.Append("--verbosity"); + arguments.Append("detailed"); + break; + case Verbosity.Diagnostic: + arguments.Append("--verbosity"); + arguments.Append("diagnostic"); + break; + default: + arguments.Append("--verbosity"); + arguments.Append("normal"); + break; + } } - + return arguments; } } diff --git a/docs/input/docs/usage/parameters.md b/docs/input/docs/usage/parameters.md index 692cea2..68c4739 100644 --- a/docs/input/docs/usage/parameters.md +++ b/docs/input/docs/usage/parameters.md @@ -50,6 +50,16 @@ If you need to specify a NuGet config file, for example you need to authenticate #tool dotnet:?package=Octopus.DotNet.Cli&version=4.41.0&configfile="../../NuGet.config" ``` +# Ignore failed sources + +There might be cases where you want to ignore failed NuGet sources as long as the package could be restored. + +## Example + +``` +#tool dotnet:?package=Octopus.DotNet.Cli&version=4.41.0&ignore-failed-sources" +``` + # Framework Specifies the [target framework](https://docs.microsoft.com/en-us/dotnet/standard/frameworks) to install the tool for. By default, the .NET Core SDK tries to choose the most appropriate target framework.