From b83ab81abfa3f8c503ec2b02b212b59bd802a32f Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 14 Dec 2014 18:29:05 +0000 Subject: [PATCH] Support target framework specific NuGet PowerShell scripts. Fix AutoMapper NuGet PowerShell scripts not being run. A NuGet package can have install.ps1 and uninstall.ps1 PowerShell scripts that target a particular framework based on the tools subdirectory where they can be placed: tools\net40\install.ps1 tools\net40\uninstall.ps1 Previously SharpDevelop would only look in the tools directory for these scripts. Now it will use the project's target framework to find the most compatible PowerShell install or uninstall script. Note that NuGet does not support init.ps1 being target framework specific and it will only be run if it exists in the tools directory inside the NuGet package. --- .../Project/Src/Design/FakeFileSystem.cs | 14 +++- .../Design/FakePackageManagementProject.cs | 4 + .../Project/Src/IPackageManagementProject.cs | 2 + .../Project/Src/PackageManagementProject.cs | 7 ++ .../Src/Scripting/IPackageScriptFileName.cs | 3 + .../Src/Scripting/PackageInstallScript.cs | 1 + .../Project/Src/Scripting/PackageScript.cs | 20 +++++ .../Src/Scripting/PackageScriptFileName.cs | 14 ++++ .../Src/Scripting/PackageUninstallScript.cs | 1 + .../Test/PackageManagement.Tests.csproj | 1 + .../Src/Helpers/FakePackageScriptFileName.cs | 6 ++ .../Test/Src/PackageManagementProjectTests.cs | 42 +++++++--- .../Scripting/PackageInstallScriptTests.cs | 35 +++++++++ .../Scripting/PackageUninstallScriptTests.cs | 76 +++++++++++++++++++ 14 files changed, 216 insertions(+), 10 deletions(-) create mode 100644 src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageUninstallScriptTests.cs diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeFileSystem.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeFileSystem.cs index ddc74b13b7..9c3a5a0367 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeFileSystem.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeFileSystem.cs @@ -59,7 +59,12 @@ namespace ICSharpCode.PackageManagement.Design public string GetFullPath(string path) { - return PathToReturnFromGetFullPath; + if (PathToReturnFromGetFullPath != null) { + return PathToReturnFromGetFullPath; + } else if (Root == null) { + return null; + } + return Path.Combine(Root, path); } public void DeleteFile(string path) @@ -70,9 +75,16 @@ namespace ICSharpCode.PackageManagement.Design public bool FileExists(string path) { PathPassedToFileExists = path; + + if (ExistingFiles.Contains(path)) { + return true; + } + return FileExistsReturnValue; } + public List ExistingFiles = new List(); + public bool DirectoryExists(string path) { PathPassedToDirectoryExists = path; diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProject.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProject.cs index 973b15ab92..3d490b2f96 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProject.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProject.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Versioning; using ICSharpCode.PackageManagement; using ICSharpCode.PackageManagement.EnvDTE; using NuGet; @@ -41,6 +42,7 @@ namespace ICSharpCode.PackageManagement.Design this.Name = name; ConstraintProvider = NullConstraintProvider.Instance; + TargetFramework = new FrameworkName(".NETFramework", new Version("4.0")); } private FakeInstallPackageAction FakeInstallPackageAction; @@ -283,5 +285,7 @@ namespace ICSharpCode.PackageManagement.Design } public IPackageConstraintProvider ConstraintProvider { get; set; } + + public FrameworkName TargetFramework { get; set; } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProject.cs b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProject.cs index 629e24c367..82b782409f 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProject.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProject.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Versioning; using ICSharpCode.PackageManagement.EnvDTE; using NuGet; @@ -33,6 +34,7 @@ namespace ICSharpCode.PackageManagement event EventHandler PackageReferenceRemoving; string Name { get; } + FrameworkName TargetFramework { get; } ILogger Logger { get; set; } IPackageRepository SourceRepository { get; } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProject.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProject.cs index 2b206d57bd..3892191f4d 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProject.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProject.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Versioning; using ICSharpCode.PackageManagement.EnvDTE; using ICSharpCode.SharpDevelop.Project; using NuGet; @@ -32,6 +33,7 @@ namespace ICSharpCode.PackageManagement ISharpDevelopProjectManager projectManager; IPackageManagementEvents packageManagementEvents; MSBuildBasedProject msbuildProject; + ProjectTargetFramework targetFramework; public PackageManagementProject( IPackageRepository sourceRepository, @@ -41,6 +43,7 @@ namespace ICSharpCode.PackageManagement { SourceRepository = sourceRepository; msbuildProject = project; + targetFramework = new ProjectTargetFramework(project); this.packageManagementEvents = packageManagementEvents; packageManager = packageManagerFactory.CreatePackageManager(sourceRepository, project); @@ -51,6 +54,10 @@ namespace ICSharpCode.PackageManagement get { return msbuildProject.Name; } } + public FrameworkName TargetFramework { + get { return targetFramework.TargetFrameworkName; } + } + public IPackageRepository SourceRepository { get; private set; } public ILogger Logger { diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageScriptFileName.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageScriptFileName.cs index 620c2366cd..79dcb47427 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageScriptFileName.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageScriptFileName.cs @@ -17,6 +17,8 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Runtime.Versioning; +using NuGet; namespace ICSharpCode.PackageManagement.Scripting { @@ -27,5 +29,6 @@ namespace ICSharpCode.PackageManagement.Scripting bool ScriptDirectoryExists(); bool FileExists(); string GetScriptDirectory(); + void UseTargetSpecificFileName(IPackage package, FrameworkName frameworkName); } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageInstallScript.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageInstallScript.cs index 257d1ed39f..257d9346a4 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageInstallScript.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageInstallScript.cs @@ -26,6 +26,7 @@ namespace ICSharpCode.PackageManagement.Scripting public PackageInstallScript(IPackage package, IPackageScriptFileName fileName) : base(package, fileName) { + UseTargetSpecificScript = true; } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScript.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScript.cs index 5bcf8134b2..ceb6e3ea5d 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScript.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScript.cs @@ -17,6 +17,9 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Versioning; using ICSharpCode.PackageManagement.EnvDTE; using NuGet; @@ -24,6 +27,8 @@ namespace ICSharpCode.PackageManagement.Scripting { public class PackageScript : IPackageScript { + bool lookedForTargetSpecificScript; + public PackageScript(IPackage package, IPackageScriptFileName fileName) { this.Package = package; @@ -32,12 +37,14 @@ namespace ICSharpCode.PackageManagement.Scripting protected IPackageScriptFileName ScriptFileName { get; private set; } protected IPackageScriptSession Session { get; private set; } + protected bool UseTargetSpecificScript { get; set; } public IPackage Package { get; set; } public IPackageManagementProject Project { get; set; } public bool Exists() { + FindTargetSpecificScriptFileName(); return ScriptFileName.FileExists(); } @@ -97,5 +104,18 @@ namespace ICSharpCode.PackageManagement.Scripting Session.RemoveVariable("__package"); Session.RemoveVariable("__project"); } + + void FindTargetSpecificScriptFileName() + { + if (UseTargetSpecificScript && !lookedForTargetSpecificScript) { + ScriptFileName.UseTargetSpecificFileName(Package, GetTargetFramework()); + lookedForTargetSpecificScript = true; + } + } + + FrameworkName GetTargetFramework() + { + return Project.TargetFramework; + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScriptFileName.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScriptFileName.cs index 590fe081de..3344a4601f 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScriptFileName.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageScriptFileName.cs @@ -17,7 +17,10 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Runtime.Versioning; using NuGet; namespace ICSharpCode.PackageManagement.Scripting @@ -68,5 +71,16 @@ namespace ICSharpCode.PackageManagement.Scripting { return fileSystem.GetFullPath("tools"); } + + public void UseTargetSpecificFileName(IPackage package, FrameworkName targetFramework) + { + IEnumerable files; + if (VersionUtility.TryGetCompatibleItems(targetFramework, package.GetToolFiles(), out files)) { + IPackageFile matchingScriptFile = files.FirstOrDefault(file => file.EffectivePath.Equals(Name, StringComparison.OrdinalIgnoreCase)); + if (matchingScriptFile != null) { + relativeScriptFilePath = matchingScriptFile.Path; + } + } + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageUninstallScript.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageUninstallScript.cs index 27eaa94a54..4007bef931 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageUninstallScript.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageUninstallScript.cs @@ -26,6 +26,7 @@ namespace ICSharpCode.PackageManagement.Scripting public PackageUninstallScript(IPackage package, IPackageScriptFileName fileName) : base(package, fileName) { + UseTargetSpecificScript = true; } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj index b5c3c304a8..e08013ea35 100644 --- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj +++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj @@ -198,6 +198,7 @@ + diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageScriptFileName.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageScriptFileName.cs index 29991ea814..1a0918e63e 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageScriptFileName.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageScriptFileName.cs @@ -17,7 +17,9 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Runtime.Versioning; using ICSharpCode.PackageManagement.Scripting; +using NuGet; namespace PackageManagement.Tests.Helpers { @@ -52,5 +54,9 @@ namespace PackageManagement.Tests.Helpers { return ToStringReturnValue; } + + public void UseTargetSpecificFileName(IPackage package, FrameworkName frameworkName) + { + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementProjectTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementProjectTests.cs index 3c1c06b677..d2929838d8 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementProjectTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementProjectTests.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Versioning; using ICSharpCode.PackageManagement; using ICSharpCode.PackageManagement.Design; using ICSharpCode.PackageManagement.EnvDTE; @@ -46,17 +47,25 @@ namespace PackageManagement.Tests UpdatePackagesAction updatePackagesAction; void CreateProject() + { + fakeMSBuildProject = ProjectHelper.CreateTestProject(); + fakeMSBuildProject.SetProperty("TargetFrameworkIdentifier", null); + fakeMSBuildProject.SetProperty("TargetFrameworkVersion", "v4.0"); + fakeMSBuildProject.SetProperty("TargetFrameworkProfile", null); + CreateProject(fakeMSBuildProject); + } + + void CreateProject(MSBuildBasedProject msbuildProject) { fakePackageManagerFactory = new FakePackageManagerFactory(); fakePackageManager = fakePackageManagerFactory.FakePackageManager; fakeProjectManager = fakePackageManager.FakeProjectManager; fakeSourceRepository = new FakePackageRepository(); - fakeMSBuildProject = ProjectHelper.CreateTestProject(); fakePackageManagementEvents = new FakePackageManagementEvents(); project = new PackageManagementProject( fakeSourceRepository, - fakeMSBuildProject, + msbuildProject, fakePackageManagementEvents, fakePackageManagerFactory); } @@ -761,25 +770,40 @@ namespace PackageManagement.Tests } [Test] - public void ConstraintProvider_LocalRepositoryDoesNotImplementIConstraintProvider_ReturnsNullConstraintProviderInstance () + public void ConstraintProvider_LocalRepositoryDoesNotImplementIConstraintProvider_ReturnsNullConstraintProviderInstance() { - CreateProject (); + CreateProject(); IPackageConstraintProvider provider = project.ConstraintProvider; - Assert.AreEqual (NullConstraintProvider.Instance, provider); + Assert.AreEqual(NullConstraintProvider.Instance, provider); } [Test] - public void ConstraintProvider_LocalRepositoryImplementsIConstraintProvider_ReturnsLocalRepository () + public void ConstraintProvider_LocalRepositoryImplementsIConstraintProvider_ReturnsLocalRepository() { - CreateProject (); - var localRepository = new FakePackageRepositoryWithConstraintProvider (); + CreateProject(); + var localRepository = new FakePackageRepositoryWithConstraintProvider(); fakeProjectManager.FakeLocalRepository = localRepository; IPackageConstraintProvider provider = project.ConstraintProvider; - Assert.AreEqual (localRepository, provider); + Assert.AreEqual(localRepository, provider); + } + + [Test] + public void TargetFramework_TargetFrameworkVersion40DefinedInProject_ReturnsFullDotNetFramework40() + { + fakeMSBuildProject = ProjectHelper.CreateTestProject(); + fakeMSBuildProject.SetProperty("TargetFrameworkIdentifier", null); + fakeMSBuildProject.SetProperty("TargetFrameworkVersion", "v4.0"); + fakeMSBuildProject.SetProperty("TargetFrameworkProfile", null); + CreateProject(fakeMSBuildProject); + var expectedName = new FrameworkName(".NETFramework, Version=v4.0"); + + FrameworkName targetFramework = project.TargetFramework; + + Assert.AreEqual(expectedName, targetFramework); } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageInstallScriptTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageInstallScriptTests.cs index 382564c402..1159bd5fe2 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageInstallScriptTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageInstallScriptTests.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Runtime.Versioning; using ICSharpCode.PackageManagement.Design; using ICSharpCode.PackageManagement.EnvDTE; using ICSharpCode.PackageManagement.Scripting; @@ -34,6 +35,7 @@ namespace PackageManagement.Tests.Scripting PackageInstallScript script; FakeFileSystem fakeFileSystem; FakePackage fakePackage; + FakePackageManagementProject fakeProject; void CreateScript() { @@ -45,7 +47,10 @@ namespace PackageManagement.Tests.Scripting fakeSession = new FakePackageScriptSession(); fakePackage = new FakePackage(); + fakeProject = new FakePackageManagementProject(); + script = new PackageInstallScript(fakePackage, scriptFileName); + script.Project = fakeProject; } void ExecuteScript() @@ -123,5 +128,35 @@ namespace PackageManagement.Tests.Scripting Assert.AreEqual(fakePackage, package); } + + [Test] + public void Run_PackageHasTargetFrameworkSpecificInstallPowerShellScript_InstallPowerShellScriptIsRun() + { + CreateScript(); + fakeFileSystem.Root = @"d:\projects\MyProject\packages\MyPackage.1.0"; + fakePackage.AddFile(@"tools\net40\Install.ps1"); + fakeProject.TargetFramework = new FrameworkName(".NETFramework", new Version("4.0")); + + script.Run(fakeSession); + + bool result = fakeSession.ScriptPassedToInvokeScript.StartsWith( + @"& 'd:\projects\MyProject\packages\MyPackage.1.0\tools\net40\Install.ps1'"); + Assert.IsTrue(result, fakeSession.ScriptPassedToInvokeScript); + } + + [Test] + public void Exists_PackageHasTargetFrameworkSpecificInstallPowerShellScript_ReturnsTrue() + { + CreateScript(); + fakeFileSystem.Root = @"d:\projects\MyProject\packages\MyPackage.1.0"; + fakeFileSystem.ExistingFiles.Add(@"tools\net40\install.ps1"); + fakeFileSystem.FileExistsReturnValue = false; + fakePackage.AddFile(@"tools\net40\install.ps1"); + fakeProject.TargetFramework = new FrameworkName(".NETFramework", new Version("4.0")); + + bool exists = script.Exists(); + + Assert.IsTrue(exists); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageUninstallScriptTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageUninstallScriptTests.cs new file mode 100644 index 0000000000..30058975da --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageUninstallScriptTests.cs @@ -0,0 +1,76 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Runtime.Versioning; +using ICSharpCode.PackageManagement.Design; +using ICSharpCode.PackageManagement.EnvDTE; +using ICSharpCode.PackageManagement.Scripting; +using NuGet; +using NUnit.Framework; +using PackageManagement.Tests.Helpers; + +namespace PackageManagement.Tests.Scripting +{ + [TestFixture] + public class PackageUninstallScriptTests + { + PackageUninstallScriptFileName scriptFileName; + FakePackageScriptSession fakeSession; + PackageUninstallScript script; + FakeFileSystem fakeFileSystem; + FakePackage fakePackage; + FakePackageManagementProject fakeProject; + + void CreateScript() + { + fakeFileSystem = new FakeFileSystem(); + fakeFileSystem.FileExistsReturnValue = true; + fakeFileSystem.DirectoryExistsReturnValue = true; + scriptFileName = new PackageUninstallScriptFileName(fakeFileSystem); + + fakeSession = new FakePackageScriptSession(); + fakePackage = new FakePackage(); + + fakeProject = new FakePackageManagementProject(); + + script = new PackageUninstallScript(fakePackage, scriptFileName); + script.Project = fakeProject; + } + + void ExecuteScript() + { + script.Run(fakeSession); + } + + [Test] + public void Run_PackageHasTargetFrameworkSpecificUnistallPowerShellScript_UninstallPowerShellScriptIsRun() + { + CreateScript(); + fakeFileSystem.Root = @"d:\projects\MyProject\packages\MyPackage.1.0"; + fakePackage.AddFile(@"tools\net40\uninstall.ps1"); + fakeProject.TargetFramework = new FrameworkName(".NETFramework", new Version("4.0")); + + script.Run(fakeSession); + + bool result = fakeSession.ScriptPassedToInvokeScript.StartsWith( + @"& 'd:\projects\MyProject\packages\MyPackage.1.0\tools\net40\uninstall.ps1'"); + Assert.IsTrue(result, fakeSession.ScriptPassedToInvokeScript); + } + } +}