diff --git a/docs/content/nuget-dependencies.md b/docs/content/nuget-dependencies.md index 34d582f2fd..c5f2cca45d 100644 --- a/docs/content/nuget-dependencies.md +++ b/docs/content/nuget-dependencies.md @@ -196,6 +196,20 @@ You can instruct Paket to create assembly binding redirects for NuGet packages: nuget FSharp.Core redirects: on +Redirects are created only if they are required. However, you can instruct Paket to create it regardless: + + source https://nuget.org/api/v2 + + nuget FSharp.Core redirects: force + +In constract, you have the option to force Paket to not create a redirect: + + source https://nuget.org/api/v2 + + nuget FSharp.Core redirects: off + +You can also override the redirects settings per project, from its [references file](references-files.html#Redirects-settings). + ### import_targets settings If you don't want to import `.targets` and `.props` files you can disable it via the `import_targets` switch: diff --git a/docs/content/references-files.md b/docs/content/references-files.md index 4c058fc3e5..869db401eb 100644 --- a/docs/content/references-files.md +++ b/docs/content/references-files.md @@ -55,6 +55,22 @@ Sometimes you don't want to generate dependencies for older framework versions. Newtonsoft.Json framework: net35, net40 DotNetZip framework: >= net45 +## Redirects settings + +You can instruct Paket to create assembly binding redirects for NuGet packages: + + FSharp.Core redirects: on + +Redirects are created only if they are required. However, you can instruct Paket to create it regardless: + + FSharp.Core redirects: force + +In constract, you have the option to force Paket to not create a redirect: + + FSharp.Core redirects: off + +Redirects settings in [references files](references-files.html#Redirects-settings) takes precedence over settings in [dependencies file](nuget-dependencies.html#redirects-settings). + ## File name conventions If Paket finds `paket.references` in a folder, the dependencies it specifies will be added to all MSBuild projects in that folder. diff --git a/integrationtests/Paket.IntegrationTests/BindingRedirect.fs b/integrationtests/Paket.IntegrationTests/BindingRedirect.fs index cc8e1c6ff3..7145d9ed0e 100644 --- a/integrationtests/Paket.IntegrationTests/BindingRedirect.fs +++ b/integrationtests/Paket.IntegrationTests/BindingRedirect.fs @@ -235,4 +235,40 @@ let ``#1248 install should replace paket's binding redirects with required only config2 |> normalizeLineEndings - |> shouldEqual (normalizeLineEndings originalConfig2) \ No newline at end of file + |> shouldEqual (normalizeLineEndings originalConfig2) + +[] +let ``#1270 force redirects``() = + paket "install --createnewbindingfiles" "i001270-force-redirects" |> ignore + let path = Path.Combine(scenarioTempPath "i001270-force-redirects") + let configPath = Path.Combine(path, "MyClassLibrary", "MyClassLibrary", "app.config") + + let ``FSharp.Core`` = """""" + let AlphaFS = """""" + let ``Newtonsoft.Json`` = """""" + let ``Newtonsoft.Json.Schema`` = """""" + + let config = File.ReadAllText(configPath) + + config |> shouldContainText ``FSharp.Core`` + config.Contains AlphaFS |> shouldEqual false + config.Contains ``Newtonsoft.Json`` |> shouldEqual false + config.Contains ``Newtonsoft.Json.Schema`` |> shouldEqual false + +[] +let ``#1270 redirects from references``() = + paket "install --createnewbindingfiles" "i001270-force-redirects" |> ignore + let path = Path.Combine(scenarioTempPath "i001270-force-redirects") + let configPath = Path.Combine(path, "MyClassLibrary", "MyClassLibrary2", "app.config") + + let ``FSharp.Core`` = """""" + let AlphaFS = """""" + let ``Newtonsoft.Json`` = """""" + let ``Newtonsoft.Json.Schema`` = """""" + + let config = File.ReadAllText(configPath) + + config.Contains ``FSharp.Core`` |> shouldEqual false + config.Contains AlphaFS |> shouldEqual false + config |> shouldContainText ``Newtonsoft.Json.Schema`` + config.Contains ``Newtonsoft.Json`` |> shouldEqual false diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary.sln b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary.sln new file mode 100644 index 0000000000..d319700402 --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{673951A0-5216-4FBD-BA08-7FA057D5CC0D}" + ProjectSection(SolutionItems) = preProject + ..\paket.dependencies = ..\paket.dependencies + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyClassLibrary", "MyClassLibrary\MyClassLibrary.csproj", "{CD678800-8DFC-4BB1-911A-7234F492EA29}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CD678800-8DFC-4BB1-911A-7234F492EA29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD678800-8DFC-4BB1-911A-7234F492EA29}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD678800-8DFC-4BB1-911A-7234F492EA29}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD678800-8DFC-4BB1-911A-7234F492EA29}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/Class1.cs b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/Class1.cs new file mode 100644 index 0000000000..2580be441d --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/Class1.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MyClassLibrary +{ + public class Class1 + { + } +} diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate new file mode 100644 index 0000000000..97b6f1f633 --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -0,0 +1,104 @@ + + + + + Debug + AnyCPU + {CD678800-8DFC-4BB1-911A-7234F492EA29} + Library + Properties + MyClassLibrary + MyClassLibrary + v4.5.2 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + ..\..\packages\AlphaFS\lib\net35\AlphaFS.dll + True + True + + + True + + + + + + + ..\..\packages\AlphaFS\lib\net45\AlphaFS.dll + True + True + + + True + + + + + + + ..\..\packages\AlphaFS\lib\net40\AlphaFS.dll + True + True + + + True + + + + + + + ..\..\packages\AlphaFS\lib\net451\AlphaFS.dll + True + True + + + True + + + + + \ No newline at end of file diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/Properties/AssemblyInfo.cs b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7920bce104 --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MyClassLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MyClassLibrary")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("cd678800-8dfc-4bb1-911a-7234f492ea29")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/paket.references b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/paket.references new file mode 100644 index 0000000000..ba7ad127f5 --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/paket.references @@ -0,0 +1,3 @@ +alphafs +FSharp.Core +Newtonsoft.Json.Schema \ No newline at end of file diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/Class1.cs b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/Class1.cs new file mode 100644 index 0000000000..2580be441d --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/Class1.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MyClassLibrary +{ + public class Class1 + { + } +} diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary2.csprojtemplate b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary2.csprojtemplate new file mode 100644 index 0000000000..97b6f1f633 --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary2.csprojtemplate @@ -0,0 +1,104 @@ + + + + + Debug + AnyCPU + {CD678800-8DFC-4BB1-911A-7234F492EA29} + Library + Properties + MyClassLibrary + MyClassLibrary + v4.5.2 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + ..\..\packages\AlphaFS\lib\net35\AlphaFS.dll + True + True + + + True + + + + + + + ..\..\packages\AlphaFS\lib\net45\AlphaFS.dll + True + True + + + True + + + + + + + ..\..\packages\AlphaFS\lib\net40\AlphaFS.dll + True + True + + + True + + + + + + + ..\..\packages\AlphaFS\lib\net451\AlphaFS.dll + True + True + + + True + + + + + \ No newline at end of file diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/Properties/AssemblyInfo.cs b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7920bce104 --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MyClassLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MyClassLibrary")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("cd678800-8dfc-4bb1-911a-7234f492ea29")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/paket.references b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/paket.references new file mode 100644 index 0000000000..7c72ac150c --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/paket.references @@ -0,0 +1,4 @@ +alphafs redirects: on +FSharp.Core redirects: off +Newtonsoft.Json.Schema redirects: force +Newtonsoft.Json \ No newline at end of file diff --git a/integrationtests/scenarios/i001270-force-redirects/before/paket.dependencies b/integrationtests/scenarios/i001270-force-redirects/before/paket.dependencies new file mode 100644 index 0000000000..af516e9a54 --- /dev/null +++ b/integrationtests/scenarios/i001270-force-redirects/before/paket.dependencies @@ -0,0 +1,5 @@ +source https://www.nuget.org/api/v2/ +nuget Alphafs redirects: on +nuget FSharp.Core redirects: force +nuget Newtonsoft.Json 7.0.1 redirects: off +nuget Newtonsoft.Json.Schema 1.0.11 \ No newline at end of file diff --git a/src/Paket.Core/InstallProcess.fs b/src/Paket.Core/InstallProcess.fs index 0603716880..3ff31faa03 100644 --- a/src/Paket.Core/InstallProcess.fs +++ b/src/Paket.Core/InstallProcess.fs @@ -161,14 +161,19 @@ let CreateModel(root, force, dependenciesFile:DependenciesFile, lockFile : LockF extractedPackages /// Applies binding redirects for all strong-named references to all app. and web.config files. -let private applyBindingRedirects (loadedLibs:Dictionary<_,_>) isFirstGroup createNewBindingFiles cleanBindingRedirects root groupName findDependencies (extractedPackages:seq<_*InstallModel>) = +let private applyBindingRedirects (loadedLibs:Dictionary<_,_>) isFirstGroup createNewBindingFiles cleanBindingRedirects redirects root groupName findDependencies extractedPackages = let dependencyGraph = ConcurrentDictionary<_,Set<_>>() let projects = ConcurrentDictionary<_,ProjectFile option>(); + let referenceFiles = ConcurrentDictionary<_,ReferencesFile option>(); + let referenceFile (projectFile : ProjectFile) = + let referenceFile (projectFile : ProjectFile) = + ProjectFile.FindReferencesFile (FileInfo projectFile.FileName) + |> Option.map ReferencesFile.FromFile + referenceFiles.GetOrAdd(projectFile, referenceFile) let rec dependencies (projectFile : ProjectFile) = - match ProjectFile.FindReferencesFile (FileInfo projectFile.FileName) with - | Some fileName -> - let referenceFile = ReferencesFile.FromFile fileName + match referenceFile projectFile with + | Some referenceFile -> projectFile.GetInterProjectDependencies() |> Seq.map (fun r -> projects.GetOrAdd(r.Path, ProjectFile.TryLoad)) |> Seq.choose id @@ -182,17 +187,26 @@ let private applyBindingRedirects (loadedLibs:Dictionary<_,_>) isFirstGroup crea | None -> Set.empty let bindingRedirects (projectFile : ProjectFile) = + let referenceFile = referenceFile projectFile let dependencies = dependencyGraph.GetOrAdd(projectFile, dependencies) + let redirectsFromReference packageName = + referenceFile + |> Option.bind (fun r -> + r.Groups + |> Seq.filter (fun g -> g.Key = groupName) + |> Seq.collect (fun g -> g.Value.NugetPackages) + |> Seq.tryFind (fun p -> p.Name = packageName) + |> Option.bind (fun p -> p.Settings.CreateBindingRedirects)) let assemblies = extractedPackages - |> Seq.map snd - |> Seq.filter (fun model -> dependencies |> Set.contains model.PackageName) - |> Seq.collect (fun model -> model.GetLibReferences(projectFile.GetTargetProfile())) - |> Seq.groupBy (fun p -> FileInfo(p).Name) + |> Seq.map (fun (model,redirects) -> (model, redirectsFromReference model.PackageName |> Option.fold (fun _ x -> Some x) redirects)) + |> Seq.filter (fun (model,_) -> dependencies |> Set.contains model.PackageName) + |> Seq.collect (fun (model,redirects) -> model.GetLibReferences(projectFile.GetTargetProfile()) |> Seq.map (fun lib -> lib,redirects)) + |> Seq.groupBy (fun (p,_) -> FileInfo(p).Name) |> Seq.choose(fun (_,librariesForPackage) -> librariesForPackage - |> Seq.choose(fun library -> + |> Seq.choose(fun (library,redirects) -> try let key = FileInfo(library).FullName.ToLowerInvariant() let assembly = @@ -203,22 +217,24 @@ let private applyBindingRedirects (loadedLibs:Dictionary<_,_>) isFirstGroup crea loadedLibs.Add(key,v) v - Some (assembly, BindingRedirects.getPublicKeyToken assembly, assembly.GetReferencedAssemblies()) + Some (assembly, BindingRedirects.getPublicKeyToken assembly, assembly.GetReferencedAssemblies(), redirects) with exn -> None) - |> Seq.sortBy(fun (assembly,_,_) -> assembly.GetName().Version) + |> Seq.sortBy(fun (assembly,_,_,_) -> assembly.GetName().Version) |> Seq.toList |> List.rev |> function | head :: _ -> Some head | _ -> None) |> Seq.cache assemblies - |> Seq.choose (fun (assembly,token,refs) -> token |> Option.map (fun token -> (assembly,token,refs))) - |> Seq.filter (fun (assembly,_,refs) -> - assemblies - |> Seq.collect (fun (_,_,refs) -> refs) + |> Seq.choose (fun (assembly,token,refs,redirects) -> token |> Option.map (fun token -> (assembly,token,refs,redirects))) + |> Seq.filter (fun (_,_,_,packageRedirects) -> defaultArg (packageRedirects |> Option.map ((<>) Off)) redirects) + |> Seq.filter (fun (assembly,_,refs,redirects) -> + redirects = Some Force + || assemblies + |> Seq.collect (fun (_,_,refs,_) -> refs) |> Seq.filter (fun a -> assembly.GetName().Name = a.Name) |> Seq.exists (fun a -> assembly.GetName().Version > a.Version)) - |> Seq.map(fun (assembly, token,_) -> + |> Seq.map(fun (assembly, token,_,_) -> { BindingRedirect.AssemblyName = assembly.GetName().Name Version = assembly.GetName().Version.ToString() PublicKeyToken = token @@ -370,16 +386,15 @@ let InstallIntoProjects(options : InstallerOptions, dependenciesFile, lockFile : for g in lockFile.Groups do let group = g.Value model - |> Seq.filter (fun kv -> + |> Seq.filter (fun kv -> (fst kv.Key) = g.Key) + |> Seq.map (fun kv -> let packageRedirects = - match group.Resolution |> Map.tryFind (snd kv.Key) with - | None -> None - | Some p -> p.Settings.CreateBindingRedirects + group.Resolution + |> Map.tryFind (snd kv.Key) + |> Option.bind (fun p -> p.Settings.CreateBindingRedirects) - let isEnabled = defaultArg packageRedirects (options.Redirects || g.Value.Options.Redirects) - isEnabled && (fst kv.Key) = g.Key) - |> Seq.map (fun kv -> kv.Value) - |> applyBindingRedirects loadedLibs !first options.CreateNewBindingFiles options.Hard (FileInfo project.FileName).Directory.FullName g.Key lockFile.GetAllDependenciesOf + (snd kv.Value,packageRedirects)) + |> applyBindingRedirects loadedLibs !first options.CreateNewBindingFiles options.Hard (options.Redirects || g.Value.Options.Redirects) (FileInfo project.FileName).Directory.FullName g.Key lockFile.GetAllDependenciesOf first := false /// Installs all packages from the lock file. diff --git a/src/Paket.Core/ReferencesFile.fs b/src/Paket.Core/ReferencesFile.fs index 1278d76c66..ee1e313329 100644 --- a/src/Paket.Core/ReferencesFile.fs +++ b/src/Paket.Core/ReferencesFile.fs @@ -104,7 +104,7 @@ type ReferencesFile = let lines = File.ReadAllLines(fileName) { ReferencesFile.FromLines lines with FileName = fileName } - member this.AddNuGetReference(groupName, packageName : PackageName, copyLocal: bool, importTargets: bool, frameworkRestrictions, includeVersionInPath, omitContent : bool, createBindingRedirects: bool, referenceCondition) = + member this.AddNuGetReference(groupName, packageName : PackageName, copyLocal: bool, importTargets: bool, frameworkRestrictions, includeVersionInPath, omitContent : bool, createBindingRedirects, referenceCondition) = let package: PackageInstallSettings = { Name = packageName Settings = @@ -113,7 +113,7 @@ type ReferencesFile = FrameworkRestrictions = frameworkRestrictions IncludeVersionInPath = if includeVersionInPath then Some includeVersionInPath else None ReferenceCondition = if String.IsNullOrWhiteSpace referenceCondition |> not then Some referenceCondition else None - CreateBindingRedirects = if createBindingRedirects then Some createBindingRedirects else None + CreateBindingRedirects = createBindingRedirects OmitContent = if omitContent then Some ContentCopySettings.Omit else None } } @@ -140,7 +140,7 @@ type ReferencesFile = { this with Groups = newGroups } - member this.AddNuGetReference(groupName, packageName : PackageName) = this.AddNuGetReference(groupName, packageName, true, true, [], false, false, false, null) + member this.AddNuGetReference(groupName, packageName : PackageName) = this.AddNuGetReference(groupName, packageName, true, true, [], false, false, None, null) member this.RemoveNuGetReference(groupName, packageName : PackageName) = let group = this.Groups.[groupName] diff --git a/src/Paket.Core/Requirements.fs b/src/Paket.Core/Requirements.fs index 0ee9858df4..7606487215 100644 --- a/src/Paket.Core/Requirements.fs +++ b/src/Paket.Core/Requirements.fs @@ -282,13 +282,18 @@ type ContentCopySettings = | Overwrite | OmitIfExisting +type BindingRedirectsSettings = +| On +| Off +| Force + type InstallSettings = { ImportTargets : bool option FrameworkRestrictions: FrameworkRestrictions OmitContent : ContentCopySettings option IncludeVersionInPath: bool option ReferenceCondition : string option - CreateBindingRedirects : bool option + CreateBindingRedirects : BindingRedirectsSettings option CopyLocal : bool option } static member Default = @@ -320,8 +325,9 @@ type InstallSettings = | Some x -> yield "condition: " + x.ToUpper() | None -> () match this.CreateBindingRedirects with - | Some true -> yield "redirects: on" - | Some false -> yield "redirects: off" + | Some On -> yield "redirects: on" + | Some Off -> yield "redirects: off" + | Some Force -> yield "redirects: force" | None -> () match this.FrameworkRestrictions with | [] -> () @@ -363,8 +369,9 @@ type InstallSettings = | _ -> None CreateBindingRedirects = match kvPairs.TryGetValue "redirects" with - | true, "on" -> Some true - | true, "off" -> Some false + | true, "on" -> Some On + | true, "off" -> Some Off + | true, "force" -> Some Force | _ -> None IncludeVersionInPath = match kvPairs.TryGetValue "version_in_path" with diff --git a/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs b/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs index 403f2f94d8..2d2a758b40 100644 --- a/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs +++ b/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs @@ -807,7 +807,7 @@ let ``should read config with reference condition``() = cfg.Groups.[Constants.MainDependencyGroup].Options.Settings.ReferenceCondition |> shouldEqual (Some "MAIN-GROUP") cfg.Groups.[GroupName "Build"].Packages.Head.Settings.ReferenceCondition |> shouldEqual None - cfg.Groups.[GroupName "Build"].Packages.Head.Settings.CreateBindingRedirects |> shouldEqual (Some true) + cfg.Groups.[GroupName "Build"].Packages.Head.Settings.CreateBindingRedirects |> shouldEqual (Some On) cfg.Groups.[GroupName "Build"].Packages.Tail.Head.Settings.ReferenceCondition |> shouldEqual (Some "LEGACY") cfg.Groups.[GroupName "Build"].Packages.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual None @@ -980,4 +980,39 @@ let ``should read config with target framework``() = let cfg = DependenciesFile.FromCode(configTargetFramework) cfg.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions - |> shouldEqual [FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] \ No newline at end of file + |> shouldEqual [FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] + +[] +let ``should read packages with redirects``() = + let config = """ +redirects on +source http://nuget.org/api/v2 + +nuget Paket.Core redirects: on +nuget FSharp.Compiler.Service redirects: off +nuget FsReveal redirects: force +nuget FAKE + +group Build +redirects off + + nuget FAKE redirects: on + nuget NUnit redirects: force + nuget Paket.Core redirects: off + nuget FsReveal + """ + + let cfg = DependenciesFile.FromCode(config) + + cfg.Groups.[Constants.MainDependencyGroup].Options.Redirects |> shouldEqual true + + cfg.Groups.[Constants.MainDependencyGroup].Packages.Head.Settings.CreateBindingRedirects |> shouldEqual (Some On) + cfg.Groups.[Constants.MainDependencyGroup].Packages.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Off) + cfg.Groups.[Constants.MainDependencyGroup].Packages.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Force) + cfg.Groups.[Constants.MainDependencyGroup].Packages.Tail.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual None + + cfg.Groups.[GroupName "Build"].Options.Redirects |> shouldEqual false + cfg.Groups.[GroupName "Build"].Packages.Head.Settings.CreateBindingRedirects |> shouldEqual (Some On) + cfg.Groups.[GroupName "Build"].Packages.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Force) + cfg.Groups.[GroupName "Build"].Packages.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Off) + cfg.Groups.[GroupName "Build"].Packages.Tail.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual None diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index 8c8ee02a0d..795914fdcf 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -565,7 +565,7 @@ let ``should parse lock file with groups``() = packages2.Head.Source |> shouldEqual (PackageSource.LocalNuget("D:\code\\temp with space")) packages2.[0].Name |> shouldEqual (PackageName "FAKE") - packages2.[0].Settings.CreateBindingRedirects |> shouldEqual (Some true) + packages2.[0].Settings.CreateBindingRedirects |> shouldEqual (Some On) [] @@ -616,3 +616,49 @@ let ``should parse no strategy lock file``() = packages.Length |> shouldEqual 1 lockFile.Options.ResolverStrategy |> shouldEqual None + +let packageRedirectsLockFile = """REDIRECTS: ON +NUGET + remote: "D:\code\temp with space" + specs: + Castle.Windsor (2.1) + DotNetZip (1.9.3) - redirects: on + FAKE (3.5.5) - redirects: off + FSharp.Compiler.Service (0.0.62) - redirects: force + +GROUP Build +NUGET + remote: "D:\code\temp with space" + specs: + FAKE (4.0) - redirects: on +""" + +[] +let ``should parse and serialize redirects lock file``() = + let lockFile = LockFileParser.Parse(toLines packageRedirectsLockFile) + let main = lockFile.Tail.Head + let packages = List.rev main.Packages + + packages.Length |> shouldEqual 4 + main.Options.Redirects |> shouldEqual true + + packages.Head.Settings.CreateBindingRedirects |> shouldEqual None + packages.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some On) + packages.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Off) + packages.Tail.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Force) + + let build = lockFile.Head + let packages = List.rev build.Packages + + packages.Length |> shouldEqual 1 + build.Options.Redirects |> shouldEqual false + + packages.Head.Settings.CreateBindingRedirects |> shouldEqual (Some On) + +[] +let ``should parse and serialise redirects lockfile``() = + let lockFile = LockFile.Parse("",toLines packageRedirectsLockFile) + let lockFile' = lockFile.ToString() + + normalizeLineEndings lockFile' + |> shouldEqual (normalizeLineEndings packageRedirectsLockFile) \ No newline at end of file diff --git a/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs b/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs index 09b828459a..6bc44b8c2b 100644 --- a/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs +++ b/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs @@ -359,19 +359,22 @@ let refFileWithRedirects = """ Castle.Windsor Newtonsoft.Json redirects:on FSharp.Core redirects:off +xUnit redirects:force """ [] let ``should parse reffiles with redirects``() = let refFile = ReferencesFile.FromLines(toLines refFileWithRedirects) let mainGroup = refFile.Groups.[Constants.MainDependencyGroup] - mainGroup.NugetPackages.Length |> shouldEqual 3 + mainGroup.NugetPackages.Length |> shouldEqual 4 mainGroup.NugetPackages.Head.Name |> shouldEqual (PackageName "Castle.Windsor") mainGroup.NugetPackages.Head.Settings.CreateBindingRedirects |> shouldEqual None mainGroup.NugetPackages.Tail.Head.Name |> shouldEqual (PackageName "Newtonsoft.Json") - mainGroup.NugetPackages.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some true) + mainGroup.NugetPackages.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some On) mainGroup.NugetPackages.Tail.Tail.Head.Name |> shouldEqual (PackageName "FSharp.Core") - mainGroup.NugetPackages.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some false) + mainGroup.NugetPackages.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Off) + mainGroup.NugetPackages.Tail.Tail.Tail.Head.Name |> shouldEqual (PackageName "xUnit") + mainGroup.NugetPackages.Tail.Tail.Tail.Head.Settings.CreateBindingRedirects |> shouldEqual (Some Force) let refFileWithLinkFalse = """Castle.Windsor Newtonsoft.Json redirects: on