From 80e94ed827ef5db8feb47c7c2ed034a14c24b661 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sat, 13 May 2017 17:54:42 +0200 Subject: [PATCH 01/47] start fixing #2317 because #2333 shows that its relevant. --- .../Dependencies/PackageResolver.fs | 1 + .../PaketConfigFiles/ProjectFile.fs | 4 +- .../Versioning/FrameworkHandling.fs | 91 +++++++++++-------- src/Paket.Core/Versioning/Requirements.fs | 64 +++++++------ ...System.Security.Cryptography.Algorithms.fs | 3 +- .../Versioning/FrameworkCompatibilitySpecs.fs | 8 +- 6 files changed, 97 insertions(+), 74 deletions(-) diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index cc848f2e86..752570ce6b 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -57,6 +57,7 @@ module DependencySetFilter = let _,_,restrictions = dependency let restrictions = restrictions |> getRestrictionList if Seq.isEmpty restrictions then true else + // TODO: fix broken logic match restriction with | FrameworkRestriction.Exactly v1 -> restrictions diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs index 0a9b687af8..d2215a4bf9 100644 --- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs @@ -736,8 +736,8 @@ module ProjectFile = // I don't think there is anyone actually using this part, but it's there for backwards compat. let netCoreRestricted = model.ApplyFrameworkRestrictions - [ FrameworkRestriction.AtLeast (FrameworkIdentifier.DotNetStandard DotNetStandardVersion.V1_0); - FrameworkRestriction.AtLeast (FrameworkIdentifier.DotNetCore DotNetCoreVersion.V1_0) ] + ((List.map DotNetCore KnownTargetProfiles.DotNetCoreVersions @ List.map DotNetStandard KnownTargetProfiles.DotNetStandardVersions) + |> List.map FrameworkRestriction.Exactly) // handle legacy conditions let conditions = diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index 52bdd945ad..56d3a0c26e 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -341,42 +341,59 @@ type FrameworkIdentifier = | XamariniOS _, XamariniOS _ -> true | Native _, Native _ -> true | _ -> false - - /// TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list - - member x.IsCompatible y = - x = y || - (x.SupportedPlatforms |> Seq.exists (fun x' -> x' = y && not (x'.IsSameCategoryAs x))) || - (y.SupportedPlatforms |> Seq.exists (fun y' -> y' = x && not (y'.IsSameCategoryAs y))) - - member x.IsAtLeast y = - if x.IsSameCategoryAs y then - x >= y - else - let isCompatible() = - y.SupportedPlatforms - |> Seq.exists x.IsAtLeast - - match x,y with - | DotNetStandard _, DotNetFramework _ -> isCompatible() - | DotNetFramework _, DotNetStandard _ -> isCompatible() - | _ -> false - - member x.IsAtMost y = - if x.IsSameCategoryAs y then - x < y - else - let isCompatible() = - y.SupportedPlatforms - |> Seq.exists x.IsAtMost - - match x,y with - | DotNetStandard _, DotNetFramework _ -> isCompatible() - | DotNetFramework _, DotNetStandard _ -> isCompatible() - | _ -> false - - member x.IsBetween(a,b) = x.IsAtLeast a && x.IsAtMost b + // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list + /// true when x is supported by y, for example netstandard15 is supported by netcore10 + member x.IsSupportedBy y = + x = y || + (y.SupportedPlatforms |> Seq.exists (fun s -> x.IsSupportedBy s)) + //x = y || + // (x.SupportedPlatforms |> Seq.exists (fun x' -> x' = y && not (x'.IsSameCategoryAs x))) || + // (y.SupportedPlatforms |> Seq.exists (fun y' -> y' = x && not (y'.IsSameCategoryAs y))) + + /// true when x is at least (>=) y ie when y is supported by x, for example netcore10 >= netstandard15 as netstandard15 is supported by netcore10. + /// Note that this relation is not complete, for example for WindowsPhoneSilverlightv7.0 and Windowsv4.5 both <= and >= are false from this definition as + /// no platform supports the other. + member x.IsAtLeast (y:FrameworkIdentifier) = + y.IsSupportedBy x + //if x.IsSameCategoryAs y then + // x >= y + //else + // let isCompatible() = + // y.SupportedPlatforms + // |> Seq.exists x.IsAtLeast + // + // match x,y with + // | DotNetStandard _, DotNetFramework _ -> isCompatible() + // | DotNetFramework _, DotNetStandard _ -> isCompatible() + // | _ -> false + + /// Get all platforms y for which x >= y holds + member x.SupportedPlatformsTransitive = + let findNewPlats (known:FrameworkIdentifier list) (lastStep:FrameworkIdentifier list) = + lastStep + |> List.collect (fun k -> k.SupportedPlatforms) + |> List.filter (fun k -> known |> Seq.contains k |> not) + + Seq.initInfinite (fun _ -> 1) + |> Seq.scan (fun state _ -> + match state with + | Some (known, lastStep) -> + match findNewPlats known lastStep with + | [] -> None + | items -> Some (known @ items, items) + | None -> None) (Some ([x], [x])) + |> Seq.takeWhile (fun i -> i.IsSome) + |> Seq.choose id + |> Seq.last + |> fst + + /// x < y, see y >= x && x <> y + member x.IsSmallerThan y = + x.IsSupportedBy y && x <> y + + /// Note that this returns true only when a >= x and x < b holds. + member x.IsBetween(a,b) = x.IsAtLeast a && x.IsSmallerThan b module FrameworkDetection = @@ -727,7 +744,7 @@ module KnownTargetProfiles = SinglePlatform(WindowsPhoneApp "v8.1")] @ (AllPortableProfiles |> List.map PortableProfile) - let AllDotNetStandardProfiles = + let AllDotNetStandardAndCoreProfiles = DotNetStandardProfiles @ DotNetCoreProfiles // only used in "should understand aot in runtimes" test @@ -749,7 +766,7 @@ module KnownTargetProfiles = let AllProfiles = (AllNativeProfiles |> List.map SinglePlatform) @ - AllDotNetStandardProfiles @ + AllDotNetStandardAndCoreProfiles @ AllDotNetProfiles let FindPortableProfile name = diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index ee0177c8ac..e17bae7f74 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -20,6 +20,7 @@ type FrameworkRestriction = | FrameworkRestriction.AtLeast r -> ">= " + r.ToString() | FrameworkRestriction.Between(min,max) -> sprintf ">= %O < %O" min max + // TODO: remove broken api member x.GetOneIdentifier = match x with | Exactly r -> Some r @@ -27,6 +28,7 @@ type FrameworkRestriction = | AtLeast r -> Some r | Between(r, _) -> Some r + // TODO: remove broken api /// Return if the parameter is a restriction of the same framework category (dotnet, windows phone, silverlight, ...) member x.IsSameCategoryAs (y : FrameworkRestriction) = match (x.GetOneIdentifier, y.GetOneIdentifier) with @@ -85,9 +87,13 @@ let parseRestrictions failImmediatly (text:string) = else yield FrameworkRestriction.Exactly x] +// TODO: remove broken api let private minRestriction = FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V1)) + +// TODO: remove broken api let private minStandardRestriction = FrameworkRestriction.Exactly(DotNetStandard(DotNetStandardVersion.V1_0)) +// TODO: remove broken api let findMaxDotNetRestriction restrictions = minRestriction :: restrictions |> List.filter (fun (r:FrameworkRestriction) -> @@ -100,6 +106,7 @@ let findMaxDotNetRestriction restrictions = | FrameworkRestriction.Exactly r -> r | _ -> failwith "error" +// TODO: remove broken api let findMaxStandardRestriction restrictions = minStandardRestriction :: restrictions |> List.filter (fun (r:FrameworkRestriction) -> @@ -377,26 +384,26 @@ let optimizeDependencies originalDependencies = newRestictions else newRestictions - |> List.map (fun (name,vr,rs) -> - let newRs = - rs - |> List.collect (function - | FrameworkRestriction.Exactly(DotNetStandard(r)) -> - let compatible = - KnownTargetProfiles.DotNetFrameworkIdentifiers - |> List.filter (fun p -> p.IsCompatible(DotNetStandard r)) - |> List.map (fun p -> FrameworkRestriction.Exactly p) - FrameworkRestriction.AtLeast(DotNetStandard(r)) :: compatible - | FrameworkRestriction.AtLeast(DotNetStandard(r)) -> - let compatible = - KnownTargetProfiles.DotNetFrameworkIdentifiers - |> List.filter (fun p -> p.IsCompatible(DotNetStandard r)) - |> List.map (fun p -> FrameworkRestriction.AtLeast p) - FrameworkRestriction.AtLeast(DotNetStandard(r)) :: compatible - | r -> [r]) - |> optimizeRestrictions - - name,vr,newRs) + //|> List.map (fun (name,vr,rs) -> + // let newRs = + // rs + // |> List.collect (function + // | FrameworkRestriction.Exactly(DotNetStandard(r)) -> + // let compatible = + // KnownTargetProfiles.DotNetFrameworkIdentifiers + // |> List.filter (fun p -> p.IsCompatible(DotNetStandard r)) + // |> List.map (fun p -> FrameworkRestriction.Exactly p) + // FrameworkRestriction.AtLeast(DotNetStandard(r)) :: compatible + // | FrameworkRestriction.AtLeast(DotNetStandard(r)) -> + // let compatible = + // KnownTargetProfiles.DotNetFrameworkIdentifiers + // |> List.filter (fun p -> p.IsCompatible(DotNetStandard r)) + // |> List.map (fun p -> FrameworkRestriction.AtLeast p) + // FrameworkRestriction.AtLeast(DotNetStandard(r)) :: compatible + // | r -> [r]) + // |> optimizeRestrictions + // + // name,vr,newRs) newRestictions @@ -511,22 +518,13 @@ let isTargetMatchingRestrictions = match pf with | Native(_) -> true | _ -> false - | FrameworkRestriction.Exactly fw -> - match fw, pf with - | DotNetFramework _, DotNetStandard _ -> false - | DotNetStandard _, DotNetFramework _ -> false - | _ -> pf.IsCompatible(fw) + | FrameworkRestriction.Exactly fw -> + pf = fw | FrameworkRestriction.Portable _ -> false | FrameworkRestriction.AtLeast fw -> - match fw, pf with - | DotNetFramework _, DotNetStandard _ -> false - | DotNetStandard _, DotNetFramework _ -> false - | _ -> pf.IsAtLeast(fw) + pf.IsAtLeast(fw) | FrameworkRestriction.Between(min,max) -> - match min, pf with - | DotNetFramework _, DotNetStandard _ -> false - | DotNetStandard _, DotNetFramework _ -> false - | _ -> pf.IsBetween(min,max)) + pf.IsBetween(min,max)) | _ -> restrictions |> List.exists (fun restriction -> diff --git a/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs b/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs index cb5741535c..751aeef144 100644 --- a/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs +++ b/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs @@ -97,4 +97,5 @@ let ``should generate Xml for System.Security.Cryptography.Algorithms in CSharp ctx.ChooseNodes |> (fun n -> n.Head.OuterXml) |> normalizeXml - result |> shouldEqual (normalizeXml expected) + let expectedXml = normalizeXml expected + result |> shouldEqual expectedXml diff --git a/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs b/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs index 19100c5e63..f43de1c97b 100644 --- a/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs +++ b/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs @@ -30,6 +30,12 @@ open Paket.Requirements [] let ``net46 should be compatible with netstandard13``() = - (DotNetFramework FrameworkVersion.V4_6).IsCompatible (DotNetStandard DotNetStandardVersion.V1_3) + (DotNetFramework FrameworkVersion.V4_6).IsAtLeast (DotNetStandard DotNetStandardVersion.V1_3) + |> shouldEqual true + + (DotNetStandard DotNetStandardVersion.V1_3).IsSupportedBy (DotNetFramework FrameworkVersion.V4_6) + |> shouldEqual true + + (DotNetStandard DotNetStandardVersion.V1_3).IsSmallerThan (DotNetFramework FrameworkVersion.V4_6) |> shouldEqual true From 624c71eacee8ca41f41ba97d7bfe35da3f31bb4e Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sun, 14 May 2017 16:11:33 +0200 Subject: [PATCH 02/47] initial (probably broken) compiling version. --- .../Dependencies/DependenciesFileParser.fs | 6 +- src/Paket.Core/Dependencies/NuGetV2.fs | 69 +- src/Paket.Core/Dependencies/NuGetV3.fs | 4 +- src/Paket.Core/Dependencies/Nuspec.fs | 87 +- .../Dependencies/PackageResolver.fs | 108 ++- src/Paket.Core/Installation/RestoreProcess.fs | 6 +- src/Paket.Core/Installation/UpdateProcess.fs | 17 +- src/Paket.Core/PackageAnalysis/Queries.fs | 18 +- src/Paket.Core/PackageAnalysis/Why.fs | 9 +- .../PackageManagement/NugetConvert.fs | 11 +- .../PaketConfigFiles/DependenciesFile.fs | 75 +- .../PaketConfigFiles/DependencyCache.fs | 2 +- .../PaketConfigFiles/InstallModel.fs | 59 +- src/Paket.Core/PaketConfigFiles/LockFile.fs | 18 +- .../PaketConfigFiles/ProjectFile.fs | 5 +- .../PaketConfigFiles/ReferencesFile.fs | 2 +- src/Paket.Core/PublicAPI.fs | 2 +- src/Paket.Core/Versioning/PlatformMatching.fs | 3 +- src/Paket.Core/Versioning/Requirements.fs | 914 +++++++++--------- .../DependenciesFile/ParserSpecs.fs | 14 +- .../InstallModel/ProcessingSpecs.fs | 18 +- .../InstallModel/Xml/CodeCracker.fs | 7 +- .../Paket.Tests/InstallModel/Xml/EmptyLibs.fs | 2 +- .../InstallModel/Xml/FSharp.Data.SqlClient.fs | 2 +- .../Paket.Tests/InstallModel/Xml/Fantomas.fs | 10 +- .../InstallModel/Xml/FantomasLib.fs | 2 +- tests/Paket.Tests/InstallModel/Xml/Fuchu.fs | 2 +- .../InstallModel/Xml/GitInfoPlanter.fs | 2 +- .../InstallModel/Xml/LibGit2Sharp.fs | 2 +- .../InstallModel/Xml/ManualNodes.fs | 8 +- .../InstallModel/Xml/Microsoft.Bcl.Build.fs | 3 +- .../Xml/Microsoft.CodeAnalysis.Analyzers.fs | 5 +- tests/Paket.Tests/InstallModel/Xml/Plossum.fs | 2 +- .../InstallModel/Xml/RefactoringEssentials.fs | 5 +- tests/Paket.Tests/InstallModel/Xml/RxXaml.fs | 10 +- tests/Paket.Tests/InstallModel/Xml/SQLite.fs | 4 +- .../InstallModel/Xml/StyleCop.MSBuild.fs | 2 +- ...System.Security.Cryptography.Algorithms.fs | 3 +- .../InstallModel/Xml/System.Spatial.fs | 2 +- .../InstallModel/Xml/SystemNetHttp.fs | 2 +- .../InstallModel/Xml/SystemNetHttpForNet4.fs | 2 +- ...mNetHttpWithExistingFrameworkReferences.fs | 6 +- .../SystemNetHttpWithFrameworkReferences.fs | 6 +- .../InstallModel/Xml/xunit.runner.fs | 4 +- .../Lockfile/GenerateWithOptionsSpecs.fs | 8 +- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 56 +- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 37 +- tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 52 +- .../DependencyGroupsAndRestrictions.fs | 4 +- tests/Paket.Tests/TestHelpers.fs | 15 +- .../Versioning/DependencySetSpecs.fs | 210 ++-- .../Versioning/RestrictionApplicationSpecs.fs | 8 +- .../Versioning/RestrictionFilterSpecs.fs | 82 +- 53 files changed, 1038 insertions(+), 974 deletions(-) diff --git a/src/Paket.Core/Dependencies/DependenciesFileParser.fs b/src/Paket.Core/Dependencies/DependenciesFileParser.fs index f8d65d67ae..ac8a4f5957 100644 --- a/src/Paket.Core/Dependencies/DependenciesFileParser.fs +++ b/src/Paket.Core/Dependencies/DependenciesFileParser.fs @@ -289,11 +289,11 @@ module DependenciesFileParser = if text = "auto-detect" then Some (ParserOptions (ParserOption.AutodetectFrameworkRestrictions)) else - let restrictions = Requirements.parseRestrictions true text - if String.IsNullOrWhiteSpace text |> not && List.isEmpty restrictions then + let restrictions = Requirements.parseRestrictionsLegacy true text + if String.IsNullOrWhiteSpace text |> not && restrictions = FrameworkRestriction.NoRestriction then failwithf "Could not parse framework restriction \"%s\"" text - let options = ParserOption.FrameworkRestrictions (FrameworkRestrictionList restrictions) + let options = ParserOption.FrameworkRestrictions (ExplicitRestriction restrictions) Some (ParserOptions options) | String.RemovePrefix "content" trimmed -> diff --git a/src/Paket.Core/Dependencies/NuGetV2.fs b/src/Paket.Core/Dependencies/NuGetV2.fs index f54f14da98..18bd4e6883 100644 --- a/src/Paket.Core/Dependencies/NuGetV2.fs +++ b/src/Paket.Core/Dependencies/NuGetV2.fs @@ -187,15 +187,16 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra (if a.Length > 2 && a.[2] <> "" then let restriction = a.[2] if String.startsWithIgnoreCase "portable" restriction then - Some [ yield FrameworkRestriction.Portable restriction ] + let fws = (PlatformMatching.extractPlatforms restriction).Platforms + Some (FrameworkRestriction.Portable (restriction, fws)) else match FrameworkDetection.Extract restriction with - | Some x -> Some [ FrameworkRestriction.Exactly x ] + | Some x -> Some (FrameworkRestriction.Exactly x) | None -> if verbose then verbosefn "Unable to parse framework restriction '%s' for package '%s' in package '%s'" restriction a.[0] (packageName.ToString()) None - else Some []) + else Some (FrameworkRestriction.NoRestriction)) dependencies |> fun s -> s.Split([| '|' |], System.StringSplitOptions.RemoveEmptyEntries) @@ -205,37 +206,39 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra | Some(restrictions) -> Some (name, version, restrictions) | None -> None) + //let expandedPackages = + // let isMatch (n',v',r') = + // r' + // |> List.exists (fun r -> + // match r with + // | FrameworkRestriction.Exactly(DotNetFramework _) -> true + // | FrameworkRestriction.Exactly(DotNetStandard _) -> true + // |_ -> false) + // + // packages + // |> Seq.collect (fun (n,v,r) -> + // match r with + // | [ FrameworkRestriction.Portable p ] -> + // [yield n,v,r + // let standardAliases = KnownTargetProfiles.portableStandards p + // for alias in standardAliases do + // let s = FrameworkRestriction.Exactly(DotNetStandard alias) + // let s2 = FrameworkRestriction.AtLeast(DotNetStandard alias) + // if packages |> Array.exists (fun (n,v,r) -> r |> List.exists (fun r -> r = s || r = s2)) |> not then + // yield n,v,[s2] + // + // if standardAliases = [] && not <| Array.exists isMatch packages then + // for p in p.Split([|'+'; '-'|]) do + // match FrameworkDetection.Extract p with + // | Some(DotNetFramework _ as r) -> + // yield n,v,[FrameworkRestriction.Exactly r] + // | Some(DotNetStandard _ as r) -> + // yield n,v,[FrameworkRestriction.Exactly r] + // | _ -> () ] + // | _ -> [n,v,r]) + // |> Seq.toList let expandedPackages = - let isMatch (n',v',r') = - r' - |> List.exists (fun r -> - match r with - | FrameworkRestriction.Exactly(DotNetFramework _) -> true - | FrameworkRestriction.Exactly(DotNetStandard _) -> true - |_ -> false) - - packages - |> Seq.collect (fun (n,v,r) -> - match r with - | [ FrameworkRestriction.Portable p ] -> - [yield n,v,r - let standardAliases = KnownTargetProfiles.portableStandards p - for alias in standardAliases do - let s = FrameworkRestriction.Exactly(DotNetStandard alias) - let s2 = FrameworkRestriction.AtLeast(DotNetStandard alias) - if packages |> Array.exists (fun (n,v,r) -> r |> List.exists (fun r -> r = s || r = s2)) |> not then - yield n,v,[s2] - - if standardAliases = [] && not <| Array.exists isMatch packages then - for p in p.Split([|'+'; '-'|]) do - match FrameworkDetection.Extract p with - | Some(DotNetFramework _ as r) -> - yield n,v,[FrameworkRestriction.Exactly r] - | Some(DotNetStandard _ as r) -> - yield n,v,[FrameworkRestriction.Exactly r] - | _ -> () ] - | _ -> [n,v,r]) - |> Seq.toList + packages |> Seq.toList let dependencies = Requirements.optimizeDependencies expandedPackages diff --git a/src/Paket.Core/Dependencies/NuGetV3.fs b/src/Paket.Core/Dependencies/NuGetV3.fs index ae20914dc3..e6f8224c19 100644 --- a/src/Paket.Core/Dependencies/NuGetV3.fs +++ b/src/Paket.Core/Dependencies/NuGetV3.fs @@ -244,8 +244,8 @@ let getPackageDetails (source:NugetV3Source) (packageName:PackageName) (version: |> Seq.map(fun (dep, targetFramework) -> let targetFramework = match targetFramework with - | null -> [] - | x -> Requirements.parseRestrictions false x + | null -> FrameworkRestriction.NoRestriction + | x -> Requirements.parseRestrictionsLegacy false x (PackageName dep.Id), (VersionRequirement.Parse dep.Range), targetFramework) |> Seq.toList let unlisted = diff --git a/src/Paket.Core/Dependencies/Nuspec.fs b/src/Paket.Core/Dependencies/Nuspec.fs index c181461c93..364c289ce9 100644 --- a/src/Paket.Core/Dependencies/Nuspec.fs +++ b/src/Paket.Core/Dependencies/Nuspec.fs @@ -34,25 +34,26 @@ module internal NuSpecParserHelper = | n , Some framework when String.equalsIgnoreCase n "group" -> let framework = framework.Replace(".NETPortable0.0","portable") if String.startsWithIgnoreCase "portable" framework then - Some(name,version,[FrameworkRestriction.Portable framework]) + let fws = (PlatformMatching.extractPlatforms framework).Platforms + Some(name,version,FrameworkRestriction.Portable (framework, fws)) else match FrameworkDetection.Extract framework with - | Some x -> Some(name,version,[FrameworkRestriction.Exactly x]) + | Some x -> Some(name,version,FrameworkRestriction.Exactly x) | None -> None - | _ -> Some(name,version,[]) + | _ -> Some(name,version,FrameworkRestriction.NoRestriction) let getAssemblyRefs node = let name = node |> getAttribute "assemblyName" let targetFrameworks = node |> getAttribute "targetFramework" match name,targetFrameworks with | Some name, Some targetFrameworks when targetFrameworks = "" -> - [{ AssemblyName = name; FrameworkRestrictions = FrameworkRestrictionList [] }] + [{ AssemblyName = name; FrameworkRestrictions = ExplicitRestriction FrameworkRestriction.NoRestriction }] | Some name, None -> - [{ AssemblyName = name; FrameworkRestrictions = FrameworkRestrictionList [] }] + [{ AssemblyName = name; FrameworkRestrictions = ExplicitRestriction FrameworkRestriction.NoRestriction }] | Some name, Some targetFrameworks -> targetFrameworks.Split([|','; ' '|],System.StringSplitOptions.RemoveEmptyEntries) |> Array.choose FrameworkDetection.Extract - |> Array.map (fun fw -> { AssemblyName = name; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly fw] }) + |> Array.map (fun fw -> { AssemblyName = name; FrameworkRestrictions = ExplicitRestriction (FrameworkRestriction.Exactly fw) }) |> Array.toList | _ -> [] @@ -82,48 +83,48 @@ type Nuspec = match node |> getAttribute "targetFramework" with | Some framework when framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable").StartsWith "portable" -> let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") + let fws = (PlatformMatching.extractPlatforms framework).Platforms [PackageName "", - VersionRequirement.NoRestriction, - [ yield FrameworkRestriction.Portable framework]] + VersionRequirement.NoRestriction, FrameworkRestriction.Portable (framework, fws)] | Some framework -> match FrameworkDetection.Extract framework with - | Some x -> [PackageName "",VersionRequirement.NoRestriction, [FrameworkRestriction.Exactly x]] + | Some x -> [PackageName "",VersionRequirement.NoRestriction, FrameworkRestriction.Exactly x] | None -> [] | _ -> []) |> List.concat - let framworks = - let isMatch (n',v',r') = - r' - |> List.exists (fun r -> - match r with - | FrameworkRestriction.Exactly(DotNetFramework _) -> true - | FrameworkRestriction.Exactly(DotNetStandard _) -> true - |_ -> false) - - frameworks - |> Seq.collect (fun (n,v,r) -> - match r with - | [ FrameworkRestriction.Portable p ] -> - [ yield n,v,r - let standardAliases = KnownTargetProfiles.portableStandards p - for alias in standardAliases do - let s = FrameworkRestriction.Exactly(DotNetStandard alias) - let s2 = FrameworkRestriction.AtLeast(DotNetStandard alias) - if frameworks |> List.exists (fun (n,v,r) -> r |> List.exists (fun r -> r = s || r = s2)) |> not then - yield n,v,[s2] - - if standardAliases = [] && not <| List.exists isMatch frameworks then - for p in p.Split([|'+'; '-'|]) do - match FrameworkDetection.Extract p with - | Some(DotNetFramework _ as r) -> - yield n,v,[FrameworkRestriction.Exactly r] - | Some(DotNetStandard _ as r) -> - yield n,v,[FrameworkRestriction.Exactly r] - | _ -> () ] - | _ -> [n,v,r]) - |> Seq.toList + //let framworks = + // let isMatch (n',v',r') = + // r' + // |> List.exists (fun r -> + // match r with + // | FrameworkRestriction.Exactly(DotNetFramework _) -> true + // | FrameworkRestriction.Exactly(DotNetStandard _) -> true + // |_ -> false) + // + // frameworks + // |> Seq.collect (fun (n,v,r) -> + // match r with + // | [ FrameworkRestriction.Portable p ] -> + // [ yield n,v,r + // let standardAliases = KnownTargetProfiles.portableStandards p + // for alias in standardAliases do + // let s = FrameworkRestriction.Exactly(DotNetStandard alias) + // let s2 = FrameworkRestriction.AtLeast(DotNetStandard alias) + // if frameworks |> List.exists (fun (n,v,r) -> r |> List.exists (fun r -> r = s || r = s2)) |> not then + // yield n,v,[s2] + // + // if standardAliases = [] && not <| List.exists isMatch frameworks then + // for p in p.Split([|'+'; '-'|]) do + // match FrameworkDetection.Extract p with + // | Some(DotNetFramework _ as r) -> + // yield n,v,[FrameworkRestriction.Exactly r] + // | Some(DotNetStandard _ as r) -> + // yield n,v,[FrameworkRestriction.Exactly r] + // | _ -> () ] + // | _ -> [n,v,r]) + // |> Seq.toList let depsTags = doc @@ -168,7 +169,11 @@ type Nuspec = [for name,restrictions in grouped do yield { AssemblyName = name - FrameworkRestrictions = FrameworkRestrictionList(List.collect (fun x -> x.FrameworkRestrictions |> getRestrictionList) restrictions) } ] } + FrameworkRestrictions = + ExplicitRestriction( + restrictions + |> List.map (fun x -> x.FrameworkRestrictions |> getExplicitRestriction) + |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet) } ] } /// load the file from an nuspec text stream. The fileName is only used for error reporting. static member internal Load(fileName:string, f:Stream) = diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 752570ce6b..d40b61b473 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -37,7 +37,7 @@ type ResolvedPackage = { override this.ToString () = sprintf "%O %O" this.Name this.Version member self.HasFrameworkRestrictions = - not (getRestrictionList self.Settings.FrameworkRestrictions = []) + getExplicitRestriction self.Settings.FrameworkRestrictions <> FrameworkRestriction.NoRestriction member private self.Display with get() = @@ -54,47 +54,51 @@ type PackageResolution = Map module DependencySetFilter = let isIncluded (restriction:FrameworkRestriction) (dependency:PackageName * VersionRequirement * FrameworkRestrictions) = - let _,_,restrictions = dependency - let restrictions = restrictions |> getRestrictionList - if Seq.isEmpty restrictions then true else + let _,_,dependencyRestrictions = dependency + let dependencyRestrictions = dependencyRestrictions |> getExplicitRestriction + if dependencyRestrictions = FrameworkRestriction.NoRestriction then true else // TODO: fix broken logic - match restriction with - | FrameworkRestriction.Exactly v1 -> - restrictions - |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) - |> Seq.exists (fun r2 -> - match r2 with - | FrameworkRestriction.Exactly v2 when v1 = v2 -> true - | FrameworkRestriction.AtLeast v2 when v1 >= v2 -> true - | FrameworkRestriction.Between(v2,v3) when v1 >= v2 && v1 < v3 -> true - | _ -> false) - | FrameworkRestriction.AtLeast v1 -> - restrictions - |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) - |> Seq.exists (fun r2 -> - match r2 with - | FrameworkRestriction.Exactly v2 when v1 <= v2 -> true - | FrameworkRestriction.AtLeast v2 -> true - | FrameworkRestriction.Between(v2,v3) when v1 < v3 -> true - | _ -> false) - | FrameworkRestriction.Between (min, max) -> - restrictions - |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) - |> Seq.exists (fun r2 -> - match r2 with - | FrameworkRestriction.Exactly v when v >= min && v < max -> true - | FrameworkRestriction.AtLeast v when v < max -> true - | FrameworkRestriction.Between(min',max') when max' >= min && min' < max -> true - | _ -> false) - | _ -> true + + // This is the framework restriction we build for (example = net46) + // While the dependency specifies the framework restrictions of the dependency ([ >= netstandard13 ]) + // we need to take the dependency, when 'restriction' is a subset of any of 'dependencyRestrictions' + restriction.IsSubsetOf dependencyRestrictions + //match restriction with + //| FrameworkRestriction.Exactly v1 -> + // dependencyRestrictions + // |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) + // |> Seq.exists (fun r2 -> + // match r2 with + // | FrameworkRestriction.Exactly v2 when v1 = v2 -> true + // | FrameworkRestriction.AtLeast v2 when v1 >= v2 -> true + // | FrameworkRestriction.Between(v2,v3) when v1 >= v2 && v1 < v3 -> true + // | _ -> false) + //| FrameworkRestriction.AtLeast v1 -> + // restrictions + // |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) + // |> Seq.exists (fun r2 -> + // match r2 with + // | FrameworkRestriction.Exactly v2 when v1 <= v2 -> true + // | FrameworkRestriction.AtLeast v2 -> true + // | FrameworkRestriction.Between(v2,v3) when v1 < v3 -> true + // | _ -> false) + //| FrameworkRestriction.Between (min, max) -> + // restrictions + // |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) + // |> Seq.exists (fun r2 -> + // match r2 with + // | FrameworkRestriction.Exactly v when v >= min && v < max -> true + // | FrameworkRestriction.AtLeast v when v < max -> true + // | FrameworkRestriction.Between(min',max') when max' >= min && min' < max -> true + // | _ -> false) + //| _ -> true let filterByRestrictions (restrictions:FrameworkRestrictions) (dependencies:DependencySet) : DependencySet = - match getRestrictionList restrictions with - | [] -> dependencies + match getExplicitRestriction restrictions with + | FrameworkRestriction.NoRestriction -> dependencies | restrictions -> dependencies - |> Set.filter (fun dependency -> - restrictions |> List.exists (fun r -> isIncluded r dependency)) + |> Set.filter (isIncluded restrictions) let isPackageCompatible (dependencies:DependencySet) (package:ResolvedPackage) : bool = dependencies @@ -255,11 +259,11 @@ let calcOpenRequirements (exploredPackage:ResolvedPackage,globalFrameworkRestric | VersionRequirement(ra1,p1),VersionRequirement(ra2,p2) when p1 = p2 -> let newRestrictions = match r with - | FrameworkRestrictionList r -> + | ExplicitRestriction r -> match r2 with - | FrameworkRestrictionList r2 -> - FrameworkRestrictionList (r @ r2) - | AutoDetectFramework -> FrameworkRestrictionList r + | ExplicitRestriction r2 -> + combineRestrictionsWithOr r r2 |> ExplicitRestriction + | AutoDetectFramework -> ExplicitRestriction r | AutoDetectFramework -> r if ra1.IsIncludedIn ra2 then @@ -282,7 +286,7 @@ let calcOpenRequirements (exploredPackage:ResolvedPackage,globalFrameworkRestric let newRestrictions = filterRestrictions restriction exploredPackage.Settings.FrameworkRestrictions |> filterRestrictions globalFrameworkRestrictions - |> fun xs -> if xs = FrameworkRestrictionList [] then exploredPackage.Settings.FrameworkRestrictions else xs + |> fun xs -> if xs = ExplicitRestriction FrameworkRestriction.NoRestriction then exploredPackage.Settings.FrameworkRestrictions else xs { dependency with Name = n @@ -343,27 +347,29 @@ type private PackageConfig = { UpdateMode : UpdateMode } with member self.HasGlobalRestrictions = - not(getRestrictionList self.GlobalRestrictions = []) + not(getExplicitRestriction self.GlobalRestrictions = FrameworkRestriction.NoRestriction) member self.HasDependencyRestrictions = - not(getRestrictionList self.Dependency.Settings.FrameworkRestrictions = []) + not(getExplicitRestriction self.Dependency.Settings.FrameworkRestrictions = FrameworkRestriction.NoRestriction) let private updateRestrictions (pkgConfig:PackageConfig) (package:ResolvedPackage) = let newRestrictions = if not pkgConfig.HasGlobalRestrictions - && (List.isEmpty (package.Settings.FrameworkRestrictions |> getRestrictionList) + && (FrameworkRestriction.NoRestriction = (package.Settings.FrameworkRestrictions |> getExplicitRestriction) || not pkgConfig.HasDependencyRestrictions ) then - [] + FrameworkRestriction.NoRestriction else - let packageSettings = package.Settings.FrameworkRestrictions |> getRestrictionList - let dependencySettings = pkgConfig.Dependency.Settings.FrameworkRestrictions |> getRestrictionList - let globalSettings = pkgConfig.GlobalRestrictions |> getRestrictionList - optimizeRestrictions (List.concat[packageSettings;dependencySettings;globalSettings]) + let packageSettings = package.Settings.FrameworkRestrictions |> getExplicitRestriction + let dependencySettings = pkgConfig.Dependency.Settings.FrameworkRestrictions |> getExplicitRestriction + let globalSettings = pkgConfig.GlobalRestrictions |> getExplicitRestriction + [packageSettings;dependencySettings;globalSettings] + |> Seq.fold (combineRestrictionsWithAnd) FrameworkRestriction.NoRestriction + //optimizeRestrictions (List.concat) { package with - Settings = { package.Settings with FrameworkRestrictions = FrameworkRestrictionList newRestrictions } + Settings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } } diff --git a/src/Paket.Core/Installation/RestoreProcess.fs b/src/Paket.Core/Installation/RestoreProcess.fs index 77ee846b85..9c55adde27 100644 --- a/src/Paket.Core/Installation/RestoreProcess.fs +++ b/src/Paket.Core/Installation/RestoreProcess.fs @@ -166,7 +166,7 @@ let CreateInstallModel(alternativeProjectRoot, root, groupName, sources, caches, let! (package, files, targetsFiles, analyzerFiles) = ExtractPackage(alternativeProjectRoot, root, groupName, sources, caches, force, package, false) let nuspec = Nuspec.Load(root,groupName,package.Version,defaultArg package.Settings.IncludeVersionInPath false,package.Name) let targetsFiles = targetsFiles |> Array.toList - let model = InstallModel.CreateFromLibs(package.Name, package.Version, package.Settings.FrameworkRestrictions |> Requirements.getRestrictionList, files, targetsFiles, analyzerFiles, nuspec) + let model = InstallModel.CreateFromLibs(package.Name, package.Version, package.Settings.FrameworkRestrictions |> Requirements.getExplicitRestriction, files, targetsFiles, analyzerFiles, nuspec) return (groupName,package.Name), (package,model) } @@ -276,7 +276,7 @@ let Restore(dependenciesFileName,projectFile,force,group,referencesFileNames,ign let resolvedPackage = resolved.Force().[key] match resolvedPackage.Settings.FrameworkRestrictions with - | Requirements.FrameworkRestrictionList restrictions -> + | Requirements.ExplicitRestriction restrictions -> Requirements.isTargetMatchingRestrictions(restrictions, SinglePlatform target) | _ -> true @@ -324,7 +324,7 @@ let Restore(dependenciesFileName,projectFile,force,group,referencesFileNames,ign let resolvedPackage = resolved.Force().[key] match resolvedPackage.Settings.FrameworkRestrictions with - | Requirements.FrameworkRestrictionList restrictions -> + | Requirements.ExplicitRestriction restrictions -> Requirements.isTargetMatchingRestrictions(restrictions, SinglePlatform target) | _ -> true) diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs index 60b58bae94..ce87883c7d 100644 --- a/src/Paket.Core/Installation/UpdateProcess.fs +++ b/src/Paket.Core/Installation/UpdateProcess.fs @@ -165,19 +165,22 @@ let detectProjectFrameworksForDependenciesFile (dependenciesFile:DependenciesFil let root = Path.GetDirectoryName dependenciesFile.FileName let groups = let targetFrameworks = lazy ( - RestoreProcess.findAllReferencesFiles root |> returnOrFail - |> List.map (fun (p,_) -> - match p.GetTargetFramework() with - | Some fw -> Requirements.FrameworkRestriction.Exactly fw - | None -> failwithf "Could not detect target framework for project %s" p.FileName) - |> List.distinct) + let rawRestrictions = + RestoreProcess.findAllReferencesFiles root |> returnOrFail + |> List.map (fun (p,_) -> + match p.GetTargetFramework() with + | Some fw -> Requirements.FrameworkRestriction.Exactly fw + | None -> failwithf "Could not detect target framework for project %s" p.FileName) + |> List.distinct + if rawRestrictions.IsEmpty then Paket.Requirements.FrameworkRestriction.NoRestriction + else rawRestrictions |> Seq.fold Paket.Requirements.combineRestrictionsWithOr Paket.Requirements.FrameworkRestriction.EmptySet) dependenciesFile.Groups |> Map.map (fun groupName group -> let restrictions = match group.Options.Settings.FrameworkRestrictions with | Requirements.FrameworkRestrictions.AutoDetectFramework -> - Requirements.FrameworkRestrictions.FrameworkRestrictionList (targetFrameworks.Force()) + Requirements.FrameworkRestrictions.ExplicitRestriction (targetFrameworks.Force()) | x -> x let settings = { group.Options.Settings with FrameworkRestrictions = restrictions } diff --git a/src/Paket.Core/PackageAnalysis/Queries.fs b/src/Paket.Core/PackageAnalysis/Queries.fs index 9243513569..4fc7c0ef9e 100644 --- a/src/Paket.Core/PackageAnalysis/Queries.fs +++ b/src/Paket.Core/PackageAnalysis/Queries.fs @@ -32,7 +32,7 @@ let getInstalledPackageModel (lockFile: LockFile) (QualifiedPackageName(groupNam let nuspec = FileInfo(sprintf "%s/packages%s/%O/%O.nuspec" lockFile.RootPath groupFolder packageName packageName) let nuspec = Nuspec.Load nuspec.FullName let files = NuGetV2.GetLibFiles(folder.FullName) - InstallModel.CreateFromLibs(packageName, resolvedPackage.Version, [], files, [], [], nuspec) + InstallModel.CreateFromLibs(packageName, resolvedPackage.Version, Paket.Requirements.FrameworkRestriction.NoRestriction, files, [], [], nuspec) let getRuntimeGraph (lockFile: LockFile) (groupName:GroupName) = lockFile.Groups @@ -66,14 +66,14 @@ let resolveFrameworkForScriptGeneration (dependencies: DependenciesFile) = lazy |> Seq.map(fun restrictions -> match restrictions with | Paket.Requirements.AutoDetectFramework -> failwithf "couldn't detect framework" - | Paket.Requirements.FrameworkRestrictionList list -> - list |> Seq.collect ( - function - | Paket.Requirements.FrameworkRestriction.Exactly framework - | Paket.Requirements.FrameworkRestriction.AtLeast framework -> Seq.singleton framework - | Paket.Requirements.FrameworkRestriction.Between (bottom,top) -> [bottom; top] |> Seq.ofList //TODO: do we need to cap the list of generated frameworks based on this? also see todo in Requirements.fs for potential generation of range for 'between' - | Paket.Requirements.FrameworkRestriction.Portable portable -> failwithf "unhandled portable framework %s" portable - ) + | Paket.Requirements.ExplicitRestriction list -> list.RepresentedFrameworks + //list |> Seq.collect ( + // function + // | Paket.Requirements.FrameworkRestriction.Exactly framework + // | Paket.Requirements.FrameworkRestriction.AtLeast framework -> Seq.singleton framework + // | Paket.Requirements.FrameworkRestriction.Between (bottom,top) -> [bottom; top] |> Seq.ofList //TODO: do we need to cap the list of generated frameworks based on this? also see todo in Requirements.fs for potential generation of range for 'between' + // | Paket.Requirements.FrameworkRestriction.Portable portable -> failwithf "unhandled portable framework %s" portable + //) ) |> Seq.concat ) diff --git a/src/Paket.Core/PackageAnalysis/Why.fs b/src/Paket.Core/PackageAnalysis/Why.fs index ce95929375..4ae2e77da6 100644 --- a/src/Paket.Core/PackageAnalysis/Why.fs +++ b/src/Paket.Core/PackageAnalysis/Why.fs @@ -64,13 +64,8 @@ module DependencyChain = let formatFxReq (fr : FrameworkRestrictions) = match fr with | AutoDetectFramework - | FrameworkRestrictionList [] -> "" - | FrameworkRestrictionList [fx] -> sprintf " (%O)" fx - | FrameworkRestrictionList fxs -> - fxs - |> List.map string - |> String.concat "," - |> sprintf " (%s)" + | ExplicitRestriction Paket.Requirements.FrameworkRestriction.NoRestriction -> "" + | ExplicitRestriction fr -> sprintf " (%O)" fr let formatName name i = sprintf "%s-> %O" (String.replicate i " ") name let rec format' i (name,chain) = let rest = diff --git a/src/Paket.Core/PackageManagement/NugetConvert.fs b/src/Paket.Core/PackageManagement/NugetConvert.fs index 737c000c51..031968655a 100644 --- a/src/Paket.Core/PackageManagement/NugetConvert.fs +++ b/src/Paket.Core/PackageManagement/NugetConvert.fs @@ -259,20 +259,23 @@ let createDependenciesFileR (rootDirectory : DirectoryInfo) nugetEnv mode = let latestVersion, _ = versions |> List.maxBy fst let restrictions = match versions with - | [ version, targetFramework ] -> targetFramework |> Option.toList |> List.collect (Requirements.parseRestrictions false) + | [ version, targetFramework ] -> targetFramework |> Option.toList |> List.map (Requirements.parseRestrictionsLegacy false) | _ -> [] + let restrictions = + if restrictions = [] then FrameworkRestriction.NoRestriction + else restrictions |> Seq.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet name, latestVersion, restrictions) let packages = match nugetEnv.NuGetExe with - | Some _ -> ("NuGet.CommandLine",VersionRange.AtLeast "0",[]) :: latestVersions + | Some _ -> ("NuGet.CommandLine",VersionRange.AtLeast "0",FrameworkRestriction.NoRestriction) :: latestVersions | _ -> latestVersions let read() = let addPackages dependenciesFile = packages |> List.map (fun (name, vr, restrictions) -> - Constants.MainDependencyGroup, PackageName name, vr, { InstallSettings.Default with FrameworkRestrictions = FrameworkRestrictionList restrictions}) + Constants.MainDependencyGroup, PackageName name, vr, { InstallSettings.Default with FrameworkRestrictions = ExplicitRestriction restrictions}) |> List.fold (fun (dependenciesFile:DependenciesFile) (groupName, packageName,versionRange,installSettings) -> dependenciesFile.Add(groupName, packageName,versionRange,installSettings)) dependenciesFile try @@ -305,7 +308,7 @@ let createDependenciesFileR (rootDirectory : DirectoryInfo) nugetEnv mode = let packageLines = packages |> List.map (fun (name,vr,restr) -> - let vr = createPackageRequirement sources (name, vr, FrameworkRestrictionList restr) dependenciesFileName + let vr = createPackageRequirement sources (name, vr, ExplicitRestriction restr) dependenciesFileName DependenciesFileSerializer.packageString vr.Name vr.VersionRequirement vr.ResolverStrategyForTransitives vr.Settings) let newLines = sourceLines @ [""] @ packageLines |> Seq.toArray diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index 80b7e16c8f..b30fe2dc31 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -143,35 +143,38 @@ type DependenciesFile(fileName,groups:Map, textRepr let dir = (lockFile : FileInfo).DirectoryName let projects = ProjectFile.FindAllProjects dir let frameworks = projects |> Array.choose ProjectFile.getTargetFramework |> Array.distinct - frameworks |> Array.map FrameworkRestriction.Exactly |> List.ofArray + let restrictions = frameworks |> Array.map FrameworkRestriction.Exactly + if restrictions |> Array.isEmpty then FrameworkRestriction.NoRestriction + else restrictions |> Array.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet ) fun restrictions -> match restrictions with - | FrameworkRestrictionList l -> l + | ExplicitRestriction l -> l | AutoDetectFramework -> projectFrameworks.Force() - if group.Options.Settings.FrameworkRestrictions |> getRestrictionList <> [] then dependenciesFile else + if group.Options.Settings.FrameworkRestrictions |> getRestrictionList <> FrameworkRestriction.NoRestriction then dependenciesFile else match group.Packages with | [] -> dependenciesFile - | package::rest -> - let commonRestrictions = - package.Settings.FrameworkRestrictions - |> getRestrictionList - |> List.filter (fun r -> rest |> Seq.forall (fun p' -> p'.Settings.FrameworkRestrictions |> getRestrictionList |> List.contains r)) - - match commonRestrictions with - | [] -> dependenciesFile - | _ -> - let newDependenciesFile = dependenciesFile.AddFrameworkRestriction(group.Name,commonRestrictions) - group.Packages - |> List.fold (fun (d:DependenciesFile) package -> - let oldRestrictions = package.Settings.FrameworkRestrictions |> getRestrictionList - let newRestrictions = oldRestrictions |> List.filter (fun r -> commonRestrictions |> List.contains r |> not) - if oldRestrictions = newRestrictions then d else - let (d:DependenciesFile) = d.Remove(group.Name,package.Name) - let installSettings = { package.Settings with FrameworkRestrictions = FrameworkRestrictionList newRestrictions } - let vr = { VersionRequirement = package.VersionRequirement; ResolverStrategy = package.ResolverStrategyForDirectDependencies } - d.AddAdditionalPackage(group.Name, package.Name,vr,installSettings)) newDependenciesFile + | package::rest -> dependenciesFile + //let commonRestrictions = + // package.Settings.FrameworkRestrictions + // |> getRestrictionList + // |> List.filter (fun r -> + // rest |> Seq.forall (fun p' -> p'.Settings.FrameworkRestrictions |> getRestrictionList |> List.contains r)) + // + //match commonRestrictions with + //| [] -> dependenciesFile + //| _ -> + // let newDependenciesFile = dependenciesFile.AddFrameworkRestriction(group.Name,commonRestrictions) + // group.Packages + // |> List.fold (fun (d:DependenciesFile) package -> + // let oldRestrictions = package.Settings.FrameworkRestrictions |> getRestrictionList + // let newRestrictions = oldRestrictions |> List.filter (fun r -> commonRestrictions |> List.contains r |> not) + // if oldRestrictions = newRestrictions then d else + // let (d:DependenciesFile) = d.Remove(group.Name,package.Name) + // let installSettings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } + // let vr = { VersionRequirement = package.VersionRequirement; ResolverStrategy = package.ResolverStrategyForDirectDependencies } + // d.AddAdditionalPackage(group.Name, package.Name,vr,installSettings)) newDependenciesFile this.Groups |> Seq.map (fun kv -> kv.Value) @@ -301,10 +304,10 @@ type DependenciesFile(fileName,groups:Map, textRepr if Environment.GetEnvironmentVariable "PAKET_DEBUG_RUNTIME_DEPS" = "true" then tracefn "Runtime dependencies: " - let runtimeDepsFile = DependenciesFile.FromSource "" - let runtimeDepsFile = runtimeDepsFile.AddFrameworkRestriction(Constants.MainDependencyGroup, getRestrictionList group.Options.Settings.FrameworkRestrictions) - let runtimeDepsFile = runtimeDepsFile.AddResolverStrategyForTransitives(Constants.MainDependencyGroup, group.Options.ResolverStrategyForTransitives) - let runtimeDepsFile = (runtimeDepsFile:DependenciesFile).AddResolverStrategyForDirectDependencies(Constants.MainDependencyGroup, group.Options.ResolverStrategyForDirectDependencies) + let (runtimeDepsFile:DependenciesFile) = DependenciesFile.FromSource "" + let (runtimeDepsFile:DependenciesFile) = runtimeDepsFile.AddFrameworkRestriction(Constants.MainDependencyGroup, getExplicitRestriction group.Options.Settings.FrameworkRestrictions) + let (runtimeDepsFile:DependenciesFile) = runtimeDepsFile.AddResolverStrategyForTransitives(Constants.MainDependencyGroup, group.Options.ResolverStrategyForTransitives) + let (runtimeDepsFile:DependenciesFile) = runtimeDepsFile.AddResolverStrategyForDirectDependencies(Constants.MainDependencyGroup, group.Options.ResolverStrategyForDirectDependencies) let runtimeDepsFile = runtimeResolutionDeps |> Seq.fold (fun (deps:DependenciesFile) dep -> deps.AddAdditionalPackage(Constants.MainDependencyGroup, dep.Name, dep.VersionRequirement, dep.ResolverStrategyForTransitives, dep.Settings)) runtimeDepsFile @@ -348,9 +351,9 @@ type DependenciesFile(fileName,groups:Map, textRepr |> Map.map resolveGroup - member private this.AddFrameworkRestriction(groupName, frameworkRestrictions:FrameworkRestriction list) = - if List.isEmpty frameworkRestrictions then this else - let restrictionString = sprintf "framework %s" (String.Join(", ",frameworkRestrictions)) + member private this.AddFrameworkRestriction(groupName, frameworkRestriction:FrameworkRestriction) = + if frameworkRestriction = FrameworkRestriction.NoRestriction then this else + let restrictionString = sprintf "restriction: %O" frameworkRestriction let list = new System.Collections.Generic.List<_>() list.AddRange textRepresentation @@ -689,13 +692,13 @@ type DependenciesFile(fileName,groups:Map, textRepr |> Seq.map(fun restrictions -> match restrictions with | Paket.Requirements.AutoDetectFramework -> failwithf "couldn't detect framework" - | Paket.Requirements.FrameworkRestrictionList list -> - list |> Seq.collect (function - | Paket.Requirements.FrameworkRestriction.Exactly framework - | Paket.Requirements.FrameworkRestriction.AtLeast framework -> Seq.singleton framework - | Paket.Requirements.FrameworkRestriction.Between (bottom,top) -> [bottom; top] |> Seq.ofList //TODO: do we need to cap the list of generated frameworks based on this? also see todo in Requirements.fs for potential generation of range for 'between' - | Paket.Requirements.FrameworkRestriction.Portable portable -> failwithf "unhandled portable framework %s" portable - ) + | Paket.Requirements.ExplicitRestriction list -> list.RepresentedFrameworks + //list |> Seq.collect (function + //| Paket.Requirements.FrameworkRestriction.Exactly framework + //| Paket.Requirements.FrameworkRestriction.AtLeast framework -> Seq.singleton framework + //| Paket.Requirements.FrameworkRestriction.Between (bottom,top) -> [bottom; top] |> Seq.ofList //TODO: do we need to cap the list of generated frameworks based on this? also see todo in Requirements.fs for potential generation of range for 'between' + //| Paket.Requirements.FrameworkRestriction.Portable portable -> failwithf "unhandled portable framework %s" portable + //) ) |> Seq.concat ) diff --git a/src/Paket.Core/PaketConfigFiles/DependencyCache.fs b/src/Paket.Core/PaketConfigFiles/DependencyCache.fs index 5d8703bfe2..bcba372089 100644 --- a/src/Paket.Core/PaketConfigFiles/DependencyCache.fs +++ b/src/Paket.Core/PaketConfigFiles/DependencyCache.fs @@ -202,7 +202,7 @@ type DependencyCache (dependencyFile:DependenciesFile, lockFile:LockFile) = let nuspec = Nuspec.Load nuspec.FullName nuspecCache.TryAdd((package.Name,package.Version),nuspec)|>ignore let files = NuGetV2.GetLibFiles(folder.FullName) - let model = InstallModel.CreateFromLibs(packageName, package.Version, [], files, [], [], nuspec) + let model = InstallModel.CreateFromLibs(packageName, package.Version, Paket.Requirements.FrameworkRestriction.NoRestriction, files, [], [], nuspec) installModelCache.TryAdd((groupName,package.Name) , model) |> ignore }) |> Array.ofSeq Async.Parallel exprs diff --git a/src/Paket.Core/PaketConfigFiles/InstallModel.fs b/src/Paket.Core/PaketConfigFiles/InstallModel.fs index dba3d05ffd..815983e3b7 100644 --- a/src/Paket.Core/PaketConfigFiles/InstallModel.fs +++ b/src/Paket.Core/PaketConfigFiles/InstallModel.fs @@ -671,27 +671,30 @@ module InstallModel = let addFrameworkAssemblyReference (installModel:InstallModel) (reference:FrameworkAssemblyReference) : InstallModel = let referenceApplies (folder : FrameworkFolder<_>) = - match reference.FrameworkRestrictions |> getRestrictionList with - | [] -> true - | restrictions -> - restrictions - |> List.exists (fun restriction -> - match restriction with - | FrameworkRestriction.Portable _ -> - folder.Targets - |> List.exists (fun target -> - match target with - | SinglePlatform _ -> false - | _ -> true) - | FrameworkRestriction.Exactly target -> - folder.GetSinglePlatforms() - |> List.exists ((=) target) - | FrameworkRestriction.AtLeast target -> - folder.GetSinglePlatforms() - |> List.exists (fun t -> t >= target && t.IsSameCategoryAs(target)) - | FrameworkRestriction.Between(min,max) -> - folder.GetSinglePlatforms() - |> List.exists (fun t -> t >= min && t < max && t.IsSameCategoryAs(min))) + applyRestrictionsToTargets (reference.FrameworkRestrictions |> getExplicitRestriction) folder.Targets + |> Seq.isEmpty + |> not + //match reference.FrameworkRestrictions |> getRestrictionList with + //| [] -> true + //| restrictions -> + // restrictions + // |> List.exists (fun restriction -> + // match restriction with + // | FrameworkRestriction.Portable _ -> + // folder.Targets + // |> List.exists (fun target -> + // match target with + // | SinglePlatform _ -> false + // | _ -> true) + // | FrameworkRestriction.Exactly target -> + // folder.GetSinglePlatforms() + // |> List.exists ((=) target) + // | FrameworkRestriction.AtLeast target -> + // folder.GetSinglePlatforms() + // |> List.exists (fun t -> t >= target && t.IsSameCategoryAs(target)) + // | FrameworkRestriction.Between(min,max) -> + // folder.GetSinglePlatforms() + // |> List.exists (fun t -> t >= min && t < max && t.IsSameCategoryAs(min))) let model = if List.isEmpty installModel.CompileLibFolders then @@ -733,12 +736,12 @@ module InstallModel = let targetsFile = t.Path (String.endsWithIgnoreCase ".props" targetsFile|| String.endsWithIgnoreCase ".targets" targetsFile))) - let applyFrameworkRestrictions (restrictions:FrameworkRestriction list) (installModel:InstallModel) = - match restrictions with - | [] -> installModel - | restrictions -> + let applyFrameworkRestrictions (restriction:FrameworkRestriction) (installModel:InstallModel) = + match restriction with + | FrameworkRestriction.NoRestriction -> installModel + | restriction -> let applyRestriction folder = - { folder with Targets = applyRestrictionsToTargets restrictions folder.Targets} + { folder with Targets = applyRestrictionsToTargets restriction folder.Targets} { installModel with CompileLibFolders = @@ -869,5 +872,5 @@ type InstallModel with member this.RemoveIfCompletelyEmpty() = InstallModel.removeIfCompletelyEmpty this - static member CreateFromLibs(packageName, packageVersion, frameworkRestrictions:FrameworkRestriction list, libs : UnparsedPackageFile seq, targetsFiles, analyzerFiles, nuspec : Nuspec) = - InstallModel.createFromLibs packageName packageVersion frameworkRestrictions libs targetsFiles analyzerFiles nuspec \ No newline at end of file + static member CreateFromLibs(packageName, packageVersion, frameworkRestriction:FrameworkRestriction, libs : UnparsedPackageFile seq, targetsFiles, analyzerFiles, nuspec : Nuspec) = + InstallModel.createFromLibs packageName packageVersion frameworkRestriction libs targetsFiles analyzerFiles nuspec \ No newline at end of file diff --git a/src/Paket.Core/PaketConfigFiles/LockFile.fs b/src/Paket.Core/PaketConfigFiles/LockFile.fs index 1ddc8856d6..d9572d0af2 100644 --- a/src/Paket.Core/PaketConfigFiles/LockFile.fs +++ b/src/Paket.Core/PaketConfigFiles/LockFile.fs @@ -62,9 +62,9 @@ module LockFileSerializer = | Some condition -> yield "CONDITION: " + condition.ToUpper() | None -> () - match options.Settings.FrameworkRestrictions |> getRestrictionList with - | [] -> () - | list -> yield "FRAMEWORK: " + (String.Join(", ",list)).ToUpper()] + match options.Settings.FrameworkRestrictions |> getExplicitRestriction with + | FrameworkRestriction.NoRestriction -> () + | list -> yield "RESTRICTION: " + list.ToString() ] /// [omit] let serializePackages options (resolved : PackageResolution) = @@ -104,7 +104,7 @@ module LockFileSerializer = let settings = if package.Settings.FrameworkRestrictions = options.Settings.FrameworkRestrictions then - { package.Settings with FrameworkRestrictions = FrameworkRestrictionList [] } + { package.Settings with FrameworkRestrictions = ExplicitRestriction FrameworkRestriction.NoRestriction } else package.Settings let s = @@ -124,8 +124,8 @@ module LockFileSerializer = let s = v.ToString() if s = "" then s else "(" + s + ")" - let restrictions = filterRestrictions options.Settings.FrameworkRestrictions restrictions |> getRestrictionList - if List.isEmpty restrictions || restrictions = getRestrictionList options.Settings.FrameworkRestrictions then + let restrictions = filterRestrictions options.Settings.FrameworkRestrictions restrictions |> getExplicitRestriction + if FrameworkRestriction.NoRestriction = restrictions || restrictions = getExplicitRestriction options.Settings.FrameworkRestrictions then yield sprintf " %O %s" name versionStr else yield sprintf " %O %s - framework: %s" name versionStr (String.Join(", ",restrictions).ToLower())] @@ -280,7 +280,9 @@ module LockFileParser = | x -> failwithf "Unknown copy_content_to_output_dir settings: %A" x InstallOption (CopyContentToOutputDir setting) - | _, String.RemovePrefix "FRAMEWORK:" trimmed -> InstallOption(FrameworkRestrictions(FrameworkRestrictionList (trimmed.Trim() |> Requirements.parseRestrictions true))) + | _, String.RemovePrefix "FRAMEWORK:" trimmed -> InstallOption(FrameworkRestrictions(ExplicitRestriction (trimmed.Trim() |> Requirements.parseRestrictionsLegacy true))) + // TODO: use new parser here. + | _, String.RemovePrefix "RESTRICTION:" trimmed -> InstallOption(FrameworkRestrictions(ExplicitRestriction (trimmed.Trim() |> Requirements.parseRestrictionsLegacy true))) | _, String.RemovePrefix "CONDITION:" trimmed -> InstallOption(ReferenceCondition(trimmed.Trim().ToUpper())) | _, String.RemovePrefix "CONTENT:" trimmed -> let setting = @@ -891,7 +893,7 @@ type LockFile (fileName:string, groups: Map) = let nuspec = FileInfo(sprintf "%s/packages%s/%O/%O.nuspec" this.RootPath groupFolder packageName packageName) let nuspec = Nuspec.Load nuspec.FullName let files = NuGetV2.GetLibFiles(folder.FullName) - InstallModel.CreateFromLibs(packageName, resolvedPackage.Version, [], files, [], [], nuspec) + InstallModel.CreateFromLibs(packageName, resolvedPackage.Version, FrameworkRestriction.NoRestriction, files, [], [], nuspec) /// Returns a list of packages inside the lockfile with their group and version number diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs index d2215a4bf9..fb31105cd0 100644 --- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs @@ -737,7 +737,8 @@ module ProjectFile = let netCoreRestricted = model.ApplyFrameworkRestrictions ((List.map DotNetCore KnownTargetProfiles.DotNetCoreVersions @ List.map DotNetStandard KnownTargetProfiles.DotNetStandardVersions) - |> List.map FrameworkRestriction.Exactly) + |> List.map FrameworkRestriction.Exactly + |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet) // handle legacy conditions let conditions = @@ -1041,7 +1042,7 @@ module ProjectFile = |> Seq.map (fun kv -> deleteCustomModelNodes (snd kv.Value) project let installSettings = snd usedPackages.[kv.Key] - let restrictionList = installSettings.FrameworkRestrictions |> getRestrictionList + let restrictionList = installSettings.FrameworkRestrictions |> getExplicitRestriction let projectModel = (snd kv.Value) diff --git a/src/Paket.Core/PaketConfigFiles/ReferencesFile.fs b/src/Paket.Core/PaketConfigFiles/ReferencesFile.fs index 19abd51d95..fa7f3bdb99 100644 --- a/src/Paket.Core/PaketConfigFiles/ReferencesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ReferencesFile.fs @@ -168,7 +168,7 @@ type ReferencesFile = { this with Groups = newGroups } - member this.AddNuGetReference(groupName, packageName : PackageName) = this.AddNuGetReference(groupName, packageName, true, true, FrameworkRestrictionList [], false, false, None, null) + member this.AddNuGetReference(groupName, packageName : PackageName) = this.AddNuGetReference(groupName, packageName, true, true, ExplicitRestriction FrameworkRestriction.NoRestriction, false, false, None, null) member this.RemoveNuGetReference(groupName, packageName : PackageName) = let group = this.Groups.[groupName] diff --git a/src/Paket.Core/PublicAPI.fs b/src/Paket.Core/PublicAPI.fs index a116bb389f..5402ff9c28 100644 --- a/src/Paket.Core/PublicAPI.fs +++ b/src/Paket.Core/PublicAPI.fs @@ -460,7 +460,7 @@ type Dependencies(dependenciesFileName: string) = let nuspec = FileInfo(sprintf "%s/packages%s/%O/%O.nuspec" this.RootPath groupFolder packageName packageName) let nuspec = Nuspec.Load nuspec.FullName let files = NuGetV2.GetLibFiles(folder.FullName) - InstallModel.CreateFromLibs(packageName, resolvedPackage.Version, [], files, [], [], nuspec) + InstallModel.CreateFromLibs(packageName, resolvedPackage.Version, Paket.Requirements.FrameworkRestriction.NoRestriction, files, [], [], nuspec) /// Returns all libraries for the given package and framework. member this.GetLibraries(groupName,packageName,frameworkIdentifier:FrameworkIdentifier) = diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index bcad68c3f2..390d2a92bc 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -176,7 +176,8 @@ let getSupportedTargetProfiles = let getTargetCondition (target:TargetProfile) = match target with - | SinglePlatform(platform) -> + | SinglePlatform(platform) -> + // BUG: Pattern incomplete! match platform with | DotNetFramework(version) when version = FrameworkVersion.V4_Client -> "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Client')" version diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index e17bae7f74..e31aa1d35e 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -7,44 +7,91 @@ open Paket.PackageSources open Paket.Logging [] -type FrameworkRestriction = +type FrameworkRestriction = +// TODO: make this presentation private and add helper -> prevents different presentations of empty set +| NoRestriction +| EmptySet | Exactly of FrameworkIdentifier -| Portable of string +| Portable of string * FrameworkIdentifier list | AtLeast of FrameworkIdentifier | Between of FrameworkIdentifier * FrameworkIdentifier - +| Or of FrameworkRestriction * FrameworkRestriction +| And of FrameworkRestriction * FrameworkRestriction override this.ToString() = match this with + | FrameworkRestriction.NoRestriction -> "norestriction" + | FrameworkRestriction.EmptySet -> "emptyset" | FrameworkRestriction.Exactly r -> r.ToString() - | FrameworkRestriction.Portable r -> r + | FrameworkRestriction.Portable (r,_) -> r | FrameworkRestriction.AtLeast r -> ">= " + r.ToString() | FrameworkRestriction.Between(min,max) -> sprintf ">= %O < %O" min max + | FrameworkRestriction.Or(fr1, fr2) -> sprintf "|| (%O) (%O)" fr1 fr2 + | FrameworkRestriction.And(fr1, fr2) -> sprintf "&& (%O) (%O)" fr1 fr2 - // TODO: remove broken api - member x.GetOneIdentifier = + /// The list represented by this restriction (ie the included set of frameworks) + member x.RepresentedFrameworks = match x with - | Exactly r -> Some r - | Portable _ -> None - | AtLeast r -> Some r - | Between(r, _) -> Some r - - // TODO: remove broken api - /// Return if the parameter is a restriction of the same framework category (dotnet, windows phone, silverlight, ...) - member x.IsSameCategoryAs (y : FrameworkRestriction) = - match (x.GetOneIdentifier, y.GetOneIdentifier) with - | Some r, Some r' -> Some(r.IsSameCategoryAs r') - | _ -> None - -type FrameworkRestrictions = -| FrameworkRestrictionList of FrameworkRestriction list + | FrameworkRestriction.NoRestriction -> + KnownTargetProfiles.AllProfiles |> List.collect (function + | SinglePlatform fw -> [fw] + | PortableProfile (_, fws) -> fws) + | FrameworkRestriction.Exactly r -> [ r ] + | FrameworkRestriction.EmptySet -> [ ] + | FrameworkRestriction.Portable (r, fws) -> + fws + |> List.collect (fun fw -> (FrameworkRestriction.AtLeast fw).RepresentedFrameworks) + |> List.distinct + | FrameworkRestriction.AtLeast r -> r.SupportedPlatformsTransitive + | FrameworkRestriction.Between(min,max) -> + let minSupported = min.SupportedPlatformsTransitive + let maxSupported = max.SupportedPlatformsTransitive + minSupported + |> List.filter (fun fw -> maxSupported |> Seq.contains fw |> not) + | FrameworkRestriction.Or (fr1, fr2) -> + [ fr1; fr2 ] + |> List.collect (fun fr -> fr.RepresentedFrameworks) + |> List.distinct + | FrameworkRestriction.And (fr1, fr2) -> + let l1 = fr1.RepresentedFrameworks + fr2.RepresentedFrameworks + |> List.filter (fun fw -> l1 |> Seq.contains fw) + + /// Returns true if the restriction x is a subset of the restriction y (a restriction basically represents a list, see RepresentedFrameworks) + /// For example =net46 is a subset of >=netstandard13 + member x.IsSubsetOf (y:FrameworkRestriction) = + let superset = y.RepresentedFrameworks + x.RepresentedFrameworks + |> List.forall (fun inner -> superset |> Seq.contains inner) + + +type FrameworkRestrictions = +| ExplicitRestriction of FrameworkRestriction | AutoDetectFramework + member x.GetExplicitRestriction () = + match x with + | ExplicitRestriction list -> list + | AutoDetectFramework -> failwith "The framework restriction could not be determined." -let getRestrictionList (frameworkRestrictions:FrameworkRestrictions) = - match frameworkRestrictions with - | FrameworkRestrictionList list -> list - | AutoDetectFramework -> failwith "The framework restriction could not be determined." + member x.IsSupersetOf (fw:FrameworkRestriction) = + fw.IsSubsetOf(x.GetExplicitRestriction ()) -let parseRestrictions failImmediatly (text:string) = +let getExplicitRestriction (frameworkRestrictions:FrameworkRestrictions) = + frameworkRestrictions.GetExplicitRestriction() + +let combineRestrictionsWithOr (x : FrameworkRestriction) y = + if x.IsSubsetOf y then + y + elif y.IsSubsetOf x then + x + else + let combined = FrameworkRestriction.Or(x, y) + if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then + FrameworkRestriction.NoRestriction + else combined + +let parseRestrictionsLegacy failImmediatly (text:string) = + // TODO: Change this code to convert old "framework" sematics in + // older lockfiles to the new "restriction" semantics let handleError = if failImmediatly then failwith @@ -57,6 +104,8 @@ let parseRestrictions failImmediatly (text:string) = let text = // workaround missing spaces text.Replace("<=","<= ").Replace(">=",">= ").Replace("=","= ") + if text.StartsWith("||") || text.StartsWith("&&") then + raise <| NotImplementedException("&& and || are not yet implemented.") let commaSplit = text.Trim().Split(',') [for p in commaSplit do @@ -70,8 +119,9 @@ let parseRestrictions failImmediatly (text:string) = match FrameworkDetection.Extract(framework) with | None -> - if (PlatformMatching.extractPlatforms framework).Platforms |> List.isEmpty |> not then - yield FrameworkRestriction.Portable framework + let platforms = (PlatformMatching.extractPlatforms framework).Platforms + if platforms |> List.isEmpty |> not then + yield FrameworkRestriction.Portable (framework, platforms) else handleError <| sprintf "Could not parse framework '%s'. Try to update or install again or report a paket bug." framework | Some x -> @@ -86,304 +136,274 @@ let parseRestrictions failImmediatly (text:string) = | Some y -> yield FrameworkRestriction.Between(x,y) else yield FrameworkRestriction.Exactly x] - -// TODO: remove broken api -let private minRestriction = FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V1)) - -// TODO: remove broken api -let private minStandardRestriction = FrameworkRestriction.Exactly(DotNetStandard(DotNetStandardVersion.V1_0)) - -// TODO: remove broken api -let findMaxDotNetRestriction restrictions = - minRestriction :: restrictions - |> List.filter (fun (r:FrameworkRestriction) -> - match r with - | FrameworkRestriction.Exactly(DotNetFramework _) -> true - | _ -> false) - |> List.max - |> fun r -> - match r with - | FrameworkRestriction.Exactly r -> r - | _ -> failwith "error" - -// TODO: remove broken api -let findMaxStandardRestriction restrictions = - minStandardRestriction :: restrictions - |> List.filter (fun (r:FrameworkRestriction) -> - match r with - | FrameworkRestriction.Exactly(DotNetStandard _) -> true - | _ -> false) - |> List.max - |> fun r -> - match r with - | FrameworkRestriction.Exactly r -> r - | _ -> failwith "error" + |> List.fold (fun state item -> combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet let rec optimizeRestrictions restrictions = - let sorting xs = - xs - |> List.sortBy (fun x -> - match x with - | FrameworkRestriction.Exactly r -> r - | FrameworkRestriction.Portable r -> FrameworkIdentifier.MonoMac - | FrameworkRestriction.AtLeast r -> r - | FrameworkRestriction.Between(min,max) -> min - |> fun y -> y,x) - - match sorting restrictions |> List.distinct with - | [] -> [] - | [x] -> [x] - | odered -> - let newRestrictions = - match odered |> Seq.tryFind (function | FrameworkRestriction.AtLeast r -> true | _ -> false) with - | Some((FrameworkRestriction.AtLeast(DotNetFramework(v)) as r)) -> - odered - |> List.filter (fun r' -> - match r' with - | FrameworkRestriction.Exactly(DotNetFramework(x)) when x > v -> false - | FrameworkRestriction.AtLeast(DotNetFramework(x)) when x > v -> false - | _ -> true) - | Some((FrameworkRestriction.AtLeast(DotNetStandard(v)) as r)) -> - odered - |> List.filter (fun r' -> - match r' with - | FrameworkRestriction.Exactly(DotNetStandard(x)) when x > v -> false - | FrameworkRestriction.AtLeast(DotNetStandard(x)) when x > v -> false - | _ -> true) - | _ -> odered - - let filtered = - match newRestrictions |> Seq.rev |> Seq.tryFind (function | FrameworkRestriction.AtLeast(DotNetFramework r) -> true | FrameworkRestriction.AtLeast(DotNetStandard r) -> true | _ -> false) with - | None -> newRestrictions - | Some r -> - let currentVersion = - match r with - | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> DotNetFramework x - | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> DotNetStandard x - | x -> failwithf "Unknown .NET moniker %O" x - - let isLowerVersion (currentVersion:FrameworkIdentifier) compareVersion = - let isMatching (x:FrameworkIdentifier) = - if x = DotNetFramework FrameworkVersion.V3_5 && currentVersion = DotNetFramework FrameworkVersion.V4 then true else - if x = DotNetFramework FrameworkVersion.V3_5 && currentVersion = DotNetFramework FrameworkVersion.V4_Client then true else - if x = DotNetFramework FrameworkVersion.V4_Client && currentVersion = DotNetFramework FrameworkVersion.V4_5 then true else - let hasFrameworksBetween = - KnownTargetProfiles.DotNetFrameworkVersions - |> Seq.exists (fun p -> DotNetFramework p > x && DotNetFramework p < currentVersion) - let hasStandardsBetween = - KnownTargetProfiles.DotNetStandardVersions - |> Seq.exists (fun p -> DotNetStandard p > x && DotNetStandard p < currentVersion) - - not hasFrameworksBetween && not hasStandardsBetween - - match compareVersion with - | FrameworkRestriction.Exactly(DotNetFramework(x)) -> isMatching (DotNetFramework x) - | FrameworkRestriction.Exactly(DotNetStandard(x)) -> isMatching (DotNetStandard x) - | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> - isMatching (DotNetFramework x) || - (match currentVersion with - | DotNetFramework(y) when x < y -> true - | _ -> false) - | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> - isMatching (DotNetStandard x) || - (match currentVersion with - | DotNetStandard(y) when x < y -> true - | _ -> false) - | _ -> false - - match newRestrictions |> Seq.tryFind (isLowerVersion currentVersion) with - | None -> newRestrictions - | Some n -> - let newLowest = - match n with - | FrameworkRestriction.Exactly(DotNetFramework(x)) -> DotNetFramework x - | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> DotNetFramework x - | FrameworkRestriction.Exactly(DotNetStandard(x)) -> DotNetStandard x - | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> DotNetStandard x - | x -> failwithf "Unknown .NET moniker %O" x - - let filtered = - newRestrictions - |> List.filter (fun x -> x <> r && x <> n) - - filtered @ [FrameworkRestriction.AtLeast(newLowest)] - - if restrictions = filtered then sorting filtered else optimizeRestrictions filtered - -let hasDotNetFrameworkOrAnyCase = - List.exists (fun (_,_,rs) -> - rs = [] || - rs - |> List.exists (function - | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true - | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true - | _ -> false)) + restrictions +// let sorting xs = +// xs +// |> List.sortBy (fun x -> +// match x with +// | FrameworkRestriction.Exactly r -> r +// | FrameworkRestriction.Portable _ -> FrameworkIdentifier.MonoMac +// | FrameworkRestriction.AtLeast r -> r +// | FrameworkRestriction.Between(min,max) -> min +// |> fun y -> y,x) +// +// match sorting restrictions |> List.distinct with +// | [] -> [] +// | [x] -> [x] +// | odered -> +// let newRestrictions = +// match odered |> Seq.tryFind (function | FrameworkRestriction.AtLeast r -> true | _ -> false) with +// | Some((FrameworkRestriction.AtLeast(DotNetFramework(v)) as r)) -> +// odered +// |> List.filter (fun r' -> +// match r' with +// | FrameworkRestriction.Exactly(DotNetFramework(x)) when x > v -> false +// | FrameworkRestriction.AtLeast(DotNetFramework(x)) when x > v -> false +// | _ -> true) +// | Some((FrameworkRestriction.AtLeast(DotNetStandard(v)) as r)) -> +// odered +// |> List.filter (fun r' -> +// match r' with +// | FrameworkRestriction.Exactly(DotNetStandard(x)) when x > v -> false +// | FrameworkRestriction.AtLeast(DotNetStandard(x)) when x > v -> false +// | _ -> true) +// | _ -> odered +// +// let filtered = +// match newRestrictions |> Seq.rev |> Seq.tryFind (function | FrameworkRestriction.AtLeast(DotNetFramework r) -> true | FrameworkRestriction.AtLeast(DotNetStandard r) -> true | _ -> false) with +// | None -> newRestrictions +// | Some r -> +// let currentVersion = +// match r with +// | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> DotNetFramework x +// | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> DotNetStandard x +// | x -> failwithf "Unknown .NET moniker %O" x +// +// let isLowerVersion (currentVersion:FrameworkIdentifier) compareVersion = +// let isMatching (x:FrameworkIdentifier) = +// if x = DotNetFramework FrameworkVersion.V3_5 && currentVersion = DotNetFramework FrameworkVersion.V4 then true else +// if x = DotNetFramework FrameworkVersion.V3_5 && currentVersion = DotNetFramework FrameworkVersion.V4_Client then true else +// if x = DotNetFramework FrameworkVersion.V4_Client && currentVersion = DotNetFramework FrameworkVersion.V4_5 then true else +// let hasFrameworksBetween = +// KnownTargetProfiles.DotNetFrameworkVersions +// |> Seq.exists (fun p -> DotNetFramework p > x && DotNetFramework p < currentVersion) +// let hasStandardsBetween = +// KnownTargetProfiles.DotNetStandardVersions +// |> Seq.exists (fun p -> DotNetStandard p > x && DotNetStandard p < currentVersion) +// +// not hasFrameworksBetween && not hasStandardsBetween +// +// match compareVersion with +// | FrameworkRestriction.Exactly(DotNetFramework(x)) -> isMatching (DotNetFramework x) +// | FrameworkRestriction.Exactly(DotNetStandard(x)) -> isMatching (DotNetStandard x) +// | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> +// isMatching (DotNetFramework x) || +// (match currentVersion with +// | DotNetFramework(y) when x < y -> true +// | _ -> false) +// | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> +// isMatching (DotNetStandard x) || +// (match currentVersion with +// | DotNetStandard(y) when x < y -> true +// | _ -> false) +// | _ -> false +// +// match newRestrictions |> Seq.tryFind (isLowerVersion currentVersion) with +// | None -> newRestrictions +// | Some n -> +// let newLowest = +// match n with +// | FrameworkRestriction.Exactly(DotNetFramework(x)) -> DotNetFramework x +// | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> DotNetFramework x +// | FrameworkRestriction.Exactly(DotNetStandard(x)) -> DotNetStandard x +// | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> DotNetStandard x +// | x -> failwithf "Unknown .NET moniker %O" x +// +// let filtered = +// newRestrictions +// |> List.filter (fun x -> x <> r && x <> n) +// +// filtered @ [FrameworkRestriction.AtLeast(newLowest)] +// +// if restrictions = filtered then sorting filtered else optimizeRestrictions filtered + +//let hasDotNetFrameworkOrAnyCase = +// List.exists (fun (_,_,rs) -> +// rs = [] || +// rs +// |> List.exists (function +// | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true +// | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true +// | _ -> false)) let optimizeDependencies originalDependencies = - let grouped = originalDependencies |> List.groupBy (fun (n,v,_) -> n,v) - - let expanded = - [for (n,vr,r:FrameworkRestriction list) in originalDependencies do - for r' in r do - yield n,vr,r'] - |> List.groupBy (fun (_,_,r) -> r) - - let invertedRestrictions = - [for restriction,packages in expanded do - match restriction with - | FrameworkRestriction.Exactly(DotNetFramework _ as r) -> - yield r,packages |> List.map (fun (n,v,_) -> n,v) - | _ -> () ] - |> List.sortBy fst - - let invertedStandardRestrictions = - [for restriction,packages in expanded do - match restriction with - | FrameworkRestriction.Exactly(DotNetStandard _ as r) -> - yield r,packages |> List.map (fun (n,v,_) -> n,v) - | _ -> () ] - |> List.sortBy fst - - let globalMax = - invertedRestrictions - |> List.tryLast - |> Option.map fst - - let globalStandardMax = - invertedStandardRestrictions - |> List.tryLast - |> Option.map fst - - let globalMin = - invertedRestrictions - |> List.tryHead - |> Option.map fst - - let globalStandardMin = - invertedStandardRestrictions - |> List.tryHead - |> Option.map fst - - let emptyRestrictions = - [for (n,vr,r:FrameworkRestriction list) in originalDependencies do - if r = [] then - yield n,vr] - |> Set.ofList - - let allRestrictions = - [for (n,vr,r:FrameworkRestriction list) in originalDependencies do - yield r] - |> Set.ofList - - let restrictionsPerPackage = - originalDependencies - |> List.groupBy (fun (n,vr,r) -> n,vr) - |> List.map (fun ((n,vr),rs) -> - n,vr, - (rs - |> List.map (fun (_,_,r) -> r) - |> Set.ofList)) - - let packagesWithAllRestrictions = - restrictionsPerPackage - |> List.filter (fun (_,_,rs) -> rs = allRestrictions) - |> List.map (fun (n,vr,_) -> n,vr) - |> Set.ofList - - let newRestictions = - [for (name,versionRequirement:VersionRequirement),group in grouped do - if name <> PackageName "" then - let hasEmpty = not (Set.isEmpty emptyRestrictions) && Set.contains (name,versionRequirement) emptyRestrictions - let hasAll = not (Set.isEmpty packagesWithAllRestrictions) && Set.contains (name,versionRequirement) packagesWithAllRestrictions - - if hasEmpty && hasAll then - yield name,versionRequirement,[] - else - let sorted = - group - |> List.map (fun (_,_,res) -> res) - |> List.concat - |> List.distinct - |> List.sort - - let localMaxDotNetRestriction = findMaxDotNetRestriction sorted - let localMaxStandardRestriction = findMaxStandardRestriction sorted - let globalMax = defaultArg globalMax localMaxDotNetRestriction - let globalStandardMax = defaultArg globalStandardMax localMaxStandardRestriction - - let plain = - match sorted with - | [] -> - let globalStandardMin = defaultArg globalStandardMin localMaxDotNetRestriction - - let frameworks = - match globalMin with - | Some globalMin -> - KnownTargetProfiles.DotNetFrameworkVersions - |> List.filter (fun fw -> DotNetFramework(fw) < globalMin) - |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetFramework(fw))) - | _ -> - KnownTargetProfiles.DotNetFrameworkVersions - |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetFramework(fw))) - - let standards = - KnownTargetProfiles.DotNetStandardVersions - |> List.filter (fun fw -> DotNetStandard(fw) < globalStandardMin) - |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetStandard(fw))) - - frameworks @ standards - - | _ -> sorted - - let dotnetRestrictions,others = - plain - |> List.partition (fun p -> - match p with - | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true - | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true - | FrameworkRestriction.Exactly(DotNetStandard(_)) -> true - | FrameworkRestriction.AtLeast(DotNetStandard(_)) -> true - | _ -> false) - - let restrictions' = - dotnetRestrictions - |> List.map (fun restriction -> - match restriction with - | FrameworkRestriction.Exactly(DotNetFramework _ as r) -> - if r = localMaxDotNetRestriction && r = globalMax then - FrameworkRestriction.AtLeast r - else - restriction - | FrameworkRestriction.Exactly (DotNetStandard _ as r) -> - if r = localMaxStandardRestriction && r = globalStandardMax then - FrameworkRestriction.AtLeast r - else - restriction - | _ -> restriction) - - let restrictions = optimizeRestrictions restrictions' - - yield name,versionRequirement,others @ restrictions] - - let hasDotNetFrameworkOrStandard = - newRestictions - |> List.exists (fun (_,_,rs) -> - rs - |> List.exists (function - | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true - | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true - | FrameworkRestriction.Exactly(DotNetStandard(_)) -> true - | FrameworkRestriction.AtLeast(DotNetStandard(_)) -> true - | _ -> false)) - - if not hasDotNetFrameworkOrStandard then - newRestictions - else - let newRestictions = - if hasDotNetFrameworkOrAnyCase originalDependencies then - newRestictions - else - newRestictions + //let grouped = originalDependencies |> List.groupBy (fun (n,v,_) -> n,v) + // + //let expanded = + // [for (n,vr,r:FrameworkRestriction list) in originalDependencies do + // for r' in r do + // yield n,vr,r'] + // |> List.groupBy (fun (_,_,r) -> r) + // + //let invertedRestrictions = + // [for restriction,packages in expanded do + // match restriction with + // | FrameworkRestriction.Exactly(DotNetFramework _ as r) -> + // yield r,packages |> List.map (fun (n,v,_) -> n,v) + // | _ -> () ] + // |> List.sortBy fst + // + //let invertedStandardRestrictions = + // [for restriction,packages in expanded do + // match restriction with + // | FrameworkRestriction.Exactly(DotNetStandard _ as r) -> + // yield r,packages |> List.map (fun (n,v,_) -> n,v) + // | _ -> () ] + // |> List.sortBy fst + // + //let globalMax = + // invertedRestrictions + // |> List.tryLast + // |> Option.map fst + // + //let globalStandardMax = + // invertedStandardRestrictions + // |> List.tryLast + // |> Option.map fst + // + //let globalMin = + // invertedRestrictions + // |> List.tryHead + // |> Option.map fst + // + //let globalStandardMin = + // invertedStandardRestrictions + // |> List.tryHead + // |> Option.map fst + // + //let emptyRestrictions = + // [for (n,vr,r:FrameworkRestriction list) in originalDependencies do + // if r = [] then + // yield n,vr] + // |> Set.ofList + // + //let allRestrictions = + // [for (n,vr,r:FrameworkRestriction list) in originalDependencies do + // yield r] + // |> Set.ofList + // + //let restrictionsPerPackage = + // originalDependencies + // |> List.groupBy (fun (n,vr,r) -> n,vr) + // |> List.map (fun ((n,vr),rs) -> + // n,vr, + // (rs + // |> List.map (fun (_,_,r) -> r) + // |> Set.ofList)) + // + //let packagesWithAllRestrictions = + // restrictionsPerPackage + // |> List.filter (fun (_,_,rs) -> rs = allRestrictions) + // |> List.map (fun (n,vr,_) -> n,vr) + // |> Set.ofList + // + //let newRestictions = + // [for (name,versionRequirement:VersionRequirement),group in grouped do + // if name <> PackageName "" then + // let hasEmpty = not (Set.isEmpty emptyRestrictions) && Set.contains (name,versionRequirement) emptyRestrictions + // let hasAll = not (Set.isEmpty packagesWithAllRestrictions) && Set.contains (name,versionRequirement) packagesWithAllRestrictions + // + // if hasEmpty && hasAll then + // yield name,versionRequirement,[] + // else + // let sorted = + // group + // |> List.map (fun (_,_,res) -> res) + // |> List.concat + // |> List.distinct + // |> List.sort + // + // let localMaxDotNetRestriction = findMaxDotNetRestriction sorted + // let localMaxStandardRestriction = findMaxStandardRestriction sorted + // let globalMax = defaultArg globalMax localMaxDotNetRestriction + // let globalStandardMax = defaultArg globalStandardMax localMaxStandardRestriction + // + // let plain = + // match sorted with + // | [] -> + // let globalStandardMin = defaultArg globalStandardMin localMaxDotNetRestriction + // + // let frameworks = + // match globalMin with + // | Some globalMin -> + // KnownTargetProfiles.DotNetFrameworkVersions + // |> List.filter (fun fw -> DotNetFramework(fw) < globalMin) + // |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetFramework(fw))) + // | _ -> + // KnownTargetProfiles.DotNetFrameworkVersions + // |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetFramework(fw))) + // + // let standards = + // KnownTargetProfiles.DotNetStandardVersions + // |> List.filter (fun fw -> DotNetStandard(fw) < globalStandardMin) + // |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetStandard(fw))) + // + // frameworks @ standards + // + // | _ -> sorted + // + // let dotnetRestrictions,others = + // plain + // |> List.partition (fun p -> + // match p with + // | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true + // | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true + // | FrameworkRestriction.Exactly(DotNetStandard(_)) -> true + // | FrameworkRestriction.AtLeast(DotNetStandard(_)) -> true + // | _ -> false) + // + // let restrictions' = + // dotnetRestrictions + // |> List.map (fun restriction -> + // match restriction with + // | FrameworkRestriction.Exactly(DotNetFramework _ as r) -> + // if r = localMaxDotNetRestriction && r = globalMax then + // FrameworkRestriction.AtLeast r + // else + // restriction + // | FrameworkRestriction.Exactly (DotNetStandard _ as r) -> + // if r = localMaxStandardRestriction && r = globalStandardMax then + // FrameworkRestriction.AtLeast r + // else + // restriction + // | _ -> restriction) + // + // let restrictions = optimizeRestrictions restrictions' + // + // yield name,versionRequirement,others @ restrictions] + + //let hasDotNetFrameworkOrStandard = + // newRestictions + // |> List.exists (fun (_,_,rs) -> + // rs + // |> List.exists (function + // | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true + // | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true + // | FrameworkRestriction.Exactly(DotNetStandard(_)) -> true + // | FrameworkRestriction.AtLeast(DotNetStandard(_)) -> true + // | _ -> false)) + + //if not hasDotNetFrameworkOrStandard then + // newRestictions + //else + // let newRestictions = + // if hasDotNetFrameworkOrAnyCase originalDependencies then + // newRestictions + // else + // newRestictions //|> List.map (fun (name,vr,rs) -> // let newRs = // rs @@ -406,136 +426,133 @@ let optimizeDependencies originalDependencies = // name,vr,newRs) - newRestictions - |> List.map (fun (p,v,rs) -> - let filtered = - rs - |> List.map (fun r -> - match r with - | FrameworkRestriction.Portable portable -> - let newPortable = - portable.Split('+') - |> Array.filter (fun s -> s.StartsWith "net" |> not) - |> fun xs -> String.Join("+",xs) - FrameworkRestriction.Portable newPortable - | _ -> r) - p,v,filtered) - - - |> List.map (fun (a,b,c) -> a,b, FrameworkRestrictionList c) - -let private combineSameCategoryOrPortableRestrictions x y = - match x with - | FrameworkRestriction.Exactly r -> - match y with - | FrameworkRestriction.Exactly r' -> if r = r' then [FrameworkRestriction.Exactly r] else [] - | FrameworkRestriction.Portable _ -> [] - | FrameworkRestriction.AtLeast r' -> if r' <= r then [FrameworkRestriction.Exactly r] else [] - | FrameworkRestriction.Between(min,max) -> if min <= r && r < max then [FrameworkRestriction.Exactly r] else [] - | FrameworkRestriction.Portable r -> - match y with - | FrameworkRestriction.Portable r' -> if r = r' then [FrameworkRestriction.Portable r] else [] - | _ -> [] - | FrameworkRestriction.AtLeast r -> - match y with - | FrameworkRestriction.Exactly r' -> if r <= r' then [FrameworkRestriction.Exactly r'] else [] - | FrameworkRestriction.Portable _ -> [] - | FrameworkRestriction.AtLeast r' -> [FrameworkRestriction.AtLeast (max r r')] - | FrameworkRestriction.Between(min,max') -> if r < max' then [FrameworkRestriction.Between(max r min,max')] else [] - | FrameworkRestriction.Between(min1,max1) -> - match y with - | FrameworkRestriction.Exactly r -> if min1 <= r && r < max1 then [FrameworkRestriction.Exactly r] else [] - | FrameworkRestriction.Portable _ -> [] - | FrameworkRestriction.AtLeast r -> if r < max1 then [FrameworkRestriction.Between(max r min1,max1)] else [] - | FrameworkRestriction.Between(min2,max2) -> - let min' = max min1 min2 - let max' = min max1 max2 - if min' < max' then [FrameworkRestriction.Between(min',max')] else - if min' = max' then [FrameworkRestriction.Exactly(min')] else - [] - -let combineRestrictions loose (x : FrameworkRestriction) y = - if x.IsSameCategoryAs(y) <> Some false then - combineSameCategoryOrPortableRestrictions x y + //newRestictions + //|> List.map (fun (p,v,rs) -> + // let filtered = + // rs + // |> List.map (fun r -> + // match r with + // | FrameworkRestriction.Portable (portable, fws) -> + // let newPortable = + // portable.Split('+') + // |> Array.filter (fun s -> s.StartsWith "net" |> not) + // |> fun xs -> String.Join("+",xs) + // let newFws = + // fws + // |> List.filter (fun fw -> + // fw.IsSameCategoryAs (DotNetFramework FrameworkVersion.V1) || + // fw.IsSameCategoryAs (DotNetUnity DotNetUnityVersion.V3_5_Web) || + // fw.IsSameCategoryAs (DotNetStandard DotNetStandardVersion.V1_0) || + // fw.IsSameCategoryAs (DotNetCore DotNetCoreVersion.V1_0) + // |> not) + // FrameworkRestriction.Portable (newPortable, newFws) + // | _ -> r) + // p,v,filtered) + + originalDependencies + |> List.map (fun (a,b,c) -> a,b, ExplicitRestriction c) + +let combineRestrictionsWithAnd (x : FrameworkRestriction) y = + // combine means basically we say AND (both need to be satisfied) + if x.IsSubsetOf y then + x + elif y.IsSubsetOf x then + y else - if loose then - match (x.GetOneIdentifier, y.GetOneIdentifier) with - | Some (FrameworkIdentifier.DotNetFramework _ ), Some (FrameworkIdentifier.DotNetStandard _ ) -> [x] - | Some (FrameworkIdentifier.DotNetStandard _ ), Some (FrameworkIdentifier.DotNetFramework _ ) -> [y] - | _ -> [] - else - [] + let combined = FrameworkRestriction.And(x, y) + if combined.RepresentedFrameworks |> Seq.isEmpty then + FrameworkRestriction.EmptySet + else combined + //if x.IsSameCategoryAs(y) <> Some false then + // combineSameCategoryOrPortableRestrictions x y + //else + // if loose then + // match (x.GetOneIdentifier, y.GetOneIdentifier) with + // | Some (FrameworkIdentifier.DotNetFramework _ ), Some (FrameworkIdentifier.DotNetStandard _ ) -> [x] + // | Some (FrameworkIdentifier.DotNetStandard _ ), Some (FrameworkIdentifier.DotNetFramework _ ) -> [y] + // | _ -> [] + // else + // [] let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestrictions) = match list1,list2 with - | FrameworkRestrictionList [], AutoDetectFramework -> AutoDetectFramework - | AutoDetectFramework, FrameworkRestrictionList [] -> AutoDetectFramework + | ExplicitRestriction FrameworkRestriction.NoRestriction, AutoDetectFramework -> AutoDetectFramework + | AutoDetectFramework, ExplicitRestriction FrameworkRestriction.NoRestriction -> AutoDetectFramework | AutoDetectFramework, AutoDetectFramework -> AutoDetectFramework - | FrameworkRestrictionList list1 , FrameworkRestrictionList list2 -> - let filtered = - match list1, list2 with - | [],_ -> list2 - | _,[] -> list1 - | _ -> - [for x in list1 do - for y in list2 do - let c = combineRestrictions false x y - if c <> [] then yield! c] - - let tryLoose = - (filtered |> List.exists (fun r -> match r.GetOneIdentifier with | Some (FrameworkIdentifier.DotNetFramework _ ) -> true | _ -> false) |> not) && - (list2 |> List.exists (fun r -> match r.GetOneIdentifier with | Some (FrameworkIdentifier.DotNetFramework _ ) -> true | _ -> false)) - - let filtered = - if tryLoose then - match list1, list2 with - | [],_ -> list2 - | _,[] -> list1 - | _ -> - [for x in list1 do - for y in list2 do - let c = combineRestrictions true x y - if c <> [] then yield! c] - else - filtered - - let optimized = - filtered - |> optimizeRestrictions - FrameworkRestrictionList optimized + | ExplicitRestriction fr1 , ExplicitRestriction fr2 -> ExplicitRestriction (combineRestrictionsWithAnd fr1 fr2) + //let filtered = + // match list1, list2 with + // | [],_ -> list2 + // | _,[] -> list1 + // | _ -> + // [for x in list1 do + // for y in list2 do + // let c = combineRestrictions false x y + // if c <> [] then yield! c] + // + //let tryLoose = + // (filtered |> List.exists (fun r -> match r.GetOneIdentifier with | Some (FrameworkIdentifier.DotNetFramework _ ) -> true | _ -> false) |> not) && + // (list2 |> List.exists (fun r -> match r.GetOneIdentifier with | Some (FrameworkIdentifier.DotNetFramework _ ) -> true | _ -> false)) + // + //let filtered = + // if tryLoose then + // match list1, list2 with + // | [],_ -> list2 + // | _,[] -> list1 + // | _ -> + // [for x in list1 do + // for y in list2 do + // let c = combineRestrictions true x y + // if c <> [] then yield! c] + // else + // filtered + // + //let optimized = + // filtered + // |> optimizeRestrictions + //FrameworkRestrictionList optimized | _ -> failwithf "The framework restriction %O and %O could not be combined." list1 list2 /// Get if a target should be considered with the specified restrictions -let isTargetMatchingRestrictions = - memoize <| fun (restrictions:FrameworkRestriction list, target) -> - if List.isEmpty restrictions then true else - match target with - | SinglePlatform pf -> - restrictions - |> List.exists (fun restriction -> - match restriction with - | FrameworkRestriction.Exactly (Native(NoBuildMode,NoPlatform)) -> - match pf with - | Native(_) -> true - | _ -> false - | FrameworkRestriction.Exactly fw -> - pf = fw - | FrameworkRestriction.Portable _ -> false - | FrameworkRestriction.AtLeast fw -> - pf.IsAtLeast(fw) - | FrameworkRestriction.Between(min,max) -> - pf.IsBetween(min,max)) - | _ -> - restrictions - |> List.exists (fun restriction -> - match restriction with - | FrameworkRestriction.Portable r -> true - | _ -> false) +let isTargetMatchingRestrictions (restriction:FrameworkRestriction, target)= + match target with + | SinglePlatform pf -> + restriction.RepresentedFrameworks |> Seq.contains pf + | PortableProfile (_, fws) -> + // TODO: Review - check if we need to use exists instead of forall? + fws + |> Seq.forall (fun fw -> + restriction.RepresentedFrameworks |> Seq.contains fw) + + //memoize <| fun (restrictions:FrameworkRestriction list, target) -> + // if List.isEmpty restrictions then true else + // match target with + // | SinglePlatform pf -> + // restrictions + // |> List.exists (fun restriction -> + // match restriction with + // | FrameworkRestriction.Exactly (Native(NoBuildMode,NoPlatform)) -> + // match pf with + // | Native(_) -> true + // | _ -> false + // | FrameworkRestriction.Exactly fw -> + // pf = fw + // | FrameworkRestriction.Portable _ -> false + // | FrameworkRestriction.AtLeast fw -> + // pf.IsAtLeast(fw) + // | FrameworkRestriction.Between(min,max) -> + // pf.IsBetween(min,max)) + // | _ -> + // restrictions + // |> List.exists (fun restriction -> + // match restriction with + // | FrameworkRestriction.Portable _ -> true + // | _ -> false) /// Get all targets that should be considered with the specified restrictions -let applyRestrictionsToTargets (restrictions:FrameworkRestriction list) (targets: TargetProfile list) = +let applyRestrictionsToTargets (restriction:FrameworkRestriction) (targets: TargetProfile list) = targets - |> List.filter (fun t -> isTargetMatchingRestrictions(restrictions,t)) + |> List.filter (fun t -> isTargetMatchingRestrictions(restriction,t)) type ContentCopySettings = | Omit @@ -568,7 +585,7 @@ type InstallSettings = static member Default = { CopyLocal = None ImportTargets = None - FrameworkRestrictions = FrameworkRestrictionList [] + FrameworkRestrictions = ExplicitRestriction FrameworkRestriction.NoRestriction IncludeVersionInPath = None ReferenceCondition = None CreateBindingRedirects = None @@ -608,9 +625,9 @@ type InstallSettings = | Some Force -> yield "redirects: force" | None -> () match this.FrameworkRestrictions with - | FrameworkRestrictionList [] -> () + | ExplicitRestriction FrameworkRestriction.NoRestriction -> () | AutoDetectFramework -> () - | FrameworkRestrictionList list -> yield "framework: " + (String.Join(", ",list)) + | ExplicitRestriction fr -> yield "restriction: " + (fr.ToString()) match this.GenerateLoadScripts with | Some true -> yield "generate_load_scripts: true" | Some false -> yield "generate_load_scripts: false" @@ -650,9 +667,14 @@ type InstallSettings = | Some "true" -> Some true | _ -> None FrameworkRestrictions = - match getPair "framework" with - | Some s -> FrameworkRestrictionList(parseRestrictions true s) - | _ -> FrameworkRestrictionList [] + match getPair "restriction" with + | Some s -> + // TODO: Change to new parser. + ExplicitRestriction(parseRestrictionsLegacy true s) + | _ -> + match getPair "framework" with + | Some s -> ExplicitRestriction(parseRestrictionsLegacy true s) + | _ -> ExplicitRestriction FrameworkRestriction.NoRestriction OmitContent = match getPair "content" with | Some "none" -> Some ContentCopySettings.Omit diff --git a/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs b/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs index c41032bd26..69b97e1fee 100644 --- a/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs +++ b/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs @@ -749,7 +749,7 @@ let ``should read config with local source``() = let p = cfg.Groups.[Constants.MainDependencyGroup].Packages |> List.find (fun x-> x.Name = PackageName "Nancy.Owin") p.VersionRequirement.Range |> shouldEqual (VersionRange.Specific (SemVer.Parse "0.22.2")) - p.Settings.FrameworkRestrictions |> getRestrictionList |> shouldEqual [] + p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual FrameworkRestriction.NoRestriction [] @@ -770,7 +770,7 @@ let ``should read config with single framework restriction``() = let p = cfg.Groups.[Constants.MainDependencyGroup].Packages |> List.find (fun x-> x.Name = PackageName "Foobar") p.VersionRequirement.Range |> shouldEqual (VersionRange.Specific (SemVer.Parse "1.2.3")) - p.Settings.FrameworkRestrictions |> getRestrictionList |> shouldEqual [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))] + p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))) p.Settings.ImportTargets |> shouldEqual None @@ -783,7 +783,7 @@ let ``should read config with framework restriction``() = let p = cfg.Groups.[Constants.MainDependencyGroup].Packages |> List.find (fun x-> x.Name = PackageName "Foobar") p.VersionRequirement.Range |> shouldEqual (VersionRange.Specific (SemVer.Parse "1.2.3")) - p.Settings.FrameworkRestrictions |> getRestrictionList |> shouldEqual [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5)); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))] + p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5)); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))] |> getExplicitRestriction) p.Settings.ImportTargets |> shouldEqual None p.Settings.CopyLocal |> shouldEqual None @@ -796,7 +796,7 @@ let ``should read config with no targets import``() = let p = cfg.Groups.[Constants.MainDependencyGroup].Packages |> List.find (fun x-> x.Name = PackageName "Foobar") p.VersionRequirement.Range |> shouldEqual (VersionRange.Specific (SemVer.Parse "1.2.3")) - p.Settings.FrameworkRestrictions |> getRestrictionList |> shouldEqual [] + p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual FrameworkRestriction.NoRestriction p.Settings.ImportTargets |> shouldEqual (Some false) p.Settings.CopyLocal |> shouldEqual (Some false) p.Settings.OmitContent |> shouldEqual None @@ -810,7 +810,7 @@ let ``should read config with content none``() = let p = cfg.Groups.[Constants.MainDependencyGroup].Packages |> List.find (fun x-> x.Name = PackageName "Foobar") p.VersionRequirement.Range |> shouldEqual (VersionRange.Specific (SemVer.Parse "1.2.3")) - p.Settings.FrameworkRestrictions |> getRestrictionList |> shouldEqual [] + p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual FrameworkRestriction.NoRestriction p.Settings.ImportTargets |> shouldEqual None p.Settings.CopyLocal |> shouldEqual (Some false) p.Settings.OmitContent |> shouldEqual (Some ContentCopySettings.Omit) @@ -1127,8 +1127,8 @@ let ``should read config with target framework``() = let cfg = DependenciesFile.FromSource(configTargetFramework) cfg.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual [FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) [] let ``should read packages with redirects``() = diff --git a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs index 51abf56392..5a09a4904a 100644 --- a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs +++ b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs @@ -738,7 +738,7 @@ let ``should filter .NET 4.0 dlls for System.Net.Http 2.2.8``() = let model = InstallModel.CreateFromLibs (PackageName "System.Net.Http", SemVer.Parse "2.2.8", - [ ], + FrameworkRestriction.NoRestriction, [ @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Extensions.dll" @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Primitives.dll" @"..\Microsoft.Net.Http\lib\monotouch\System.Net.Http.Extensions.dll" @@ -773,7 +773,7 @@ let ``should filter .NET 4.5 dlls for System.Net.Http 2.2.8``() = let model = InstallModel.CreateFromLibs (PackageName "System.Net.Http", SemVer.Parse "2.2.8", - [ ], + FrameworkRestriction.NoRestriction, [ @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Extensions.dll" @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Primitives.dll" @"..\Microsoft.Net.Http\lib\monotouch\System.Net.Http.Extensions.dll" @@ -807,7 +807,7 @@ let ``should filter properly when portables are available``() = let model = InstallModel.CreateFromLibs (PackageName "Newtonsoft.Json", SemVer.Parse "8.0.3", - [ ], + FrameworkRestriction.NoRestriction, [ @"..\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll" @"..\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll" @"..\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll" @@ -816,7 +816,7 @@ let ``should filter properly when portables are available``() = @"..\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll" ] |> fromLegacyList @"..\Newtonsoft.Json\", [], [], Nuspec.All) let filteredModel = - model.ApplyFrameworkRestrictions ( [ FrameworkRestriction.Exactly (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_5) ] ) + model.ApplyFrameworkRestrictions (FrameworkRestriction.Exactly (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_5)) filteredModel.GetLegacyReferences(SinglePlatform(DotNetFramework(FrameworkVersion.V4_5))) |> Seq.map (fun f -> f.Path) @@ -832,11 +832,11 @@ let ``should keep net20 if nothing better is available``() = let model = InstallModel.CreateFromLibs (PackageName "EPPlus", SemVer.Parse "4.0.5", - [ ], + FrameworkRestriction.NoRestriction, [ @"..\EPPlus\lib\net20\EPPlus.dll" ] |> fromLegacyList @"..\EPPlus\", [], [], Nuspec.All) let filteredModel = - model.ApplyFrameworkRestrictions ( [ FrameworkRestriction.Exactly (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_6_1) ] ) + model.ApplyFrameworkRestrictions (FrameworkRestriction.Exactly (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_6_1)) filteredModel.GetLegacyReferences(SinglePlatform(DotNetFramework(FrameworkVersion.V4_6_1))) |> Seq.map (fun f -> f.Path) @@ -853,12 +853,12 @@ let ``prefer net20 over empty folder``() = let model = InstallModel.CreateFromLibs (PackageName "EPPlus", SemVer.Parse "4.0.5", - [ ], + FrameworkRestriction.NoRestriction, [ @"..\EPPlus\lib\readme.txt" @"..\EPPlus\lib\net20\EPPlus.dll" ] |> fromLegacyList @"..\EPPlus\", [], [], Nuspec.All) let filteredModel = - model.ApplyFrameworkRestrictions ( [ FrameworkRestriction.Exactly (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_6_1) ] ) + model.ApplyFrameworkRestrictions (FrameworkRestriction.Exactly (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_6_1)) filteredModel.GetLegacyReferences(SinglePlatform(DotNetFramework(FrameworkVersion.V4_6_1))) |> Seq.map (fun f -> f.Path) @@ -871,7 +871,7 @@ let ``prefer net20 over empty folder``() = [] let ``should understand xamarinios``() = - let model = emptymodel.ApplyFrameworkRestrictions ([FrameworkRestriction.Exactly (XamariniOS)]) + let model = emptymodel.ApplyFrameworkRestrictions (FrameworkRestriction.Exactly (XamariniOS)) let model = model.AddReferences ([ @"..\FSharp.Core\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll" ] |> fromLegacyList @"..\FSharp.Core\") model.GetLegacyReferences(SinglePlatform (XamariniOS)) diff --git a/tests/Paket.Tests/InstallModel/Xml/CodeCracker.fs b/tests/Paket.Tests/InstallModel/Xml/CodeCracker.fs index 8f191e0649..12e8057042 100644 --- a/tests/Paket.Tests/InstallModel/Xml/CodeCracker.fs +++ b/tests/Paket.Tests/InstallModel/Xml/CodeCracker.fs @@ -3,6 +3,7 @@ open FsUnit open NUnit.Framework open Paket +open Paket.Requirements open Paket.Domain open Paket.TestHelpers @@ -23,7 +24,7 @@ let expectedCsharp = """ let ``should generate Xml for codecracker.CSharp``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "codecracker.CSharp", SemVer.Parse "1.0.0-rc2", [], + InstallModel.CreateFromLibs(PackageName "codecracker.CSharp", SemVer.Parse "1.0.0-rc2", FrameworkRestriction.NoRestriction, [], [], [ @@ -45,7 +46,7 @@ let ``should generate Xml for codecracker.CSharp``() = let ``should generate Xml for codecracker.CSharp in VisualBasic project``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "codecracker.CSharp", SemVer.Parse "1.0.0-rc2", [], + InstallModel.CreateFromLibs(PackageName "codecracker.CSharp", SemVer.Parse "1.0.0-rc2", FrameworkRestriction.NoRestriction, [], [], [ @@ -76,7 +77,7 @@ let expectedVb = """ let ``should generate Xml for codecracker.VisualBasic``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "codecracker.VisualBasic", SemVer.Parse "1.0.0-rc2", [], + InstallModel.CreateFromLibs(PackageName "codecracker.VisualBasic", SemVer.Parse "1.0.0-rc2", FrameworkRestriction.NoRestriction, [], [], [ diff --git a/tests/Paket.Tests/InstallModel/Xml/EmptyLibs.fs b/tests/Paket.Tests/InstallModel/Xml/EmptyLibs.fs index 3a69904a96..670258c47e 100644 --- a/tests/Paket.Tests/InstallModel/Xml/EmptyLibs.fs +++ b/tests/Paket.Tests/InstallModel/Xml/EmptyLibs.fs @@ -18,7 +18,7 @@ let expected = """ let ``should generate Xml for framework references and empty libs``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "TempPkg", SemVer.Parse "0.1", [], + InstallModel.CreateFromLibs(PackageName "TempPkg", SemVer.Parse "0.1", FrameworkRestriction.NoRestriction, [ ], [], [], diff --git a/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs b/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs index 16e2709309..2fe6b1e033 100644 --- a/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs +++ b/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs @@ -32,7 +32,7 @@ let ``should generate Xml for FSharp.Data.SqlClient 1.4.4``() = if not isMonoRuntime then // TODO - figure out why nuspec content is different on Mono ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "FSharp.Data.SqlClient", SemVer.Parse "1.4.4", [], + InstallModel.CreateFromLibs(PackageName "FSharp.Data.SqlClient", SemVer.Parse "1.4.4", FrameworkRestriction.NoRestriction, [ @"..\FSharp.Data.SqlClient\lib\net40\FSharp.Data.SqlClient.dll" @"..\FSharp.Data.SqlClient\lib\net40\FSharp.Data.SqlClient.pdb" @"..\FSharp.Data.SqlClient\lib\net40\FSharp.Data.SqlClient.XML" diff --git a/tests/Paket.Tests/InstallModel/Xml/Fantomas.fs b/tests/Paket.Tests/InstallModel/Xml/Fantomas.fs index 73a70a84a1..c482357eab 100644 --- a/tests/Paket.Tests/InstallModel/Xml/Fantomas.fs +++ b/tests/Paket.Tests/InstallModel/Xml/Fantomas.fs @@ -22,7 +22,7 @@ let fromLegacyList = Paket.InstallModel.ProcessingSpecs.fromLegacyList let ``should generate Xml for Fantomas 1.5``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList @"..\Fantomas\", @@ -60,7 +60,7 @@ let fullDoc = """ let ``should generate full Xml for Fantomas 1.5``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList @"..\Fantomas\", @@ -82,7 +82,7 @@ let ``should generate full Xml for Fantomas 1.5``() = let ``should not generate full Xml for Fantomas 1.5 if not referenced``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList @"..\Fantomas\", @@ -119,7 +119,7 @@ let fullDocWithRefernceCondition = """ let ``should generate full Xml with reference condition for Fantomas 1.5``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList @"..\Fantomas\", @@ -163,7 +163,7 @@ let ``should generate full Xml with reference condition and framework restrictio let model = InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [ FrameworkRestriction.Exactly (FrameworkIdentifier.XamariniOS) - FrameworkRestriction.Exactly (FrameworkIdentifier.MonoAndroid)], + FrameworkRestriction.Exactly (FrameworkIdentifier.MonoAndroid)] |> makeOrList |> getExplicitRestriction, [ @"..\Fantomas\lib\portable-net45+win8\FantomasLib.dll" ] |> fromLegacyList @"..\Fantomas\", [], [], diff --git a/tests/Paket.Tests/InstallModel/Xml/FantomasLib.fs b/tests/Paket.Tests/InstallModel/Xml/FantomasLib.fs index 1e4e5111b8..8cdeaf204b 100644 --- a/tests/Paket.Tests/InstallModel/Xml/FantomasLib.fs +++ b/tests/Paket.Tests/InstallModel/Xml/FantomasLib.fs @@ -20,7 +20,7 @@ let expected = """ let ``should generate Xml for Fantomas 1.5``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\Lib\FantomasLib.dll" @"..\Fantomas\Lib\FSharp.Core.dll" @"..\Fantomas\Lib\Fantomas.exe" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\Fantomas\", diff --git a/tests/Paket.Tests/InstallModel/Xml/Fuchu.fs b/tests/Paket.Tests/InstallModel/Xml/Fuchu.fs index 26b83b2df0..53e030f02a 100644 --- a/tests/Paket.Tests/InstallModel/Xml/Fuchu.fs +++ b/tests/Paket.Tests/InstallModel/Xml/Fuchu.fs @@ -20,7 +20,7 @@ let expected = """ let ``should generate Xml for Fuchu 0.4``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fuchu", SemVer.Parse "0.4.0", [], + InstallModel.CreateFromLibs(PackageName "Fuchu", SemVer.Parse "0.4.0", FrameworkRestriction.NoRestriction, [ @"..\Fuchu\lib\Fuchu.dll" @"..\Fuchu\lib\Fuchu.XML" @"..\Fuchu\lib\Fuchu.pdb" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\Fuchu\", diff --git a/tests/Paket.Tests/InstallModel/Xml/GitInfoPlanter.fs b/tests/Paket.Tests/InstallModel/Xml/GitInfoPlanter.fs index d42d35698a..85d3de7524 100644 --- a/tests/Paket.Tests/InstallModel/Xml/GitInfoPlanter.fs +++ b/tests/Paket.Tests/InstallModel/Xml/GitInfoPlanter.fs @@ -20,7 +20,7 @@ let expectedPropertyNodes = """ let ``should generate Xml for GitInfoPlanter2.0.0``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "GitInfoPlanter", SemVer.Parse "0.21", [], + InstallModel.CreateFromLibs(PackageName "GitInfoPlanter", SemVer.Parse "0.21", FrameworkRestriction.NoRestriction, [ ], [ @"..\GitInfoPlanter\build\GitInfoPlanter.targets" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\GitInfoPlanter\", diff --git a/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs b/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs index 245e87531f..df666b697e 100644 --- a/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs +++ b/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs @@ -36,7 +36,7 @@ let expectedPropertyNodes = """ let ``should generate Xml for LibGit2Sharp 2.0.0``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "LibGit2Sharp", SemVer.Parse "0.21", [], + InstallModel.CreateFromLibs(PackageName "LibGit2Sharp", SemVer.Parse "0.21", FrameworkRestriction.NoRestriction, [ @"..\LibGit2Sharp\lib\net40\LibGit2Sharp.dll" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\LibGit2Sharp\", [ @"..\LibGit2Sharp\build\net40\LibGit2Sharp.props" ] diff --git a/tests/Paket.Tests/InstallModel/Xml/ManualNodes.fs b/tests/Paket.Tests/InstallModel/Xml/ManualNodes.fs index 7a0c03a992..4663a6fea5 100644 --- a/tests/Paket.Tests/InstallModel/Xml/ManualNodes.fs +++ b/tests/Paket.Tests/InstallModel/Xml/ManualNodes.fs @@ -13,7 +13,7 @@ let fromLegacyList = Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\Fant let ``should find custom nodes in doc``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList, @@ -28,7 +28,7 @@ let ``should find custom nodes in doc``() = let ``should find custom Paket nodes in doc``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList, @@ -44,7 +44,7 @@ let ``should find custom Paket nodes in doc``() = let ``should not find custom nodes if there are none``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList, @@ -60,7 +60,7 @@ let ``should not find custom nodes if there are none``() = let ``should delete custom nodes if there are some``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Fantomas", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Fantomas\lib\FantomasLib.dll" @"..\Fantomas\lib\FSharp.Core.dll" @"..\Fantomas\lib\Fantomas.exe" ] |> fromLegacyList, diff --git a/tests/Paket.Tests/InstallModel/Xml/Microsoft.Bcl.Build.fs b/tests/Paket.Tests/InstallModel/Xml/Microsoft.Bcl.Build.fs index 8307878950..a909cbfccd 100644 --- a/tests/Paket.Tests/InstallModel/Xml/Microsoft.Bcl.Build.fs +++ b/tests/Paket.Tests/InstallModel/Xml/Microsoft.Bcl.Build.fs @@ -4,13 +4,14 @@ open Paket open NUnit.Framework open FsUnit open Paket.Domain +open Paket.Requirements open Paket.TestHelpers [] let ``should not install targets node for Microsoft.Bcl.Build``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Microsoft.Bcl.Build", SemVer.Parse "1.0.21", [], + InstallModel.CreateFromLibs(PackageName "Microsoft.Bcl.Build", SemVer.Parse "1.0.21", FrameworkRestriction.NoRestriction, [ ], [ @"..\Microsoft.Bcl.Build\build\Microsoft.Bcl.Build.Tasks.dll"; @"..\Microsoft.Bcl.Build\build\Microsoft.Bcl.Build.targets" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\Microsoft.Bcl.Build\", diff --git a/tests/Paket.Tests/InstallModel/Xml/Microsoft.CodeAnalysis.Analyzers.fs b/tests/Paket.Tests/InstallModel/Xml/Microsoft.CodeAnalysis.Analyzers.fs index 1d6302cb7a..d0cc3ce7df 100644 --- a/tests/Paket.Tests/InstallModel/Xml/Microsoft.CodeAnalysis.Analyzers.fs +++ b/tests/Paket.Tests/InstallModel/Xml/Microsoft.CodeAnalysis.Analyzers.fs @@ -3,6 +3,7 @@ open FsUnit open NUnit.Framework open Paket +open Paket.Requirements open Paket.Constants open Paket.Domain open Paket.TestHelpers @@ -10,7 +11,7 @@ open System.Text open System.IO let model = - InstallModel.CreateFromLibs(PackageName "Microsoft.CodeAnalysis.Analyzers", SemVer.Parse "1.0.0", [], + InstallModel.CreateFromLibs(PackageName "Microsoft.CodeAnalysis.Analyzers", SemVer.Parse "1.0.0", FrameworkRestriction.NoRestriction, [], [], [ @@ -64,7 +65,7 @@ let ``should generate Xml for RefactoringEssentials in VisualBasic project``() = |> shouldEqual (normalizeXml expectedVb) let oldModel = - InstallModel.CreateFromLibs(PackageName "Microsoft.CodeAnalysis.Analyzers", SemVer.Parse "1.0.0-rc2", [], + InstallModel.CreateFromLibs(PackageName "Microsoft.CodeAnalysis.Analyzers", SemVer.Parse "1.0.0-rc2", FrameworkRestriction.NoRestriction, [], [], [], // Analyzers weren't in the correct folder and won't be found for this version diff --git a/tests/Paket.Tests/InstallModel/Xml/Plossum.fs b/tests/Paket.Tests/InstallModel/Xml/Plossum.fs index fcb895fa3d..e76636afe5 100644 --- a/tests/Paket.Tests/InstallModel/Xml/Plossum.fs +++ b/tests/Paket.Tests/InstallModel/Xml/Plossum.fs @@ -24,7 +24,7 @@ let expected = """ let ``should generate Xml for Plossum``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Plossum.CommandLine", SemVer.Parse "1.5.0", [], + InstallModel.CreateFromLibs(PackageName "Plossum.CommandLine", SemVer.Parse "1.5.0", FrameworkRestriction.NoRestriction, [ @"..\Plossum.CommandLine\lib\net40\Plossum CommandLine.dll" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\Plossum.CommandLine\", [], diff --git a/tests/Paket.Tests/InstallModel/Xml/RefactoringEssentials.fs b/tests/Paket.Tests/InstallModel/Xml/RefactoringEssentials.fs index 76eaefaf69..b9746c6d7c 100644 --- a/tests/Paket.Tests/InstallModel/Xml/RefactoringEssentials.fs +++ b/tests/Paket.Tests/InstallModel/Xml/RefactoringEssentials.fs @@ -3,6 +3,7 @@ open FsUnit open NUnit.Framework open Paket +open Paket.Requirements open Paket.Domain open Paket.TestHelpers @@ -17,7 +18,7 @@ let expected = """ let ``should generate Xml for RefactoringEssentials in CSharp project``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "RefactoringEssentials", SemVer.Parse "1.2.0", [], + InstallModel.CreateFromLibs(PackageName "RefactoringEssentials", SemVer.Parse "1.2.0", FrameworkRestriction.NoRestriction, [], [], [ @@ -37,7 +38,7 @@ let ``should generate Xml for RefactoringEssentials in CSharp project``() = let ``should generate Xml for RefactoringEssentials in VisualBasic project``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "RefactoringEssentials", SemVer.Parse "1.2.0", [], + InstallModel.CreateFromLibs(PackageName "RefactoringEssentials", SemVer.Parse "1.2.0", FrameworkRestriction.NoRestriction, [], [], [ diff --git a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs index 8e29541839..5d44560dcf 100644 --- a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs +++ b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs @@ -90,7 +90,7 @@ let expected = """ let ``should generate Xml for Rx-XAML 2.2.4 with correct framework assembly references``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "Rx-XAML", SemVer.Parse "2.2.4", [], + InstallModel.CreateFromLibs(PackageName "Rx-XAML", SemVer.Parse "2.2.4", FrameworkRestriction.NoRestriction, [ @"..\Rx-XAML\lib\net40\System.Reactive.Windows.Threading.dll" @"..\Rx-XAML\lib\net45\System.Reactive.Windows.Threading.dll" @"..\Rx-XAML\lib\portable-win81+wpa81\System.Reactive.Windows.Threading.dll" @@ -108,10 +108,10 @@ let ``should generate Xml for Rx-XAML 2.2.4 with correct framework assembly refe LicenseUrl = "" IsDevelopmentDependency = false FrameworkAssemblyReferences = - [{ AssemblyName = "WindowsBase"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4_5)] } - { AssemblyName = "WindowsBase"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4)] } - { AssemblyName = "System.Windows"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(Silverlight "v5.0")] } - { AssemblyName = "System.Windows"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(WindowsPhoneSilverlight "v7.1")] }]}) + [{ AssemblyName = "WindowsBase"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4_5)] } + { AssemblyName = "WindowsBase"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4)] } + { AssemblyName = "System.Windows"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(Silverlight "v5.0")] } + { AssemblyName = "System.Windows"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(WindowsPhoneSilverlight "v7.1")] }]}) let ctx = ProjectFile.TryLoad("./ProjectFile/TestData/Empty.fsprojtest").Value.GenerateXml(model, System.Collections.Generic.HashSet<_>(),Map.empty,Some true,true,KnownTargetProfiles.AllProfiles,None) let currentXml = ctx.ChooseNodes.Head.OuterXml |> normalizeXml diff --git a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs index cbdcddb89d..15cca76c41 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs @@ -142,7 +142,7 @@ let ``should init model for SQLite``() = [] let ``should generate model for SQLite``() = let model = - InstallModel.CreateFromLibs(PackageName "System.Data.SQLite.Core", SemVer.Parse "3.8.2", [], + InstallModel.CreateFromLibs(PackageName "System.Data.SQLite.Core", SemVer.Parse "3.8.2", FrameworkRestriction.NoRestriction, [ @"..\System.Data.SQLite.Core\lib\net20\System.Data.SQLite.dll" @"..\System.Data.SQLite.Core\lib\net40\System.Data.SQLite.dll" @"..\System.Data.SQLite.Core\lib\net45\System.Data.SQLite.dll" @@ -164,7 +164,7 @@ let ``should generate model for SQLite``() = let ``should generate Xml for SQLite``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "System.Data.SQLite.Core", SemVer.Parse "3.8.2", [], + InstallModel.CreateFromLibs(PackageName "System.Data.SQLite.Core", SemVer.Parse "3.8.2", FrameworkRestriction.NoRestriction, [ @"..\System.Data.SQLite.Core\lib\net20\System.Data.SQLite.dll" @"..\System.Data.SQLite.Core\lib\net40\System.Data.SQLite.dll" @"..\System.Data.SQLite.Core\lib\net45\System.Data.SQLite.dll" diff --git a/tests/Paket.Tests/InstallModel/Xml/StyleCop.MSBuild.fs b/tests/Paket.Tests/InstallModel/Xml/StyleCop.MSBuild.fs index 1bb145d462..a4a63f7b2f 100644 --- a/tests/Paket.Tests/InstallModel/Xml/StyleCop.MSBuild.fs +++ b/tests/Paket.Tests/InstallModel/Xml/StyleCop.MSBuild.fs @@ -17,7 +17,7 @@ let expectedPropertyNodes = """ let ``should generate Xml for StyleCop.MSBuild``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "StyleCop.MSBuild", SemVer.Parse "4.7.49.1", [],[], + InstallModel.CreateFromLibs(PackageName "StyleCop.MSBuild", SemVer.Parse "4.7.49.1", FrameworkRestriction.NoRestriction,[], [ @"..\StyleCop.MSBuild\build\StyleCop.MSBuild.Targets" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\StyleCop.MSBuild\", [], Nuspec.All) diff --git a/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs b/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs index 751aeef144..88e65b5daa 100644 --- a/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs +++ b/tests/Paket.Tests/InstallModel/Xml/System.Security.Cryptography.Algorithms.fs @@ -3,6 +3,7 @@ open FsUnit open NUnit.Framework open Paket +open Paket.Requirements open Paket.Domain open Paket.TestHelpers @@ -68,7 +69,7 @@ let expected = """ let ``should generate Xml for System.Security.Cryptography.Algorithms in CSharp project``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "System.Security.Cryptography.Algorithms", SemVer.Parse "1.2.0", [], + InstallModel.CreateFromLibs(PackageName "System.Security.Cryptography.Algorithms", SemVer.Parse "1.2.0", FrameworkRestriction.NoRestriction, [ @"..\System.Security.Cryptography.Algorithms\lib\net46\System.Security.Cryptography.Algorithms.dll" @"..\System.Security.Cryptography.Algorithms\lib\net461\System.Security.Cryptography.Algorithms.dll" @"..\System.Security.Cryptography.Algorithms\lib\net463\System.Security.Cryptography.Algorithms.dll" diff --git a/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs b/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs index cda2855da0..ecb2413049 100644 --- a/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs +++ b/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs @@ -33,7 +33,7 @@ let expected = """ let ``should generate Xml for System.Spatial``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "System.Spatial", SemVer.Parse "5.6.3", [], + InstallModel.CreateFromLibs(PackageName "System.Spatial", SemVer.Parse "5.6.3", FrameworkRestriction.NoRestriction, [ @"..\System.Spatial\lib\net40\System.Spatial.dll" @"..\System.Spatial\lib\net40\de\System.Spatial.resources.dll" @"..\System.Spatial\lib\net40\es\System.Spatial.resources.dll" diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs index 57a4ae51e8..d492acfbf5 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs @@ -156,7 +156,7 @@ let expected = """ let ``should generate Xml for System.Net.Http 2.2.8``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", [], + InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", FrameworkRestriction.NoRestriction, [ @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Extensions.dll" @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Primitives.dll" diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs index 45fb5b0482..239758ed4e 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs @@ -39,7 +39,7 @@ let expected = """ let ``should generate Xml for System.Net.Http 2.2.8``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4))], + InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4)), [ @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Extensions.dll" @"..\Microsoft.Net.Http\lib\monoandroid\System.Net.Http.Primitives.dll" diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs index 7b3e354817..85c86180e7 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs @@ -51,7 +51,7 @@ let expected = """ let ``should generate Xml for System.Net.Http 2.2.8``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", [], + InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", FrameworkRestriction.NoRestriction, [ @"..\Microsoft.Net.Http\lib\net40\System.Net.Http.dll" @"..\Microsoft.Net.Http\lib\net40\System.Net.Http.Extensions.dll" @"..\Microsoft.Net.Http\lib\net40\System.Net.Http.Primitives.dll" @@ -69,8 +69,8 @@ let ``should generate Xml for System.Net.Http 2.2.8``() = LicenseUrl = "" IsDevelopmentDependency = false FrameworkAssemblyReferences = - [{ AssemblyName = "System.Net.Http"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] } - { AssemblyName = "System.Net.Http.WebRequest"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }]}) + [{ AssemblyName = "System.Net.Http"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] } + { AssemblyName = "System.Net.Http.WebRequest"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }]}) let ctx = ProjectFile.TryLoad("./ProjectFile/TestData/FrameworkAssemblies.fsprojtest").Value.GenerateXml(model, System.Collections.Generic.HashSet<_>(),Map.empty,Some true,true,KnownTargetProfiles.AllProfiles,None) let currentXML = ctx.ChooseNodes.Head.OuterXml |> normalizeXml diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs index f24880ef43..0c642a9e3e 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs @@ -59,7 +59,7 @@ let expected = """ let ``should generate Xml for System.Net.Http 2.2.8``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", [], + InstallModel.CreateFromLibs(PackageName "System.Net.Http", SemVer.Parse "2.2.8", FrameworkRestriction.NoRestriction, [ @"..\Microsoft.Net.Http\lib\net40\System.Net.Http.dll" @"..\Microsoft.Net.Http\lib\net40\System.Net.Http.Extensions.dll" @"..\Microsoft.Net.Http\lib\net40\System.Net.Http.Primitives.dll" @@ -76,8 +76,8 @@ let ``should generate Xml for System.Net.Http 2.2.8``() = LicenseUrl = "" IsDevelopmentDependency = false FrameworkAssemblyReferences = - [{ AssemblyName = "System.Net.Http"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))] } - { AssemblyName = "System.Net.Http.WebRequest"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }]}) + [{ AssemblyName = "System.Net.Http"; FrameworkRestrictions = makeOrList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))] } + { AssemblyName = "System.Net.Http.WebRequest"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }]}) let ctx = ProjectFile.TryLoad("./ProjectFile/TestData/Empty.fsprojtest").Value.GenerateXml(model, System.Collections.Generic.HashSet<_>(),Map.empty,Some true,true,KnownTargetProfiles.AllProfiles,None) let currentXML = ctx.ChooseNodes.Head.OuterXml |> normalizeXml diff --git a/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs b/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs index 03502e2d00..314b4741d3 100644 --- a/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs +++ b/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs @@ -31,7 +31,7 @@ let expectedPropertyDefinitionNodes = """ let ``should generate Xml for xunit.runner.visualstudio 2.0.0``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "xunit.runner.visualstudio", SemVer.Parse "2.50.0", [],[], + InstallModel.CreateFromLibs(PackageName "xunit.runner.visualstudio", SemVer.Parse "2.50.0", FrameworkRestriction.NoRestriction,[], [ @"..\xunit.runner.visualstudio\build\net20\xunit.runner.visualstudio.props" @"..\xunit.runner.visualstudio\build\portable-net45+aspnetcore50+win+wpa81+wp80+monotouch+monoandroid\xunit.runner.visualstudio.props" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\xunit.runner.visualstudio\", @@ -63,7 +63,7 @@ let disabledChooseNode = """ let ``should not generate Xml for xunit.runner.visualstudio 2.0.0 if import is disabled``() = ensureDir() let model = - InstallModel.CreateFromLibs(PackageName "xunit.runner.visualstudio", SemVer.Parse "2.50.0", [],[], + InstallModel.CreateFromLibs(PackageName "xunit.runner.visualstudio", SemVer.Parse "2.50.0", FrameworkRestriction.NoRestriction,[], [ @"..\xunit.runner.visualstudio\build\net20\xunit.runner.visualstudio.props" @"..\xunit.runner.visualstudio\build\portable-net45+aspnetcore50+win+wpa81+wp80+monotouch+monoandroid\xunit.runner.visualstudio.props" ] |> Paket.InstallModel.ProcessingSpecs.fromLegacyList @"..\xunit.runner.visualstudio\", diff --git a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs index 5b7a5eacd2..9bb093a24f 100644 --- a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs +++ b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs @@ -191,14 +191,14 @@ NUGET let cfg = DependenciesFile.FromSource(config) let group = cfg.Groups.[Constants.MainDependencyGroup] group.Packages.Head.Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual [FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client)) ] + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) let resolved = ResolveWithGraph(cfg,noSha1,VersionsFromGraphAsSeq graph, PackageDetailsFromGraph graph).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() getVersion resolved.[PackageName "NLog"] |> shouldEqual "1.0.1" resolved.[PackageName "NLog"].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual [FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client)) ] + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) resolved |> LockFileSerializer.serializePackages cfg.Groups.[Constants.MainDependencyGroup].Options diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index 12c1e4da35..a11ea68208 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -47,12 +47,12 @@ let ``should parse lock file``() = packages.[1].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[1].Name |> shouldEqual (PackageName "Castle.Windsor-log4net") packages.[1].Version |> shouldEqual (SemVer.Parse "3.3") - packages.[1].Dependencies |> shouldEqual (Set.ofList [PackageName "Castle.Windsor", VersionRequirement(Minimum(SemVer.Parse "2.0"), PreReleaseStatus.No), FrameworkRestrictionList []; PackageName "log4net", VersionRequirement(Minimum(SemVer.Parse "1.0"), PreReleaseStatus.No), FrameworkRestrictionList []]) + packages.[1].Dependencies |> shouldEqual (Set.ofList [PackageName "Castle.Windsor", VersionRequirement(Minimum(SemVer.Parse "2.0"), PreReleaseStatus.No), makeOrList []; PackageName "log4net", VersionRequirement(Minimum(SemVer.Parse "1.0"), PreReleaseStatus.No), makeOrList []]) packages.[5].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[5].Name |> shouldEqual (PackageName "log4net") packages.[5].Version |> shouldEqual (SemVer.Parse "1.1") - packages.[5].Dependencies |> shouldEqual (Set.ofList [PackageName "log", VersionRequirement(Minimum(SemVer.Parse "1.0"), PreReleaseStatus.No), FrameworkRestrictionList []]) + packages.[5].Dependencies |> shouldEqual (Set.ofList [PackageName "log", VersionRequirement(Minimum(SemVer.Parse "1.0"), PreReleaseStatus.No), makeOrList []]) let sourceFiles = List.rev lockFile.SourceFiles sourceFiles|> shouldEqual @@ -111,7 +111,7 @@ let ``should parse strict lock file``() = packages.[5].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[5].Name |> shouldEqual (PackageName "log4net") packages.[5].Version |> shouldEqual (SemVer.Parse "1.1") - packages.[5].Dependencies |> shouldEqual (Set.ofList [PackageName "log", VersionRequirement(Minimum(SemVer.Parse "1.0"), PreReleaseStatus.No), FrameworkRestrictionList []]) + packages.[5].Dependencies |> shouldEqual (Set.ofList [PackageName "log", VersionRequirement(Minimum(SemVer.Parse "1.0"), PreReleaseStatus.No), makeOrList []]) let redirectsLockFile = """REDIRECTS: ON IMPORT-TARGETS: TRUE @@ -224,7 +224,7 @@ let ``should parse own lock file``() = packages.[1].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[1].Name |> shouldEqual (PackageName "FAKE") packages.[1].Version |> shouldEqual (SemVer.Parse "3.5.5") - packages.[1].Settings.FrameworkRestrictions |> shouldEqual (FrameworkRestrictionList []) + packages.[1].Settings.FrameworkRestrictions |> shouldEqual (makeOrList []) lockFile.SourceFiles.[0].Name |> shouldEqual "modules/Octokit/Octokit.fsx" @@ -274,7 +274,7 @@ let ``should parse own lock file2``() = packages.[1].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[1].Name |> shouldEqual (PackageName "FAKE") packages.[1].Version |> shouldEqual (SemVer.Parse "3.5.5") - packages.[3].Settings.FrameworkRestrictions |> shouldEqual (FrameworkRestrictionList []) + packages.[3].Settings.FrameworkRestrictions |> shouldEqual (makeOrList []) lockFile.SourceFiles.[0].Name |> shouldEqual "modules/Octokit/Octokit.fsx" @@ -306,37 +306,37 @@ let ``should parse framework restricted lock file``() = packages.[0].Dependencies |> Set.toList |> List.map (fun (_, _, r) -> r) |> List.item 2 - |> getRestrictionList - |> shouldEqual ([FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))]) + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) packages.[3].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[3].Name |> shouldEqual (PackageName "LinqBridge") packages.[3].Version |> shouldEqual (SemVer.Parse "1.3.0") packages.[3].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual ([FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2),FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))]) + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2),FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))) packages.[3].Settings.ImportTargets |> shouldEqual None let dependencies4 = packages.[4].Dependencies |> Set.toList |> List.map (fun (_, _, r) -> r) dependencies4.Head - |> getRestrictionList - |> shouldEqual ([FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2), FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))]) + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2), FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))) dependencies4.Tail.Head - |> getRestrictionList + |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))]) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) packages.[5].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[5].Name |> shouldEqual (PackageName "ReadOnlyCollectionInterfaces") packages.[5].Version |> shouldEqual (SemVer.Parse "1.0.0") packages.[5].Settings.FrameworkRestrictions - |> getRestrictionList + |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))]) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) let frameworkRestricted' = """NUGET remote: https://www.nuget.org/api/v2 @@ -365,16 +365,16 @@ let ``should parse framework restricted lock file in new syntax``() = packages.[0].Dependencies |> Set.toList |> List.map (fun (_, _, r) -> r) |> List.item 2 - |> getRestrictionList - |> shouldEqual ([FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))]) + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) packages.[3].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[3].Name |> shouldEqual (PackageName "LinqBridge") packages.[3].Version |> shouldEqual (SemVer.Parse "1.3.0") packages.[3].Settings.CopyContentToOutputDirectory |> shouldEqual (Some CopyToOutputDirectorySettings.Never) packages.[3].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual ([FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2),FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))]) + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2),FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))) packages.[3].Settings.CopyLocal |> shouldEqual None packages.[3].Settings.ImportTargets |> shouldEqual (Some false) packages.[3].Settings.IncludeVersionInPath |> shouldEqual (Some true) @@ -384,13 +384,13 @@ let ``should parse framework restricted lock file in new syntax``() = packages.[4].Dependencies |> Set.toList |> List.map (fun (_, _, r) -> r) dependencies4.Head - |> getRestrictionList - |> shouldEqual ([FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2), FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))]) + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.Between(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2), FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))) dependencies4.Tail.Head - |> getRestrictionList + |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))]) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) packages.[5].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[5].Name |> shouldEqual (PackageName "ReadOnlyCollectionInterfaces") @@ -400,10 +400,10 @@ let ``should parse framework restricted lock file in new syntax``() = packages.[5].Settings.OmitContent |> shouldEqual None packages.[5].Settings.IncludeVersionInPath |> shouldEqual None packages.[5].Settings.FrameworkRestrictions - |> getRestrictionList + |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))]) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) let simpleHTTP = """ HTTP @@ -465,7 +465,7 @@ let ``should parse portable lockfile``() = packages.[1].Name |> shouldEqual (PackageName "Zlib.Portable") packages.[1].Version |> shouldEqual (SemVer.Parse "1.10.0") - (packages.[1].Settings.FrameworkRestrictions |> getRestrictionList).ToString() |> shouldEqual "[portable-net40+sl50+wp80+win80]" + (packages.[1].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "[portable-net40+sl50+wp80+win80]" let reactiveuiLockFile = """NUGET remote: https://www.nuget.org/api/v2 @@ -512,11 +512,11 @@ let ``should parse reactiveui lockfile``() = packages.[8].Name |> shouldEqual (PackageName "Rx-WindowStoreApps") packages.[8].Version |> shouldEqual (SemVer.Parse "2.2.5") - (packages.[8].Settings.FrameworkRestrictions |> getRestrictionList).ToString() |> shouldEqual "[winv4.5]" + (packages.[8].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "[winv4.5]" packages.[10].Name |> shouldEqual (PackageName "Rx-Xaml") packages.[10].Version |> shouldEqual (SemVer.Parse "2.2.5") - (packages.[10].Settings.FrameworkRestrictions |> getRestrictionList).ToString() |> shouldEqual "[winv4.5; wpv8.0; >= net45]" + (packages.[10].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "[winv4.5; wpv8.0; >= net45]" let multipleFeedLockFile = """NUGET remote: http://internalfeed/NugetWebFeed/nuget diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index 3ae2ebe54f..8fb8485c6e 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -8,6 +8,7 @@ open Paket.NuGetV2 open Paket.NuGetV3 open Paket.Requirements +open Paket.TestHelpers open Domain let fakeUrl = "http://doesntmatter" @@ -21,7 +22,7 @@ let ``can detect explicit dependencies for Fantomas``() = |> shouldEqual { PackageName = "Fantomas" DownloadUrl = "http://www.nuget.org/api/v2/package/Fantomas/1.6.0" - Dependencies = [PackageName "FSharp.Compiler.Service",DependenciesFileParser.parseVersionRequirement(">= 0.0.73"), FrameworkRestrictionList []] + Dependencies = [PackageName "FSharp.Compiler.Service",DependenciesFileParser.parseVersionRequirement(">= 0.0.73"), makeOrList []] Unlisted = false LicenseUrl = "http://github.com/dungpa/fantomas/blob/master/LICENSE.md" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion @@ -35,8 +36,8 @@ let ``can detect explicit dependencies for Rx-PlaformServices``() = { PackageName = "Rx-PlatformServices" DownloadUrl = "https://www.nuget.org/api/v2/package/Rx-PlatformServices/2.3.0" Dependencies = - [PackageName "Rx-Interfaces",DependenciesFileParser.parseVersionRequirement(">= 2.2"), FrameworkRestrictionList [] - PackageName "Rx-Core",DependenciesFileParser.parseVersionRequirement(">= 2.2"), FrameworkRestrictionList []] + [PackageName "Rx-Interfaces",DependenciesFileParser.parseVersionRequirement(">= 2.2"), makeOrList [] + PackageName "Rx-Core",DependenciesFileParser.parseVersionRequirement(">= 2.2"), makeOrList []] Unlisted = true LicenseUrl = "http://go.microsoft.com/fwlink/?LinkID=261272" Version = "2.3.0" @@ -50,7 +51,7 @@ let ``can detect explicit dependencies for EasyNetQ``() = { PackageName = "EasyNetQ" DownloadUrl = "https://www.nuget.org/api/v2/package/EasyNetQ/0.40.3.352" Dependencies = - [PackageName "RabbitMQ.Client",DependenciesFileParser.parseVersionRequirement(">= 3.4.3"),FrameworkRestrictionList []] + [PackageName "RabbitMQ.Client",DependenciesFileParser.parseVersionRequirement(">= 3.4.3"),makeOrList []] Unlisted = false LicenseUrl = "https://github.com/mikehadlow/EasyNetQ/blob/master/licence.txt" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion @@ -68,10 +69,10 @@ let ``can detect explicit dependencies for Fleece``() = LicenseUrl = "https://raw.github.com/mausch/Fleece/master/LICENSE" Version = "0.4.0" Dependencies = - [PackageName "FSharpPlus",DependenciesFileParser.parseVersionRequirement(">= 0.0.4"),FrameworkRestrictionList [] - PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"),FrameworkRestrictionList [] - PackageName "ReadOnlyCollectionExtensions",DependenciesFileParser.parseVersionRequirement(">= 1.2.0"),FrameworkRestrictionList [] - PackageName "System.Json",DependenciesFileParser.parseVersionRequirement(">= 4.0.20126.16343"),FrameworkRestrictionList []] + [PackageName "FSharpPlus",DependenciesFileParser.parseVersionRequirement(">= 0.0.4"),makeOrList [] + PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"),makeOrList [] + PackageName "ReadOnlyCollectionExtensions",DependenciesFileParser.parseVersionRequirement(">= 1.2.0"),makeOrList [] + PackageName "System.Json",DependenciesFileParser.parseVersionRequirement(">= 4.0.20126.16343"),makeOrList []] SourceUrl = fakeUrl } [] @@ -85,9 +86,9 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = LicenseUrl = "https://github.com/mausch/ReadOnlyCollections/blob/master/license.txt" Version = "1.2.0" Dependencies = - [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"),FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] + [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"),makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V3_5))]] SourceUrl = fakeUrl } @@ -103,7 +104,7 @@ let ``can detect explicit dependencies for Math.Numerics``() = LicenseUrl = "http://numerics.mathdotnet.com/docs/License.html" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion Dependencies = - [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))]] + [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))]] SourceUrl = fakeUrl } [] @@ -111,7 +112,7 @@ let ``can detect explicit dependencies for Math.Numerics.FSharp``() = (parse "NuGetOData/Math.Numerics.FSharp.xml").Dependencies |> Seq.head |> shouldEqual (PackageName "MathNet.Numerics", - DependenciesFileParser.parseVersionRequirement("3.3.0"),FrameworkRestrictionList []) + DependenciesFileParser.parseVersionRequirement("3.3.0"),makeOrList []) [] let ``can calculate v3 path``() = @@ -126,10 +127,10 @@ let ``can detect explicit dependencies for Microsoft.AspNet.WebApi.Client``() = let dependencies = odata.Dependencies |> Array.ofList dependencies.[0] |> shouldEqual (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 6.0.4"), - FrameworkRestrictionList [FrameworkRestriction.Portable("portable-wp80+win+wp81+wpa81"); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]) + makeOrList [getPortableRestriction("portable-wp80+win+wp81+wpa81"); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]) dependencies.[1] |> shouldEqual (PackageName "Microsoft.Net.Http", DependenciesFileParser.parseVersionRequirement(">= 2.2.22"), - FrameworkRestrictionList [FrameworkRestriction.Portable("portable-wp80+win+wp81+wpa81")]) + makeOrList [getPortableRestriction("portable-wp80+win+wp81+wpa81")]) [] let ``can detect explicit dependencies for WindowsAzure.Storage``() = @@ -139,7 +140,7 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = let dependencies = odata.Dependencies |> Array.ofList dependencies.[0] |> shouldEqual (PackageName "Microsoft.Data.OData", DependenciesFileParser.parseVersionRequirement(">= 5.6.3"), - FrameworkRestrictionList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) let vr,pr = match DependenciesFileParser.parseVersionRequirement(">= 4.0.0-beta-22231") with @@ -147,11 +148,11 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = dependencies.[18] |> shouldEqual (PackageName "System.Net.Http", VersionRequirement(vr,PreReleaseStatus.All), - FrameworkRestrictionList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) dependencies.[44] |> shouldEqual (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 6.0.8"), - FrameworkRestrictionList [FrameworkRestriction.Exactly(WindowsPhoneSilverlight("v8.0")); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))]) + makeOrList [FrameworkRestriction.Exactly(WindowsPhoneSilverlight("v8.0")); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))]) [] let ``can ignore unknown frameworks``() = @@ -163,7 +164,7 @@ let ``can ignore unknown frameworks``() = [ PackageName "BenchmarkDotNet.Toolchains.Roslyn", DependenciesFileParser.parseVersionRequirement(">= 0.10.1"), - FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5)] + makeOrList [FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5)] ] Unlisted = false LicenseUrl = "https://github.com/dotnet/BenchmarkDotNet/blob/master/LICENSE.md" diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index fc554255de..c6b8d82fdf 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -88,13 +88,13 @@ let ``can detect framework assemblies for Microsoft.Net.Http``() = |> shouldEqual [{ AssemblyName = "System.Net.Http" FrameworkRestrictions = - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5)) FrameworkRestriction.Exactly(MonoTouch) FrameworkRestriction.Exactly(MonoAndroid)] } { AssemblyName = "System.Net.Http.WebRequest" FrameworkRestrictions = - FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }] + makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] }] [] let ``can detect deps assemblies for RazorEngine``() = @@ -102,25 +102,25 @@ let ``can detect deps assemblies for RazorEngine``() = Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"RazorEngine.nuspec")).Dependencies |> shouldEqual [PackageName "Microsoft.AspNet.Razor",DependenciesFileParser.parseVersionRequirement("= 2.0.30506.0"), - FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))] + makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))] PackageName "Microsoft.AspNet.Razor",DependenciesFileParser.parseVersionRequirement(">= 3.0.0"), - FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]] + makeOrList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]] [] let ``can detect framework assemblies for FluentAssertions``() = //ensureDir() Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"FluentAssertions.nuspec")).FrameworkAssemblyReferences |> shouldEqual - [{ AssemblyName = "System.Xml"; FrameworkRestrictions = FrameworkRestrictionList [] } - { AssemblyName = "System.Xml.Linq"; FrameworkRestrictions = FrameworkRestrictionList [] } ] + [{ AssemblyName = "System.Xml"; FrameworkRestrictions = makeOrList [] } + { AssemblyName = "System.Xml.Linq"; FrameworkRestrictions = makeOrList [] } ] [] let ``can detect framework assemblies for SqlCLient``() = //ensureDir() Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"FSharp.Data.SqlClient.nuspec")).FrameworkAssemblyReferences |> shouldEqual - [{ AssemblyName = "System.Data"; FrameworkRestrictions = FrameworkRestrictionList [] } - { AssemblyName = "System.Xml"; FrameworkRestrictions = FrameworkRestrictionList [] } ] + [{ AssemblyName = "System.Data"; FrameworkRestrictions = makeOrList [] } + { AssemblyName = "System.Xml"; FrameworkRestrictions = makeOrList [] } ] [] let ``can detect license for SqlCLient``() = @@ -133,7 +133,7 @@ let ``can detect dependencies for SqlCLient``() = //ensureDir() Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"FSharp.Data.SqlClient.nuspec")).Dependencies |> shouldEqual - [PackageName "Microsoft.SqlServer.Types",DependenciesFileParser.parseVersionRequirement(">= 11.0.0"), FrameworkRestrictionList []] + [PackageName "Microsoft.SqlServer.Types",DependenciesFileParser.parseVersionRequirement(">= 11.0.0"), makeOrList []] [] let ``can detect reference files for SqlCLient``() = @@ -148,7 +148,7 @@ let ``can detect framework assemblies for Octokit``() = |> shouldEqual [{ AssemblyName = "System.Net.Http" FrameworkRestrictions = - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5)) FrameworkRestriction.Exactly(Windows "v4.5")] }] @@ -157,8 +157,8 @@ let ``can detect framework assemblies for FSharp.Data.SqlEnumProvider``() = //ensureDir() Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"FSharp.Data.SqlEnumProvider.nuspec")).FrameworkAssemblyReferences |> shouldEqual - [{ AssemblyName = "System.Data"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))] } - { AssemblyName = "System.Xml"; FrameworkRestrictions = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))] }] + [{ AssemblyName = "System.Data"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))] } + { AssemblyName = "System.Xml"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))] }] [] let ``can detect empty framework assemblies for ReadOnlyCollectionExtensions``() = @@ -176,7 +176,7 @@ let ``can detect empty dependencies for log4net``() = let ``can detect explicit dependencies for Fantomas``() = //ensureDir() Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"Fantomas.nuspec")).Dependencies - |> shouldEqual [PackageName "FSharp.Compiler.Service",DependenciesFileParser.parseVersionRequirement(">= 0.0.57"), FrameworkRestrictionList []] + |> shouldEqual [PackageName "FSharp.Compiler.Service",DependenciesFileParser.parseVersionRequirement(">= 0.0.57"), makeOrList []] [] let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = @@ -184,9 +184,9 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"ReadOnlyCollectionExtensions.nuspec")).Dependencies |> shouldEqual [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"), - FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] + makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V3_5))]] @@ -202,7 +202,7 @@ let ``can detect explicit dependencies for Microsoft.AspNetCore.Antiforgery``() deps.[0] |> shouldEqual (PackageName "Microsoft.AspNetCore.DataProtection", VersionRequirement(v,PreReleaseStatus.All), - FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)); FrameworkRestriction.AtLeast (DotNetStandard(DotNetStandardVersion.V1_3))]) + makeOrList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)); FrameworkRestriction.AtLeast (DotNetStandard(DotNetStandardVersion.V1_3))]) [] let ``can detect explicit dependencies for Microsoft.AspNetCore.Mvc.ViewFeatures``() = @@ -216,7 +216,7 @@ let ``can detect explicit dependencies for Microsoft.AspNetCore.Mvc.ViewFeatures deps.[0] |> shouldEqual (PackageName "Microsoft.AspNetCore.Antiforgery", VersionRequirement(v,PreReleaseStatus.All), - FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)); FrameworkRestriction.AtLeast (DotNetStandard(DotNetStandardVersion.V1_5))]) + makeOrList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)); FrameworkRestriction.AtLeast (DotNetStandard(DotNetStandardVersion.V1_5))]) [] let ``can detect framework assemblies for MathNet.Numerics``() = @@ -225,7 +225,7 @@ let ``can detect framework assemblies for MathNet.Numerics``() = |> shouldEqual [{ AssemblyName = "System.Numerics" FrameworkRestrictions = - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client)) FrameworkRestriction.Exactly(Windows("v4.5")) FrameworkRestriction.Exactly(Silverlight("v5.0")) @@ -240,7 +240,7 @@ let ``can detect dependencies for MathNet.Numerics``() = |> shouldEqual [ PackageName "TaskParallelLibrary", DependenciesFileParser.parseVersionRequirement(">= 1.0.2856.0"), - FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] ] + makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] ] [] let ``can detect dependencies for MathNet.Numerics.FSharp``() = @@ -249,7 +249,7 @@ let ``can detect dependencies for MathNet.Numerics.FSharp``() = |> Seq.head |> shouldEqual (PackageName "MathNet.Numerics", - DependenciesFileParser.parseVersionRequirement("3.3.0"),FrameworkRestrictionList []) + DependenciesFileParser.parseVersionRequirement("3.3.0"),makeOrList []) [] let ``can detect explicit dependencies for WindowsAzure.Storage``() = @@ -260,7 +260,7 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = |> shouldEqual (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 5.0.8"), - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly(WindowsPhoneSilverlight("v8.0")) FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))]) @@ -271,7 +271,7 @@ let ``can detect framework assemblies for Microsoft.Framework.Logging``() = nuspec.FrameworkAssemblyReferences.[0].AssemblyName |> shouldEqual "System.Collections.Concurrent" nuspec.FrameworkAssemblyReferences.[0].FrameworkRestrictions |> shouldEqual - (FrameworkRestrictionList + (makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5)) FrameworkRestriction.Exactly(DNX(FrameworkVersion.V4_5_1))]) @@ -280,7 +280,7 @@ let ``can detect framework assemblies for Microsoft.Framework.Logging``() = let name,_,restrictions = nuspec.Dependencies.[2] name |> shouldEqual (PackageName "System.Collections.Concurrent") - restrictions |> shouldEqual (FrameworkRestrictionList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + restrictions |> shouldEqual (makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) [] let ``can detect explicit dependencies for FluentAssertions 4``() = @@ -291,7 +291,7 @@ let ``can detect explicit dependencies for FluentAssertions 4``() = |> shouldEqual (PackageName "System.Collections", DependenciesFileParser.parseVersionRequirement(">= 4.0.10"), - FrameworkRestrictionList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) @@ -304,13 +304,13 @@ let ``can detect explicit dependencies for EasyNetQ``() = |> shouldEqual (PackageName "RabbitMQ.Client", DependenciesFileParser.parseVersionRequirement(">= 3.5.7"), - FrameworkRestrictionList []) + makeOrList []) deps.[1] |> shouldEqual (PackageName "Microsoft.Bcl", DependenciesFileParser.parseVersionRequirement(">= 1.1.10"), - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V1)) FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V1_1)) FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V2)) diff --git a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs index 2c0d7a73fd..38cebbb793 100644 --- a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs +++ b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs @@ -253,12 +253,12 @@ nuget Chessie""" getVersion netStandard |> shouldEqual "1.6.0" // Don't install netstandard to net45 Requirements.isTargetMatchingRestrictions - (Requirements.getRestrictionList netStandard.Settings.FrameworkRestrictions, + (Requirements.getExplicitRestriction netStandard.Settings.FrameworkRestrictions, (TargetProfile.SinglePlatform (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_5))) |> shouldEqual false // Don't install netstandard to net463 Requirements.isTargetMatchingRestrictions - (Requirements.getRestrictionList netStandard.Settings.FrameworkRestrictions, + (Requirements.getExplicitRestriction netStandard.Settings.FrameworkRestrictions, (TargetProfile.SinglePlatform (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_6_3))) |> shouldEqual false // This also tests that "UnknownPackage" is not pulled unexpectedly (because this dependency is never relevant) \ No newline at end of file diff --git a/tests/Paket.Tests/TestHelpers.fs b/tests/Paket.Tests/TestHelpers.fs index a00c3aa59b..225a69e65d 100644 --- a/tests/Paket.Tests/TestHelpers.fs +++ b/tests/Paket.Tests/TestHelpers.fs @@ -9,6 +9,15 @@ open System.Xml open System.IO open Paket.Domain +let makeOrList (l:_ list) = + if l.IsEmpty then FrameworkRestriction.NoRestriction + else Seq.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet l + |> ExplicitRestriction + +let getPortableRestriction s = + let pf = PlatformMatching.extractPlatforms s + FrameworkRestriction.Portable(s, pf.Platforms) + type GraphDependency = string * VersionRequirement * FrameworkRestrictions type DependencyGraph = list @@ -16,7 +25,7 @@ type DependencyGraph = list) : DependencyGraph = g |> Seq.map (fun (x, y, (rqs)) -> - x, y, rqs |> List.map (fun (a,b) -> (a, b, FrameworkRestrictionList [])), RuntimeGraph.Empty) + x, y, rqs |> List.map (fun (a,b) -> (a, b, ExplicitRestriction FrameworkRestriction.NoRestriction)), RuntimeGraph.Empty) |> Seq.toList let OfGraphWithRestriction (g:seq) : DependencyGraph = @@ -35,7 +44,7 @@ let GraphOfNuspecs (g:seq) : DependencyGraph = let OfGraphWithRuntimeDeps (g:seq) : DependencyGraph = g |> Seq.map (fun (x, y, rqs, run) -> - x, y, rqs |> List.map (fun (a,b) -> (a, b, FrameworkRestrictionList [])), run) + x, y, rqs |> List.map (fun (a,b) -> (a, b, ExplicitRestriction FrameworkRestriction.NoRestriction)), run) |> Seq.toList @@ -94,7 +103,7 @@ let safeResolve graph (dependencies : (string * VersionRange) list) = ResolverStrategyForTransitives = Some ResolverStrategy.Max }) |> Set.ofList - PackageResolver.Resolve(VersionsFromGraphAsSeq graph, PackageDetailsFromGraph graph, Constants.MainDependencyGroup, None, None, FrameworkRestrictionList [], packages, UpdateMode.UpdateAll) + PackageResolver.Resolve(VersionsFromGraphAsSeq graph, PackageDetailsFromGraph graph, Constants.MainDependencyGroup, None, None, ExplicitRestriction FrameworkRestriction.NoRestriction, packages, UpdateMode.UpdateAll) let resolve graph dependencies = (safeResolve graph dependencies).GetModelOrFail() diff --git a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs index f24b2ed2fb..3df797e226 100644 --- a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs +++ b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs @@ -8,18 +8,20 @@ open FsUnit open Paket.PackageResolver open Paket.Requirements open Paket.Domain +open Paket.TestHelpers + [] let ``should optimize 2 restriction set with only exactly``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P2"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))]] + [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] let expected = - [PackageName("P1"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P2"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))]] + [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] original |> optimizeDependencies @@ -28,14 +30,14 @@ let ``should optimize 2 restriction set with only exactly``() = [] let ``should optimize 2 restriction set with only exactly and client framework``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P2"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))]] + [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] let expected = - [PackageName("P1"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P2"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))]] + [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] original |> optimizeDependencies @@ -44,14 +46,14 @@ let ``should optimize 2 restriction set with only exactly and client framework`` [] let ``should optimize 2 restriction sets with between``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P2"), VersionRequirement.AllReleases, [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client))]] + [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client)))] let expected = - [PackageName("P1"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P2"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client))]] + [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client)))] original |> optimizeDependencies @@ -60,140 +62,140 @@ let ``should optimize 2 restriction sets with between``() = [] let ``empty set filtered with empty restrictions should give empty set``() = Set.empty - |> DependencySetFilter.filterByRestrictions (FrameworkRestrictionList []) + |> DependencySetFilter.filterByRestrictions (ExplicitRestriction FrameworkRestriction.NoRestriction) |> shouldEqual Set.empty [] let ``filtered with empty restrictions should give full set``() = let set = - [PackageName("P1"), VersionRequirement.AllReleases, FrameworkRestrictionList [] - PackageName("P2"), VersionRequirement.AllReleases, FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P3"), VersionRequirement.AllReleases, FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))]] + [PackageName("P1"), VersionRequirement.AllReleases, ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P2"), VersionRequirement.AllReleases, ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P3"), VersionRequirement.AllReleases, ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5)))] |> Set.ofList set - |> DependencySetFilter.filterByRestrictions (FrameworkRestrictionList []) + |> DependencySetFilter.filterByRestrictions (ExplicitRestriction FrameworkRestriction.NoRestriction) |> shouldEqual set [] let ``filtered with empty should not remove netstandard``() = let set = - [PackageName("P1"), VersionRequirement.AllReleases, FrameworkRestrictionList [] - PackageName("P2"), VersionRequirement.AllReleases, FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P3"), VersionRequirement.AllReleases, FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)); FrameworkRestriction.Exactly (DotNetStandard(DotNetStandardVersion.V1_3))]] + [PackageName("P1"), VersionRequirement.AllReleases, ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P2"), VersionRequirement.AllReleases, ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P3"), VersionRequirement.AllReleases, makeOrList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)); FrameworkRestriction.Exactly (DotNetStandard(DotNetStandardVersion.V1_3))]] |> Set.ofList set - |> DependencySetFilter.filterByRestrictions (FrameworkRestrictionList []) + |> DependencySetFilter.filterByRestrictions (ExplicitRestriction FrameworkRestriction.NoRestriction) |> shouldEqual set [] let ``filtered with concrete restriction should filter non-matching``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases,FrameworkRestrictionList [] - PackageName("P2"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P3"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P4"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P5"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P6"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P7"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3),DotNetFramework(FrameworkVersion.V3_5))]] + [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P3"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P4"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P5"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P6"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P7"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3),DotNetFramework(FrameworkVersion.V3_5)))] |> Set.ofList let expected = - [PackageName("P1"), VersionRequirement.AllReleases,FrameworkRestrictionList [] - PackageName("P2"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P6"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))]] + [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P6"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2)))] |> Set.ofList original - |> DependencySetFilter.filterByRestrictions (FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))]) + |> DependencySetFilter.filterByRestrictions (ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4)))) |> shouldEqual expected [] let ``filtered with AtLeast restriction should filter non-matching``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases,FrameworkRestrictionList [] - PackageName("P2"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P3"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P4"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P5"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P6"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P7"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3),DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P8"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P9"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2))]] + [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P3"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P4"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P5"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P6"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P7"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3),DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P8"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P9"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2)))] |> Set.ofList let expected = - [PackageName("P1"), VersionRequirement.AllReleases,FrameworkRestrictionList [] - PackageName("P2"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P3"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P4"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P5"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P6"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P8"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P9"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2))]] + [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P3"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P4"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P5"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P6"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P8"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P9"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2)))] |> Set.ofList original - |> DependencySetFilter.filterByRestrictions ( FrameworkRestrictionList[FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))]) + |> DependencySetFilter.filterByRestrictions ( ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4)))) |> shouldEqual expected [] let ``filtered with Between restriction should filter non-matching`` () = let original = - [PackageName("P01"), VersionRequirement.AllReleases,FrameworkRestrictionList [] - PackageName("P02"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P03"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P04"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P05"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P06"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P07"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3),DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P08"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P09"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P10"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5_1),DotNetFramework(FrameworkVersion.V4_6))] - PackageName("P11"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))] - PackageName("P12"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P13"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))] - PackageName("P14"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1))]] + [PackageName("P01"), VersionRequirement.AllReleases,ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P02"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P03"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P04"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P05"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P06"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P07"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3),DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P08"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P09"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P10"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5_1),DotNetFramework(FrameworkVersion.V4_6))) + PackageName("P11"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))) + PackageName("P12"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P13"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) + PackageName("P14"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)))] |> Set.ofList let expected = - [PackageName("P01"), VersionRequirement.AllReleases,FrameworkRestrictionList [] - PackageName("P02"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))] - PackageName("P03"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P04"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P05"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P06"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P08"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P09"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2))] - PackageName("P13"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))]] + [PackageName("P01"), VersionRequirement.AllReleases,ExplicitRestriction FrameworkRestriction.NoRestriction + PackageName("P02"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4))) + PackageName("P03"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P04"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P05"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P06"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P08"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P09"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2))) + PackageName("P13"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4)))] |> Set.ofList original - |> DependencySetFilter.filterByRestrictions (FrameworkRestrictionList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_1))]) + |> DependencySetFilter.filterByRestrictions (ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5_1)))) |> shouldEqual expected [] let ``should optimize ZendeskApi_v2 ``() = let original = - [PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))] - PackageName("AsyncCTP"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))] - PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, [FrameworkRestriction.Portable "portable-net45+sl40+wp71+win80"] - PackageName("Microsoft.Bcl.Async"), VersionRequirement.AllReleases, [FrameworkRestriction.Portable "portable-net45+sl40+wp71+win80"]] + [PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) + PackageName("AsyncCTP"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) + PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (getPortableRestriction "portable-net45+sl40+wp71+win80") + PackageName("Microsoft.Bcl.Async"), VersionRequirement.AllReleases, (getPortableRestriction "portable-net45+sl40+wp71+win80")] let expected = [PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, - FrameworkRestrictionList - [FrameworkRestriction.Portable "portable-net45+sl40+wp71+win80" + makeOrList + [getPortableRestriction "portable-net45+sl40+wp71+win80" FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("AsyncCTP"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))] - PackageName("Microsoft.Bcl.Async"), VersionRequirement.AllReleases,FrameworkRestrictionList [FrameworkRestriction.Portable "portable-net45+sl40+wp71+win80"]] + PackageName("AsyncCTP"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) + PackageName("Microsoft.Bcl.Async"), VersionRequirement.AllReleases,ExplicitRestriction (getPortableRestriction "portable-net45+sl40+wp71+win80")] original |> optimizeDependencies @@ -202,15 +204,15 @@ let ``should optimize ZendeskApi_v2 ``() = [] let ``should optimize real world restrictions``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_6))]] + [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_6)))] let expected = [PackageName("P1"), VersionRequirement.AllReleases, - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)) FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5)) @@ -223,15 +225,15 @@ let ``should optimize real world restrictions``() = [] let ``should optimize real world restrictions 2``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))] - PackageName("P1"), VersionRequirement.AllReleases, [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_6))]] + [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_6)))] let expected = [PackageName("P1"), VersionRequirement.AllReleases, - FrameworkRestrictionList + makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client)) FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5)) @@ -247,9 +249,9 @@ let ``should optimize real world restrictions 3``() = [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_Client)) FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1))] - let expected = [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_Client))] + let expected = FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_Client)) - let result = optimizeRestrictions original + let result = makeOrList original |> getExplicitRestriction result |> shouldEqual expected diff --git a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs index 29724281a1..bef947a30b 100644 --- a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs @@ -64,14 +64,14 @@ module TestTargetProfiles = [] let ``>= net10 contains all but only dotnet versions (#1124)`` () = /// https://github.com/fsprojects/Paket/issues/1124 - let restrictions = [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V1))] + let restrictions = FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V1)) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles restricted |> shouldEqual TestTargetProfiles.DotNetFrameworkProfiles [] let ``>= net452 contains 4.5.2 and following versions`` () = - let restrictions = [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5_2))] + let restrictions = FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5_2)) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles let expected = [FrameworkVersion.V4_5_2; FrameworkVersion.V4_5_3; FrameworkVersion.V4_6] |> List.map dotnet @@ -79,7 +79,7 @@ let ``>= net452 contains 4.5.2 and following versions`` () = [] let ``>= net40 < net451 contains 4.0 and 4.5`` () = - let restrictions = [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4), DotNetFramework(FrameworkVersion.V4_5_1))] + let restrictions = FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4), DotNetFramework(FrameworkVersion.V4_5_1)) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles let expected = [FrameworkVersion.V4; FrameworkVersion.V4_5] |> List.map dotnet @@ -87,7 +87,7 @@ let ``>= net40 < net451 contains 4.0 and 4.5`` () = [] let ``>= sl30 contains all but only silverlight versions`` () = - let restrictions = [FrameworkRestriction.AtLeast(Silverlight "v3.0")] + let restrictions = FrameworkRestriction.AtLeast(Silverlight "v3.0") let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles restricted |> shouldEqual TestTargetProfiles.SilverlightProfiles \ No newline at end of file diff --git a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs index 505014b638..15475f21e4 100644 --- a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs @@ -11,123 +11,123 @@ open Paket.Requirements [] let ``should filter net45 and >= net40``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] + let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) filterRestrictions l1 l2 |> shouldEqual l2 [] let ``should filter >= net40 and net45``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] + let l1 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) + let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 |> shouldEqual l1 [] let ``should filter >= net40 and net40``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))] + let l1 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))) + let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))) filterRestrictions l1 l2 |> shouldEqual l1 [] let ``should filter >=net40 and >= net45``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))] + let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))) filterRestrictions l1 l2 |> shouldEqual l2 [] let ``should filter >= net40 and portable``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Portable("abc")] + let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (getPortableRestriction("abc")) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList []) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) [] let ``should filter >= net40 and >= net20 < net46``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4_6))] + let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4_6))) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6))]) + |> shouldEqual (ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6)))) [] let ``should filter >= net40 and >= net45 < net46``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_6))] + let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_6))) filterRestrictions l1 l2 |> shouldEqual l2 [] let ``should filter >= net40 and >= net20 < net40``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4))] + let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList []) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) [] let ``should filter net45 and >= net40 < net46``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6))] + let l1 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) + let l2 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6))) filterRestrictions l1 l2 |> shouldEqual l1 [] let ``should filter net45 and >= net40 < net45``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5))] + let l1 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) + let l2 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5))) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList []) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) [] let ``should filter >= net40 < net46 and net45``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] + let l1 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6))) + let l2 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) filterRestrictions l1 l2 |> shouldEqual l2 [] let ``should filter >= net40 < net45 and net45``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))] + let l1 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5))) + let l2 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList []) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) [] let ``should filter >= net20 < net46 and >= net40``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4_6))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] + let l1 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4_6))) + let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6))]) + |> shouldEqual (ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_6)))) [] let ``should filter >= net45 < net46 and >= net40``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_6))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] + let l1 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4_5),DotNetFramework(FrameworkVersion.V4_6))) + let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 |> shouldEqual l1 [] let ``should filter >= net20 < net40 and >= net40``() = - let l1 = FrameworkRestrictionList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] + let l1 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList []) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) [] let ``should not filter native, net452``() = - FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform)).IsSameCategoryAs(FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))) |> shouldEqual (Some true) + //FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform)).IsSameCategoryAs(FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))) |> shouldEqual (Some true) - let l1 = FrameworkRestrictionList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5_2)); FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))] - let l2 = FrameworkRestrictionList [FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))] + let l1 = ExplicitRestriction (FrameworkRestriction.Or (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5_2)), FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform)))) + let l2 = ExplicitRestriction (FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))) filterRestrictions l1 l2 - |> shouldEqual (FrameworkRestrictionList [FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))]) + |> shouldEqual (ExplicitRestriction (FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform)))) From 1e187c8392734b5cbf47494c6ad5ab0b0fc152d7 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sun, 14 May 2017 17:01:27 +0200 Subject: [PATCH 03/47] we need to find all platforms supporting us in restriction logic. --- .../ConvertFromNuGetSpecs.fs | 4 +-- .../FrameworkRestrictionsSpecs.fs | 34 +++++++++--------- .../UpdatePackageSpecs.fs | 4 +-- src/Paket.Core/Dependencies/Nuspec.fs | 36 +++++++++---------- src/Paket.Core/Versioning/PlatformMatching.fs | 14 ++++++++ src/Paket.Core/Versioning/Requirements.fs | 6 ++-- 6 files changed, 56 insertions(+), 42 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs b/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs index bfec0594b0..b3f64b8459 100644 --- a/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs @@ -44,13 +44,13 @@ let ``#1225 should convert simple C# project with non-matching framework restric requirement.Name |> shouldEqual (PackageName "Castle.Core") requirement.VersionRequirement.ToString() |> shouldEqual "3.3.3" requirement.ResolverStrategyForTransitives |> shouldEqual None - requirement.Settings.FrameworkRestrictions |> getRestrictionList |> shouldEqual [FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))] + requirement.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5))) let requirement2 = depsFile.GetGroup(Constants.MainDependencyGroup).Packages.Tail.Head requirement2.Name |> shouldEqual (PackageName "Newtonsoft.Json") requirement2.VersionRequirement.ToString() |> shouldEqual "7.0.1" requirement2.ResolverStrategyForTransitives |> shouldEqual None - requirement2.Settings.FrameworkRestrictions |> getRestrictionList |> shouldEqual [FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] + requirement2.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) [] let ``#1217 should replace packages.config files in project``() = diff --git a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs index d0b34b169d..19810bd409 100644 --- a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs @@ -13,8 +13,8 @@ open Paket.Requirements let ``#140 windsor should resolve framework dependent dependencies``() = let lockFile = update "i000140-resolve-framework-restrictions" lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "TaskParallelLibrary"].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5))] + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5))) [] let ``#1182 framework restrictions overwrite each other``() = @@ -27,11 +27,11 @@ let ``#1182 framework restrictions overwrite each other``() = [] // PATH TOO LONG on Windows... let ``#1190 paket add nuget should handle transitive dependencies``() = paket "add nuget xunit version 2.1.0" "i001190-transitive-dependencies-with-restr" |> ignore - - let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001190-transitive-dependencies-with-restr","paket.lock")) - lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "xunit.abstractions"].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldContain (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))) + failwithf "Fix Me" + //let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001190-transitive-dependencies-with-restr","paket.lock")) + //lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "xunit.abstractions"].Settings.FrameworkRestrictions + //|> getExplicitRestriction + //|> shouldContain (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))) [] let ``#1190 paket add nuget should handle transitive dependencies with restrictions``() = @@ -39,8 +39,8 @@ let ``#1190 paket add nuget should handle transitive dependencies with restricti let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001190-transitive-deps","paket.lock")) lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "xunit.abstractions"].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual [] + |> getExplicitRestriction + |> shouldEqual FrameworkRestriction.NoRestriction [] @@ -56,24 +56,24 @@ let ``#1213 framework dependencies propagate``() = let lockFile = update "i001213-framework-propagation" lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "Newtonsoft.Json"].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual [] + |> getExplicitRestriction + |> shouldEqual FrameworkRestriction.NoRestriction [] let ``#1215 framework dependencies propagate``() = let lockFile = update "i001215-framework-propagation-no-restriction" lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "Microsoft.Bcl.Async"].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldEqual [] + |> getExplicitRestriction + |> shouldEqual FrameworkRestriction.NoRestriction [] let ``#1232 framework dependencies propagate``() = let lockFile = update "i001232-sql-lite" - - lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "System.Data.SQLite.Core"].Settings.FrameworkRestrictions - |> getRestrictionList - |> shouldContain (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))) + failwithf "Fix me" + //lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "System.Data.SQLite.Core"].Settings.FrameworkRestrictions + //|> getExplicitRestriction + //|> shouldContain (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))) [] let ``#1494 detect platform 5.0``() = diff --git a/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs b/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs index 077fc06a4c..33d5340f5a 100644 --- a/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs @@ -87,12 +87,12 @@ let ``#1117 can understand portable``() = let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001117-aws","paket.lock")) let restrictions = lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "PCLStorage"].Settings.FrameworkRestrictions match restrictions with - | FrameworkRestrictionList l -> l.ToString() |> shouldEqual ("[portable-net45+win8+wp8+wpa81]") + | ExplicitRestriction l -> l.ToString() |> shouldEqual ("[portable-net45+win8+wp8+wpa81]") | _ -> failwith "wrong" let restrictions = lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "Microsoft.Bcl.Async"].Settings.FrameworkRestrictions match restrictions with - | FrameworkRestrictionList l -> l.ToString() |> shouldEqual ("[portable-net45+win8+wp8+wpa81]") + | ExplicitRestriction l -> l.ToString() |> shouldEqual ("[portable-net45+win8+wp8+wpa81]") | _ -> failwith "wrong" [] diff --git a/src/Paket.Core/Dependencies/Nuspec.fs b/src/Paket.Core/Dependencies/Nuspec.fs index 364c289ce9..8abe076d47 100644 --- a/src/Paket.Core/Dependencies/Nuspec.fs +++ b/src/Paket.Core/Dependencies/Nuspec.fs @@ -76,23 +76,23 @@ type Nuspec = /// load the file from an XmlDocument. The fileName is only used for error reporting. static member private Load(fileName:string, doc:XmlDocument) = - let frameworks = - doc - |> getDescendants "group" - |> List.map (fun node -> - match node |> getAttribute "targetFramework" with - | Some framework when framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable").StartsWith "portable" -> - let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") - let fws = (PlatformMatching.extractPlatforms framework).Platforms - [PackageName "", - VersionRequirement.NoRestriction, FrameworkRestriction.Portable (framework, fws)] - - | Some framework -> - match FrameworkDetection.Extract framework with - | Some x -> [PackageName "",VersionRequirement.NoRestriction, FrameworkRestriction.Exactly x] - | None -> [] - | _ -> []) - |> List.concat + //let frameworks = + // doc + // |> getDescendants "group" + // |> List.map (fun node -> + // match node |> getAttribute "targetFramework" with + // | Some framework when framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable").StartsWith "portable" -> + // let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") + // let fws = (PlatformMatching.extractPlatforms framework).Platforms + // [PackageName "", + // VersionRequirement.NoRestriction, FrameworkRestriction.Portable (framework, fws)] + // + // | Some framework -> + // match FrameworkDetection.Extract framework with + // | Some x -> [PackageName "",VersionRequirement.NoRestriction, FrameworkRestriction.Exactly x] + // | None -> [] + // | _ -> []) + // |> List.concat //let framworks = // let isMatch (n',v',r') = @@ -133,7 +133,7 @@ type Nuspec = let referenced = depsTags |> List.choose (NuSpecParserHelper.getDependency fileName) - |> List.append frameworks + //|> List.append frameworks let dependencies = Requirements.optimizeDependencies referenced diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index 390d2a92bc..de2920edc4 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -105,6 +105,20 @@ let collectPlatforms = | _::tl -> loop acc framework tl memoize (fun (framework,profls) -> loop ([]:FrameworkIdentifier list) framework profls) +/// Returns all framework identifiers which (transitively) support the given framework identifier +let getFrameworksSupporting = + let cache = System.Collections.Concurrent.ConcurrentDictionary<_,FrameworkIdentifier list>() + fun (x:FrameworkIdentifier) -> + cache.GetOrAdd(x, fun _ -> + // calculate + KnownTargetProfiles.AllProfiles + |> List.collect(function + | SinglePlatform p -> [p] + | PortableProfile (_, fws) -> fws) + |> List.distinct + |> List.filter (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains x) + ) + let platformsSupport = let rec platformsSupport platform platforms = if List.isEmpty platforms then MaxPenalty diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index e31aa1d35e..16bd251aaa 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -41,10 +41,10 @@ type FrameworkRestriction = fws |> List.collect (fun fw -> (FrameworkRestriction.AtLeast fw).RepresentedFrameworks) |> List.distinct - | FrameworkRestriction.AtLeast r -> r.SupportedPlatformsTransitive + | FrameworkRestriction.AtLeast r -> PlatformMatching.getFrameworksSupporting r | FrameworkRestriction.Between(min,max) -> - let minSupported = min.SupportedPlatformsTransitive - let maxSupported = max.SupportedPlatformsTransitive + let minSupported = PlatformMatching.getFrameworksSupporting min + let maxSupported = PlatformMatching.getFrameworksSupporting max minSupported |> List.filter (fun fw -> maxSupported |> Seq.contains fw |> not) | FrameworkRestriction.Or (fr1, fr2) -> From a97805b3bd269c70f1b8080d54b39e018a0e29d9 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sat, 20 May 2017 13:31:49 +0200 Subject: [PATCH 04/47] parsing nuspec is a bit more complicated than expected. We properly need to detect the group restrictions in a future compatible way. --- .../Properties/AssemblyInfo.cs | 4 +- src/Paket.Core/AssemblyInfo.fs | 4 +- src/Paket.Core/Dependencies/Nuspec.fs | 80 ++++++++++++++----- .../Versioning/FrameworkHandling.fs | 1 - src/Paket.Core/Versioning/Requirements.fs | 65 ++++++++++----- src/Paket/AssemblyInfo.fs | 4 +- tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 13 ++- 7 files changed, 116 insertions(+), 55 deletions(-) diff --git a/src/Paket.Bootstrapper/Properties/AssemblyInfo.cs b/src/Paket.Bootstrapper/Properties/AssemblyInfo.cs index f14a8090e8..18467dbc02 100644 --- a/src/Paket.Bootstrapper/Properties/AssemblyInfo.cs +++ b/src/Paket.Bootstrapper/Properties/AssemblyInfo.cs @@ -6,7 +6,7 @@ [assembly: AssemblyDescriptionAttribute("A dependency manager for .NET with support for NuGet packages and git repositories.")] [assembly: AssemblyVersionAttribute("5.0.0")] [assembly: AssemblyFileVersionAttribute("5.0.0")] -[assembly: AssemblyInformationalVersionAttribute("5.0.0-beta003")] +[assembly: AssemblyInformationalVersionAttribute("5.0.0-beta004")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "Paket.Bootstrapper"; @@ -14,6 +14,6 @@ internal static class AssemblyVersionInformation { internal const System.String AssemblyDescription = "A dependency manager for .NET with support for NuGet packages and git repositories."; internal const System.String AssemblyVersion = "5.0.0"; internal const System.String AssemblyFileVersion = "5.0.0"; - internal const System.String AssemblyInformationalVersion = "5.0.0-beta003"; + internal const System.String AssemblyInformationalVersion = "5.0.0-beta004"; } } diff --git a/src/Paket.Core/AssemblyInfo.fs b/src/Paket.Core/AssemblyInfo.fs index bc39166495..6a298180db 100644 --- a/src/Paket.Core/AssemblyInfo.fs +++ b/src/Paket.Core/AssemblyInfo.fs @@ -8,7 +8,7 @@ open System.Reflection [] [] [] -[] +[] do () module internal AssemblyVersionInformation = @@ -18,4 +18,4 @@ module internal AssemblyVersionInformation = let [] AssemblyDescription = "A dependency manager for .NET with support for NuGet packages and git repositories." let [] AssemblyVersion = "5.0.0" let [] AssemblyFileVersion = "5.0.0" - let [] AssemblyInformationalVersion = "5.0.0-beta003" + let [] AssemblyInformationalVersion = "5.0.0-beta004" diff --git a/src/Paket.Core/Dependencies/Nuspec.fs b/src/Paket.Core/Dependencies/Nuspec.fs index 8abe076d47..f9c0e461fb 100644 --- a/src/Paket.Core/Dependencies/Nuspec.fs +++ b/src/Paket.Core/Dependencies/Nuspec.fs @@ -35,12 +35,12 @@ module internal NuSpecParserHelper = let framework = framework.Replace(".NETPortable0.0","portable") if String.startsWithIgnoreCase "portable" framework then let fws = (PlatformMatching.extractPlatforms framework).Platforms - Some(name,version,FrameworkRestriction.Portable (framework, fws)) + Some(name,version, { PlatformMatching.ParsedPlatformPath.Name = framework; PlatformMatching.ParsedPlatformPath.Platforms = fws}) else match FrameworkDetection.Extract framework with - | Some x -> Some(name,version,FrameworkRestriction.Exactly x) + | Some x -> Some(name,version, { Name = framework; Platforms = [x]}) | None -> None - | _ -> Some(name,version,FrameworkRestriction.NoRestriction) + | _ -> Some(name,version, { Name = ""; Platforms = [] }) let getAssemblyRefs node = let name = node |> getAttribute "assemblyName" @@ -76,23 +76,22 @@ type Nuspec = /// load the file from an XmlDocument. The fileName is only used for error reporting. static member private Load(fileName:string, doc:XmlDocument) = - //let frameworks = - // doc - // |> getDescendants "group" - // |> List.map (fun node -> - // match node |> getAttribute "targetFramework" with - // | Some framework when framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable").StartsWith "portable" -> - // let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") - // let fws = (PlatformMatching.extractPlatforms framework).Platforms - // [PackageName "", - // VersionRequirement.NoRestriction, FrameworkRestriction.Portable (framework, fws)] - // - // | Some framework -> - // match FrameworkDetection.Extract framework with - // | Some x -> [PackageName "",VersionRequirement.NoRestriction, FrameworkRestriction.Exactly x] - // | None -> [] - // | _ -> []) - // |> List.concat + let frameworks = + doc + |> getDescendants "group" + |> List.map (fun node -> + match node |> getAttribute "targetFramework" with + | Some framework when framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable").StartsWith "portable" -> + let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") + let fws = (PlatformMatching.extractPlatforms framework).Platforms + [] // TODO: Maybe fws? + + | Some framework -> + match FrameworkDetection.Extract framework with + | Some x -> [x] + | None -> [] + | _ -> []) + |> List.concat //let framworks = // let isMatch (n',v',r') = @@ -133,8 +132,49 @@ type Nuspec = let referenced = depsTags |> List.choose (NuSpecParserHelper.getDependency fileName) + // We need to append all the other platforms we support. + |> List.map (fun (name, req, pp) -> + let restriction = + match pp.Platforms with + | _ when System.String.IsNullOrEmpty pp.Name -> FrameworkRestriction.NoRestriction + | [] -> FrameworkRestriction.NoRestriction + | [ pf ] -> FrameworkRestriction.AtLeast pf + | _ -> FrameworkRestriction.Portable(pp.Name, pp.Platforms) + let minimalRestriction = + frameworks + |> Seq.filter (fun fw -> pp.Platforms |> Seq.contains fw |> not) + |> Seq.filter (fun fw -> + // filter all restrictions which would render this group to nothing (ie smaller restrictions) + restriction.IsSubsetOf (FrameworkRestriction.AtLeast fw) |> not) + |> Seq.fold (fun curRestr fw -> + FrameworkRestriction.And(curRestr, FrameworkRestriction.Not (FrameworkRestriction.AtLeast fw))) restriction + name, req, minimalRestriction + ) //|> List.append frameworks + let referenced = + referenced + |> List.groupBy (fun (n,req,_) -> n,req) + |> List.map (fun ((n, req), group) -> + let restrictions = group |> List.map (fun (_,_,r) -> r) + n, req, restrictions |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet) + + // While this is correct we want a more generic representation, such that future platforms "just work" + //let availablePlatforms = referenced |> List.map (fun (_,_,pp) -> pp) + //let calculateDistribution = PlatformMatching.getSupportedTargetProfiles availablePlatforms + // + //let referenced = + // referenced + // |> List.map (fun (name, req, pp) -> + // let restriction = + // calculateDistribution.[pp] + // |> Seq.fold (fun state profile -> + // FrameworkRestriction.Or(state, FrameworkRestriction.ExactlyProfile profile)) FrameworkRestriction.EmptySet + // name, req, restriction) + // + + + let dependencies = Requirements.optimizeDependencies referenced let references = diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index 56d3a0c26e..d85a43f20b 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -507,7 +507,6 @@ module FrameworkDetection = type TargetProfile = | SinglePlatform of FrameworkIdentifier | PortableProfile of string * FrameworkIdentifier list - member this.ProfilesCompatibleWithPortableProfile = match this with | SinglePlatform _ -> [ ] diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 16bd251aaa..fc5c4e71be 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -7,16 +7,21 @@ open Paket.PackageSources open Paket.Logging [] +// To make reasoning and writing tests easier. +// Ideally we would "simplify" the trees to a "normal" form internally +[] type FrameworkRestriction = -// TODO: make this presentation private and add helper -> prevents different presentations of empty set -| NoRestriction -| EmptySet -| Exactly of FrameworkIdentifier -| Portable of string * FrameworkIdentifier list -| AtLeast of FrameworkIdentifier -| Between of FrameworkIdentifier * FrameworkIdentifier -| Or of FrameworkRestriction * FrameworkRestriction -| And of FrameworkRestriction * FrameworkRestriction + // TODO: private + | NoRestriction + | EmptySet + | Exactly of FrameworkIdentifier + //[] + | Portable of string * FrameworkIdentifier list + | AtLeast of FrameworkIdentifier + // Means: Take all frameworks NOT given by the restriction + | Not of FrameworkRestriction + | Or of FrameworkRestriction * FrameworkRestriction + | And of FrameworkRestriction * FrameworkRestriction override this.ToString() = match this with | FrameworkRestriction.NoRestriction -> "norestriction" @@ -24,7 +29,7 @@ type FrameworkRestriction = | FrameworkRestriction.Exactly r -> r.ToString() | FrameworkRestriction.Portable (r,_) -> r | FrameworkRestriction.AtLeast r -> ">= " + r.ToString() - | FrameworkRestriction.Between(min,max) -> sprintf ">= %O < %O" min max + | FrameworkRestriction.Not(fr) -> sprintf "NOT (%O)" fr | FrameworkRestriction.Or(fr1, fr2) -> sprintf "|| (%O) (%O)" fr1 fr2 | FrameworkRestriction.And(fr1, fr2) -> sprintf "&& (%O) (%O)" fr1 fr2 @@ -35,22 +40,24 @@ type FrameworkRestriction = KnownTargetProfiles.AllProfiles |> List.collect (function | SinglePlatform fw -> [fw] | PortableProfile (_, fws) -> fws) + |> List.sort | FrameworkRestriction.Exactly r -> [ r ] | FrameworkRestriction.EmptySet -> [ ] | FrameworkRestriction.Portable (r, fws) -> fws |> List.collect (fun fw -> (FrameworkRestriction.AtLeast fw).RepresentedFrameworks) |> List.distinct + |> List.sort | FrameworkRestriction.AtLeast r -> PlatformMatching.getFrameworksSupporting r - | FrameworkRestriction.Between(min,max) -> - let minSupported = PlatformMatching.getFrameworksSupporting min - let maxSupported = PlatformMatching.getFrameworksSupporting max - minSupported - |> List.filter (fun fw -> maxSupported |> Seq.contains fw |> not) + | FrameworkRestriction.Not(fr) -> + let notTaken = fr.RepresentedFrameworks + FrameworkRestriction.NoRestriction.RepresentedFrameworks + |> List.filter (fun fw -> notTaken |> Seq.contains fw |> not) | FrameworkRestriction.Or (fr1, fr2) -> [ fr1; fr2 ] |> List.collect (fun fr -> fr.RepresentedFrameworks) |> List.distinct + |> List.sort | FrameworkRestriction.And (fr1, fr2) -> let l1 = fr1.RepresentedFrameworks fr2.RepresentedFrameworks @@ -62,6 +69,18 @@ type FrameworkRestriction = let superset = y.RepresentedFrameworks x.RepresentedFrameworks |> List.forall (fun inner -> superset |> Seq.contains inner) + static member Between (x, y) = + FrameworkRestriction.And(FrameworkRestriction.AtLeast x, FrameworkRestriction.Not (FrameworkRestriction.AtLeast y)) + static member ExactlyProfile (pf: TargetProfile) = + match pf with + | SinglePlatform f -> Exactly f + | PortableProfile(name,fws) -> Portable(name, fws) + + override x.Equals(y) = (match y with :? FrameworkRestriction as r -> r.RepresentedFrameworks = x.RepresentedFrameworks | _ -> false) + override x.GetHashCode() = x.RepresentedFrameworks.GetHashCode() + interface System.IComparable with + member x.CompareTo(y) = (match y with :? FrameworkRestriction as r -> compare x.RepresentedFrameworks r.RepresentedFrameworks | _ -> failwith "wrong type") + type FrameworkRestrictions = @@ -84,10 +103,16 @@ let combineRestrictionsWithOr (x : FrameworkRestriction) y = elif y.IsSubsetOf x then x else - let combined = FrameworkRestriction.Or(x, y) - if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then - FrameworkRestriction.NoRestriction - else combined + match x, y with + | FrameworkRestriction.And(FrameworkRestriction.Not a, b), _ when a = y -> b + | FrameworkRestriction.And(a, FrameworkRestriction.Not b), _ when b = y -> a + | _, FrameworkRestriction.And(FrameworkRestriction.Not a, b) when a = x -> b + | _, FrameworkRestriction.And(a, FrameworkRestriction.Not b) when b = x -> a + | _ -> + let combined = FrameworkRestriction.Or(x, y) + if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then + FrameworkRestriction.NoRestriction + else combined let parseRestrictionsLegacy failImmediatly (text:string) = // TODO: Change this code to convert old "framework" sematics in @@ -133,7 +158,7 @@ let parseRestrictionsLegacy failImmediatly (text:string) = match FrameworkDetection.Extract(item) with | None -> handleError <| sprintf "Could not parse second framework of between operator '%s'. Try to update or install again or report a paket bug." item - | Some y -> yield FrameworkRestriction.Between(x,y) + | Some y -> yield FrameworkRestriction.Between(x, y) else yield FrameworkRestriction.Exactly x] |> List.fold (fun state item -> combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet diff --git a/src/Paket/AssemblyInfo.fs b/src/Paket/AssemblyInfo.fs index 8d31910e46..16945e716c 100644 --- a/src/Paket/AssemblyInfo.fs +++ b/src/Paket/AssemblyInfo.fs @@ -8,7 +8,7 @@ open System.Reflection [] [] [] -[] +[] do () module internal AssemblyVersionInformation = @@ -18,4 +18,4 @@ module internal AssemblyVersionInformation = let [] AssemblyDescription = "A dependency manager for .NET with support for NuGet packages and git repositories." let [] AssemblyVersion = "5.0.0" let [] AssemblyFileVersion = "5.0.0" - let [] AssemblyInformationalVersion = "5.0.0-beta003" + let [] AssemblyInformationalVersion = "5.0.0-beta004" diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index c6b8d82fdf..153eeb0b80 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -102,7 +102,7 @@ let ``can detect deps assemblies for RazorEngine``() = Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"RazorEngine.nuspec")).Dependencies |> shouldEqual [PackageName "Microsoft.AspNet.Razor",DependenciesFileParser.parseVersionRequirement("= 2.0.30506.0"), - makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))] + makeOrList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4_Client), DotNetFramework(FrameworkVersion.V4_5))] PackageName "Microsoft.AspNet.Razor",DependenciesFileParser.parseVersionRequirement(">= 3.0.0"), makeOrList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]] @@ -311,10 +311,7 @@ let ``can detect explicit dependencies for EasyNetQ``() = (PackageName "Microsoft.Bcl", DependenciesFileParser.parseVersionRequirement(">= 1.1.10"), makeOrList - [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V1)) - FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V1_1)) - FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V2)) - FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3)) - FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client)) - FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4)) ]) \ No newline at end of file + [FrameworkRestriction.And( + FrameworkRestriction.NoRestriction, + FrameworkRestriction.Not (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5)))) + ]) \ No newline at end of file From b246942b6b62790b33bb00d7bbf35aac2a7e6d4c Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sat, 20 May 2017 16:30:28 +0200 Subject: [PATCH 05/47] generating a generic description is not as easy as it should be :/ --- src/Paket.Core/Dependencies/NuGetV2.fs | 63 +++++---------- src/Paket.Core/Dependencies/Nuspec.fs | 81 +------------------ .../Versioning/FrameworkHandling.fs | 4 + src/Paket.Core/Versioning/Requirements.fs | 57 ++++++++++++- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 1 + tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 2 +- tests/Paket.Tests/Paket.Tests.fsproj | 1 + .../Versioning/FrameworkRestrictionTests.fs | 24 ++++++ 8 files changed, 110 insertions(+), 123 deletions(-) create mode 100644 tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs diff --git a/src/Paket.Core/Dependencies/NuGetV2.fs b/src/Paket.Core/Dependencies/NuGetV2.fs index 18bd4e6883..74dbcb83b5 100644 --- a/src/Paket.Core/Dependencies/NuGetV2.fs +++ b/src/Paket.Core/Dependencies/NuGetV2.fs @@ -179,7 +179,7 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra | Some node -> node.InnerText | None -> failwithf "unable to find dependencies for package %O %O" packageName version - let packages = + let rawPackages = let split (d : string) = let a = d.Split ':' PackageName a.[0], @@ -188,15 +188,18 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra let restriction = a.[2] if String.startsWithIgnoreCase "portable" restriction then let fws = (PlatformMatching.extractPlatforms restriction).Platforms - Some (FrameworkRestriction.Portable (restriction, fws)) + Some { PlatformMatching.ParsedPlatformPath.Name = restriction; PlatformMatching.ParsedPlatformPath.Platforms = fws } + //Some (FrameworkRestriction.Portable (restriction, fws)) else match FrameworkDetection.Extract restriction with - | Some x -> Some (FrameworkRestriction.Exactly x) + | Some x -> Some { PlatformMatching.ParsedPlatformPath.Name = restriction; PlatformMatching.ParsedPlatformPath.Platforms = [x] } + //(FrameworkRestriction.Exactly x) | None -> - if verbose then - verbosefn "Unable to parse framework restriction '%s' for package '%s' in package '%s'" restriction a.[0] (packageName.ToString()) + traceWarnfn "Unable to parse framework restriction '%s' for package '%s' in package '%s'" restriction a.[0] (packageName.ToString()) + //if verbose then + // verbosefn "Unable to parse framework restriction '%s' for package '%s' in package '%s'" restriction a.[0] (packageName.ToString()) None - else Some (FrameworkRestriction.NoRestriction)) + else Some PlatformMatching.ParsedPlatformPath.Empty) dependencies |> fun s -> s.Split([| '|' |], System.StringSplitOptions.RemoveEmptyEntries) @@ -206,41 +209,19 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra | Some(restrictions) -> Some (name, version, restrictions) | None -> None) - //let expandedPackages = - // let isMatch (n',v',r') = - // r' - // |> List.exists (fun r -> - // match r with - // | FrameworkRestriction.Exactly(DotNetFramework _) -> true - // | FrameworkRestriction.Exactly(DotNetStandard _) -> true - // |_ -> false) - // - // packages - // |> Seq.collect (fun (n,v,r) -> - // match r with - // | [ FrameworkRestriction.Portable p ] -> - // [yield n,v,r - // let standardAliases = KnownTargetProfiles.portableStandards p - // for alias in standardAliases do - // let s = FrameworkRestriction.Exactly(DotNetStandard alias) - // let s2 = FrameworkRestriction.AtLeast(DotNetStandard alias) - // if packages |> Array.exists (fun (n,v,r) -> r |> List.exists (fun r -> r = s || r = s2)) |> not then - // yield n,v,[s2] - // - // if standardAliases = [] && not <| Array.exists isMatch packages then - // for p in p.Split([|'+'; '-'|]) do - // match FrameworkDetection.Extract p with - // | Some(DotNetFramework _ as r) -> - // yield n,v,[FrameworkRestriction.Exactly r] - // | Some(DotNetStandard _ as r) -> - // yield n,v,[FrameworkRestriction.Exactly r] - // | _ -> () ] - // | _ -> [n,v,r]) - // |> Seq.toList - let expandedPackages = - packages |> Seq.toList - - let dependencies = Requirements.optimizeDependencies expandedPackages + let frameworks = + rawPackages + |> Seq.collect (fun (_,_,pp) -> + match pp.Platforms with + | [h] -> [h] + | _ -> []) + |> Seq.toList + let cleanedPackages = + rawPackages + |> Seq.filter (fun (n,_,_) -> System.String.IsNullOrEmpty (n.ToString()) |> not) + |> Seq.toList + let dependencies = + addFrameworkRestrictionsToDependencies cleanedPackages frameworks { PackageName = officialName DownloadUrl = downloadLink diff --git a/src/Paket.Core/Dependencies/Nuspec.fs b/src/Paket.Core/Dependencies/Nuspec.fs index f9c0e461fb..cbfeb80989 100644 --- a/src/Paket.Core/Dependencies/Nuspec.fs +++ b/src/Paket.Core/Dependencies/Nuspec.fs @@ -93,89 +93,12 @@ type Nuspec = | _ -> []) |> List.concat - //let framworks = - // let isMatch (n',v',r') = - // r' - // |> List.exists (fun r -> - // match r with - // | FrameworkRestriction.Exactly(DotNetFramework _) -> true - // | FrameworkRestriction.Exactly(DotNetStandard _) -> true - // |_ -> false) - // - // frameworks - // |> Seq.collect (fun (n,v,r) -> - // match r with - // | [ FrameworkRestriction.Portable p ] -> - // [ yield n,v,r - // let standardAliases = KnownTargetProfiles.portableStandards p - // for alias in standardAliases do - // let s = FrameworkRestriction.Exactly(DotNetStandard alias) - // let s2 = FrameworkRestriction.AtLeast(DotNetStandard alias) - // if frameworks |> List.exists (fun (n,v,r) -> r |> List.exists (fun r -> r = s || r = s2)) |> not then - // yield n,v,[s2] - // - // if standardAliases = [] && not <| List.exists isMatch frameworks then - // for p in p.Split([|'+'; '-'|]) do - // match FrameworkDetection.Extract p with - // | Some(DotNetFramework _ as r) -> - // yield n,v,[FrameworkRestriction.Exactly r] - // | Some(DotNetStandard _ as r) -> - // yield n,v,[FrameworkRestriction.Exactly r] - // | _ -> () ] - // | _ -> [n,v,r]) - // |> Seq.toList - - let depsTags = + let rawDependencies = doc |> getDescendants "dependency" - - let referenced = - depsTags |> List.choose (NuSpecParserHelper.getDependency fileName) - // We need to append all the other platforms we support. - |> List.map (fun (name, req, pp) -> - let restriction = - match pp.Platforms with - | _ when System.String.IsNullOrEmpty pp.Name -> FrameworkRestriction.NoRestriction - | [] -> FrameworkRestriction.NoRestriction - | [ pf ] -> FrameworkRestriction.AtLeast pf - | _ -> FrameworkRestriction.Portable(pp.Name, pp.Platforms) - let minimalRestriction = - frameworks - |> Seq.filter (fun fw -> pp.Platforms |> Seq.contains fw |> not) - |> Seq.filter (fun fw -> - // filter all restrictions which would render this group to nothing (ie smaller restrictions) - restriction.IsSubsetOf (FrameworkRestriction.AtLeast fw) |> not) - |> Seq.fold (fun curRestr fw -> - FrameworkRestriction.And(curRestr, FrameworkRestriction.Not (FrameworkRestriction.AtLeast fw))) restriction - name, req, minimalRestriction - ) - //|> List.append frameworks - - let referenced = - referenced - |> List.groupBy (fun (n,req,_) -> n,req) - |> List.map (fun ((n, req), group) -> - let restrictions = group |> List.map (fun (_,_,r) -> r) - n, req, restrictions |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet) - - // While this is correct we want a more generic representation, such that future platforms "just work" - //let availablePlatforms = referenced |> List.map (fun (_,_,pp) -> pp) - //let calculateDistribution = PlatformMatching.getSupportedTargetProfiles availablePlatforms - // - //let referenced = - // referenced - // |> List.map (fun (name, req, pp) -> - // let restriction = - // calculateDistribution.[pp] - // |> Seq.fold (fun state profile -> - // FrameworkRestriction.Or(state, FrameworkRestriction.ExactlyProfile profile)) FrameworkRestriction.EmptySet - // name, req, restriction) - // - - - let dependencies = Requirements.optimizeDependencies referenced + let dependencies = addFrameworkRestrictionsToDependencies rawDependencies frameworks let references = doc diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index d85a43f20b..f1431eefe7 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -507,6 +507,10 @@ module FrameworkDetection = type TargetProfile = | SinglePlatform of FrameworkIdentifier | PortableProfile of string * FrameworkIdentifier list + member this.FrameworkIdentifiers = + match this with + | SinglePlatform p -> [p] + | PortableProfile (_, pfs) -> pfs member this.ProfilesCompatibleWithPortableProfile = match this with | SinglePlatform _ -> [ ] diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index fc5c4e71be..28f78d59f5 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -40,6 +40,7 @@ type FrameworkRestriction = KnownTargetProfiles.AllProfiles |> List.collect (function | SinglePlatform fw -> [fw] | PortableProfile (_, fws) -> fws) + |> List.distinct |> List.sort | FrameworkRestriction.Exactly r -> [ r ] | FrameworkRestriction.EmptySet -> [ ] @@ -112,7 +113,8 @@ let combineRestrictionsWithOr (x : FrameworkRestriction) y = let combined = FrameworkRestriction.Or(x, y) if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then FrameworkRestriction.NoRestriction - else combined + else + combined let parseRestrictionsLegacy failImmediatly (text:string) = // TODO: Change this code to convert old "framework" sematics in @@ -866,4 +868,55 @@ type PackageRequirement = match that with | :? PackageRequirement as that -> PackageRequirement.Compare(this,that,None,0,0) - | _ -> invalidArg "that" "cannot compare value of different types" \ No newline at end of file + | _ -> invalidArg "that" "cannot compare value of different types" + +let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = + + let referenced = + rawDependencies + |> List.groupBy (fun (n:PackageName,req,pp:PlatformMatching.ParsedPlatformPath) -> n,req) + |> List.map (fun ((name, req), group) -> + // We need to append all the other platforms we support. + // TODO: this might miss out intersections! + let pps = group |> List.map (fun (_,_,pp) -> pp) + let restrictions = + pps + |> List.map (fun pp -> + let restriction = + match pp.Platforms with + | _ when System.String.IsNullOrEmpty pp.Name -> FrameworkRestriction.NoRestriction + | [] -> FrameworkRestriction.NoRestriction + | [ pf ] -> FrameworkRestriction.AtLeast pf + | _ -> FrameworkRestriction.Portable(pp.Name, pp.Platforms) + let minimalRestriction = + frameworkGroups + |> Seq.filter (fun fw -> + // special casing for portable -> should be removed once portable is a normal FrameworkIdentifier + if pp.Platforms.Length < 2 then pp.Platforms |> Seq.contains fw |> not else true) + |> Seq.filter (fun fw -> + // filter all restrictions which would render this group to nothing (ie smaller restrictions) + // filter out unrelated restrictions + restriction.IsSubsetOf (FrameworkRestriction.AtLeast fw) |> not) + |> Seq.fold (fun curRestr fw -> + FrameworkRestriction.And(curRestr, FrameworkRestriction.Not (FrameworkRestriction.AtLeast fw))) restriction + minimalRestriction) + name, req, restrictions |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet + ) + //|> List.append frameworks + + // While this is correct we want a more generic representation, such that future platforms "just work" + // I'll leave this code for now to better understand that the above is doing the same thing, but resulting in a more generallized restriction. + //let availablePlatforms = referenced |> List.map (fun (_,_,pp) -> pp) + //let calculateDistribution = PlatformMatching.getSupportedTargetProfiles availablePlatforms + // + //let referenced = + // referenced + // |> List.map (fun (name, req, pp) -> + // let restriction = + // calculateDistribution.[pp] + // |> Seq.fold (fun state profile -> + // FrameworkRestriction.Or(state, FrameworkRestriction.ExactlyProfile profile)) FrameworkRestriction.EmptySet + // name, req, restriction) + // + + optimizeDependencies referenced \ No newline at end of file diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index 8fb8485c6e..cd00cebf1f 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -14,6 +14,7 @@ open Domain let fakeUrl = "http://doesntmatter" let parse fileName = + System.Environment.CurrentDirectory <- Path.GetDirectoryName __SOURCE_DIRECTORY__ parseODataDetails("tenp",fakeUrl,PackageName "package",SemVer.Parse "0",File.ReadAllText fileName) [] diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index 153eeb0b80..5ff7864455 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -291,7 +291,7 @@ let ``can detect explicit dependencies for FluentAssertions 4``() = |> shouldEqual (PackageName "System.Collections", DependenciesFileParser.parseVersionRequirement(">= 4.0.10"), - makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + makeOrList [FrameworkRestriction.AtLeast(DNXCore(FrameworkVersion.V5_0))]) diff --git a/tests/Paket.Tests/Paket.Tests.fsproj b/tests/Paket.Tests/Paket.Tests.fsproj index 659375dd8c..59f9adb493 100644 --- a/tests/Paket.Tests/Paket.Tests.fsproj +++ b/tests/Paket.Tests/Paket.Tests.fsproj @@ -96,6 +96,7 @@ + diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs new file mode 100644 index 0000000000..49a0e834a4 --- /dev/null +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -0,0 +1,24 @@ +module Paket.Requirements.FrameworkRestrictionTests + +open Paket +open FsUnit +open NUnit.Framework +open Paket.Requirements + +[] +let ``combineOrSimplifiesRestrictions``() = + let left = + (FrameworkRestriction.Or + (FrameworkRestriction.And + (FrameworkRestriction.And + (FrameworkRestriction.NoRestriction, + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5))), + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))), + FrameworkRestriction.And + (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5), + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))))) + let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client) + combineRestrictionsWithOr left right + |> shouldEqual FrameworkRestriction.NoRestriction + + From 127a1756a32cae654886fb891816d8e6e52868e1 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sat, 20 May 2017 20:50:22 +0200 Subject: [PATCH 06/47] proper handling in addFrameworkRestrictionsToDependencies. --- .../Versioning/FrameworkHandling.fs | 1 - src/Paket.Core/Versioning/Requirements.fs | 102 +++++++++++------- tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 10 +- .../Versioning/FrameworkRestrictionTests.fs | 40 +++++-- .../Versioning/RestrictionFilterSpecs.fs | 2 +- 5 files changed, 101 insertions(+), 54 deletions(-) diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index f1431eefe7..26ec7c236c 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -238,7 +238,6 @@ type FrameworkIdentifier = | WindowsPhoneApp of string | Silverlight of string - override x.ToString() = match x with | DotNetFramework v -> "net" + v.ShortString() diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 28f78d59f5..f4b99db38a 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -20,8 +20,8 @@ type FrameworkRestriction = | AtLeast of FrameworkIdentifier // Means: Take all frameworks NOT given by the restriction | Not of FrameworkRestriction - | Or of FrameworkRestriction * FrameworkRestriction - | And of FrameworkRestriction * FrameworkRestriction + | Or of FrameworkRestriction list + | And of FrameworkRestriction list override this.ToString() = match this with | FrameworkRestriction.NoRestriction -> "norestriction" @@ -30,8 +30,8 @@ type FrameworkRestriction = | FrameworkRestriction.Portable (r,_) -> r | FrameworkRestriction.AtLeast r -> ">= " + r.ToString() | FrameworkRestriction.Not(fr) -> sprintf "NOT (%O)" fr - | FrameworkRestriction.Or(fr1, fr2) -> sprintf "|| (%O) (%O)" fr1 fr2 - | FrameworkRestriction.And(fr1, fr2) -> sprintf "&& (%O) (%O)" fr1 fr2 + | FrameworkRestriction.Or(frl) -> sprintf "|| %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) + | FrameworkRestriction.And(frl) -> sprintf "&& %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) /// The list represented by this restriction (ie the included set of frameworks) member x.RepresentedFrameworks = @@ -54,15 +54,18 @@ type FrameworkRestriction = let notTaken = fr.RepresentedFrameworks FrameworkRestriction.NoRestriction.RepresentedFrameworks |> List.filter (fun fw -> notTaken |> Seq.contains fw |> not) - | FrameworkRestriction.Or (fr1, fr2) -> - [ fr1; fr2 ] + | FrameworkRestriction.Or (frl) -> + frl |> List.collect (fun fr -> fr.RepresentedFrameworks) |> List.distinct |> List.sort - | FrameworkRestriction.And (fr1, fr2) -> - let l1 = fr1.RepresentedFrameworks - fr2.RepresentedFrameworks - |> List.filter (fun fw -> l1 |> Seq.contains fw) + | FrameworkRestriction.And (frl) -> + match frl with + | h :: _ -> + let allLists = frl |> List.map (fun fr -> fr.RepresentedFrameworks) + h.RepresentedFrameworks + |> List.filter (fun fw -> allLists |> List.forall(fun l1 -> l1 |> Seq.contains fw)) + | _ -> [] /// Returns true if the restriction x is a subset of the restriction y (a restriction basically represents a list, see RepresentedFrameworks) /// For example =net46 is a subset of >=netstandard13 @@ -71,7 +74,7 @@ type FrameworkRestriction = x.RepresentedFrameworks |> List.forall (fun inner -> superset |> Seq.contains inner) static member Between (x, y) = - FrameworkRestriction.And(FrameworkRestriction.AtLeast x, FrameworkRestriction.Not (FrameworkRestriction.AtLeast y)) + FrameworkRestriction.And[FrameworkRestriction.AtLeast x; FrameworkRestriction.Not (FrameworkRestriction.AtLeast y)] static member ExactlyProfile (pf: TargetProfile) = match pf with | SinglePlatform f -> Exactly f @@ -105,12 +108,14 @@ let combineRestrictionsWithOr (x : FrameworkRestriction) y = x else match x, y with - | FrameworkRestriction.And(FrameworkRestriction.Not a, b), _ when a = y -> b - | FrameworkRestriction.And(a, FrameworkRestriction.Not b), _ when b = y -> a - | _, FrameworkRestriction.And(FrameworkRestriction.Not a, b) when a = x -> b - | _, FrameworkRestriction.And(a, FrameworkRestriction.Not b) when b = x -> a + | FrameworkRestriction.And[FrameworkRestriction.Not negate; general], other + | FrameworkRestriction.And[general; FrameworkRestriction.Not negate], other + | other, FrameworkRestriction.And[FrameworkRestriction.Not negate; general] + | other, FrameworkRestriction.And[general; FrameworkRestriction.Not negate] when negate = other -> + // "negate && NOT general" might not be empty, ie general might not be a superset of negate + if other.IsSubsetOf general then general else FrameworkRestriction.Or[general; other] | _ -> - let combined = FrameworkRestriction.Or(x, y) + let combined = FrameworkRestriction.Or[x; y] if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then FrameworkRestriction.NoRestriction else @@ -486,7 +491,7 @@ let combineRestrictionsWithAnd (x : FrameworkRestriction) y = elif y.IsSubsetOf x then y else - let combined = FrameworkRestriction.And(x, y) + let combined = FrameworkRestriction.And[x; y] if combined.RepresentedFrameworks |> Seq.isEmpty then FrameworkRestriction.EmptySet else combined @@ -871,36 +876,55 @@ type PackageRequirement = | _ -> invalidArg "that" "cannot compare value of different types" let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = - + let frameworkGroupPaths = + frameworkGroups + |> Seq.map (fun fw -> {PlatformMatching.ParsedPlatformPath.Name = fw.ToString(); PlatformMatching.ParsedPlatformPath.Platforms = [fw] }) + |> Seq.toList let referenced = rawDependencies |> List.groupBy (fun (n:PackageName,req,pp:PlatformMatching.ParsedPlatformPath) -> n,req) |> List.map (fun ((name, req), group) -> // We need to append all the other platforms we support. - // TODO: this might miss out intersections! - let pps = group |> List.map (fun (_,_,pp) -> pp) + let packageGroups = group |> List.map (fun (_,_,packageGroup) -> packageGroup) let restrictions = - pps - |> List.map (fun pp -> - let restriction = - match pp.Platforms with - | _ when System.String.IsNullOrEmpty pp.Name -> FrameworkRestriction.NoRestriction + packageGroups + |> List.map (fun packageGroup -> + let packageGroupRestriction = + match packageGroup.Platforms with + | _ when System.String.IsNullOrEmpty packageGroup.Name -> FrameworkRestriction.NoRestriction | [] -> FrameworkRestriction.NoRestriction | [ pf ] -> FrameworkRestriction.AtLeast pf - | _ -> FrameworkRestriction.Portable(pp.Name, pp.Platforms) - let minimalRestriction = - frameworkGroups - |> Seq.filter (fun fw -> - // special casing for portable -> should be removed once portable is a normal FrameworkIdentifier - if pp.Platforms.Length < 2 then pp.Platforms |> Seq.contains fw |> not else true) - |> Seq.filter (fun fw -> - // filter all restrictions which would render this group to nothing (ie smaller restrictions) - // filter out unrelated restrictions - restriction.IsSubsetOf (FrameworkRestriction.AtLeast fw) |> not) - |> Seq.fold (fun curRestr fw -> - FrameworkRestriction.And(curRestr, FrameworkRestriction.Not (FrameworkRestriction.AtLeast fw))) restriction - minimalRestriction) - name, req, restrictions |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet + | _ -> FrameworkRestriction.Portable(packageGroup.Name, packageGroup.Platforms) + + frameworkGroups + |> Seq.filter (fun frameworkGroup -> + // special casing for portable -> should be removed once portable is a normal FrameworkIdentifier + if packageGroup.Platforms.Length < 2 then packageGroup.Platforms |> Seq.contains frameworkGroup |> not else true) + // TODO: Check if this is needed (I think the logic below is a general version of this subset logic) + |> Seq.filter (fun frameworkGroup -> + // filter all restrictions which would render this group to nothing (ie smaller restrictions) + // filter out unrelated restrictions + packageGroupRestriction.IsSubsetOf (FrameworkRestriction.AtLeast frameworkGroup) |> not) + |> Seq.fold (fun curRestr frameworkGroup -> + // We start with the restriction inherently given by the current group, + // But this is too broad as other groups might "steal" better suited frameworks + // So we subtract all "bigger" groups ('frameworkGroup' parameter). + // Problem is that this is too strict as there might be an intersection that now is assigned nowhere + // Example would be two groups with netstandard13 and net451 which will generate + // (>=net451 && <=netstandard13) for one and (>=netstandard13 && <=net451) for the other group + // but now net461 which supports netstandard13 is nowhere -> we need to decide here and add back the intersection + + let missing = combineRestrictionsWithAnd curRestr (FrameworkRestriction.AtLeast frameworkGroup) + let combined = combineRestrictionsWithAnd curRestr (FrameworkRestriction.Not (FrameworkRestriction.AtLeast frameworkGroup)) + match packageGroup.Platforms, missing.RepresentedFrameworks with + | [ packageGroupFw ], firstMissing :: _ -> + // the common set goes to the better matching one + match PlatformMatching.findBestMatch (frameworkGroupPaths, SinglePlatform firstMissing) with + | Some { PlatformMatching.ParsedPlatformPath.Platforms = [ cfw ] } when cfw = packageGroupFw -> curRestr + | _ -> combined + | _ -> combined) packageGroupRestriction) + let combinedRestrictions = restrictions |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet + name, req, combinedRestrictions ) //|> List.append frameworks diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index 5ff7864455..bfbf0a2314 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -184,7 +184,7 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"ReadOnlyCollectionExtensions.nuspec")).Dependencies |> shouldEqual [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"), - makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] + makeOrList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V2), DotNetFramework(FrameworkVersion.V3_5))] PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V2)) @@ -240,7 +240,7 @@ let ``can detect dependencies for MathNet.Numerics``() = |> shouldEqual [ PackageName "TaskParallelLibrary", DependenciesFileParser.parseVersionRequirement(">= 1.0.2856.0"), - makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))] ] + makeOrList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client))] ] [] let ``can detect dependencies for MathNet.Numerics.FSharp``() = @@ -311,7 +311,7 @@ let ``can detect explicit dependencies for EasyNetQ``() = (PackageName "Microsoft.Bcl", DependenciesFileParser.parseVersionRequirement(">= 1.1.10"), makeOrList - [FrameworkRestriction.And( - FrameworkRestriction.NoRestriction, - FrameworkRestriction.Not (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5)))) + [FrameworkRestriction.And[ + FrameworkRestriction.NoRestriction + FrameworkRestriction.Not (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5)))] ]) \ No newline at end of file diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index 49a0e834a4..bb9f0e6692 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -6,19 +6,43 @@ open NUnit.Framework open Paket.Requirements [] -let ``combineOrSimplifiesRestrictions``() = +let ``combineOr can simplify the NoRestriction set``() = let left = (FrameworkRestriction.Or - (FrameworkRestriction.And - (FrameworkRestriction.And - (FrameworkRestriction.NoRestriction, - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5))), - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))), + [FrameworkRestriction.And + [ FrameworkRestriction.And + [ FrameworkRestriction.NoRestriction + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5))] + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))] FrameworkRestriction.And - (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5), - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))))) + [FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5) + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))]]) let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client) combineRestrictionsWithOr left right |> shouldEqual FrameworkRestriction.NoRestriction +[] +let ``combineOr can simplify disjunct sets``() = + let left = + FrameworkRestriction.And[ + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1) + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_6_2))] + let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_6_2) + // Logic says this is >= net451 but it is >= net451 || >= netstandard13 + combineRestrictionsWithOr left right + |> shouldEqual (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1)) + +[] +let ``combineOr needs to consider partly disjunct sets``() = + let left = + FrameworkRestriction.And[ + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1) + FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3))] + let right = FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3) + // Logic says this is >= net451 but it is >= net451 || >= netstandard13 + combineRestrictionsWithOr left right + |> shouldEqual (FrameworkRestriction.Or[ + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1) + FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3)]) + diff --git a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs index 15475f21e4..ae57f26315 100644 --- a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs @@ -126,7 +126,7 @@ let ``should filter >= net20 < net40 and >= net40``() = let ``should not filter native, net452``() = //FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform)).IsSameCategoryAs(FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))) |> shouldEqual (Some true) - let l1 = ExplicitRestriction (FrameworkRestriction.Or (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5_2)), FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform)))) + let l1 = ExplicitRestriction (FrameworkRestriction.Or [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5_2)); FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))]) let l2 = ExplicitRestriction (FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))) filterRestrictions l1 l2 From 98d3ab87353d0f3ca839451497aa53449d1317f4 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sat, 20 May 2017 21:08:25 +0200 Subject: [PATCH 07/47] refactor --- src/Paket.Core/Dependencies/Nuspec.fs | 2 +- .../Dependencies/PackageResolver.fs | 6 +- src/Paket.Core/Installation/UpdateProcess.fs | 2 +- src/Paket.Core/PackageAnalysis/Why.fs | 2 +- .../PackageManagement/NugetConvert.fs | 2 +- .../PaketConfigFiles/DependenciesFile.fs | 2 +- .../PaketConfigFiles/InstallModel.fs | 2 +- src/Paket.Core/PaketConfigFiles/LockFile.fs | 2 +- .../PaketConfigFiles/ProjectFile.fs | 2 +- src/Paket.Core/Versioning/Requirements.fs | 171 ++++++++++-------- tests/Paket.Tests/TestHelpers.fs | 2 +- .../Versioning/FrameworkRestrictionTests.fs | 6 +- 12 files changed, 107 insertions(+), 94 deletions(-) diff --git a/src/Paket.Core/Dependencies/Nuspec.fs b/src/Paket.Core/Dependencies/Nuspec.fs index cbfeb80989..81ead9dd9f 100644 --- a/src/Paket.Core/Dependencies/Nuspec.fs +++ b/src/Paket.Core/Dependencies/Nuspec.fs @@ -136,7 +136,7 @@ type Nuspec = ExplicitRestriction( restrictions |> List.map (fun x -> x.FrameworkRestrictions |> getExplicitRestriction) - |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet) } ] } + |> List.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet) } ] } /// load the file from an nuspec text stream. The fileName is only used for error reporting. static member internal Load(fileName:string, f:Stream) = diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index d40b61b473..25b1e96185 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -95,7 +95,7 @@ module DependencySetFilter = let filterByRestrictions (restrictions:FrameworkRestrictions) (dependencies:DependencySet) : DependencySet = match getExplicitRestriction restrictions with - | FrameworkRestriction.NoRestriction -> dependencies + | FrameworkRestriction.HasNoRestriction -> dependencies | restrictions -> dependencies |> Set.filter (isIncluded restrictions) @@ -262,7 +262,7 @@ let calcOpenRequirements (exploredPackage:ResolvedPackage,globalFrameworkRestric | ExplicitRestriction r -> match r2 with | ExplicitRestriction r2 -> - combineRestrictionsWithOr r r2 |> ExplicitRestriction + FrameworkRestriction.combineRestrictionsWithOr r r2 |> ExplicitRestriction | AutoDetectFramework -> ExplicitRestriction r | AutoDetectFramework -> r @@ -365,7 +365,7 @@ let private updateRestrictions (pkgConfig:PackageConfig) (package:ResolvedPackag let dependencySettings = pkgConfig.Dependency.Settings.FrameworkRestrictions |> getExplicitRestriction let globalSettings = pkgConfig.GlobalRestrictions |> getExplicitRestriction [packageSettings;dependencySettings;globalSettings] - |> Seq.fold (combineRestrictionsWithAnd) FrameworkRestriction.NoRestriction + |> Seq.fold (FrameworkRestriction.combineRestrictionsWithAnd) FrameworkRestriction.NoRestriction //optimizeRestrictions (List.concat) { package with diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs index ce87883c7d..dcae2d0e40 100644 --- a/src/Paket.Core/Installation/UpdateProcess.fs +++ b/src/Paket.Core/Installation/UpdateProcess.fs @@ -173,7 +173,7 @@ let detectProjectFrameworksForDependenciesFile (dependenciesFile:DependenciesFil | None -> failwithf "Could not detect target framework for project %s" p.FileName) |> List.distinct if rawRestrictions.IsEmpty then Paket.Requirements.FrameworkRestriction.NoRestriction - else rawRestrictions |> Seq.fold Paket.Requirements.combineRestrictionsWithOr Paket.Requirements.FrameworkRestriction.EmptySet) + else rawRestrictions |> Seq.fold Paket.Requirements.FrameworkRestriction.combineRestrictionsWithOr Paket.Requirements.FrameworkRestriction.EmptySet) dependenciesFile.Groups |> Map.map (fun groupName group -> diff --git a/src/Paket.Core/PackageAnalysis/Why.fs b/src/Paket.Core/PackageAnalysis/Why.fs index 4ae2e77da6..711b92f958 100644 --- a/src/Paket.Core/PackageAnalysis/Why.fs +++ b/src/Paket.Core/PackageAnalysis/Why.fs @@ -64,7 +64,7 @@ module DependencyChain = let formatFxReq (fr : FrameworkRestrictions) = match fr with | AutoDetectFramework - | ExplicitRestriction Paket.Requirements.FrameworkRestriction.NoRestriction -> "" + | ExplicitRestriction Paket.Requirements.FrameworkRestriction.HasNoRestriction -> "" | ExplicitRestriction fr -> sprintf " (%O)" fr let formatName name i = sprintf "%s-> %O" (String.replicate i " ") name let rec format' i (name,chain) = diff --git a/src/Paket.Core/PackageManagement/NugetConvert.fs b/src/Paket.Core/PackageManagement/NugetConvert.fs index 031968655a..e5c3c151e6 100644 --- a/src/Paket.Core/PackageManagement/NugetConvert.fs +++ b/src/Paket.Core/PackageManagement/NugetConvert.fs @@ -263,7 +263,7 @@ let createDependenciesFileR (rootDirectory : DirectoryInfo) nugetEnv mode = | _ -> [] let restrictions = if restrictions = [] then FrameworkRestriction.NoRestriction - else restrictions |> Seq.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet + else restrictions |> Seq.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet name, latestVersion, restrictions) let packages = diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index b30fe2dc31..e8443ce9ec 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -145,7 +145,7 @@ type DependenciesFile(fileName,groups:Map, textRepr let frameworks = projects |> Array.choose ProjectFile.getTargetFramework |> Array.distinct let restrictions = frameworks |> Array.map FrameworkRestriction.Exactly if restrictions |> Array.isEmpty then FrameworkRestriction.NoRestriction - else restrictions |> Array.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet + else restrictions |> Array.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet ) fun restrictions -> match restrictions with diff --git a/src/Paket.Core/PaketConfigFiles/InstallModel.fs b/src/Paket.Core/PaketConfigFiles/InstallModel.fs index 815983e3b7..aa913d1575 100644 --- a/src/Paket.Core/PaketConfigFiles/InstallModel.fs +++ b/src/Paket.Core/PaketConfigFiles/InstallModel.fs @@ -738,7 +738,7 @@ module InstallModel = let applyFrameworkRestrictions (restriction:FrameworkRestriction) (installModel:InstallModel) = match restriction with - | FrameworkRestriction.NoRestriction -> installModel + | FrameworkRestriction.HasNoRestriction -> installModel | restriction -> let applyRestriction folder = { folder with Targets = applyRestrictionsToTargets restriction folder.Targets} diff --git a/src/Paket.Core/PaketConfigFiles/LockFile.fs b/src/Paket.Core/PaketConfigFiles/LockFile.fs index d9572d0af2..35bf189814 100644 --- a/src/Paket.Core/PaketConfigFiles/LockFile.fs +++ b/src/Paket.Core/PaketConfigFiles/LockFile.fs @@ -63,7 +63,7 @@ module LockFileSerializer = | None -> () match options.Settings.FrameworkRestrictions |> getExplicitRestriction with - | FrameworkRestriction.NoRestriction -> () + | FrameworkRestriction.HasNoRestriction -> () | list -> yield "RESTRICTION: " + list.ToString() ] /// [omit] diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs index fb31105cd0..5ecd6f6db4 100644 --- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs @@ -738,7 +738,7 @@ module ProjectFile = model.ApplyFrameworkRestrictions ((List.map DotNetCore KnownTargetProfiles.DotNetCoreVersions @ List.map DotNetStandard KnownTargetProfiles.DotNetStandardVersions) |> List.map FrameworkRestriction.Exactly - |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet) + |> List.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet) // handle legacy conditions let conditions = diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index f4b99db38a..36d365839f 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -11,55 +11,55 @@ open Paket.Logging // Ideally we would "simplify" the trees to a "normal" form internally [] type FrameworkRestriction = - // TODO: private - | NoRestriction - | EmptySet - | Exactly of FrameworkIdentifier + private + | NoRestrictionP + | EmptySetP + | ExactlyP of FrameworkIdentifier //[] - | Portable of string * FrameworkIdentifier list - | AtLeast of FrameworkIdentifier + | PortableP of string * FrameworkIdentifier list + | AtLeastP of FrameworkIdentifier // Means: Take all frameworks NOT given by the restriction - | Not of FrameworkRestriction - | Or of FrameworkRestriction list - | And of FrameworkRestriction list + | NotP of FrameworkRestriction + | OrP of FrameworkRestriction list + | AndP of FrameworkRestriction list override this.ToString() = match this with - | FrameworkRestriction.NoRestriction -> "norestriction" - | FrameworkRestriction.EmptySet -> "emptyset" - | FrameworkRestriction.Exactly r -> r.ToString() - | FrameworkRestriction.Portable (r,_) -> r - | FrameworkRestriction.AtLeast r -> ">= " + r.ToString() - | FrameworkRestriction.Not(fr) -> sprintf "NOT (%O)" fr - | FrameworkRestriction.Or(frl) -> sprintf "|| %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) - | FrameworkRestriction.And(frl) -> sprintf "&& %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) + | FrameworkRestriction.NoRestrictionP -> "norestriction" + | FrameworkRestriction.EmptySetP -> "emptyset" + | FrameworkRestriction.ExactlyP r -> r.ToString() + | FrameworkRestriction.PortableP (r,_) -> r + | FrameworkRestriction.AtLeastP r -> ">= " + r.ToString() + | FrameworkRestriction.NotP(fr) -> sprintf "NOT (%O)" fr + | FrameworkRestriction.OrP(frl) -> sprintf "|| %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) + | FrameworkRestriction.AndP(frl) -> sprintf "&& %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) /// The list represented by this restriction (ie the included set of frameworks) member x.RepresentedFrameworks = match x with - | FrameworkRestriction.NoRestriction -> + | FrameworkRestriction.NoRestrictionP -> KnownTargetProfiles.AllProfiles |> List.collect (function | SinglePlatform fw -> [fw] | PortableProfile (_, fws) -> fws) |> List.distinct |> List.sort - | FrameworkRestriction.Exactly r -> [ r ] - | FrameworkRestriction.EmptySet -> [ ] - | FrameworkRestriction.Portable (r, fws) -> + | FrameworkRestriction.ExactlyP r -> [ r ] + | FrameworkRestriction.EmptySetP -> [ ] + | FrameworkRestriction.PortableP (r, fws) -> fws - |> List.collect (fun fw -> (FrameworkRestriction.AtLeast fw).RepresentedFrameworks) + |> List.collect (fun fw -> (FrameworkRestriction.AtLeastP fw).RepresentedFrameworks) |> List.distinct |> List.sort - | FrameworkRestriction.AtLeast r -> PlatformMatching.getFrameworksSupporting r - | FrameworkRestriction.Not(fr) -> + | FrameworkRestriction.AtLeastP r -> PlatformMatching.getFrameworksSupporting r + | FrameworkRestriction.NotP(fr) -> let notTaken = fr.RepresentedFrameworks - FrameworkRestriction.NoRestriction.RepresentedFrameworks + FrameworkRestriction.NoRestrictionP.RepresentedFrameworks |> List.filter (fun fw -> notTaken |> Seq.contains fw |> not) - | FrameworkRestriction.Or (frl) -> + | FrameworkRestriction.OrP (frl) -> frl |> List.collect (fun fr -> fr.RepresentedFrameworks) |> List.distinct |> List.sort - | FrameworkRestriction.And (frl) -> + | FrameworkRestriction.AndP (frl) -> match frl with | h :: _ -> let allLists = frl |> List.map (fun fr -> fr.RepresentedFrameworks) @@ -73,20 +73,73 @@ type FrameworkRestriction = let superset = y.RepresentedFrameworks x.RepresentedFrameworks |> List.forall (fun inner -> superset |> Seq.contains inner) + static member NoRestriction = NoRestrictionP + static member EmptySet = EmptySetP + static member Exactly = ExactlyP + static member Portable = PortableP + static member AtLeast = AtLeastP static member Between (x, y) = - FrameworkRestriction.And[FrameworkRestriction.AtLeast x; FrameworkRestriction.Not (FrameworkRestriction.AtLeast y)] + FrameworkRestriction.AndP[FrameworkRestriction.AtLeastP x; FrameworkRestriction.NotP (FrameworkRestriction.AtLeastP y)] static member ExactlyProfile (pf: TargetProfile) = match pf with - | SinglePlatform f -> Exactly f - | PortableProfile(name,fws) -> Portable(name, fws) - + | SinglePlatform f -> ExactlyP f + | PortableProfile(name,fws) -> PortableP(name, fws) + + override x.Equals(y) = (match y with :? FrameworkRestriction as r -> r.RepresentedFrameworks = x.RepresentedFrameworks | _ -> false) override x.GetHashCode() = x.RepresentedFrameworks.GetHashCode() interface System.IComparable with member x.CompareTo(y) = (match y with :? FrameworkRestriction as r -> compare x.RepresentedFrameworks r.RepresentedFrameworks | _ -> failwith "wrong type") +module FrameworkRestriction = + let And = FrameworkRestriction.AndP + let Or = FrameworkRestriction.OrP + let Not = FrameworkRestriction.NotP + + let combineRestrictionsWithOr (x : FrameworkRestriction) y = + if x.IsSubsetOf y then + y + elif y.IsSubsetOf x then + x + else + match x, y with + | FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general], other + | FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate], other + | other, FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general] + | other, FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate] when negate = other -> + // "negate && NOT general" might not be empty, ie general might not be a superset of negate + if other.IsSubsetOf general then general else FrameworkRestriction.OrP[general; other] + | _ -> + let combined = FrameworkRestriction.OrP[x; y] + if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then + FrameworkRestriction.NoRestriction + else + combined + let (|HasNoRestriction|_|) x = + if x = FrameworkRestriction.NoRestrictionP then Some () else None + let combineRestrictionsWithAnd (x : FrameworkRestriction) y = + // combine means basically we say AND (both need to be satisfied) + if x.IsSubsetOf y then + x + elif y.IsSubsetOf x then + y + else + let combined = FrameworkRestriction.AndP[x; y] + if combined.RepresentedFrameworks |> Seq.isEmpty then + FrameworkRestriction.EmptySet + else combined + //if x.IsSameCategoryAs(y) <> Some false then + // combineSameCategoryOrPortableRestrictions x y + //else + // if loose then + // match (x.GetOneIdentifier, y.GetOneIdentifier) with + // | Some (FrameworkIdentifier.DotNetFramework _ ), Some (FrameworkIdentifier.DotNetStandard _ ) -> [x] + // | Some (FrameworkIdentifier.DotNetStandard _ ), Some (FrameworkIdentifier.DotNetFramework _ ) -> [y] + // | _ -> [] + // else + // [] type FrameworkRestrictions = | ExplicitRestriction of FrameworkRestriction | AutoDetectFramework @@ -101,25 +154,6 @@ type FrameworkRestrictions = let getExplicitRestriction (frameworkRestrictions:FrameworkRestrictions) = frameworkRestrictions.GetExplicitRestriction() -let combineRestrictionsWithOr (x : FrameworkRestriction) y = - if x.IsSubsetOf y then - y - elif y.IsSubsetOf x then - x - else - match x, y with - | FrameworkRestriction.And[FrameworkRestriction.Not negate; general], other - | FrameworkRestriction.And[general; FrameworkRestriction.Not negate], other - | other, FrameworkRestriction.And[FrameworkRestriction.Not negate; general] - | other, FrameworkRestriction.And[general; FrameworkRestriction.Not negate] when negate = other -> - // "negate && NOT general" might not be empty, ie general might not be a superset of negate - if other.IsSubsetOf general then general else FrameworkRestriction.Or[general; other] - | _ -> - let combined = FrameworkRestriction.Or[x; y] - if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then - FrameworkRestriction.NoRestriction - else - combined let parseRestrictionsLegacy failImmediatly (text:string) = // TODO: Change this code to convert old "framework" sematics in @@ -168,7 +202,7 @@ let parseRestrictionsLegacy failImmediatly (text:string) = | Some y -> yield FrameworkRestriction.Between(x, y) else yield FrameworkRestriction.Exactly x] - |> List.fold (fun state item -> combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet + |> List.fold (fun state item -> FrameworkRestriction.combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet let rec optimizeRestrictions restrictions = restrictions @@ -484,34 +518,13 @@ let optimizeDependencies originalDependencies = originalDependencies |> List.map (fun (a,b,c) -> a,b, ExplicitRestriction c) -let combineRestrictionsWithAnd (x : FrameworkRestriction) y = - // combine means basically we say AND (both need to be satisfied) - if x.IsSubsetOf y then - x - elif y.IsSubsetOf x then - y - else - let combined = FrameworkRestriction.And[x; y] - if combined.RepresentedFrameworks |> Seq.isEmpty then - FrameworkRestriction.EmptySet - else combined - //if x.IsSameCategoryAs(y) <> Some false then - // combineSameCategoryOrPortableRestrictions x y - //else - // if loose then - // match (x.GetOneIdentifier, y.GetOneIdentifier) with - // | Some (FrameworkIdentifier.DotNetFramework _ ), Some (FrameworkIdentifier.DotNetStandard _ ) -> [x] - // | Some (FrameworkIdentifier.DotNetStandard _ ), Some (FrameworkIdentifier.DotNetFramework _ ) -> [y] - // | _ -> [] - // else - // [] let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestrictions) = match list1,list2 with - | ExplicitRestriction FrameworkRestriction.NoRestriction, AutoDetectFramework -> AutoDetectFramework - | AutoDetectFramework, ExplicitRestriction FrameworkRestriction.NoRestriction -> AutoDetectFramework + | ExplicitRestriction FrameworkRestriction.HasNoRestriction, AutoDetectFramework -> AutoDetectFramework + | AutoDetectFramework, ExplicitRestriction FrameworkRestriction.HasNoRestriction -> AutoDetectFramework | AutoDetectFramework, AutoDetectFramework -> AutoDetectFramework - | ExplicitRestriction fr1 , ExplicitRestriction fr2 -> ExplicitRestriction (combineRestrictionsWithAnd fr1 fr2) + | ExplicitRestriction fr1 , ExplicitRestriction fr2 -> ExplicitRestriction (FrameworkRestriction.combineRestrictionsWithAnd fr1 fr2) //let filtered = // match list1, list2 with // | [],_ -> list2 @@ -657,7 +670,7 @@ type InstallSettings = | Some Force -> yield "redirects: force" | None -> () match this.FrameworkRestrictions with - | ExplicitRestriction FrameworkRestriction.NoRestriction -> () + | ExplicitRestriction FrameworkRestriction.HasNoRestriction -> () | AutoDetectFramework -> () | ExplicitRestriction fr -> yield "restriction: " + (fr.ToString()) match this.GenerateLoadScripts with @@ -914,8 +927,8 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = // (>=net451 && <=netstandard13) for one and (>=netstandard13 && <=net451) for the other group // but now net461 which supports netstandard13 is nowhere -> we need to decide here and add back the intersection - let missing = combineRestrictionsWithAnd curRestr (FrameworkRestriction.AtLeast frameworkGroup) - let combined = combineRestrictionsWithAnd curRestr (FrameworkRestriction.Not (FrameworkRestriction.AtLeast frameworkGroup)) + let missing = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.AtLeast frameworkGroup) + let combined = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.Not (FrameworkRestriction.AtLeast frameworkGroup)) match packageGroup.Platforms, missing.RepresentedFrameworks with | [ packageGroupFw ], firstMissing :: _ -> // the common set goes to the better matching one @@ -923,7 +936,7 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = | Some { PlatformMatching.ParsedPlatformPath.Platforms = [ cfw ] } when cfw = packageGroupFw -> curRestr | _ -> combined | _ -> combined) packageGroupRestriction) - let combinedRestrictions = restrictions |> List.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet + let combinedRestrictions = restrictions |> List.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet name, req, combinedRestrictions ) //|> List.append frameworks diff --git a/tests/Paket.Tests/TestHelpers.fs b/tests/Paket.Tests/TestHelpers.fs index 225a69e65d..49affdf5b6 100644 --- a/tests/Paket.Tests/TestHelpers.fs +++ b/tests/Paket.Tests/TestHelpers.fs @@ -11,7 +11,7 @@ open Paket.Domain let makeOrList (l:_ list) = if l.IsEmpty then FrameworkRestriction.NoRestriction - else Seq.fold combineRestrictionsWithOr FrameworkRestriction.EmptySet l + else Seq.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet l |> ExplicitRestriction let getPortableRestriction s = diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index bb9f0e6692..a526c0454b 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -18,7 +18,7 @@ let ``combineOr can simplify the NoRestriction set``() = [FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5) FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))]]) let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client) - combineRestrictionsWithOr left right + FrameworkRestriction.combineRestrictionsWithOr left right |> shouldEqual FrameworkRestriction.NoRestriction [] @@ -29,7 +29,7 @@ let ``combineOr can simplify disjunct sets``() = FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_6_2))] let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_6_2) // Logic says this is >= net451 but it is >= net451 || >= netstandard13 - combineRestrictionsWithOr left right + FrameworkRestriction.combineRestrictionsWithOr left right |> shouldEqual (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1)) [] @@ -40,7 +40,7 @@ let ``combineOr needs to consider partly disjunct sets``() = FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3))] let right = FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3) // Logic says this is >= net451 but it is >= net451 || >= netstandard13 - combineRestrictionsWithOr left right + FrameworkRestriction.combineRestrictionsWithOr left right |> shouldEqual (FrameworkRestriction.Or[ FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1) FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3)]) From 7f86897884712e5df24ee8d0df48d5c918df3e39 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sun, 21 May 2017 13:40:00 +0200 Subject: [PATCH 08/47] make sure formulars are always in dnf (which makes writing the simplifier easier and only generated 'simple' formulas). --- .../Versioning/FrameworkHandling.fs | 2 + src/Paket.Core/Versioning/PlatformMatching.fs | 52 ++- src/Paket.Core/Versioning/Requirements.fs | 324 ++++++++++++++---- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 2 +- tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 8 +- .../Versioning/FrameworkRestrictionTests.fs | 62 +++- 6 files changed, 355 insertions(+), 95 deletions(-) diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index 26ec7c236c..452c0e6fe5 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -770,6 +770,8 @@ module KnownTargetProfiles = (AllNativeProfiles |> List.map SinglePlatform) @ AllDotNetStandardAndCoreProfiles @ AllDotNetProfiles + |> List.distinct + |> List.sort let FindPortableProfile name = AllProfiles diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index de2920edc4..f1dd3e5d01 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -107,17 +107,49 @@ let collectPlatforms = /// Returns all framework identifiers which (transitively) support the given framework identifier let getFrameworksSupporting = - let cache = System.Collections.Concurrent.ConcurrentDictionary<_,FrameworkIdentifier list>() - fun (x:FrameworkIdentifier) -> - cache.GetOrAdd(x, fun _ -> - // calculate + let calculate (x:FrameworkIdentifier) = + // calculate + KnownTargetProfiles.AllProfiles + |> List.collect(function + | SinglePlatform p -> [p] + | PortableProfile (_, fws) -> fws) + |> List.distinct + |> List.filter (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains x) + memoize calculate + +let getPlatformsSupporting = + // http://nugettoolsdev.azurewebsites.net + let calculate (x:TargetProfile) = + match x with + | PortableProfile (name,fws) -> + // Portables can be supported by other portables and by all fws given. KnownTargetProfiles.AllProfiles - |> List.collect(function - | SinglePlatform p -> [p] - | PortableProfile (_, fws) -> fws) - |> List.distinct - |> List.filter (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains x) - ) + |> List.filter (function + | PortableProfile (otherName,otherfws) -> + // the other portable profile is supported, when the transitive supported set is a superset + let currentSupportedFrameworks = + fws + |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) + |> List.distinct + |> List.sort + let otherSupportedFrameworks = + otherfws + |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) + |> List.distinct + |> List.sort + + // take if the other profile supports all frameworks we support + currentSupportedFrameworks + |> Seq.forall (fun fw -> otherSupportedFrameworks |> Seq.exists ((=) fw)) + | SinglePlatform otherfw -> + // otherfw is supported if it is supported by of any fw in fws + fws + |> Seq.exists (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains otherfw)) + | SinglePlatform tf -> + // SinglePlatforms are only supported by other SinglePlatforms + getFrameworksSupporting tf + |> List.map SinglePlatform + memoize calculate let platformsSupport = let rec platformsSupport platform platforms = diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 36d365839f..7877fc1472 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -6,130 +6,302 @@ open Paket.Domain open Paket.PackageSources open Paket.Logging +let private allFrameworks = + KnownTargetProfiles.AllProfiles + |> List.collect (function + | SinglePlatform fw -> [fw] + | PortableProfile (_, fws) -> fws) + |> List.distinct + |> List.sort [] // To make reasoning and writing tests easier. // Ideally we would "simplify" the trees to a "normal" form internally -[] -type FrameworkRestriction = +[] +[] +type FrameworkRestrictionP = private - | NoRestrictionP - | EmptySetP + //| NoRestrictionP // = AndP [] + //| EmptySetP // = OrP [] | ExactlyP of FrameworkIdentifier //[] | PortableP of string * FrameworkIdentifier list | AtLeastP of FrameworkIdentifier // Means: Take all frameworks NOT given by the restriction - | NotP of FrameworkRestriction - | OrP of FrameworkRestriction list - | AndP of FrameworkRestriction list + | NotP of FrameworkRestrictionP + | OrP of FrameworkRestrictionP list + | AndP of FrameworkRestrictionP list + member x.InfixNotation = + match x with + | FrameworkRestrictionP.ExactlyP r -> r.ToString() + | FrameworkRestrictionP.PortableP (r,_) -> r + | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() + | FrameworkRestrictionP.NotP(fr) -> sprintf "NOT (%O)" fr + | FrameworkRestrictionP.OrP(frl) -> + match frl with + | [] -> "false" + | [single] -> sprintf "%O" single + | _ -> sprintf "(%s)" (System.String.Join(" || ", frl |> Seq.map (fun inner -> sprintf "(%s)" inner.InfixNotation))) + | FrameworkRestrictionP.AndP(frl) -> + match frl with + | [] -> "true" + | [single] -> sprintf "%O" single + | _ -> sprintf "(%s)" (System.String.Join(" && ", frl |> Seq.map (fun inner -> sprintf "(%s)" inner.InfixNotation))) override this.ToString() = match this with - | FrameworkRestriction.NoRestrictionP -> "norestriction" - | FrameworkRestriction.EmptySetP -> "emptyset" - | FrameworkRestriction.ExactlyP r -> r.ToString() - | FrameworkRestriction.PortableP (r,_) -> r - | FrameworkRestriction.AtLeastP r -> ">= " + r.ToString() - | FrameworkRestriction.NotP(fr) -> sprintf "NOT (%O)" fr - | FrameworkRestriction.OrP(frl) -> sprintf "|| %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) - | FrameworkRestriction.AndP(frl) -> sprintf "&& %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) + | FrameworkRestrictionP.ExactlyP r -> r.ToString() + | FrameworkRestrictionP.PortableP (r,_) -> r + | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() + | FrameworkRestrictionP.NotP(fr) -> sprintf "NOT (%O)" fr + | FrameworkRestrictionP.OrP(frl) -> + match frl with + | [] -> "false" + | [single] -> sprintf "%O" single + | _ -> sprintf "|| %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) + | FrameworkRestrictionP.AndP(frl) -> + match frl with + | [] -> "true" + | [single] -> sprintf "%O" single + | _ -> sprintf "&& %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) /// The list represented by this restriction (ie the included set of frameworks) member x.RepresentedFrameworks = match x with - | FrameworkRestriction.NoRestrictionP -> - KnownTargetProfiles.AllProfiles |> List.collect (function - | SinglePlatform fw -> [fw] - | PortableProfile (_, fws) -> fws) - |> List.distinct - |> List.sort - | FrameworkRestriction.ExactlyP r -> [ r ] - | FrameworkRestriction.EmptySetP -> [ ] - | FrameworkRestriction.PortableP (r, fws) -> + | FrameworkRestrictionP.ExactlyP r -> [ r ] + | FrameworkRestrictionP.PortableP (r, fws) -> fws - |> List.collect (fun fw -> (FrameworkRestriction.AtLeastP fw).RepresentedFrameworks) + |> List.collect (fun fw -> (FrameworkRestrictionP.AtLeastP fw).RepresentedFrameworks) |> List.distinct |> List.sort - | FrameworkRestriction.AtLeastP r -> PlatformMatching.getFrameworksSupporting r - | FrameworkRestriction.NotP(fr) -> + | FrameworkRestrictionP.AtLeastP r -> + PlatformMatching.getFrameworksSupporting r + | FrameworkRestrictionP.NotP(fr) -> let notTaken = fr.RepresentedFrameworks - FrameworkRestriction.NoRestrictionP.RepresentedFrameworks + allFrameworks |> List.filter (fun fw -> notTaken |> Seq.contains fw |> not) - | FrameworkRestriction.OrP (frl) -> + | FrameworkRestrictionP.OrP (frl) -> frl |> List.collect (fun fr -> fr.RepresentedFrameworks) |> List.distinct |> List.sort - | FrameworkRestriction.AndP (frl) -> + | FrameworkRestrictionP.AndP (frl) -> match frl with | h :: _ -> let allLists = frl |> List.map (fun fr -> fr.RepresentedFrameworks) h.RepresentedFrameworks |> List.filter (fun fw -> allLists |> List.forall(fun l1 -> l1 |> Seq.contains fw)) - | _ -> [] + | [] -> + allFrameworks /// Returns true if the restriction x is a subset of the restriction y (a restriction basically represents a list, see RepresentedFrameworks) /// For example =net46 is a subset of >=netstandard13 - member x.IsSubsetOf (y:FrameworkRestriction) = + member x.IsSubsetOf (y:FrameworkRestrictionP) = let superset = y.RepresentedFrameworks x.RepresentedFrameworks |> List.forall (fun inner -> superset |> Seq.contains inner) - static member NoRestriction = NoRestrictionP - static member EmptySet = EmptySetP - static member Exactly = ExactlyP - static member Portable = PortableP - static member AtLeast = AtLeastP - static member Between (x, y) = - FrameworkRestriction.AndP[FrameworkRestriction.AtLeastP x; FrameworkRestriction.NotP (FrameworkRestriction.AtLeastP y)] static member ExactlyProfile (pf: TargetProfile) = match pf with | SinglePlatform f -> ExactlyP f | PortableProfile(name,fws) -> PortableP(name, fws) - override x.Equals(y) = (match y with :? FrameworkRestriction as r -> r.RepresentedFrameworks = x.RepresentedFrameworks | _ -> false) + override x.Equals(y) = (match y with :? FrameworkRestrictionP as r -> r.RepresentedFrameworks = x.RepresentedFrameworks | _ -> false) override x.GetHashCode() = x.RepresentedFrameworks.GetHashCode() interface System.IComparable with - member x.CompareTo(y) = (match y with :? FrameworkRestriction as r -> compare x.RepresentedFrameworks r.RepresentedFrameworks | _ -> failwith "wrong type") + member x.CompareTo(y) = (match y with :? FrameworkRestrictionP as r -> compare x.RepresentedFrameworks r.RepresentedFrameworks | _ -> failwith "wrong type") + +type FrameworkRestrictionLiteralI = + | ExactlyL of FrameworkIdentifier + | PortableL of string * FrameworkIdentifier list + | AtLeastL of FrameworkIdentifier + member internal x.RawFormular = + match x with + | ExactlyL id -> FrameworkRestrictionP.ExactlyP id + | PortableL (name, fws) -> FrameworkRestrictionP.PortableP (name, fws) + | AtLeastL id -> FrameworkRestrictionP.AtLeastP id +type FrameworkRestrictionLiteral = + { LiteraL : FrameworkRestrictionLiteralI; IsNegated : bool } + member internal x.RawFormular = + let raw = x.LiteraL.RawFormular + if x.IsNegated then FrameworkRestrictionP.NotP raw else raw + static member FromLiteral l = + { LiteraL = l ; IsNegated = false } + static member FromNegatedLiteral l = + { LiteraL = l ; IsNegated = true } +type FrameworkRestrictionAndList = + { Literals : FrameworkRestrictionLiteral list } + member internal x.RawFormular = + FrameworkRestrictionP.AndP (x.Literals |> List.map (fun literal -> literal.RawFormular)) + +type FrameworkRestriction = + { OrFormulas : FrameworkRestrictionAndList list } + member internal x.RawFormular = + FrameworkRestrictionP.OrP (x.OrFormulas |> List.map (fun andList -> andList.RawFormular)) + override x.ToString() = + x.RawFormular.ToString() + member x.IsSubsetOf (y:FrameworkRestriction) = + x.RawFormular.IsSubsetOf y.RawFormular + member x.RepresentedFrameworks = + x.RawFormular.RepresentedFrameworks module FrameworkRestriction = - let And = FrameworkRestriction.AndP - let Or = FrameworkRestriction.OrP - let Not = FrameworkRestriction.NotP + let EmptySet = { OrFormulas = [] } // false + let NoRestriction = { OrFormulas = [ { Literals = [] } ] } // true + let Exactly id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (ExactlyL id) ] } ] } + let Portable (name, fws)= { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (PortableL (name, fws)) ] } ] } + let AtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (AtLeastL id) ] } ] } + let NotAtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromNegatedLiteral (AtLeastL id) ] } ] } + + let private simplify (fr:FrameworkRestriction) = + /// When we have a restriction like (>=net35 && =net45 + /// then we can "optimize" / simplify to (>=net35 || >= net45) + /// because we don't need to "pseudo" restrict the set with the first restriction + /// when we add back later all the things we removed. + /// Generally: We can remove all negated literals in all clauses when a positive literal exists as a standalone Or clause + let rec removeNegatedLiteralsWhichOccurSinglePositive (fr:FrameworkRestriction) = + let positiveSingles = + fr.OrFormulas + |> List.choose (fun andFormular -> match andFormular.Literals with [ h ] -> Some h | _ -> None) + let workDone, reworked = + fr.OrFormulas + |> List.fold (fun (workDone, reworkedOrFormulas) andFormula -> + let reworkedAnd = + andFormula.Literals + |> List.filter (fun literal -> + positiveSingles + |> List.exists (fun p -> literal.IsNegated && literal.LiteraL = p.LiteraL) + |> not + ) + if reworkedAnd.Length < andFormula.Literals.Length then + true, { Literals = reworkedAnd } :: reworkedOrFormulas + else + workDone, andFormula :: reworkedOrFormulas + ) (false, []) + if workDone then removeNegatedLiteralsWhichOccurSinglePositive { OrFormulas = reworked } + else fr + /// (>= net40-full) && (< net46) && (>= net20) can be simplified to (< net46) && (>= net40-full) because (>= net40-full) is a subset of (>= net20) + // NOTE: This optimization is kind of dangerous as future frameworks might make it invalid + // However a lot of tests expect this simplification... We maybe want to remove it (or at least test) after we know the new framework restriction works. + let removeSubsetLiteralsInAndClause (fr:FrameworkRestriction) = + let simplifyAndClause (andClause:FrameworkRestrictionAndList) = + let literals = andClause.Literals + { Literals = + andClause.Literals + |> List.filter (fun literal -> + // we filter out literals, for which another literal exists which is a subset + literals + |> Seq.filter (fun l -> l <> literal) + |> Seq.exists (fun otherLiteral -> + otherLiteral.RawFormular.IsSubsetOf literal.RawFormular) + |> not) } + //andClause + { OrFormulas = fr.OrFormulas |> List.map simplifyAndClause } + + /// (>= net40-full) || (< net46) || (>= net20) can be simplified to (< net46) || (>= net20) because (>= net40-full) is a subset of (>= net20) + // NOTE: This optimization is kind of dangerous as future frameworks might make it invalid + // However a lot of tests expect this simplification... We maybe want to remove it (or at least test) after we know the new framework restriction works. + let removeSubsetLiteralsInOrClause (fr:FrameworkRestriction) = + let simpleOrLiterals = + fr.OrFormulas + |> List.choose (function { Literals = [h] } -> Some h | _ -> None) + { OrFormulas = + fr.OrFormulas + |> List.filter (function + | { Literals = [h] } -> + simpleOrLiterals + |> Seq.filter (fun l -> l <> h) + |> Seq.exists (fun otherLiteral -> + h.RawFormular.IsSubsetOf otherLiteral.RawFormular) + |> not + | _ -> true) } + + /// When we optmized a clause away completely we can replace the hole formula with "NoRestriction" + /// This happens for example with ( =net45) and the removeNegatedLiteralsWhichOccurSinglePositive + /// optimization + let replaceWithNoRestrictionIfAnyLiteralListIsEmpty (fr:FrameworkRestriction) = + let containsEmptyAnd = + fr.OrFormulas + |> Seq.exists (fun andFormular -> andFormular.Literals |> Seq.isEmpty) + if containsEmptyAnd then NoRestriction else fr + + fr + |> removeNegatedLiteralsWhichOccurSinglePositive + |> removeSubsetLiteralsInAndClause + |> removeSubsetLiteralsInOrClause + |> replaceWithNoRestrictionIfAnyLiteralListIsEmpty + + let rec private And2 (left : FrameworkRestriction) (right : FrameworkRestriction) = + match left.OrFormulas with + | [] -> right + | [h] -> + { OrFormulas = + right.OrFormulas + |> List.map (fun andFormula -> { Literals = andFormula.Literals @ h.Literals } ) } + | h :: t -> + { OrFormulas = (And2 {OrFormulas = [h]} right).OrFormulas @ ((And2 {OrFormulas = t} right).OrFormulas) } + + let And (rst:FrameworkRestriction list) = + List.fold And2 EmptySet rst + |> simplify + + let private Or2 (left : FrameworkRestriction) (right : FrameworkRestriction) = + { OrFormulas = left.OrFormulas @ right.OrFormulas } + + let Or (rst:FrameworkRestriction list) = + List.fold Or2 NoRestriction rst + |> simplify + + //[] + //let Not (rst:FrameworkRestriction) = + // Unchecked.defaultof<_> + + //let NotLiteral (lit : FrameworkRestrictionLiteral) = { lit with IsNegated = not lit.IsNegated } + + //let fromLiteral = { OrFormulas = [ { Literals = [lit] } ] } + + let Between (x, y) = + And2 (AtLeast x) (NotAtLeast y) + //FrameworkRestrictionP.AndP[FrameworkRestrictionP.AtLeastP x; FrameworkRestrictionP.NotP (FrameworkRestrictionP.AtLeastP y)] let combineRestrictionsWithOr (x : FrameworkRestriction) y = - if x.IsSubsetOf y then - y - elif y.IsSubsetOf x then - x - else - match x, y with - | FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general], other - | FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate], other - | other, FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general] - | other, FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate] when negate = other -> - // "negate && NOT general" might not be empty, ie general might not be a superset of negate - if other.IsSubsetOf general then general else FrameworkRestriction.OrP[general; other] - | _ -> - let combined = FrameworkRestriction.OrP[x; y] - if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then - FrameworkRestriction.NoRestriction - else - combined + Or2 x y + |> simplify + //if x.IsSubsetOf y then + // y + //elif y.IsSubsetOf x then + // x + //else + // match x, y with + // | FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general], other + // | FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate], other + // | other, FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general] + // | other, FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate] when negate = other -> + // // "negate && NOT general" might not be empty, ie general might not be a superset of negate + // if other.IsSubsetOf general then general else FrameworkRestriction.OrP[general; other] + // | _ -> + // let combined = FrameworkRestriction.OrP[x; y] + // if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then + // FrameworkRestriction.NoRestriction + // else + // combined let (|HasNoRestriction|_|) x = - if x = FrameworkRestriction.NoRestrictionP then Some () else None + if x = NoRestriction then Some () else None - let combineRestrictionsWithAnd (x : FrameworkRestriction) y = + let combineRestrictionsWithAnd (x : FrameworkRestriction) y = + And2 x y + |> simplify // combine means basically we say AND (both need to be satisfied) - if x.IsSubsetOf y then - x - elif y.IsSubsetOf x then - y - else - let combined = FrameworkRestriction.AndP[x; y] - if combined.RepresentedFrameworks |> Seq.isEmpty then - FrameworkRestriction.EmptySet - else combined + //if x.IsSubsetOf y then + // x + //elif y.IsSubsetOf x then + // y + //else + // let combined = FrameworkRestriction.AndP[x; y] + // if combined.RepresentedFrameworks |> Seq.isEmpty then + // FrameworkRestriction.EmptySet + // else combined //if x.IsSameCategoryAs(y) <> Some false then // combineSameCategoryOrPortableRestrictions x y //else @@ -143,6 +315,10 @@ module FrameworkRestriction = type FrameworkRestrictions = | ExplicitRestriction of FrameworkRestriction | AutoDetectFramework + override x.ToString() = + match x with + | ExplicitRestriction r -> r.ToString() + | AutoDetectFramework -> "AutoDetect" member x.GetExplicitRestriction () = match x with | ExplicitRestriction list -> list @@ -928,7 +1104,7 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = // but now net461 which supports netstandard13 is nowhere -> we need to decide here and add back the intersection let missing = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.AtLeast frameworkGroup) - let combined = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.Not (FrameworkRestriction.AtLeast frameworkGroup)) + let combined = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.NotAtLeast frameworkGroup) match packageGroup.Platforms, missing.RepresentedFrameworks with | [ packageGroupFw ], firstMissing :: _ -> // the common set goes to the better matching one diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index cd00cebf1f..9cfb4a0efb 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -105,7 +105,7 @@ let ``can detect explicit dependencies for Math.Numerics``() = LicenseUrl = "http://numerics.mathdotnet.com/docs/License.html" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion Dependencies = - [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))]] + [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), makeOrList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V3_5), DotNetFramework(FrameworkVersion.V4_Client))]] SourceUrl = fakeUrl } [] diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index bfbf0a2314..19623b2b7a 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -245,8 +245,10 @@ let ``can detect dependencies for MathNet.Numerics``() = [] let ``can detect dependencies for MathNet.Numerics.FSharp``() = //ensureDir() - Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"MathNet.Numerics.FSharp.nuspec")).Dependencies - |> Seq.head + let s = + Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"MathNet.Numerics.FSharp.nuspec")).Dependencies + |> Seq.head + s |> shouldEqual (PackageName "MathNet.Numerics", DependenciesFileParser.parseVersionRequirement("3.3.0"),makeOrList []) @@ -313,5 +315,5 @@ let ``can detect explicit dependencies for EasyNetQ``() = makeOrList [FrameworkRestriction.And[ FrameworkRestriction.NoRestriction - FrameworkRestriction.Not (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5)))] + FrameworkRestriction.NotAtLeast(DotNetFramework(FrameworkVersion.V4_5))] ]) \ No newline at end of file diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index a526c0454b..9a14b621e6 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -4,6 +4,52 @@ open Paket open FsUnit open NUnit.Framework open Paket.Requirements +[] +let ``PlatformMatching works with portable ``() = + // portable-net40-sl4 + let l = PlatformMatching.getPlatformsSupporting (KnownTargetProfiles.FindPortableProfile "Profile18") + // portable-net45-sl5 + let needPortable = KnownTargetProfiles.FindPortableProfile "Profile24" + + l + |> shouldContain needPortable + +[] +let ``Simplify && (&& (>= net40-full) (< net46) (>= net20)``() = + let toSimplify = + (FrameworkRestriction.And[ + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4) + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_6) + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V2)]) + toSimplify + |> shouldEqual (FrameworkRestriction.Between (DotNetFramework FrameworkVersion.V4, DotNetFramework FrameworkVersion.V4_6)) + +[] +let ``Simplify || (&& (< net40) (< net35)) (&& (< net40) (>= net35)) (>= net40))``() = + // Test simplify || (&& (< net40) (< net35)) (&& (< net40) (>= net35)) (>= net40)) + let smaller = + (FrameworkRestriction.And[ + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client) + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V3_5)]) + let between = + (FrameworkRestriction.And[ + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client) + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5)]) + let rest = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client) + + let combined = FrameworkRestriction.Or [ smaller ; between; rest ] + combined + |> shouldEqual FrameworkRestriction.NoRestriction + +[] +let ``Empty set should be empty``() = + FrameworkRestriction.EmptySet.RepresentedFrameworks + |> shouldEqual [] + +[] +let ``NoRestriction set should not be empty``() = + FrameworkRestriction.NoRestriction.RepresentedFrameworks + |> shouldNotEqual [] [] let ``combineOr can simplify the NoRestriction set``() = @@ -12,11 +58,11 @@ let ``combineOr can simplify the NoRestriction set``() = [FrameworkRestriction.And [ FrameworkRestriction.And [ FrameworkRestriction.NoRestriction - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5))] - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))] + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V3_5)] + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client)] FrameworkRestriction.And [FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5) - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client))]]) + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client)]]) let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client) FrameworkRestriction.combineRestrictionsWithOr left right |> shouldEqual FrameworkRestriction.NoRestriction @@ -26,10 +72,12 @@ let ``combineOr can simplify disjunct sets``() = let left = FrameworkRestriction.And[ FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1) - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_6_2))] + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_6_2)] let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_6_2) - // Logic says this is >= net451 but it is >= net451 || >= netstandard13 - FrameworkRestriction.combineRestrictionsWithOr left right + // we can simplify this expression to >=net451 because they are disjunct + let combined = FrameworkRestriction.combineRestrictionsWithOr left right + + combined |> shouldEqual (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1)) [] @@ -37,7 +85,7 @@ let ``combineOr needs to consider partly disjunct sets``() = let left = FrameworkRestriction.And[ FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5_1) - FrameworkRestriction.Not (FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3))] + FrameworkRestriction.NotAtLeast (DotNetStandard DotNetStandardVersion.V1_3)] let right = FrameworkRestriction.AtLeast (DotNetStandard DotNetStandardVersion.V1_3) // Logic says this is >= net451 but it is >= net451 || >= netstandard13 FrameworkRestriction.combineRestrictionsWithOr left right From 7f272251fe454cf3a79630501d9e0d43a8d8b522 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sun, 21 May 2017 18:11:18 +0200 Subject: [PATCH 09/47] refactor FrameworkIdentifier, remove V4_Client (if still needed we need to solve it for all version). Remove magic strings (not finished jet) --- .../ConvertFromNuGetSpecs.fs | 2 +- .../PaketConfigFiles/DependenciesFile.fs | 3 +- .../PaketConfigFiles/ProjectFile.fs | 4 +- .../Versioning/FrameworkHandling.fs | 638 +++++++++++------- src/Paket.Core/Versioning/PlatformMatching.fs | 246 +++---- src/Paket.Core/Versioning/Requirements.fs | 101 +-- .../DependenciesFile/ParserSpecs.fs | 6 +- .../InstallModel/FrameworkIdentifierSpecs.fs | 12 +- .../Penalty/FrameworkConditionsSpecs.fs | 4 +- .../InstallModel/Penalty/PenaltySpecs.fs | 50 +- .../InstallModel/ProcessingSpecs.fs | 56 +- .../InstallModel/Xml/LibGit2Sharp.fs | 2 +- tests/Paket.Tests/InstallModel/Xml/RxXaml.fs | 4 +- .../Lockfile/GenerateWithOptionsSpecs.fs | 4 +- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 12 +- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 4 +- tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 20 +- .../Paket.Tests/ProjectFile/ConditionSpecs.fs | 22 +- tests/Paket.Tests/ProjectFile/OutputSpecs.fs | 2 +- .../ProjectFile/TargetFrameworkSpecs.fs | 10 +- tests/Paket.Tests/TestHelpers.fs | 2 +- .../Versioning/DependencySetSpecs.fs | 14 +- .../Versioning/FrameworkCompatibilitySpecs.fs | 6 +- .../Versioning/FrameworkRestrictionTests.fs | 27 +- .../Versioning/RestrictionApplicationSpecs.fs | 35 +- .../Versioning/RestrictionFilterSpecs.fs | 4 +- 26 files changed, 728 insertions(+), 562 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs b/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs index b3f64b8459..d0f08a5f9b 100644 --- a/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/ConvertFromNuGetSpecs.fs @@ -50,7 +50,7 @@ let ``#1225 should convert simple C# project with non-matching framework restric requirement2.Name |> shouldEqual (PackageName "Newtonsoft.Json") requirement2.VersionRequirement.ToString() |> shouldEqual "7.0.1" requirement2.ResolverStrategyForTransitives |> shouldEqual None - requirement2.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) + requirement2.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) [] let ``#1217 should replace packages.config files in project``() = diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index e8443ce9ec..6430cac210 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -692,7 +692,8 @@ type DependenciesFile(fileName,groups:Map, textRepr |> Seq.map(fun restrictions -> match restrictions with | Paket.Requirements.AutoDetectFramework -> failwithf "couldn't detect framework" - | Paket.Requirements.ExplicitRestriction list -> list.RepresentedFrameworks + | Paket.Requirements.ExplicitRestriction list -> + list.RepresentedFrameworks |> Seq.choose (function SinglePlatform tf -> Some tf | _ -> None) //list |> Seq.collect (function //| Paket.Requirements.FrameworkRestriction.Exactly framework //| Paket.Requirements.FrameworkRestriction.AtLeast framework -> Seq.singleton framework diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs index 5ecd6f6db4..eda0bfe8f2 100644 --- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs @@ -974,8 +974,8 @@ module ProjectFile = let getTargetProfile (project:ProjectFile) = match getTargetFrameworkProfile project with - | Some profile when profile = "Client" -> - SinglePlatform (DotNetFramework FrameworkVersion.V4_Client) + //| Some profile when profile = "Client" -> + // SinglePlatform (DotNetFramework FrameworkVersion.V4_Client) | Some profile when String.IsNullOrWhiteSpace profile |> not -> KnownTargetProfiles.FindPortableProfile profile | _ -> diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index 452c0e6fe5..a94ea0b023 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -47,8 +47,8 @@ type FrameworkVersion = | V2 | V3 | V3_5 - | V4_Client | V4 + | V4_0_3 | V4_5 | V4_5_1 | V4_5_2 @@ -66,8 +66,8 @@ type FrameworkVersion = | V2 -> "v2.0" | V3 -> "v3.0" | V3_5 -> "v3.5" - | V4_Client -> "v4.0" | V4 -> "v4.0" + | V4_0_3 -> "v4.0.3" | V4_5 -> "v4.5" | V4_5_1 -> "v4.5.1" | V4_5_2 -> "v4.5.2" @@ -86,8 +86,8 @@ type FrameworkVersion = | FrameworkVersion.V2 -> "20" | FrameworkVersion.V3 -> "30" | FrameworkVersion.V3_5 -> "35" - | FrameworkVersion.V4_Client -> "40" - | FrameworkVersion.V4 -> "40-full" + | FrameworkVersion.V4 -> "40" + | FrameworkVersion.V4_0_3 -> "403" | FrameworkVersion.V4_5 -> "45" | FrameworkVersion.V4_5_1 -> "451" | FrameworkVersion.V4_5_2 -> "452" @@ -178,9 +178,9 @@ module KnownAliases = "winrt", "netcore" "netcoreapp", "netcore" "silverlight", "sl" + "windowsPhoneApp", "wpa" "windowsphone", "wp" "windows", "win" - "windowsPhoneApp", "wpa" ".netportable", "portable" "netportable", "portable" "10.0", "100" @@ -217,6 +217,70 @@ type Platform = | UnknownPlatform s -> s override x.ToString() = x.AsString +[] +type WindowsPhoneVersion = + | V7 + | V7_5 + | V8 + | V8_1 + member this.ShortString() = + match this with + | WindowsPhoneVersion.V7 -> "7" + | WindowsPhoneVersion.V7_5 -> "75" + | WindowsPhoneVersion.V8 -> "8" + | WindowsPhoneVersion.V8_1 -> "81" + override this.ToString() = + match this with + | WindowsPhoneVersion.V7 -> "v7.0" + | WindowsPhoneVersion.V7_5 -> "v7.5" + | WindowsPhoneVersion.V8 -> "v8.0" + | WindowsPhoneVersion.V8_1 -> "v8.1" + +[] +type WindowsPhoneAppVersion = + | V8 + | V8_1 + member this.ShortString() = + match this with + | WindowsPhoneAppVersion.V8 -> "8" + | WindowsPhoneAppVersion.V8_1 -> "81" + override this.ToString() = + match this with + | WindowsPhoneAppVersion.V8 -> "v8.0" + | WindowsPhoneAppVersion.V8_1 -> "v8.1" + +[] +type SilverlightVersion = + | V3 + | V4 + | V5 + member this.ShortString() = + match this with + | SilverlightVersion.V3 -> "3" + | SilverlightVersion.V4 -> "4" + | SilverlightVersion.V5 -> "5" + override this.ToString() = + match this with + | SilverlightVersion.V3 -> "v3.0" + | SilverlightVersion.V4 -> "v4.0" + | SilverlightVersion.V5 -> "v5.0" + +[] +type WindowsVersion = + | V8 + | V8_1 + | V10 + member this.ShortString() = + match this with + | WindowsVersion.V8 -> "8" + | WindowsVersion.V8_1 -> "81" + | WindowsVersion.V10 -> "10" + override this.ToString() = + match this with + | WindowsVersion.V8 -> "v8.0" + | WindowsVersion.V8_1 -> "v8.1" + | WindowsVersion.V10 -> "v10.0" + /// Framework Identifier type. // Each time a new version is added NuGetPackageCache.CurrentCacheVersion should be bumped. type FrameworkIdentifier = @@ -233,10 +297,10 @@ type FrameworkIdentifier = | Native of BuildMode * Platform | XamariniOS | XamarinMac - | Windows of string - | WindowsPhoneSilverlight of string - | WindowsPhoneApp of string - | Silverlight of string + | Windows of WindowsVersion + | WindowsPhone of WindowsPhoneVersion + | WindowsPhoneApp of WindowsPhoneAppVersion + | Silverlight of SilverlightVersion override x.ToString() = match x with @@ -253,14 +317,33 @@ type FrameworkIdentifier = | XamariniOS -> "xamarinios" | UAP v -> "uap" + v.ShortString() | XamarinMac -> "xamarinmac" - | Windows v -> "win" + v - | WindowsPhoneSilverlight v -> "wp" + v - | WindowsPhoneApp v -> "wpa" + v - | Silverlight v -> "sl" + v.Replace("v","").Replace(".","") + | Windows v -> "win" + v.ShortString() + | WindowsPhone v -> "wp" + v.ShortString() + | WindowsPhoneApp v -> "wpa" + v.ShortString() + | Silverlight v -> "sl" + v.ShortString() + + member internal x.RawSupportedPlatformsTransitive = + let findNewPlats (known:FrameworkIdentifier list) (lastStep:FrameworkIdentifier list) = + lastStep + |> List.collect (fun k -> k.RawSupportedPlatforms) + |> List.filter (fun k -> known |> Seq.contains k |> not) + + Seq.initInfinite (fun _ -> 1) + |> Seq.scan (fun state _ -> + match state with + | Some (known, lastStep) -> + match findNewPlats known lastStep with + | [] -> None + | items -> Some (known @ items, items) + | None -> None) (Some ([x], [x])) + |> Seq.takeWhile (fun i -> i.IsSome) + |> Seq.choose id + |> Seq.last + |> fst // returns a list of compatible platforms that this platform also supports - member x.SupportedPlatforms = + member internal x.RawSupportedPlatforms = match x with | MonoAndroid -> [ ] | MonoTouch -> [ ] @@ -274,9 +357,9 @@ type FrameworkIdentifier = | DotNetFramework FrameworkVersion.V2 -> [ DotNetFramework FrameworkVersion.V1_1 ] | DotNetFramework FrameworkVersion.V3 -> [ DotNetFramework FrameworkVersion.V2 ] | DotNetFramework FrameworkVersion.V3_5 -> [ DotNetFramework FrameworkVersion.V3 ] - | DotNetFramework FrameworkVersion.V4_Client -> [ DotNetFramework FrameworkVersion.V3_5 ] - | DotNetFramework FrameworkVersion.V4 -> [ DotNetFramework FrameworkVersion.V4_Client ] - | DotNetFramework FrameworkVersion.V4_5 -> [ DotNetFramework FrameworkVersion.V4; DotNetStandard DotNetStandardVersion.V1_1 ] + | DotNetFramework FrameworkVersion.V4 -> [ DotNetFramework FrameworkVersion.V3_5 ] + | DotNetFramework FrameworkVersion.V4_0_3 -> [ DotNetFramework FrameworkVersion.V4 ] + | DotNetFramework FrameworkVersion.V4_5 -> [ DotNetFramework FrameworkVersion.V4_0_3; DotNetStandard DotNetStandardVersion.V1_1 ] | DotNetFramework FrameworkVersion.V4_5_1 -> [ DotNetFramework FrameworkVersion.V4_5; DotNetStandard DotNetStandardVersion.V1_2 ] | DotNetFramework FrameworkVersion.V4_5_2 -> [ DotNetFramework FrameworkVersion.V4_5_1; DotNetStandard DotNetStandardVersion.V1_2 ] | DotNetFramework FrameworkVersion.V4_5_3 -> [ DotNetFramework FrameworkVersion.V4_5_2; DotNetStandard DotNetStandardVersion.V1_2 ] @@ -303,96 +386,24 @@ type FrameworkIdentifier = | DotNetUnity DotNetUnityVersion.V3_5_Subset -> [ ] | DotNetUnity DotNetUnityVersion.V3_5_Micro -> [ ] | DotNetUnity DotNetUnityVersion.V3_5_Web -> [ ] - | Silverlight "v3.0" -> [ ] - | Silverlight "v4.0" -> [ Silverlight "v3.0" ] - | Silverlight "v5.0" -> [ Silverlight "v4.0" ] - | Windows "v4.5" -> [ ] - | Windows "v4.5.1" -> [ Windows "v4.5" ] - | WindowsPhoneApp "v8.1" -> [ DotNetStandard DotNetStandardVersion.V1_2 ] - | WindowsPhoneSilverlight "v7.0" -> [ ] - | WindowsPhoneSilverlight "v7.1" -> [ WindowsPhoneSilverlight "v7.0" ] - | WindowsPhoneSilverlight "v8.0" -> [ WindowsPhoneSilverlight "v7.1"; DotNetStandard DotNetStandardVersion.V1_0 ] - | WindowsPhoneSilverlight "v8.1" -> [ WindowsPhoneSilverlight "v8.0"; DotNetStandard DotNetStandardVersion.V1_0 ] + | Silverlight SilverlightVersion.V3 -> [ ] + | Silverlight SilverlightVersion.V4 -> [ Silverlight SilverlightVersion.V3 ] + | Silverlight SilverlightVersion.V5 -> [ Silverlight SilverlightVersion.V4 ] + | Windows WindowsVersion.V8 -> [ ] + | Windows WindowsVersion.V8_1 -> [ Windows WindowsVersion.V8 ] + | Windows WindowsVersion.V10 -> [ Windows WindowsVersion.V8_1 ] + | WindowsPhoneApp WindowsPhoneAppVersion.V8 -> [ ] + | WindowsPhoneApp WindowsPhoneAppVersion.V8_1 -> [ DotNetStandard DotNetStandardVersion.V1_2 ] + | WindowsPhone WindowsPhoneVersion.V7 -> [ ] + | WindowsPhone WindowsPhoneVersion.V7_5 -> [ WindowsPhone WindowsPhoneVersion.V7 ] + | WindowsPhone WindowsPhoneVersion.V8 -> [ WindowsPhone WindowsPhoneVersion.V7_5; DotNetStandard DotNetStandardVersion.V1_0 ] + | WindowsPhone WindowsPhoneVersion.V8_1 -> [ WindowsPhone WindowsPhoneVersion.V8 ] // wildcards for future versions. new versions should be added above, though, so the penalty will be calculated correctly. - | Silverlight _ -> [ Silverlight "v5.0" ] - | Windows _ -> [ Windows "v4.5.1" ] - | WindowsPhoneApp _ -> [ WindowsPhoneApp "v8.1" ] - | WindowsPhoneSilverlight _ -> [ WindowsPhoneSilverlight "v8.1" ] - /// Return if the parameter is of the same framework category (dotnet, windows phone, silverlight, ...) - member x.IsSameCategoryAs y = - match (x, y) with - | UAP _, UAP _ -> true - | DotNetFramework _, DotNetFramework _ -> true - | DotNetStandard _, DotNetStandard _ -> true - | DotNetCore _, DotNetCore _ -> true - | DotNetUnity _, DotNetUnity _ -> true - | Silverlight _, Silverlight _ -> true - | DNX _, DNX _ -> true - | DNXCore _, DNXCore _ -> true - | MonoAndroid _, MonoAndroid _ -> true - | MonoMac _, MonoMac _ -> true - | MonoTouch _, MonoTouch _ -> true - | Windows _, Windows _ -> true - | WindowsPhoneApp _, WindowsPhoneApp _ -> true - | WindowsPhoneSilverlight _, WindowsPhoneSilverlight _ -> true - | XamarinMac _, XamarinMac _ -> true - | XamariniOS _, XamariniOS _ -> true - | Native _, Native _ -> true - | _ -> false - - // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list - /// true when x is supported by y, for example netstandard15 is supported by netcore10 - member x.IsSupportedBy y = - x = y || - (y.SupportedPlatforms |> Seq.exists (fun s -> x.IsSupportedBy s)) - //x = y || - // (x.SupportedPlatforms |> Seq.exists (fun x' -> x' = y && not (x'.IsSameCategoryAs x))) || - // (y.SupportedPlatforms |> Seq.exists (fun y' -> y' = x && not (y'.IsSameCategoryAs y))) - - /// true when x is at least (>=) y ie when y is supported by x, for example netcore10 >= netstandard15 as netstandard15 is supported by netcore10. - /// Note that this relation is not complete, for example for WindowsPhoneSilverlightv7.0 and Windowsv4.5 both <= and >= are false from this definition as - /// no platform supports the other. - member x.IsAtLeast (y:FrameworkIdentifier) = - y.IsSupportedBy x - //if x.IsSameCategoryAs y then - // x >= y - //else - // let isCompatible() = - // y.SupportedPlatforms - // |> Seq.exists x.IsAtLeast - // - // match x,y with - // | DotNetStandard _, DotNetFramework _ -> isCompatible() - // | DotNetFramework _, DotNetStandard _ -> isCompatible() - // | _ -> false - - /// Get all platforms y for which x >= y holds - member x.SupportedPlatformsTransitive = - let findNewPlats (known:FrameworkIdentifier list) (lastStep:FrameworkIdentifier list) = - lastStep - |> List.collect (fun k -> k.SupportedPlatforms) - |> List.filter (fun k -> known |> Seq.contains k |> not) - - Seq.initInfinite (fun _ -> 1) - |> Seq.scan (fun state _ -> - match state with - | Some (known, lastStep) -> - match findNewPlats known lastStep with - | [] -> None - | items -> Some (known @ items, items) - | None -> None) (Some ([x], [x])) - |> Seq.takeWhile (fun i -> i.IsSome) - |> Seq.choose id - |> Seq.last - |> fst - - /// x < y, see y >= x && x <> y - member x.IsSmallerThan y = - x.IsSupportedBy y && x <> y - - /// Note that this returns true only when a >= x and x < b holds. - member x.IsBetween(a,b) = x.IsAtLeast a && x.IsSmallerThan b + //| Silverlight _ -> [ Silverlight "v5.0" ] + //| Windows _ -> [ Windows "v4.5.1" ] + //| WindowsPhoneApp _ -> [ WindowsPhoneApp "v8.1" ] + //| WindowsPhoneSilverlight _ -> [ WindowsPhoneSilverlight "v8.1" ] module FrameworkDetection = @@ -426,6 +437,7 @@ module FrameworkDetection = sb.ToString() // Each time the parsing is changed, NuGetPackageCache.CurrentCacheVersion should be bumped. + // http://nugettoolsdev.azurewebsites.net/4.0.0/parse-framework?framework=.NETPortable%2CVersion%3Dv0.0%2CProfile%3DProfile2 let result = match path with | "net35-Unity Web v3.5" -> Some (DotNetUnity DotNetUnityVersion.V3_5_Web) @@ -437,8 +449,8 @@ module FrameworkDetection = | "net20" | "net2" | "net" | "net20-full" | "net20-client" | "20" -> Some (DotNetFramework FrameworkVersion.V2) | "net30" | "net3" | "30" -> Some (DotNetFramework FrameworkVersion.V3) | "net35" | "net35-client" | "net35-full" | "35" -> Some (DotNetFramework FrameworkVersion.V3_5) - | "net40" | "net4" | "40" | "net40-client" | "net4-client" -> Some (DotNetFramework FrameworkVersion.V4_Client) - | "net40-full" | "net403" -> Some (DotNetFramework FrameworkVersion.V4) + | "net40-full" | "net40" | "net4" | "40" | "net40-client" | "net4-client" -> Some (DotNetFramework FrameworkVersion.V4) + | "net403"| "net403-full"| "net403-client" -> Some (DotNetFramework FrameworkVersion.V4_0_3) | "net45" | "net45-full" | "45" -> Some (DotNetFramework FrameworkVersion.V4_5) | "net451" -> Some (DotNetFramework FrameworkVersion.V4_5_1) | "net452" -> Some (DotNetFramework FrameworkVersion.V4_5_2) @@ -463,16 +475,17 @@ module FrameworkDetection = | "native/address-model-32" -> Some(Native(NoBuildMode,Win32)) | "native/address-model-64" -> Some(Native(NoBuildMode,X64)) | "native" -> Some(Native(NoBuildMode,NoPlatform)) - | "sl" | "sl3" | "sl30" -> Some (Silverlight "v3.0") - | "sl4" | "sl40" -> Some (Silverlight "v4.0") - | "sl5" | "sl50" -> Some (Silverlight "v5.0") - | "win8" | "windows8" | "win80" | "netcore45" | "win" | "winv45" -> Some (Windows "v4.5") - | "win81" | "windows81" | "netcore46" | "netcore451" | "winv451" -> Some (Windows "v4.5.1") - | "wp7" | "wp70" | "wpv7" | "wpv70" | "sl4-wp7"| "sl4-wp70" -> Some (WindowsPhoneSilverlight "v7.0") - | "wp71" | "wpv71" | "sl4-wp71" | "sl4-wp" -> Some (WindowsPhoneSilverlight "v7.1") - | "wpa00" | "wpa" | "wpa81" | "wpav81" | "wpapp81" | "wpapp" -> Some (WindowsPhoneApp "v8.1") - | "wp8" | "wp80" | "wpv80" -> Some (WindowsPhoneSilverlight "v8.0") - | "wp81" | "wpv81" -> Some (WindowsPhoneSilverlight "v8.1") + | "sl" | "sl3" | "sl30" -> Some (Silverlight SilverlightVersion.V3) + | "sl4" | "sl40" -> Some (Silverlight SilverlightVersion.V4) + | "sl5" | "sl50" -> Some (Silverlight SilverlightVersion.V5) + | "win8" | "windows8" | "win80" | "netcore45" | "win" | "winv45" -> Some (Windows WindowsVersion.V8) + | "win81" | "windows81" | "netcore46" | "netcore451" | "winv451" -> Some (Windows WindowsVersion.V8_1) + | "wp7" | "wp70" | "wpv7" | "wpv70" | "sl4-wp7"| "sl4-wp70" -> Some (WindowsPhone WindowsPhoneVersion.V7) + //| "wp71" | "wpv71" | "sl4-wp71" | "sl4-wp" -> Some (WindowsPhone WindowsPhoneVersion.V7_5) + | "wp75" | "wpv75" | "sl4-wp75" | "sl4-wp" -> Some (WindowsPhone WindowsPhoneVersion.V7_5) + | "wp8" | "wp80" | "wpv80" -> Some (WindowsPhone WindowsPhoneVersion.V8) + | "wpa00" | "wpa" | "wpa81" | "wpav81" | "wpapp81" | "wpapp" -> Some (WindowsPhoneApp WindowsPhoneAppVersion.V8_1) + | "wp81" | "wpv81" -> Some (WindowsPhone WindowsPhoneVersion.V8_1) | "dnx451" -> Some(DNX FrameworkVersion.V4_5_1) | "dnxcore50" | "netplatform50" | "netcore50" | "aspnetcore50" | "aspnet50" | "dotnet" -> Some(DNXCore FrameworkVersion.V5_0) | v when v.StartsWith "dotnet" -> Some(DNXCore FrameworkVersion.V5_0) @@ -506,87 +519,47 @@ module FrameworkDetection = type TargetProfile = | SinglePlatform of FrameworkIdentifier | PortableProfile of string * FrameworkIdentifier list - member this.FrameworkIdentifiers = - match this with - | SinglePlatform p -> [p] - | PortableProfile (_, pfs) -> pfs - member this.ProfilesCompatibleWithPortableProfile = - match this with - | SinglePlatform _ -> [ ] - | PortableProfile(name,required) -> - let netstandard = - // See https://github.com/dotnet/corefx/blob/master/Documentation/architecture/net-platform-standard.md#portable-profiles - match name with - | "Profile7" -> [ DotNetStandard DotNetStandardVersion.V1_1 ] - | "Profile31" -> [ DotNetStandard DotNetStandardVersion.V1_0 ] - | "Profile32" -> [ DotNetStandard DotNetStandardVersion.V1_2 ] - | "Profile44" -> [ DotNetStandard DotNetStandardVersion.V1_2 ] - | "Profile49" -> [ DotNetStandard DotNetStandardVersion.V1_0 ] - | "Profile78" -> [ DotNetStandard DotNetStandardVersion.V1_0 ] - | "Profile84" -> [ DotNetStandard DotNetStandardVersion.V1_0 ] - | "Profile111" -> [ DotNetStandard DotNetStandardVersion.V1_1 ] - | "Profile151" -> [ DotNetStandard DotNetStandardVersion.V1_2 ] - | "Profile157" -> [ DotNetStandard DotNetStandardVersion.V1_0 ] - | "Profile259" -> [ DotNetStandard DotNetStandardVersion.V1_0 ] - | _ -> [ ] - required - |> List.map (function - | DotNetFramework FrameworkVersion.V4_5 - | DotNetFramework FrameworkVersion.V4_5_1 - | DotNetFramework FrameworkVersion.V4_5_2 - | DotNetFramework FrameworkVersion.V4_5_3 - | DotNetFramework FrameworkVersion.V4_6 - | DotNetFramework FrameworkVersion.V4_6_1 - | DotNetFramework FrameworkVersion.V4_6_2 - | DotNetFramework FrameworkVersion.V4_6_3 -> - [ - MonoTouch - MonoAndroid - XamariniOS - XamarinMac - ] - | _ -> [ ] - ) - |> List.reduce (@) - |> (@) netstandard - |> List.distinct - override this.ToString() = match this with | SinglePlatform x -> x.ToString() - | PortableProfile(name,_) -> - match name with - | "Profile5" -> "portable-net4+netcore45+MonoAndroid1+MonoTouch1" - | "Profile6" -> "portable-net403+netcore45+MonoAndroid1+MonoTouch1" - | "Profile7" -> "portable-net45+netcore45+MonoAndroid1+MonoTouch1" - | "Profile14" -> "portable-net4+sl5+MonoAndroid1+MonoTouch1" - | "Profile19" -> "portable-net403+sl5+MonoAndroid1+MonoTouch1" - | "Profile24" -> "portable-net45+sl5+MonoAndroid1+MonoTouch1" - | "Profile31" -> "portable-netcore451+wp81" - | "Profile32" -> "portable-netcore451+wpa81" - | "Profile37" -> "portable-net4+sl5+netcore45+MonoAndroid1+MonoTouch1" - | "Profile42" -> "portable-net403+sl5+netcore45+MonoAndroid1+MonoTouch1" - | "Profile44" -> "portable-net451+netcore451" - | "Profile47" -> "portable-net45+sl5+netcore45+MonoAndroid1+MonoTouch1" - | "Profile49" -> "portable-net45+wp8+MonoAndroid1+MonoTouch1" - | "Profile78" -> "portable-net45+netcore45+wp8+MonoAndroid1+MonoTouch1" - | "Profile84" -> "portable-wpa81+wp81" - | "Profile92" -> "portable-net4+netcore45+wpa81+MonoAndroid1+MonoTouch1" - | "Profile102" -> "portable-net403+netcore45+wpa81+MonoAndroid1+MonoTouch1" - | "Profile111" -> "portable-net45+netcore45+wpa81+MonoAndroid1+MonoTouch1" - | "Profile136" -> "portable-net4+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" - | "Profile147" -> "portable-net403+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" - | "Profile151" -> "portable-net451+netcore451+wpa81" - | "Profile157" -> "portable-netcore451+wpa81+wp81" - | "Profile158" -> "portable-net45+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" - | "Profile225" -> "portable-net4+sl5+netcore45+wpa81+MonoAndroid1+MonoTouch1" - | "Profile240" -> "portable-net403+sl5+netcore45+wpa81" - | "Profile255" -> "portable-net45+sl5+netcore45+wpa81+MonoAndroid1+MonoTouch1" - | "Profile259" -> "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - | "Profile328" -> "portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - | "Profile336" -> "portable-net403+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - | "Profile344" -> "portable-net45+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - | _ -> "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" // Use Portable259 as default + | PortableProfile(name,fws) -> + "portable-" + + String.Join ("+", + fws + |> List.sort + |> List.map (fun fw -> fw.ToString())) + //match name with + //| "Profile5" -> "portable-net4+netcore45+MonoAndroid1+MonoTouch1" + //| "Profile6" -> "portable-net403+netcore45+MonoAndroid1+MonoTouch1" + //| "Profile7" -> "portable-net45+netcore45+MonoAndroid1+MonoTouch1" + //| "Profile14" -> "portable-net4+sl5+MonoAndroid1+MonoTouch1" + //| "Profile19" -> "portable-net403+sl5+MonoAndroid1+MonoTouch1" + //| "Profile24" -> "portable-net45+sl5+MonoAndroid1+MonoTouch1" + //| "Profile31" -> "portable-netcore451+wp81" + //| "Profile32" -> "portable-netcore451+wpa81" + //| "Profile37" -> "portable-net4+sl5+netcore45+MonoAndroid1+MonoTouch1" + //| "Profile42" -> "portable-net403+sl5+netcore45+MonoAndroid1+MonoTouch1" + //| "Profile44" -> "portable-net451+netcore451" + //| "Profile47" -> "portable-net45+sl5+netcore45+MonoAndroid1+MonoTouch1" + //| "Profile49" -> "portable-net45+wp8+MonoAndroid1+MonoTouch1" + //| "Profile78" -> "portable-net45+netcore45+wp8+MonoAndroid1+MonoTouch1" + //| "Profile84" -> "portable-wpa81+wp81" + //| "Profile92" -> "portable-net4+netcore45+wpa81+MonoAndroid1+MonoTouch1" + //| "Profile102" -> "portable-net403+netcore45+wpa81+MonoAndroid1+MonoTouch1" + //| "Profile111" -> "portable-net45+netcore45+wpa81+MonoAndroid1+MonoTouch1" + //| "Profile136" -> "portable-net4+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" + //| "Profile147" -> "portable-net403+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" + //| "Profile151" -> "portable-net451+netcore451+wpa81" + //| "Profile157" -> "portable-netcore451+wpa81+wp81" + //| "Profile158" -> "portable-net45+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" + //| "Profile225" -> "portable-net4+sl5+netcore45+wpa81+MonoAndroid1+MonoTouch1" + //| "Profile240" -> "portable-net403+sl5+netcore45+wpa81" + //| "Profile255" -> "portable-net45+sl5+netcore45+wpa81+MonoAndroid1+MonoTouch1" + //| "Profile259" -> "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" + //| "Profile328" -> "portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" + //| "Profile336" -> "portable-net403+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" + //| "Profile344" -> "portable-net45+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" + //| _ -> "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" // Use Portable259 as default module KnownTargetProfiles = let DotNetFrameworkVersions = [ @@ -595,8 +568,8 @@ module KnownTargetProfiles = FrameworkVersion.V2 FrameworkVersion.V3 FrameworkVersion.V3_5 - FrameworkVersion.V4_Client FrameworkVersion.V4 + FrameworkVersion.V4_0_3 FrameworkVersion.V4_5 FrameworkVersion.V4_5_1 FrameworkVersion.V4_5_2 @@ -649,27 +622,43 @@ module KnownTargetProfiles = DotNetCoreVersions |> List.map (DotNetCore >> SinglePlatform) + let WindowsVersions = [ + WindowsVersion.V8 + WindowsVersion.V8_1 + WindowsVersion.V10 + ] + let WindowsProfiles = - [SinglePlatform(Windows "v4.5") - SinglePlatform(Windows "v4.5.1")] + WindowsVersions + |> List.map (Windows >> SinglePlatform) let DotNetUnityProfiles = DotNetUnityVersions |> List.map (DotNetUnity >> SinglePlatform) + + let SilverlightVersions = [ + SilverlightVersion.V3 + SilverlightVersion.V4 + SilverlightVersion.V5 + ] let SilverlightProfiles = - [SinglePlatform(Silverlight "v3.0") - SinglePlatform(Silverlight "v4.0") - SinglePlatform(Silverlight "v5.0")] + SilverlightVersions + |> List.map (Silverlight >> SinglePlatform) let UAPProfiles = [SinglePlatform(UAP UAPVersion.V10)] + let WindowsPhoneVersions = [ + WindowsPhoneVersion.V7 + WindowsPhoneVersion.V7_5 + WindowsPhoneVersion.V8 + WindowsPhoneVersion.V8_1 + ] + let WindowsPhoneSilverlightProfiles = - [SinglePlatform(WindowsPhoneSilverlight "v7.0") - SinglePlatform(WindowsPhoneSilverlight "v7.1") - SinglePlatform(WindowsPhoneSilverlight "v8.0") - SinglePlatform(WindowsPhoneSilverlight "v8.1")] + WindowsPhoneVersions + |> List.map (WindowsPhone >> SinglePlatform) let portableStandards p = match p with @@ -686,51 +675,52 @@ module KnownTargetProfiles = | "portable-net45+win8+wpa81+wp8" -> [DotNetStandardVersion.V1_0] | _ -> [] + // http://nugettoolsdev.azurewebsites.net/4.0.0/parse-framework?framework=.NETPortable%2CVersion%3Dv0.0%2CProfile%3DProfile3 let AllPortableProfiles = - [("Profile2", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v7.0" ]) - ("Profile3", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0" ]) - ("Profile4", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v7.0" ]) - ("Profile5", [ DotNetFramework FrameworkVersion.V4; Windows "v4.5" ]) - ("Profile6", [ DotNetFramework FrameworkVersion.V4; Windows "v4.5" ]) - ("Profile7" , [ DotNetFramework FrameworkVersion.V4_5; Windows "v4.5" ]) - ("Profile14", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0" ]) - ("Profile18", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0" ]) - ("Profile19", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0" ]) - ("Profile23", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v4.0" ]) - ("Profile24", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v5.0" ]) - ("Profile31", [ Windows "v4.5.1"; WindowsPhoneSilverlight "v8.1" ]) - ("Profile32", [ Windows "v4.5.1"; WindowsPhoneApp "v8.1" ]) - ("Profile36", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v8.0" ]) - ("Profile37", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; Windows "v4.5" ]) - ("Profile41", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0"; Windows "v4.5" ]) - ("Profile42", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; Windows "v4.5" ]) - ("Profile44", [ DotNetFramework FrameworkVersion.V4_5_1; Windows "v4.5.1" ]) - ("Profile46", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v4.0"; Windows "v4.5" ]) - ("Profile47", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v5.0"; Windows "v4.5" ]) - ("Profile49", [ DotNetFramework FrameworkVersion.V4_5; WindowsPhoneSilverlight "v8.0" ]) - ("Profile78", [ DotNetFramework FrameworkVersion.V4_5; Windows "v4.5"; WindowsPhoneSilverlight "v8.0" ]) - ("Profile84", [ WindowsPhoneApp "v8.1"; WindowsPhoneSilverlight "v8.1" ]) - ("Profile88", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v7.1" ]) - ("Profile92", [ DotNetFramework FrameworkVersion.V4; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile95", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v7.0" ]) - ("Profile96", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v7.1" ]) - ("Profile102", [ DotNetFramework FrameworkVersion.V4; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile104", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v7.1" ]) - ("Profile111", [ DotNetFramework FrameworkVersion.V4_5; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile136", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; WindowsPhoneSilverlight "v8.0"; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile143", [ DotNetFramework FrameworkVersion.V4; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v8.0" ]) - ("Profile147", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; Windows "v4.5"; WindowsPhoneSilverlight "v8.0" ]) - ("Profile151", [ DotNetFramework FrameworkVersion.V4_5_1; Windows "v4.5.1"; WindowsPhoneApp "v8.1" ]) - ("Profile154", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v4.0"; Windows "v4.5"; WindowsPhoneSilverlight "v8.0" ]) - ("Profile157", [ Windows "v4.5.1"; WindowsPhoneApp "v8.1"; WindowsPhoneSilverlight "v8.1" ]) - ("Profile158", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v5.0"; Windows "v4.5"; WindowsPhoneSilverlight "v8.0" ]) - ("Profile225", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile240", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile255", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v5.0"; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile259", [ DotNetFramework FrameworkVersion.V4_5; Windows "v4.5"; WindowsPhoneSilverlight "v8.0"; WindowsPhoneApp "v8.1" ]) - ("Profile328", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; WindowsPhoneSilverlight "v8.0"; Windows "v4.5"; WindowsPhoneApp "v8.1" ]) - ("Profile336", [ DotNetFramework FrameworkVersion.V4; Silverlight "v5.0"; Windows "v4.5"; WindowsPhoneApp "v8.1"; WindowsPhoneSilverlight "v8.0" ]) - ("Profile344", [ DotNetFramework FrameworkVersion.V4_5; Silverlight "v5.0"; Windows "v4.5"; WindowsPhoneApp "v8.1"; WindowsPhoneSilverlight "v8.0" ]) ] + [("Profile2", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ]) + ("Profile3", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4 ]) + ("Profile4", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ]) + ("Profile5", [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8 ]) + ("Profile6", [ DotNetFramework FrameworkVersion.V4_0_3; Windows WindowsVersion.V8 ]) + ("Profile7" , [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8 ]) + ("Profile14", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5 ]) + ("Profile18", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4 ]) + ("Profile19", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5 ]) + ("Profile23", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4 ]) + ("Profile24", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5 ]) + ("Profile31", [ Windows WindowsVersion.V8_1; WindowsPhone WindowsPhoneVersion.V8_1 ]) + ("Profile32", [ Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile36", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile37", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ]) + ("Profile41", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8 ]) + ("Profile42", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ]) + ("Profile44", [ DotNetFramework FrameworkVersion.V4_5_1; Windows WindowsVersion.V8_1 ]) + ("Profile46", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8 ]) + ("Profile47", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ]) + ("Profile49", [ DotNetFramework FrameworkVersion.V4_5; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile78", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile84", [ WindowsPhone WindowsPhoneVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile88", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ]) + ("Profile92", [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile95", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ]) + ("Profile96", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ]) + ("Profile102", [ DotNetFramework FrameworkVersion.V4_0_3; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile104", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ]) + ("Profile111", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile136", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile143", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile147", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile151", [ DotNetFramework FrameworkVersion.V4_5_1; Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile154", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile157", [ Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1; WindowsPhone WindowsPhoneVersion.V8_1 ]) + ("Profile158", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) + ("Profile225", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile240", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile255", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile259", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile328", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile336", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) + ("Profile344", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) ] let AllDotNetProfiles = DotNetFrameworkProfiles @ @@ -743,7 +733,7 @@ module KnownTargetProfiles = SinglePlatform(MonoTouch) SinglePlatform(XamariniOS) SinglePlatform(XamarinMac) - SinglePlatform(WindowsPhoneApp "v8.1")] @ + SinglePlatform(WindowsPhoneApp WindowsPhoneAppVersion.V8_1)] @ (AllPortableProfiles |> List.map PortableProfile) let AllDotNetStandardAndCoreProfiles = @@ -778,3 +768,151 @@ module KnownTargetProfiles = |> List.pick (function | PortableProfile(n, _) as p when n = name -> Some p | _ -> None) + + +type TargetProfile with + // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list + /// true when x is supported by y, for example netstandard15 is supported by netcore10 + member x.IsSupportedBy y = + x = y || + (y.SupportedPlatforms |> Seq.exists (fun s -> x.IsSupportedBy s)) + //x = y || + // (x.SupportedPlatforms |> Seq.exists (fun x' -> x' = y && not (x'.IsSameCategoryAs x))) || + // (y.SupportedPlatforms |> Seq.exists (fun y' -> y' = x && not (y'.IsSameCategoryAs y))) + + /// true when x is at least (>=) y ie when y is supported by x, for example netcore10 >= netstandard15 as netstandard15 is supported by netcore10. + /// Note that this relation is not complete, for example for WindowsPhoneSilverlightv7.0 and Windowsv4.5 both <= and >= are false from this definition as + /// no platform supports the other. + member x.IsAtLeast (y:TargetProfile) = + y.IsSupportedBy x + //if x.IsSameCategoryAs y then + // x >= y + //else + // let isCompatible() = + // y.SupportedPlatforms + // |> Seq.exists x.IsAtLeast + // + // match x,y with + // | DotNetStandard _, DotNetFramework _ -> isCompatible() + // | DotNetFramework _, DotNetStandard _ -> isCompatible() + // | _ -> false + + /// Get all platforms y for which x >= y holds + member x.SupportedPlatformsTransitive = + let findNewPlats (known:TargetProfile list) (lastStep:TargetProfile list) = + lastStep + |> List.collect (fun k -> k.SupportedPlatforms) + |> List.filter (fun k -> known |> Seq.contains k |> not) + + Seq.initInfinite (fun _ -> 1) + |> Seq.scan (fun state _ -> + match state with + | Some (known, lastStep) -> + match findNewPlats known lastStep with + | [] -> None + | items -> Some (known @ items, items) + | None -> None) (Some ([x], [x])) + |> Seq.takeWhile (fun i -> i.IsSome) + |> Seq.choose id + |> Seq.last + |> fst + + /// x < y, see y >= x && x <> y + member x.IsSmallerThan y = + x.IsSupportedBy y && x <> y + + /// Note that this returns true only when a >= x and x < b holds. + member x.IsBetween(a,b) = x.IsAtLeast a && x.IsSmallerThan b + member x.SupportedPlatforms = + match x with + | SinglePlatform tf -> + let rawSupported = + tf.RawSupportedPlatforms + |> List.map SinglePlatform + let profilesSupported = + // See https://docs.microsoft.com/en-us/dotnet/articles/standard/library + match tf with + | DotNetStandard DotNetStandardVersion.V1_0 -> + [ "Profile31" + "Profile49" + "Profile78" + "Profile84" + "Profile157" + "Profile259" ] + | DotNetStandard DotNetStandardVersion.V1_1 -> + [ "Profile7" + "Profile111" ] + | DotNetStandard DotNetStandardVersion.V1_2 -> + [ "Profile32" + "Profile44" + "Profile151" ] + | MonoTouch + | MonoAndroid + | XamariniOS + | XamarinMac -> + // http://danrigby.com/2014/05/14/supported-pcl-profiles-xamarin-for-visual-studio-2/ + [ "Profile5" + "Profile6" + "Profile7" + "Profile14" + "Profile19" + "Profile24" + "Profile37" + "Profile42" + "Profile44" + "Profile47" + "Profile49" + "Profile78" + "Profile92" + "Profile102" + "Profile111" + "Profile136" + "Profile147" + "Profile151" + "Profile158" + "Profile225" + "Profile259" + "Profile328" + "Profile336" + "Profile344" ] + | _ -> + // Regular supported logic is to enumerate all profiles and select compatible ones + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun (_, fws) -> + // Portable profile is compatible as soon as it contains a fw which supports us + fws + |> List.exists (fun fw -> fw.RawSupportedPlatformsTransitive |> Seq.exists ((=) tf))) + |> List.map fst + |> List.map KnownTargetProfiles.FindPortableProfile + rawSupported @ profilesSupported + | PortableProfile (name, tfs) -> + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun (otherName, _) -> otherName <> name) + |> List.filter (fun (otherName, fws) -> + let weSupport = + tfs + |> List.collect (fun tf -> tf.RawSupportedPlatformsTransitive) + |> List.distinct + let otherSupport = + fws + |> List.collect (fun fw -> fw.RawSupportedPlatformsTransitive) + |> List.distinct + // Portable profile is compatible when it supports less frameworks. + let isSupported = + otherSupport + |> Seq.forall (fun fw -> weSupport |> List.exists ((=) fw)) + let isReverseSupported = + weSupport + |> Seq.forall (fun fw -> otherSupport |> List.exists ((=) fw)) + let isSupportedI = (PortableProfile (otherName ,fws)).ToString() < x.ToString() + let result = + if isSupported && isReverseSupported then + // Some profiles are identical, which means we need to watch out to get a nice tree here + isSupportedI + else + isSupported + //if result then System.Diagnostics.Debug.WriteLine( + // sprintf "reverse %s < %s, result: %O" otherName name result) + result + ) + |> List.map PortableProfile diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index f1dd3e5d01..a096991445 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -17,57 +17,69 @@ let inline split (path : string) = let extractPlatforms = memoize (fun path -> { Name = path; Platforms = split path |> Array.choose FrameworkDetection.Extract |> Array.toList }) -let knownInPortable = - KnownTargetProfiles.AllPortableProfiles - |> List.collect snd - |> List.distinct +//let knownInPortable = +// KnownTargetProfiles.AllPortableProfiles +// |> List.collect snd +// |> List.distinct -let tryGetProfile platforms = - let filtered = - platforms.Platforms - |> List.filter (fun p -> knownInPortable |> Seq.exists ((=) p)) - |> List.sort +//let tryGetProfile platforms = +// let filtered = +// platforms.Platforms +// |> List.filter (fun p -> knownInPortable |> Seq.exists ((=) p)) +// |> List.sort - KnownTargetProfiles.AllPortableProfiles |> Seq.tryFind (snd >> (=) filtered) - |> Option.map PortableProfile +// KnownTargetProfiles.AllPortableProfiles |> Seq.tryFind (snd >> (=) filtered) +// |> Option.map PortableProfile +// TODO: In future work this stuff should be rewritten. This penalty stuff is more random than a proper implementation. let getPlatformPenalty = - let rec getPlatformPenalty alreadyChecked (targetPlatform:FrameworkIdentifier) (packagePlatform:FrameworkIdentifier) = + let rec getPlatformPenalty alreadyChecked (targetPlatform:TargetProfile) (packagePlatform:TargetProfile) = if packagePlatform = targetPlatform then 0 else let penalty = targetPlatform.SupportedPlatforms - |> List.filter (fun x -> Set.contains x alreadyChecked |> not) + |> List.filter (fun x -> + System.Diagnostics.Debug.WriteLine(sprintf "Supported %O -> %O (trying to find %O)" targetPlatform x packagePlatform) + Set.contains x alreadyChecked |> not) |> List.map (fun target -> getPlatformPenalty (Set.add target alreadyChecked) target packagePlatform) |> List.append [MaxPenalty] |> List.min |> fun p -> p + 1 match targetPlatform, packagePlatform with - | DotNetFramework _, DotNetStandard _ -> 200 + penalty - | DotNetStandard _, DotNetFramework _ -> 200 + penalty + | SinglePlatform (DotNetFramework _), SinglePlatform (DotNetStandard _) -> 200 + penalty + | SinglePlatform (DotNetStandard _), SinglePlatform(DotNetFramework _) -> 200 + penalty + | SinglePlatform _, PortableProfile _ -> 500 + penalty + | PortableProfile _, SinglePlatform _ -> 500 + penalty | _ -> penalty - memoize (fun (targetPlatform:FrameworkIdentifier,packagePlatform:FrameworkIdentifier) -> getPlatformPenalty Set.empty targetPlatform packagePlatform) + memoize (fun (targetPlatform:TargetProfile,packagePlatform:TargetProfile) -> getPlatformPenalty Set.empty targetPlatform packagePlatform) + +let getFrameworkPenalty (fr1, fr2) = + getPlatformPenalty (SinglePlatform fr1, SinglePlatform fr2) + let getPathPenalty = memoize - (fun (path:ParsedPlatformPath,platform:FrameworkIdentifier) -> - if String.IsNullOrWhiteSpace path.Name then + (fun (path:ParsedPlatformPath,platform:TargetProfile) -> + let handleEmpty () = match platform with - | Native(_) -> MaxPenalty // an empty path is considered incompatible with native targets - | _ -> 500 // an empty path is considered compatible with every .NET target, but with a high penalty so explicit paths are preferred - else - path.Platforms - |> List.map (fun target -> getPlatformPenalty(platform,target)) - |> List.append [ MaxPenalty ] - |> List.min) - -// Checks wether a list of target platforms is supported by this path and with which penalty. -let getPenalty (requiredPlatforms:FrameworkIdentifier list) (path:ParsedPlatformPath) = - requiredPlatforms - |> List.sumBy (fun p -> getPathPenalty(path,p)) + | SinglePlatform(Native(_)) -> MaxPenalty // an empty path is considered incompatible with native targets + | _ -> 2000 // an empty path is considered compatible with every .NET target, but with a high penalty so explicit paths are preferred + match path.Platforms with + | _ when String.IsNullOrWhiteSpace path.Name -> handleEmpty() + | [] -> handleEmpty() + | [ h ] -> getPlatformPenalty(platform,SinglePlatform h) + | _ -> + getPlatformPenalty(platform, PortableProfile(path.Name, path.Platforms))) + +[] +let getFrameworkPathPenalty fr path = + match fr with + | [ h ] -> getPathPenalty (path, SinglePlatform h) + | _ -> + getPathPenalty (path, PortableProfile("unknown", fr)) type PathPenalty = (ParsedPlatformPath * int) @@ -95,60 +107,54 @@ let comparePaths (p1 : PathPenalty) (p2 : PathPenalty) = let collectPlatforms = - let rec loop (acc:FrameworkIdentifier list) (framework:FrameworkIdentifier) (profls:TargetProfile list) = + let rec loop (acc:TargetProfile list) (framework:TargetProfile) (profls:TargetProfile list) = match profls with | [] -> acc - | (SinglePlatform f)::tl -> + | f::tl -> if f.SupportedPlatforms |> List.exists ((=) framework) then loop (f::acc) framework tl else loop acc framework tl - | _::tl -> loop acc framework tl - memoize (fun (framework,profls) -> loop ([]:FrameworkIdentifier list) framework profls) - -/// Returns all framework identifiers which (transitively) support the given framework identifier -let getFrameworksSupporting = - let calculate (x:FrameworkIdentifier) = - // calculate - KnownTargetProfiles.AllProfiles - |> List.collect(function - | SinglePlatform p -> [p] - | PortableProfile (_, fws) -> fws) - |> List.distinct - |> List.filter (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains x) - memoize calculate + //| _::tl -> loop acc framework tl + memoize (fun (framework,profls) -> loop ([]:TargetProfile list) framework profls) let getPlatformsSupporting = // http://nugettoolsdev.azurewebsites.net let calculate (x:TargetProfile) = - match x with - | PortableProfile (name,fws) -> - // Portables can be supported by other portables and by all fws given. - KnownTargetProfiles.AllProfiles - |> List.filter (function - | PortableProfile (otherName,otherfws) -> - // the other portable profile is supported, when the transitive supported set is a superset - let currentSupportedFrameworks = - fws - |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) - |> List.distinct - |> List.sort - let otherSupportedFrameworks = - otherfws - |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) - |> List.distinct - |> List.sort - - // take if the other profile supports all frameworks we support - currentSupportedFrameworks - |> Seq.forall (fun fw -> otherSupportedFrameworks |> Seq.exists ((=) fw)) - | SinglePlatform otherfw -> - // otherfw is supported if it is supported by of any fw in fws - fws - |> Seq.exists (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains otherfw)) - | SinglePlatform tf -> - // SinglePlatforms are only supported by other SinglePlatforms - getFrameworksSupporting tf - |> List.map SinglePlatform + KnownTargetProfiles.AllProfiles + //|> List.collect(function + // | SinglePlatform p -> [p] + // | PortableProfile (_, fws) -> fws) + //|> List.distinct + |> List.filter (fun plat -> plat.SupportedPlatformsTransitive |> Seq.contains x) + //match x with + //| PortableProfile (name,fws) -> + // // Portables can be supported by other portables and by all fws given. + // KnownTargetProfiles.AllProfiles + // |> List.filter (function + // | PortableProfile (otherName,otherfws) -> + // // the other portable profile is supported, when the transitive supported set is a superset + // let currentSupportedFrameworks = + // fws + // |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) + // |> List.distinct + // |> List.sort + // let otherSupportedFrameworks = + // otherfws + // |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) + // |> List.distinct + // |> List.sort + // + // // take if the other profile supports all frameworks we support + // currentSupportedFrameworks + // |> Seq.forall (fun fw -> otherSupportedFrameworks |> Seq.exists ((=) fw)) + // | SinglePlatform otherfw -> + // // otherfw is supported if it is supported by of any fw in fws + // fws + // |> Seq.exists (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains otherfw)) + //| SinglePlatform tf -> + // // SinglePlatforms are only supported by other SinglePlatforms + // getFrameworksSupporting tf + // |> List.map SinglePlatform memoize calculate let platformsSupport = @@ -157,7 +163,7 @@ let platformsSupport = elif platforms |> List.exists ((=) platform) then 1 else platforms |> Array.ofList - |> Array.Parallel.map (fun (p : FrameworkIdentifier) -> + |> Array.Parallel.map (fun (p : TargetProfile) -> collectPlatforms (p,KnownTargetProfiles.AllProfiles) ) |> List.concat |> platformsSupport platform |> (+) 1 @@ -166,42 +172,38 @@ let platformsSupport = let findBestMatch = let rec findBestMatch (paths : ParsedPlatformPath list, targetProfile : TargetProfile) = - let requiredPlatforms = - match targetProfile with - | PortableProfile(_, platforms) -> platforms - | SinglePlatform(platform) -> [ platform ] - let supported = + //let supported = paths - |> List.map (fun path -> path, (getPenalty requiredPlatforms path)) + |> List.map (fun path -> path, (getPathPenalty (path, targetProfile))) |> List.filter (fun (_, penalty) -> penalty < MaxPenalty) |> List.sortWith comparePaths |> List.map fst |> List.tryHead - let findBestPortableMatch findPenalty (portableProfile:TargetProfile) paths = - paths - |> Seq.tryFind (fun p -> tryGetProfile p = Some portableProfile) - |> Option.map (fun p -> p, findPenalty) - - match supported with - | None -> - // Fallback Portable Library - KnownTargetProfiles.AllProfiles - |> List.choose (fun p -> - match targetProfile with - | SinglePlatform x -> - match platformsSupport(x,p.ProfilesCompatibleWithPortableProfile) with - | pen when pen < MaxPenalty -> - findBestPortableMatch pen p paths - | _ -> - None - | _ -> None) - |> List.distinct - |> List.sortBy (fun (x, pen) -> pen, x.Platforms.Length) // prefer portable platform with less platforms - |> List.map fst - |> List.tryHead - | path -> path + //let findBestPortableMatch findPenalty (portableProfile:TargetProfile) paths = + // paths + // |> Seq.tryFind (fun p -> tryGetProfile p = Some portableProfile) + // |> Option.map (fun p -> p, findPenalty) + // + //match supported with + //| None -> + // // Fallback Portable Library + // KnownTargetProfiles.AllProfiles + // |> List.choose (fun p -> + // match targetProfile with + // | SinglePlatform x -> + // match platformsSupport(x,p.ProfilesCompatibleWithPortableProfile) with + // | pen when pen < MaxPenalty -> + // findBestPortableMatch pen p paths + // | _ -> + // None + // | _ -> None) + // |> List.distinct + // |> List.sortBy (fun (x, pen) -> pen, x.Platforms.Length) // prefer portable platform with less platforms + // |> List.map fst + // |> List.tryHead + //| path -> path memoize (fun (paths : ParsedPlatformPath list,targetProfile : TargetProfile) -> findBestMatch(paths,targetProfile)) @@ -225,8 +227,8 @@ let getTargetCondition (target:TargetProfile) = | SinglePlatform(platform) -> // BUG: Pattern incomplete! match platform with - | DotNetFramework(version) when version = FrameworkVersion.V4_Client -> - "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Client')" version + | DotNetFramework(version) when version = FrameworkVersion.V4 -> + "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O')" version | DotNetFramework(version) ->"$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DNX(version) ->"$(TargetFrameworkIdentifier) == 'DNX'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DNXCore(version) ->"$(TargetFrameworkIdentifier) == 'DNXCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version @@ -243,7 +245,7 @@ let getTargetCondition (target:TargetProfile) = | Windows(version) -> "$(TargetFrameworkIdentifier) == '.NETCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version | Silverlight(version) -> "$(TargetFrameworkIdentifier) == 'Silverlight'", sprintf "$(TargetFrameworkVersion) == '%O'" version | WindowsPhoneApp(version) -> "$(TargetFrameworkIdentifier) == 'WindowsPhoneApp'", sprintf "$(TargetFrameworkVersion) == '%O'" version - | WindowsPhoneSilverlight(version) -> "$(TargetFrameworkIdentifier) == 'WindowsPhone'", sprintf "$(TargetFrameworkVersion) == '%O'" version + | WindowsPhone(version) -> "$(TargetFrameworkIdentifier) == 'WindowsPhone'", sprintf "$(TargetFrameworkVersion) == '%O'" version | MonoAndroid -> "$(TargetFrameworkIdentifier) == 'MonoAndroid'", "" | MonoTouch -> "$(TargetFrameworkIdentifier) == 'MonoTouch'", "" | MonoMac -> "$(TargetFrameworkIdentifier) == 'MonoMac'", "" @@ -274,18 +276,18 @@ let getCondition (referenceCondition:string option) (allTargets: TargetProfile l |> CheckIfFullyInGroup ".NETCore" (function SinglePlatform (Windows _) -> true | _ -> false) |> CheckIfFullyInGroup "Silverlight" (function SinglePlatform (Silverlight _) -> true | _ -> false) |> CheckIfFullyInGroup "WindowsPhoneApp" (function SinglePlatform (WindowsPhoneApp _) -> true | _ -> false) - |> CheckIfFullyInGroup "WindowsPhone" (function SinglePlatform (WindowsPhoneSilverlight _) -> true | _ -> false) - - let targets = - targets - |> List.map (fun target -> - match target with - | SinglePlatform(DotNetFramework(FrameworkVersion.V4_Client)) -> - if allTargets |> List.exists (List.contains (SinglePlatform(DotNetFramework(FrameworkVersion.V4)))) |> not then - SinglePlatform(DotNetFramework(FrameworkVersion.V4)) - else - target - | _ -> target) + |> CheckIfFullyInGroup "WindowsPhone" (function SinglePlatform (WindowsPhone _) -> true | _ -> false) + + //let targets = + // targets + // |> List.map (fun target -> + // match target with + // | SinglePlatform(DotNetFramework(FrameworkVersion.V4_Client)) -> + // if allTargets |> List.exists (List.contains (SinglePlatform(DotNetFramework(FrameworkVersion.V4)))) |> not then + // SinglePlatform(DotNetFramework(FrameworkVersion.V4)) + // else + // target + // | _ -> target) let conditions = if targets = [ SinglePlatform(Native(NoBuildMode,NoPlatform)) ] then @@ -294,8 +296,8 @@ let getCondition (referenceCondition:string option) (allTargets: TargetProfile l targets |> List.filter (function | SinglePlatform(Native(NoBuildMode,NoPlatform)) -> false - | SinglePlatform(DotNetFramework(FrameworkVersion.V4_Client)) -> - targets |> List.contains (SinglePlatform(DotNetFramework(FrameworkVersion.V4))) |> not + //| SinglePlatform(DotNetFramework(FrameworkVersion.V4)) -> + // targets |> List.contains (SinglePlatform(DotNetFramework(FrameworkVersion.V4))) |> not | _ -> true) |> List.map getTargetCondition |> List.filter (fun (_, v) -> v <> "false") diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 7877fc1472..a3e8178fbc 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -8,11 +8,11 @@ open Paket.Logging let private allFrameworks = KnownTargetProfiles.AllProfiles - |> List.collect (function - | SinglePlatform fw -> [fw] - | PortableProfile (_, fws) -> fws) - |> List.distinct - |> List.sort + //|> List.collect (function + // | SinglePlatform fw -> [fw] + // | PortableProfile (_, fws) -> fws) + //|> List.distinct + //|> List.sort [] // To make reasoning and writing tests easier. // Ideally we would "simplify" the trees to a "normal" form internally @@ -22,10 +22,10 @@ type FrameworkRestrictionP = private //| NoRestrictionP // = AndP [] //| EmptySetP // = OrP [] - | ExactlyP of FrameworkIdentifier + | ExactlyP of TargetProfile //[] - | PortableP of string * FrameworkIdentifier list - | AtLeastP of FrameworkIdentifier + //| PortableP of string * FrameworkIdentifier list + | AtLeastP of TargetProfile // Means: Take all frameworks NOT given by the restriction | NotP of FrameworkRestrictionP | OrP of FrameworkRestrictionP list @@ -33,7 +33,7 @@ type FrameworkRestrictionP = member x.InfixNotation = match x with | FrameworkRestrictionP.ExactlyP r -> r.ToString() - | FrameworkRestrictionP.PortableP (r,_) -> r + //| FrameworkRestrictionP.PortableP (r,_) -> r | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() | FrameworkRestrictionP.NotP(fr) -> sprintf "NOT (%O)" fr @@ -50,7 +50,7 @@ type FrameworkRestrictionP = override this.ToString() = match this with | FrameworkRestrictionP.ExactlyP r -> r.ToString() - | FrameworkRestrictionP.PortableP (r,_) -> r + //| FrameworkRestrictionP.PortableP (r,_) -> r | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() | FrameworkRestrictionP.NotP(fr) -> sprintf "NOT (%O)" fr @@ -69,13 +69,13 @@ type FrameworkRestrictionP = member x.RepresentedFrameworks = match x with | FrameworkRestrictionP.ExactlyP r -> [ r ] - | FrameworkRestrictionP.PortableP (r, fws) -> - fws - |> List.collect (fun fw -> (FrameworkRestrictionP.AtLeastP fw).RepresentedFrameworks) - |> List.distinct - |> List.sort + //| FrameworkRestrictionP.PortableP (r, fws) -> + // fws + // |> List.collect (fun fw -> (FrameworkRestrictionP.AtLeastP fw).RepresentedFrameworks) + // |> List.distinct + // |> List.sort | FrameworkRestrictionP.AtLeastP r -> - PlatformMatching.getFrameworksSupporting r + PlatformMatching.getPlatformsSupporting r | FrameworkRestrictionP.NotP(fr) -> let notTaken = fr.RepresentedFrameworks allFrameworks @@ -94,17 +94,33 @@ type FrameworkRestrictionP = | [] -> allFrameworks + member x.IsMatch (tp:TargetProfile) = + match x with + | FrameworkRestrictionP.ExactlyP r -> r = tp + //| FrameworkRestrictionP.PortableP (r, fws) -> + // fws + // |> List.collect (fun fw -> (FrameworkRestrictionP.AtLeastP fw).RepresentedFrameworks) + // |> List.distinct + // |> List.sort + | FrameworkRestrictionP.AtLeastP r -> + tp.SupportedPlatformsTransitive |> Seq.contains r + | FrameworkRestrictionP.NotP(fr) -> + fr.IsMatch tp |> not + | FrameworkRestrictionP.OrP (frl) -> + frl + |> List.exists (fun fr -> fr.IsMatch tp) + | FrameworkRestrictionP.AndP (frl) -> + frl + |> List.forall (fun fr -> fr.IsMatch tp) + /// Returns true if the restriction x is a subset of the restriction y (a restriction basically represents a list, see RepresentedFrameworks) /// For example =net46 is a subset of >=netstandard13 member x.IsSubsetOf (y:FrameworkRestrictionP) = let superset = y.RepresentedFrameworks x.RepresentedFrameworks |> List.forall (fun inner -> superset |> Seq.contains inner) - static member ExactlyProfile (pf: TargetProfile) = - match pf with - | SinglePlatform f -> ExactlyP f - | PortableProfile(name,fws) -> PortableP(name, fws) - + static member ExactlyFramework (tf: FrameworkIdentifier) = + ExactlyP (SinglePlatform tf) override x.Equals(y) = (match y with :? FrameworkRestrictionP as r -> r.RepresentedFrameworks = x.RepresentedFrameworks | _ -> false) override x.GetHashCode() = x.RepresentedFrameworks.GetHashCode() @@ -112,13 +128,13 @@ type FrameworkRestrictionP = member x.CompareTo(y) = (match y with :? FrameworkRestrictionP as r -> compare x.RepresentedFrameworks r.RepresentedFrameworks | _ -> failwith "wrong type") type FrameworkRestrictionLiteralI = - | ExactlyL of FrameworkIdentifier - | PortableL of string * FrameworkIdentifier list - | AtLeastL of FrameworkIdentifier + | ExactlyL of TargetProfile + //| PortableL of string * FrameworkIdentifier list + | AtLeastL of TargetProfile member internal x.RawFormular = match x with | ExactlyL id -> FrameworkRestrictionP.ExactlyP id - | PortableL (name, fws) -> FrameworkRestrictionP.PortableP (name, fws) + //| PortableL (name, fws) -> FrameworkRestrictionP.PortableP (name, fws) | AtLeastL id -> FrameworkRestrictionP.AtLeastP id type FrameworkRestrictionLiteral = { LiteraL : FrameworkRestrictionLiteralI; IsNegated : bool } @@ -144,14 +160,16 @@ type FrameworkRestriction = x.RawFormular.IsSubsetOf y.RawFormular member x.RepresentedFrameworks = x.RawFormular.RepresentedFrameworks - + member x.IsMatch tp = + x.RawFormular.IsMatch tp module FrameworkRestriction = let EmptySet = { OrFormulas = [] } // false let NoRestriction = { OrFormulas = [ { Literals = [] } ] } // true - let Exactly id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (ExactlyL id) ] } ] } - let Portable (name, fws)= { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (PortableL (name, fws)) ] } ] } - let AtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (AtLeastL id) ] } ] } - let NotAtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromNegatedLiteral (AtLeastL id) ] } ] } + let AtLeastPlatform pf = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (AtLeastL pf) ] } ] } + let Exactly id = AtLeastPlatform (SinglePlatform id) + let AtLeastPortable (name, fws)= AtLeastPlatform (PortableProfile (name, fws)) + let AtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (AtLeastL (SinglePlatform id)) ] } ] } + let NotAtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromNegatedLiteral (AtLeastL (SinglePlatform id)) ] } ] } let private simplify (fr:FrameworkRestriction) = /// When we have a restriction like (>=net35 && =net45 @@ -363,7 +381,7 @@ let parseRestrictionsLegacy failImmediatly (text:string) = | None -> let platforms = (PlatformMatching.extractPlatforms framework).Platforms if platforms |> List.isEmpty |> not then - yield FrameworkRestriction.Portable (framework, platforms) + yield FrameworkRestriction.AtLeastPortable (framework, platforms) else handleError <| sprintf "Could not parse framework '%s'. Try to update or install again or report a paket bug." framework | Some x -> @@ -736,14 +754,15 @@ let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestriction /// Get if a target should be considered with the specified restrictions let isTargetMatchingRestrictions (restriction:FrameworkRestriction, target)= - match target with - | SinglePlatform pf -> - restriction.RepresentedFrameworks |> Seq.contains pf - | PortableProfile (_, fws) -> - // TODO: Review - check if we need to use exists instead of forall? - fws - |> Seq.forall (fun fw -> - restriction.RepresentedFrameworks |> Seq.contains fw) + restriction.IsMatch target + + //match target with + //| SinglePlatform pf -> restriction.RepresentedFrameworks |> Seq.contains pf + //| PortableProfile (_, fws) -> + // // TODO: Review - check if we need to use exists instead of forall? + // fws + // |> Seq.forall (fun fw -> + // restriction.RepresentedFrameworks |> Seq.contains fw) //memoize <| fun (restrictions:FrameworkRestriction list, target) -> // if List.isEmpty restrictions then true else @@ -1083,7 +1102,7 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = | _ when System.String.IsNullOrEmpty packageGroup.Name -> FrameworkRestriction.NoRestriction | [] -> FrameworkRestriction.NoRestriction | [ pf ] -> FrameworkRestriction.AtLeast pf - | _ -> FrameworkRestriction.Portable(packageGroup.Name, packageGroup.Platforms) + | _ -> FrameworkRestriction.AtLeastPortable(packageGroup.Name, packageGroup.Platforms) frameworkGroups |> Seq.filter (fun frameworkGroup -> @@ -1108,7 +1127,7 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = match packageGroup.Platforms, missing.RepresentedFrameworks with | [ packageGroupFw ], firstMissing :: _ -> // the common set goes to the better matching one - match PlatformMatching.findBestMatch (frameworkGroupPaths, SinglePlatform firstMissing) with + match PlatformMatching.findBestMatch (frameworkGroupPaths, firstMissing) with | Some { PlatformMatching.ParsedPlatformPath.Platforms = [ cfw ] } when cfw = packageGroupFw -> curRestr | _ -> combined | _ -> combined) packageGroupRestriction) diff --git a/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs b/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs index 69b97e1fee..b8b0fd9f54 100644 --- a/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs +++ b/tests/Paket.Tests/DependenciesFile/ParserSpecs.fs @@ -770,7 +770,7 @@ let ``should read config with single framework restriction``() = let p = cfg.Groups.[Constants.MainDependencyGroup].Packages |> List.find (fun x-> x.Name = PackageName "Foobar") p.VersionRequirement.Range |> shouldEqual (VersionRange.Specific (SemVer.Parse "1.2.3")) - p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))) + p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) p.Settings.ImportTargets |> shouldEqual None @@ -783,7 +783,7 @@ let ``should read config with framework restriction``() = let p = cfg.Groups.[Constants.MainDependencyGroup].Packages |> List.find (fun x-> x.Name = PackageName "Foobar") p.VersionRequirement.Range |> shouldEqual (VersionRange.Specific (SemVer.Parse "1.2.3")) - p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5)); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))] |> getExplicitRestriction) + p.Settings.FrameworkRestrictions |> getExplicitRestriction |> shouldEqual (makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5)); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))] |> getExplicitRestriction) p.Settings.ImportTargets |> shouldEqual None p.Settings.CopyLocal |> shouldEqual None @@ -1128,7 +1128,7 @@ let ``should read config with target framework``() = cfg.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) [] let ``should read packages with redirects``() = diff --git a/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs b/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs index fe5bc11911..fe61e32919 100644 --- a/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs +++ b/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs @@ -7,24 +7,24 @@ open FsUnit [] let ``should understand basic framework versions net20, net40, net45 ...``() = FrameworkDetection.Extract("net20").Value |> shouldEqual (DotNetFramework(FrameworkVersion.V2)) - FrameworkDetection.Extract("net40").Value |> shouldEqual (DotNetFramework(FrameworkVersion.V4_Client)) + FrameworkDetection.Extract("net40").Value |> shouldEqual (DotNetFramework(FrameworkVersion.V4)) FrameworkDetection.Extract("net45").Value |> shouldEqual (DotNetFramework(FrameworkVersion.V4_5)) [] let ``should understand basic silverlight``() = - FrameworkDetection.Extract("sl").Value |> shouldEqual (Silverlight "v3.0") - FrameworkDetection.Extract("sl3").Value |> shouldEqual (Silverlight "v3.0") - FrameworkDetection.Extract("sl4").Value |> shouldEqual (Silverlight "v4.0") + FrameworkDetection.Extract("sl").Value |> shouldEqual (Silverlight SilverlightVersion.V3) + FrameworkDetection.Extract("sl3").Value |> shouldEqual (Silverlight SilverlightVersion.V3) + FrameworkDetection.Extract("sl4").Value |> shouldEqual (Silverlight SilverlightVersion.V4) [] let ``should serialize basic framework versions net20, net40, net45 ...``() = DotNetFramework(FrameworkVersion.V2).ToString() |> shouldEqual "net20" - DotNetFramework(FrameworkVersion.V4_Client).ToString() |> shouldEqual "net40" + DotNetFramework(FrameworkVersion.V4).ToString() |> shouldEqual "net40" DotNetFramework(FrameworkVersion.V4_5).ToString() |> shouldEqual "net45" [] let ``should serialize silverlight framework identifier correctly``() = - Silverlight("v5.0").ToString() |> shouldEqual "sl50" + (Silverlight SilverlightVersion.V5).ToString() |> shouldEqual "sl50" [] let ``should understand basic dnx``() = diff --git a/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs b/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs index 4dda0bd24e..1a71cd43d4 100644 --- a/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs +++ b/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs @@ -48,12 +48,12 @@ let ``should minimize condition if we have all WindowsProfiles``() = let ``should create nested condition for .NET Framework and Silverlight``() = [SinglePlatform(DotNetFramework FrameworkVersion.V3) SinglePlatform(DotNetFramework FrameworkVersion.V4_5) - SinglePlatform(Silverlight("v3.0"))] + SinglePlatform(Silverlight SilverlightVersion.V3)] |> getCondition None |> shouldEqual "($(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v3.0' Or $(TargetFrameworkVersion) == 'v4.5')) Or ($(TargetFrameworkIdentifier) == 'Silverlight' And $(TargetFrameworkVersion) == 'v3.0')" [] let ``should create nested condition for full .NET Framework and Silverlight``() = - SinglePlatform(Silverlight("v3.0")) :: KnownTargetProfiles.DotNetFrameworkProfiles + SinglePlatform(Silverlight SilverlightVersion.V3) :: KnownTargetProfiles.DotNetFrameworkProfiles |> getCondition None |> shouldEqual "($(TargetFrameworkIdentifier) == '.NETFramework') Or ($(TargetFrameworkIdentifier) == 'Silverlight' And $(TargetFrameworkVersion) == 'v3.0')" \ No newline at end of file diff --git a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs index 0103fb9bf8..9e94ef6f1c 100644 --- a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs +++ b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs @@ -9,23 +9,23 @@ module ``Given a target platform`` = [] let ``it should return no penalty for the same platform``() = - getPlatformPenalty (DotNetFramework FrameworkVersion.V4_5, DotNetFramework FrameworkVersion.V4_5) + getFrameworkPenalty (DotNetFramework FrameworkVersion.V4_5, DotNetFramework FrameworkVersion.V4_5) |> shouldEqual 0 [] let ``it should return the right penalty for a compatible platform``() = - getPlatformPenalty (DotNetFramework FrameworkVersion.V4_5, DotNetFramework FrameworkVersion.V4) + getFrameworkPenalty (DotNetFramework FrameworkVersion.V4_5, DotNetFramework FrameworkVersion.V4) |> shouldEqual 1 [] let ``it should return > 1000 for an incompatible platform``() = - getPlatformPenalty (DotNetFramework FrameworkVersion.V4_5, Silverlight "v5.0") + getFrameworkPenalty (DotNetFramework FrameworkVersion.V4_5, Silverlight SilverlightVersion.V5) |> shouldBeGreaterThan MaxPenalty [] let ``it should prefer .net proper``() = - let p1 = getPlatformPenalty (DotNetFramework FrameworkVersion.V4_6_2, DotNetFramework FrameworkVersion.V4_5_1) - let p2 = getPlatformPenalty (DotNetFramework FrameworkVersion.V4_6_2, DotNetStandard DotNetStandardVersion.V1_5) + let p1 = getFrameworkPenalty (DotNetFramework FrameworkVersion.V4_6_2, DotNetFramework FrameworkVersion.V4_5_1) + let p2 = getFrameworkPenalty (DotNetFramework FrameworkVersion.V4_6_2, DotNetStandard DotNetStandardVersion.V1_5) p1 |> shouldBeSmallerThan p2 module ``Given a path`` = @@ -33,53 +33,55 @@ module ``Given a path`` = let ``it should split it into the right platforms``() = extractPlatforms "net40+win8" |> shouldEqual - { Platforms = [ DotNetFramework FrameworkVersion.V4_Client; Windows "v4.5" ] + { Platforms = [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8 ] Name = "net40+win8" } [] let ``it should ignore 'portable-'``() = extractPlatforms "portable-net40+win8" |> shouldEqual - { Platforms = [ DotNetFramework FrameworkVersion.V4_Client; Windows "v4.5" ] + { Platforms = [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8 ] Name = "portable-net40+win8" } [] let ``it should return no penalty for a matching .NET framework``() = let path = extractPlatforms "net45" - getPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldEqual 0 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldEqual 0 [] let ``it should return no penalty for a matching portable profile``() = let path = extractPlatforms "net40+sl4" - getPenalty [ DotNetFramework FrameworkVersion.V4_Client - Silverlight "v4.0" ] path + getFrameworkPathPenalty + [ DotNetFramework FrameworkVersion.V4 + Silverlight SilverlightVersion.V4 ] path |> shouldEqual 0 [] let ``it should return 1 for a compatible portable profile``() = let path = extractPlatforms "net40+sl4" - getPenalty [ DotNetFramework FrameworkVersion.V4_Client - Silverlight "v5.0" ] path + getFrameworkPathPenalty + [ DotNetFramework FrameworkVersion.V4 + Silverlight SilverlightVersion.V5 ] path |> shouldEqual 1 [] let ``it should return the correct penalty for compatible .NET Frameworks``() = let path = extractPlatforms "net20" - getPenalty [ DotNetFramework FrameworkVersion.V2 ] path |> shouldEqual 0 - getPenalty [ DotNetFramework FrameworkVersion.V3 ] path |> shouldEqual 1 - getPenalty [ DotNetFramework FrameworkVersion.V3_5 ] path |> shouldEqual 2 - getPenalty [ DotNetFramework FrameworkVersion.V4_Client ] path |> shouldEqual 3 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V2 ] path |> shouldEqual 0 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V3 ] path |> shouldEqual 1 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V3_5 ] path |> shouldEqual 2 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4 ] path |> shouldEqual 3 module ``Given an empty path`` = [] let ``it should be okay to use from .NET``() = let path = extractPlatforms "" - getPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldBeSmallerThan 1000 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldBeSmallerThan 1000 [] let ``it should be okay to use from a portable profile``() = let path = extractPlatforms "" - getPenalty [ DotNetFramework FrameworkVersion.V4_5; Windows "v4.5"; WindowsPhoneApp "v8.1" ] path |> shouldBeSmallerThan 2000 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] path |> shouldBeSmallerThan 2000 module ``Given a list of paths`` = let paths = @@ -97,11 +99,11 @@ module ``Given a list of paths`` = [] let ``it should find the best match for Silverlight 5``() = - findBestMatch (paths, SinglePlatform(Silverlight "v5.0")) |> shouldEqual (find "sl5"|> Some) + findBestMatch (paths, SinglePlatform(Silverlight SilverlightVersion.V5)) |> shouldEqual (find "sl5"|> Some) [] let ``it should find no match for Silverlight 4``() = - findBestMatch (paths, SinglePlatform(Silverlight "v4.0")) |> shouldEqual None + findBestMatch (paths, SinglePlatform(Silverlight SilverlightVersion.V4)) |> shouldEqual None [] let ``it should prefer (older) full .NET frameworks over portable class libraries``() = @@ -125,10 +127,10 @@ module ``Given a list of paths`` = flattend |> shouldNotContain (KnownTargetProfiles.FindPortableProfile "Profile41") module ``ProfileAnalyzer tests`` = - [] - let ``test that we cannot detect portable-net40+sl4+win8+wp71+wpa81`` () = - let res = Paket.PlatformMatching.tryGetProfile (extractPlatforms "portable-net40+sl4+win8+wp71+wpa81") - res |> shouldEqual None + //[] + //let ``test that we cannot detect portable-net40+sl4+win8+wp71+wpa81`` () = + // let res = Paket.PlatformMatching.tryGetProfile (extractPlatforms "portable-net40+sl4+win8+wp71+wpa81") + // res |> shouldEqual None module ``General Penalty checks`` = [] diff --git a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs index 5a09a4904a..68b6ef5a6b 100644 --- a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs +++ b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs @@ -32,7 +32,7 @@ let ``should create empty model with net40, net45 ...``() = let ``should understand net40 and net45``() = let model = emptymodel.AddReferences ([ @"..\Rx-Main\lib\net40\Rx.dll"; @"..\Rx-Main\lib\net45\Rx.dll" ] |> fromLegacyList @"..\Rx-Main\") - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain (@"..\Rx-Main\lib\net40\Rx.dll") model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_5)) |> Seq.map (fun f -> f.Path)|> shouldContain @"..\Rx-Main\lib\net45\Rx.dll" @@ -41,14 +41,14 @@ let ``should understand net40 and net45``() = let ``should understand lib in lib.dll``() = let model = emptymodel.AddReferences ([ @"..\FunScript.TypeScript\lib\net40\FunScript.TypeScript.Binding.lib.dll" ] |> fromLegacyList @"..\FunScript.TypeScript\") - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\FunScript.TypeScript\lib\net40\FunScript.TypeScript.Binding.lib.dll" [] let ``should understand libuv in runtimes``() = let model = emptymodel.AddReferences ([ @"..\Microsoft.AspNetCore.Server.Kestrel\runtimes\win7-x64\native\libuv.dll" ] |> fromLegacyList @"..\Microsoft.AspNetCore.Server.Kestrel\") - model.GetRuntimeLibraries RuntimeGraph.Empty (Rid.Of "win7-x64") (SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetRuntimeLibraries RuntimeGraph.Empty (Rid.Of "win7-x64") (SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun (r:RuntimeLibrary) -> r.Library.Path) |> shouldContain @"..\Microsoft.AspNetCore.Server.Kestrel\runtimes\win7-x64\native\libuv.dll" [] @@ -198,7 +198,7 @@ let ``should put _._ files into right buckets``() = model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V2)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Rx-Main\lib\net20\_._" - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Rx-Main\lib\net40\_._" [] @@ -248,7 +248,7 @@ let ``should install single client profile lib for everything``() = let model = emptymodel.AddReferences([ @"..\Castle.Core\lib\net40-client\Castle.Core.dll" ] |> fromLegacyList @"..\Castle.Core\") - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Castle.Core\lib\net40-client\Castle.Core.dll" model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Castle.Core\lib\net40-client\Castle.Core.dll" @@ -265,7 +265,7 @@ let ``should install net40 for client profile``() = model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V3_5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll" - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll" model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll" @@ -281,7 +281,7 @@ let ``should install not use net40-full for client profile``() = |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll" model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net40-full\Newtonsoft.Json.dll" - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldNotContain @"..\Newtonsoft.Json\lib\net40-full\Newtonsoft.Json.dll" [] @@ -327,7 +327,7 @@ let ``should handle lib install of Jint for NET >= 40 and SL >= 50``() = model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Jint\lib\portable-net40+sl50+win+wp80\Jint.dll" - model.GetLegacyReferences(SinglePlatform (Silverlight "v5.0")) + model.GetLegacyReferences(SinglePlatform (Silverlight SilverlightVersion.V5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Jint\lib\portable-net40+sl50+win+wp80\Jint.dll" model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V3_5)) @@ -387,11 +387,11 @@ let ``should not use portable-net40 if we have net40``() = @"..\Microsoft.Bcl\lib\portable-net40+sl4+win8\System.Runtime.dll" @"..\Microsoft.Bcl\lib\portable-net40+sl4+win8\System.Threading.Tasks.dll" ] |> fromLegacyList @"..\Microsoft.Bcl\") - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\net40\System.IO.dll" - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\net40\System.Runtime.dll" - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\net40\System.Threading.Tasks.dll" let profile41 = KnownTargetProfiles.FindPortableProfile "Profile41" @@ -423,7 +423,7 @@ let ``should handle lib install of NUnit 2.6 for windows 8``() = |> Seq.map (fun f -> f.Path) |> shouldContain @"..\NUnit\lib\nunit.framework.dll" model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\NUnit\lib\nunit.framework.dll" - model.GetLegacyReferences(SinglePlatform (Windows "v4.5")) + model.GetLegacyReferences(SinglePlatform (Windows WindowsVersion.V8)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\NUnit\lib\nunit.framework.dll" @@ -502,14 +502,14 @@ let ``should handle lib install of Microsoft.Net.Http 2.2.28``() = model.GetLegacyReferences(profile7) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Net.Http\lib\portable-net45+win8\System.Net.Http.Primitives.dll" - model.GetLegacyReferences(SinglePlatform (Windows "v4.5")) + model.GetLegacyReferences(SinglePlatform (Windows WindowsVersion.V8)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Net.Http\lib\win8\System.Net.Http.Extensions.dll" - model.GetLegacyReferences(SinglePlatform (Windows "v4.5")) + model.GetLegacyReferences(SinglePlatform (Windows WindowsVersion.V8)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Net.Http\lib\win8\System.Net.Http.Primitives.dll" - model.GetLegacyReferences(SinglePlatform (WindowsPhoneApp "v8.1")) + model.GetLegacyReferences(SinglePlatform (WindowsPhoneApp WindowsPhoneAppVersion.V8_1)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Net.Http\lib\wpa81\System.Net.Http.Extensions.dll" - model.GetLegacyReferences(SinglePlatform (WindowsPhoneApp "v8.1")) + model.GetLegacyReferences(SinglePlatform (WindowsPhoneApp WindowsPhoneAppVersion.V8_1)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Net.Http\lib\wpa81\System.Net.Http.Primitives.dll" @@ -561,9 +561,9 @@ let ``should handle lib install of MicrosoftBcl``() = model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_5)) |> shouldBeEmpty model.GetLegacyReferences(SinglePlatform MonoAndroid) |> shouldBeEmpty model.GetLegacyReferences(SinglePlatform MonoTouch) |> shouldBeEmpty - model.GetLegacyReferences(SinglePlatform (Windows "v4.5")) |> shouldBeEmpty - model.GetLegacyReferences(SinglePlatform (WindowsPhoneSilverlight "v8.0")) |> shouldBeEmpty - model.GetLegacyReferences(SinglePlatform (WindowsPhoneApp "v8.1")) |> shouldBeEmpty + model.GetLegacyReferences(SinglePlatform (Windows WindowsVersion.V8)) |> shouldBeEmpty + model.GetLegacyReferences(SinglePlatform (WindowsPhone WindowsPhoneVersion.V8)) |> shouldBeEmpty + model.GetLegacyReferences(SinglePlatform (WindowsPhoneApp WindowsPhoneAppVersion.V8_1)) |> shouldBeEmpty model.GetLegacyReferences(KnownTargetProfiles.FindPortableProfile "Profile44") |> shouldBeEmpty model.GetLegacyReferences(KnownTargetProfiles.FindPortableProfile "Profile151") |> shouldBeEmpty @@ -575,25 +575,25 @@ let ``should handle lib install of MicrosoftBcl``() = model.GetLegacyReferences(profile41) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\portable-net40+sl4+win8\System.Threading.Tasks.dll" - model.GetLegacyReferences(SinglePlatform (Silverlight "v4.0")) + model.GetLegacyReferences(SinglePlatform (Silverlight SilverlightVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl4\System.IO.dll" - model.GetLegacyReferences(SinglePlatform (Silverlight "v4.0")) + model.GetLegacyReferences(SinglePlatform (Silverlight SilverlightVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl4\System.Runtime.dll" - model.GetLegacyReferences(SinglePlatform (Silverlight "v4.0")) + model.GetLegacyReferences(SinglePlatform (Silverlight SilverlightVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl4\System.Threading.Tasks.dll" - model.GetLegacyReferences(SinglePlatform (WindowsPhoneSilverlight "v7.1")) + model.GetLegacyReferences(SinglePlatform (WindowsPhone WindowsPhoneVersion.V7_5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl4-windowsphone71\System.IO.dll" - model.GetLegacyReferences(SinglePlatform (WindowsPhoneSilverlight "v7.1")) + model.GetLegacyReferences(SinglePlatform (WindowsPhone WindowsPhoneVersion.V7_5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl4-windowsphone71\System.Runtime.dll" - model.GetLegacyReferences(SinglePlatform (WindowsPhoneSilverlight "v7.1")) + model.GetLegacyReferences(SinglePlatform (WindowsPhone WindowsPhoneVersion.V7_5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl4-windowsphone71\System.Threading.Tasks.dll" - model.GetLegacyReferences(SinglePlatform (Silverlight "v5.0")) + model.GetLegacyReferences(SinglePlatform (Silverlight SilverlightVersion.V5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl5\System.IO.dll" - model.GetLegacyReferences(SinglePlatform (Silverlight "v5.0")) + model.GetLegacyReferences(SinglePlatform (Silverlight SilverlightVersion.V5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl5\System.Runtime.dll" - model.GetLegacyReferences(SinglePlatform (Silverlight "v5.0")) + model.GetLegacyReferences(SinglePlatform (Silverlight SilverlightVersion.V5)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Microsoft.Bcl\lib\sl5\System.Threading.Tasks.dll" diff --git a/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs b/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs index df666b697e..ea78af24b1 100644 --- a/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs +++ b/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs @@ -44,7 +44,7 @@ let ``should generate Xml for LibGit2Sharp 2.0.0``() = [], Nuspec.All) - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4_Client)) + model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\LibGit2Sharp\lib\net40\LibGit2Sharp.dll" let ctx = ProjectFile.TryLoad("./ProjectFile/TestData/Empty.fsprojtest").Value.GenerateXml(model, System.Collections.Generic.HashSet<_>(),Map.empty,Some true,true,KnownTargetProfiles.AllProfiles,None) diff --git a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs index 5d44560dcf..7e6a4f407a 100644 --- a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs +++ b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs @@ -110,8 +110,8 @@ let ``should generate Xml for Rx-XAML 2.2.4 with correct framework assembly refe FrameworkAssemblyReferences = [{ AssemblyName = "WindowsBase"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4_5)] } { AssemblyName = "WindowsBase"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4)] } - { AssemblyName = "System.Windows"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(Silverlight "v5.0")] } - { AssemblyName = "System.Windows"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(WindowsPhoneSilverlight "v7.1")] }]}) + { AssemblyName = "System.Windows"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(Silverlight SilverlightVersion.V5)] } + { AssemblyName = "System.Windows"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(WindowsPhone WindowsPhoneVersion.V7_5)] }]}) let ctx = ProjectFile.TryLoad("./ProjectFile/TestData/Empty.fsprojtest").Value.GenerateXml(model, System.Collections.Generic.HashSet<_>(),Map.empty,Some true,true,KnownTargetProfiles.AllProfiles,None) let currentXml = ctx.ChooseNodes.Head.OuterXml |> normalizeXml diff --git a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs index 9bb093a24f..25567cd490 100644 --- a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs +++ b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs @@ -192,13 +192,13 @@ NUGET let group = cfg.Groups.[Constants.MainDependencyGroup] group.Packages.Head.Settings.FrameworkRestrictions |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) + |> shouldEqual (FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) let resolved = ResolveWithGraph(cfg,noSha1,VersionsFromGraphAsSeq graph, PackageDetailsFromGraph graph).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() getVersion resolved.[PackageName "NLog"] |> shouldEqual "1.0.1" resolved.[PackageName "NLog"].Settings.FrameworkRestrictions |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) resolved |> LockFileSerializer.serializePackages cfg.Groups.[Constants.MainDependencyGroup].Options diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index a11ea68208..ec76f5705f 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -307,7 +307,7 @@ let ``should parse framework restricted lock file``() = packages.[0].Dependencies |> Set.toList |> List.map (fun (_, _, r) -> r) |> List.item 2 |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) packages.[3].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[3].Name |> shouldEqual (PackageName "LinqBridge") @@ -327,7 +327,7 @@ let ``should parse framework restricted lock file``() = |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))] |> makeOrList |> getExplicitRestriction) packages.[5].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[5].Name |> shouldEqual (PackageName "ReadOnlyCollectionInterfaces") @@ -336,7 +336,7 @@ let ``should parse framework restricted lock file``() = |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))] |> makeOrList |> getExplicitRestriction) let frameworkRestricted' = """NUGET remote: https://www.nuget.org/api/v2 @@ -366,7 +366,7 @@ let ``should parse framework restricted lock file in new syntax``() = packages.[0].Dependencies |> Set.toList |> List.map (fun (_, _, r) -> r) |> List.item 2 |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))) + |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) packages.[3].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[3].Name |> shouldEqual (PackageName "LinqBridge") @@ -390,7 +390,7 @@ let ``should parse framework restricted lock file in new syntax``() = |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))] |> makeOrList |> getExplicitRestriction) packages.[5].Source |> shouldEqual PackageSources.DefaultNuGetSource packages.[5].Name |> shouldEqual (PackageName "ReadOnlyCollectionInterfaces") @@ -403,7 +403,7 @@ let ``should parse framework restricted lock file in new syntax``() = |> getExplicitRestriction |> shouldEqual ([FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V2)) FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4_Client))] |> makeOrList |> getExplicitRestriction) + FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))] |> makeOrList |> getExplicitRestriction) let simpleHTTP = """ HTTP diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index 9cfb4a0efb..c18be23e28 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -105,7 +105,7 @@ let ``can detect explicit dependencies for Math.Numerics``() = LicenseUrl = "http://numerics.mathdotnet.com/docs/License.html" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion Dependencies = - [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), makeOrList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V3_5), DotNetFramework(FrameworkVersion.V4_Client))]] + [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), makeOrList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V3_5), DotNetFramework(FrameworkVersion.V4))]] SourceUrl = fakeUrl } [] @@ -153,7 +153,7 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = dependencies.[44] |> shouldEqual (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 6.0.8"), - makeOrList [FrameworkRestriction.Exactly(WindowsPhoneSilverlight("v8.0")); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))]) + makeOrList [FrameworkRestriction.Exactly(WindowsPhone WindowsPhoneVersion.V8); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))]) [] let ``can ignore unknown frameworks``() = diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index 19623b2b7a..a4a028c76e 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -102,7 +102,7 @@ let ``can detect deps assemblies for RazorEngine``() = Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"RazorEngine.nuspec")).Dependencies |> shouldEqual [PackageName "Microsoft.AspNet.Razor",DependenciesFileParser.parseVersionRequirement("= 2.0.30506.0"), - makeOrList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4_Client), DotNetFramework(FrameworkVersion.V4_5))] + makeOrList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4), DotNetFramework(FrameworkVersion.V4_5))] PackageName "Microsoft.AspNet.Razor",DependenciesFileParser.parseVersionRequirement(">= 3.0.0"), makeOrList [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]] @@ -150,15 +150,15 @@ let ``can detect framework assemblies for Octokit``() = FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5)) - FrameworkRestriction.Exactly(Windows "v4.5")] }] + FrameworkRestriction.Exactly(Windows WindowsVersion.V8)] }] [] let ``can detect framework assemblies for FSharp.Data.SqlEnumProvider``() = //ensureDir() Nuspec.Load(Path.Combine(__SOURCE_DIRECTORY__,"FSharp.Data.SqlEnumProvider.nuspec")).FrameworkAssemblyReferences |> shouldEqual - [{ AssemblyName = "System.Data"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))] } - { AssemblyName = "System.Xml"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))] }] + [{ AssemblyName = "System.Data"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4))] } + { AssemblyName = "System.Xml"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4))] }] [] let ``can detect empty framework assemblies for ReadOnlyCollectionExtensions``() = @@ -226,9 +226,9 @@ let ``can detect framework assemblies for MathNet.Numerics``() = [{ AssemblyName = "System.Numerics" FrameworkRestrictions = makeOrList - [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client)) - FrameworkRestriction.Exactly(Windows("v4.5")) - FrameworkRestriction.Exactly(Silverlight("v5.0")) + [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4)) + FrameworkRestriction.Exactly(Windows WindowsVersion.V8) + FrameworkRestriction.Exactly(Silverlight SilverlightVersion.V5) FrameworkRestriction.Exactly(MonoAndroid) FrameworkRestriction.Exactly(MonoTouch)] }] @@ -240,7 +240,7 @@ let ``can detect dependencies for MathNet.Numerics``() = |> shouldEqual [ PackageName "TaskParallelLibrary", DependenciesFileParser.parseVersionRequirement(">= 1.0.2856.0"), - makeOrList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client))] ] + makeOrList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4))] ] [] let ``can detect dependencies for MathNet.Numerics.FSharp``() = @@ -263,8 +263,8 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 5.0.8"), makeOrList - [FrameworkRestriction.Exactly(WindowsPhoneSilverlight("v8.0")) - FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))]) + [FrameworkRestriction.Exactly(WindowsPhone WindowsPhoneVersion.V8) + FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))]) [] let ``can detect framework assemblies for Microsoft.Framework.Logging``() = diff --git a/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs b/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs index 692588feee..cbfa41db16 100644 --- a/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs @@ -11,8 +11,8 @@ let element x = [] let ``should detect framework version from path``() = - FrameworkDetection.DetectFromPath(@"..\RestSharp\lib\net4\RestSharp.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_Client)) - FrameworkDetection.DetectFromPath(@"..\Rx-Main\lib\net40\Rx.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_Client)) + FrameworkDetection.DetectFromPath(@"..\RestSharp\lib\net4\RestSharp.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4)) + FrameworkDetection.DetectFromPath(@"..\Rx-Main\lib\net40\Rx.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4)) FrameworkDetection.DetectFromPath(@"..\Rx-Main\lib\net45\Rx.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_5)) FrameworkDetection.DetectFromPath(@"..\Rx-Main\lib\net20\Rx.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V2)) FrameworkDetection.DetectFromPath(@"..\Rx-Main\lib\net35\Rx.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V3_5)) @@ -28,16 +28,16 @@ let ``should detect CLR version from path``() = [] let ``should detect client framework version from path``() = - FrameworkDetection.DetectFromPath(@"..\packages\Castle.Core\lib\net40-client\Castle.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_Client)) + FrameworkDetection.DetectFromPath(@"..\packages\Castle.Core\lib\net40-client\Castle.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4)) [] let ``should detect client framework version from Lib path``() = - FrameworkDetection.DetectFromPath(@"..\packages\Castle.Core\Lib\net40-client\Castle.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_Client)) + FrameworkDetection.DetectFromPath(@"..\packages\Castle.Core\Lib\net40-client\Castle.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4)) [] let ``should detect net40-full as net40``() = FrameworkDetection.DetectFromPath(@"..\packages\log4net\lib\net40-full\log4net.dll")|> element |> shouldEqual(DotNetFramework(FrameworkVersion.V4)) - FrameworkDetection.DetectFromPath(@"..\packages\log4net\lib\net40\log4net.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_Client)) + FrameworkDetection.DetectFromPath(@"..\packages\log4net\lib\net40\log4net.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4)) [] let ``should detect net451``() = @@ -45,14 +45,14 @@ let ``should detect net451``() = [] let ``should detect Silverlight version from path``() = - FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl5\RestSharp.Silverlight.dll")|> element |> shouldEqual (Silverlight("v5.0")) - FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4\RestSharp.Silverlight.dll")|> element |> shouldEqual (Silverlight("v4.0")) - FrameworkDetection.DetectFromPath(@"..\..\packages\SpecFlow\lib\sl3\Specflow.Silverlight.dll")|> element |> shouldEqual (Silverlight("v3.0")) + FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl5\RestSharp.Silverlight.dll")|> element |> shouldEqual (Silverlight SilverlightVersion.V5) + FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4\RestSharp.Silverlight.dll")|> element |> shouldEqual (Silverlight SilverlightVersion.V4) + FrameworkDetection.DetectFromPath(@"..\..\packages\SpecFlow\lib\sl3\Specflow.Silverlight.dll")|> element |> shouldEqual (Silverlight SilverlightVersion.V3) [] let ``should detect WindowsPhone version from path``() = - FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp71\RestSharp.WindowsPhone.dll")|> element |> shouldEqual (WindowsPhoneSilverlight("v7.1")) - FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp\TechTalk.SpecFlow.WindowsPhone7.dll")|> element |> shouldEqual (WindowsPhoneSilverlight("v7.1")) + FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp71\RestSharp.WindowsPhone.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_5) + FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp\TechTalk.SpecFlow.WindowsPhone7.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_5) [] let ``should detect framework version from uppercase path``() = @@ -73,6 +73,6 @@ let ``should detect with spaces``() = [] let ``should detect 35, 40 and 45``() = FrameworkDetection.DetectFromPath(@"..\packages\FSharpx.Core\lib\35\FSharp.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V3_5)) - FrameworkDetection.DetectFromPath(@"..\packages\FSharpx.Core\lib\40\FSharp.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_Client)) + FrameworkDetection.DetectFromPath(@"..\packages\FSharpx.Core\lib\40\FSharp.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4)) FrameworkDetection.DetectFromPath(@"..\packages\FSharpx.Core\lib\45\FSharp.Core.dll")|> element |> shouldEqual (DotNetFramework(FrameworkVersion.V4_5)) \ No newline at end of file diff --git a/tests/Paket.Tests/ProjectFile/OutputSpecs.fs b/tests/Paket.Tests/ProjectFile/OutputSpecs.fs index ffc08e0357..555d56994f 100644 --- a/tests/Paket.Tests/ProjectFile/OutputSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/OutputSpecs.fs @@ -36,7 +36,7 @@ let ``should detect target framework for Project1 proj file``() = let ``should detect target framework for Project2 proj file``() = ensureDir () ProjectFile.TryLoad("./ProjectFile/TestData/Project2.fsprojtest").Value.GetTargetProfile() - |> shouldEqual (SinglePlatform(DotNetFramework(FrameworkVersion.V4_Client))) + |> shouldEqual (SinglePlatform(DotNetFramework(FrameworkVersion.V4))) [] let ``should detect output path for proj file`` diff --git a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs index d11024a365..29ec7f4ae2 100644 --- a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs @@ -12,19 +12,19 @@ let TestData: obj[][] = // expected TargetProfile.ToString // expected TargetFramework [|"Project2.fsprojtest"; - (SinglePlatform(DotNetFramework FrameworkVersion.V4_Client)); + (SinglePlatform(DotNetFramework FrameworkVersion.V4)); "net40"; - (Some(DotNetFramework FrameworkVersion.V4_Client))|]; + (Some(DotNetFramework FrameworkVersion.V4))|]; [|"Empty.fsprojtest"; (SinglePlatform(DotNetFramework FrameworkVersion.V4)); "net40-full"; (Some(DotNetFramework FrameworkVersion.V4))|]; [|"NewSilverlightClassLibrary.csprojtest"; - (SinglePlatform(Silverlight("v5.0"))); + (SinglePlatform(Silverlight SilverlightVersion.V5)); "sl50"; - (Some(Silverlight "v5.0"))|]; + (Some(Silverlight SilverlightVersion.V5))|]; [|"FSharp.Core.Fluent-3.1.fsprojtest"; - (PortableProfile("Profile259", [ DotNetFramework FrameworkVersion.V4_5; Windows "v4.5"; WindowsPhoneSilverlight "v8.0"; WindowsPhoneApp "v8.1" ])); + (PortableProfile("Profile259", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ])); "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1"; (Some(DotNetFramework FrameworkVersion.V4_5))|]; |] diff --git a/tests/Paket.Tests/TestHelpers.fs b/tests/Paket.Tests/TestHelpers.fs index 49affdf5b6..6c21115c3c 100644 --- a/tests/Paket.Tests/TestHelpers.fs +++ b/tests/Paket.Tests/TestHelpers.fs @@ -16,7 +16,7 @@ let makeOrList (l:_ list) = let getPortableRestriction s = let pf = PlatformMatching.extractPlatforms s - FrameworkRestriction.Portable(s, pf.Platforms) + FrameworkRestriction.AtLeastPortable(s, pf.Platforms) type GraphDependency = string * VersionRequirement * FrameworkRestrictions diff --git a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs index 3df797e226..7e21b6aa00 100644 --- a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs +++ b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs @@ -30,7 +30,7 @@ let ``should optimize 2 restriction set with only exactly``() = [] let ``should optimize 2 restriction set with only exactly and client framework``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))) + [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] @@ -49,11 +49,11 @@ let ``should optimize 2 restriction sets with between``() = [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client)))] + PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4)))] let expected = [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_Client)))] + PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4)))] original |> optimizeDependencies @@ -226,7 +226,7 @@ let ``should optimize real world restrictions``() = let ``should optimize real world restrictions 2``() = let original = [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client))) + PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))) PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_6)))] @@ -235,7 +235,7 @@ let ``should optimize real world restrictions 2``() = [PackageName("P1"), VersionRequirement.AllReleases, makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2)) - FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_Client)) + FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4)) FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5)) FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1)) FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_6))]] @@ -246,10 +246,10 @@ let ``should optimize real world restrictions 2``() = [] let ``should optimize real world restrictions 3``() = let original = - [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_Client)) + [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4)) FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1))] - let expected = FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_Client)) + let expected = FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4)) let result = makeOrList original |> getExplicitRestriction result |> shouldEqual expected diff --git a/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs b/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs index f43de1c97b..8810f97ad2 100644 --- a/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs +++ b/tests/Paket.Tests/Versioning/FrameworkCompatibilitySpecs.fs @@ -30,12 +30,12 @@ open Paket.Requirements [] let ``net46 should be compatible with netstandard13``() = - (DotNetFramework FrameworkVersion.V4_6).IsAtLeast (DotNetStandard DotNetStandardVersion.V1_3) + (SinglePlatform (DotNetFramework FrameworkVersion.V4_6)).IsAtLeast (SinglePlatform (DotNetStandard DotNetStandardVersion.V1_3)) |> shouldEqual true - (DotNetStandard DotNetStandardVersion.V1_3).IsSupportedBy (DotNetFramework FrameworkVersion.V4_6) + (SinglePlatform (DotNetStandard DotNetStandardVersion.V1_3)).IsSupportedBy (SinglePlatform (DotNetFramework FrameworkVersion.V4_6)) |> shouldEqual true - (DotNetStandard DotNetStandardVersion.V1_3).IsSmallerThan (DotNetFramework FrameworkVersion.V4_6) + (SinglePlatform (DotNetStandard DotNetStandardVersion.V1_3)).IsSmallerThan (SinglePlatform (DotNetFramework FrameworkVersion.V4_6)) |> shouldEqual true diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index 9a14b621e6..4f093bc9d5 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -4,6 +4,21 @@ open Paket open FsUnit open NUnit.Framework open Paket.Requirements +[] +let ``PortableProfile supports PortableProfiles but it is not recursive``() = + let portableProfiles = + KnownTargetProfiles.AllPortableProfiles + |> List.map PortableProfile + let getSupported (p:TargetProfile) = p.SupportedPlatforms + let supportTree = () + //Seq.initInfinite (fun _ -> 0) + //|> Seq.fold (fun (lastItems) _ -> () + // ) portableProfiles + + + () + + [] let ``PlatformMatching works with portable ``() = // portable-net40-sl4 @@ -29,13 +44,13 @@ let ``Simplify || (&& (< net40) (< net35)) (&& (< net40) (>= net35)) (>= net40)) // Test simplify || (&& (< net40) (< net35)) (&& (< net40) (>= net35)) (>= net40)) let smaller = (FrameworkRestriction.And[ - FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client) + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4) FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V3_5)]) let between = (FrameworkRestriction.And[ - FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client) + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4) FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5)]) - let rest = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client) + let rest = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4) let combined = FrameworkRestriction.Or [ smaller ; between; rest ] combined @@ -59,11 +74,11 @@ let ``combineOr can simplify the NoRestriction set``() = [ FrameworkRestriction.And [ FrameworkRestriction.NoRestriction FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V3_5)] - FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client)] + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4)] FrameworkRestriction.And [FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V3_5) - FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_Client)]]) - let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_Client) + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4)]]) + let right = FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4) FrameworkRestriction.combineRestrictionsWithOr left right |> shouldEqual FrameworkRestriction.NoRestriction diff --git a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs index bef947a30b..b0c38a6cf3 100644 --- a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs @@ -9,18 +9,7 @@ let dotnet x = SinglePlatform(DotNetFramework(x)) module TestTargetProfiles = let DotNetFrameworkVersions = - [FrameworkVersion.V1 - FrameworkVersion.V1_1 - FrameworkVersion.V2 - FrameworkVersion.V3 - FrameworkVersion.V3_5 - FrameworkVersion.V4_Client - FrameworkVersion.V4 - FrameworkVersion.V4_5 - FrameworkVersion.V4_5_1 - FrameworkVersion.V4_5_2 - FrameworkVersion.V4_5_3 - FrameworkVersion.V4_6] + KnownTargetProfiles.DotNetFrameworkVersions let DotNetFrameworkProfiles = DotNetFrameworkVersions |> List.map dotnet @@ -34,19 +23,19 @@ module TestTargetProfiles = let DotNetUnityProfiles = DotNetUnityVersions |> List.map (DotNetUnity >> SinglePlatform) let WindowsProfiles = - [SinglePlatform(Windows "v4.5") - SinglePlatform(Windows "v4.5.1")] + [SinglePlatform(Windows WindowsVersion.V8) + SinglePlatform(Windows WindowsVersion.V8_1)] let SilverlightProfiles = - [SinglePlatform(Silverlight "v3.0") - SinglePlatform(Silverlight "v4.0") - SinglePlatform(Silverlight "v5.0")] + [SinglePlatform(Silverlight SilverlightVersion.V3) + SinglePlatform(Silverlight SilverlightVersion.V4) + SinglePlatform(Silverlight SilverlightVersion.V5)] let WindowsPhoneSilverlightProfiles = - [SinglePlatform(WindowsPhoneSilverlight "v7.0") - SinglePlatform(WindowsPhoneSilverlight "v7.1") - SinglePlatform(WindowsPhoneSilverlight "v8.0") - SinglePlatform(WindowsPhoneSilverlight "v8.1")] + [SinglePlatform(WindowsPhone WindowsPhoneVersion.V7) + SinglePlatform(WindowsPhone WindowsPhoneVersion.V7_5) + SinglePlatform(WindowsPhone WindowsPhoneVersion.V8) + SinglePlatform(WindowsPhone WindowsPhoneVersion.V8_1)] let AllProfiles = DotNetFrameworkProfiles @ @@ -58,7 +47,7 @@ module TestTargetProfiles = SinglePlatform(MonoTouch) SinglePlatform(XamariniOS) SinglePlatform(XamarinMac) - SinglePlatform(WindowsPhoneApp "v8.1") + SinglePlatform(WindowsPhoneApp WindowsPhoneAppVersion.V8_1) ] [] @@ -87,7 +76,7 @@ let ``>= net40 < net451 contains 4.0 and 4.5`` () = [] let ``>= sl30 contains all but only silverlight versions`` () = - let restrictions = FrameworkRestriction.AtLeast(Silverlight "v3.0") + let restrictions = FrameworkRestriction.AtLeast(Silverlight SilverlightVersion.V3) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles restricted |> shouldEqual TestTargetProfiles.SilverlightProfiles \ No newline at end of file diff --git a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs index ae57f26315..53fb78f878 100644 --- a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs @@ -26,8 +26,8 @@ let ``should filter >= net40 and net45``() = [] let ``should filter >= net40 and net40``() = - let l1 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))) - let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_Client))) + let l1 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4))) + let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 |> shouldEqual l1 From c91e856a1960830b8b216cd9df7dc93fa36846e7 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Sun, 21 May 2017 19:24:11 +0200 Subject: [PATCH 10/47] refactor handling of portable profiles --- src/Paket.Core/Installation/UpdateProcess.fs | 5 +- .../PaketConfigFiles/DependenciesFile.fs | 4 +- .../PaketConfigFiles/DependencyCache.fs | 2 +- .../PaketConfigFiles/InstallModel.fs | 2 +- .../PaketConfigFiles/ProjectFile.fs | 28 +- src/Paket.Core/PublicAPI.fs | 2 +- .../Versioning/FrameworkHandling.fs | 420 ++++++++++++------ src/Paket.Core/Versioning/PlatformMatching.fs | 6 +- src/Paket.Core/Versioning/Requirements.fs | 7 +- .../ProjectFile/TargetFrameworkSpecs.fs | 15 +- 10 files changed, 308 insertions(+), 183 deletions(-) diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs index dcae2d0e40..d505b4c90a 100644 --- a/src/Paket.Core/Installation/UpdateProcess.fs +++ b/src/Paket.Core/Installation/UpdateProcess.fs @@ -168,9 +168,8 @@ let detectProjectFrameworksForDependenciesFile (dependenciesFile:DependenciesFil let rawRestrictions = RestoreProcess.findAllReferencesFiles root |> returnOrFail |> List.map (fun (p,_) -> - match p.GetTargetFramework() with - | Some fw -> Requirements.FrameworkRestriction.Exactly fw - | None -> failwithf "Could not detect target framework for project %s" p.FileName) + p.GetTargetProfile() + |> Requirements.FrameworkRestriction.ExactlyPlatform) |> List.distinct if rawRestrictions.IsEmpty then Paket.Requirements.FrameworkRestriction.NoRestriction else rawRestrictions |> Seq.fold Paket.Requirements.FrameworkRestriction.combineRestrictionsWithOr Paket.Requirements.FrameworkRestriction.EmptySet) diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index 6430cac210..12327747fc 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -142,8 +142,8 @@ type DependenciesFile(fileName,groups:Map, textRepr let lockFile = dependenciesFile.FindLockfile() let dir = (lockFile : FileInfo).DirectoryName let projects = ProjectFile.FindAllProjects dir - let frameworks = projects |> Array.choose ProjectFile.getTargetFramework |> Array.distinct - let restrictions = frameworks |> Array.map FrameworkRestriction.Exactly + let frameworks = projects |> Array.map ProjectFile.getTargetProfile |> Array.distinct + let restrictions = frameworks |> Array.map FrameworkRestriction.ExactlyPlatform if restrictions |> Array.isEmpty then FrameworkRestriction.NoRestriction else restrictions |> Array.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet ) diff --git a/src/Paket.Core/PaketConfigFiles/DependencyCache.fs b/src/Paket.Core/PaketConfigFiles/DependencyCache.fs index bcba372089..61fac1d20a 100644 --- a/src/Paket.Core/PaketConfigFiles/DependencyCache.fs +++ b/src/Paket.Core/PaketConfigFiles/DependencyCache.fs @@ -113,7 +113,7 @@ type DependencyCache (dependencyFile:DependenciesFile, lockFile:LockFile) = match tryGet (group,pack.Name) installModelCache with | None -> () | Some model -> - model.GetLibReferenceFiles framework |> Seq.iter (libs.Add >> ignore) + model.GetLibReferenceFiles (SinglePlatform framework) |> Seq.iter (libs.Add >> ignore) model.GetAllLegacyFrameworkReferences ()|> Seq.iter (sysLibs.Add >> ignore) ) diff --git a/src/Paket.Core/PaketConfigFiles/InstallModel.fs b/src/Paket.Core/PaketConfigFiles/InstallModel.fs index aa913d1575..216b493c50 100644 --- a/src/Paket.Core/PaketConfigFiles/InstallModel.fs +++ b/src/Paket.Core/PaketConfigFiles/InstallModel.fs @@ -460,7 +460,7 @@ module InstallModel = /// This is for library references, which at the same time can be used for references (old world - pre dotnetcore) let getLegacyPlatformReferences frameworkIdentifier installModel = - getLegacyReferences (SinglePlatform frameworkIdentifier) installModel + getLegacyReferences frameworkIdentifier installModel let isEmpty (lib: FrameworkFolder> list) = lib diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs index eda0bfe8f2..ba3a589aff 100644 --- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs @@ -992,12 +992,6 @@ module ProjectFile = | None -> defaultResult | Some x -> SinglePlatform x - let getTargetFramework (project:ProjectFile) = - match getTargetProfile project with - | SinglePlatform x -> Some x - | PortableProfile (_, x::_) -> Some x - | _ -> None - let updateReferences rootPath (completeModel: Map) @@ -1051,17 +1045,15 @@ module ProjectFile = .RemoveIfCompletelyEmpty() if directPackages.ContainsKey kv.Key then - match getTargetFramework project with - | Some targetFramework -> - if isTargetMatchingRestrictions(restrictionList,SinglePlatform targetFramework) then - if projectModel.GetLibReferenceFiles targetFramework |> Seq.isEmpty then - let libReferences = - projectModel.GetAllLegacyReferences() - - if not (Seq.isEmpty libReferences) then - traceWarnfn "Package %O contains libraries, but not for the selected TargetFramework %O in project %s." - (snd kv.Key) targetFramework project.FileName - | _ -> () + let targetProfile = getTargetProfile project + if isTargetMatchingRestrictions(restrictionList,targetProfile) then + if projectModel.GetLibReferenceFiles targetProfile |> Seq.isEmpty then + let libReferences = + projectModel.GetAllLegacyReferences() + + if not (Seq.isEmpty libReferences) then + traceWarnfn "Package %O contains libraries, but not for the selected TargetFramework %O in project %s." + (snd kv.Key) targetProfile project.FileName let importTargets = defaultArg installSettings.ImportTargets true @@ -1500,8 +1492,6 @@ type ProjectFile with member this.GetTargetFrameworkIdentifier () = ProjectFile.getTargetFrameworkIdentifier this - member this.GetTargetFramework () = ProjectFile.getTargetFramework this - member this.GetTargetFrameworkProfile () = ProjectFile.getTargetFrameworkProfile this member this.GetTargetProfile () = ProjectFile.getTargetProfile this diff --git a/src/Paket.Core/PublicAPI.fs b/src/Paket.Core/PublicAPI.fs index 5402ff9c28..9d3155a627 100644 --- a/src/Paket.Core/PublicAPI.fs +++ b/src/Paket.Core/PublicAPI.fs @@ -463,7 +463,7 @@ type Dependencies(dependenciesFileName: string) = InstallModel.CreateFromLibs(packageName, resolvedPackage.Version, Paket.Requirements.FrameworkRestriction.NoRestriction, files, [], [], nuspec) /// Returns all libraries for the given package and framework. - member this.GetLibraries(groupName,packageName,frameworkIdentifier:FrameworkIdentifier) = + member this.GetLibraries(groupName,packageName,frameworkIdentifier:TargetProfile) = this .GetInstalledPackageModel(groupName,packageName) .GetLibReferences(frameworkIdentifier) diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index a94ea0b023..f04d08bc98 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -351,7 +351,7 @@ type FrameworkIdentifier = | Native(_) -> [ ] | XamariniOS -> [ ] | XamarinMac -> [ ] - | UAP UAPVersion.V10 -> [ ] + | UAP UAPVersion.V10 -> [ Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1; DotNetStandard DotNetStandardVersion.V1_4 ] | DotNetFramework FrameworkVersion.V1 -> [ ] | DotNetFramework FrameworkVersion.V1_1 -> [ DotNetFramework FrameworkVersion.V1 ] | DotNetFramework FrameworkVersion.V2 -> [ DotNetFramework FrameworkVersion.V1_1 ] @@ -516,50 +516,162 @@ module FrameworkDetection = else Extract(path.Substring(startPos + 4, endPos - startPos - 5)) + +type PortableProfileType = + | UnsupportedProfile of FrameworkIdentifier list + | Profile2 + | Profile3 + | Profile4 + | Profile5 + | Profile6 + | Profile7 + | Profile14 + | Profile18 + | Profile19 + | Profile23 + | Profile24 + | Profile31 + | Profile32 + | Profile36 + | Profile37 + | Profile41 + | Profile42 + | Profile44 + | Profile46 + | Profile47 + | Profile49 + | Profile78 + | Profile84 + | Profile88 + | Profile92 + | Profile95 + | Profile96 + | Profile102 + | Profile104 + | Profile111 + | Profile136 + | Profile143 + | Profile147 + | Profile151 + | Profile154 + | Profile157 + | Profile158 + | Profile225 + | Profile240 + | Profile255 + | Profile259 + | Profile328 + | Profile336 + | Profile344 + member x.ProfileName = + match x with + | UnsupportedProfile fws -> x.FolderName + | Profile2 -> "Profile2" + | Profile3 -> "Profile3" + | Profile4 -> "Profile4" + | Profile5 -> "Profile5" + | Profile6 -> "Profile6" + | Profile7 -> "Profile7" + | Profile14 -> "Profile14" + | Profile18 -> "Profile18" + | Profile19 -> "Profile19" + | Profile23 -> "Profile23" + | Profile24 -> "Profile24" + | Profile31 -> "Profile31" + | Profile32 -> "Profile32" + | Profile36 -> "Profile36" + | Profile37 -> "Profile37" + | Profile41 -> "Profile41" + | Profile42 -> "Profile42" + | Profile44 -> "Profile44" + | Profile46 -> "Profile46" + | Profile47 -> "Profile47" + | Profile49 -> "Profile49" + | Profile78 -> "Profile78" + | Profile84 -> "Profile84" + | Profile88 -> "Profile88" + | Profile92 -> "Profile92" + | Profile95 -> "Profile95" + | Profile96 -> "Profile96" + | Profile102 -> "Profile102" + | Profile104 -> "Profile104" + | Profile111 -> "Profile111" + | Profile136 -> "Profile136" + | Profile143 -> "Profile143" + | Profile147 -> "Profile147" + | Profile151 -> "Profile151" + | Profile154 -> "Profile154" + | Profile157 -> "Profile157" + | Profile158 -> "Profile158" + | Profile225 -> "Profile225" + | Profile240 -> "Profile240" + | Profile255 -> "Profile255" + | Profile259 -> "Profile259" + | Profile328 -> "Profile328" + | Profile336 -> "Profile336" + | Profile344 -> "Profile344" + + member x.Frameworks = + // http://nugettoolsdev.azurewebsites.net/4.0.0/parse-framework?framework=.NETPortable%2CVersion%3Dv0.0%2CProfile%3DProfile3 + match x with + | UnsupportedProfile fws -> fws + | Profile2 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ] + | Profile3 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4 ] + | Profile4 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ] + | Profile5 -> [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8 ] + | Profile6 -> [ DotNetFramework FrameworkVersion.V4_0_3; Windows WindowsVersion.V8 ] + | Profile7 -> [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8 ] + | Profile14 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5 ] + | Profile18 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4 ] + | Profile19 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5 ] + | Profile23 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4 ] + | Profile24 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5 ] + | Profile31 -> [ Windows WindowsVersion.V8_1; WindowsPhone WindowsPhoneVersion.V8_1 ] + | Profile32 -> [ Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile36 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile37 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ] + | Profile41 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8 ] + | Profile42 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ] + | Profile44 -> [ DotNetFramework FrameworkVersion.V4_5_1; Windows WindowsVersion.V8_1 ] + | Profile46 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8 ] + | Profile47 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ] + | Profile49 -> [ DotNetFramework FrameworkVersion.V4_5; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile78 -> [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile84 -> [ WindowsPhone WindowsPhoneVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile88 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ] + | Profile92 -> [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile95 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ] + | Profile96 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ] + | Profile102 -> [ DotNetFramework FrameworkVersion.V4_0_3; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile104 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ] + | Profile111 -> [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile136 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile143 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile147 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile151 -> [ DotNetFramework FrameworkVersion.V4_5_1; Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile154 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile157 -> [ Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1; WindowsPhone WindowsPhoneVersion.V8_1 ] + | Profile158 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ] + | Profile225 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile240 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile255 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile259 -> [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile328 -> [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile336 -> [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + | Profile344 -> [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + member x.FolderName = + "portable-" + + String.Join ("+", + x.Frameworks + |> List.sort + |> List.map (fun fw -> fw.ToString())) type TargetProfile = | SinglePlatform of FrameworkIdentifier - | PortableProfile of string * FrameworkIdentifier list + | PortableProfile of PortableProfileType override this.ToString() = match this with | SinglePlatform x -> x.ToString() - | PortableProfile(name,fws) -> - "portable-" + - String.Join ("+", - fws - |> List.sort - |> List.map (fun fw -> fw.ToString())) - //match name with - //| "Profile5" -> "portable-net4+netcore45+MonoAndroid1+MonoTouch1" - //| "Profile6" -> "portable-net403+netcore45+MonoAndroid1+MonoTouch1" - //| "Profile7" -> "portable-net45+netcore45+MonoAndroid1+MonoTouch1" - //| "Profile14" -> "portable-net4+sl5+MonoAndroid1+MonoTouch1" - //| "Profile19" -> "portable-net403+sl5+MonoAndroid1+MonoTouch1" - //| "Profile24" -> "portable-net45+sl5+MonoAndroid1+MonoTouch1" - //| "Profile31" -> "portable-netcore451+wp81" - //| "Profile32" -> "portable-netcore451+wpa81" - //| "Profile37" -> "portable-net4+sl5+netcore45+MonoAndroid1+MonoTouch1" - //| "Profile42" -> "portable-net403+sl5+netcore45+MonoAndroid1+MonoTouch1" - //| "Profile44" -> "portable-net451+netcore451" - //| "Profile47" -> "portable-net45+sl5+netcore45+MonoAndroid1+MonoTouch1" - //| "Profile49" -> "portable-net45+wp8+MonoAndroid1+MonoTouch1" - //| "Profile78" -> "portable-net45+netcore45+wp8+MonoAndroid1+MonoTouch1" - //| "Profile84" -> "portable-wpa81+wp81" - //| "Profile92" -> "portable-net4+netcore45+wpa81+MonoAndroid1+MonoTouch1" - //| "Profile102" -> "portable-net403+netcore45+wpa81+MonoAndroid1+MonoTouch1" - //| "Profile111" -> "portable-net45+netcore45+wpa81+MonoAndroid1+MonoTouch1" - //| "Profile136" -> "portable-net4+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" - //| "Profile147" -> "portable-net403+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" - //| "Profile151" -> "portable-net451+netcore451+wpa81" - //| "Profile157" -> "portable-netcore451+wpa81+wp81" - //| "Profile158" -> "portable-net45+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" - //| "Profile225" -> "portable-net4+sl5+netcore45+wpa81+MonoAndroid1+MonoTouch1" - //| "Profile240" -> "portable-net403+sl5+netcore45+wpa81" - //| "Profile255" -> "portable-net45+sl5+netcore45+wpa81+MonoAndroid1+MonoTouch1" - //| "Profile259" -> "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - //| "Profile328" -> "portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - //| "Profile336" -> "portable-net403+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - //| "Profile344" -> "portable-net45+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" - //| _ -> "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" // Use Portable259 as default + | PortableProfile p -> p.FolderName module KnownTargetProfiles = let DotNetFrameworkVersions = [ @@ -660,67 +772,52 @@ module KnownTargetProfiles = WindowsPhoneVersions |> List.map (WindowsPhone >> SinglePlatform) - let portableStandards p = - match p with - | "portable-net45+win8" -> [DotNetStandardVersion.V1_1] - | "portable-win81+wp81" -> [DotNetStandardVersion.V1_0] - | "portable-win81+wpa81" -> [DotNetStandardVersion.V1_2] - | "portable-net451+win81" -> [DotNetStandardVersion.V1_2] - | "portable-net45+wp8" -> [DotNetStandardVersion.V1_0] - | "portable-net45+win8+wp8" -> [DotNetStandardVersion.V1_0] - | "portable-wp81+wpa81" -> [DotNetStandardVersion.V1_0] - | "portable-net45+win8+wpa81" -> [DotNetStandardVersion.V1_1] - | "portable-net451+win81+wpa81" -> [DotNetStandardVersion.V1_2] - | "portable-win81+wp81+wpa81" -> [DotNetStandardVersion.V1_0] - | "portable-net45+win8+wpa81+wp8" -> [DotNetStandardVersion.V1_0] - | _ -> [] - // http://nugettoolsdev.azurewebsites.net/4.0.0/parse-framework?framework=.NETPortable%2CVersion%3Dv0.0%2CProfile%3DProfile3 let AllPortableProfiles = - [("Profile2", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ]) - ("Profile3", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4 ]) - ("Profile4", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ]) - ("Profile5", [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8 ]) - ("Profile6", [ DotNetFramework FrameworkVersion.V4_0_3; Windows WindowsVersion.V8 ]) - ("Profile7" , [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8 ]) - ("Profile14", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5 ]) - ("Profile18", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4 ]) - ("Profile19", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5 ]) - ("Profile23", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4 ]) - ("Profile24", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5 ]) - ("Profile31", [ Windows WindowsVersion.V8_1; WindowsPhone WindowsPhoneVersion.V8_1 ]) - ("Profile32", [ Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile36", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile37", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ]) - ("Profile41", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8 ]) - ("Profile42", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ]) - ("Profile44", [ DotNetFramework FrameworkVersion.V4_5_1; Windows WindowsVersion.V8_1 ]) - ("Profile46", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8 ]) - ("Profile47", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8 ]) - ("Profile49", [ DotNetFramework FrameworkVersion.V4_5; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile78", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile84", [ WindowsPhone WindowsPhoneVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile88", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ]) - ("Profile92", [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile95", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7 ]) - ("Profile96", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ]) - ("Profile102", [ DotNetFramework FrameworkVersion.V4_0_3; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile104", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V7_5 ]) - ("Profile111", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile136", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile143", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile147", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile151", [ DotNetFramework FrameworkVersion.V4_5_1; Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile154", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V4; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile157", [ Windows WindowsVersion.V8_1; WindowsPhoneApp WindowsPhoneAppVersion.V8_1; WindowsPhone WindowsPhoneVersion.V8_1 ]) - ("Profile158", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8 ]) - ("Profile225", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile240", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile255", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile259", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile328", [ DotNetFramework FrameworkVersion.V4; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile336", [ DotNetFramework FrameworkVersion.V4_0_3; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) - ("Profile344", [ DotNetFramework FrameworkVersion.V4_5; Silverlight SilverlightVersion.V5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ]) ] + [PortableProfileType.Profile2 + PortableProfileType.Profile3 + PortableProfileType.Profile4 + PortableProfileType.Profile5 + PortableProfileType.Profile6 + PortableProfileType.Profile7 + PortableProfileType.Profile14 + PortableProfileType.Profile18 + PortableProfileType.Profile19 + PortableProfileType.Profile23 + PortableProfileType.Profile24 + PortableProfileType.Profile31 + PortableProfileType.Profile32 + PortableProfileType.Profile36 + PortableProfileType.Profile37 + PortableProfileType.Profile41 + PortableProfileType.Profile42 + PortableProfileType.Profile44 + PortableProfileType.Profile46 + PortableProfileType.Profile47 + PortableProfileType.Profile49 + PortableProfileType.Profile78 + PortableProfileType.Profile84 + PortableProfileType.Profile88 + PortableProfileType.Profile92 + PortableProfileType.Profile95 + PortableProfileType.Profile96 + PortableProfileType.Profile102 + PortableProfileType.Profile104 + PortableProfileType.Profile111 + PortableProfileType.Profile136 + PortableProfileType.Profile143 + PortableProfileType.Profile147 + PortableProfileType.Profile151 + PortableProfileType.Profile154 + PortableProfileType.Profile157 + PortableProfileType.Profile158 + PortableProfileType.Profile225 + PortableProfileType.Profile240 + PortableProfileType.Profile255 + PortableProfileType.Profile259 + PortableProfileType.Profile328 + PortableProfileType.Profile336 + PortableProfileType.Profile344 ] let AllDotNetProfiles = DotNetFrameworkProfiles @ @@ -766,11 +863,38 @@ module KnownTargetProfiles = let FindPortableProfile name = AllProfiles |> List.pick (function - | PortableProfile(n, _) as p when n = name -> Some p + | PortableProfile p when p.ProfileName = name -> Some (PortableProfile p) | _ -> None) type TargetProfile with + static member FindPortable (fws) = + let minimal = + fws + |> List.filter (function + | MonoTouch + | DNXCore _ + | UAP _ + | MonoAndroid -> false + | DotNetCore _ + | DotNetStandard _ -> failwithf "Unexpected famework while trying to resolve PCL Profile" + | _ -> true) + let firstMatch = + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun p -> + let otherFws = p.Frameworks + minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) + |> List.sortBy (fun p -> p.Frameworks.Length) + |> List.tryHead + match firstMatch with + | Some p -> PortableProfile p + | None -> +#if DEBUG + failwithf "Could not find pcl profile" +#else + PortableProfile (UnsupportedProfile fws) +#endif + // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list /// true when x is supported by y, for example netstandard15 is supported by netcore10 member x.IsSupportedBy y = @@ -833,62 +957,66 @@ type TargetProfile with // See https://docs.microsoft.com/en-us/dotnet/articles/standard/library match tf with | DotNetStandard DotNetStandardVersion.V1_0 -> - [ "Profile31" - "Profile49" - "Profile78" - "Profile84" - "Profile157" - "Profile259" ] + [ Profile31 + Profile49 + Profile78 + Profile84 + Profile157 + Profile259 ] | DotNetStandard DotNetStandardVersion.V1_1 -> - [ "Profile7" - "Profile111" ] + [ Profile7 + Profile111 ] | DotNetStandard DotNetStandardVersion.V1_2 -> - [ "Profile32" - "Profile44" - "Profile151" ] + [ Profile32 + Profile44 + Profile151 ] | MonoTouch | MonoAndroid | XamariniOS | XamarinMac -> // http://danrigby.com/2014/05/14/supported-pcl-profiles-xamarin-for-visual-studio-2/ - [ "Profile5" - "Profile6" - "Profile7" - "Profile14" - "Profile19" - "Profile24" - "Profile37" - "Profile42" - "Profile44" - "Profile47" - "Profile49" - "Profile78" - "Profile92" - "Profile102" - "Profile111" - "Profile136" - "Profile147" - "Profile151" - "Profile158" - "Profile225" - "Profile259" - "Profile328" - "Profile336" - "Profile344" ] + [ Profile5 + Profile6 + Profile7 + Profile14 + Profile19 + Profile24 + Profile37 + Profile42 + Profile44 + Profile47 + Profile49 + Profile78 + Profile92 + Profile102 + Profile111 + Profile136 + Profile147 + Profile151 + Profile158 + Profile225 + Profile259 + Profile328 + Profile336 + Profile344 ] | _ -> // Regular supported logic is to enumerate all profiles and select compatible ones - KnownTargetProfiles.AllPortableProfiles - |> List.filter (fun (_, fws) -> - // Portable profile is compatible as soon as it contains a fw which supports us - fws - |> List.exists (fun fw -> fw.RawSupportedPlatformsTransitive |> Seq.exists ((=) tf))) - |> List.map fst - |> List.map KnownTargetProfiles.FindPortableProfile + let supported = tf.RawSupportedPlatformsTransitive + let profiles = + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun (p) -> + // Portable profile is compatible as soon as it contains a fw which is supported by us + p.Frameworks + |> List.exists (fun fw -> supported |> Seq.exists ((=) fw))) + profiles + |> List.map PortableProfile rawSupported @ profilesSupported - | PortableProfile (name, tfs) -> + | PortableProfile p -> + let name, tfs = p.ProfileName, p.Frameworks KnownTargetProfiles.AllPortableProfiles - |> List.filter (fun (otherName, _) -> otherName <> name) - |> List.filter (fun (otherName, fws) -> + |> List.filter (fun p -> p.ProfileName <> name) + |> List.filter (fun other -> + let otherName, fws = other.ProfileName, other.Frameworks let weSupport = tfs |> List.collect (fun tf -> tf.RawSupportedPlatformsTransitive) @@ -904,7 +1032,7 @@ type TargetProfile with let isReverseSupported = weSupport |> Seq.forall (fun fw -> otherSupport |> List.exists ((=) fw)) - let isSupportedI = (PortableProfile (otherName ,fws)).ToString() < x.ToString() + let isSupportedI = other < p let result = if isSupported && isReverseSupported then // Some profiles are identical, which means we need to watch out to get a nice tree here diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index a096991445..ae72e88566 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -72,14 +72,14 @@ let getPathPenalty = | [] -> handleEmpty() | [ h ] -> getPlatformPenalty(platform,SinglePlatform h) | _ -> - getPlatformPenalty(platform, PortableProfile(path.Name, path.Platforms))) + getPlatformPenalty(platform, TargetProfile.FindPortable path.Platforms)) [] let getFrameworkPathPenalty fr path = match fr with | [ h ] -> getPathPenalty (path, SinglePlatform h) | _ -> - getPathPenalty (path, PortableProfile("unknown", fr)) + getPathPenalty (path, TargetProfile.FindPortable fr) type PathPenalty = (ParsedPlatformPath * int) @@ -255,7 +255,7 @@ let getTargetCondition (target:TargetProfile) = | Native(NoBuildMode,NoPlatform) -> "true", "" | Native(NoBuildMode,bits) -> (sprintf "'$(Platform)'=='%s'" bits.AsString), "" | Native(profile,bits) -> (sprintf "'$(Configuration)|$(Platform)'=='%s|%s'" profile.AsString bits.AsString), "" - | PortableProfile(name, _) -> sprintf "$(TargetFrameworkProfile) == '%O'" name,"" + | PortableProfile p -> sprintf "$(TargetFrameworkProfile) == '%O'" p.ProfileName,"" let getCondition (referenceCondition:string option) (allTargets: TargetProfile list list) (targets : TargetProfile list) = let inline CheckIfFullyInGroup typeName matchF (processed,targets) = diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index a3e8178fbc..051f11477e 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -166,9 +166,10 @@ module FrameworkRestriction = let EmptySet = { OrFormulas = [] } // false let NoRestriction = { OrFormulas = [ { Literals = [] } ] } // true let AtLeastPlatform pf = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (AtLeastL pf) ] } ] } - let Exactly id = AtLeastPlatform (SinglePlatform id) - let AtLeastPortable (name, fws)= AtLeastPlatform (PortableProfile (name, fws)) - let AtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (AtLeastL (SinglePlatform id)) ] } ] } + let ExactlyPlatform pf = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (ExactlyL pf) ] } ] } + let Exactly id = ExactlyPlatform (SinglePlatform id) + let AtLeastPortable (name, fws)= AtLeastPlatform (TargetProfile.FindPortable fws) + let AtLeast id = AtLeastPlatform (SinglePlatform id) let NotAtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromNegatedLiteral (AtLeastL (SinglePlatform id)) ] } ] } let private simplify (fr:FrameworkRestriction) = diff --git a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs index 29ec7f4ae2..82e2216b80 100644 --- a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs @@ -5,7 +5,9 @@ open NUnit.Framework open FsUnit open Paket.TestHelpers -let TestData: obj[][] = +let portable = TargetProfile.FindPortable [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] + +let TestData: obj[][] = [| // project file name, // expected TargetProfile @@ -24,11 +26,16 @@ let TestData: obj[][] = "sl50"; (Some(Silverlight SilverlightVersion.V5))|]; [|"FSharp.Core.Fluent-3.1.fsprojtest"; - (PortableProfile("Profile259", [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhone WindowsPhoneVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ])); + portable; "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1"; (Some(DotNetFramework FrameworkVersion.V4_5))|]; |] - + +[] +let ``should detect profile259`` () = + portable + |> shouldEqual (PortableProfile PortableProfileType.Profile259) + [] [] let ``should detect the correct framework on test projects`` projectFile expectedProfile expectedProfileString expectedTargetFramework = @@ -36,5 +43,5 @@ let ``should detect the correct framework on test projects`` projectFile expecte let p = ProjectFile.TryLoad("./ProjectFile/TestData/" + projectFile).Value p.GetTargetProfile() |> shouldEqual expectedProfile p.GetTargetProfile().ToString() |> shouldEqual expectedProfileString - p.GetTargetFramework() |> shouldEqual expectedTargetFramework + p.GetTargetProfile() |> shouldEqual (SinglePlatform expectedTargetFramework) From 4623d5dac4a544ea217fcfabcdf181c9eccdb029 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 00:30:59 +0200 Subject: [PATCH 11/47] properly implement SupportedPlatforms for PCL and start to fix test suite. --- .../Versioning/FrameworkHandling.fs | 336 +++++++++++++++--- src/Paket.Core/Versioning/PlatformMatching.fs | 43 ++- src/Paket.Core/Versioning/Requirements.fs | 8 + .../InstallModel/Penalty/PenaltySpecs.fs | 2 +- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 15 +- tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 3 +- .../Versioning/FrameworkRestrictionTests.fs | 140 ++++++++ .../Versioning/RestrictionApplicationSpecs.fs | 12 +- 8 files changed, 481 insertions(+), 78 deletions(-) diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index f04d08bc98..4173b40368 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -519,49 +519,93 @@ module FrameworkDetection = type PortableProfileType = | UnsupportedProfile of FrameworkIdentifier list + /// portable-net40+sl4+win8+wp7 | Profile2 + /// portable-net40+sl4 | Profile3 + /// portable-net45+sl4+win8+wp7 | Profile4 + /// portable-net40+win8 | Profile5 + /// portable-net403+win8 | Profile6 - | Profile7 + /// portable-net45+win8 + | Profile7 + /// portable-net40+sl5 | Profile14 + /// portable-net403+sl4 | Profile18 + /// portable-net403+sl5 | Profile19 + /// portable-net45+sl4 | Profile23 + /// portable-net45+sl5 | Profile24 + /// portable-win81+wp81 | Profile31 + /// portable-win81+wpa81 | Profile32 + /// portable-net40+sl4+win8+wp8 | Profile36 + /// portable-net40+sl5+win8 | Profile37 + /// portable-net403+sl4+win8 | Profile41 + /// portable-net403+sl5+win8 | Profile42 + /// portable-net451+win81 | Profile44 + /// portable-net45+sl4+win8 | Profile46 + /// portable-net45+sl5+win8 | Profile47 + /// portable-net45+wp8 | Profile49 + /// portable-net45+win8+wp8 | Profile78 + /// portable-wp81+wpa81 | Profile84 + /// portable-net40+sl4+win8+wp75 | Profile88 + /// portable-net40+win8+wpa81 | Profile92 + /// portable-net403+sl4+win8+wp7 | Profile95 - | Profile96 + /// portable-net403+sl4+win8+wp75 + | Profile96 + /// portable-net403+win8+wpa81 | Profile102 + /// portable-net45+sl4+win8+wp75 | Profile104 + /// portable-net45+win8+wpa81 | Profile111 + /// portable-net40+sl5+win8+wp8 | Profile136 + /// portable-net403+sl4+win8+wp8 | Profile143 + /// portable-net403+sl5+win8+wp8 | Profile147 + /// portable-net451+win81+wpa81 | Profile151 + /// portable-net45+sl4+win8+wp8 | Profile154 + /// portable-win81+wp81+wpa81 | Profile157 + /// portable-net45+sl5+win8+wp8 | Profile158 + /// portable-net40+sl5+win8+wpa81 | Profile225 + /// portable-net403+sl5+win8+wpa81 | Profile240 + /// portable-net45+sl5+win8+wpa81 | Profile255 + /// portable-net45+win8+wp8+wpa81 | Profile259 + /// portable-net40+sl5+win8+wp8+wpa81 | Profile328 + /// portable-net403+sl5+win8+wp8+wpa81 | Profile336 + /// portable-net45+sl5+win8+wp8+wpa81 | Profile344 member x.ProfileName = match x with @@ -879,21 +923,30 @@ type TargetProfile with | DotNetCore _ | DotNetStandard _ -> failwithf "Unexpected famework while trying to resolve PCL Profile" | _ -> true) - let firstMatch = - KnownTargetProfiles.AllPortableProfiles - |> List.filter (fun p -> - let otherFws = p.Frameworks - minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) - |> List.sortBy (fun p -> p.Frameworks.Length) - |> List.tryHead - match firstMatch with - | Some p -> PortableProfile p - | None -> + if minimal.Length > 0 then + let matches = + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun p -> + let otherFws = p.Frameworks + minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) + |> List.sortBy (fun p -> p.Frameworks.Length) + |> Seq.toArray // Debug + let firstMatch = + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun p -> + let otherFws = p.Frameworks + minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) + |> List.sortBy (fun p -> p.Frameworks.Length) + |> List.tryHead + match firstMatch with + | Some p -> PortableProfile p + | None -> #if DEBUG - failwithf "Could not find pcl profile" + failwithf "Could not find pcl profile" #else - PortableProfile (UnsupportedProfile fws) + PortableProfile (UnsupportedProfile fws) #endif + else PortableProfile (UnsupportedProfile fws) // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list /// true when x is supported by y, for example netstandard15 is supported by netcore10 @@ -1001,46 +1054,233 @@ type TargetProfile with Profile344 ] | _ -> // Regular supported logic is to enumerate all profiles and select compatible ones - let supported = tf.RawSupportedPlatformsTransitive let profiles = KnownTargetProfiles.AllPortableProfiles |> List.filter (fun (p) -> - // Portable profile is compatible as soon as it contains a fw which is supported by us + // Portable profile is compatible as soon as if contains us p.Frameworks - |> List.exists (fun fw -> supported |> Seq.exists ((=) fw))) + |> List.exists (fun fw -> fw = tf)) profiles |> List.map PortableProfile rawSupported @ profilesSupported | PortableProfile p -> - let name, tfs = p.ProfileName, p.Frameworks - KnownTargetProfiles.AllPortableProfiles - |> List.filter (fun p -> p.ProfileName <> name) - |> List.filter (fun other -> - let otherName, fws = other.ProfileName, other.Frameworks - let weSupport = - tfs - |> List.collect (fun tf -> tf.RawSupportedPlatformsTransitive) - |> List.distinct - let otherSupport = - fws - |> List.collect (fun fw -> fw.RawSupportedPlatformsTransitive) - |> List.distinct - // Portable profile is compatible when it supports less frameworks. - let isSupported = - otherSupport - |> Seq.forall (fun fw -> weSupport |> List.exists ((=) fw)) - let isReverseSupported = - weSupport - |> Seq.forall (fun fw -> otherSupport |> List.exists ((=) fw)) - let isSupportedI = other < p - let result = - if isSupported && isReverseSupported then - // Some profiles are identical, which means we need to watch out to get a nice tree here - isSupportedI - else - isSupported - //if result then System.Diagnostics.Debug.WriteLine( - // sprintf "reverse %s < %s, result: %O" otherName name result) - result - ) + // This is generated by the "Generate Support Table" test case! + let supported = + match p with + | Profile2 -> + [ + ] + | Profile3 -> + [ + Profile36 + ] + | Profile4 -> + [ + Profile95 + ] + | Profile5 -> + [ + Profile37 + Profile92 + ] + | Profile6 -> + [ + Profile5 + Profile42 + Profile102 + ] + | Profile7 -> + [ + Profile6 + Profile47 + Profile78 + Profile111 + ] + | Profile14 -> + [ + Profile3 + Profile37 + ] + | Profile18 -> + [ + Profile3 + Profile41 + ] + | Profile19 -> + [ + Profile14 + Profile18 + Profile42 + ] + | Profile23 -> + [ + Profile18 + Profile46 + ] + | Profile24 -> + [ + Profile19 + Profile23 + Profile47 + ] + | Profile31 -> + [ + Profile78 + Profile157 + ] + | Profile32 -> + [ + Profile151 + Profile157 + ] + | Profile36 -> + [ + Profile88 + ] + | Profile37 -> + [ + Profile136 + Profile225 + ] + | Profile41 -> + [ + Profile143 + ] + | Profile42 -> + [ + Profile37 + Profile41 + Profile147 + Profile240 + ] + | Profile44 -> + [ + Profile7 + Profile151 + ] + | Profile46 -> + [ + Profile41 + Profile154 + ] + | Profile47 -> + [ + Profile42 + Profile46 + Profile158 + Profile255 + ] + | Profile49 -> + [ + Profile78 + ] + | Profile78 -> + [ + Profile158 + Profile259 + ] + | Profile84 -> + [ + Profile157 + ] + | Profile88 -> + [ + Profile2 + ] + | Profile92 -> + [ + Profile225 + ] + | Profile95 -> + [ + Profile2 + ] + | Profile96 -> + [ + Profile88 + Profile95 + ] + | Profile102 -> + [ + Profile92 + Profile240 + ] + | Profile104 -> + [ + Profile4 + Profile96 + ] + | Profile111 -> + [ + Profile102 + Profile255 + Profile259 + ] + | Profile136 -> + [ + Profile36 + Profile328 + ] + | Profile143 -> + [ + Profile36 + Profile96 + ] + | Profile147 -> + [ + Profile136 + Profile143 + Profile336 + ] + | Profile151 -> + [ + Profile111 + ] + | Profile154 -> + [ + Profile104 + Profile143 + ] + | Profile157 -> + [ + Profile259 + ] + | Profile158 -> + [ + Profile147 + Profile154 + Profile344 + ] + | Profile225 -> + [ + Profile328 + ] + | Profile240 -> + [ + Profile225 + Profile336 + ] + | Profile255 -> + [ + Profile240 + Profile344 + ] + | Profile259 -> + [ + Profile344 + ] + | Profile328 -> + [ + ] + | Profile336 -> + [ + Profile328 + ] + | Profile344 -> + [ + Profile336 + ] + | UnsupportedProfile _ -> [] + + supported |> List.map PortableProfile diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index ae72e88566..7dad74caf8 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -32,29 +32,34 @@ let extractPlatforms = memoize (fun path -> { Name = path; Platforms = split pat // |> Option.map PortableProfile // TODO: In future work this stuff should be rewritten. This penalty stuff is more random than a proper implementation. -let getPlatformPenalty = - let rec getPlatformPenalty alreadyChecked (targetPlatform:TargetProfile) (packagePlatform:TargetProfile) = +let rec getPlatformPenalty = + memoize (fun (targetPlatform:TargetProfile,packagePlatform:TargetProfile) -> + //let rec getPlatformPenalty alreadyChecked (targetPlatform:TargetProfile) (packagePlatform:TargetProfile) = if packagePlatform = targetPlatform then 0 else - let penalty = - targetPlatform.SupportedPlatforms - |> List.filter (fun x -> - System.Diagnostics.Debug.WriteLine(sprintf "Supported %O -> %O (trying to find %O)" targetPlatform x packagePlatform) - Set.contains x alreadyChecked |> not) - |> List.map (fun target -> getPlatformPenalty (Set.add target alreadyChecked) target packagePlatform) - |> List.append [MaxPenalty] - |> List.min - |> fun p -> p + 1 - match targetPlatform, packagePlatform with - | SinglePlatform (DotNetFramework _), SinglePlatform (DotNetStandard _) -> 200 + penalty - | SinglePlatform (DotNetStandard _), SinglePlatform(DotNetFramework _) -> 200 + penalty - | SinglePlatform _, PortableProfile _ -> 500 + penalty - | PortableProfile _, SinglePlatform _ -> 500 + penalty - | _ -> penalty - - memoize (fun (targetPlatform:TargetProfile,packagePlatform:TargetProfile) -> getPlatformPenalty Set.empty targetPlatform packagePlatform) + // There is no point in searching for frameworks in portables... + | PortableProfile _, SinglePlatform _ -> MaxPenalty + | _ -> + let penalty = + targetPlatform.SupportedPlatforms + //|> List.filter (fun x -> + // System.Diagnostics.Debug.WriteLine(sprintf "Supported %O -> %O (trying to find %O)" targetPlatform x packagePlatform) + // Set.contains x alreadyChecked |> not) + |> List.map (fun target -> + //System.Diagnostics.Debug.WriteLine(sprintf "Supported %O -> %O (trying to find %O)" targetPlatform target packagePlatform) + getPlatformPenalty (target, packagePlatform)) + |> List.append [MaxPenalty] + |> List.min + |> fun p -> p + 1 + + match targetPlatform, packagePlatform with + | SinglePlatform (DotNetFramework _), SinglePlatform (DotNetStandard _) -> 200 + penalty + | SinglePlatform (DotNetStandard _), SinglePlatform(DotNetFramework _) -> 200 + penalty + | SinglePlatform _, PortableProfile _ -> 500 + penalty + | PortableProfile _, SinglePlatform _ -> 500 + penalty + | _ -> penalty) let getFrameworkPenalty (fr1, fr2) = getPlatformPenalty (SinglePlatform fr1, SinglePlatform fr2) diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 051f11477e..739893276e 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -243,12 +243,20 @@ module FrameworkRestriction = fr.OrFormulas |> Seq.exists (fun andFormular -> andFormular.Literals |> Seq.isEmpty) if containsEmptyAnd then NoRestriction else fr + + let sortClauses (fr:FrameworkRestriction) = + { OrFormulas = + fr.OrFormulas + |> List.map (fun andFormula -> { Literals = andFormula.Literals |> List.distinct |> List.sort }) + |> List.distinct + |> List.sort } fr |> removeNegatedLiteralsWhichOccurSinglePositive |> removeSubsetLiteralsInAndClause |> removeSubsetLiteralsInOrClause |> replaceWithNoRestrictionIfAnyLiteralListIsEmpty + |> sortClauses let rec private And2 (left : FrameworkRestriction) (right : FrameworkRestriction) = match left.OrFormulas with diff --git a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs index 9e94ef6f1c..5d40fb0be9 100644 --- a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs +++ b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs @@ -76,7 +76,7 @@ module ``Given an empty path`` = [] let ``it should be okay to use from .NET``() = let path = extractPlatforms "" - getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldBeSmallerThan 1000 + getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldBeSmallerThan 2000 [] let ``it should be okay to use from a portable profile``() = diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index c18be23e28..14b87a7d57 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -78,7 +78,8 @@ let ``can detect explicit dependencies for Fleece``() = [] let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = - parse "NuGetOData/ReadOnlyCollectionExtensions.xml" + let item = parse "NuGetOData/ReadOnlyCollectionExtensions.xml" + item |> shouldEqual { PackageName = "ReadOnlyCollectionExtensions" DownloadUrl = "http://www.nuget.org/api/v2/package/ReadOnlyCollectionExtensions/1.2.0" @@ -87,11 +88,11 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = LicenseUrl = "https://github.com/mausch/ReadOnlyCollections/blob/master/license.txt" Version = "1.2.0" Dependencies = - [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"),makeOrList [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))] + [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"), + makeOrList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V2), DotNetFramework(FrameworkVersion.V3_5))] PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), makeOrList - [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V2)) - FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V3_5))]] + [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V2))]] SourceUrl = fakeUrl } [] @@ -141,7 +142,7 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = let dependencies = odata.Dependencies |> Array.ofList dependencies.[0] |> shouldEqual (PackageName "Microsoft.Data.OData", DependenciesFileParser.parseVersionRequirement(">= 5.6.3"), - makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + makeOrList [FrameworkRestriction.AtLeast(DNXCore(FrameworkVersion.V5_0))]) let vr,pr = match DependenciesFileParser.parseVersionRequirement(">= 4.0.0-beta-22231") with @@ -149,11 +150,11 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = dependencies.[18] |> shouldEqual (PackageName "System.Net.Http", VersionRequirement(vr,PreReleaseStatus.All), - makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + makeOrList [FrameworkRestriction.AtLeast(DNXCore(FrameworkVersion.V5_0))]) dependencies.[44] |> shouldEqual (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 6.0.8"), - makeOrList [FrameworkRestriction.Exactly(WindowsPhone WindowsPhoneVersion.V8); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))]) + makeOrList [FrameworkRestriction.AtLeast(WindowsPhone WindowsPhoneVersion.V8); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))]) [] let ``can ignore unknown frameworks``() = diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index a4a028c76e..30f1c842cc 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -187,8 +187,7 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = makeOrList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V2), DotNetFramework(FrameworkVersion.V3_5))] PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), makeOrList - [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V2)) - FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V3_5))]] + [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V2))]] [] let ``can detect explicit dependencies for Microsoft.AspNetCore.Antiforgery``() = diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index 4f093bc9d5..aa85878d32 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -4,6 +4,128 @@ open Paket open FsUnit open NUnit.Framework open Paket.Requirements + +let isSupported (portable:PortableProfileType) (other:PortableProfileType) = + let name, tfs = portable.ProfileName, portable.Frameworks + + let otherName, otherfws = other.ProfileName, other.Frameworks + let weSupport = + tfs + |> List.collect (fun tf -> tf.RawSupportedPlatformsTransitive) + + let relevantFrameworks = + otherfws + |> Seq.filter (fun fw -> + weSupport |> List.exists ((=) fw)) + |> Seq.length + relevantFrameworks >= tfs.Length + +[] +let ``Profile 158 should not support itself``() = + isSupported Profile158 Profile158 + |> shouldEqual false +[] +let ``Profile 158 should not support Profile 78, as there is no silverlight on 78``() = + isSupported Profile158 Profile78 + |> shouldEqual false + isSupported Profile78 Profile158 + |> shouldEqual true +[] +let ``Profile 344 should support Profile 336, as it has the same frameworks but is lower``() = + isSupported Profile336 Profile344 + |> shouldEqual false + isSupported Profile344 Profile336 + |> shouldEqual true + +[] +let ``Generate Support Table``() = + // TODO: Should we include this? + let getSupported (portable:PortableProfileType) = + let name, tfs = portable.ProfileName, portable.Frameworks + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun p -> p.ProfileName <> name) + |> List.filter (fun other -> isSupported portable other) + |> List.map PortableProfile + let mutable supportMap = + KnownTargetProfiles.AllPortableProfiles + |> List.map (fun p -> + p, + getSupported p + |> List.choose (function PortableProfile p -> Some p | _ -> failwithf "Expected portable")) + |> dict + + let rec buildSupportMap p = + let directMap = supportMap.[p] + directMap + |> List.append (directMap |> List.collect buildSupportMap) + + let filterMap pos (supportMap:System.Collections.Generic.IDictionary<_,_>) = + supportMap + |> Seq.map (fun (kv:System.Collections.Generic.KeyValuePair<_,_>) -> + let profile = kv.Key + let supported : PortableProfileType list = kv.Value + + profile, + if supported.Length < pos + 1 then + supported + else + // try to optimize on the 'pos' position + let curPos = supported.[pos] + let supportList = buildSupportMap curPos // supportMap.[curPos] // + (supported |> List.take pos |> List.filter (fun s -> supportList |> List.contains s |> not)) + @ [curPos] @ + (supported + |> List.skip (pos + 1) + |> List.filter (fun s -> supportList |> List.contains s |> not)) + ) + |> dict + + for i in 0 .. 10 do + for i in 0 .. 15 do supportMap <- filterMap i supportMap + + supportMap + |> Seq.iter (fun (kv:System.Collections.Generic.KeyValuePair<_,_>) -> + let p = kv.Key + let supported : PortableProfileType list = kv.Value + System.Diagnostics.Debug.WriteLine(sprintf "| %s ->" p.ProfileName) + System.Diagnostics.Debug.WriteLine(" [ ") + supported + |> List.iter (fun p -> + System.Diagnostics.Debug.WriteLine(sprintf " %s" p.ProfileName)) + + System.Diagnostics.Debug.WriteLine(" ] ")) + + System.Diagnostics.Debug.WriteLine(" --- Finished") + +[] +let ``Unknown Portables are detected correctly``() = + PlatformMatching.extractPlatforms "portable-monotouch+monoandroid" + |> function { Platforms = o } -> TargetProfile.FindPortable o + |> shouldEqual (PortableProfile (PortableProfileType.UnsupportedProfile [MonoTouch; MonoAndroid])) +[] +let ``Portables are detected correctly``() = + // http://nugettoolsdev.azurewebsites.net/4.0.0/parse-framework?framework=portable-net451%2Bwin81%2Bwpa81%2Bwaspt2 + let portables = + [ "net40" + "portable-monotouch+monoandroid" + "portable-net40+sl5+win8+wp8+wpa81"; "portable-net45+winrt45+wp8+wpa81" + "portable-win81+wpa81" + "portable-windows8+net45+wp8" + "sl5"; "win8" + "wp8" ] + |> List.map PlatformMatching.extractPlatforms + |> List.map (function { Platforms = [ h] } -> SinglePlatform h | {Platforms = o} -> TargetProfile.FindPortable o) + let expected = + [ SinglePlatform (DotNetFramework FrameworkVersion.V4); + PortableProfile (PortableProfileType.UnsupportedProfile [MonoTouch; MonoAndroid]) + PortableProfile (PortableProfileType.Profile328); PortableProfile (PortableProfileType.Profile259) + PortableProfile (PortableProfileType.Profile32) + PortableProfile (PortableProfileType.Profile78) + SinglePlatform (Silverlight SilverlightVersion.V5); SinglePlatform (Windows WindowsVersion.V8) + SinglePlatform (WindowsPhone WindowsPhoneVersion.V8) ] + portables + |> shouldEqual expected + [] let ``PortableProfile supports PortableProfiles but it is not recursive``() = let portableProfiles = @@ -39,6 +161,24 @@ let ``Simplify && (&& (>= net40-full) (< net46) (>= net20)``() = toSimplify |> shouldEqual (FrameworkRestriction.Between (DotNetFramework FrameworkVersion.V4, DotNetFramework FrameworkVersion.V4_6)) +[] +let ``Simplify (>=net20) && (>=net20)``() = + let toSimplify = + (FrameworkRestriction.And[ + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V2) + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V2)]) + toSimplify + |> shouldEqual (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V2)) + +[] +let ``Simplify (>=net20) || (>=net20)``() = + let toSimplify = + (FrameworkRestriction.Or[ + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V2) + FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V2)]) + toSimplify + |> shouldEqual (FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V2)) + [] let ``Simplify || (&& (< net40) (< net35)) (&& (< net40) (>= net35)) (>= net40))``() = // Test simplify || (&& (< net40) (< net35)) (&& (< net40) (>= net35)) (>= net40)) diff --git a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs index b0c38a6cf3..959e45a146 100644 --- a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs @@ -9,7 +9,17 @@ let dotnet x = SinglePlatform(DotNetFramework(x)) module TestTargetProfiles = let DotNetFrameworkVersions = - KnownTargetProfiles.DotNetFrameworkVersions + [FrameworkVersion.V1 + FrameworkVersion.V1_1 + FrameworkVersion.V2 + FrameworkVersion.V3 + FrameworkVersion.V3_5 + FrameworkVersion.V4 + FrameworkVersion.V4_5 + FrameworkVersion.V4_5_1 + FrameworkVersion.V4_5_2 + FrameworkVersion.V4_5_3 + FrameworkVersion.V4_6] let DotNetFrameworkProfiles = DotNetFrameworkVersions |> List.map dotnet From d1646af10bef5630a41c0e75c7a8d00cae6350ad Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 02:09:35 +0200 Subject: [PATCH 12/47] fix several bugs and tests --- .../Dependencies/PackageResolver.fs | 4 +- .../Versioning/FrameworkHandling.fs | 2 +- src/Paket.Core/Versioning/PlatformMatching.fs | 4 +- src/Paket.Core/Versioning/Requirements.fs | 40 +++++++++++++- .../InstallModel/Penalty/PenaltySpecs.fs | 4 +- .../InstallModel/Xml/FSharp.Data.SqlClient.fs | 2 +- .../Lockfile/GenerateWithOptionsSpecs.fs | 2 +- tests/Paket.Tests/Lockfile/GeneratorSpecs.fs | 52 +++++++++---------- tests/Paket.Tests/Nuspec/NuspecSpecs.fs | 4 +- .../Paket.Tests/ProjectFile/ConditionSpecs.fs | 2 +- .../ProjectFile/TargetFrameworkSpecs.fs | 8 +-- .../Versioning/DependencySetSpecs.fs | 10 ++-- .../Versioning/FrameworkRestrictionTests.fs | 13 ++++- .../Versioning/RestrictionFilterSpecs.fs | 10 ++-- 14 files changed, 104 insertions(+), 53 deletions(-) diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 25b1e96185..28680d9568 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -62,7 +62,9 @@ module DependencySetFilter = // This is the framework restriction we build for (example = net46) // While the dependency specifies the framework restrictions of the dependency ([ >= netstandard13 ]) // we need to take the dependency, when 'restriction' is a subset of any of 'dependencyRestrictions' - restriction.IsSubsetOf dependencyRestrictions + let combined = FrameworkRestriction.And [ restriction; dependencyRestrictions ] + combined.RepresentedFrameworks.Length > 0 + //restriction.IsSubsetOf dependencyRestrictions //match restriction with //| FrameworkRestriction.Exactly v1 -> // dependencyRestrictions diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index 4173b40368..c407287240 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -67,7 +67,7 @@ type FrameworkVersion = | V3 -> "v3.0" | V3_5 -> "v3.5" | V4 -> "v4.0" - | V4_0_3 -> "v4.0.3" + | V4_0_3 -> "v4.0.3" | V4_5 -> "v4.5" | V4_5_1 -> "v4.5.1" | V4_5_2 -> "v4.5.2" diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index 7dad74caf8..04ddf07bbf 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -232,8 +232,8 @@ let getTargetCondition (target:TargetProfile) = | SinglePlatform(platform) -> // BUG: Pattern incomplete! match platform with - | DotNetFramework(version) when version = FrameworkVersion.V4 -> - "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O')" version + //| DotNetFramework(version) when version = FrameworkVersion.V4 -> + // "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O')" version | DotNetFramework(version) ->"$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DNX(version) ->"$(TargetFrameworkIdentifier) == 'DNX'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DNXCore(version) ->"$(TargetFrameworkIdentifier) == 'DNXCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 739893276e..fd96d79de1 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -235,6 +235,39 @@ module FrameworkRestriction = |> not | _ -> true) } + /// ((>= net20) && (>= net40)) || (>= net20) can be simplified to (>= net20) because any AND clause with (>= net20) can be removed. + let removeUneccessaryOrClauses (fr:FrameworkRestriction) = + let orClauses = + fr.OrFormulas + let isContained (andList:FrameworkRestrictionAndList) (item:FrameworkRestrictionAndList) = + if item.Literals.Length >= andList.Literals.Length then false + else + item.Literals + |> Seq.forall (fun lit -> andList.Literals |> Seq.contains lit) + + { OrFormulas = + fr.OrFormulas + |> List.filter (fun orClause -> + orClauses |> Seq.exists (isContained orClause) |> not) + } + + /// clauses with ((>= net20) && (< net20) && ...) can be removed because they contains a literal and its negation. + let removeUneccessaryAndClauses (fr:FrameworkRestriction) = + { OrFormulas = + fr.OrFormulas + |> List.filter (fun andList -> + let normalizeLiterals = + andList.Literals + |> List.map (function + | { LiteraL = FrameworkRestrictionLiteralI.ExactlyL l; IsNegated = n } -> + { LiteraL = FrameworkRestrictionLiteralI.AtLeastL l; IsNegated = n } + | lit -> lit) + let foundLiteralAndNegation = + normalizeLiterals + |> Seq.exists (fun l -> + normalizeLiterals |> Seq.contains { l with IsNegated = not l.IsNegated}) + not foundLiteralAndNegation) } + /// When we optmized a clause away completely we can replace the hole formula with "NoRestriction" /// This happens for example with ( =net45) and the removeNegatedLiteralsWhichOccurSinglePositive /// optimization @@ -255,6 +288,8 @@ module FrameworkRestriction = |> removeNegatedLiteralsWhichOccurSinglePositive |> removeSubsetLiteralsInAndClause |> removeSubsetLiteralsInOrClause + |> removeUneccessaryAndClauses + |> removeUneccessaryOrClauses |> replaceWithNoRestrictionIfAnyLiteralListIsEmpty |> sortClauses @@ -269,14 +304,14 @@ module FrameworkRestriction = { OrFormulas = (And2 {OrFormulas = [h]} right).OrFormulas @ ((And2 {OrFormulas = t} right).OrFormulas) } let And (rst:FrameworkRestriction list) = - List.fold And2 EmptySet rst + List.fold And2 NoRestriction rst |> simplify let private Or2 (left : FrameworkRestriction) (right : FrameworkRestriction) = { OrFormulas = left.OrFormulas @ right.OrFormulas } let Or (rst:FrameworkRestriction list) = - List.fold Or2 NoRestriction rst + List.fold Or2 EmptySet rst |> simplify //[] @@ -289,6 +324,7 @@ module FrameworkRestriction = let Between (x, y) = And2 (AtLeast x) (NotAtLeast y) + |> simplify //FrameworkRestrictionP.AndP[FrameworkRestrictionP.AtLeastP x; FrameworkRestrictionP.NotP (FrameworkRestrictionP.AtLeastP y)] let combineRestrictionsWithOr (x : FrameworkRestriction) y = diff --git a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs index 5d40fb0be9..01652776d0 100644 --- a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs +++ b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs @@ -15,7 +15,7 @@ module ``Given a target platform`` = [] let ``it should return the right penalty for a compatible platform``() = getFrameworkPenalty (DotNetFramework FrameworkVersion.V4_5, DotNetFramework FrameworkVersion.V4) - |> shouldEqual 1 + |> shouldEqual 2 [] let ``it should return > 1000 for an incompatible platform``() = @@ -235,7 +235,7 @@ module ``General Penalty checks`` = let ``make sure not all portable profiles match``()= // Not all portable profiles have a match. Paket.PlatformMatching.findBestMatch - (["portable-net403+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1"]|> List.map extractPlatforms, + (["portable-net45+win8"]|> List.map extractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_0))) |> shouldEqual (None) diff --git a/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs b/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs index 2fe6b1e033..1ecead7d76 100644 --- a/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs +++ b/tests/Paket.Tests/InstallModel/Xml/FSharp.Data.SqlClient.fs @@ -10,7 +10,7 @@ open System.IO let expected = """ - + True diff --git a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs index 25567cd490..cfa6063ecb 100644 --- a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs +++ b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs @@ -23,7 +23,7 @@ let graph1 = let expected1 = """REFERENCES: STRICT COPY-LOCAL: FALSE -FRAMEWORK: >= NET45 +RESTRICTION: >= NET45 NUGET remote: http://www.nuget.org/api/v2 Castle.Windsor-log4net (3.2)""" diff --git a/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs b/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs index 9099bc10a1..58dfbd195b 100644 --- a/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs +++ b/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs @@ -59,15 +59,15 @@ nuget "Rx-Main" "~> 2.0" framework: >= net40 """ let ``should generate lock file with framework restrictions for packages``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 - Castle.Windsor (2.1) - framework: net35 - Castle.Windsor-log4net (3.3) - framework: net35 + Castle.Windsor (2.1) - restriction: net35 + Castle.Windsor-log4net (3.3) - restriction: net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - framework: net35 - log4net (1.1) - framework: net35 + log (1.2) - restriction: net35 + log4net (1.1) - restriction: net35 log (>= 1.0) - Rx-Core (2.1) - framework: >= net40 - Rx-Main (2.0) - framework: >= net40 + Rx-Core (2.1) - restriction: >= net40 + Rx-Main (2.0) - restriction: >= net40 Rx-Core (>= 2.1)""" let cfg = DependenciesFile.FromSource(configWithRestrictions) @@ -86,15 +86,15 @@ nuget "Rx-Main" "~> 2.0" framework: >= net40 """ let ``should generate lock file with no targets import for packages``() = let expected = """NUGET remote: "D:\code\temp with space" - Castle.Windsor (2.1) - import_targets: false, framework: net35 - Castle.Windsor-log4net (3.3) - import_targets: false, framework: net35 + Castle.Windsor (2.1) - import_targets: false, restriction: net35 + Castle.Windsor-log4net (3.3) - import_targets: false, restriction: net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - import_targets: false, framework: net35 - log4net (1.1) - import_targets: false, framework: net35 + log (1.2) - import_targets: false, restriction: net35 + log4net (1.1) - import_targets: false, restriction: net35 log (>= 1.0) - Rx-Core (2.1) - framework: >= net40 - Rx-Main (2.0) - framework: >= net40 + Rx-Core (2.1) - restriction: >= net40 + Rx-Main (2.0) - restriction: >= net40 Rx-Core (>= 2.1)""" let cfg = DependenciesFile.FromSource(configWithNoImport) @@ -112,15 +112,15 @@ nuget "Rx-Main" "~> 2.0" framework: >= net40 """ let ``should generate lock file with no copy local for packages``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 - Castle.Windsor (2.1) - copy_local: false, import_targets: false, framework: net35 - Castle.Windsor-log4net (3.3) - copy_local: false, import_targets: false, framework: net35 + Castle.Windsor (2.1) - copy_local: false, import_targets: false, restriction: net35 + Castle.Windsor-log4net (3.3) - copy_local: false, import_targets: false, restriction: net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - copy_local: false, import_targets: false, framework: net35 - log4net (1.1) - copy_local: false, import_targets: false, framework: net35 + log (1.2) - copy_local: false, import_targets: false, restriction: net35 + log4net (1.1) - copy_local: false, import_targets: false, restriction: net35 log (>= 1.0) - Rx-Core (2.1) - framework: >= net40 - Rx-Main (2.0) - framework: >= net40 + Rx-Core (2.1) - restriction: >= net40 + Rx-Main (2.0) - restriction: >= net40 Rx-Core (>= 2.1)""" let cfg = DependenciesFile.FromSource(configWithCopyLocal) ResolveWithGraph(cfg,noSha1,VersionsFromGraphAsSeq graph, PackageDetailsFromGraph graph).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() @@ -138,15 +138,15 @@ nuget "Rx-Main" "~> 2.0" content: none, framework: >= net40 """ let ``should generate lock file with disabled content for packages``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 - Castle.Windsor (2.1) - framework: net35 - Castle.Windsor-log4net (3.3) - framework: net35 + Castle.Windsor (2.1) - restriction: net35 + Castle.Windsor-log4net (3.3) - restriction: net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - framework: net35 - log4net (1.1) - framework: net35 + log (1.2) - restriction: net35 + log4net (1.1) - restriction: net35 log (>= 1.0) - Rx-Core (2.1) - content: none, framework: >= net40 - Rx-Main (2.0) - content: none, framework: >= net40 + Rx-Core (2.1) - content: none, restriction: >= net40 + Rx-Main (2.0) - content: none, restriction: >= net40 Rx-Core (>= 2.1)""" let cfg = DependenciesFile.FromSource(configWithDisabledContent) ResolveWithGraph(cfg,noSha1,VersionsFromGraphAsSeq graph, PackageDetailsFromGraph graph).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() @@ -356,14 +356,14 @@ let ``should generate lock file with second group``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 Castle.Windsor (2.1) - copy_content_to_output_dir: preserve_newest - Castle.Windsor-log4net (3.3) - framework: net35 + Castle.Windsor-log4net (3.3) - restriction: net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) log (1.2) log4net (1.1) - copy_content_to_output_dir: never log (>= 1.0) Rx-Core (2.1) - content: none - Rx-Main (2.0) - content: none, framework: >= net40 + Rx-Main (2.0) - content: none, restriction: >= net40 Rx-Core (>= 2.1) GROUP Build diff --git a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs index 30f1c842cc..7ce8dadb8d 100644 --- a/tests/Paket.Tests/Nuspec/NuspecSpecs.fs +++ b/tests/Paket.Tests/Nuspec/NuspecSpecs.fs @@ -262,7 +262,7 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 5.0.8"), makeOrList - [FrameworkRestriction.Exactly(WindowsPhone WindowsPhoneVersion.V8) + [FrameworkRestriction.AtLeast(WindowsPhone WindowsPhoneVersion.V8) FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))]) [] @@ -281,7 +281,7 @@ let ``can detect framework assemblies for Microsoft.Framework.Logging``() = let name,_,restrictions = nuspec.Dependencies.[2] name |> shouldEqual (PackageName "System.Collections.Concurrent") - restrictions |> shouldEqual (makeOrList [FrameworkRestriction.Exactly(DNXCore(FrameworkVersion.V5_0))]) + restrictions |> shouldEqual (makeOrList [FrameworkRestriction.AtLeast(DNXCore(FrameworkVersion.V5_0))]) [] let ``can detect explicit dependencies for FluentAssertions 4``() = diff --git a/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs b/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs index cbfa41db16..13abf09be7 100644 --- a/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs @@ -51,7 +51,7 @@ let ``should detect Silverlight version from path``() = [] let ``should detect WindowsPhone version from path``() = - FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp71\RestSharp.WindowsPhone.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_5) + FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp75\RestSharp.WindowsPhone.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_5) FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp\TechTalk.SpecFlow.WindowsPhone7.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_5) [] diff --git a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs index 82e2216b80..b6269a770e 100644 --- a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs @@ -16,19 +16,19 @@ let TestData: obj[][] = [|"Project2.fsprojtest"; (SinglePlatform(DotNetFramework FrameworkVersion.V4)); "net40"; - (Some(DotNetFramework FrameworkVersion.V4))|]; + (DotNetFramework FrameworkVersion.V4)|]; [|"Empty.fsprojtest"; (SinglePlatform(DotNetFramework FrameworkVersion.V4)); "net40-full"; - (Some(DotNetFramework FrameworkVersion.V4))|]; + (DotNetFramework FrameworkVersion.V4)|]; [|"NewSilverlightClassLibrary.csprojtest"; (SinglePlatform(Silverlight SilverlightVersion.V5)); "sl50"; - (Some(Silverlight SilverlightVersion.V5))|]; + (Silverlight SilverlightVersion.V5)|]; [|"FSharp.Core.Fluent-3.1.fsprojtest"; portable; "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1"; - (Some(DotNetFramework FrameworkVersion.V4_5))|]; + (DotNetFramework FrameworkVersion.V4_5)|]; |] [] diff --git a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs index 7e21b6aa00..a7a34698f3 100644 --- a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs +++ b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs @@ -138,10 +138,12 @@ let ``filtered with AtLeast restriction should filter non-matching``() = PackageName("P9"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4_5_2)))] |> Set.ofList - - original - |> DependencySetFilter.filterByRestrictions ( ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4)))) - |> shouldEqual expected + let result = + original + |> DependencySetFilter.filterByRestrictions ( ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4)))) + |> Seq.toArray + result + |> shouldEqual (expected |> Seq.toArray) [] let ``filtered with Between restriction should filter non-matching`` () = diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index aa85878d32..6f5627fcd8 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -18,7 +18,7 @@ let isSupported (portable:PortableProfileType) (other:PortableProfileType) = |> Seq.filter (fun fw -> weSupport |> List.exists ((=) fw)) |> Seq.length - relevantFrameworks >= tfs.Length + relevantFrameworks >= tfs.Length && portable <> other [] let ``Profile 158 should not support itself``() = @@ -161,6 +161,17 @@ let ``Simplify && (&& (>= net40-full) (< net46) (>= net20)``() = toSimplify |> shouldEqual (FrameworkRestriction.Between (DotNetFramework FrameworkVersion.V4, DotNetFramework FrameworkVersion.V4_6)) +[] +let ``Simplify <|| (&& (net452) (native)) (native)>`` () = + let toSimplify = + (FrameworkRestriction.Or[ + FrameworkRestriction.And[ + FrameworkRestriction.Exactly (DotNetFramework FrameworkVersion.V4_5_2) + FrameworkRestriction.Exactly (Native(NoBuildMode,NoPlatform))] + FrameworkRestriction.Exactly (Native(NoBuildMode,NoPlatform))]) + toSimplify + |> shouldEqual (FrameworkRestriction.Exactly (Native(NoBuildMode,NoPlatform))) + [] let ``Simplify (>=net20) && (>=net20)``() = let toSimplify = diff --git a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs index 53fb78f878..991302ce66 100644 --- a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs @@ -41,7 +41,7 @@ let ``should filter >=net40 and >= net45``() = [] let ``should filter >= net40 and portable``() = let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) - let l2 = ExplicitRestriction (getPortableRestriction("abc")) + let l2 = ExplicitRestriction (getPortableRestriction("net45")) filterRestrictions l1 l2 |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) @@ -68,7 +68,7 @@ let ``should filter >= net40 and >= net20 < net40``() = let l2 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V2),DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 - |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.EmptySet) [] let ``should filter net45 and >= net40 < net46``() = @@ -82,7 +82,7 @@ let ``should filter net45 and >= net40 < net45``() = let l1 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) let l2 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5))) filterRestrictions l1 l2 - |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.EmptySet) [] let ``should filter >= net40 < net46 and net45``() = @@ -96,7 +96,7 @@ let ``should filter >= net40 < net45 and net45``() = let l1 = ExplicitRestriction (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4),DotNetFramework(FrameworkVersion.V4_5))) let l2 = ExplicitRestriction (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5))) filterRestrictions l1 l2 - |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.EmptySet) [] let ``should filter >= net20 < net46 and >= net40``() = @@ -120,7 +120,7 @@ let ``should filter >= net20 < net40 and >= net40``() = let l2 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) filterRestrictions l1 l2 - |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) + |> shouldEqual (ExplicitRestriction FrameworkRestriction.EmptySet) [] let ``should not filter native, net452``() = From e4c0f8941a40bfea160d1d1db94ddcd3b2e127dc Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 02:48:07 +0200 Subject: [PATCH 13/47] cleanup and more test fixes --- src/Paket.Core/Versioning/Requirements.fs | 417 +----------------- .../InstallModel/FrameworkIdentifierSpecs.fs | 2 +- .../InstallModel/ProcessingSpecs.fs | 4 +- .../InstallModel/Xml/LibGit2Sharp.fs | 4 +- tests/Paket.Tests/InstallModel/Xml/Plossum.fs | 2 +- tests/Paket.Tests/InstallModel/Xml/RxXaml.fs | 2 +- tests/Paket.Tests/InstallModel/Xml/SQLite.fs | 4 +- .../InstallModel/Xml/System.Spatial.fs | 2 +- .../InstallModel/Xml/SystemNetHttp.fs | 2 +- .../InstallModel/Xml/SystemNetHttpForNet4.fs | 2 +- ...mNetHttpWithExistingFrameworkReferences.fs | 2 +- .../SystemNetHttpWithFrameworkReferences.fs | 2 +- .../InstallModel/Xml/xunit.runner.fs | 2 +- .../Lockfile/GenerateWithOptionsSpecs.fs | 8 +- .../ProjectFile/TargetFrameworkSpecs.fs | 6 +- .../DependencyGroupsAndRestrictions.fs | 41 +- .../Versioning/DependencySetSpecs.fs | 65 --- 17 files changed, 63 insertions(+), 504 deletions(-) diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index fd96d79de1..30fa01b853 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -318,36 +318,13 @@ module FrameworkRestriction = //let Not (rst:FrameworkRestriction) = // Unchecked.defaultof<_> - //let NotLiteral (lit : FrameworkRestrictionLiteral) = { lit with IsNegated = not lit.IsNegated } - - //let fromLiteral = { OrFormulas = [ { Literals = [lit] } ] } - let Between (x, y) = And2 (AtLeast x) (NotAtLeast y) |> simplify - //FrameworkRestrictionP.AndP[FrameworkRestrictionP.AtLeastP x; FrameworkRestrictionP.NotP (FrameworkRestrictionP.AtLeastP y)] let combineRestrictionsWithOr (x : FrameworkRestriction) y = Or2 x y |> simplify - //if x.IsSubsetOf y then - // y - //elif y.IsSubsetOf x then - // x - //else - // match x, y with - // | FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general], other - // | FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate], other - // | other, FrameworkRestriction.AndP[FrameworkRestriction.NotP negate; general] - // | other, FrameworkRestriction.AndP[general; FrameworkRestriction.NotP negate] when negate = other -> - // // "negate && NOT general" might not be empty, ie general might not be a superset of negate - // if other.IsSubsetOf general then general else FrameworkRestriction.OrP[general; other] - // | _ -> - // let combined = FrameworkRestriction.OrP[x; y] - // if combined.RepresentedFrameworks.Length = FrameworkRestriction.NoRestriction.RepresentedFrameworks.Length then - // FrameworkRestriction.NoRestriction - // else - // combined let (|HasNoRestriction|_|) x = if x = NoRestriction then Some () else None @@ -355,26 +332,7 @@ module FrameworkRestriction = let combineRestrictionsWithAnd (x : FrameworkRestriction) y = And2 x y |> simplify - // combine means basically we say AND (both need to be satisfied) - //if x.IsSubsetOf y then - // x - //elif y.IsSubsetOf x then - // y - //else - // let combined = FrameworkRestriction.AndP[x; y] - // if combined.RepresentedFrameworks |> Seq.isEmpty then - // FrameworkRestriction.EmptySet - // else combined - //if x.IsSameCategoryAs(y) <> Some false then - // combineSameCategoryOrPortableRestrictions x y - //else - // if loose then - // match (x.GetOneIdentifier, y.GetOneIdentifier) with - // | Some (FrameworkIdentifier.DotNetFramework _ ), Some (FrameworkIdentifier.DotNetStandard _ ) -> [x] - // | Some (FrameworkIdentifier.DotNetStandard _ ), Some (FrameworkIdentifier.DotNetFramework _ ) -> [y] - // | _ -> [] - // else - // [] + type FrameworkRestrictions = | ExplicitRestriction of FrameworkRestriction | AutoDetectFramework @@ -443,317 +401,8 @@ let parseRestrictionsLegacy failImmediatly (text:string) = yield FrameworkRestriction.Exactly x] |> List.fold (fun state item -> FrameworkRestriction.combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet -let rec optimizeRestrictions restrictions = - restrictions -// let sorting xs = -// xs -// |> List.sortBy (fun x -> -// match x with -// | FrameworkRestriction.Exactly r -> r -// | FrameworkRestriction.Portable _ -> FrameworkIdentifier.MonoMac -// | FrameworkRestriction.AtLeast r -> r -// | FrameworkRestriction.Between(min,max) -> min -// |> fun y -> y,x) -// -// match sorting restrictions |> List.distinct with -// | [] -> [] -// | [x] -> [x] -// | odered -> -// let newRestrictions = -// match odered |> Seq.tryFind (function | FrameworkRestriction.AtLeast r -> true | _ -> false) with -// | Some((FrameworkRestriction.AtLeast(DotNetFramework(v)) as r)) -> -// odered -// |> List.filter (fun r' -> -// match r' with -// | FrameworkRestriction.Exactly(DotNetFramework(x)) when x > v -> false -// | FrameworkRestriction.AtLeast(DotNetFramework(x)) when x > v -> false -// | _ -> true) -// | Some((FrameworkRestriction.AtLeast(DotNetStandard(v)) as r)) -> -// odered -// |> List.filter (fun r' -> -// match r' with -// | FrameworkRestriction.Exactly(DotNetStandard(x)) when x > v -> false -// | FrameworkRestriction.AtLeast(DotNetStandard(x)) when x > v -> false -// | _ -> true) -// | _ -> odered -// -// let filtered = -// match newRestrictions |> Seq.rev |> Seq.tryFind (function | FrameworkRestriction.AtLeast(DotNetFramework r) -> true | FrameworkRestriction.AtLeast(DotNetStandard r) -> true | _ -> false) with -// | None -> newRestrictions -// | Some r -> -// let currentVersion = -// match r with -// | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> DotNetFramework x -// | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> DotNetStandard x -// | x -> failwithf "Unknown .NET moniker %O" x -// -// let isLowerVersion (currentVersion:FrameworkIdentifier) compareVersion = -// let isMatching (x:FrameworkIdentifier) = -// if x = DotNetFramework FrameworkVersion.V3_5 && currentVersion = DotNetFramework FrameworkVersion.V4 then true else -// if x = DotNetFramework FrameworkVersion.V3_5 && currentVersion = DotNetFramework FrameworkVersion.V4_Client then true else -// if x = DotNetFramework FrameworkVersion.V4_Client && currentVersion = DotNetFramework FrameworkVersion.V4_5 then true else -// let hasFrameworksBetween = -// KnownTargetProfiles.DotNetFrameworkVersions -// |> Seq.exists (fun p -> DotNetFramework p > x && DotNetFramework p < currentVersion) -// let hasStandardsBetween = -// KnownTargetProfiles.DotNetStandardVersions -// |> Seq.exists (fun p -> DotNetStandard p > x && DotNetStandard p < currentVersion) -// -// not hasFrameworksBetween && not hasStandardsBetween -// -// match compareVersion with -// | FrameworkRestriction.Exactly(DotNetFramework(x)) -> isMatching (DotNetFramework x) -// | FrameworkRestriction.Exactly(DotNetStandard(x)) -> isMatching (DotNetStandard x) -// | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> -// isMatching (DotNetFramework x) || -// (match currentVersion with -// | DotNetFramework(y) when x < y -> true -// | _ -> false) -// | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> -// isMatching (DotNetStandard x) || -// (match currentVersion with -// | DotNetStandard(y) when x < y -> true -// | _ -> false) -// | _ -> false -// -// match newRestrictions |> Seq.tryFind (isLowerVersion currentVersion) with -// | None -> newRestrictions -// | Some n -> -// let newLowest = -// match n with -// | FrameworkRestriction.Exactly(DotNetFramework(x)) -> DotNetFramework x -// | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> DotNetFramework x -// | FrameworkRestriction.Exactly(DotNetStandard(x)) -> DotNetStandard x -// | FrameworkRestriction.AtLeast(DotNetStandard(x)) -> DotNetStandard x -// | x -> failwithf "Unknown .NET moniker %O" x -// -// let filtered = -// newRestrictions -// |> List.filter (fun x -> x <> r && x <> n) -// -// filtered @ [FrameworkRestriction.AtLeast(newLowest)] -// -// if restrictions = filtered then sorting filtered else optimizeRestrictions filtered - -//let hasDotNetFrameworkOrAnyCase = -// List.exists (fun (_,_,rs) -> -// rs = [] || -// rs -// |> List.exists (function -// | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true -// | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true -// | _ -> false)) let optimizeDependencies originalDependencies = - //let grouped = originalDependencies |> List.groupBy (fun (n,v,_) -> n,v) - // - //let expanded = - // [for (n,vr,r:FrameworkRestriction list) in originalDependencies do - // for r' in r do - // yield n,vr,r'] - // |> List.groupBy (fun (_,_,r) -> r) - // - //let invertedRestrictions = - // [for restriction,packages in expanded do - // match restriction with - // | FrameworkRestriction.Exactly(DotNetFramework _ as r) -> - // yield r,packages |> List.map (fun (n,v,_) -> n,v) - // | _ -> () ] - // |> List.sortBy fst - // - //let invertedStandardRestrictions = - // [for restriction,packages in expanded do - // match restriction with - // | FrameworkRestriction.Exactly(DotNetStandard _ as r) -> - // yield r,packages |> List.map (fun (n,v,_) -> n,v) - // | _ -> () ] - // |> List.sortBy fst - // - //let globalMax = - // invertedRestrictions - // |> List.tryLast - // |> Option.map fst - // - //let globalStandardMax = - // invertedStandardRestrictions - // |> List.tryLast - // |> Option.map fst - // - //let globalMin = - // invertedRestrictions - // |> List.tryHead - // |> Option.map fst - // - //let globalStandardMin = - // invertedStandardRestrictions - // |> List.tryHead - // |> Option.map fst - // - //let emptyRestrictions = - // [for (n,vr,r:FrameworkRestriction list) in originalDependencies do - // if r = [] then - // yield n,vr] - // |> Set.ofList - // - //let allRestrictions = - // [for (n,vr,r:FrameworkRestriction list) in originalDependencies do - // yield r] - // |> Set.ofList - // - //let restrictionsPerPackage = - // originalDependencies - // |> List.groupBy (fun (n,vr,r) -> n,vr) - // |> List.map (fun ((n,vr),rs) -> - // n,vr, - // (rs - // |> List.map (fun (_,_,r) -> r) - // |> Set.ofList)) - // - //let packagesWithAllRestrictions = - // restrictionsPerPackage - // |> List.filter (fun (_,_,rs) -> rs = allRestrictions) - // |> List.map (fun (n,vr,_) -> n,vr) - // |> Set.ofList - // - //let newRestictions = - // [for (name,versionRequirement:VersionRequirement),group in grouped do - // if name <> PackageName "" then - // let hasEmpty = not (Set.isEmpty emptyRestrictions) && Set.contains (name,versionRequirement) emptyRestrictions - // let hasAll = not (Set.isEmpty packagesWithAllRestrictions) && Set.contains (name,versionRequirement) packagesWithAllRestrictions - // - // if hasEmpty && hasAll then - // yield name,versionRequirement,[] - // else - // let sorted = - // group - // |> List.map (fun (_,_,res) -> res) - // |> List.concat - // |> List.distinct - // |> List.sort - // - // let localMaxDotNetRestriction = findMaxDotNetRestriction sorted - // let localMaxStandardRestriction = findMaxStandardRestriction sorted - // let globalMax = defaultArg globalMax localMaxDotNetRestriction - // let globalStandardMax = defaultArg globalStandardMax localMaxStandardRestriction - // - // let plain = - // match sorted with - // | [] -> - // let globalStandardMin = defaultArg globalStandardMin localMaxDotNetRestriction - // - // let frameworks = - // match globalMin with - // | Some globalMin -> - // KnownTargetProfiles.DotNetFrameworkVersions - // |> List.filter (fun fw -> DotNetFramework(fw) < globalMin) - // |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetFramework(fw))) - // | _ -> - // KnownTargetProfiles.DotNetFrameworkVersions - // |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetFramework(fw))) - // - // let standards = - // KnownTargetProfiles.DotNetStandardVersions - // |> List.filter (fun fw -> DotNetStandard(fw) < globalStandardMin) - // |> List.map (fun fw -> FrameworkRestriction.Exactly(DotNetStandard(fw))) - // - // frameworks @ standards - // - // | _ -> sorted - // - // let dotnetRestrictions,others = - // plain - // |> List.partition (fun p -> - // match p with - // | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true - // | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true - // | FrameworkRestriction.Exactly(DotNetStandard(_)) -> true - // | FrameworkRestriction.AtLeast(DotNetStandard(_)) -> true - // | _ -> false) - // - // let restrictions' = - // dotnetRestrictions - // |> List.map (fun restriction -> - // match restriction with - // | FrameworkRestriction.Exactly(DotNetFramework _ as r) -> - // if r = localMaxDotNetRestriction && r = globalMax then - // FrameworkRestriction.AtLeast r - // else - // restriction - // | FrameworkRestriction.Exactly (DotNetStandard _ as r) -> - // if r = localMaxStandardRestriction && r = globalStandardMax then - // FrameworkRestriction.AtLeast r - // else - // restriction - // | _ -> restriction) - // - // let restrictions = optimizeRestrictions restrictions' - // - // yield name,versionRequirement,others @ restrictions] - - //let hasDotNetFrameworkOrStandard = - // newRestictions - // |> List.exists (fun (_,_,rs) -> - // rs - // |> List.exists (function - // | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true - // | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true - // | FrameworkRestriction.Exactly(DotNetStandard(_)) -> true - // | FrameworkRestriction.AtLeast(DotNetStandard(_)) -> true - // | _ -> false)) - - //if not hasDotNetFrameworkOrStandard then - // newRestictions - //else - // let newRestictions = - // if hasDotNetFrameworkOrAnyCase originalDependencies then - // newRestictions - // else - // newRestictions - //|> List.map (fun (name,vr,rs) -> - // let newRs = - // rs - // |> List.collect (function - // | FrameworkRestriction.Exactly(DotNetStandard(r)) -> - // let compatible = - // KnownTargetProfiles.DotNetFrameworkIdentifiers - // |> List.filter (fun p -> p.IsCompatible(DotNetStandard r)) - // |> List.map (fun p -> FrameworkRestriction.Exactly p) - // FrameworkRestriction.AtLeast(DotNetStandard(r)) :: compatible - // | FrameworkRestriction.AtLeast(DotNetStandard(r)) -> - // let compatible = - // KnownTargetProfiles.DotNetFrameworkIdentifiers - // |> List.filter (fun p -> p.IsCompatible(DotNetStandard r)) - // |> List.map (fun p -> FrameworkRestriction.AtLeast p) - // FrameworkRestriction.AtLeast(DotNetStandard(r)) :: compatible - // | r -> [r]) - // |> optimizeRestrictions - // - // name,vr,newRs) - - - //newRestictions - //|> List.map (fun (p,v,rs) -> - // let filtered = - // rs - // |> List.map (fun r -> - // match r with - // | FrameworkRestriction.Portable (portable, fws) -> - // let newPortable = - // portable.Split('+') - // |> Array.filter (fun s -> s.StartsWith "net" |> not) - // |> fun xs -> String.Join("+",xs) - // let newFws = - // fws - // |> List.filter (fun fw -> - // fw.IsSameCategoryAs (DotNetFramework FrameworkVersion.V1) || - // fw.IsSameCategoryAs (DotNetUnity DotNetUnityVersion.V3_5_Web) || - // fw.IsSameCategoryAs (DotNetStandard DotNetStandardVersion.V1_0) || - // fw.IsSameCategoryAs (DotNetCore DotNetCoreVersion.V1_0) - // |> not) - // FrameworkRestriction.Portable (newPortable, newFws) - // | _ -> r) - // p,v,filtered) - originalDependencies |> List.map (fun (a,b,c) -> a,b, ExplicitRestriction c) @@ -764,75 +413,11 @@ let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestriction | AutoDetectFramework, ExplicitRestriction FrameworkRestriction.HasNoRestriction -> AutoDetectFramework | AutoDetectFramework, AutoDetectFramework -> AutoDetectFramework | ExplicitRestriction fr1 , ExplicitRestriction fr2 -> ExplicitRestriction (FrameworkRestriction.combineRestrictionsWithAnd fr1 fr2) - //let filtered = - // match list1, list2 with - // | [],_ -> list2 - // | _,[] -> list1 - // | _ -> - // [for x in list1 do - // for y in list2 do - // let c = combineRestrictions false x y - // if c <> [] then yield! c] - // - //let tryLoose = - // (filtered |> List.exists (fun r -> match r.GetOneIdentifier with | Some (FrameworkIdentifier.DotNetFramework _ ) -> true | _ -> false) |> not) && - // (list2 |> List.exists (fun r -> match r.GetOneIdentifier with | Some (FrameworkIdentifier.DotNetFramework _ ) -> true | _ -> false)) - // - //let filtered = - // if tryLoose then - // match list1, list2 with - // | [],_ -> list2 - // | _,[] -> list1 - // | _ -> - // [for x in list1 do - // for y in list2 do - // let c = combineRestrictions true x y - // if c <> [] then yield! c] - // else - // filtered - // - //let optimized = - // filtered - // |> optimizeRestrictions - //FrameworkRestrictionList optimized | _ -> failwithf "The framework restriction %O and %O could not be combined." list1 list2 /// Get if a target should be considered with the specified restrictions let isTargetMatchingRestrictions (restriction:FrameworkRestriction, target)= restriction.IsMatch target - - //match target with - //| SinglePlatform pf -> restriction.RepresentedFrameworks |> Seq.contains pf - //| PortableProfile (_, fws) -> - // // TODO: Review - check if we need to use exists instead of forall? - // fws - // |> Seq.forall (fun fw -> - // restriction.RepresentedFrameworks |> Seq.contains fw) - - //memoize <| fun (restrictions:FrameworkRestriction list, target) -> - // if List.isEmpty restrictions then true else - // match target with - // | SinglePlatform pf -> - // restrictions - // |> List.exists (fun restriction -> - // match restriction with - // | FrameworkRestriction.Exactly (Native(NoBuildMode,NoPlatform)) -> - // match pf with - // | Native(_) -> true - // | _ -> false - // | FrameworkRestriction.Exactly fw -> - // pf = fw - // | FrameworkRestriction.Portable _ -> false - // | FrameworkRestriction.AtLeast fw -> - // pf.IsAtLeast(fw) - // | FrameworkRestriction.Between(min,max) -> - // pf.IsBetween(min,max)) - // | _ -> - // restrictions - // |> List.exists (fun restriction -> - // match restriction with - // | FrameworkRestriction.Portable _ -> true - // | _ -> false) /// Get all targets that should be considered with the specified restrictions let applyRestrictionsToTargets (restriction:FrameworkRestriction) (targets: TargetProfile list) = diff --git a/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs b/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs index fe61e32919..ea6e6f7fc7 100644 --- a/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs +++ b/tests/Paket.Tests/InstallModel/FrameworkIdentifierSpecs.fs @@ -24,7 +24,7 @@ let ``should serialize basic framework versions net20, net40, net45 ...``() = [] let ``should serialize silverlight framework identifier correctly``() = - (Silverlight SilverlightVersion.V5).ToString() |> shouldEqual "sl50" + (Silverlight SilverlightVersion.V5).ToString() |> shouldEqual "sl5" [] let ``should understand basic dnx``() = diff --git a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs index 68b6ef5a6b..d9a37db8de 100644 --- a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs +++ b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs @@ -281,8 +281,8 @@ let ``should install not use net40-full for client profile``() = |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll" model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net40-full\Newtonsoft.Json.dll" - model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) - |> Seq.map (fun f -> f.Path) |> shouldNotContain @"..\Newtonsoft.Json\lib\net40-full\Newtonsoft.Json.dll" + //model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) + // |> Seq.map (fun f -> f.Path) |> shouldNotContain @"..\Newtonsoft.Json\lib\net40-full\Newtonsoft.Json.dll" [] let ``should handle lib install of Microsoft.Net.Http for .NET 4.5``() = diff --git a/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs b/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs index ea78af24b1..8192b1336c 100644 --- a/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs +++ b/tests/Paket.Tests/InstallModel/Xml/LibGit2Sharp.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expectedReferenceNodes = """ - + ..\..\..\LibGit2Sharp\lib\net40\LibGit2Sharp.dll @@ -22,7 +22,7 @@ let expectedReferenceNodes = """ let expectedPropertyDefinitionNodes = """ - + <__paket__LibGit2Sharp_props>net40\LibGit2Sharp diff --git a/tests/Paket.Tests/InstallModel/Xml/Plossum.fs b/tests/Paket.Tests/InstallModel/Xml/Plossum.fs index e76636afe5..2d7673229c 100644 --- a/tests/Paket.Tests/InstallModel/Xml/Plossum.fs +++ b/tests/Paket.Tests/InstallModel/Xml/Plossum.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expected = """ - + ..\..\..\Plossum.CommandLine\lib\net40\Plossum CommandLine.dll diff --git a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs index 7e6a4f407a..9732faa095 100644 --- a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs +++ b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expected = """ - + True diff --git a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs index 15cca76c41..2b34f0d14f 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs @@ -22,7 +22,7 @@ let expectedReferenceNodes = """ - + ..\..\..\System.Data.SQLite.Core\lib\net40\System.Data.SQLite.dll @@ -59,7 +59,7 @@ let expectedPropertyDefinitionNodes = """ <__paket__System_Data_SQLite_Core_targets>net20\System.Data.SQLite.Core - + <__paket__System_Data_SQLite_Core_targets>net40\System.Data.SQLite.Core diff --git a/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs b/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs index ecb2413049..b04aa4757b 100644 --- a/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs +++ b/tests/Paket.Tests/InstallModel/Xml/System.Spatial.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expected = """ - + ..\..\..\System.Spatial\lib\net40\System.Spatial.dll diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs index d492acfbf5..1f925b3097 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs @@ -37,7 +37,7 @@ let expected = """ - + ..\..\..\Microsoft.Net.Http\lib\net40\System.Net.Http.dll diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs index 239758ed4e..94e3cd2664 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expected = """ - + ..\..\..\Microsoft.Net.Http\lib\net40\System.Net.Http.dll diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs index 85c86180e7..5c49ab1dbf 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithExistingFrameworkReferences.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expected = """ - + ..\..\..\Microsoft.Net.Http\lib\net40\System.Net.Http.dll diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs index 0c642a9e3e..0267226bd4 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpWithFrameworkReferences.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expected = """ - + ..\..\..\Microsoft.Net.Http\lib\net40\System.Net.Http.dll diff --git a/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs b/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs index 314b4741d3..4acd801400 100644 --- a/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs +++ b/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs @@ -15,7 +15,7 @@ let expectedPropertyNodes = """ let expectedPropertyDefinitionNodes = """ - + <__paket__xunit_runner_visualstudio_props>net20\xunit.runner.visualstudio diff --git a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs index cfa6063ecb..64e8dc6f84 100644 --- a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs +++ b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs @@ -23,7 +23,7 @@ let graph1 = let expected1 = """REFERENCES: STRICT COPY-LOCAL: FALSE -RESTRICTION: >= NET45 +RESTRICTION: >= net45 NUGET remote: http://www.nuget.org/api/v2 Castle.Windsor-log4net (3.2)""" @@ -181,10 +181,10 @@ nuget NLog.Contrib "NLog.Contrib","1.0.0",["NLog",DependenciesFileParser.parseVersionRequirement ">= 1.0.1"] ] - let expected = """FRAMEWORK: >= NET40 + let expected = """RESTRICTION: >= net40 NUGET remote: https://www.nuget.org/api/v2 - NLog (1.0.1) + NLog (1.0.1) - restriction: net40 NLog.Contrib (1.0) NLog (>= 1.0.1)""" @@ -198,7 +198,7 @@ NUGET getVersion resolved.[PackageName "NLog"] |> shouldEqual "1.0.1" resolved.[PackageName "NLog"].Settings.FrameworkRestrictions |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.AtLeast(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) + |> shouldEqual (FrameworkRestriction.Exactly(FrameworkIdentifier.DotNetFramework(FrameworkVersion.V4))) resolved |> LockFileSerializer.serializePackages cfg.Groups.[Constants.MainDependencyGroup].Options diff --git a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs index b6269a770e..b5c0702512 100644 --- a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs @@ -19,15 +19,15 @@ let TestData: obj[][] = (DotNetFramework FrameworkVersion.V4)|]; [|"Empty.fsprojtest"; (SinglePlatform(DotNetFramework FrameworkVersion.V4)); - "net40-full"; + "net40"; (DotNetFramework FrameworkVersion.V4)|]; [|"NewSilverlightClassLibrary.csprojtest"; (SinglePlatform(Silverlight SilverlightVersion.V5)); - "sl50"; + "sl5"; (Silverlight SilverlightVersion.V5)|]; [|"FSharp.Core.Fluent-3.1.fsprojtest"; portable; - "portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1"; + "portable-net45+win8+wp8+wpa81"; (DotNetFramework FrameworkVersion.V4_5)|]; |] diff --git a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs index 38cebbb793..5bf3f2939c 100644 --- a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs +++ b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs @@ -216,8 +216,47 @@ nuget Marten""" getVersion resolved.[PackageName "Npgsql"] |> shouldEqual "3.1.4" let graph6 = - graph1 @ GraphOfNuspecs [ + """ + + + Chessie + 0.6.0 + + + + + + + + + + + + + + + """ + """ + + + FSharp.Core + 4.0.0.1 + + + """ + """ + + + FSharp.Core + 4.0.1.7-alpha + + + + + + +""" """ diff --git a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs index a7a34698f3..2a284aa786 100644 --- a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs +++ b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs @@ -10,55 +10,6 @@ open Paket.Requirements open Paket.Domain open Paket.TestHelpers - -[] -let ``should optimize 2 restriction set with only exactly``() = - let original = - [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] - - let expected = - [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] - - original - |> optimizeDependencies - |> shouldEqual expected - -[] -let ``should optimize 2 restriction set with only exactly and client framework``() = - let original = - [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] - - let expected = - [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)))] - - original - |> optimizeDependencies - |> shouldEqual expected - -[] -let ``should optimize 2 restriction sets with between``() = - let original = - [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases, (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4)))] - - let expected = - [PackageName("P1"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P2"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V3_5),DotNetFramework(FrameworkVersion.V4)))] - - original - |> optimizeDependencies - |> shouldEqual expected - [] let ``empty set filtered with empty restrictions should give empty set``() = Set.empty @@ -255,19 +206,3 @@ let ``should optimize real world restrictions 3``() = let result = makeOrList original |> getExplicitRestriction result |> shouldEqual expected - - - -[] -let ``should optimize real world .NET Standard restrictions``() = - let original = - [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)) - FrameworkRestriction.AtLeast (DotNetStandard(DotNetStandardVersion.V1_1)) - FrameworkRestriction.AtLeast (DotNetStandard(DotNetStandardVersion.V1_3))] - - let expected = - [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_5_1)) - FrameworkRestriction.AtLeast (DotNetStandard(DotNetStandardVersion.V1_1))] - - let result = optimizeRestrictions original - result |> shouldEqual expected \ No newline at end of file From 6951693f0e172f4fbbe1878ed26e681cafc92dd6 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 03:21:18 +0200 Subject: [PATCH 14/47] increase cache version --- src/Paket.Core/Dependencies/Nuget.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Paket.Core/Dependencies/Nuget.fs b/src/Paket.Core/Dependencies/Nuget.fs index 7a8e9c7420..28b7a327e3 100644 --- a/src/Paket.Core/Dependencies/Nuget.fs +++ b/src/Paket.Core/Dependencies/Nuget.fs @@ -56,7 +56,7 @@ type NuGetPackageCache = Version: string CacheVersion: string } - static member CurrentCacheVersion = "3.37" + static member CurrentCacheVersion = "4.0" let inline normalizeUrl(url:string) = url.Replace("https://","http://").Replace("www.","") From 8d15286217de28428761f6a4fc6517acd41ee3f0 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 14:12:03 +0200 Subject: [PATCH 15/47] more cleanup and more test fixes. --- src/Paket.Core/Dependencies/NuGetV2.fs | 7 +- src/Paket.Core/Dependencies/NuGetV3.fs | 5 +- src/Paket.Core/Dependencies/Nuspec.fs | 5 +- .../Versioning/FrameworkHandling.fs | 34 +++++++-- src/Paket.Core/Versioning/PlatformMatching.fs | 63 ++++++++------- src/Paket.Core/Versioning/Requirements.fs | 33 ++++---- .../InstallModel/Penalty/PenaltySpecs.fs | 1 + tests/Paket.Tests/InstallModel/Xml/RxXaml.fs | 2 +- .../InstallModel/Xml/xunit.runner.fs | 2 +- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 4 +- .../ProjectFile/TargetFrameworkSpecs.fs | 2 +- .../ReferencesFile/ReferencesFileSpecs.fs | 45 ++++++----- .../Versioning/DependencySetSpecs.fs | 76 ++++++++++--------- .../Versioning/FrameworkRestrictionTests.fs | 24 ++++++ .../Versioning/RestrictionFilterSpecs.fs | 8 -- 15 files changed, 184 insertions(+), 127 deletions(-) diff --git a/src/Paket.Core/Dependencies/NuGetV2.fs b/src/Paket.Core/Dependencies/NuGetV2.fs index 74dbcb83b5..2724cd1881 100644 --- a/src/Paket.Core/Dependencies/NuGetV2.fs +++ b/src/Paket.Core/Dependencies/NuGetV2.fs @@ -213,8 +213,11 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra rawPackages |> Seq.collect (fun (_,_,pp) -> match pp.Platforms with - | [h] -> [h] - | _ -> []) + | [h] -> [SinglePlatform h] + | plats when plats.Length > 1 -> [TargetProfile.FindPortable plats] + | _ -> + traceWarnfn "Could not detect frameworks in '%s', ignoring..." pp.Name + []) |> Seq.toList let cleanedPackages = rawPackages diff --git a/src/Paket.Core/Dependencies/NuGetV3.fs b/src/Paket.Core/Dependencies/NuGetV3.fs index e6f8224c19..e073f400d1 100644 --- a/src/Paket.Core/Dependencies/NuGetV3.fs +++ b/src/Paket.Core/Dependencies/NuGetV3.fs @@ -253,8 +253,9 @@ let getPackageDetails (source:NugetV3Source) (packageName:PackageName) (version: not catalogData.Listed.Value else false - - let optimized = Requirements.optimizeDependencies dependencies + // TODO: We probably need our new restriction logic here because I guess what nuget gives us is not enough... + let optimized = + dependencies |> List.map (fun (m,v,r) -> m,v, ExplicitRestriction r) return { Dependencies = optimized PackageName = packageName.ToString() diff --git a/src/Paket.Core/Dependencies/Nuspec.fs b/src/Paket.Core/Dependencies/Nuspec.fs index 81ead9dd9f..6a360167b8 100644 --- a/src/Paket.Core/Dependencies/Nuspec.fs +++ b/src/Paket.Core/Dependencies/Nuspec.fs @@ -84,11 +84,12 @@ type Nuspec = | Some framework when framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable").StartsWith "portable" -> let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") let fws = (PlatformMatching.extractPlatforms framework).Platforms - [] // TODO: Maybe fws? + [TargetProfile.FindPortable(fws)] + //[] // TODO: Maybe fws? | Some framework -> match FrameworkDetection.Extract framework with - | Some x -> [x] + | Some x -> [SinglePlatform x] | None -> [] | _ -> []) |> List.concat diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index c407287240..4fad4e1cc2 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -112,6 +112,12 @@ type UAPVersion = match this with | UAPVersion.V10 -> "100" + member this.NetCoreVersion = + // WTF: https://github.com/onovotny/MSBuildSdkExtras/blob/8d2d4ad63b552481da06e646dbb6504abc415260/src/build/platforms/Windows.targets + match this with + // Assumed from C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore + | UAPVersion.V10 -> "v5.0" + [] /// The .NET Standard version. @@ -220,18 +226,21 @@ type Platform = [] type WindowsPhoneVersion = | V7 + | V7_1 | V7_5 | V8 | V8_1 member this.ShortString() = match this with | WindowsPhoneVersion.V7 -> "7" + | WindowsPhoneVersion.V7_1 -> "71" | WindowsPhoneVersion.V7_5 -> "75" | WindowsPhoneVersion.V8 -> "8" | WindowsPhoneVersion.V8_1 -> "81" override this.ToString() = match this with | WindowsPhoneVersion.V7 -> "v7.0" + | WindowsPhoneVersion.V7_1 -> "v7.1" | WindowsPhoneVersion.V7_5 -> "v7.5" | WindowsPhoneVersion.V8 -> "v8.0" | WindowsPhoneVersion.V8_1 -> "v8.1" @@ -270,6 +279,13 @@ type WindowsVersion = | V8 | V8_1 | V10 + member this.NetCoreVersion = + // WTF: https://github.com/onovotny/MSBuildSdkExtras/blob/8d2d4ad63b552481da06e646dbb6504abc415260/src/build/platforms/Windows.targets + match this with + | WindowsVersion.V8 -> "v4.5" + | WindowsVersion.V8_1 -> "v4.5.1" + // Assumed from C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore + | WindowsVersion.V10 -> "v5.0" member this.ShortString() = match this with | WindowsVersion.V8 -> "8" @@ -395,7 +411,8 @@ type FrameworkIdentifier = | WindowsPhoneApp WindowsPhoneAppVersion.V8 -> [ ] | WindowsPhoneApp WindowsPhoneAppVersion.V8_1 -> [ DotNetStandard DotNetStandardVersion.V1_2 ] | WindowsPhone WindowsPhoneVersion.V7 -> [ ] - | WindowsPhone WindowsPhoneVersion.V7_5 -> [ WindowsPhone WindowsPhoneVersion.V7 ] + | WindowsPhone WindowsPhoneVersion.V7_1 -> [ WindowsPhone WindowsPhoneVersion.V7 ] + | WindowsPhone WindowsPhoneVersion.V7_5 -> [ WindowsPhone WindowsPhoneVersion.V7_1 ] | WindowsPhone WindowsPhoneVersion.V8 -> [ WindowsPhone WindowsPhoneVersion.V7_5; DotNetStandard DotNetStandardVersion.V1_0 ] | WindowsPhone WindowsPhoneVersion.V8_1 -> [ WindowsPhone WindowsPhoneVersion.V8 ] @@ -481,8 +498,8 @@ module FrameworkDetection = | "win8" | "windows8" | "win80" | "netcore45" | "win" | "winv45" -> Some (Windows WindowsVersion.V8) | "win81" | "windows81" | "netcore46" | "netcore451" | "winv451" -> Some (Windows WindowsVersion.V8_1) | "wp7" | "wp70" | "wpv7" | "wpv70" | "sl4-wp7"| "sl4-wp70" -> Some (WindowsPhone WindowsPhoneVersion.V7) - //| "wp71" | "wpv71" | "sl4-wp71" | "sl4-wp" -> Some (WindowsPhone WindowsPhoneVersion.V7_5) - | "wp75" | "wpv75" | "sl4-wp75" | "sl4-wp" -> Some (WindowsPhone WindowsPhoneVersion.V7_5) + | "wp71" | "wpv71" | "sl4-wp71" | "sl4-wp" -> Some (WindowsPhone WindowsPhoneVersion.V7_1) + | "wp75" | "wpv75" | "sl4-wp75" -> Some (WindowsPhone WindowsPhoneVersion.V7_5) | "wp8" | "wp80" | "wpv80" -> Some (WindowsPhone WindowsPhoneVersion.V8) | "wpa00" | "wpa" | "wpa81" | "wpav81" | "wpapp81" | "wpapp" -> Some (WindowsPhoneApp WindowsPhoneAppVersion.V8_1) | "wp81" | "wpv81" -> Some (WindowsPhone WindowsPhoneVersion.V8_1) @@ -807,6 +824,7 @@ module KnownTargetProfiles = let WindowsPhoneVersions = [ WindowsPhoneVersion.V7 + WindowsPhoneVersion.V7_1 WindowsPhoneVersion.V7_5 WindowsPhoneVersion.V8 WindowsPhoneVersion.V8_1 @@ -912,7 +930,12 @@ module KnownTargetProfiles = type TargetProfile with - static member FindPortable (fws) = + member p.Frameworks = + match p with + | SinglePlatform fw -> [fw] + | PortableProfile p -> p.Frameworks + static member FindPortable (fws: _ list) = + if fws.Length = 0 then failwithf "can not find portable for an empty list (Details: Empty lists need to be handled earlier with a warning)!" let minimal = fws |> List.filter (function @@ -946,7 +969,8 @@ type TargetProfile with #else PortableProfile (UnsupportedProfile fws) #endif - else PortableProfile (UnsupportedProfile fws) + else + PortableProfile (UnsupportedProfile fws) // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list /// true when x is supported by y, for example netstandard15 is supported by netcore10 diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index 04ddf07bbf..4c8a7c143e 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -2,6 +2,7 @@ open System open ProviderImplementation.AssemblyReader.Utils.SHA1 +open Logging [] let MaxPenalty = 1000000 @@ -9,27 +10,27 @@ let MaxPenalty = 1000000 type ParsedPlatformPath = { Name : string Platforms : FrameworkIdentifier list } - static member Empty = { Name = ""; Platforms = [] } - + static member Empty = { Name = ""; Platforms = [] } + static member FromTargetProfile (p:TargetProfile) = + { Name = p.ToString(); Platforms = p.Frameworks } + member x.ToTargetProfile = + match x.Platforms with + | _ when System.String.IsNullOrEmpty x.Name -> None + | [] -> None // Not detected earlier. + | [p] -> Some (SinglePlatform p) + | plats -> Some (TargetProfile.FindPortable plats) let inline split (path : string) = path.Split('+') |> Array.map (fun s -> System.Text.RegularExpressions.Regex.Replace(s, "portable\\d*-","")) -let extractPlatforms = memoize (fun path -> { Name = path; Platforms = split path |> Array.choose FrameworkDetection.Extract |> Array.toList }) - -//let knownInPortable = -// KnownTargetProfiles.AllPortableProfiles -// |> List.collect snd -// |> List.distinct - -//let tryGetProfile platforms = -// let filtered = -// platforms.Platforms -// |> List.filter (fun p -> knownInPortable |> Seq.exists ((=) p)) -// |> List.sort - -// KnownTargetProfiles.AllPortableProfiles |> Seq.tryFind (snd >> (=) filtered) -// |> Option.map PortableProfile +let extractPlatforms = memoize (fun path -> + if System.String.IsNullOrEmpty path then ParsedPlatformPath.Empty + else + let platforms = split path |> Array.choose FrameworkDetection.Extract |> Array.toList + if platforms.Length = 0 then + failwithf "Could not detect any platforms from '%s'" path + //traceWarnfn "Could not detect any platforms from '%s'" path + { Name = path; Platforms = platforms }) // TODO: In future work this stuff should be rewritten. This penalty stuff is more random than a proper implementation. let rec getPlatformPenalty = @@ -74,7 +75,7 @@ let getPathPenalty = | _ -> 2000 // an empty path is considered compatible with every .NET target, but with a high penalty so explicit paths are preferred match path.Platforms with | _ when String.IsNullOrWhiteSpace path.Name -> handleEmpty() - | [] -> handleEmpty() + | [] -> MaxPenalty // Ignore this path as it contains no platforms, but the folder apparently has a name -> we failed to detect the framework and ignore it | [ h ] -> getPlatformPenalty(platform,SinglePlatform h) | _ -> getPlatformPenalty(platform, TargetProfile.FindPortable path.Platforms)) @@ -247,7 +248,7 @@ let getTargetCondition (target:TargetProfile) = "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Unity Micro v3.5')" version | DotNetUnity(version) when version = DotNetUnityVersion.V3_5_Web -> "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Unity Web v3.5')" version - | Windows(version) -> "$(TargetFrameworkIdentifier) == '.NETCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version + | Windows(version) -> "$(TargetFrameworkIdentifier) == '.NETCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version.NetCoreVersion | Silverlight(version) -> "$(TargetFrameworkIdentifier) == 'Silverlight'", sprintf "$(TargetFrameworkVersion) == '%O'" version | WindowsPhoneApp(version) -> "$(TargetFrameworkIdentifier) == 'WindowsPhoneApp'", sprintf "$(TargetFrameworkVersion) == '%O'" version | WindowsPhone(version) -> "$(TargetFrameworkIdentifier) == 'WindowsPhone'", sprintf "$(TargetFrameworkVersion) == '%O'" version @@ -255,7 +256,8 @@ let getTargetCondition (target:TargetProfile) = | MonoTouch -> "$(TargetFrameworkIdentifier) == 'MonoTouch'", "" | MonoMac -> "$(TargetFrameworkIdentifier) == 'MonoMac'", "" | XamariniOS -> "$(TargetFrameworkIdentifier) == 'Xamarin.iOS'", "" - | UAP(version) ->"$(TargetPlatformIdentifier) == 'UAP'", sprintf "$(TargetPlatformVersion.StartsWith('%O'))" version + | UAP(version) -> // "$(TargetPlatformIdentifier) == 'UAP'", sprintf "$(TargetPlatformVersion.StartsWith('%O'))" version + "$(TargetFrameworkIdentifier) == '.NETCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version.NetCoreVersion | XamarinMac -> "$(TargetFrameworkIdentifier) == 'Xamarin.Mac'", "" | Native(NoBuildMode,NoPlatform) -> "true", "" | Native(NoBuildMode,bits) -> (sprintf "'$(Platform)'=='%s'" bits.AsString), "" @@ -263,25 +265,26 @@ let getTargetCondition (target:TargetProfile) = | PortableProfile p -> sprintf "$(TargetFrameworkProfile) == '%O'" p.ProfileName,"" let getCondition (referenceCondition:string option) (allTargets: TargetProfile list list) (targets : TargetProfile list) = - let inline CheckIfFullyInGroup typeName matchF (processed,targets) = + let inline CheckIfFullyInGroup typeName matchF filterRestF (processed,targets) = let fullyContained = KnownTargetProfiles.AllDotNetProfiles |> List.filter matchF |> List.forall (fun p -> targets |> Seq.exists ((=) p)) if fullyContained then - (sprintf "$(TargetFrameworkIdentifier) == '%s'" typeName,"") :: processed,targets |> List.filter (matchF >> not) + (sprintf "$(TargetFrameworkIdentifier) == '%s'" typeName,"") :: processed,targets |> List.filter (filterRestF >> not) else processed,targets - + let inline CheckIfFullyInGroupS typeName matchF (processed,targets) = + CheckIfFullyInGroup typeName matchF matchF (processed,targets) let grouped,targets = ([],targets) - |> CheckIfFullyInGroup "true" (fun _ -> true) - |> CheckIfFullyInGroup ".NETFramework" (function SinglePlatform (DotNetFramework _) -> true | _ -> false) - |> CheckIfFullyInGroup ".NETCore" (function SinglePlatform (Windows _) -> true | _ -> false) - |> CheckIfFullyInGroup "Silverlight" (function SinglePlatform (Silverlight _) -> true | _ -> false) - |> CheckIfFullyInGroup "WindowsPhoneApp" (function SinglePlatform (WindowsPhoneApp _) -> true | _ -> false) - |> CheckIfFullyInGroup "WindowsPhone" (function SinglePlatform (WindowsPhone _) -> true | _ -> false) + |> CheckIfFullyInGroupS "true" (fun _ -> true) + |> CheckIfFullyInGroupS ".NETFramework" (function SinglePlatform (DotNetFramework _) -> true | _ -> false) + |> CheckIfFullyInGroup ".NETCore" (function SinglePlatform (Windows _) -> true | _ -> false) (function SinglePlatform (Windows _) -> true | SinglePlatform (UAP _) -> true | _ -> false) + |> CheckIfFullyInGroupS "Silverlight" (function SinglePlatform (Silverlight _) -> true | _ -> false) + |> CheckIfFullyInGroupS "WindowsPhoneApp" (function SinglePlatform (WindowsPhoneApp _) -> true | _ -> false) + |> CheckIfFullyInGroupS "WindowsPhone" (function SinglePlatform (WindowsPhone _) -> true | _ -> false) //let targets = // targets @@ -318,6 +321,8 @@ let getCondition (referenceCondition:string option) (allTargets: TargetProfile l | [] -> "false" | [ detail ] -> sprintf "%s And %s" group detail | conditions -> + if conditions |> Seq.exists (String.IsNullOrEmpty) then + failwithf "Something went wrong (Details: probably in CheckIfFullyInGroup). Please open an issue." let detail = conditions |> fun cs -> String.Join(" Or ",cs) diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 30fa01b853..819c8f1d80 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -165,12 +165,14 @@ type FrameworkRestriction = module FrameworkRestriction = let EmptySet = { OrFormulas = [] } // false let NoRestriction = { OrFormulas = [ { Literals = [] } ] } // true - let AtLeastPlatform pf = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (AtLeastL pf) ] } ] } - let ExactlyPlatform pf = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromLiteral (ExactlyL pf) ] } ] } + let FromLiteral lit = { OrFormulas = [ { Literals = [ lit ] } ] } + let AtLeastPlatform pf = FromLiteral (FrameworkRestrictionLiteral.FromLiteral (AtLeastL pf)) + let ExactlyPlatform pf = FromLiteral (FrameworkRestrictionLiteral.FromLiteral (ExactlyL pf)) let Exactly id = ExactlyPlatform (SinglePlatform id) let AtLeastPortable (name, fws)= AtLeastPlatform (TargetProfile.FindPortable fws) let AtLeast id = AtLeastPlatform (SinglePlatform id) - let NotAtLeast id = { OrFormulas = [ { Literals = [ FrameworkRestrictionLiteral.FromNegatedLiteral (AtLeastL (SinglePlatform id)) ] } ] } + let NotAtLeastPlatform pf = FromLiteral (FrameworkRestrictionLiteral.FromNegatedLiteral (AtLeastL pf)) + let NotAtLeast id = NotAtLeastPlatform (SinglePlatform id) let private simplify (fr:FrameworkRestriction) = /// When we have a restriction like (>=net35 && =net45 @@ -401,12 +403,6 @@ let parseRestrictionsLegacy failImmediatly (text:string) = yield FrameworkRestriction.Exactly x] |> List.fold (fun state item -> FrameworkRestriction.combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet - -let optimizeDependencies originalDependencies = - originalDependencies - |> List.map (fun (a,b,c) -> a,b, ExplicitRestriction c) - - let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestrictions) = match list1,list2 with | ExplicitRestriction FrameworkRestriction.HasNoRestriction, AutoDetectFramework -> AutoDetectFramework @@ -713,10 +709,10 @@ type PackageRequirement = PackageRequirement.Compare(this,that,None,0,0) | _ -> invalidArg "that" "cannot compare value of different types" -let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = +let addFrameworkRestrictionsToDependencies rawDependencies (frameworkGroups:TargetProfile list) = let frameworkGroupPaths = frameworkGroups - |> Seq.map (fun fw -> {PlatformMatching.ParsedPlatformPath.Name = fw.ToString(); PlatformMatching.ParsedPlatformPath.Platforms = [fw] }) + |> Seq.map (PlatformMatching.ParsedPlatformPath.FromTargetProfile) |> Seq.toList let referenced = rawDependencies @@ -735,14 +731,14 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = | _ -> FrameworkRestriction.AtLeastPortable(packageGroup.Name, packageGroup.Platforms) frameworkGroups - |> Seq.filter (fun frameworkGroup -> - // special casing for portable -> should be removed once portable is a normal FrameworkIdentifier - if packageGroup.Platforms.Length < 2 then packageGroup.Platforms |> Seq.contains frameworkGroup |> not else true) + //|> Seq.filter (fun frameworkGroup -> + // // special casing for portable -> should be removed once portable is a normal FrameworkIdentifier + // if packageGroup.Platforms.Length < 2 then packageGroup.Platforms |> Seq.contains frameworkGroup |> not else true) // TODO: Check if this is needed (I think the logic below is a general version of this subset logic) |> Seq.filter (fun frameworkGroup -> // filter all restrictions which would render this group to nothing (ie smaller restrictions) // filter out unrelated restrictions - packageGroupRestriction.IsSubsetOf (FrameworkRestriction.AtLeast frameworkGroup) |> not) + packageGroupRestriction.IsSubsetOf (FrameworkRestriction.AtLeastPlatform frameworkGroup) |> not) |> Seq.fold (fun curRestr frameworkGroup -> // We start with the restriction inherently given by the current group, // But this is too broad as other groups might "steal" better suited frameworks @@ -752,8 +748,8 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = // (>=net451 && <=netstandard13) for one and (>=netstandard13 && <=net451) for the other group // but now net461 which supports netstandard13 is nowhere -> we need to decide here and add back the intersection - let missing = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.AtLeast frameworkGroup) - let combined = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.NotAtLeast frameworkGroup) + let missing = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.AtLeastPlatform frameworkGroup) + let combined = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.NotAtLeastPlatform frameworkGroup) match packageGroup.Platforms, missing.RepresentedFrameworks with | [ packageGroupFw ], firstMissing :: _ -> // the common set goes to the better matching one @@ -781,4 +777,5 @@ let addFrameworkRestrictionsToDependencies rawDependencies frameworkGroups = // name, req, restriction) // - optimizeDependencies referenced \ No newline at end of file + referenced + |> List.map (fun (a,b,c) -> a,b, ExplicitRestriction c) \ No newline at end of file diff --git a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs index 01652776d0..4d5b4f2f9b 100644 --- a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs +++ b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs @@ -127,6 +127,7 @@ module ``Given a list of paths`` = flattend |> shouldNotContain (KnownTargetProfiles.FindPortableProfile "Profile41") module ``ProfileAnalyzer tests`` = + () //[] //let ``test that we cannot detect portable-net40+sl4+win8+wp71+wpa81`` () = // let res = Paket.PlatformMatching.tryGetProfile (extractPlatforms "portable-net40+sl4+win8+wp71+wpa81") diff --git a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs index 9732faa095..63f428a7c4 100644 --- a/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs +++ b/tests/Paket.Tests/InstallModel/Xml/RxXaml.fs @@ -63,7 +63,7 @@ let expected = """ - + True diff --git a/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs b/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs index 4acd801400..7bd450e67e 100644 --- a/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs +++ b/tests/Paket.Tests/InstallModel/Xml/xunit.runner.fs @@ -20,7 +20,7 @@ let expectedPropertyDefinitionNodes = """ <__paket__xunit_runner_visualstudio_props>net20\xunit.runner.visualstudio - + <__paket__xunit_runner_visualstudio_props>portable-net45+aspnetcore50+win+wpa81+wp80+monotouch+monoandroid\xunit.runner.visualstudio diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index ec76f5705f..3a56f9fe78 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -512,11 +512,11 @@ let ``should parse reactiveui lockfile``() = packages.[8].Name |> shouldEqual (PackageName "Rx-WindowStoreApps") packages.[8].Version |> shouldEqual (SemVer.Parse "2.2.5") - (packages.[8].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "[winv4.5]" + (packages.[8].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "win8" packages.[10].Name |> shouldEqual (PackageName "Rx-Xaml") packages.[10].Version |> shouldEqual (SemVer.Parse "2.2.5") - (packages.[10].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "[winv4.5; wpv8.0; >= net45]" + (packages.[10].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "|| (win8) (wp8) (>= net45)" let multipleFeedLockFile = """NUGET remote: http://internalfeed/NugetWebFeed/nuget diff --git a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs index b5c0702512..00a498c625 100644 --- a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs @@ -43,5 +43,5 @@ let ``should detect the correct framework on test projects`` projectFile expecte let p = ProjectFile.TryLoad("./ProjectFile/TestData/" + projectFile).Value p.GetTargetProfile() |> shouldEqual expectedProfile p.GetTargetProfile().ToString() |> shouldEqual expectedProfileString - p.GetTargetProfile() |> shouldEqual (SinglePlatform expectedTargetFramework) + //p.GetTargetProfile() |> shouldEqual (portable) diff --git a/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs b/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs index c5e07960fc..494755005e 100644 --- a/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs +++ b/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs @@ -230,31 +230,36 @@ xUnit import_targets: false""" |> shouldEqual (normalizeLineEndings expected) -let refFileContentWithMultipleSettings = """Castle.Windsor copy_local: false, import_targets: false, framework: net35, >= net40 +let legacyRefFileContentWithMultipleSettings = """Castle.Windsor copy_local: false, import_targets: false, framework: net35, >= net40 Newtonsoft.Json content: none, framework: net40 xUnit import_targets: false""" +let refFileContentWithMultipleSettings = """Castle.Windsor copy_local: false, import_targets: false, restriction: || (net35) (>= net40) +Newtonsoft.Json content: none, restriction: net40 +xUnit import_targets: false""" + [] let ``should parse and serialize lines with multiple settings settings correctly``() = - let refFile = ReferencesFile.FromLines(toLines refFileContentWithMultipleSettings) - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Length |> shouldEqual 3 - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Head.Name |> shouldEqual (PackageName "Castle.Windsor") - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Head.Settings.CopyLocal |> shouldEqual (Some false) - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Head.Settings.ImportTargets |> shouldEqual (Some false) - - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Name |> shouldEqual (PackageName "Newtonsoft.Json") - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Settings.CopyLocal |> shouldEqual None - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Settings.ImportTargets |> shouldEqual None - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Settings.OmitContent |> shouldEqual (Some ContentCopySettings.Omit) - - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Name |> shouldEqual (PackageName "xUnit") - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Settings.CopyLocal |> shouldEqual None - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Settings.ImportTargets |> shouldEqual (Some false) - refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Settings.OmitContent |> shouldEqual None - - refFile.ToString() - |> normalizeLineEndings - |> shouldEqual (normalizeLineEndings refFileContentWithMultipleSettings) + for refFileContent in [legacyRefFileContentWithMultipleSettings; refFileContentWithMultipleSettings] do + let refFile = ReferencesFile.FromLines(toLines refFileContent) + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Length |> shouldEqual 3 + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Head.Name |> shouldEqual (PackageName "Castle.Windsor") + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Head.Settings.CopyLocal |> shouldEqual (Some false) + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Head.Settings.ImportTargets |> shouldEqual (Some false) + + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Name |> shouldEqual (PackageName "Newtonsoft.Json") + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Settings.CopyLocal |> shouldEqual None + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Settings.ImportTargets |> shouldEqual None + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Head.Settings.OmitContent |> shouldEqual (Some ContentCopySettings.Omit) + + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Name |> shouldEqual (PackageName "xUnit") + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Settings.CopyLocal |> shouldEqual None + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Settings.ImportTargets |> shouldEqual (Some false) + refFile.Groups.[Constants.MainDependencyGroup].NugetPackages.Tail.Tail.Head.Settings.OmitContent |> shouldEqual None + + refFile.ToString() + |> normalizeLineEndings + |> shouldEqual (normalizeLineEndings refFileContentWithMultipleSettings) [] diff --git a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs index 2a284aa786..6b7befd3bb 100644 --- a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs +++ b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs @@ -135,65 +135,69 @@ let ``filtered with Between restriction should filter non-matching`` () = [] let ``should optimize ZendeskApi_v2 ``() = let original = - [PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) - PackageName("AsyncCTP"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) - PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) - PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, (getPortableRestriction "portable-net45+sl40+wp71+win80") - PackageName("Microsoft.Bcl.Async"), VersionRequirement.AllReleases, (getPortableRestriction "portable-net45+sl40+wp71+win80")] + [PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "net35" + PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "net4" + PackageName("AsyncCTP"), (), PlatformMatching.extractPlatforms "net4" + PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "net45" + PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "portable-net45+sl40+wp71+win80" + PackageName("Microsoft.Bcl.Async"),(), PlatformMatching.extractPlatforms "portable-net45+sl40+wp71+win80"] let expected = - [PackageName("Newtonsoft.Json"), VersionRequirement.AllReleases, + [PackageName("Newtonsoft.Json"), (), makeOrList [getPortableRestriction "portable-net45+sl40+wp71+win80" FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V3_5))] - PackageName("AsyncCTP"), VersionRequirement.AllReleases,ExplicitRestriction (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) - PackageName("Microsoft.Bcl.Async"), VersionRequirement.AllReleases,ExplicitRestriction (getPortableRestriction "portable-net45+sl40+wp71+win80")] - - original - |> optimizeDependencies + PackageName("AsyncCTP"), (),ExplicitRestriction (FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V4), DotNetFramework(FrameworkVersion.V4_5))) + PackageName("Microsoft.Bcl.Async"), (),ExplicitRestriction (getPortableRestriction "portable-net45+sl40+wp71+win80")] + let result = + addFrameworkRestrictionsToDependencies original [ + SinglePlatform (DotNetFramework(FrameworkVersion.V3_5)) + SinglePlatform (DotNetFramework(FrameworkVersion.V4)) + SinglePlatform (DotNetFramework(FrameworkVersion.V4_5)) + (PlatformMatching.extractPlatforms "portable-net45+sl40+wp71+win80").ToTargetProfile.Value ] + result |> shouldEqual expected [] let ``should optimize real world restrictions``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_6)))] + [PackageName("P1"), (), PlatformMatching.extractPlatforms "net20" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net35" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net45" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net451" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net46"] let expected = - [PackageName("P1"), VersionRequirement.AllReleases, + [PackageName("P1"), (), makeOrList - [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2)) - FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V3_5)) - FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5)) - FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1)) - FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_6))]] + [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V2))]] - let result = optimizeDependencies original + let result = + addFrameworkRestrictionsToDependencies original + ([ FrameworkVersion.V2; FrameworkVersion.V3_5 + FrameworkVersion.V4_5; FrameworkVersion.V4_5_1 + FrameworkVersion.V4_6] |> List.map (DotNetFramework >> SinglePlatform)) result |> shouldEqual expected [] let ``should optimize real world restrictions 2``() = let original = - [PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1))) - PackageName("P1"), VersionRequirement.AllReleases, (FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_6)))] + [PackageName("P1"), (), PlatformMatching.extractPlatforms "net20" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net4" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net45" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net451" + PackageName("P1"), (), PlatformMatching.extractPlatforms "net46"] let expected = - [PackageName("P1"), VersionRequirement.AllReleases, + [PackageName("P1"), (), makeOrList - [FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V2)) - FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4)) - FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5)) - FrameworkRestriction.Exactly (DotNetFramework(FrameworkVersion.V4_5_1)) - FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V4_6))]] + [FrameworkRestriction.AtLeast (DotNetFramework(FrameworkVersion.V2))]] - let result = optimizeDependencies original + let result = + addFrameworkRestrictionsToDependencies original + ([ FrameworkVersion.V2; FrameworkVersion.V4 + FrameworkVersion.V4_5; FrameworkVersion.V4_5_1 + FrameworkVersion.V4_6] |> List.map (DotNetFramework >> SinglePlatform)) result |> shouldEqual expected [] diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index 6f5627fcd8..3b45915070 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -20,6 +20,30 @@ let isSupported (portable:PortableProfileType) (other:PortableProfileType) = |> Seq.length relevantFrameworks >= tfs.Length && portable <> other +[] +let ``__unknowntfm__ should not match everything`` () = + try + let model = + InstallModel.CreateFromLibs(Paket.Domain.PackageName "Rx-XAML", SemVer.Parse "2.2.4", FrameworkRestriction.NoRestriction, + [ { Paket.NuGet.UnparsedPackageFile.FullPath = @"..\Rx-XAML\lib\__unknowntfm__\System.Reactive.Windows.Threading.dll" + Paket.NuGet.UnparsedPackageFile.PathWithinPackage = "lib/__unknowntfm__/System.Reactive.Windows.Threading.dll" } ], + [], + [], + { References = NuspecReferences.All + OfficialName = "Reactive Extensions - XAML Support Library" + Version = "2.2.4" + Dependencies = [] + LicenseUrl = "" + IsDevelopmentDependency = false + FrameworkAssemblyReferences = []}) + let target = PortableProfile PortableProfileType.Profile344 + let newModel = model.ApplyFrameworkRestrictions (FrameworkRestriction.ExactlyPlatform target) + newModel.GetCompileReferences target |> Seq.toArray + |> shouldEqual [||] + with e -> + // Throwing is OK as well. + () + [] let ``Profile 158 should not support itself``() = isSupported Profile158 Profile158 diff --git a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs index 991302ce66..f214cf825e 100644 --- a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs @@ -38,14 +38,6 @@ let ``should filter >=net40 and >= net45``() = filterRestrictions l1 l2 |> shouldEqual l2 -[] -let ``should filter >= net40 and portable``() = - let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) - let l2 = ExplicitRestriction (getPortableRestriction("net45")) - - filterRestrictions l1 l2 - |> shouldEqual (ExplicitRestriction FrameworkRestriction.NoRestriction) - [] let ``should filter >= net40 and >= net20 < net46``() = let l1 = ExplicitRestriction (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4))) From 281b221d5898566049dcf4a560cce86f3548a293 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 15:48:27 +0200 Subject: [PATCH 16/47] cleanup and support for unknown portable profiles. --- .../Paket.IntegrationTests/TestHelper.fs | 2 + .../Versioning/FrameworkHandling.fs | 349 ++++++------------ src/Paket.Core/Versioning/PlatformMatching.fs | 29 +- .../InstallModel/Xml/SystemNetHttpForNet4.fs | 2 +- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 4 +- .../Paket.Tests/ProjectFile/ConditionSpecs.fs | 3 +- .../Versioning/FrameworkRestrictionTests.fs | 91 ++--- 7 files changed, 174 insertions(+), 306 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/TestHelper.fs b/integrationtests/Paket.IntegrationTests/TestHelper.fs index 2adc1663d3..e5e312943b 100644 --- a/integrationtests/Paket.IntegrationTests/TestHelper.fs +++ b/integrationtests/Paket.IntegrationTests/TestHelper.fs @@ -10,6 +10,7 @@ open System open System.IO let scenarios = System.Collections.Generic.List<_>() +let isLiveUnitTesting = AppDomain.CurrentDomain.GetAssemblies() |> Seq.exists (fun a -> a.GetName().Name = "Microsoft.CodeAnalysis.LiveUnitTesting.Runtime") let paketToolPath = FullName(__SOURCE_DIRECTORY__ + "../../../bin/paket.exe") let integrationTestPath = FullName(__SOURCE_DIRECTORY__ + "../../../integrationtests/scenarios") @@ -26,6 +27,7 @@ let cleanupAllScenarios() = scenarios.Clear() let prepare scenario = + if isLiveUnitTesting then Assert.Inconclusive("Integration tests are disabled when in a Live-Unit-Session") if scenarios.Count > 10 then cleanupAllScenarios() diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index 4fad4e1cc2..ced19fe7d0 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -3,6 +3,7 @@ open System.IO open System open System.Diagnostics +open Logging /// The .NET Standard version. @@ -922,11 +923,106 @@ module KnownTargetProfiles = |> List.distinct |> List.sort - let FindPortableProfile name = + let TryFindPortableProfile (name:string) = + let lowerName = name.ToLowerInvariant() AllProfiles - |> List.pick (function - | PortableProfile p when p.ProfileName = name -> Some (PortableProfile p) - | _ -> None) + |> List.tryPick (function + | PortableProfile p when p.ProfileName.ToLowerInvariant() = lowerName -> Some (PortableProfile p) + | _ -> None) + let FindPortableProfile name = + match TryFindPortableProfile name with + | Some s -> s + | None -> failwithf "tried to find portable profile '%s' but it is unknown to paket" name + +module PortableProfileSupportCalculation = + let isSupported (portable:PortableProfileType) (other:PortableProfileType) = + let name, tfs = portable.ProfileName, portable.Frameworks + + let otherName, otherfws = other.ProfileName, other.Frameworks + let weSupport = + tfs + |> List.collect (fun tf -> tf.RawSupportedPlatformsTransitive) + + let relevantFrameworks = + otherfws + |> Seq.filter (fun fw -> + weSupport |> List.exists ((=) fw)) + |> Seq.length + relevantFrameworks >= tfs.Length && portable <> other + + let getSupported (portable:PortableProfileType) = + let name, tfs = portable.ProfileName, portable.Frameworks + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun p -> p.ProfileName <> name) + |> List.filter (fun other -> isSupported portable other) + |> List.map PortableProfile + type SupportMap = System.Collections.Concurrent.ConcurrentDictionary + let ofSeq s = s|> dict |> System.Collections.Concurrent.ConcurrentDictionary + let toSeq s = s|> Seq.map (fun (kv:System.Collections.Generic.KeyValuePair<_,_>) -> kv.Key, kv.Value) + let rec buildSupportMap (supportMap:SupportMap) p = + let directMap = supportMap.[p] + directMap + |> List.append (directMap |> List.collect (buildSupportMap supportMap)) + + let filterMap pos (supportMap:SupportMap) : SupportMap = + supportMap + |> toSeq + |> Seq.map (fun (profile, supported) -> + profile, + if supported.Length < pos + 1 then + supported + else + // try to optimize on the 'pos' position + let curPos = supported.[pos] + let supportList = buildSupportMap supportMap curPos // supportMap.[curPos] // + (supported |> List.take pos |> List.filter (fun s -> supportList |> List.contains s |> not)) + @ [curPos] @ + (supported + |> List.skip (pos + 1) + |> List.filter (fun s -> supportList |> List.contains s |> not)) + ) + |> ofSeq + + // Optimize support map, ie remove entries which are not needed + let optimizeSupportMap (supportMap:SupportMap) = + let mutable sup = supportMap + let mutable hasChanged = true + while hasChanged do + hasChanged <- false + let maxNum = sup.Values |> Seq.map (fun l -> l.Length) |> Seq.max + for i in 0 .. maxNum - 1 do + let old = sup + sup <- filterMap i sup + if old.Count <> sup.Count then + hasChanged <- true + sup + let private getSupportedPortables p = + getSupported p + |> List.choose (function PortableProfile p -> Some p | _ -> failwithf "Expected portable") + + let createInitialSupportMap () = + KnownTargetProfiles.AllPortableProfiles + |> List.map (fun p -> p, getSupportedPortables p) + |> ofSeq + + let mutable private supportMap = optimizeSupportMap (createInitialSupportMap()) + + let getSupportedPreCalculated (p:PortableProfileType) = + match supportMap.TryGetValue p with + | true, v -> v + | _ -> + match p with + | UnsupportedProfile tfs -> + match supportMap.TryGetValue p with + | true, v -> v + | _ -> + let clone = supportMap |> toSeq |> ofSeq + clone.[p] <- getSupportedPortables p + let opt = optimizeSupportMap clone + let result = opt.[p] + supportMap <- opt + result + | _ -> failwithf "Expected that default profiles are already created." type TargetProfile with @@ -936,6 +1032,7 @@ type TargetProfile with | PortableProfile p -> p.Frameworks static member FindPortable (fws: _ list) = if fws.Length = 0 then failwithf "can not find portable for an empty list (Details: Empty lists need to be handled earlier with a warning)!" + let fallback = PortableProfile (UnsupportedProfile (fws |> List.sort)) let minimal = fws |> List.filter (function @@ -964,19 +1061,27 @@ type TargetProfile with match firstMatch with | Some p -> PortableProfile p | None -> -#if DEBUG - failwithf "Could not find pcl profile" -#else - PortableProfile (UnsupportedProfile fws) -#endif + traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback + fallback else - PortableProfile (UnsupportedProfile fws) + traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback + fallback // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list /// true when x is supported by y, for example netstandard15 is supported by netcore10 member x.IsSupportedBy y = - x = y || - (y.SupportedPlatforms |> Seq.exists (fun s -> x.IsSupportedBy s)) + match x with + | PortableProfile (PortableProfileType.UnsupportedProfile xs' as x') -> + // custom profiles are not in our lists -> custom logic + match y with + | PortableProfile y' -> + PortableProfileSupportCalculation.isSupported y' x' + | SinglePlatform y' -> + y'.RawSupportedPlatformsTransitive |> Seq.exists (fun y'' -> + xs' |> Seq.contains y'') + | _ -> + x = y || + (y.SupportedPlatforms |> Seq.exists (fun s -> x.IsSupportedBy s)) //x = y || // (x.SupportedPlatforms |> Seq.exists (fun x' -> x' = y && not (x'.IsSameCategoryAs x))) || // (y.SupportedPlatforms |> Seq.exists (fun y' -> y' = x && not (y'.IsSameCategoryAs y))) @@ -1088,223 +1193,5 @@ type TargetProfile with |> List.map PortableProfile rawSupported @ profilesSupported | PortableProfile p -> - // This is generated by the "Generate Support Table" test case! - let supported = - match p with - | Profile2 -> - [ - ] - | Profile3 -> - [ - Profile36 - ] - | Profile4 -> - [ - Profile95 - ] - | Profile5 -> - [ - Profile37 - Profile92 - ] - | Profile6 -> - [ - Profile5 - Profile42 - Profile102 - ] - | Profile7 -> - [ - Profile6 - Profile47 - Profile78 - Profile111 - ] - | Profile14 -> - [ - Profile3 - Profile37 - ] - | Profile18 -> - [ - Profile3 - Profile41 - ] - | Profile19 -> - [ - Profile14 - Profile18 - Profile42 - ] - | Profile23 -> - [ - Profile18 - Profile46 - ] - | Profile24 -> - [ - Profile19 - Profile23 - Profile47 - ] - | Profile31 -> - [ - Profile78 - Profile157 - ] - | Profile32 -> - [ - Profile151 - Profile157 - ] - | Profile36 -> - [ - Profile88 - ] - | Profile37 -> - [ - Profile136 - Profile225 - ] - | Profile41 -> - [ - Profile143 - ] - | Profile42 -> - [ - Profile37 - Profile41 - Profile147 - Profile240 - ] - | Profile44 -> - [ - Profile7 - Profile151 - ] - | Profile46 -> - [ - Profile41 - Profile154 - ] - | Profile47 -> - [ - Profile42 - Profile46 - Profile158 - Profile255 - ] - | Profile49 -> - [ - Profile78 - ] - | Profile78 -> - [ - Profile158 - Profile259 - ] - | Profile84 -> - [ - Profile157 - ] - | Profile88 -> - [ - Profile2 - ] - | Profile92 -> - [ - Profile225 - ] - | Profile95 -> - [ - Profile2 - ] - | Profile96 -> - [ - Profile88 - Profile95 - ] - | Profile102 -> - [ - Profile92 - Profile240 - ] - | Profile104 -> - [ - Profile4 - Profile96 - ] - | Profile111 -> - [ - Profile102 - Profile255 - Profile259 - ] - | Profile136 -> - [ - Profile36 - Profile328 - ] - | Profile143 -> - [ - Profile36 - Profile96 - ] - | Profile147 -> - [ - Profile136 - Profile143 - Profile336 - ] - | Profile151 -> - [ - Profile111 - ] - | Profile154 -> - [ - Profile104 - Profile143 - ] - | Profile157 -> - [ - Profile259 - ] - | Profile158 -> - [ - Profile147 - Profile154 - Profile344 - ] - | Profile225 -> - [ - Profile328 - ] - | Profile240 -> - [ - Profile225 - Profile336 - ] - | Profile255 -> - [ - Profile240 - Profile344 - ] - | Profile259 -> - [ - Profile344 - ] - | Profile328 -> - [ - ] - | Profile336 -> - [ - Profile328 - ] - | Profile344 -> - [ - Profile336 - ] - | UnsupportedProfile _ -> [] - - supported + PortableProfileSupportCalculation.getSupportedPreCalculated p |> List.map PortableProfile diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index 4c8a7c143e..ad75a97b3e 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -21,16 +21,25 @@ type ParsedPlatformPath = | plats -> Some (TargetProfile.FindPortable plats) let inline split (path : string) = path.Split('+') - |> Array.map (fun s -> System.Text.RegularExpressions.Regex.Replace(s, "portable\\d*-","")) + |> Array.map (fun s -> System.Text.RegularExpressions.Regex.Replace(s, @"portable[\d\.]*-","")) +// TODO: This function does now quite a lot, there probably should be several functions. let extractPlatforms = memoize (fun path -> if System.String.IsNullOrEmpty path then ParsedPlatformPath.Empty else - let platforms = split path |> Array.choose FrameworkDetection.Extract |> Array.toList + let splits = split path + let platforms = splits |> Array.choose FrameworkDetection.Extract |> Array.toList if platforms.Length = 0 then - failwithf "Could not detect any platforms from '%s'" path + if splits.Length = 1 && splits.[0].ToLowerInvariant().StartsWith "profile" then + // might be something like portable4.6-profile151 + let found = + KnownTargetProfiles.FindPortableProfile splits.[0] + |> ParsedPlatformPath.FromTargetProfile + { found with Name = path } + else + failwithf "Could not detect any platforms from '%s'" path //traceWarnfn "Could not detect any platforms from '%s'" path - { Name = path; Platforms = platforms }) + else { Name = path; Platforms = platforms }) // TODO: In future work this stuff should be rewritten. This penalty stuff is more random than a proper implementation. let rec getPlatformPenalty = @@ -40,8 +49,16 @@ let rec getPlatformPenalty = 0 else match targetPlatform, packagePlatform with - // There is no point in searching for frameworks in portables... - | PortableProfile _, SinglePlatform _ -> MaxPenalty + | PortableProfile _, SinglePlatform _ -> + // There is no point in searching for frameworks in portables... + MaxPenalty + | _, PortableProfile (PortableProfileType.UnsupportedProfile fws) -> + // We cannot find unsupported profiles in our "SupportedPlatforms" list + // Just check if we are compatible at all and return a high penalty + + if packagePlatform.IsSupportedBy targetPlatform then + 700 + else MaxPenalty | _ -> let penalty = targetPlatform.SupportedPlatforms diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs index 94e3cd2664..239758ed4e 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttpForNet4.fs @@ -9,7 +9,7 @@ open Paket.Requirements let expected = """ - + ..\..\..\Microsoft.Net.Http\lib\net40\System.Net.Http.dll diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index 14b87a7d57..183391f050 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -129,10 +129,10 @@ let ``can detect explicit dependencies for Microsoft.AspNet.WebApi.Client``() = let dependencies = odata.Dependencies |> Array.ofList dependencies.[0] |> shouldEqual (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 6.0.4"), - makeOrList [getPortableRestriction("portable-wp80+win+wp81+wpa81"); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]) + makeOrList [getPortableRestriction("portable-net45+win8+wp8+wp81+wpa81"); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]) dependencies.[1] |> shouldEqual (PackageName "Microsoft.Net.Http", DependenciesFileParser.parseVersionRequirement(">= 2.2.22"), - makeOrList [getPortableRestriction("portable-wp80+win+wp81+wpa81")]) + makeOrList [getPortableRestriction("portable-net45+win8+wp8+wp81+wpa81")]) [] let ``can detect explicit dependencies for WindowsAzure.Storage``() = diff --git a/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs b/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs index 13abf09be7..7d33f5aed3 100644 --- a/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/ConditionSpecs.fs @@ -52,7 +52,8 @@ let ``should detect Silverlight version from path``() = [] let ``should detect WindowsPhone version from path``() = FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp75\RestSharp.WindowsPhone.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_5) - FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp\TechTalk.SpecFlow.WindowsPhone7.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_5) + FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp71\RestSharp.WindowsPhone.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_1) + FrameworkDetection.DetectFromPath(@"..\..\packages\RestSharp\lib\sl4-wp\TechTalk.SpecFlow.WindowsPhone7.dll")|> element |> shouldEqual (WindowsPhone WindowsPhoneVersion.V7_1) [] let ``should detect framework version from uppercase path``() = diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index 3b45915070..fc6c1d82db 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -5,20 +5,22 @@ open FsUnit open NUnit.Framework open Paket.Requirements -let isSupported (portable:PortableProfileType) (other:PortableProfileType) = - let name, tfs = portable.ProfileName, portable.Frameworks - - let otherName, otherfws = other.ProfileName, other.Frameworks - let weSupport = - tfs - |> List.collect (fun tf -> tf.RawSupportedPlatformsTransitive) +[] +let ``CustomProfile is Supported by its Platforms``() = + let unknownProfile = + (PlatformMatching.extractPlatforms "portable-net45+monoandroid10+monotouch10+xamarinios10").ToTargetProfile.Value - let relevantFrameworks = - otherfws - |> Seq.filter (fun fw -> - weSupport |> List.exists ((=) fw)) - |> Seq.length - relevantFrameworks >= tfs.Length && portable <> other + unknownProfile.IsSupportedBy (SinglePlatform (DotNetFramework FrameworkVersion.V4_5)) + |> shouldEqual true + unknownProfile.IsSupportedBy (SinglePlatform (DotNetFramework FrameworkVersion.V4)) + |> shouldEqual false + + unknownProfile.IsSupportedBy (SinglePlatform (MonoAndroid)) + |> shouldEqual true + unknownProfile.IsSupportedBy (SinglePlatform (MonoTouch)) + |> shouldEqual true + unknownProfile.IsSupportedBy (SinglePlatform (Silverlight SilverlightVersion.V5)) + |> shouldEqual false [] let ``__unknowntfm__ should not match everything`` () = @@ -46,71 +48,30 @@ let ``__unknowntfm__ should not match everything`` () = [] let ``Profile 158 should not support itself``() = - isSupported Profile158 Profile158 + PortableProfileSupportCalculation.isSupported Profile158 Profile158 |> shouldEqual false [] let ``Profile 158 should not support Profile 78, as there is no silverlight on 78``() = - isSupported Profile158 Profile78 + PortableProfileSupportCalculation.isSupported Profile158 Profile78 |> shouldEqual false - isSupported Profile78 Profile158 + PortableProfileSupportCalculation.isSupported Profile78 Profile158 |> shouldEqual true [] let ``Profile 344 should support Profile 336, as it has the same frameworks but is lower``() = - isSupported Profile336 Profile344 + PortableProfileSupportCalculation.isSupported Profile336 Profile344 |> shouldEqual false - isSupported Profile344 Profile336 + PortableProfileSupportCalculation.isSupported Profile344 Profile336 |> shouldEqual true [] let ``Generate Support Table``() = // TODO: Should we include this? - let getSupported (portable:PortableProfileType) = - let name, tfs = portable.ProfileName, portable.Frameworks - KnownTargetProfiles.AllPortableProfiles - |> List.filter (fun p -> p.ProfileName <> name) - |> List.filter (fun other -> isSupported portable other) - |> List.map PortableProfile - let mutable supportMap = - KnownTargetProfiles.AllPortableProfiles - |> List.map (fun p -> - p, - getSupported p - |> List.choose (function PortableProfile p -> Some p | _ -> failwithf "Expected portable")) - |> dict - - let rec buildSupportMap p = - let directMap = supportMap.[p] - directMap - |> List.append (directMap |> List.collect buildSupportMap) - - let filterMap pos (supportMap:System.Collections.Generic.IDictionary<_,_>) = - supportMap - |> Seq.map (fun (kv:System.Collections.Generic.KeyValuePair<_,_>) -> - let profile = kv.Key - let supported : PortableProfileType list = kv.Value - - profile, - if supported.Length < pos + 1 then - supported - else - // try to optimize on the 'pos' position - let curPos = supported.[pos] - let supportList = buildSupportMap curPos // supportMap.[curPos] // - (supported |> List.take pos |> List.filter (fun s -> supportList |> List.contains s |> not)) - @ [curPos] @ - (supported - |> List.skip (pos + 1) - |> List.filter (fun s -> supportList |> List.contains s |> not)) - ) - |> dict - - for i in 0 .. 10 do - for i in 0 .. 15 do supportMap <- filterMap i supportMap + let mutable supportMap = PortableProfileSupportCalculation.createInitialSupportMap() + supportMap <- PortableProfileSupportCalculation.optimizeSupportMap supportMap supportMap - |> Seq.iter (fun (kv:System.Collections.Generic.KeyValuePair<_,_>) -> - let p = kv.Key - let supported : PortableProfileType list = kv.Value + |> PortableProfileSupportCalculation.toSeq + |> Seq.iter (fun (p, supported) -> System.Diagnostics.Debug.WriteLine(sprintf "| %s ->" p.ProfileName) System.Diagnostics.Debug.WriteLine(" [ ") supported @@ -125,7 +86,7 @@ let ``Generate Support Table``() = let ``Unknown Portables are detected correctly``() = PlatformMatching.extractPlatforms "portable-monotouch+monoandroid" |> function { Platforms = o } -> TargetProfile.FindPortable o - |> shouldEqual (PortableProfile (PortableProfileType.UnsupportedProfile [MonoTouch; MonoAndroid])) + |> shouldEqual (PortableProfile (PortableProfileType.UnsupportedProfile [MonoAndroid; MonoTouch])) [] let ``Portables are detected correctly``() = // http://nugettoolsdev.azurewebsites.net/4.0.0/parse-framework?framework=portable-net451%2Bwin81%2Bwpa81%2Bwaspt2 @@ -141,7 +102,7 @@ let ``Portables are detected correctly``() = |> List.map (function { Platforms = [ h] } -> SinglePlatform h | {Platforms = o} -> TargetProfile.FindPortable o) let expected = [ SinglePlatform (DotNetFramework FrameworkVersion.V4); - PortableProfile (PortableProfileType.UnsupportedProfile [MonoTouch; MonoAndroid]) + PortableProfile (PortableProfileType.UnsupportedProfile [MonoAndroid; MonoTouch]) PortableProfile (PortableProfileType.Profile328); PortableProfile (PortableProfileType.Profile259) PortableProfile (PortableProfileType.Profile32) PortableProfile (PortableProfileType.Profile78) From d02e5a0e26776d57877cddd320d5ee4aa48dfa7c Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 17:32:18 +0200 Subject: [PATCH 17/47] cleanup and fix almost everything but the parser. --- .../Dependencies/DependenciesFileParser.fs | 11 +++ .../Dependencies/PackageResolver.fs | 37 +-------- src/Paket.Core/PackageAnalysis/Queries.fs | 7 -- .../PaketConfigFiles/DependenciesFile.fs | 56 +++++++------- .../PaketConfigFiles/InstallModel.fs | 21 ------ src/Paket.Core/PaketConfigFiles/LockFile.fs | 5 +- src/Paket.Core/Versioning/PlatformMatching.fs | 38 ++-------- src/Paket.Core/Versioning/Requirements.fs | 33 +++++--- .../InstallModel/Xml/SystemNetHttp.fs | 3 +- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 75 +++++++++++++------ .../Simplifier/BasicScenarioSpecs.fs | 29 ++++--- .../Versioning/FrameworkRestrictionTests.fs | 15 ++++ 12 files changed, 160 insertions(+), 170 deletions(-) diff --git a/src/Paket.Core/Dependencies/DependenciesFileParser.fs b/src/Paket.Core/Dependencies/DependenciesFileParser.fs index ac8a4f5957..90a9fc72bd 100644 --- a/src/Paket.Core/Dependencies/DependenciesFileParser.fs +++ b/src/Paket.Core/Dependencies/DependenciesFileParser.fs @@ -295,7 +295,18 @@ module DependenciesFileParser = let options = ParserOption.FrameworkRestrictions (ExplicitRestriction restrictions) Some (ParserOptions options) + | String.RemovePrefix "restriction" trimmed -> + let text = trimmed.Replace(":", "").Trim() + + if text = "auto-detect" then + Some (ParserOptions (ParserOption.AutodetectFrameworkRestrictions)) + else + let restrictions = Requirements.parseRestrictions true text + if String.IsNullOrWhiteSpace text |> not && restrictions = FrameworkRestriction.NoRestriction then + failwithf "Could not parse framework restriction \"%s\"" text + let options = ParserOption.FrameworkRestrictions (ExplicitRestriction restrictions) + Some (ParserOptions options) | String.RemovePrefix "content" trimmed -> let setting = match trimmed.Replace(":","").Trim() with diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 28680d9568..8de6ab01f6 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -57,43 +57,11 @@ module DependencySetFilter = let _,_,dependencyRestrictions = dependency let dependencyRestrictions = dependencyRestrictions |> getExplicitRestriction if dependencyRestrictions = FrameworkRestriction.NoRestriction then true else - // TODO: fix broken logic - - // This is the framework restriction we build for (example = net46) // While the dependency specifies the framework restrictions of the dependency ([ >= netstandard13 ]) - // we need to take the dependency, when 'restriction' is a subset of any of 'dependencyRestrictions' + // we need to take the dependency, when the combination still contains packages. + // NOTE: This is not forwards compatible... let combined = FrameworkRestriction.And [ restriction; dependencyRestrictions ] combined.RepresentedFrameworks.Length > 0 - //restriction.IsSubsetOf dependencyRestrictions - //match restriction with - //| FrameworkRestriction.Exactly v1 -> - // dependencyRestrictions - // |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) - // |> Seq.exists (fun r2 -> - // match r2 with - // | FrameworkRestriction.Exactly v2 when v1 = v2 -> true - // | FrameworkRestriction.AtLeast v2 when v1 >= v2 -> true - // | FrameworkRestriction.Between(v2,v3) when v1 >= v2 && v1 < v3 -> true - // | _ -> false) - //| FrameworkRestriction.AtLeast v1 -> - // restrictions - // |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) - // |> Seq.exists (fun r2 -> - // match r2 with - // | FrameworkRestriction.Exactly v2 when v1 <= v2 -> true - // | FrameworkRestriction.AtLeast v2 -> true - // | FrameworkRestriction.Between(v2,v3) when v1 < v3 -> true - // | _ -> false) - //| FrameworkRestriction.Between (min, max) -> - // restrictions - // |> Seq.filter (fun r2 -> restriction.IsSameCategoryAs(r2) = Some(true)) - // |> Seq.exists (fun r2 -> - // match r2 with - // | FrameworkRestriction.Exactly v when v >= min && v < max -> true - // | FrameworkRestriction.AtLeast v when v < max -> true - // | FrameworkRestriction.Between(min',max') when max' >= min && min' < max -> true - // | _ -> false) - //| _ -> true let filterByRestrictions (restrictions:FrameworkRestrictions) (dependencies:DependencySet) : DependencySet = match getExplicitRestriction restrictions with @@ -368,7 +336,6 @@ let private updateRestrictions (pkgConfig:PackageConfig) (package:ResolvedPackag let globalSettings = pkgConfig.GlobalRestrictions |> getExplicitRestriction [packageSettings;dependencySettings;globalSettings] |> Seq.fold (FrameworkRestriction.combineRestrictionsWithAnd) FrameworkRestriction.NoRestriction - //optimizeRestrictions (List.concat) { package with Settings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } diff --git a/src/Paket.Core/PackageAnalysis/Queries.fs b/src/Paket.Core/PackageAnalysis/Queries.fs index 4fc7c0ef9e..785a3dde0e 100644 --- a/src/Paket.Core/PackageAnalysis/Queries.fs +++ b/src/Paket.Core/PackageAnalysis/Queries.fs @@ -67,13 +67,6 @@ let resolveFrameworkForScriptGeneration (dependencies: DependenciesFile) = lazy match restrictions with | Paket.Requirements.AutoDetectFramework -> failwithf "couldn't detect framework" | Paket.Requirements.ExplicitRestriction list -> list.RepresentedFrameworks - //list |> Seq.collect ( - // function - // | Paket.Requirements.FrameworkRestriction.Exactly framework - // | Paket.Requirements.FrameworkRestriction.AtLeast framework -> Seq.singleton framework - // | Paket.Requirements.FrameworkRestriction.Between (bottom,top) -> [bottom; top] |> Seq.ofList //TODO: do we need to cap the list of generated frameworks based on this? also see todo in Requirements.fs for potential generation of range for 'between' - // | Paket.Requirements.FrameworkRestriction.Portable portable -> failwithf "unhandled portable framework %s" portable - //) ) |> Seq.concat ) diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index 12327747fc..cc2cecd608 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -155,26 +155,36 @@ type DependenciesFile(fileName,groups:Map, textRepr if group.Options.Settings.FrameworkRestrictions |> getRestrictionList <> FrameworkRestriction.NoRestriction then dependenciesFile else match group.Packages with | [] -> dependenciesFile - | package::rest -> dependenciesFile - //let commonRestrictions = - // package.Settings.FrameworkRestrictions - // |> getRestrictionList - // |> List.filter (fun r -> - // rest |> Seq.forall (fun p' -> p'.Settings.FrameworkRestrictions |> getRestrictionList |> List.contains r)) - // - //match commonRestrictions with - //| [] -> dependenciesFile - //| _ -> - // let newDependenciesFile = dependenciesFile.AddFrameworkRestriction(group.Name,commonRestrictions) - // group.Packages - // |> List.fold (fun (d:DependenciesFile) package -> - // let oldRestrictions = package.Settings.FrameworkRestrictions |> getRestrictionList - // let newRestrictions = oldRestrictions |> List.filter (fun r -> commonRestrictions |> List.contains r |> not) - // if oldRestrictions = newRestrictions then d else - // let (d:DependenciesFile) = d.Remove(group.Name,package.Name) - // let installSettings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } - // let vr = { VersionRequirement = package.VersionRequirement; ResolverStrategy = package.ResolverStrategyForDirectDependencies } - // d.AddAdditionalPackage(group.Name, package.Name,vr,installSettings)) newDependenciesFile + | package::rest -> //dependenciesFile + let commonRestrictions = + group.Packages + |> Seq.map (fun p' -> p'.Settings.FrameworkRestrictions) + |> Seq.fold (fun a b -> FrameworkRestriction.And [a;b.GetExplicitRestriction()]) FrameworkRestriction.EmptySet + //package.Settings.FrameworkRestrictions + //|> getRestrictionList + //|> List.filter (fun r -> + // rest |> Seq.forall (fun p' -> p'.Settings.FrameworkRestrictions |> getRestrictionList |> List.contains r)) + + match commonRestrictions.RepresentedFrameworks with + | [] -> dependenciesFile + // Only take when our commonRestriction formula is actually "simple" + | _ when commonRestrictions.OrFormulas |> List.forall (fun andFormula -> andFormula.Literals.Length <= 1) -> + let newDependenciesFile = dependenciesFile.AddFrameworkRestriction(group.Name,commonRestrictions) + let newNegatedLiterals = + commonRestrictions.OrFormulas |> List.collect (fun andFormala -> andFormala.Literals) + |> List.map (fun lit -> FrameworkRestriction.FromLiteral { lit with IsNegated = not lit.IsNegated }) + |> List.fold (fun a b -> FrameworkRestriction.Or [ a; b]) FrameworkRestriction.EmptySet + + group.Packages + |> List.fold (fun (d:DependenciesFile) package -> + let oldRestrictions = package.Settings.FrameworkRestrictions |> getRestrictionList + let newRestrictions = FrameworkRestriction.Or [ oldRestrictions; newNegatedLiterals ]// |> List.filter (fun r -> commonRestrictions |> List.contains r |> not) + if oldRestrictions = newRestrictions then d else + let (d:DependenciesFile) = d.Remove(group.Name,package.Name) + let installSettings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } + let vr = { VersionRequirement = package.VersionRequirement; ResolverStrategy = package.ResolverStrategyForDirectDependencies } + d.AddAdditionalPackage(group.Name, package.Name,vr,installSettings)) newDependenciesFile + | _ -> dependenciesFile this.Groups |> Seq.map (fun kv -> kv.Value) @@ -694,12 +704,6 @@ type DependenciesFile(fileName,groups:Map, textRepr | Paket.Requirements.AutoDetectFramework -> failwithf "couldn't detect framework" | Paket.Requirements.ExplicitRestriction list -> list.RepresentedFrameworks |> Seq.choose (function SinglePlatform tf -> Some tf | _ -> None) - //list |> Seq.collect (function - //| Paket.Requirements.FrameworkRestriction.Exactly framework - //| Paket.Requirements.FrameworkRestriction.AtLeast framework -> Seq.singleton framework - //| Paket.Requirements.FrameworkRestriction.Between (bottom,top) -> [bottom; top] |> Seq.ofList //TODO: do we need to cap the list of generated frameworks based on this? also see todo in Requirements.fs for potential generation of range for 'between' - //| Paket.Requirements.FrameworkRestriction.Portable portable -> failwithf "unhandled portable framework %s" portable - //) ) |> Seq.concat ) diff --git a/src/Paket.Core/PaketConfigFiles/InstallModel.fs b/src/Paket.Core/PaketConfigFiles/InstallModel.fs index 216b493c50..80aa2af9b0 100644 --- a/src/Paket.Core/PaketConfigFiles/InstallModel.fs +++ b/src/Paket.Core/PaketConfigFiles/InstallModel.fs @@ -674,27 +674,6 @@ module InstallModel = applyRestrictionsToTargets (reference.FrameworkRestrictions |> getExplicitRestriction) folder.Targets |> Seq.isEmpty |> not - //match reference.FrameworkRestrictions |> getRestrictionList with - //| [] -> true - //| restrictions -> - // restrictions - // |> List.exists (fun restriction -> - // match restriction with - // | FrameworkRestriction.Portable _ -> - // folder.Targets - // |> List.exists (fun target -> - // match target with - // | SinglePlatform _ -> false - // | _ -> true) - // | FrameworkRestriction.Exactly target -> - // folder.GetSinglePlatforms() - // |> List.exists ((=) target) - // | FrameworkRestriction.AtLeast target -> - // folder.GetSinglePlatforms() - // |> List.exists (fun t -> t >= target && t.IsSameCategoryAs(target)) - // | FrameworkRestriction.Between(min,max) -> - // folder.GetSinglePlatforms() - // |> List.exists (fun t -> t >= min && t < max && t.IsSameCategoryAs(min))) let model = if List.isEmpty installModel.CompileLibFolders then diff --git a/src/Paket.Core/PaketConfigFiles/LockFile.fs b/src/Paket.Core/PaketConfigFiles/LockFile.fs index 35bf189814..5603cc9a36 100644 --- a/src/Paket.Core/PaketConfigFiles/LockFile.fs +++ b/src/Paket.Core/PaketConfigFiles/LockFile.fs @@ -128,7 +128,7 @@ module LockFileSerializer = if FrameworkRestriction.NoRestriction = restrictions || restrictions = getExplicitRestriction options.Settings.FrameworkRestrictions then yield sprintf " %O %s" name versionStr else - yield sprintf " %O %s - framework: %s" name versionStr (String.Join(", ",restrictions).ToLower())] + yield sprintf " %O %s - restriction: %O" name versionStr restrictions] String.Join(Environment.NewLine, all |> List.map (fun s -> s.TrimEnd())) @@ -281,8 +281,7 @@ module LockFileParser = InstallOption (CopyContentToOutputDir setting) | _, String.RemovePrefix "FRAMEWORK:" trimmed -> InstallOption(FrameworkRestrictions(ExplicitRestriction (trimmed.Trim() |> Requirements.parseRestrictionsLegacy true))) - // TODO: use new parser here. - | _, String.RemovePrefix "RESTRICTION:" trimmed -> InstallOption(FrameworkRestrictions(ExplicitRestriction (trimmed.Trim() |> Requirements.parseRestrictionsLegacy true))) + | _, String.RemovePrefix "RESTRICTION:" trimmed -> InstallOption(FrameworkRestrictions(ExplicitRestriction (trimmed.Trim() |> Requirements.parseRestrictions true))) | _, String.RemovePrefix "CONDITION:" trimmed -> InstallOption(ReferenceCondition(trimmed.Trim().ToUpper())) | _, String.RemovePrefix "CONTENT:" trimmed -> let setting = diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index ad75a97b3e..abf993d685 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -144,40 +144,14 @@ let getPlatformsSupporting = // http://nugettoolsdev.azurewebsites.net let calculate (x:TargetProfile) = KnownTargetProfiles.AllProfiles - //|> List.collect(function - // | SinglePlatform p -> [p] - // | PortableProfile (_, fws) -> fws) - //|> List.distinct - |> List.filter (fun plat -> plat.SupportedPlatformsTransitive |> Seq.contains x) + |> List.filter (fun plat -> x.IsSupportedBy plat) //match x with - //| PortableProfile (name,fws) -> - // // Portables can be supported by other portables and by all fws given. + //| PortableProfile (PortableProfileType.UnsupportedProfile fws) -> + // + // + //| _ -> // KnownTargetProfiles.AllProfiles - // |> List.filter (function - // | PortableProfile (otherName,otherfws) -> - // // the other portable profile is supported, when the transitive supported set is a superset - // let currentSupportedFrameworks = - // fws - // |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) - // |> List.distinct - // |> List.sort - // let otherSupportedFrameworks = - // otherfws - // |> List.collect (fun fw -> fw.SupportedPlatformsTransitive) - // |> List.distinct - // |> List.sort - // - // // take if the other profile supports all frameworks we support - // currentSupportedFrameworks - // |> Seq.forall (fun fw -> otherSupportedFrameworks |> Seq.exists ((=) fw)) - // | SinglePlatform otherfw -> - // // otherfw is supported if it is supported by of any fw in fws - // fws - // |> Seq.exists (fun fw -> fw.SupportedPlatformsTransitive |> Seq.contains otherfw)) - //| SinglePlatform tf -> - // // SinglePlatforms are only supported by other SinglePlatforms - // getFrameworksSupporting tf - // |> List.map SinglePlatform + // |> List.filter (fun plat -> plat.SupportedPlatformsTransitive |> Seq.contains x) memoize calculate let platformsSupport = diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 819c8f1d80..068abb00ac 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -285,15 +285,23 @@ module FrameworkRestriction = |> List.map (fun andFormula -> { Literals = andFormula.Literals |> List.distinct |> List.sort }) |> List.distinct |> List.sort } - - fr - |> removeNegatedLiteralsWhichOccurSinglePositive - |> removeSubsetLiteralsInAndClause - |> removeSubsetLiteralsInOrClause - |> removeUneccessaryAndClauses - |> removeUneccessaryOrClauses - |> replaceWithNoRestrictionIfAnyLiteralListIsEmpty - |> sortClauses + let optimize fr = + fr + |> removeNegatedLiteralsWhichOccurSinglePositive + |> removeSubsetLiteralsInAndClause + |> removeSubsetLiteralsInOrClause + |> removeUneccessaryAndClauses + |> removeUneccessaryOrClauses + |> replaceWithNoRestrictionIfAnyLiteralListIsEmpty + |> sortClauses + let mutable hasChanged = true + let mutable newFormula = fr + while hasChanged do + let old = newFormula + newFormula <- optimize newFormula + if old = newFormula then hasChanged <- false + newFormula + let rec private And2 (left : FrameworkRestriction) (right : FrameworkRestriction) = match left.OrFormulas with @@ -403,6 +411,9 @@ let parseRestrictionsLegacy failImmediatly (text:string) = yield FrameworkRestriction.Exactly x] |> List.fold (fun state item -> FrameworkRestriction.combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet +let parseRestrictions failImmediatly (text:string) = + parseRestrictionsLegacy failImmediatly text + let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestrictions) = match list1,list2 with | ExplicitRestriction FrameworkRestriction.HasNoRestriction, AutoDetectFramework -> AutoDetectFramework @@ -534,9 +545,7 @@ type InstallSettings = | _ -> None FrameworkRestrictions = match getPair "restriction" with - | Some s -> - // TODO: Change to new parser. - ExplicitRestriction(parseRestrictionsLegacy true s) + | Some s -> ExplicitRestriction(parseRestrictions true s) | _ -> match getPair "framework" with | Some s -> ExplicitRestriction(parseRestrictionsLegacy true s) diff --git a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs index 1f925b3097..49f7b30a96 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SystemNetHttp.fs @@ -75,7 +75,7 @@ let expected = """ - + ..\..\..\Microsoft.Net.Http\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.dll @@ -153,6 +153,7 @@ let expected = """ """ [] +[] let ``should generate Xml for System.Net.Http 2.2.8``() = ensureDir() let model = diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index 3a56f9fe78..4390a5f002 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -465,7 +465,7 @@ let ``should parse portable lockfile``() = packages.[1].Name |> shouldEqual (PackageName "Zlib.Portable") packages.[1].Version |> shouldEqual (SemVer.Parse "1.10.0") - (packages.[1].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "[portable-net40+sl50+wp80+win80]" + (packages.[1].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual ">= portable-net40+win8+wp8+sl5" let reactiveuiLockFile = """NUGET remote: https://www.nuget.org/api/v2 @@ -518,7 +518,7 @@ let ``should parse reactiveui lockfile``() = packages.[10].Version |> shouldEqual (SemVer.Parse "2.2.5") (packages.[10].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "|| (win8) (wp8) (>= net45)" -let multipleFeedLockFile = """NUGET +let multipleFeedLockFileLegacy = """NUGET remote: http://internalfeed/NugetWebFeed/nuget Internal_1 (1.2.10) Newtonsoft.Json (>= 6.0 < 6.1) @@ -536,27 +536,47 @@ let multipleFeedLockFile = """NUGET Microsoft.AspNet.WebApi.Core (>= 5.2.3 < 5.3) """ +let multipleFeedLockFile = """NUGET + remote: http://internalfeed/NugetWebFeed/nuget + Internal_1 (1.2.10) + Newtonsoft.Json (>= 6.0 < 6.1) + log4net (1.2.10) + Newtonsoft.Json (6.0.6) + remote: https://www.nuget.org/api/v2 + Microsoft.AspNet.WebApi (5.2.3) + Microsoft.AspNet.WebApi.WebHost (>= 5.2.3 < 5.3) + Microsoft.AspNet.WebApi.Client (5.2.3) + Microsoft.Net.Http (>= 2.2.22) - restriction: >= portable-net45+win8+wp8+wp81+wpa81 + Newtonsoft.Json (>= 6.0.4) - restriction: >= portable-net45+win8+wp8+wp81+wpa81 + Microsoft.AspNet.WebApi.Core (5.2.3) + Microsoft.AspNet.WebApi.Client (>= 5.2.3) + Microsoft.AspNet.WebApi.WebHost (5.2.3) + Microsoft.AspNet.WebApi.Core (>= 5.2.3 < 5.3) +""" + [] let ``should parse lockfile with multiple feeds``() = - let lockFile = LockFileParser.Parse(toLines multipleFeedLockFile) |> List.head - let references = lockFile.SourceFiles + for lockFileText in [multipleFeedLockFileLegacy;multipleFeedLockFile] do + let lockFile = LockFileParser.Parse(toLines lockFileText) |> List.head + let references = lockFile.SourceFiles - references.Length |> shouldEqual 0 + references.Length |> shouldEqual 0 - let packages = List.rev lockFile.Packages - packages.Length |> shouldEqual 7 + let packages = List.rev lockFile.Packages + packages.Length |> shouldEqual 7 - packages.[3].Name |> shouldEqual (PackageName "Microsoft.AspNet.WebApi") - packages.[3].Version |> shouldEqual (SemVer.Parse "5.2.3") - packages.[3].Source.ToString() |> shouldEqual "https://www.nuget.org/api/v2" + packages.[3].Name |> shouldEqual (PackageName "Microsoft.AspNet.WebApi") + packages.[3].Version |> shouldEqual (SemVer.Parse "5.2.3") + packages.[3].Source.ToString() |> shouldEqual "https://www.nuget.org/api/v2" [] let ``should parse and serialise multiple feed lockfile``() = - let lockFile = LockFile.Parse("",toLines multipleFeedLockFile) - let lockFile' = lockFile.ToString() + for lockFileText in [multipleFeedLockFileLegacy;multipleFeedLockFile] do + let lockFile = LockFile.Parse("",toLines lockFileText) + let lockFile' = lockFile.ToString() - normalizeLineEndings lockFile' - |> shouldEqual (normalizeLineEndings multipleFeedLockFile) + normalizeLineEndings lockFile' + |> shouldEqual (normalizeLineEndings multipleFeedLockFile) let groupsLockFile = """REDIRECTS: ON @@ -753,26 +773,33 @@ let ``should parse lock file from auto-detect settings``() = let deps = packages.Tail.Head.Dependencies |> Seq.toList |> List.map (fun (n,_,_) -> n) deps.Head |> shouldEqual (PackageName "Autofac") -let lockFileWithManyFrameworks = """NUGET +let lockFileWithManyFrameworksLegacy = """NUGET remote: https://www.nuget.org/api/v2 CommonServiceLocator (1.3) - framework: >= net40, monoandroid, portable-net45+wp80+wpa81+win+monoandroid10+xamarinios10, xamarinios, winv4.5, winv4.5.1, wpv8.0, wpv8.1, sl50 MvvmLightLibs (5.2) CommonServiceLocator (>= 1.0) - framework: net35, sl40 CommonServiceLocator (>= 1.3) - framework: >= net40, monoandroid, portable-net45+wp80+wpa81+win+monoandroid10+xamarinios10, xamarinios, winv4.5, winv4.5.1, wpv8.0, wpv8.1, sl50""" +let lockFileWithManyFrameworks = """NUGET + remote: https://www.nuget.org/api/v2 + CommonServiceLocator (1.3) - restriction: || (sl5) (>= net40) (>= portable-net45+monoandroid+xamarinios+win8+wp8+wpa81) + MvvmLightLibs (5.2) + CommonServiceLocator (>= 1.0) - restriction: || (net35) (sl4) + CommonServiceLocator (>= 1.3) - restriction: || (sl5) (>= net40) (>= portable-net45+monoandroid+xamarinios+win8+wp8+wpa81)""" [] let ``should parse lock file many frameworks``() = - let lockFile = LockFileParser.Parse(toLines lockFileWithManyFrameworks) - let main = lockFile.Head - let packages = List.rev main.Packages + for lockFile in [lockFileWithManyFrameworksLegacy;lockFileWithManyFrameworks] do + let lockFile = LockFileParser.Parse(toLines lockFile) + let main = lockFile.Head + let packages = List.rev main.Packages - packages.Length |> shouldEqual 2 + packages.Length |> shouldEqual 2 - packages.Head.Name |> shouldEqual (PackageName "CommonServiceLocator") - packages.Tail.Head.Name |> shouldEqual (PackageName "MvvmLightLibs") - LockFileSerializer.serializePackages main.Options (main.Packages |> List.map (fun p -> p.Name,p) |> Map.ofList) - |> normalizeLineEndings - |> shouldEqual (normalizeLineEndings lockFileWithManyFrameworks) + packages.Head.Name |> shouldEqual (PackageName "CommonServiceLocator") + packages.Tail.Head.Name |> shouldEqual (PackageName "MvvmLightLibs") + LockFileSerializer.serializePackages main.Options (main.Packages |> List.map (fun p -> p.Name,p) |> Map.ofList) + |> normalizeLineEndings + |> shouldEqual (normalizeLineEndings lockFileWithManyFrameworks) let lockFileWithDependencies = """NUGET remote: https://www.nuget.org/api/v2 diff --git a/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs b/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs index eca8760ae2..3e5fc64d2f 100644 --- a/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs +++ b/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs @@ -204,7 +204,7 @@ nuget Autofac.WebApi2 3.4.0 framework: >= net45 nuget Autofac.WebApi2.Owin 3.2.0 framework: >= net45""" let expected = """source https://www.nuget.org/api/v2/ -framework >= net45 +restriction: >= net45 nuget angularjs 1.4.3 nuget AngularTemplates.Compile 1.0.0 @@ -233,6 +233,16 @@ nuget Autofac.Owin 3.1.0 framework: >= net40 nuget Autofac.WebApi 3.1.0 framework: >= net45 nuget Autofac.WebApi2 3.4.0 framework: >= net45 nuget Autofac.WebApi2.Owin 3.2.0 framework: >= net45""" + let after = """source https://www.nuget.org/api/v2/ + +nuget angularjs 1.4.3 restriction: >= net45 +nuget AngularTemplates.Compile 1.0.0 restriction: >= net45 +nuget Antlr 3.4.1.9004 restriction: >= net45 +nuget Autofac 3.5.0 restriction: >= net45 +nuget Autofac.Owin 3.1.0 restriction: >= net40 +nuget Autofac.WebApi 3.1.0 restriction: >= net45 +nuget Autofac.WebApi2 3.4.0 restriction: >= net45 +nuget Autofac.WebApi2.Owin 3.2.0 restriction: >= net45""" let originalLockFile = DependenciesFile.FromSource(before) originalLockFile.SimplifyFrameworkRestrictions().ToString() @@ -256,7 +266,7 @@ nuget Autofac.WebApi2 3.4.0 framework: >= net40 nuget Autofac.WebApi2.Owin 3.2.0 framework: >= net40""" let expected = """source https://www.nuget.org/api/v2/ -framework >= net45 +restriction: >= net45 nuget angularjs 1.4.3 nuget AngularTemplates.Compile 1.0.0 @@ -265,7 +275,7 @@ nuget Autofac 3.5.0 group Build source https://www.nuget.org/api/v2/ -framework >= net40 +restriction: >= net40 nuget Autofac.Owin 3.1.0 nuget Autofac.WebApi 3.1.0 nuget Autofac.WebApi2 3.4.0 @@ -303,7 +313,7 @@ nuget Autofac.WebApi2 3.4.0 framework: sl5, sl4 nuget Autofac.WebApi2.Owin 3.2.0 framework: sl4, sl5""" let expected = """source https://www.nuget.org/api/v2/ -framework net40, net45 +restriction: || (net40) (net45) nuget angularjs 1.4.3 nuget AngularTemplates.Compile 1.0.0 @@ -312,7 +322,8 @@ nuget Autofac 3.5.0 group Build source https://www.nuget.org/api/v2/ -framework sl40, sl50 +restriction: || (sl40) (sl50) + nuget Autofac.Owin 3.1.0 nuget Autofac.WebApi 3.1.0 nuget Autofac.WebApi2 3.4.0 @@ -341,19 +352,19 @@ nuget Autofac.WebApi2 3.4.0 framework: sl5, sl4, >= net45 nuget Autofac.WebApi2.Owin 3.2.0 framework: sl4, sl5""" let expected = """source https://www.nuget.org/api/v2/ -framework net40, net45 +restriction: || (net40) (net45) -nuget angularjs 1.4.3 framework: net20 +nuget angularjs 1.4.3 restriction: net20 nuget AngularTemplates.Compile 1.0.0 nuget Antlr 3.4.1.9004 nuget Autofac 3.5.0 group Build source https://www.nuget.org/api/v2/ -framework sl40, sl50 +restriction: || (sl4) (sl5) nuget Autofac.Owin 3.1.0 nuget Autofac.WebApi 3.1.0 -nuget Autofac.WebApi2 3.4.0 framework: >= net45 +nuget Autofac.WebApi2 3.4.0 restriction: >= net45 nuget Autofac.WebApi2.Owin 3.2.0""" diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index fc6c1d82db..f9cdaa769a 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -5,6 +5,21 @@ open FsUnit open NUnit.Framework open Paket.Requirements +[] +let ``Simplify || (>= net45) (>= portable-net45+win8+wp8+wp81+wpa81)`` () = + // because that is a custom portable profile! + let portable = (PlatformMatching.extractPlatforms "portable-net45+win8+wp8+wp81+wpa81").ToTargetProfile.Value + let atLeastPortable = FrameworkRestriction.AtLeastPlatform portable + + // this was the underlying bug + atLeastPortable.RepresentedFrameworks + |> shouldContain (SinglePlatform (DotNetFramework FrameworkVersion.V4_5)) + + let formula = FrameworkRestriction.Or [ atLeastPortable; FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5) ] + + formula + |> shouldEqual (atLeastPortable) + [] let ``CustomProfile is Supported by its Platforms``() = let unknownProfile = From 9318160b44c3d3f574ee8c12ee94064e8d583e34 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 21:07:44 +0200 Subject: [PATCH 18/47] unit tests green again --- .../PaketConfigFiles/DependenciesFile.fs | 61 +++++++------- src/Paket.Core/PaketConfigFiles/LockFile.fs | 6 +- src/Paket.Core/Versioning/Requirements.fs | 80 +++++++++++++++++-- .../Lockfile/GenerateWithOptionsSpecs.fs | 2 +- tests/Paket.Tests/Lockfile/GeneratorSpecs.fs | 34 ++++---- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 10 +-- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 3 +- .../ReferencesFile/ReferencesFileSpecs.fs | 4 +- .../Simplifier/BasicScenarioSpecs.fs | 6 +- .../Versioning/DependencySetSpecs.fs | 1 + 10 files changed, 144 insertions(+), 63 deletions(-) diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index cc2cecd608..a61e8ae28b 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -155,36 +155,37 @@ type DependenciesFile(fileName,groups:Map, textRepr if group.Options.Settings.FrameworkRestrictions |> getRestrictionList <> FrameworkRestriction.NoRestriction then dependenciesFile else match group.Packages with | [] -> dependenciesFile - | package::rest -> //dependenciesFile - let commonRestrictions = - group.Packages - |> Seq.map (fun p' -> p'.Settings.FrameworkRestrictions) - |> Seq.fold (fun a b -> FrameworkRestriction.And [a;b.GetExplicitRestriction()]) FrameworkRestriction.EmptySet - //package.Settings.FrameworkRestrictions - //|> getRestrictionList - //|> List.filter (fun r -> - // rest |> Seq.forall (fun p' -> p'.Settings.FrameworkRestrictions |> getRestrictionList |> List.contains r)) - - match commonRestrictions.RepresentedFrameworks with - | [] -> dependenciesFile - // Only take when our commonRestriction formula is actually "simple" - | _ when commonRestrictions.OrFormulas |> List.forall (fun andFormula -> andFormula.Literals.Length <= 1) -> - let newDependenciesFile = dependenciesFile.AddFrameworkRestriction(group.Name,commonRestrictions) - let newNegatedLiterals = - commonRestrictions.OrFormulas |> List.collect (fun andFormala -> andFormala.Literals) - |> List.map (fun lit -> FrameworkRestriction.FromLiteral { lit with IsNegated = not lit.IsNegated }) - |> List.fold (fun a b -> FrameworkRestriction.Or [ a; b]) FrameworkRestriction.EmptySet - - group.Packages - |> List.fold (fun (d:DependenciesFile) package -> - let oldRestrictions = package.Settings.FrameworkRestrictions |> getRestrictionList - let newRestrictions = FrameworkRestriction.Or [ oldRestrictions; newNegatedLiterals ]// |> List.filter (fun r -> commonRestrictions |> List.contains r |> not) - if oldRestrictions = newRestrictions then d else - let (d:DependenciesFile) = d.Remove(group.Name,package.Name) - let installSettings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } - let vr = { VersionRequirement = package.VersionRequirement; ResolverStrategy = package.ResolverStrategyForDirectDependencies } - d.AddAdditionalPackage(group.Name, package.Name,vr,installSettings)) newDependenciesFile - | _ -> dependenciesFile + | package::rest -> dependenciesFile + // TODO: Fix simplifier + //let commonRestrictions = + // group.Packages + // |> Seq.map (fun p' -> p'.Settings.FrameworkRestrictions) + // |> Seq.fold (fun a b -> FrameworkRestriction.And [a;b.GetExplicitRestriction()]) FrameworkRestriction.EmptySet + // //package.Settings.FrameworkRestrictions + // //|> getRestrictionList + // //|> List.filter (fun r -> + // // rest |> Seq.forall (fun p' -> p'.Settings.FrameworkRestrictions |> getRestrictionList |> List.contains r)) + // + //match commonRestrictions.RepresentedFrameworks with + //| [] -> dependenciesFile + //// Only take when our commonRestriction formula is actually "simple" + //| _ when commonRestrictions.OrFormulas |> List.forall (fun andFormula -> andFormula.Literals.Length <= 1) -> + // let newDependenciesFile = dependenciesFile.AddFrameworkRestriction(group.Name,commonRestrictions) + // let newNegatedLiterals = + // commonRestrictions.OrFormulas |> List.collect (fun andFormala -> andFormala.Literals) + // |> List.map (fun lit -> FrameworkRestriction.FromLiteral { lit with IsNegated = not lit.IsNegated }) + // |> List.fold (fun a b -> FrameworkRestriction.Or [ a; b]) FrameworkRestriction.EmptySet + // + // group.Packages + // |> List.fold (fun (d:DependenciesFile) package -> + // let oldRestrictions = package.Settings.FrameworkRestrictions |> getRestrictionList + // let newRestrictions = FrameworkRestriction.Or [ oldRestrictions; newNegatedLiterals ]// |> List.filter (fun r -> commonRestrictions |> List.contains r |> not) + // if oldRestrictions = newRestrictions then d else + // let (d:DependenciesFile) = d.Remove(group.Name,package.Name) + // let installSettings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } + // let vr = { VersionRequirement = package.VersionRequirement; ResolverStrategy = package.ResolverStrategyForDirectDependencies } + // d.AddAdditionalPackage(group.Name, package.Name,vr,installSettings)) newDependenciesFile + //| _ -> dependenciesFile this.Groups |> Seq.map (fun kv -> kv.Value) diff --git a/src/Paket.Core/PaketConfigFiles/LockFile.fs b/src/Paket.Core/PaketConfigFiles/LockFile.fs index 5603cc9a36..9869eaed47 100644 --- a/src/Paket.Core/PaketConfigFiles/LockFile.fs +++ b/src/Paket.Core/PaketConfigFiles/LockFile.fs @@ -325,7 +325,11 @@ module LockFileParser = InstallSettings.Default if trimmed.Contains "(" then let parts = trimmed.Split '(' - NugetDependency (parts.[0].Trim(),parts.[1].Replace("(", "").Replace(")", "").Trim(),frameworkSettings) + let first = parts.[0] + let rest = String.Join ("(", parts |> Seq.skip 1) + let versionEndPos = rest.IndexOf(")") + if versionEndPos < 0 then failwithf "Missing matching ') in line '%s'" line + NugetDependency (parts.[0].Trim(),rest.Substring(0, versionEndPos).Trim(),frameworkSettings) else if trimmed.Contains(" -") then let pos = trimmed.IndexOf(" -") diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 068abb00ac..8ec9aaaffe 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -32,7 +32,7 @@ type FrameworkRestrictionP = | AndP of FrameworkRestrictionP list member x.InfixNotation = match x with - | FrameworkRestrictionP.ExactlyP r -> r.ToString() + | FrameworkRestrictionP.ExactlyP r -> "== " + r.ToString() //| FrameworkRestrictionP.PortableP (r,_) -> r | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() @@ -49,7 +49,7 @@ type FrameworkRestrictionP = | _ -> sprintf "(%s)" (System.String.Join(" && ", frl |> Seq.map (fun inner -> sprintf "(%s)" inner.InfixNotation))) override this.ToString() = match this with - | FrameworkRestrictionP.ExactlyP r -> r.ToString() + | FrameworkRestrictionP.ExactlyP r -> "== " + r.ToString() //| FrameworkRestrictionP.PortableP (r,_) -> r | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() @@ -363,7 +363,6 @@ let getExplicitRestriction (frameworkRestrictions:FrameworkRestrictions) = let parseRestrictionsLegacy failImmediatly (text:string) = - // TODO: Change this code to convert old "framework" sematics in // older lockfiles to the new "restriction" semantics let handleError = if failImmediatly then @@ -378,7 +377,7 @@ let parseRestrictionsLegacy failImmediatly (text:string) = // workaround missing spaces text.Replace("<=","<= ").Replace(">=",">= ").Replace("=","= ") if text.StartsWith("||") || text.StartsWith("&&") then - raise <| NotImplementedException("&& and || are not yet implemented.") + raise <| InvalidOperationException("&& and || are not allowed in a legacy 'framework' section.") let commaSplit = text.Trim().Split(',') [for p in commaSplit do @@ -412,7 +411,78 @@ let parseRestrictionsLegacy failImmediatly (text:string) = |> List.fold (fun state item -> FrameworkRestriction.combineRestrictionsWithOr state item) FrameworkRestriction.EmptySet let parseRestrictions failImmediatly (text:string) = - parseRestrictionsLegacy failImmediatly text + let handleError = + if failImmediatly then + failwith + else + if verbose then + (fun s -> + traceError s + traceVerbose Environment.StackTrace) + else traceError + + let rec parseOperator (text:string) = + match text.Trim() with + | t when String.IsNullOrEmpty t -> failwithf "trying to parse an otherator but got no content" + | h when h.StartsWith ">=" || h.StartsWith "==" || h.StartsWith "<" -> + // parse >= + let smallerThan = h.StartsWith "<" + let isEquals = h.StartsWith "==" + let rest = h.Substring 2 + let splitted = rest.Split([|' '|], StringSplitOptions.RemoveEmptyEntries) + if splitted.Length < 1 then failwithf "No parameter after >= or < in '%s'" text + let rawOperator = splitted.[0] + let operator = rawOperator.TrimEnd([|')'|]) + match (PlatformMatching.extractPlatforms operator).ToTargetProfile with + | None -> failwithf "invalid parameter '%s' after >= or < in '%s'" operator text + | Some plat -> + let f = + if smallerThan then FrameworkRestriction.NotAtLeastPlatform + elif isEquals then FrameworkRestriction.ExactlyPlatform + else FrameworkRestriction.AtLeastPlatform + let operatorIndex = text.IndexOf operator + f plat, text.Substring(operatorIndex + operator.Length) + | h when h.StartsWith "&&" || h.StartsWith "||" -> + let isAnd = h.StartsWith "&&" + let next = h.Substring 2 + let rec parseOperand cur (next:string) = + let trimmed = next.TrimStart() + if trimmed.StartsWith "(" then + let operand, remaining = parseOperator (trimmed.Substring 1) + let remaining = remaining.TrimStart() + if remaining.StartsWith ")" |> not then failwithf "expected ')' after operand, '%s'" text + parseOperand (operand::cur) (remaining.Substring 1) + else + cur, next + + let operands, next = parseOperand [] next + if operands.Length = 0 then failwithf "Operand '%s' without argument is invalid in '%s'" (h.Substring (0, 2)) text + let f, def = if isAnd then FrameworkRestriction.And, FrameworkRestriction.NoRestriction else FrameworkRestriction.Or, FrameworkRestriction.EmptySet + operands |> List.fold (fun a b -> f [a;b]) def, next + | h when h.StartsWith "NOT" -> + let next = h.Substring 2 + + if next.TrimStart().StartsWith "(" then + let operand, remaining = parseOperator (next.Substring 1) + let remaining = remaining.TrimStart() + if remaining.StartsWith ")" |> not then failwithf "expected ')' after operand, '%s'" text + let next = remaining.Substring 1 + + let negated = + match operand with + | { OrFormulas = [ {Literals = [ lit] } ] } -> + { OrFormulas = [ {Literals = [ { lit with IsNegated = not lit.IsNegated } ] } ] } + | _ -> failwithf "a general NOT is not implemted jet (and shouldn't be emitted for now)" + negated, next + else + failwithf "Expected operand after NOT, '%s'" text + | _ -> + failwithf "Expected operator, but got '%s'" text + + let result, next = parseOperator text + if String.IsNullOrEmpty next |> not then + failwithf "Successfully parsed '%O' but got additional text '%s'" result next + result let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestrictions) = match list1,list2 with diff --git a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs index 64e8dc6f84..e8ee2647c6 100644 --- a/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs +++ b/tests/Paket.Tests/Lockfile/GenerateWithOptionsSpecs.fs @@ -184,7 +184,7 @@ nuget NLog.Contrib let expected = """RESTRICTION: >= net40 NUGET remote: https://www.nuget.org/api/v2 - NLog (1.0.1) - restriction: net40 + NLog (1.0.1) - restriction: == net40 NLog.Contrib (1.0) NLog (>= 1.0.1)""" diff --git a/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs b/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs index 58dfbd195b..d026fa3f2f 100644 --- a/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs +++ b/tests/Paket.Tests/Lockfile/GeneratorSpecs.fs @@ -59,12 +59,12 @@ nuget "Rx-Main" "~> 2.0" framework: >= net40 """ let ``should generate lock file with framework restrictions for packages``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 - Castle.Windsor (2.1) - restriction: net35 - Castle.Windsor-log4net (3.3) - restriction: net35 + Castle.Windsor (2.1) - restriction: == net35 + Castle.Windsor-log4net (3.3) - restriction: == net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - restriction: net35 - log4net (1.1) - restriction: net35 + log (1.2) - restriction: == net35 + log4net (1.1) - restriction: == net35 log (>= 1.0) Rx-Core (2.1) - restriction: >= net40 Rx-Main (2.0) - restriction: >= net40 @@ -86,12 +86,12 @@ nuget "Rx-Main" "~> 2.0" framework: >= net40 """ let ``should generate lock file with no targets import for packages``() = let expected = """NUGET remote: "D:\code\temp with space" - Castle.Windsor (2.1) - import_targets: false, restriction: net35 - Castle.Windsor-log4net (3.3) - import_targets: false, restriction: net35 + Castle.Windsor (2.1) - import_targets: false, restriction: == net35 + Castle.Windsor-log4net (3.3) - import_targets: false, restriction: == net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - import_targets: false, restriction: net35 - log4net (1.1) - import_targets: false, restriction: net35 + log (1.2) - import_targets: false, restriction: == net35 + log4net (1.1) - import_targets: false, restriction: == net35 log (>= 1.0) Rx-Core (2.1) - restriction: >= net40 Rx-Main (2.0) - restriction: >= net40 @@ -112,12 +112,12 @@ nuget "Rx-Main" "~> 2.0" framework: >= net40 """ let ``should generate lock file with no copy local for packages``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 - Castle.Windsor (2.1) - copy_local: false, import_targets: false, restriction: net35 - Castle.Windsor-log4net (3.3) - copy_local: false, import_targets: false, restriction: net35 + Castle.Windsor (2.1) - copy_local: false, import_targets: false, restriction: == net35 + Castle.Windsor-log4net (3.3) - copy_local: false, import_targets: false, restriction: == net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - copy_local: false, import_targets: false, restriction: net35 - log4net (1.1) - copy_local: false, import_targets: false, restriction: net35 + log (1.2) - copy_local: false, import_targets: false, restriction: == net35 + log4net (1.1) - copy_local: false, import_targets: false, restriction: == net35 log (>= 1.0) Rx-Core (2.1) - restriction: >= net40 Rx-Main (2.0) - restriction: >= net40 @@ -138,12 +138,12 @@ nuget "Rx-Main" "~> 2.0" content: none, framework: >= net40 """ let ``should generate lock file with disabled content for packages``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 - Castle.Windsor (2.1) - restriction: net35 - Castle.Windsor-log4net (3.3) - restriction: net35 + Castle.Windsor (2.1) - restriction: == net35 + Castle.Windsor-log4net (3.3) - restriction: == net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) - log (1.2) - restriction: net35 - log4net (1.1) - restriction: net35 + log (1.2) - restriction: == net35 + log4net (1.1) - restriction: == net35 log (>= 1.0) Rx-Core (2.1) - content: none, restriction: >= net40 Rx-Main (2.0) - content: none, restriction: >= net40 @@ -356,7 +356,7 @@ let ``should generate lock file with second group``() = let expected = """NUGET remote: http://www.nuget.org/api/v2 Castle.Windsor (2.1) - copy_content_to_output_dir: preserve_newest - Castle.Windsor-log4net (3.3) - restriction: net35 + Castle.Windsor-log4net (3.3) - restriction: == net35 Castle.Windsor (>= 2.0) log4net (>= 1.0) log (1.2) diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index 4390a5f002..c4597358d8 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -512,11 +512,11 @@ let ``should parse reactiveui lockfile``() = packages.[8].Name |> shouldEqual (PackageName "Rx-WindowStoreApps") packages.[8].Version |> shouldEqual (SemVer.Parse "2.2.5") - (packages.[8].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "win8" + (packages.[8].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "== win8" packages.[10].Name |> shouldEqual (PackageName "Rx-Xaml") packages.[10].Version |> shouldEqual (SemVer.Parse "2.2.5") - (packages.[10].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "|| (win8) (wp8) (>= net45)" + (packages.[10].Settings.FrameworkRestrictions |> getExplicitRestriction).ToString() |> shouldEqual "|| (== win8) (== wp8) (>= net45)" let multipleFeedLockFileLegacy = """NUGET remote: http://internalfeed/NugetWebFeed/nuget @@ -781,10 +781,10 @@ let lockFileWithManyFrameworksLegacy = """NUGET CommonServiceLocator (>= 1.3) - framework: >= net40, monoandroid, portable-net45+wp80+wpa81+win+monoandroid10+xamarinios10, xamarinios, winv4.5, winv4.5.1, wpv8.0, wpv8.1, sl50""" let lockFileWithManyFrameworks = """NUGET remote: https://www.nuget.org/api/v2 - CommonServiceLocator (1.3) - restriction: || (sl5) (>= net40) (>= portable-net45+monoandroid+xamarinios+win8+wp8+wpa81) + CommonServiceLocator (1.3) - restriction: || (== sl5) (>= net40) (>= portable-net45+monoandroid+xamarinios+win8+wp8+wpa81) MvvmLightLibs (5.2) - CommonServiceLocator (>= 1.0) - restriction: || (net35) (sl4) - CommonServiceLocator (>= 1.3) - restriction: || (sl5) (>= net40) (>= portable-net45+monoandroid+xamarinios+win8+wp8+wpa81)""" + CommonServiceLocator (>= 1.0) - restriction: || (== net35) (== sl4) + CommonServiceLocator (>= 1.3) - restriction: || (== sl5) (>= net40) (>= portable-net45+monoandroid+xamarinios+win8+wp8+wpa81)""" [] let ``should parse lock file many frameworks``() = diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index 183391f050..8ed9855ba1 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -132,7 +132,8 @@ let ``can detect explicit dependencies for Microsoft.AspNet.WebApi.Client``() = makeOrList [getPortableRestriction("portable-net45+win8+wp8+wp81+wpa81"); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]) dependencies.[1] |> shouldEqual (PackageName "Microsoft.Net.Http", DependenciesFileParser.parseVersionRequirement(">= 2.2.22"), - makeOrList [getPortableRestriction("portable-net45+win8+wp8+wp81+wpa81")]) + FrameworkRestriction.And [getPortableRestriction("portable-net45+win8+wp8+wp81+wpa81"); FrameworkRestriction.NotAtLeast(DotNetFramework(FrameworkVersion.V4_5))] + |> ExplicitRestriction) [] let ``can detect explicit dependencies for WindowsAzure.Storage``() = diff --git a/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs b/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs index 494755005e..56a09929f1 100644 --- a/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs +++ b/tests/Paket.Tests/ReferencesFile/ReferencesFileSpecs.fs @@ -234,8 +234,8 @@ let legacyRefFileContentWithMultipleSettings = """Castle.Windsor copy_local: fal Newtonsoft.Json content: none, framework: net40 xUnit import_targets: false""" -let refFileContentWithMultipleSettings = """Castle.Windsor copy_local: false, import_targets: false, restriction: || (net35) (>= net40) -Newtonsoft.Json content: none, restriction: net40 +let refFileContentWithMultipleSettings = """Castle.Windsor copy_local: false, import_targets: false, restriction: || (== net35) (>= net40) +Newtonsoft.Json content: none, restriction: == net40 xUnit import_targets: false""" [] diff --git a/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs b/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs index 3e5fc64d2f..f5e93c6bcd 100644 --- a/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs +++ b/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs @@ -191,6 +191,7 @@ nuget C 1.0""" |> shouldEqual (normalizeLineEndings expected) [] +[] let ``should simplify framework restrictions in main group``() = let before = """source https://www.nuget.org/api/v2/ @@ -250,6 +251,7 @@ nuget Autofac.WebApi2.Owin 3.2.0 restriction: >= net45""" |> shouldEqual (normalizeLineEndings before) [] +[] let ``should simplify framework restrictions in every group``() = let before = """source https://www.nuget.org/api/v2/ @@ -295,8 +297,9 @@ let ``should not simplify framework restrictions in empty file``() = originalLockFile.SimplifyFrameworkRestrictions().ToString() |> normalizeLineEndings |> shouldEqual (normalizeLineEndings before) - + [] +[] let ``should simplify multiple framework restrictions in every group``() = let before = """source https://www.nuget.org/api/v2/ @@ -336,6 +339,7 @@ nuget Autofac.WebApi2.Owin 3.2.0""" |> shouldEqual (normalizeLineEndings expected) [] +[] let ``should simplify subset of framework restrictions in every group``() = let before = """source https://www.nuget.org/api/v2/ diff --git a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs index 6b7befd3bb..3988dab236 100644 --- a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs +++ b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs @@ -133,6 +133,7 @@ let ``filtered with Between restriction should filter non-matching`` () = |> shouldEqual expected [] +[] let ``should optimize ZendeskApi_v2 ``() = let original = [PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "net35" From 8245a163a211d768afe238f61003ca789e387bc6 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 22 May 2017 23:01:52 +0200 Subject: [PATCH 19/47] Cleanup and some code-simplifications. --- .../FrameworkRestrictionsSpecs.fs | 17 ++-- src/Paket.Core/Dependencies/NuGetV2.fs | 36 ++----- src/Paket.Core/Dependencies/Nuspec.fs | 27 ++--- .../PaketConfigFiles/InstallModel.fs | 9 +- .../PaketConfigFiles/ProjectFile.fs | 2 - .../Versioning/FrameworkHandling.fs | 22 +---- src/Paket.Core/Versioning/PlatformMatching.fs | 98 +++++-------------- src/Paket.Core/Versioning/Requirements.fs | 71 +++----------- .../InstallModel/Penalty/PenaltySpecs.fs | 95 +++++++++--------- .../InstallModel/ProcessingSpecs.fs | 2 - tests/Paket.Tests/InstallModel/Xml/SQLite.fs | 4 +- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 3 +- .../ProjectFile/TargetFrameworkSpecs.fs | 1 - tests/Paket.Tests/TestHelpers.fs | 2 +- .../Versioning/DependencySetSpecs.fs | 56 ++++++----- .../Versioning/FrameworkRestrictionTests.fs | 23 +---- .../Versioning/RestrictionFilterSpecs.fs | 2 - 17 files changed, 150 insertions(+), 320 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs index 19810bd409..8ce40974a3 100644 --- a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs @@ -1,4 +1,5 @@ module Paket.IntegrationTests.FrameworkRestrictionsSpecs + open Fake open Paket open System @@ -27,11 +28,10 @@ let ``#1182 framework restrictions overwrite each other``() = [] // PATH TOO LONG on Windows... let ``#1190 paket add nuget should handle transitive dependencies``() = paket "add nuget xunit version 2.1.0" "i001190-transitive-dependencies-with-restr" |> ignore - failwithf "Fix Me" - //let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001190-transitive-dependencies-with-restr","paket.lock")) - //lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "xunit.abstractions"].Settings.FrameworkRestrictions - //|> getExplicitRestriction - //|> shouldContain (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))) + let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001190-transitive-dependencies-with-restr","paket.lock")) + lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "xunit.abstractions"].Settings.FrameworkRestrictions + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))) [] let ``#1190 paket add nuget should handle transitive dependencies with restrictions``() = @@ -70,10 +70,9 @@ let ``#1215 framework dependencies propagate``() = [] let ``#1232 framework dependencies propagate``() = let lockFile = update "i001232-sql-lite" - failwithf "Fix me" - //lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "System.Data.SQLite.Core"].Settings.FrameworkRestrictions - //|> getExplicitRestriction - //|> shouldContain (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_Client))) + lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "System.Data.SQLite.Core"].Settings.FrameworkRestrictions + |> getExplicitRestriction + |> shouldEqual (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4))) [] let ``#1494 detect platform 5.0``() = diff --git a/src/Paket.Core/Dependencies/NuGetV2.fs b/src/Paket.Core/Dependencies/NuGetV2.fs index 2724cd1881..64420b7e8b 100644 --- a/src/Paket.Core/Dependencies/NuGetV2.fs +++ b/src/Paket.Core/Dependencies/NuGetV2.fs @@ -182,42 +182,22 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra let rawPackages = let split (d : string) = let a = d.Split ':' - PackageName a.[0], - VersionRequirement.Parse(if a.Length > 1 then a.[1] else "0"), + let name = PackageName a.[0] + let version = VersionRequirement.Parse(if a.Length > 1 then a.[1] else "0") (if a.Length > 2 && a.[2] <> "" then - let restriction = a.[2] - if String.startsWithIgnoreCase "portable" restriction then - let fws = (PlatformMatching.extractPlatforms restriction).Platforms - Some { PlatformMatching.ParsedPlatformPath.Name = restriction; PlatformMatching.ParsedPlatformPath.Platforms = fws } - //Some (FrameworkRestriction.Portable (restriction, fws)) - else - match FrameworkDetection.Extract restriction with - | Some x -> Some { PlatformMatching.ParsedPlatformPath.Name = restriction; PlatformMatching.ParsedPlatformPath.Platforms = [x] } - //(FrameworkRestriction.Exactly x) - | None -> - traceWarnfn "Unable to parse framework restriction '%s' for package '%s' in package '%s'" restriction a.[0] (packageName.ToString()) - //if verbose then - // verbosefn "Unable to parse framework restriction '%s' for package '%s' in package '%s'" restriction a.[0] (packageName.ToString()) - None + let restriction = a.[2] + PlatformMatching.extractPlatforms restriction else Some PlatformMatching.ParsedPlatformPath.Empty) + |> Option.map (fun pp -> name, version, pp) dependencies |> fun s -> s.Split([| '|' |], System.StringSplitOptions.RemoveEmptyEntries) - |> Array.map split - |> Array.choose (fun (name, version, restrictions) -> - match restrictions with - | Some(restrictions) -> Some (name, version, restrictions) - | None -> None) + |> Array.choose split let frameworks = rawPackages - |> Seq.collect (fun (_,_,pp) -> - match pp.Platforms with - | [h] -> [SinglePlatform h] - | plats when plats.Length > 1 -> [TargetProfile.FindPortable plats] - | _ -> - traceWarnfn "Could not detect frameworks in '%s', ignoring..." pp.Name - []) + |> Seq.map (fun (_,_,pp) -> pp) + |> Seq.distinctBy (fun pp -> pp.Platforms |> List.sort) |> Seq.toList let cleanedPackages = rawPackages diff --git a/src/Paket.Core/Dependencies/Nuspec.fs b/src/Paket.Core/Dependencies/Nuspec.fs index 6a360167b8..6f96c12e87 100644 --- a/src/Paket.Core/Dependencies/Nuspec.fs +++ b/src/Paket.Core/Dependencies/Nuspec.fs @@ -33,14 +33,9 @@ module internal NuSpecParserHelper = match parent.Name, parent |> getAttribute "targetFramework" with | n , Some framework when String.equalsIgnoreCase n "group" -> let framework = framework.Replace(".NETPortable0.0","portable") - if String.startsWithIgnoreCase "portable" framework then - let fws = (PlatformMatching.extractPlatforms framework).Platforms - Some(name,version, { PlatformMatching.ParsedPlatformPath.Name = framework; PlatformMatching.ParsedPlatformPath.Platforms = fws}) - else - match FrameworkDetection.Extract framework with - | Some x -> Some(name,version, { Name = framework; Platforms = [x]}) - | None -> None - | _ -> Some(name,version, { Name = ""; Platforms = [] }) + PlatformMatching.extractPlatforms framework + |> Option.map (fun pp -> name, version, pp) + | _ -> Some(name,version, PlatformMatching.ParsedPlatformPath.Empty) let getAssemblyRefs node = let name = node |> getAttribute "assemblyName" @@ -79,20 +74,12 @@ type Nuspec = let frameworks = doc |> getDescendants "group" - |> List.map (fun node -> + |> List.choose (fun node -> match node |> getAttribute "targetFramework" with - | Some framework when framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable").StartsWith "portable" -> - let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") - let fws = (PlatformMatching.extractPlatforms framework).Platforms - [TargetProfile.FindPortable(fws)] - //[] // TODO: Maybe fws? - | Some framework -> - match FrameworkDetection.Extract framework with - | Some x -> [SinglePlatform x] - | None -> [] - | _ -> []) - |> List.concat + let framework = framework.ToLower().Replace(".netportable","portable").Replace("netportable","portable") + PlatformMatching.extractPlatforms framework + | _ -> Some PlatformMatching.ParsedPlatformPath.Empty) let rawDependencies = doc diff --git a/src/Paket.Core/PaketConfigFiles/InstallModel.fs b/src/Paket.Core/PaketConfigFiles/InstallModel.fs index 80aa2af9b0..4f1d5470d4 100644 --- a/src/Paket.Core/PaketConfigFiles/InstallModel.fs +++ b/src/Paket.Core/PaketConfigFiles/InstallModel.fs @@ -144,11 +144,16 @@ module FolderScanner = let toParseResult error (wasSuccess, result) = if wasSuccess then ParseSucceeded result else ParseError error - + let check errorMsg f x = if f x then ParseSucceeded x else ParseError (errorMsg) + let choose errorMsg f x = + match f x with + | Some y -> ParseSucceeded y + | None -> ParseError (errorMsg) + let parseDecimal x = Decimal.TryParse(x, Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture) let parsers = dict [ @@ -344,7 +349,7 @@ module InstallModel = [ { FolderScanner.AdvancedScanner.Name = "noSeperator"; FolderScanner.AdvancedScanner.Parser = FolderScanner.check "seperator not allowed" (fun s -> not (s.Contains "/" || s.Contains "\\")) >> FolderScanner.ParseResult.box } { FolderScanner.AdvancedScanner.Name = "tfm"; - FolderScanner.AdvancedScanner.Parser = PlatformMatching.extractPlatforms >> FolderScanner.ParseResult.ParseSucceeded >> FolderScanner.ParseResult.box } + FolderScanner.AdvancedScanner.Parser = FolderScanner.choose "invalid tfm" PlatformMatching.extractPlatforms >> FolderScanner.ParseResult.box } { FolderScanner.AdvancedScanner.Name = "rid"; FolderScanner.AdvancedScanner.Parser = (fun rid -> { Rid = rid }) >> FolderScanner.ParseResult.ParseSucceeded >> FolderScanner.ParseResult.box }] let trySscanf pf s = diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs index ba3a589aff..51118e7ede 100644 --- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs @@ -974,8 +974,6 @@ module ProjectFile = let getTargetProfile (project:ProjectFile) = match getTargetFrameworkProfile project with - //| Some profile when profile = "Client" -> - // SinglePlatform (DotNetFramework FrameworkVersion.V4_Client) | Some profile when String.IsNullOrWhiteSpace profile |> not -> KnownTargetProfiles.FindPortableProfile profile | _ -> diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index ced19fe7d0..d9aeb90bc4 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -417,12 +417,6 @@ type FrameworkIdentifier = | WindowsPhone WindowsPhoneVersion.V8 -> [ WindowsPhone WindowsPhoneVersion.V7_5; DotNetStandard DotNetStandardVersion.V1_0 ] | WindowsPhone WindowsPhoneVersion.V8_1 -> [ WindowsPhone WindowsPhoneVersion.V8 ] - // wildcards for future versions. new versions should be added above, though, so the penalty will be calculated correctly. - //| Silverlight _ -> [ Silverlight "v5.0" ] - //| Windows _ -> [ Windows "v4.5.1" ] - //| WindowsPhoneApp _ -> [ WindowsPhoneApp "v8.1" ] - //| WindowsPhoneSilverlight _ -> [ WindowsPhoneSilverlight "v8.1" ] - module FrameworkDetection = /// Used for script generation @@ -445,6 +439,7 @@ module FrameworkDetection = open Logging /// parse a string to construct a Netframework, NetCore, NetStandard, or other dotnet identifier + [] let Extract = memoize (fun (path:string) -> @@ -1067,7 +1062,6 @@ type TargetProfile with traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback fallback - // TODO: some notion of an increasing/decreasing sequence of FrameworkIdentitifers, so that Between(bottom, top) constraints can enumerate the list /// true when x is supported by y, for example netstandard15 is supported by netcore10 member x.IsSupportedBy y = match x with @@ -1082,26 +1076,12 @@ type TargetProfile with | _ -> x = y || (y.SupportedPlatforms |> Seq.exists (fun s -> x.IsSupportedBy s)) - //x = y || - // (x.SupportedPlatforms |> Seq.exists (fun x' -> x' = y && not (x'.IsSameCategoryAs x))) || - // (y.SupportedPlatforms |> Seq.exists (fun y' -> y' = x && not (y'.IsSameCategoryAs y))) /// true when x is at least (>=) y ie when y is supported by x, for example netcore10 >= netstandard15 as netstandard15 is supported by netcore10. /// Note that this relation is not complete, for example for WindowsPhoneSilverlightv7.0 and Windowsv4.5 both <= and >= are false from this definition as /// no platform supports the other. member x.IsAtLeast (y:TargetProfile) = y.IsSupportedBy x - //if x.IsSameCategoryAs y then - // x >= y - //else - // let isCompatible() = - // y.SupportedPlatforms - // |> Seq.exists x.IsAtLeast - // - // match x,y with - // | DotNetStandard _, DotNetFramework _ -> isCompatible() - // | DotNetFramework _, DotNetStandard _ -> isCompatible() - // | _ -> false /// Get all platforms y for which x >= y holds member x.SupportedPlatformsTransitive = diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index abf993d685..1b00616f47 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -19,13 +19,15 @@ type ParsedPlatformPath = | [] -> None // Not detected earlier. | [p] -> Some (SinglePlatform p) | plats -> Some (TargetProfile.FindPortable plats) + member pp.IsEmpty = String.IsNullOrEmpty pp.Name || pp.Platforms.IsEmpty + let inline split (path : string) = path.Split('+') |> Array.map (fun s -> System.Text.RegularExpressions.Regex.Replace(s, @"portable[\d\.]*-","")) // TODO: This function does now quite a lot, there probably should be several functions. let extractPlatforms = memoize (fun path -> - if System.String.IsNullOrEmpty path then ParsedPlatformPath.Empty + if System.String.IsNullOrEmpty path then Some ParsedPlatformPath.Empty else let splits = split path let platforms = splits |> Array.choose FrameworkDetection.Extract |> Array.toList @@ -35,16 +37,20 @@ let extractPlatforms = memoize (fun path -> let found = KnownTargetProfiles.FindPortableProfile splits.[0] |> ParsedPlatformPath.FromTargetProfile - { found with Name = path } + Some { found with Name = path } else - failwithf "Could not detect any platforms from '%s'" path - //traceWarnfn "Could not detect any platforms from '%s'" path - else { Name = path; Platforms = platforms }) + traceWarnfn "Could not detect any platforms from '%s'" path + None + else Some { Name = path; Platforms = platforms }) + +let forceExtractPlatforms path = + match extractPlatforms path with + | Some s -> s + | None -> failwithf "Extracting platforms from path '%s' failed" path // TODO: In future work this stuff should be rewritten. This penalty stuff is more random than a proper implementation. let rec getPlatformPenalty = memoize (fun (targetPlatform:TargetProfile,packagePlatform:TargetProfile) -> - //let rec getPlatformPenalty alreadyChecked (targetPlatform:TargetProfile) (packagePlatform:TargetProfile) = if packagePlatform = targetPlatform then 0 else @@ -62,12 +68,7 @@ let rec getPlatformPenalty = | _ -> let penalty = targetPlatform.SupportedPlatforms - //|> List.filter (fun x -> - // System.Diagnostics.Debug.WriteLine(sprintf "Supported %O -> %O (trying to find %O)" targetPlatform x packagePlatform) - // Set.contains x alreadyChecked |> not) - |> List.map (fun target -> - //System.Diagnostics.Debug.WriteLine(sprintf "Supported %O -> %O (trying to find %O)" targetPlatform target packagePlatform) - getPlatformPenalty (target, packagePlatform)) + |> List.map (fun target -> getPlatformPenalty (target, packagePlatform)) |> List.append [MaxPenalty] |> List.min |> fun p -> p + 1 @@ -137,7 +138,6 @@ let collectPlatforms = if f.SupportedPlatforms |> List.exists ((=) framework) then loop (f::acc) framework tl else loop acc framework tl - //| _::tl -> loop acc framework tl memoize (fun (framework,profls) -> loop ([]:TargetProfile list) framework profls) let getPlatformsSupporting = @@ -145,13 +145,6 @@ let getPlatformsSupporting = let calculate (x:TargetProfile) = KnownTargetProfiles.AllProfiles |> List.filter (fun plat -> x.IsSupportedBy plat) - //match x with - //| PortableProfile (PortableProfileType.UnsupportedProfile fws) -> - // - // - //| _ -> - // KnownTargetProfiles.AllProfiles - // |> List.filter (fun plat -> plat.SupportedPlatformsTransitive |> Seq.contains x) memoize calculate let platformsSupport = @@ -169,38 +162,12 @@ let platformsSupport = let findBestMatch = let rec findBestMatch (paths : ParsedPlatformPath list, targetProfile : TargetProfile) = - - //let supported = - paths - |> List.map (fun path -> path, (getPathPenalty (path, targetProfile))) - |> List.filter (fun (_, penalty) -> penalty < MaxPenalty) - |> List.sortWith comparePaths - |> List.map fst - |> List.tryHead - - //let findBestPortableMatch findPenalty (portableProfile:TargetProfile) paths = - // paths - // |> Seq.tryFind (fun p -> tryGetProfile p = Some portableProfile) - // |> Option.map (fun p -> p, findPenalty) - // - //match supported with - //| None -> - // // Fallback Portable Library - // KnownTargetProfiles.AllProfiles - // |> List.choose (fun p -> - // match targetProfile with - // | SinglePlatform x -> - // match platformsSupport(x,p.ProfilesCompatibleWithPortableProfile) with - // | pen when pen < MaxPenalty -> - // findBestPortableMatch pen p paths - // | _ -> - // None - // | _ -> None) - // |> List.distinct - // |> List.sortBy (fun (x, pen) -> pen, x.Platforms.Length) // prefer portable platform with less platforms - // |> List.map fst - // |> List.tryHead - //| path -> path + paths + |> List.map (fun path -> path, (getPathPenalty (path, targetProfile))) + |> List.filter (fun (_, penalty) -> penalty < MaxPenalty) + |> List.sortWith comparePaths + |> List.map fst + |> List.tryHead memoize (fun (paths : ParsedPlatformPath list,targetProfile : TargetProfile) -> findBestMatch(paths,targetProfile)) @@ -222,22 +189,19 @@ let getSupportedTargetProfiles = let getTargetCondition (target:TargetProfile) = match target with | SinglePlatform(platform) -> - // BUG: Pattern incomplete! match platform with - //| DotNetFramework(version) when version = FrameworkVersion.V4 -> - // "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O')" version | DotNetFramework(version) ->"$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DNX(version) ->"$(TargetFrameworkIdentifier) == 'DNX'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DNXCore(version) ->"$(TargetFrameworkIdentifier) == 'DNXCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DotNetStandard(version) ->"$(TargetFrameworkIdentifier) == '.NETStandard'", sprintf "$(TargetFrameworkVersion) == '%O'" version | DotNetCore(version) ->"$(TargetFrameworkIdentifier) == '.NETCoreApp'", sprintf "$(TargetFrameworkVersion) == '%O'" version - | DotNetUnity(version) when version = DotNetUnityVersion.V3_5_Full -> + | DotNetUnity(DotNetUnityVersion.V3_5_Full as version) -> "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Unity Full v3.5')" version - | DotNetUnity(version) when version = DotNetUnityVersion.V3_5_Subset -> + | DotNetUnity(DotNetUnityVersion.V3_5_Subset as version) -> "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Unity Subset v3.5')" version - | DotNetUnity(version) when version = DotNetUnityVersion.V3_5_Micro -> + | DotNetUnity(DotNetUnityVersion.V3_5_Micro as version) -> "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Unity Micro v3.5')" version - | DotNetUnity(version) when version = DotNetUnityVersion.V3_5_Web -> + | DotNetUnity(DotNetUnityVersion.V3_5_Web as version) -> "$(TargetFrameworkIdentifier) == '.NETFramework'", sprintf "($(TargetFrameworkVersion) == '%O' And $(TargetFrameworkProfile) == 'Unity Web v3.5')" version | Windows(version) -> "$(TargetFrameworkIdentifier) == '.NETCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version.NetCoreVersion | Silverlight(version) -> "$(TargetFrameworkIdentifier) == 'Silverlight'", sprintf "$(TargetFrameworkVersion) == '%O'" version @@ -247,8 +211,7 @@ let getTargetCondition (target:TargetProfile) = | MonoTouch -> "$(TargetFrameworkIdentifier) == 'MonoTouch'", "" | MonoMac -> "$(TargetFrameworkIdentifier) == 'MonoMac'", "" | XamariniOS -> "$(TargetFrameworkIdentifier) == 'Xamarin.iOS'", "" - | UAP(version) -> // "$(TargetPlatformIdentifier) == 'UAP'", sprintf "$(TargetPlatformVersion.StartsWith('%O'))" version - "$(TargetFrameworkIdentifier) == '.NETCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version.NetCoreVersion + | UAP(version) -> "$(TargetFrameworkIdentifier) == '.NETCore'", sprintf "$(TargetFrameworkVersion) == '%O'" version.NetCoreVersion | XamarinMac -> "$(TargetFrameworkIdentifier) == 'Xamarin.Mac'", "" | Native(NoBuildMode,NoPlatform) -> "true", "" | Native(NoBuildMode,bits) -> (sprintf "'$(Platform)'=='%s'" bits.AsString), "" @@ -277,17 +240,6 @@ let getCondition (referenceCondition:string option) (allTargets: TargetProfile l |> CheckIfFullyInGroupS "WindowsPhoneApp" (function SinglePlatform (WindowsPhoneApp _) -> true | _ -> false) |> CheckIfFullyInGroupS "WindowsPhone" (function SinglePlatform (WindowsPhone _) -> true | _ -> false) - //let targets = - // targets - // |> List.map (fun target -> - // match target with - // | SinglePlatform(DotNetFramework(FrameworkVersion.V4_Client)) -> - // if allTargets |> List.exists (List.contains (SinglePlatform(DotNetFramework(FrameworkVersion.V4)))) |> not then - // SinglePlatform(DotNetFramework(FrameworkVersion.V4)) - // else - // target - // | _ -> target) - let conditions = if targets = [ SinglePlatform(Native(NoBuildMode,NoPlatform)) ] then targets @@ -295,8 +247,6 @@ let getCondition (referenceCondition:string option) (allTargets: TargetProfile l targets |> List.filter (function | SinglePlatform(Native(NoBuildMode,NoPlatform)) -> false - //| SinglePlatform(DotNetFramework(FrameworkVersion.V4)) -> - // targets |> List.contains (SinglePlatform(DotNetFramework(FrameworkVersion.V4))) |> not | _ -> true) |> List.map getTargetCondition |> List.filter (fun (_, v) -> v <> "false") diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 8ec9aaaffe..3f239de164 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -6,13 +6,6 @@ open Paket.Domain open Paket.PackageSources open Paket.Logging -let private allFrameworks = - KnownTargetProfiles.AllProfiles - //|> List.collect (function - // | SinglePlatform fw -> [fw] - // | PortableProfile (_, fws) -> fws) - //|> List.distinct - //|> List.sort [] // To make reasoning and writing tests easier. // Ideally we would "simplify" the trees to a "normal" form internally @@ -20,11 +13,7 @@ let private allFrameworks = [] type FrameworkRestrictionP = private - //| NoRestrictionP // = AndP [] - //| EmptySetP // = OrP [] | ExactlyP of TargetProfile - //[] - //| PortableP of string * FrameworkIdentifier list | AtLeastP of TargetProfile // Means: Take all frameworks NOT given by the restriction | NotP of FrameworkRestrictionP @@ -33,7 +22,6 @@ type FrameworkRestrictionP = member x.InfixNotation = match x with | FrameworkRestrictionP.ExactlyP r -> "== " + r.ToString() - //| FrameworkRestrictionP.PortableP (r,_) -> r | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() | FrameworkRestrictionP.NotP(fr) -> sprintf "NOT (%O)" fr @@ -50,7 +38,6 @@ type FrameworkRestrictionP = override this.ToString() = match this with | FrameworkRestrictionP.ExactlyP r -> "== " + r.ToString() - //| FrameworkRestrictionP.PortableP (r,_) -> r | FrameworkRestrictionP.AtLeastP r -> ">= " + r.ToString() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP r) -> sprintf "< " + r.ToString() | FrameworkRestrictionP.NotP(fr) -> sprintf "NOT (%O)" fr @@ -69,16 +56,11 @@ type FrameworkRestrictionP = member x.RepresentedFrameworks = match x with | FrameworkRestrictionP.ExactlyP r -> [ r ] - //| FrameworkRestrictionP.PortableP (r, fws) -> - // fws - // |> List.collect (fun fw -> (FrameworkRestrictionP.AtLeastP fw).RepresentedFrameworks) - // |> List.distinct - // |> List.sort | FrameworkRestrictionP.AtLeastP r -> PlatformMatching.getPlatformsSupporting r | FrameworkRestrictionP.NotP(fr) -> let notTaken = fr.RepresentedFrameworks - allFrameworks + KnownTargetProfiles.AllProfiles |> List.filter (fun fw -> notTaken |> Seq.contains fw |> not) | FrameworkRestrictionP.OrP (frl) -> frl @@ -92,16 +74,11 @@ type FrameworkRestrictionP = h.RepresentedFrameworks |> List.filter (fun fw -> allLists |> List.forall(fun l1 -> l1 |> Seq.contains fw)) | [] -> - allFrameworks + KnownTargetProfiles.AllProfiles member x.IsMatch (tp:TargetProfile) = match x with | FrameworkRestrictionP.ExactlyP r -> r = tp - //| FrameworkRestrictionP.PortableP (r, fws) -> - // fws - // |> List.collect (fun fw -> (FrameworkRestrictionP.AtLeastP fw).RepresentedFrameworks) - // |> List.distinct - // |> List.sort | FrameworkRestrictionP.AtLeastP r -> tp.SupportedPlatformsTransitive |> Seq.contains r | FrameworkRestrictionP.NotP(fr) -> @@ -129,12 +106,10 @@ type FrameworkRestrictionP = type FrameworkRestrictionLiteralI = | ExactlyL of TargetProfile - //| PortableL of string * FrameworkIdentifier list | AtLeastL of TargetProfile member internal x.RawFormular = match x with | ExactlyL id -> FrameworkRestrictionP.ExactlyP id - //| PortableL (name, fws) -> FrameworkRestrictionP.PortableP (name, fws) | AtLeastL id -> FrameworkRestrictionP.AtLeastP id type FrameworkRestrictionLiteral = { LiteraL : FrameworkRestrictionLiteralI; IsNegated : bool } @@ -390,12 +365,12 @@ let parseRestrictionsLegacy failImmediatly (text:string) = match FrameworkDetection.Extract(framework) with - | None -> - let platforms = (PlatformMatching.extractPlatforms framework).Platforms - if platforms |> List.isEmpty |> not then - yield FrameworkRestriction.AtLeastPortable (framework, platforms) - else - handleError <| sprintf "Could not parse framework '%s'. Try to update or install again or report a paket bug." framework + | None -> + match PlatformMatching.extractPlatforms framework |> Option.bind (fun pp -> pp.ToTargetProfile) with + | Some profile -> + yield FrameworkRestriction.AtLeastPlatform profile + | None -> + handleError <| sprintf "Could not parse framework '%s'. Try to update or install again or report a paket bug." framework | Some x -> if operatorSplit.[0] = ">=" then if operatorSplit.Length < 4 then @@ -433,7 +408,7 @@ let parseRestrictions failImmediatly (text:string) = if splitted.Length < 1 then failwithf "No parameter after >= or < in '%s'" text let rawOperator = splitted.[0] let operator = rawOperator.TrimEnd([|')'|]) - match (PlatformMatching.extractPlatforms operator).ToTargetProfile with + match PlatformMatching.extractPlatforms operator |> Option.bind (fun pp -> pp.ToTargetProfile) with | None -> failwithf "invalid parameter '%s' after >= or < in '%s'" operator text | Some plat -> let f = @@ -788,11 +763,7 @@ type PackageRequirement = PackageRequirement.Compare(this,that,None,0,0) | _ -> invalidArg "that" "cannot compare value of different types" -let addFrameworkRestrictionsToDependencies rawDependencies (frameworkGroups:TargetProfile list) = - let frameworkGroupPaths = - frameworkGroups - |> Seq.map (PlatformMatching.ParsedPlatformPath.FromTargetProfile) - |> Seq.toList +let addFrameworkRestrictionsToDependencies rawDependencies (frameworkGroups:PlatformMatching.ParsedPlatformPath list) = let referenced = rawDependencies |> List.groupBy (fun (n:PackageName,req,pp:PlatformMatching.ParsedPlatformPath) -> n,req) @@ -810,9 +781,7 @@ let addFrameworkRestrictionsToDependencies rawDependencies (frameworkGroups:Targ | _ -> FrameworkRestriction.AtLeastPortable(packageGroup.Name, packageGroup.Platforms) frameworkGroups - //|> Seq.filter (fun frameworkGroup -> - // // special casing for portable -> should be removed once portable is a normal FrameworkIdentifier - // if packageGroup.Platforms.Length < 2 then packageGroup.Platforms |> Seq.contains frameworkGroup |> not else true) + |> Seq.choose (fun g -> g.ToTargetProfile) // TODO: Check if this is needed (I think the logic below is a general version of this subset logic) |> Seq.filter (fun frameworkGroup -> // filter all restrictions which would render this group to nothing (ie smaller restrictions) @@ -832,29 +801,13 @@ let addFrameworkRestrictionsToDependencies rawDependencies (frameworkGroups:Targ match packageGroup.Platforms, missing.RepresentedFrameworks with | [ packageGroupFw ], firstMissing :: _ -> // the common set goes to the better matching one - match PlatformMatching.findBestMatch (frameworkGroupPaths, firstMissing) with + match PlatformMatching.findBestMatch (frameworkGroups, firstMissing) with | Some { PlatformMatching.ParsedPlatformPath.Platforms = [ cfw ] } when cfw = packageGroupFw -> curRestr | _ -> combined | _ -> combined) packageGroupRestriction) let combinedRestrictions = restrictions |> List.fold FrameworkRestriction.combineRestrictionsWithOr FrameworkRestriction.EmptySet name, req, combinedRestrictions ) - //|> List.append frameworks - - // While this is correct we want a more generic representation, such that future platforms "just work" - // I'll leave this code for now to better understand that the above is doing the same thing, but resulting in a more generallized restriction. - //let availablePlatforms = referenced |> List.map (fun (_,_,pp) -> pp) - //let calculateDistribution = PlatformMatching.getSupportedTargetProfiles availablePlatforms - // - //let referenced = - // referenced - // |> List.map (fun (name, req, pp) -> - // let restriction = - // calculateDistribution.[pp] - // |> Seq.fold (fun state profile -> - // FrameworkRestriction.Or(state, FrameworkRestriction.ExactlyProfile profile)) FrameworkRestriction.EmptySet - // name, req, restriction) - // referenced |> List.map (fun (a,b,c) -> a,b, ExplicitRestriction c) \ No newline at end of file diff --git a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs index 4d5b4f2f9b..10ad68b377 100644 --- a/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs +++ b/tests/Paket.Tests/InstallModel/Penalty/PenaltySpecs.fs @@ -31,26 +31,26 @@ module ``Given a target platform`` = module ``Given a path`` = [] let ``it should split it into the right platforms``() = - extractPlatforms "net40+win8" + forceExtractPlatforms "net40+win8" |> shouldEqual { Platforms = [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8 ] Name = "net40+win8" } [] let ``it should ignore 'portable-'``() = - extractPlatforms "portable-net40+win8" + forceExtractPlatforms "portable-net40+win8" |> shouldEqual { Platforms = [ DotNetFramework FrameworkVersion.V4; Windows WindowsVersion.V8 ] Name = "portable-net40+win8" } [] let ``it should return no penalty for a matching .NET framework``() = - let path = extractPlatforms "net45" + let path = forceExtractPlatforms "net45" getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldEqual 0 [] let ``it should return no penalty for a matching portable profile``() = - let path = extractPlatforms "net40+sl4" + let path = forceExtractPlatforms "net40+sl4" getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4 Silverlight SilverlightVersion.V4 ] path @@ -58,7 +58,7 @@ module ``Given a path`` = [] let ``it should return 1 for a compatible portable profile``() = - let path = extractPlatforms "net40+sl4" + let path = forceExtractPlatforms "net40+sl4" getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4 Silverlight SilverlightVersion.V5 ] path @@ -66,7 +66,7 @@ module ``Given a path`` = [] let ``it should return the correct penalty for compatible .NET Frameworks``() = - let path = extractPlatforms "net20" + let path = forceExtractPlatforms "net20" getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V2 ] path |> shouldEqual 0 getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V3 ] path |> shouldEqual 1 getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V3_5 ] path |> shouldEqual 2 @@ -75,12 +75,12 @@ module ``Given a path`` = module ``Given an empty path`` = [] let ``it should be okay to use from .NET``() = - let path = extractPlatforms "" + let path = forceExtractPlatforms "" getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5 ] path |> shouldBeSmallerThan 2000 [] let ``it should be okay to use from a portable profile``() = - let path = extractPlatforms "" + let path = forceExtractPlatforms "" getFrameworkPathPenalty [ DotNetFramework FrameworkVersion.V4_5; Windows WindowsVersion.V8; WindowsPhoneApp WindowsPhoneAppVersion.V8_1 ] path |> shouldBeSmallerThan 2000 module ``Given a list of paths`` = @@ -88,7 +88,7 @@ module ``Given a list of paths`` = [ "net40"; "portable-monotouch+monoandroid"; "portable-net40+sl5+win8+wp8+wpa81" "portable-net45+winrt45+wp8+wpa81"; "portable-win81+wpa81"; "portable-windows8+net45+wp8"; "sl5"; "win8" "wp8" ] - |> List.map extractPlatforms + |> List.map forceExtractPlatforms let find n = paths |> Seq.find (fun p -> p.Name = n) @@ -126,131 +126,124 @@ module ``Given a list of paths`` = } flattend |> shouldNotContain (KnownTargetProfiles.FindPortableProfile "Profile41") -module ``ProfileAnalyzer tests`` = - () - //[] - //let ``test that we cannot detect portable-net40+sl4+win8+wp71+wpa81`` () = - // let res = Paket.PlatformMatching.tryGetProfile (extractPlatforms "portable-net40+sl4+win8+wp71+wpa81") - // res |> shouldEqual None - module ``General Penalty checks`` = [] let ``prefer net20 over emtpy folder``()= - Paket.PlatformMatching.findBestMatch ([""; "net20"] |> List.map extractPlatforms, SinglePlatform(DotNetFramework(FrameworkVersion.V4_6_1))) - |> shouldEqual (Some (extractPlatforms "net20")) + Paket.PlatformMatching.findBestMatch ([""; "net20"] |> List.map forceExtractPlatforms, SinglePlatform(DotNetFramework(FrameworkVersion.V4_6_1))) + |> shouldEqual (Some (forceExtractPlatforms "net20")) [] let ``best match for DotNet Standard 1.0``()= - Paket.PlatformMatching.findBestMatch (["net20"; "net40"; "net45"; "net451"]|> List.map extractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_0))) + Paket.PlatformMatching.findBestMatch (["net20"; "net40"; "net45"; "net451"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_0))) |> shouldEqual (None) [] let ``best match for DotNet Standard 1.1``()= - Paket.PlatformMatching.findBestMatch (["net20"; "net40"; "net45"; "net451"]|> List.map extractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_1))) + Paket.PlatformMatching.findBestMatch (["net20"; "net40"; "net45"; "net451"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_1))) |> shouldEqual (None) [] let ``best match for DotNet Standard 1.5``()= - Paket.PlatformMatching.findBestMatch (["net20"; "net40"; "net45"; "net451"]|> List.map extractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_5))) + Paket.PlatformMatching.findBestMatch (["net20"; "net40"; "net45"; "net451"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_5))) |> shouldEqual (None) [] let ``best match for net45``()= Paket.PlatformMatching.findBestMatch - (["netstandard10"; "netstandard11"; "netstandard12"; "netstandard13"; "netstandard14"; "netstandard15"; "netstandard16"]|> List.map extractPlatforms, + (["netstandard10"; "netstandard11"; "netstandard12"; "netstandard13"; "netstandard14"; "netstandard15"; "netstandard16"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetFramework(FrameworkVersion.V4_5))) - |> shouldEqual (Some (extractPlatforms "netstandard11")) + |> shouldEqual (Some (forceExtractPlatforms "netstandard11")) [] let ``best match for netstandard in portable``()= Paket.PlatformMatching.findBestMatch - (["portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_1))) |> shouldEqual (None) Paket.PlatformMatching.findBestMatch - (["portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_2))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wpa81")) Paket.PlatformMatching.findBestMatch - (["portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_3))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wpa81")) Paket.PlatformMatching.findBestMatch - (["portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_4))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wpa81")) Paket.PlatformMatching.findBestMatch - (["portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_5))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wpa81")) Paket.PlatformMatching.findBestMatch - (["portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_6))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wpa81")) [] let ``best match for netstandard, netstandard is preferred``()= Paket.PlatformMatching.findBestMatch - (["portable-win81+wpa81"; "netstandard1.3"]|> List.map extractPlatforms, + (["portable-win81+wpa81"; "netstandard1.3"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_2))) - |> shouldEqual (Some (extractPlatforms "portable-win81+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-win81+wpa81")) Paket.PlatformMatching.findBestMatch - (["portable-win81+wpa81"; "netstandard1.3"]|> List.map extractPlatforms, + (["portable-win81+wpa81"; "netstandard1.3"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_3))) - |> shouldEqual (Some (extractPlatforms "netstandard1.3")) + |> shouldEqual (Some (forceExtractPlatforms "netstandard1.3")) Paket.PlatformMatching.findBestMatch - (["portable-win81+wpa81"; "netstandard1.3"]|> List.map extractPlatforms, + (["portable-win81+wpa81"; "netstandard1.3"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_4))) - |> shouldEqual (Some (extractPlatforms "netstandard1.3")) + |> shouldEqual (Some (forceExtractPlatforms "netstandard1.3")) [] let ``best match for netstandard, use possible.``()= Paket.PlatformMatching.findBestMatch // Profile31 (supports netstandard1.0), Profile32 (supports netstandard1.2) - (["portable-netcore451+wp81"; "portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wp81"; "portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_0))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wp81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wp81")) Paket.PlatformMatching.findBestMatch // Profile31 (supports netstandard1.0), Profile32 (supports netstandard1.2) - (["portable-netcore451+wp81"; "portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wp81"; "portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_2))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wpa81")) Paket.PlatformMatching.findBestMatch // Profile31 (supports netstandard1.0), Profile32 (supports netstandard1.2) - (["portable-netcore451+wp81"; "portable-netcore451+wpa81"]|> List.map extractPlatforms, + (["portable-netcore451+wp81"; "portable-netcore451+wpa81"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_4))) - |> shouldEqual (Some (extractPlatforms "portable-netcore451+wpa81")) + |> shouldEqual (Some (forceExtractPlatforms "portable-netcore451+wpa81")) [] let ``make sure not all portable profiles match``()= // Not all portable profiles have a match. Paket.PlatformMatching.findBestMatch - (["portable-net45+win8"]|> List.map extractPlatforms, + (["portable-net45+win8"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetStandard(DotNetStandardVersion.V1_0))) |> shouldEqual (None) [] let ``best match for net451``()= Paket.PlatformMatching.findBestMatch - (["netstandard10"; "netstandard11"; "netstandard12"; "netstandard13"; "netstandard14"; "netstandard15"; "netstandard16"]|> List.map extractPlatforms, + (["netstandard10"; "netstandard11"; "netstandard12"; "netstandard13"; "netstandard14"; "netstandard15"; "netstandard16"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetFramework(FrameworkVersion.V4_5_1))) - |> shouldEqual (Some (extractPlatforms "netstandard12")) + |> shouldEqual (Some (forceExtractPlatforms "netstandard12")) [] let ``best match for net463``()= Paket.PlatformMatching.findBestMatch - (["netstandard10"; "netstandard11"; "netstandard12"; "netstandard13"; "netstandard14"; "netstandard15"; "netstandard16"]|> List.map extractPlatforms, + (["netstandard10"; "netstandard11"; "netstandard12"; "netstandard13"; "netstandard14"; "netstandard15"; "netstandard16"]|> List.map forceExtractPlatforms, SinglePlatform(DotNetFramework(FrameworkVersion.V4_6_3))) - |> shouldEqual (Some (extractPlatforms "netstandard16")) + |> shouldEqual (Some (forceExtractPlatforms "netstandard16")) diff --git a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs index d9a37db8de..69b5a88740 100644 --- a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs +++ b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs @@ -281,8 +281,6 @@ let ``should install not use net40-full for client profile``() = |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll" model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) |> Seq.map (fun f -> f.Path) |> shouldContain @"..\Newtonsoft.Json\lib\net40-full\Newtonsoft.Json.dll" - //model.GetLegacyReferences(SinglePlatform (DotNetFramework FrameworkVersion.V4)) - // |> Seq.map (fun f -> f.Path) |> shouldNotContain @"..\Newtonsoft.Json\lib\net40-full\Newtonsoft.Json.dll" [] let ``should handle lib install of Microsoft.Net.Http for .NET 4.5``() = diff --git a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs index 2b34f0d14f..937f81ee6c 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs @@ -83,10 +83,10 @@ let expectedPropertyNodes = """ let ``can get supported target profile``()= let profiles = ["net20"; "net40"; "net45"; "net451"; "netstandard14" ] - |> List.map extractPlatforms + |> List.map forceExtractPlatforms |> PlatformMatching.getSupportedTargetProfiles let folder = profiles |> Seq.item 2 - folder.Key |> shouldEqual (extractPlatforms "net45") + folder.Key |> shouldEqual (forceExtractPlatforms "net45") folder.Value |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] [] diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index 8ed9855ba1..d19d67fbc8 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -159,7 +159,8 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = [] let ``can ignore unknown frameworks``() = - parse "NuGetOData/BenchmarkDotNet-UnknownFramework.xml" + let parsed = parse "NuGetOData/BenchmarkDotNet-UnknownFramework.xml" + parsed |> shouldEqual { PackageName = "BenchmarkDotNet" DownloadUrl = "https://www.nuget.org/api/v2/package/BenchmarkDotNet/0.10.1" diff --git a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs index 00a498c625..8d8e070229 100644 --- a/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs +++ b/tests/Paket.Tests/ProjectFile/TargetFrameworkSpecs.fs @@ -43,5 +43,4 @@ let ``should detect the correct framework on test projects`` projectFile expecte let p = ProjectFile.TryLoad("./ProjectFile/TestData/" + projectFile).Value p.GetTargetProfile() |> shouldEqual expectedProfile p.GetTargetProfile().ToString() |> shouldEqual expectedProfileString - //p.GetTargetProfile() |> shouldEqual (portable) diff --git a/tests/Paket.Tests/TestHelpers.fs b/tests/Paket.Tests/TestHelpers.fs index 6c21115c3c..b92663a8fa 100644 --- a/tests/Paket.Tests/TestHelpers.fs +++ b/tests/Paket.Tests/TestHelpers.fs @@ -16,7 +16,7 @@ let makeOrList (l:_ list) = let getPortableRestriction s = let pf = PlatformMatching.extractPlatforms s - FrameworkRestriction.AtLeastPortable(s, pf.Platforms) + FrameworkRestriction.AtLeastPortable(s, pf.Value.Platforms) type GraphDependency = string * VersionRequirement * FrameworkRestrictions diff --git a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs index 3988dab236..4dd06f261a 100644 --- a/tests/Paket.Tests/Versioning/DependencySetSpecs.fs +++ b/tests/Paket.Tests/Versioning/DependencySetSpecs.fs @@ -136,12 +136,12 @@ let ``filtered with Between restriction should filter non-matching`` () = [] let ``should optimize ZendeskApi_v2 ``() = let original = - [PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "net35" - PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "net4" - PackageName("AsyncCTP"), (), PlatformMatching.extractPlatforms "net4" - PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "net45" - PackageName("Newtonsoft.Json"), (), PlatformMatching.extractPlatforms "portable-net45+sl40+wp71+win80" - PackageName("Microsoft.Bcl.Async"),(), PlatformMatching.extractPlatforms "portable-net45+sl40+wp71+win80"] + [PackageName("Newtonsoft.Json"), (), PlatformMatching.forceExtractPlatforms "net35" + PackageName("Newtonsoft.Json"), (), PlatformMatching.forceExtractPlatforms "net4" + PackageName("AsyncCTP"), (), PlatformMatching.forceExtractPlatforms "net4" + PackageName("Newtonsoft.Json"), (), PlatformMatching.forceExtractPlatforms "net45" + PackageName("Newtonsoft.Json"), (), PlatformMatching.forceExtractPlatforms "portable-net45+sl40+wp71+win80" + PackageName("Microsoft.Bcl.Async"),(), PlatformMatching.forceExtractPlatforms "portable-net45+sl40+wp71+win80"] let expected = [PackageName("Newtonsoft.Json"), (), @@ -152,21 +152,21 @@ let ``should optimize ZendeskApi_v2 ``() = PackageName("Microsoft.Bcl.Async"), (),ExplicitRestriction (getPortableRestriction "portable-net45+sl40+wp71+win80")] let result = addFrameworkRestrictionsToDependencies original [ - SinglePlatform (DotNetFramework(FrameworkVersion.V3_5)) - SinglePlatform (DotNetFramework(FrameworkVersion.V4)) - SinglePlatform (DotNetFramework(FrameworkVersion.V4_5)) - (PlatformMatching.extractPlatforms "portable-net45+sl40+wp71+win80").ToTargetProfile.Value ] + PlatformMatching.forceExtractPlatforms "net35" + PlatformMatching.forceExtractPlatforms "net40" + PlatformMatching.forceExtractPlatforms "net45" + PlatformMatching.forceExtractPlatforms "portable-net45+sl40+wp71+win80" ] result |> shouldEqual expected [] let ``should optimize real world restrictions``() = let original = - [PackageName("P1"), (), PlatformMatching.extractPlatforms "net20" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net35" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net45" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net451" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net46"] + [PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net20" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net35" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net45" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net451" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net46"] let expected = [PackageName("P1"), (), @@ -175,19 +175,21 @@ let ``should optimize real world restrictions``() = let result = addFrameworkRestrictionsToDependencies original - ([ FrameworkVersion.V2; FrameworkVersion.V3_5 - FrameworkVersion.V4_5; FrameworkVersion.V4_5_1 - FrameworkVersion.V4_6] |> List.map (DotNetFramework >> SinglePlatform)) + [ PlatformMatching.forceExtractPlatforms "net2" + PlatformMatching.forceExtractPlatforms "net35" + PlatformMatching.forceExtractPlatforms "net45" + PlatformMatching.forceExtractPlatforms "net451" + PlatformMatching.forceExtractPlatforms "net46" ] result |> shouldEqual expected [] let ``should optimize real world restrictions 2``() = let original = - [PackageName("P1"), (), PlatformMatching.extractPlatforms "net20" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net4" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net45" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net451" - PackageName("P1"), (), PlatformMatching.extractPlatforms "net46"] + [PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net20" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net4" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net45" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net451" + PackageName("P1"), (), PlatformMatching.forceExtractPlatforms "net46"] let expected = [PackageName("P1"), (), @@ -196,9 +198,11 @@ let ``should optimize real world restrictions 2``() = let result = addFrameworkRestrictionsToDependencies original - ([ FrameworkVersion.V2; FrameworkVersion.V4 - FrameworkVersion.V4_5; FrameworkVersion.V4_5_1 - FrameworkVersion.V4_6] |> List.map (DotNetFramework >> SinglePlatform)) + [ PlatformMatching.forceExtractPlatforms "net2" + PlatformMatching.forceExtractPlatforms "net4" + PlatformMatching.forceExtractPlatforms "net45" + PlatformMatching.forceExtractPlatforms "net451" + PlatformMatching.forceExtractPlatforms "net46" ] result |> shouldEqual expected [] diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index f9cdaa769a..56b9659960 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -8,7 +8,7 @@ open Paket.Requirements [] let ``Simplify || (>= net45) (>= portable-net45+win8+wp8+wp81+wpa81)`` () = // because that is a custom portable profile! - let portable = (PlatformMatching.extractPlatforms "portable-net45+win8+wp8+wp81+wpa81").ToTargetProfile.Value + let portable = (PlatformMatching.forceExtractPlatforms "portable-net45+win8+wp8+wp81+wpa81").ToTargetProfile.Value let atLeastPortable = FrameworkRestriction.AtLeastPlatform portable // this was the underlying bug @@ -23,7 +23,7 @@ let ``Simplify || (>= net45) (>= portable-net45+win8+wp8+wp81+wpa81)`` () = [] let ``CustomProfile is Supported by its Platforms``() = let unknownProfile = - (PlatformMatching.extractPlatforms "portable-net45+monoandroid10+monotouch10+xamarinios10").ToTargetProfile.Value + (PlatformMatching.forceExtractPlatforms "portable-net45+monoandroid10+monotouch10+xamarinios10").ToTargetProfile.Value unknownProfile.IsSupportedBy (SinglePlatform (DotNetFramework FrameworkVersion.V4_5)) |> shouldEqual true @@ -99,7 +99,7 @@ let ``Generate Support Table``() = [] let ``Unknown Portables are detected correctly``() = - PlatformMatching.extractPlatforms "portable-monotouch+monoandroid" + PlatformMatching.forceExtractPlatforms "portable-monotouch+monoandroid" |> function { Platforms = o } -> TargetProfile.FindPortable o |> shouldEqual (PortableProfile (PortableProfileType.UnsupportedProfile [MonoAndroid; MonoTouch])) [] @@ -113,7 +113,7 @@ let ``Portables are detected correctly``() = "portable-windows8+net45+wp8" "sl5"; "win8" "wp8" ] - |> List.map PlatformMatching.extractPlatforms + |> List.map PlatformMatching.forceExtractPlatforms |> List.map (function { Platforms = [ h] } -> SinglePlatform h | {Platforms = o} -> TargetProfile.FindPortable o) let expected = [ SinglePlatform (DotNetFramework FrameworkVersion.V4); @@ -126,21 +126,6 @@ let ``Portables are detected correctly``() = portables |> shouldEqual expected -[] -let ``PortableProfile supports PortableProfiles but it is not recursive``() = - let portableProfiles = - KnownTargetProfiles.AllPortableProfiles - |> List.map PortableProfile - let getSupported (p:TargetProfile) = p.SupportedPlatforms - let supportTree = () - //Seq.initInfinite (fun _ -> 0) - //|> Seq.fold (fun (lastItems) _ -> () - // ) portableProfiles - - - () - - [] let ``PlatformMatching works with portable ``() = // portable-net40-sl4 diff --git a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs index f214cf825e..af2bbefc76 100644 --- a/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionFilterSpecs.fs @@ -116,8 +116,6 @@ let ``should filter >= net20 < net40 and >= net40``() = [] let ``should not filter native, net452``() = - //FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform)).IsSameCategoryAs(FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))) |> shouldEqual (Some true) - let l1 = ExplicitRestriction (FrameworkRestriction.Or [FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4_5_2)); FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))]) let l2 = ExplicitRestriction (FrameworkRestriction.Exactly(Native(NoBuildMode,NoPlatform))) From 9d3831fc40f8375f64a79a7b10779d81c2ca1310 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 02:01:45 +0200 Subject: [PATCH 20/47] use sets for targetprofiles. --- Paket.sln | 5 +- .../Dependencies/PackageResolver.fs | 2 +- .../PaketConfigFiles/InstallModel.fs | 14 ++-- .../PaketConfigFiles/ProjectFile.fs | 4 +- .../Versioning/FrameworkHandling.fs | 82 ++++++++++--------- src/Paket.Core/Versioning/PlatformMatching.fs | 38 ++++----- src/Paket.Core/Versioning/Requirements.fs | 34 ++++---- src/Paket/Paket.fsproj | 2 +- .../Penalty/FrameworkConditionsSpecs.fs | 18 ++-- .../InstallModel/ProcessingSpecs.fs | 2 +- tests/Paket.Tests/InstallModel/Xml/SQLite.fs | 8 +- .../Versioning/FrameworkRestrictionTests.fs | 8 +- .../Versioning/RestrictionApplicationSpecs.fs | 11 +-- 13 files changed, 119 insertions(+), 109 deletions(-) diff --git a/Paket.sln b/Paket.sln index 8e9e3014d9..0d5d453b8e 100644 --- a/Paket.sln +++ b/Paket.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26403.7 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{A6A6AF7D-D6E3-442D-9B1E-58CC91879BE1}" EndProject @@ -102,6 +102,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{62D18A EndProjectSection EndProject Global + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 8de6ab01f6..c2caa21ad4 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -61,7 +61,7 @@ module DependencySetFilter = // we need to take the dependency, when the combination still contains packages. // NOTE: This is not forwards compatible... let combined = FrameworkRestriction.And [ restriction; dependencyRestrictions ] - combined.RepresentedFrameworks.Length > 0 + not combined.RepresentedFrameworks.IsEmpty let filterByRestrictions (restrictions:FrameworkRestrictions) (dependencies:DependencySet) : DependencySet = match getExplicitRestriction restrictions with diff --git a/src/Paket.Core/PaketConfigFiles/InstallModel.fs b/src/Paket.Core/PaketConfigFiles/InstallModel.fs index 4f1d5470d4..875a5f11c6 100644 --- a/src/Paket.Core/PaketConfigFiles/InstallModel.fs +++ b/src/Paket.Core/PaketConfigFiles/InstallModel.fs @@ -72,12 +72,12 @@ module ReferenceOrLibraryFolder = /// Represents a subfolder of a nuget package that provides files (content, references, etc) for one or more Target Profiles. This is a logical representation of the 'net45' folder in a NuGet package, for example. type FrameworkFolder<'T> = { Path : ParsedPlatformPath - Targets : TargetProfile list + Targets : TargetProfile Set FolderContents : 'T } with member this.GetSinglePlatforms() = this.Targets - |> List.choose (function SinglePlatform t -> Some t | _ -> None) + |> Seq.choose (function SinglePlatform t -> Some t | _ -> None) module FrameworkFolder = let map f (l:FrameworkFolder<_>) = { @@ -676,7 +676,7 @@ module InstallModel = let addFrameworkAssemblyReference (installModel:InstallModel) (reference:FrameworkAssemblyReference) : InstallModel = let referenceApplies (folder : FrameworkFolder<_>) = - applyRestrictionsToTargets (reference.FrameworkRestrictions |> getExplicitRestriction) folder.Targets + applyRestrictionsToTargets (reference.FrameworkRestrictions |> getExplicitRestriction) (folder.Targets) |> Seq.isEmpty |> not @@ -731,22 +731,22 @@ module InstallModel = CompileLibFolders = installModel.CompileLibFolders |> List.map applyRestriction - |> List.filter (fun folder -> folder.Targets <> []) + |> List.filter (fun folder -> not folder.Targets.IsEmpty) CompileRefFolders = installModel.CompileRefFolders |> List.map applyRestriction - |> List.filter (fun folder -> folder.Targets <> []) + |> List.filter (fun folder -> not folder.Targets.IsEmpty) RuntimeAssemblyFolders = installModel.RuntimeAssemblyFolders |> List.map applyRestriction - |> List.filter (fun folder -> folder.Targets <> []) + |> List.filter (fun folder -> not folder.Targets.IsEmpty) TargetsFileFolders = installModel.TargetsFileFolders |> List.map applyRestriction - |> List.filter (fun folder -> folder.Targets <> []) + |> List.filter (fun folder -> not folder.Targets.IsEmpty) } let rec addTargetsFiles (targetsFiles:UnparsedPackageFile list) (this:InstallModel) : InstallModel = diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs index 51118e7ede..592ada8b74 100644 --- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs +++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs @@ -670,7 +670,7 @@ module ProjectFile = |> Set.ofList let model = model.FilterReferences references - let createItemGroup (targets:TargetProfile list) (frameworkReferences:FrameworkReference list) (libraries:Library list) = + let createItemGroup (targets:TargetProfile Set) (frameworkReferences:FrameworkReference list) (libraries:Library list) = let itemGroup = createNode "ItemGroup" project for ref in frameworkReferences |> List.sortBy (fun f -> f.Name) do @@ -762,7 +762,7 @@ module ProjectFile = for frameworkAssembly in frameworkReferences do for t in libFolder.Targets do if not <| usedFrameworkLibs.Add(t,frameworkAssembly.Name) then - assemblyTargets := List.filter ((<>) t) !assemblyTargets + assemblyTargets := Set.remove t !assemblyTargets // List.filter ((<>) t) !assemblyTargets duplicates.Add frameworkAssembly.Name |> ignore if !assemblyTargets = libFolder.Targets then diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index d9aeb90bc4..447b94fd9b 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -915,13 +915,13 @@ module KnownTargetProfiles = (AllNativeProfiles |> List.map SinglePlatform) @ AllDotNetStandardAndCoreProfiles @ AllDotNetProfiles - |> List.distinct - |> List.sort + |> Set.ofList let TryFindPortableProfile (name:string) = let lowerName = name.ToLowerInvariant() AllProfiles - |> List.tryPick (function + |> Set.toSeq + |> Seq.tryPick (function | PortableProfile p when p.ProfileName.ToLowerInvariant() = lowerName -> Some (PortableProfile p) | _ -> None) let FindPortableProfile name = @@ -1018,49 +1018,51 @@ module PortableProfileSupportCalculation = supportMap <- opt result | _ -> failwithf "Expected that default profiles are already created." - + + let findPortable = + memoize (fun (fws: _ list) -> + if fws.Length = 0 then failwithf "can not find portable for an empty list (Details: Empty lists need to be handled earlier with a warning)!" + let fallback = PortableProfile (UnsupportedProfile (fws |> List.sort)) + let minimal = + fws + |> List.filter (function + | MonoTouch + | DNXCore _ + | UAP _ + | MonoAndroid -> false + | DotNetCore _ + | DotNetStandard _ -> failwithf "Unexpected famework while trying to resolve PCL Profile" + | _ -> true) + if minimal.Length > 0 then + let matches = + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun p -> + let otherFws = p.Frameworks + minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) + |> List.sortBy (fun p -> p.Frameworks.Length) + |> Seq.toArray // Debug + let firstMatch = + KnownTargetProfiles.AllPortableProfiles + |> List.filter (fun p -> + let otherFws = p.Frameworks + minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) + |> List.sortBy (fun p -> p.Frameworks.Length) + |> List.tryHead + match firstMatch with + | Some p -> PortableProfile p + | None -> + traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback + fallback + else + traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback + fallback) type TargetProfile with member p.Frameworks = match p with | SinglePlatform fw -> [fw] | PortableProfile p -> p.Frameworks - static member FindPortable (fws: _ list) = - if fws.Length = 0 then failwithf "can not find portable for an empty list (Details: Empty lists need to be handled earlier with a warning)!" - let fallback = PortableProfile (UnsupportedProfile (fws |> List.sort)) - let minimal = - fws - |> List.filter (function - | MonoTouch - | DNXCore _ - | UAP _ - | MonoAndroid -> false - | DotNetCore _ - | DotNetStandard _ -> failwithf "Unexpected famework while trying to resolve PCL Profile" - | _ -> true) - if minimal.Length > 0 then - let matches = - KnownTargetProfiles.AllPortableProfiles - |> List.filter (fun p -> - let otherFws = p.Frameworks - minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) - |> List.sortBy (fun p -> p.Frameworks.Length) - |> Seq.toArray // Debug - let firstMatch = - KnownTargetProfiles.AllPortableProfiles - |> List.filter (fun p -> - let otherFws = p.Frameworks - minimal |> List.forall(fun mfw -> otherFws |> Seq.contains mfw)) - |> List.sortBy (fun p -> p.Frameworks.Length) - |> List.tryHead - match firstMatch with - | Some p -> PortableProfile p - | None -> - traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback - fallback - else - traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback - fallback + static member FindPortable (fws: _ list) = PortableProfileSupportCalculation.findPortable fws /// true when x is supported by y, for example netstandard15 is supported by netcore10 member x.IsSupportedBy y = diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index 1b00616f47..81e733f3f3 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -131,20 +131,19 @@ let comparePaths (p1 : PathPenalty) (p2 : PathPenalty) = let collectPlatforms = - let rec loop (acc:TargetProfile list) (framework:TargetProfile) (profls:TargetProfile list) = - match profls with - | [] -> acc - | f::tl -> - if f.SupportedPlatforms |> List.exists ((=) framework) - then loop (f::acc) framework tl - else loop acc framework tl + let rec loop (acc:TargetProfile list) (framework:TargetProfile) (profls:TargetProfile Set) = + profls + |> Seq.fold (fun acc f -> + if f.SupportedPlatforms |> List.exists ((=) framework) then + f::acc + else acc) [] memoize (fun (framework,profls) -> loop ([]:TargetProfile list) framework profls) let getPlatformsSupporting = // http://nugettoolsdev.azurewebsites.net let calculate (x:TargetProfile) = KnownTargetProfiles.AllProfiles - |> List.filter (fun plat -> x.IsSupportedBy plat) + |> Set.filter (fun plat -> x.IsSupportedBy plat) memoize calculate let platformsSupport = @@ -177,13 +176,13 @@ let getSupportedTargetProfiles = memoize (fun (paths : ParsedPlatformPath list) -> KnownTargetProfiles.AllProfiles - |> List.choose (fun target -> + |> Seq.choose (fun target -> match findBestMatch(paths,target) with | Some p -> Some(p, target) | _ -> None) - |> List.groupBy fst - |> List.map (fun (path, group) -> path, List.map snd group) - |> Map.ofList) + |> Seq.groupBy fst + |> Seq.map (fun (path, group) -> path, Seq.map snd group |> Set.ofSeq) + |> Map.ofSeq) let getTargetCondition (target:TargetProfile) = @@ -218,15 +217,15 @@ let getTargetCondition (target:TargetProfile) = | Native(profile,bits) -> (sprintf "'$(Configuration)|$(Platform)'=='%s|%s'" profile.AsString bits.AsString), "" | PortableProfile p -> sprintf "$(TargetFrameworkProfile) == '%O'" p.ProfileName,"" -let getCondition (referenceCondition:string option) (allTargets: TargetProfile list list) (targets : TargetProfile list) = +let getCondition (referenceCondition:string option) (allTargets: TargetProfile Set list) (targets : TargetProfile Set) = let inline CheckIfFullyInGroup typeName matchF filterRestF (processed,targets) = let fullyContained = KnownTargetProfiles.AllDotNetProfiles |> List.filter matchF - |> List.forall (fun p -> targets |> Seq.exists ((=) p)) + |> List.forall (fun p -> targets |> Set.contains p) if fullyContained then - (sprintf "$(TargetFrameworkIdentifier) == '%s'" typeName,"") :: processed,targets |> List.filter (filterRestF >> not) + (sprintf "$(TargetFrameworkIdentifier) == '%s'" typeName,"") :: processed,targets |> Set.filter (filterRestF >> not) else processed,targets let inline CheckIfFullyInGroupS typeName matchF (processed,targets) = @@ -241,15 +240,16 @@ let getCondition (referenceCondition:string option) (allTargets: TargetProfile l |> CheckIfFullyInGroupS "WindowsPhone" (function SinglePlatform (WindowsPhone _) -> true | _ -> false) let conditions = - if targets = [ SinglePlatform(Native(NoBuildMode,NoPlatform)) ] then + if targets.Count = 1 && targets |> Set.minElement = SinglePlatform(Native(NoBuildMode,NoPlatform)) then targets else targets - |> List.filter (function + |> Set.filter (function | SinglePlatform(Native(NoBuildMode,NoPlatform)) -> false | _ -> true) - |> List.map getTargetCondition - |> List.filter (fun (_, v) -> v <> "false") + |> Seq.map getTargetCondition + |> Seq.filter (fun (_, v) -> v <> "false") + |> Seq.toList |> List.append grouped |> List.groupBy fst diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 3f239de164..228d6ae55d 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -53,26 +53,27 @@ type FrameworkRestrictionP = | _ -> sprintf "&& %s" (System.String.Join(" ", frl |> Seq.map (sprintf "(%O)"))) /// The list represented by this restriction (ie the included set of frameworks) + // NOTE: All critical paths test only if this set is empty, so we use lazy seq here member x.RepresentedFrameworks = match x with - | FrameworkRestrictionP.ExactlyP r -> [ r ] + | FrameworkRestrictionP.ExactlyP r -> [ r ] |> Set.ofList | FrameworkRestrictionP.AtLeastP r -> PlatformMatching.getPlatformsSupporting r + //KnownTargetProfiles.AllProfiles + //|> Set.filter (fun plat -> r.IsSupportedBy plat) | FrameworkRestrictionP.NotP(fr) -> let notTaken = fr.RepresentedFrameworks - KnownTargetProfiles.AllProfiles - |> List.filter (fun fw -> notTaken |> Seq.contains fw |> not) + Set.difference KnownTargetProfiles.AllProfiles notTaken | FrameworkRestrictionP.OrP (frl) -> frl - |> List.collect (fun fr -> fr.RepresentedFrameworks) - |> List.distinct - |> List.sort + |> Seq.map (fun fr -> fr.RepresentedFrameworks) + |> Set.unionMany | FrameworkRestrictionP.AndP (frl) -> match frl with | h :: _ -> - let allLists = frl |> List.map (fun fr -> fr.RepresentedFrameworks) - h.RepresentedFrameworks - |> List.filter (fun fw -> allLists |> List.forall(fun l1 -> l1 |> Seq.contains fw)) + frl + |> Seq.map (fun fr -> fr.RepresentedFrameworks) + |> Set.intersectMany | [] -> KnownTargetProfiles.AllProfiles @@ -95,7 +96,7 @@ type FrameworkRestrictionP = member x.IsSubsetOf (y:FrameworkRestrictionP) = let superset = y.RepresentedFrameworks x.RepresentedFrameworks - |> List.forall (fun inner -> superset |> Seq.contains inner) + |> Seq.forall (fun inner -> superset |> Seq.contains inner) static member ExactlyFramework (tf: FrameworkIdentifier) = ExactlyP (SinglePlatform tf) @@ -472,9 +473,10 @@ let isTargetMatchingRestrictions (restriction:FrameworkRestriction, target)= restriction.IsMatch target /// Get all targets that should be considered with the specified restrictions -let applyRestrictionsToTargets (restriction:FrameworkRestriction) (targets: TargetProfile list) = - targets - |> List.filter (fun t -> isTargetMatchingRestrictions(restriction,t)) +let applyRestrictionsToTargets (restriction:FrameworkRestriction) (targets: TargetProfile Set) = + Set.intersect targets restriction.RepresentedFrameworks + //targets + //|> List.filter (fun t -> isTargetMatchingRestrictions(restriction,t)) type ContentCopySettings = | Omit @@ -798,10 +800,10 @@ let addFrameworkRestrictionsToDependencies rawDependencies (frameworkGroups:Plat let missing = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.AtLeastPlatform frameworkGroup) let combined = FrameworkRestriction.combineRestrictionsWithAnd curRestr (FrameworkRestriction.NotAtLeastPlatform frameworkGroup) - match packageGroup.Platforms, missing.RepresentedFrameworks with - | [ packageGroupFw ], firstMissing :: _ -> + match packageGroup.Platforms, missing.RepresentedFrameworks.IsEmpty with + | [ packageGroupFw ], false -> // the common set goes to the better matching one - match PlatformMatching.findBestMatch (frameworkGroups, firstMissing) with + match PlatformMatching.findBestMatch (frameworkGroups, missing.RepresentedFrameworks.MinimumElement) with | Some { PlatformMatching.ParsedPlatformPath.Platforms = [ cfw ] } when cfw = packageGroupFw -> curRestr | _ -> combined | _ -> combined) packageGroupRestriction) diff --git a/src/Paket/Paket.fsproj b/src/Paket/Paket.fsproj index 6abd605f9a..49e87d12b2 100644 --- a/src/Paket/Paket.fsproj +++ b/src/Paket/Paket.fsproj @@ -42,7 +42,7 @@ update - D:\temp\TestProject + C:\PROJ\Yaaf\paket-tests\brainsharp\ 14.0 diff --git a/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs b/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs index 1a71cd43d4..89a3a79752 100644 --- a/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs +++ b/tests/Paket.Tests/InstallModel/Penalty/FrameworkConditionsSpecs.fs @@ -11,49 +11,51 @@ let getCondition cond targets = getCondition cond [targets] targets [] let ``should create empty condition for empty profile list``() = - getCondition None [] + getCondition None Set.empty |> shouldEqual "" [] let ``should create simple condition for simple .NET Framework``() = - getCondition None [SinglePlatform(DotNetFramework FrameworkVersion.V3)] + getCondition None (SinglePlatform(DotNetFramework FrameworkVersion.V3) |> Set.singleton) |> shouldEqual "$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v3.0'" [] let ``should create nested condition for two .NET Frameworks``() = - getCondition None [SinglePlatform(DotNetFramework FrameworkVersion.V3); SinglePlatform(DotNetFramework FrameworkVersion.V4_5)] + getCondition None ([SinglePlatform(DotNetFramework FrameworkVersion.V3); SinglePlatform(DotNetFramework FrameworkVersion.V4_5)] |> Set.ofSeq) |> shouldEqual "$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v3.0' Or $(TargetFrameworkVersion) == 'v4.5')" [] let ``should create nested condition for two .NET Frameworks in different order``() = - getCondition None [SinglePlatform(DotNetFramework FrameworkVersion.V4_5); SinglePlatform(DotNetFramework FrameworkVersion.V3)] + getCondition None ([SinglePlatform(DotNetFramework FrameworkVersion.V4_5); SinglePlatform(DotNetFramework FrameworkVersion.V3)] |> Set.ofSeq) |> shouldEqual "$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v3.0' Or $(TargetFrameworkVersion) == 'v4.5')" [] let ``should create nested condition for multiple .NET Frameworks``() = - getCondition None [SinglePlatform(DotNetFramework FrameworkVersion.V3); SinglePlatform(DotNetFramework FrameworkVersion.V4_5); SinglePlatform(DotNetFramework FrameworkVersion.V2)] + getCondition None ([SinglePlatform(DotNetFramework FrameworkVersion.V3); SinglePlatform(DotNetFramework FrameworkVersion.V4_5); SinglePlatform(DotNetFramework FrameworkVersion.V2)] |> Set.ofSeq) |> shouldEqual "$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v2.0' Or $(TargetFrameworkVersion) == 'v3.0' Or $(TargetFrameworkVersion) == 'v4.5')" [] let ``should minimize condition if we have all .NET Frameworks``() = - getCondition None KnownTargetProfiles.DotNetFrameworkProfiles + getCondition None (KnownTargetProfiles.DotNetFrameworkProfiles |> Set.ofSeq) |> shouldEqual "$(TargetFrameworkIdentifier) == '.NETFramework'" [] let ``should minimize condition if we have all WindowsProfiles``() = - getCondition None KnownTargetProfiles.WindowsProfiles + getCondition None (KnownTargetProfiles.WindowsProfiles |> Set.ofSeq) |> shouldEqual "$(TargetFrameworkIdentifier) == '.NETCore'" [] let ``should create nested condition for .NET Framework and Silverlight``() = [SinglePlatform(DotNetFramework FrameworkVersion.V3) SinglePlatform(DotNetFramework FrameworkVersion.V4_5) - SinglePlatform(Silverlight SilverlightVersion.V3)] + SinglePlatform(Silverlight SilverlightVersion.V3)] + |> Set.ofSeq |> getCondition None |> shouldEqual "($(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v3.0' Or $(TargetFrameworkVersion) == 'v4.5')) Or ($(TargetFrameworkIdentifier) == 'Silverlight' And $(TargetFrameworkVersion) == 'v3.0')" [] let ``should create nested condition for full .NET Framework and Silverlight``() = SinglePlatform(Silverlight SilverlightVersion.V3) :: KnownTargetProfiles.DotNetFrameworkProfiles + |> Set.ofSeq |> getCondition None |> shouldEqual "($(TargetFrameworkIdentifier) == '.NETFramework') Or ($(TargetFrameworkIdentifier) == 'Silverlight' And $(TargetFrameworkVersion) == 'v3.0')" \ No newline at end of file diff --git a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs index 69b5a88740..d0496373d9 100644 --- a/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs +++ b/tests/Paket.Tests/InstallModel/ProcessingSpecs.fs @@ -22,7 +22,7 @@ let ``should create empty model with net40, net45 ...``() = let targets = model.CompileLibFolders - |> List.map (fun folder -> folder.Targets) + |> List.map (fun folder -> folder.Targets |> Set.toList) |> List.concat targets |> shouldContain (SinglePlatform (DotNetFramework FrameworkVersion.V4)) diff --git a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs index 937f81ee6c..fd577deff0 100644 --- a/tests/Paket.Tests/InstallModel/Xml/SQLite.fs +++ b/tests/Paket.Tests/InstallModel/Xml/SQLite.fs @@ -87,7 +87,7 @@ let ``can get supported target profile``()= |> PlatformMatching.getSupportedTargetProfiles let folder = profiles |> Seq.item 2 folder.Key |> shouldEqual (forceExtractPlatforms "net45") - folder.Value |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] + folder.Value |> Set.toList |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] [] let ``should extract lib folders for SQLite``() = @@ -118,7 +118,7 @@ let ``should calc lib folders for SQLite``() = let model = calcLegacyReferenceLibFolders libs let folder = model |> List.item 2 - folder.Targets |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] + folder.Targets |> Set.toList |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] [] @@ -136,7 +136,7 @@ let ``should init model for SQLite``() = let libFolder = model.CompileLibFolders |> List.item 2 libFolder.Path.Name |> shouldEqual "net45" - libFolder.Targets |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] + libFolder.Targets |> Set.toList |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] [] @@ -158,7 +158,7 @@ let ``should generate model for SQLite``() = let libFolder = model.CompileLibFolders |> List.item 2 libFolder.Path.Name |> shouldEqual "net45" - libFolder.Targets |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] + libFolder.Targets |> Set.toList |> shouldEqual [SinglePlatform (DotNetFramework FrameworkVersion.V4_5)] [] let ``should generate Xml for SQLite``() = diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index 56b9659960..c5b1848631 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -194,13 +194,13 @@ let ``Simplify || (&& (< net40) (< net35)) (&& (< net40) (>= net35)) (>= net40)) [] let ``Empty set should be empty``() = - FrameworkRestriction.EmptySet.RepresentedFrameworks - |> shouldEqual [] + FrameworkRestriction.EmptySet.RepresentedFrameworks.IsEmpty + |> shouldEqual true [] let ``NoRestriction set should not be empty``() = - FrameworkRestriction.NoRestriction.RepresentedFrameworks - |> shouldNotEqual [] + FrameworkRestriction.NoRestriction.RepresentedFrameworks.IsEmpty + |> shouldEqual false [] let ``combineOr can simplify the NoRestriction set``() = diff --git a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs index 959e45a146..6576bb2455 100644 --- a/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs +++ b/tests/Paket.Tests/Versioning/RestrictionApplicationSpecs.fs @@ -20,6 +20,7 @@ module TestTargetProfiles = FrameworkVersion.V4_5_2 FrameworkVersion.V4_5_3 FrameworkVersion.V4_6] + let DotNetFrameworkProfiles = DotNetFrameworkVersions |> List.map dotnet @@ -58,7 +59,7 @@ module TestTargetProfiles = SinglePlatform(XamariniOS) SinglePlatform(XamarinMac) SinglePlatform(WindowsPhoneApp WindowsPhoneAppVersion.V8_1) - ] + ]|> Set.ofList [] let ``>= net10 contains all but only dotnet versions (#1124)`` () = @@ -66,13 +67,13 @@ let ``>= net10 contains all but only dotnet versions (#1124)`` () = let restrictions = FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V1)) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles - restricted |> shouldEqual TestTargetProfiles.DotNetFrameworkProfiles + restricted |> shouldEqual (TestTargetProfiles.DotNetFrameworkProfiles |> Set.ofList) [] let ``>= net452 contains 4.5.2 and following versions`` () = let restrictions = FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5_2)) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles - let expected = [FrameworkVersion.V4_5_2; FrameworkVersion.V4_5_3; FrameworkVersion.V4_6] |> List.map dotnet + let expected = [FrameworkVersion.V4_5_2; FrameworkVersion.V4_5_3; FrameworkVersion.V4_6] |> List.map dotnet |> Set.ofList restricted |> shouldEqual expected @@ -80,7 +81,7 @@ let ``>= net452 contains 4.5.2 and following versions`` () = let ``>= net40 < net451 contains 4.0 and 4.5`` () = let restrictions = FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4), DotNetFramework(FrameworkVersion.V4_5_1)) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles - let expected = [FrameworkVersion.V4; FrameworkVersion.V4_5] |> List.map dotnet + let expected = [FrameworkVersion.V4; FrameworkVersion.V4_5] |> List.map dotnet|> Set.ofList restricted |> shouldEqual expected @@ -89,4 +90,4 @@ let ``>= sl30 contains all but only silverlight versions`` () = let restrictions = FrameworkRestriction.AtLeast(Silverlight SilverlightVersion.V3) let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles - restricted |> shouldEqual TestTargetProfiles.SilverlightProfiles \ No newline at end of file + restricted |> shouldEqual (TestTargetProfiles.SilverlightProfiles|> Set.ofList) \ No newline at end of file From 20c1ae6648bcf767c9304871290207b64acbf4f9 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 03:21:37 +0200 Subject: [PATCH 21/47] add some very basic profiling capabilites. --- src/Paket.Core/Common/Profile.fs | 51 +++++++++++++++++++ src/Paket.Core/Common/Utils.fs | 6 ++- src/Paket.Core/Dependencies/NuGetV2.fs | 21 ++++++-- src/Paket.Core/Installation/UpdateProcess.fs | 53 ++++++++++++++------ src/Paket.Core/Paket.Core.fsproj | 1 + src/Paket/Program.fs | 19 ++++--- 6 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 src/Paket.Core/Common/Profile.fs diff --git a/src/Paket.Core/Common/Profile.fs b/src/Paket.Core/Common/Profile.fs new file mode 100644 index 0000000000..fbe453b957 --- /dev/null +++ b/src/Paket.Core/Common/Profile.fs @@ -0,0 +1,51 @@ +module Paket.Profile + +open System.Diagnostics + +type Categories = + | ResolverAlgorithm + | NuGetRequest + | NuGetDownload + | FileCopy + | Other + +let watches = + [ ResolverAlgorithm; NuGetRequest; NuGetDownload; FileCopy; Other ] + |> List.map (fun cat -> cat, new Stopwatch()) + |> Map.ofList +let other = watches.[Other] +let mutable current = other +let reset () = + watches + |> Seq.iter (fun (kv) -> kv.Value.Reset()) + other.Start() + current <- other + +let startCategory cat = + watches + |> Seq.iter (fun (kv) -> kv.Value.Stop()) + let prev = current + let cw = watches.[cat] + current <- cw + cw.Start() + + { new System.IDisposable with member x.Dispose () = cw.Stop(); prev.Start() } + +let startCategoryRaw cat = + watches + |> Seq.iter (fun (kv) -> kv.Value.Stop()) + let cw = watches.[cat] + current <- cw + cw.Start() + +let startCategoryF cat f = + watches + |> Seq.iter (fun (kv) -> kv.Value.Stop()) + let prev = current + let cw = watches.[cat] + current <- prev + cw.Start() + let res = f() + cw.Stop() + prev.Start() + res diff --git a/src/Paket.Core/Common/Utils.fs b/src/Paket.Core/Common/Utils.fs index 88ed2738c1..7a5da28a2f 100644 --- a/src/Paket.Core/Common/Utils.fs +++ b/src/Paket.Core/Common/Utils.fs @@ -552,6 +552,7 @@ let downloadFromUrl (auth:Auth option, url : string) (filePath: string) = async { try use client = createWebClient (url,auth) + use _ = Profile.startCategory Profile.Categories.NuGetDownload let task = client.DownloadFileTaskAsync (Uri url, filePath) |> Async.AwaitTask do! task with @@ -566,7 +567,8 @@ let getFromUrl (auth:Auth option, url : string, contentType : string) = use client = createWebClient(url,auth) if notNullOrEmpty contentType then addAcceptHeader client contentType - + + use _ = Profile.startCategory Profile.Categories.NuGetRequest return! client.DownloadStringTaskAsync (Uri url) |> Async.AwaitTask with | exn -> @@ -584,6 +586,7 @@ let getXmlFromUrl (auth:Auth option, url : string) = addHeader client "DataServiceVersion" "1.0;NetFx" addHeader client "MaxDataServiceVersion" "2.0;NetFx" + use _ = Profile.startCategory Profile.Categories.NuGetRequest return! client.DownloadStringTaskAsync (Uri url) |> Async.AwaitTask with | exn -> @@ -604,6 +607,7 @@ let safeGetFromUrl (auth:Auth option, url : string, contentType : string) = #else client.Encoding <- Encoding.UTF8 #endif + use _ = Profile.startCategory Profile.Categories.NuGetRequest let! raw = client.DownloadStringTaskAsync(uri) |> Async.AwaitTask return Some raw with e -> diff --git a/src/Paket.Core/Dependencies/NuGetV2.fs b/src/Paket.Core/Dependencies/NuGetV2.fs index 64420b7e8b..f89e73a1a1 100644 --- a/src/Paket.Core/Dependencies/NuGetV2.fs +++ b/src/Paket.Core/Dependencies/NuGetV2.fs @@ -333,6 +333,7 @@ let findLocalPackage directory (packageName:PackageName) (version:SemVerInfo) = /// Reads package name from a nupkg file let getPackageNameFromLocalFile fileName = + use __ = Profile.startCategory Profile.Categories.FileCopy fixArchive fileName use zipToCreate = new FileStream(fileName, FileMode.Open, FileAccess.Read) use zip = new ZipArchive(zipToCreate, ZipArchiveMode.Read) @@ -349,7 +350,8 @@ let getDetailsFromLocalNuGetPackage isCache alternativeProjectRoot root localNuG let localNugetPath = Utils.normalizeLocalPath localNuGetPath let di = getDirectoryInfoForLocalNuGetFeed localNugetPath alternativeProjectRoot root let nupkg = findLocalPackage di.FullName packageName version - + + use _ = Profile.startCategory Profile.Categories.FileCopy fixArchive nupkg.FullName use zipToCreate = new FileStream(nupkg.FullName, FileMode.Open, FileAccess.Read) use zip = new ZipArchive(zipToCreate,ZipArchiveMode.Read) @@ -423,7 +425,8 @@ let rec private cleanup (dir : DirectoryInfo) = let ExtractPackageToUserFolder(fileName:string, packageName:PackageName, version:SemVerInfo, detailed) = async { let targetFolder = DirectoryInfo(Path.Combine(Constants.UserNuGetPackagesFolder,packageName.ToString(),version.Normalize())) - + + use _ = Profile.startCategory Profile.Categories.FileCopy if isExtracted targetFolder fileName |> not then Directory.CreateDirectory(targetFolder.FullName) |> ignore let fi = FileInfo fileName @@ -448,6 +451,7 @@ let ExtractPackageToUserFolder(fileName:string, packageName:PackageName, version /// Extracts the given package to the ./packages folder let ExtractPackage(fileName:string, targetFolder, packageName:PackageName, version:SemVerInfo, detailed) = async { + use _ = Profile.startCategory Profile.Categories.FileCopy let directory = DirectoryInfo(targetFolder) if isExtracted directory fileName then if verbose then @@ -483,6 +487,7 @@ let CopyLicenseFromCache(root, groupName, cacheFileName, packageName:PackageName if verbose then verbosefn "License %O %O already copied" packageName version else + use _ = Profile.startCategory Profile.Categories.FileCopy File.Copy(cacheFile.FullName, targetFile.FullName, true) with | exn -> traceWarnfn "Could not copy license for %O %O from %s.%s %s" packageName version cacheFileName Environment.NewLine exn.Message @@ -498,6 +503,7 @@ let CopyFromCache(root, groupName, cacheFileName, licenseCacheFile, packageName: if verbose then verbosefn "%O %O already copied" packageName version else + use _ = Profile.startCategory Profile.Categories.FileCopy CleanDir targetFolder File.Copy(cacheFileName, targetFile.FullName) try @@ -506,6 +512,7 @@ let CopyFromCache(root, groupName, cacheFileName, licenseCacheFile, packageName: return extracted with | exn -> + use _ = Profile.startCategory Profile.Categories.FileCopy File.Delete targetFile.FullName Directory.Delete(targetFolder,true) return! raise exn @@ -514,6 +521,7 @@ let CopyFromCache(root, groupName, cacheFileName, licenseCacheFile, packageName: /// Puts the package into the cache let CopyToCache(cache:Cache, fileName, force) = try + use __ = Profile.startCategory Profile.Categories.FileCopy if Cache.isInaccessible cache then if verbose then verbosefn "Cache %s is inaccessible, skipping" cache.Location @@ -563,6 +571,7 @@ let DownloadLicense(root,force,packageName:PackageName,version:SemVerInfo,licens request.UseDefaultCredentials <- true request.Proxy <- Utils.getDefaultProxyFor licenseUrl + use _ = Profile.startCategory Profile.Categories.NuGetRequest use! httpResponse = request.AsyncGetResponse() use httpResponseStream = httpResponse.GetResponseStream() @@ -936,7 +945,8 @@ let DownloadPackage(alternativeProjectRoot, root, (source : PackageSource), cach let path = Utils.normalizeLocalPath path let di = Utils.getDirectoryInfoForLocalNuGetFeed path alternativeProjectRoot root let nupkg = findLocalPackage di.FullName packageName version - + + use _ = Profile.startCategory Profile.Categories.FileCopy File.Copy(nupkg.FullName,targetFileName) | _ -> // discover the link on the fly @@ -961,7 +971,8 @@ let DownloadPackage(alternativeProjectRoot, root, (source : PackageSource), cach if authenticated && verbose then tracefn " from %O" !downloadUrl tracefn " to %s" targetFileName - + + use trackDownload = Profile.startCategory Profile.Categories.NuGetDownload let! license = Async.StartChild(DownloadLicense(root,force,packageName,version,nugetPackage.LicenseUrl,licenseFileName), 5000) let request = HttpWebRequest.Create(downloadUri) :?> HttpWebRequest @@ -1007,7 +1018,7 @@ let DownloadPackage(alternativeProjectRoot, root, (source : PackageSource), cach let! bytes = httpResponseStream.AsyncRead(buffer, 0, bufferSize) bytesRead := bytes do! fileStream.AsyncWrite(buffer, 0, !bytesRead) - + match (httpResponse :?> HttpWebResponse).StatusCode with | HttpStatusCode.OK -> () | statusCode -> failwithf "HTTP status code was %d - %O" (int statusCode) statusCode diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs index d505b4c90a..fc6f4e958e 100644 --- a/src/Paket.Core/Installation/UpdateProcess.fs +++ b/src/Paket.Core/Installation/UpdateProcess.fs @@ -122,26 +122,49 @@ let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRunti v,s :: (List.map PackageSources.PackageSource.FromCache caches)) - let getVersionsF sources resolverStrategy groupName packageName = - seq { - match preferredVersions |> Map.tryFind (groupName, packageName), resolverStrategy with - | Some x, ResolverStrategy.Min -> yield x - | Some x, _ -> - if not (changes |> Set.contains (groupName, packageName)) then - yield x - | _ -> () - yield! getSortedAndCachedVersionsF sources resolverStrategy groupName packageName - } |> Seq.cache + let getVersionsF sources resolverStrategy groupName packageName = + Profile.startCategoryRaw Profile.Categories.Other + try + seq { + match preferredVersions |> Map.tryFind (groupName, packageName), resolverStrategy with + | Some x, ResolverStrategy.Min -> yield x + | Some x, _ -> + if not (changes |> Set.contains (groupName, packageName)) then + yield x + | _ -> () + yield! getSortedAndCachedVersionsF sources resolverStrategy groupName packageName + } |> Seq.cache + finally + Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm let getPackageDetailsF sources groupName packageName version = - let exploredPackage:PackageDetails = getPackageDetailsF sources groupName packageName version - match preferredVersions |> Map.tryFind (groupName,packageName) with - | Some (preferedVersion,_) when version = preferedVersion -> { exploredPackage with Unlisted = false } - | _ -> exploredPackage + Profile.startCategoryRaw Profile.Categories.Other + try + let exploredPackage:PackageDetails = getPackageDetailsF sources groupName packageName version + match preferredVersions |> Map.tryFind (groupName,packageName) with + | Some (preferedVersion,_) when version = preferedVersion -> { exploredPackage with Unlisted = false } + | _ -> exploredPackage + finally + Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm getVersionsF,getPackageDetailsF,groups - let resolution = dependenciesFile.Resolve(force, getSha1, getVersionsF, getPackageDetailsF, getRuntimeGraphFromPackage, groupsToUpdate, updateMode) + let getRuntimeGraphFromPackageF groupName resolvedPackage = + Profile.startCategoryRaw Profile.Categories.Other + try + getRuntimeGraphFromPackage groupName resolvedPackage + finally + Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm + + let getSha1F origin s1 s2 restriction s3 = + Profile.startCategoryRaw Profile.Categories.Other + try + getSha1 origin s1 s2 restriction s3 + finally + Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm + use d = Profile.startCategory Profile.Categories.ResolverAlgorithm + let resolution = dependenciesFile.Resolve(force, getSha1F, getVersionsF, getPackageDetailsF, getRuntimeGraphFromPackageF, groupsToUpdate, updateMode) + d.Dispose() let groups = dependenciesFile.Groups diff --git a/src/Paket.Core/Paket.Core.fsproj b/src/Paket.Core/Paket.Core.fsproj index 873a9a1e29..829b5cb7e1 100644 --- a/src/Paket.Core/Paket.Core.fsproj +++ b/src/Paket.Core/Paket.Core.fsproj @@ -100,6 +100,7 @@ + diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index f017480d5f..02c633efd4 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -13,8 +13,7 @@ open PackageSources open System.Xml open Paket.Domain -let private stopWatch = new Stopwatch() -stopWatch.Start() +do Paket.Profile.reset() type PaketExiter() = interface IExiter with @@ -35,10 +34,18 @@ let processWithValidation silent validateF commandF (result : ParseResults<'T>) Environment.ExitCode <- 1 #endif else - commandF result - let elapsedTime = Utils.TimeSpanToReadableString stopWatch.Elapsed - if not silent then - tracefn "%s - ready." elapsedTime + try + commandF result + finally + if not silent then + let results = + Profile.watches + |> Seq.map (fun (kv) -> kv.Key, kv.Value.Elapsed) + |> Seq.toList + let combined = results |> List.map snd |> List.fold (+) (TimeSpan()) + let elapsedTime = Utils.TimeSpanToReadableString combined + for (cat, elapsed) in results do tracefn "%s - %A." (Utils.TimeSpanToReadableString elapsed) cat + tracefn "%s - ready." elapsedTime let processCommand silent commandF result = processWithValidation silent (fun _ -> true) commandF result From 4dd7398cbb12785743b4eda2eabd4d35e1c3fadc Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 16:28:20 +0200 Subject: [PATCH 22/47] performance improvements by using sets and caches --- Paket.sln | 3 + .../Dependencies/PackageResolver.fs | 9 +- .../Versioning/FrameworkHandling.fs | 144 ++++++++++------- src/Paket.Core/Versioning/PlatformMatching.fs | 26 ++- src/Paket.Core/Versioning/Requirements.fs | 148 +++++++++++++++++- src/Paket/Paket.fsproj | 2 +- .../Versioning/FrameworkRestrictionTests.fs | 26 +-- 7 files changed, 266 insertions(+), 92 deletions(-) diff --git a/Paket.sln b/Paket.sln index 0d5d453b8e..9320683307 100644 --- a/Paket.sln +++ b/Paket.sln @@ -146,4 +146,7 @@ Global {7C622582-E281-4EAB-AADA-B5893BB89B45} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} {7234B9B4-8CF5-4E68-AA29-050C087B9246} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index c2caa21ad4..e8ddbeceec 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -60,8 +60,13 @@ module DependencySetFilter = // While the dependency specifies the framework restrictions of the dependency ([ >= netstandard13 ]) // we need to take the dependency, when the combination still contains packages. // NOTE: This is not forwards compatible... - let combined = FrameworkRestriction.And [ restriction; dependencyRestrictions ] - not combined.RepresentedFrameworks.IsEmpty + //let combined = FrameworkRestriction.And [ restriction; dependencyRestrictions ] + //not combined.RepresentedFrameworks.IsEmpty + + // "And" is not cleap therefore we use this, because we don't want to re-use the "simplified" formula + Set.intersect restriction.RepresentedFrameworks dependencyRestrictions.RepresentedFrameworks + |> Set.isEmpty + |> not let filterByRestrictions (restrictions:FrameworkRestrictions) (dependencies:DependencySet) : DependencySet = match getExplicitRestriction restrictions with diff --git a/src/Paket.Core/Versioning/FrameworkHandling.fs b/src/Paket.Core/Versioning/FrameworkHandling.fs index 447b94fd9b..8d7a767be3 100644 --- a/src/Paket.Core/Versioning/FrameworkHandling.fs +++ b/src/Paket.Core/Versioning/FrameworkHandling.fs @@ -929,8 +929,8 @@ module KnownTargetProfiles = | Some s -> s | None -> failwithf "tried to find portable profile '%s' but it is unknown to paket" name -module PortableProfileSupportCalculation = - let isSupported (portable:PortableProfileType) (other:PortableProfileType) = +module SupportCalculation = + let isSupportedNotEqual (portable:PortableProfileType) (other:PortableProfileType) = let name, tfs = portable.ProfileName, portable.Frameworks let otherName, otherfws = other.ProfileName, other.Frameworks @@ -949,7 +949,7 @@ module PortableProfileSupportCalculation = let name, tfs = portable.ProfileName, portable.Frameworks KnownTargetProfiles.AllPortableProfiles |> List.filter (fun p -> p.ProfileName <> name) - |> List.filter (fun other -> isSupported portable other) + |> List.filter (fun other -> isSupportedNotEqual portable other) |> List.map PortableProfile type SupportMap = System.Collections.Concurrent.ConcurrentDictionary let ofSeq s = s|> dict |> System.Collections.Concurrent.ConcurrentDictionary @@ -1057,61 +1057,7 @@ module PortableProfileSupportCalculation = traceWarnfn "The profile '%O' is not a known profile. Please tell the package author." fallback fallback) -type TargetProfile with - member p.Frameworks = - match p with - | SinglePlatform fw -> [fw] - | PortableProfile p -> p.Frameworks - static member FindPortable (fws: _ list) = PortableProfileSupportCalculation.findPortable fws - - /// true when x is supported by y, for example netstandard15 is supported by netcore10 - member x.IsSupportedBy y = - match x with - | PortableProfile (PortableProfileType.UnsupportedProfile xs' as x') -> - // custom profiles are not in our lists -> custom logic - match y with - | PortableProfile y' -> - PortableProfileSupportCalculation.isSupported y' x' - | SinglePlatform y' -> - y'.RawSupportedPlatformsTransitive |> Seq.exists (fun y'' -> - xs' |> Seq.contains y'') - | _ -> - x = y || - (y.SupportedPlatforms |> Seq.exists (fun s -> x.IsSupportedBy s)) - - /// true when x is at least (>=) y ie when y is supported by x, for example netcore10 >= netstandard15 as netstandard15 is supported by netcore10. - /// Note that this relation is not complete, for example for WindowsPhoneSilverlightv7.0 and Windowsv4.5 both <= and >= are false from this definition as - /// no platform supports the other. - member x.IsAtLeast (y:TargetProfile) = - y.IsSupportedBy x - - /// Get all platforms y for which x >= y holds - member x.SupportedPlatformsTransitive = - let findNewPlats (known:TargetProfile list) (lastStep:TargetProfile list) = - lastStep - |> List.collect (fun k -> k.SupportedPlatforms) - |> List.filter (fun k -> known |> Seq.contains k |> not) - - Seq.initInfinite (fun _ -> 1) - |> Seq.scan (fun state _ -> - match state with - | Some (known, lastStep) -> - match findNewPlats known lastStep with - | [] -> None - | items -> Some (known @ items, items) - | None -> None) (Some ([x], [x])) - |> Seq.takeWhile (fun i -> i.IsSome) - |> Seq.choose id - |> Seq.last - |> fst - - /// x < y, see y >= x && x <> y - member x.IsSmallerThan y = - x.IsSupportedBy y && x <> y - - /// Note that this returns true only when a >= x and x < b holds. - member x.IsBetween(a,b) = x.IsAtLeast a && x.IsSmallerThan b - member x.SupportedPlatforms = + let getSupportedPlatforms x = match x with | SinglePlatform tf -> let rawSupported = @@ -1175,5 +1121,85 @@ type TargetProfile with |> List.map PortableProfile rawSupported @ profilesSupported | PortableProfile p -> - PortableProfileSupportCalculation.getSupportedPreCalculated p + getSupportedPreCalculated p |> List.map PortableProfile + |> Set.ofList + + let getSupportedPlatformsTransitive = + let findNewPlats (known:TargetProfile Set) (lastStep:TargetProfile Set) = + lastStep + |> Seq.map (fun k -> Set.difference (getSupportedPlatforms k) known) + |> Set.unionMany + + memoize (fun x -> + Seq.initInfinite (fun _ -> 1) + |> Seq.scan (fun state _ -> + match state with + | Some (known, lastStep) -> + match findNewPlats known lastStep with + | s when s.IsEmpty -> None + | items -> Some (Set.union known items, items) + | None -> None) (Some (Set.singleton x, Set.singleton x)) + |> Seq.takeWhile (fun i -> i.IsSome) + |> Seq.choose id + |> Seq.last + |> fst + ) + + /// true when x is supported by y, for example netstandard15 is supported by netcore10 + let isSupportedBy x y = + match x with + | PortableProfile (PortableProfileType.UnsupportedProfile xs' as x') -> + // custom profiles are not in our lists -> custom logic + match y with + | PortableProfile y' -> + x' = y' || + isSupportedNotEqual y' x' + | SinglePlatform y' -> + y'.RawSupportedPlatformsTransitive |> Seq.exists (fun y'' -> + xs' |> Seq.contains y'') + | _ -> + x = y || + (getSupportedPlatformsTransitive y |> Set.contains x) + + let getPlatformsSupporting = + // http://nugettoolsdev.azurewebsites.net + let calculate (x:TargetProfile) = + KnownTargetProfiles.AllProfiles + |> Set.filter (fun plat -> isSupportedBy x plat) + memoize calculate + +type TargetProfile with + member p.Frameworks = + match p with + | SinglePlatform fw -> [fw] + | PortableProfile p -> p.Frameworks + static member FindPortable (fws: _ list) = SupportCalculation.findPortable fws + + member inline x.PlatformsSupporting = SupportCalculation.getPlatformsSupporting x + + /// true when x is supported by y, for example netstandard15 is supported by netcore10 + member inline x.IsSupportedBy y = + SupportCalculation.isSupportedBy x y + /// true when x is at least (>=) y ie when y is supported by x, for example netcore10 >= netstandard15 as netstandard15 is supported by netcore10. + /// Note that this relation is not complete, for example for WindowsPhoneSilverlightv7.0 and Windowsv4.5 both <= and >= are false from this definition as + /// no platform supports the other. + member inline x.IsAtLeast (y:TargetProfile) = + y.IsSupportedBy x + + /// Get all platforms y for which x >= y holds + member inline x.SupportedPlatformsTransitive = + SupportCalculation.getSupportedPlatformsTransitive x + + member inline x.SupportedPlatforms : TargetProfile Set = + SupportCalculation.getSupportedPlatforms x + + /// x < y, see y >= x && x <> y + member inline x.IsSmallerThan y = + x.IsSupportedBy y && x <> y + + member inline x.IsSmallerThanOrEqual y = + x.IsSupportedBy y + + /// Note that this returns true only when a >= x and x < b holds. + member x.IsBetween(a,b) = x.IsAtLeast a && x.IsSmallerThan b \ No newline at end of file diff --git a/src/Paket.Core/Versioning/PlatformMatching.fs b/src/Paket.Core/Versioning/PlatformMatching.fs index 81e733f3f3..e48d04e626 100644 --- a/src/Paket.Core/Versioning/PlatformMatching.fs +++ b/src/Paket.Core/Versioning/PlatformMatching.fs @@ -68,9 +68,9 @@ let rec getPlatformPenalty = | _ -> let penalty = targetPlatform.SupportedPlatforms - |> List.map (fun target -> getPlatformPenalty (target, packagePlatform)) - |> List.append [MaxPenalty] - |> List.min + |> Seq.map (fun target -> getPlatformPenalty (target, packagePlatform)) + |> Seq.append [MaxPenalty] + |> Seq.min |> fun p -> p + 1 match targetPlatform, packagePlatform with @@ -134,27 +134,21 @@ let collectPlatforms = let rec loop (acc:TargetProfile list) (framework:TargetProfile) (profls:TargetProfile Set) = profls |> Seq.fold (fun acc f -> - if f.SupportedPlatforms |> List.exists ((=) framework) then - f::acc - else acc) [] + if f.SupportedPlatforms |> Set.contains (framework) then + Set.add f acc + else acc) Set.empty memoize (fun (framework,profls) -> loop ([]:TargetProfile list) framework profls) -let getPlatformsSupporting = - // http://nugettoolsdev.azurewebsites.net - let calculate (x:TargetProfile) = - KnownTargetProfiles.AllProfiles - |> Set.filter (fun plat -> x.IsSupportedBy plat) - memoize calculate let platformsSupport = let rec platformsSupport platform platforms = - if List.isEmpty platforms then MaxPenalty - elif platforms |> List.exists ((=) platform) then 1 + if Set.isEmpty platforms then MaxPenalty + elif platforms |> Set.contains (platform) then 1 else - platforms |> Array.ofList + platforms |> Set.toArray |> Array.Parallel.map (fun (p : TargetProfile) -> collectPlatforms (p,KnownTargetProfiles.AllProfiles) - ) |> List.concat + ) |> Set.unionMany |> platformsSupport platform |> (+) 1 memoize (fun (platform,platforms) -> platformsSupport platform platforms) diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 228d6ae55d..cc6f97a65c 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -57,8 +57,8 @@ type FrameworkRestrictionP = member x.RepresentedFrameworks = match x with | FrameworkRestrictionP.ExactlyP r -> [ r ] |> Set.ofList - | FrameworkRestrictionP.AtLeastP r -> - PlatformMatching.getPlatformsSupporting r + | FrameworkRestrictionP.AtLeastP r -> r.PlatformsSupporting + //PlatformMatching.get r //KnownTargetProfiles.AllProfiles //|> Set.filter (fun plat -> r.IsSupportedBy plat) | FrameworkRestrictionP.NotP(fr) -> @@ -94,9 +94,147 @@ type FrameworkRestrictionP = /// Returns true if the restriction x is a subset of the restriction y (a restriction basically represents a list, see RepresentedFrameworks) /// For example =net46 is a subset of >=netstandard13 member x.IsSubsetOf (y:FrameworkRestrictionP) = - let superset = y.RepresentedFrameworks - x.RepresentedFrameworks - |> Seq.forall (fun inner -> superset |> Seq.contains inner) + + // better ~ 5 Mins + let inline fallBack doAssert = +#if DEBUG + if doAssert then + assert (false)// make sure the fallback is never needed +#endif + let superset = y.RepresentedFrameworks + let subset = x.RepresentedFrameworks + Set.isSubset subset superset + + // Because the formula simplifier needs it this is a quite HOT PATH + match x with + | FrameworkRestrictionP.ExactlyP x' -> + match y with + | FrameworkRestrictionP.ExactlyP y' -> x' = y' + | FrameworkRestrictionP.AtLeastP y' -> + // =x' is a subset of >=y' when 'y is smaller than 'x + y'.IsSmallerThanOrEqual x' + //x'.SupportedPlatformsTransitiveSeq + //|> Seq.exists (Set.contains y') + // these are or 'common' forms, others are not allowed + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP y') -> + // =x is only a subset of = y + y'.IsSmallerThanOrEqual x' + |> not + //// We go down from x' and if we find y' it is a subset -> not + //x'.SupportedPlatformsTransitiveSeq + //|> Seq.exists (Set.contains y') + //|> not + //fallBack() + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.ExactlyP y') -> + x' <> y' + // This one should never actually hit. + | FrameworkRestrictionP.NotP(y') -> fallBack true + | FrameworkRestrictionP.OrP (ys) -> + ys + |> Seq.exists (fun y' -> x.IsSubsetOf y') + | FrameworkRestrictionP.AndP (ys) -> + ys + |> Seq.forall (fun y' -> x.IsSubsetOf y') + | FrameworkRestrictionP.AtLeastP x' -> + match y with + | FrameworkRestrictionP.ExactlyP y' -> + // >=x can only be a subset of =y when it is already the max + x' = y' && x'.SupportedPlatforms.IsEmpty + | FrameworkRestrictionP.AtLeastP y' -> + // >=x is only a subset of >=y when y is 'smaller" than x + y'.IsSmallerThanOrEqual x' + // these are or 'common' forms, others are not allowed + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP y') -> + // >= x' is only a subset of < y' when their intersection is empty + Set.intersect (x'.PlatformsSupporting) (y'.PlatformsSupporting) + |> Set.isEmpty + //fallBack() + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.ExactlyP y') -> + // >= x' is only a subset of <> y' when y' is not part of >=x' + x'.PlatformsSupporting + |> Set.contains y' + |> not + //fallBack() + // This one should never actually hit. + | FrameworkRestrictionP.NotP(y') -> fallBack true + | FrameworkRestrictionP.OrP (ys) -> + ys + |> Seq.exists (fun y' -> x.IsSubsetOf y') + | FrameworkRestrictionP.AndP (ys) -> + ys + |> Seq.forall (fun y' -> x.IsSubsetOf y') + + // these are or 'common' forms, others are not allowed + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP x' as notX) -> + match y with + | FrameworkRestrictionP.ExactlyP y' -> + // < x is a subset of ='y when? + //x'.SupportedPlatforms.IsEmpty && x' = y' +#if DEBUG + assert (not (fallBack false))// TODO: can this happen? +#endif + false + | FrameworkRestrictionP.AtLeastP y' -> + // < x is a subset of >= y when there are no smaller things than y and +#if DEBUG + assert (not (fallBack false))// TODO: can this happen? +#endif + false + // these are or 'common' forms, others are not allowed + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP y' as notY) -> + // < 'x is a subset of < y when >=y is a subset of >=x + notY.IsSubsetOf notX + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.ExactlyP y' as notY) -> + // < 'x is a subset of <> y when =y is a subset of >=x + notY.IsSubsetOf notX + // This one should never actually hit. + | FrameworkRestrictionP.NotP(y') -> fallBack true + | FrameworkRestrictionP.OrP (ys) -> + ys + |> Seq.exists (fun y' -> x.IsSubsetOf y') + | FrameworkRestrictionP.AndP (ys) -> + ys + |> Seq.forall (fun y' -> x.IsSubsetOf y') + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.ExactlyP x' as notX) -> + match y with + | FrameworkRestrictionP.ExactlyP y' -> + // <> x is a subset of =y ? +#if DEBUG + assert (not (fallBack false))// TODO: can this happen? +#endif + false + | FrameworkRestrictionP.AtLeastP y' -> + // <> x is a subset of >= y +#if DEBUG + assert (not (fallBack false))// TODO: can this happen? +#endif + false + //fallBack() + // these are or 'common' forms, others are not allowed + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP y' as notY) -> + notY.IsSubsetOf notX + | FrameworkRestrictionP.NotP(FrameworkRestrictionP.ExactlyP y' as notY) -> + notY.IsSubsetOf notX + // This one should never actually hit. + | FrameworkRestrictionP.NotP(y') -> fallBack true + | FrameworkRestrictionP.OrP (ys) -> + ys + |> Seq.exists (fun y' -> x.IsSubsetOf y') + | FrameworkRestrictionP.AndP (ys) -> + ys + |> Seq.forall (fun y' -> x.IsSubsetOf y') + // This one should never actually hit. + | FrameworkRestrictionP.NotP(x') -> fallBack true + | FrameworkRestrictionP.OrP (xs) -> + xs + |> Seq.forall (fun x' -> x'.IsSubsetOf y) + | FrameworkRestrictionP.AndP (xs) -> + xs + |> Seq.exists (fun x' -> x'.IsSubsetOf y) + + + // Bad ~ 10 mins + //|> Seq.forall (fun inner -> superset |> Seq.contains inner) static member ExactlyFramework (tf: FrameworkIdentifier) = ExactlyP (SinglePlatform tf) diff --git a/src/Paket/Paket.fsproj b/src/Paket/Paket.fsproj index 49e87d12b2..913a1c7bf8 100644 --- a/src/Paket/Paket.fsproj +++ b/src/Paket/Paket.fsproj @@ -42,7 +42,7 @@ update - C:\PROJ\Yaaf\paket-tests\brainsharp\ + C:\PROJ\Yaaf\paket-tests\test2\ 14.0 diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index c5b1848631..c3fe5a237a 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -5,6 +5,14 @@ open FsUnit open NUnit.Framework open Paket.Requirements +[] +let ``IsSubset works for unknown Portables`` () = + let p = PlatformMatching.forceExtractPlatforms "portable-net45+win8+wp8+wp81+wpa81" + let t = p.ToTargetProfile.Value + let r = FrameworkRestriction.AtLeastPlatform t + r.IsSubsetOf r + |> shouldEqual true + [] let ``Simplify || (>= net45) (>= portable-net45+win8+wp8+wp81+wpa81)`` () = // because that is a custom portable profile! @@ -63,29 +71,29 @@ let ``__unknowntfm__ should not match everything`` () = [] let ``Profile 158 should not support itself``() = - PortableProfileSupportCalculation.isSupported Profile158 Profile158 + SupportCalculation.isSupportedNotEqual Profile158 Profile158 |> shouldEqual false [] let ``Profile 158 should not support Profile 78, as there is no silverlight on 78``() = - PortableProfileSupportCalculation.isSupported Profile158 Profile78 + SupportCalculation.isSupportedNotEqual Profile158 Profile78 |> shouldEqual false - PortableProfileSupportCalculation.isSupported Profile78 Profile158 + SupportCalculation.isSupportedNotEqual Profile78 Profile158 |> shouldEqual true [] let ``Profile 344 should support Profile 336, as it has the same frameworks but is lower``() = - PortableProfileSupportCalculation.isSupported Profile336 Profile344 + SupportCalculation.isSupportedNotEqual Profile336 Profile344 |> shouldEqual false - PortableProfileSupportCalculation.isSupported Profile344 Profile336 + SupportCalculation.isSupportedNotEqual Profile344 Profile336 |> shouldEqual true [] let ``Generate Support Table``() = // TODO: Should we include this? - let mutable supportMap = PortableProfileSupportCalculation.createInitialSupportMap() - supportMap <- PortableProfileSupportCalculation.optimizeSupportMap supportMap + let mutable supportMap = SupportCalculation.createInitialSupportMap() + supportMap <- SupportCalculation.optimizeSupportMap supportMap supportMap - |> PortableProfileSupportCalculation.toSeq + |> SupportCalculation.toSeq |> Seq.iter (fun (p, supported) -> System.Diagnostics.Debug.WriteLine(sprintf "| %s ->" p.ProfileName) System.Diagnostics.Debug.WriteLine(" [ ") @@ -129,7 +137,7 @@ let ``Portables are detected correctly``() = [] let ``PlatformMatching works with portable ``() = // portable-net40-sl4 - let l = PlatformMatching.getPlatformsSupporting (KnownTargetProfiles.FindPortableProfile "Profile18") + let l = (KnownTargetProfiles.FindPortableProfile "Profile18").PlatformsSupporting // portable-net45-sl5 let needPortable = KnownTargetProfiles.FindPortableProfile "Profile24" From c37374cf833587a69034073ca85b059c1996990d Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 16:42:32 +0200 Subject: [PATCH 23/47] add profile to netcore --- src/Paket.Core.preview3/Paket.Core.fsproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Paket.Core.preview3/Paket.Core.fsproj b/src/Paket.Core.preview3/Paket.Core.fsproj index 6fd54b35d9..88b35f50e1 100644 --- a/src/Paket.Core.preview3/Paket.Core.fsproj +++ b/src/Paket.Core.preview3/Paket.Core.fsproj @@ -19,6 +19,7 @@ + From 70a268c1f5bba7b50fd376b226695d55a8f8d121 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 17:02:25 +0200 Subject: [PATCH 24/47] no more verbose for you --- build.fsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.fsx b/build.fsx index 378ab331af..f19d1e6e1c 100644 --- a/build.fsx +++ b/build.fsx @@ -288,7 +288,7 @@ let mergePaketTool () = let result = ExecProcess (fun info -> info.FileName <- currentDirectory "packages" "build" "ILRepack" "tools" "ILRepack.exe" - info.Arguments <- sprintf "/verbose /lib:%s /ver:%s /out:%s %s" buildDir release.AssemblyVersion paketFile toPack + info.Arguments <- sprintf "/lib:%s /ver:%s /out:%s %s" buildDir release.AssemblyVersion paketFile toPack ) (TimeSpan.FromMinutes 5.) if result <> 0 then failwithf "Error during ILRepack execution." From c9ed5c5d9a58d783fd3172a247261314e6e90139 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 18:16:59 +0200 Subject: [PATCH 25/47] another round of performance by improving the equals implementation --- src/Paket.Core/Versioning/Requirements.fs | 98 ++++++++++++++++------- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index cc6f97a65c..f0de411391 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -264,22 +264,42 @@ type FrameworkRestrictionAndList = member internal x.RawFormular = FrameworkRestrictionP.AndP (x.Literals |> List.map (fun literal -> literal.RawFormular)) +[] type FrameworkRestriction = - { OrFormulas : FrameworkRestrictionAndList list } + private { OrFormulas : FrameworkRestrictionAndList list + mutable PrivateRawFormula : FrameworkRestrictionP option ref + mutable PrivateRepresentedFrameworks : TargetProfile Set option ref } + static member FromOrList l = { OrFormulas = l; PrivateRepresentedFrameworks = ref None; PrivateRawFormula = ref None } + static member internal WithOrListInternal orList l = { l with OrFormulas = orList } member internal x.RawFormular = - FrameworkRestrictionP.OrP (x.OrFormulas |> List.map (fun andList -> andList.RawFormular)) + match !x.PrivateRawFormula with + | Some f -> f + | None -> + let raw = FrameworkRestrictionP.OrP (x.OrFormulas |> List.map (fun andList -> andList.RawFormular)) + x.PrivateRawFormula := Some raw + raw override x.ToString() = x.RawFormular.ToString() member x.IsSubsetOf (y:FrameworkRestriction) = x.RawFormular.IsSubsetOf y.RawFormular member x.RepresentedFrameworks = - x.RawFormular.RepresentedFrameworks + match !x.PrivateRepresentedFrameworks with + | Some s -> s + | None -> + let set = x.RawFormular.RepresentedFrameworks + x.PrivateRepresentedFrameworks := Some set + set member x.IsMatch tp = x.RawFormular.IsMatch tp + override x.Equals(y) = (match y with :? FrameworkRestriction as r -> r.RepresentedFrameworks = x.RepresentedFrameworks | _ -> false) + override x.GetHashCode() = x.RepresentedFrameworks.GetHashCode() + interface System.IComparable with + member x.CompareTo(y) = (match y with :? FrameworkRestriction as r -> compare x.RepresentedFrameworks r.RepresentedFrameworks | _ -> failwith "wrong type") + module FrameworkRestriction = - let EmptySet = { OrFormulas = [] } // false - let NoRestriction = { OrFormulas = [ { Literals = [] } ] } // true - let FromLiteral lit = { OrFormulas = [ { Literals = [ lit ] } ] } + let EmptySet = FrameworkRestriction.FromOrList [] // false + let NoRestriction = FrameworkRestriction.FromOrList [ { Literals = [] } ] // true + let FromLiteral lit = FrameworkRestriction.FromOrList [ { Literals = [ lit ] } ] let AtLeastPlatform pf = FromLiteral (FrameworkRestrictionLiteral.FromLiteral (AtLeastL pf)) let ExactlyPlatform pf = FromLiteral (FrameworkRestrictionLiteral.FromLiteral (ExactlyL pf)) let Exactly id = ExactlyPlatform (SinglePlatform id) @@ -313,7 +333,7 @@ module FrameworkRestriction = else workDone, andFormula :: reworkedOrFormulas ) (false, []) - if workDone then removeNegatedLiteralsWhichOccurSinglePositive { OrFormulas = reworked } + if workDone then removeNegatedLiteralsWhichOccurSinglePositive (FrameworkRestriction.WithOrListInternal reworked fr) else fr /// (>= net40-full) && (< net46) && (>= net20) can be simplified to (< net46) && (>= net40-full) because (>= net40-full) is a subset of (>= net20) // NOTE: This optimization is kind of dangerous as future frameworks might make it invalid @@ -321,7 +341,7 @@ module FrameworkRestriction = let removeSubsetLiteralsInAndClause (fr:FrameworkRestriction) = let simplifyAndClause (andClause:FrameworkRestrictionAndList) = let literals = andClause.Literals - { Literals = + let newLiterals = andClause.Literals |> List.filter (fun literal -> // we filter out literals, for which another literal exists which is a subset @@ -329,9 +349,19 @@ module FrameworkRestriction = |> Seq.filter (fun l -> l <> literal) |> Seq.exists (fun otherLiteral -> otherLiteral.RawFormular.IsSubsetOf literal.RawFormular) - |> not) } + |> not) + if newLiterals.Length <> literals.Length + then true, {Literals = newLiterals} + else false, andClause //andClause - { OrFormulas = fr.OrFormulas |> List.map simplifyAndClause } + let wasChanged, newOrList = + fr.OrFormulas + |> List.fold (fun (oldWasChanged, newList) andList -> + let wasChanged, newAndList = simplifyAndClause andList + oldWasChanged || wasChanged, newAndList :: newList) (false, []) + if wasChanged then + FrameworkRestriction.WithOrListInternal newOrList fr + else fr /// (>= net40-full) || (< net46) || (>= net20) can be simplified to (< net46) || (>= net20) because (>= net40-full) is a subset of (>= net20) // NOTE: This optimization is kind of dangerous as future frameworks might make it invalid @@ -340,7 +370,7 @@ module FrameworkRestriction = let simpleOrLiterals = fr.OrFormulas |> List.choose (function { Literals = [h] } -> Some h | _ -> None) - { OrFormulas = + let newOrList = fr.OrFormulas |> List.filter (function | { Literals = [h] } -> @@ -349,7 +379,10 @@ module FrameworkRestriction = |> Seq.exists (fun otherLiteral -> h.RawFormular.IsSubsetOf otherLiteral.RawFormular) |> not - | _ -> true) } + | _ -> true) + if newOrList.Length < fr.OrFormulas.Length then + FrameworkRestriction.WithOrListInternal newOrList fr + else fr /// ((>= net20) && (>= net40)) || (>= net20) can be simplified to (>= net20) because any AND clause with (>= net20) can be removed. let removeUneccessaryOrClauses (fr:FrameworkRestriction) = @@ -361,15 +394,18 @@ module FrameworkRestriction = item.Literals |> Seq.forall (fun lit -> andList.Literals |> Seq.contains lit) - { OrFormulas = + let newOrList = fr.OrFormulas |> List.filter (fun orClause -> orClauses |> Seq.exists (isContained orClause) |> not) - } + + if newOrList.Length < fr.OrFormulas.Length then + FrameworkRestriction.WithOrListInternal newOrList fr + else fr /// clauses with ((>= net20) && (< net20) && ...) can be removed because they contains a literal and its negation. let removeUneccessaryAndClauses (fr:FrameworkRestriction) = - { OrFormulas = + let newOrList = fr.OrFormulas |> List.filter (fun andList -> let normalizeLiterals = @@ -382,7 +418,12 @@ module FrameworkRestriction = normalizeLiterals |> Seq.exists (fun l -> normalizeLiterals |> Seq.contains { l with IsNegated = not l.IsNegated}) - not foundLiteralAndNegation) } + not foundLiteralAndNegation) + + if newOrList.Length < fr.OrFormulas.Length then + FrameworkRestriction.WithOrListInternal newOrList fr + else fr + /// When we optmized a clause away completely we can replace the hole formula with "NoRestriction" /// This happens for example with ( =net45) and the removeNegatedLiteralsWhichOccurSinglePositive @@ -394,11 +435,11 @@ module FrameworkRestriction = if containsEmptyAnd then NoRestriction else fr let sortClauses (fr:FrameworkRestriction) = - { OrFormulas = - fr.OrFormulas - |> List.map (fun andFormula -> { Literals = andFormula.Literals |> List.distinct |> List.sort }) - |> List.distinct - |> List.sort } + fr.OrFormulas + |> List.map (fun andFormula -> { Literals = andFormula.Literals |> List.distinct |> List.sort }) + |> List.distinct + |> List.sort + |> fun newOrList -> FrameworkRestriction.WithOrListInternal newOrList fr let optimize fr = fr |> removeNegatedLiteralsWhichOccurSinglePositive @@ -421,18 +462,20 @@ module FrameworkRestriction = match left.OrFormulas with | [] -> right | [h] -> - { OrFormulas = - right.OrFormulas - |> List.map (fun andFormula -> { Literals = andFormula.Literals @ h.Literals } ) } + right.OrFormulas + |> List.map (fun andFormula -> { Literals = andFormula.Literals @ h.Literals } ) + |> FrameworkRestriction.FromOrList | h :: t -> - { OrFormulas = (And2 {OrFormulas = [h]} right).OrFormulas @ ((And2 {OrFormulas = t} right).OrFormulas) } + (And2 (FrameworkRestriction.FromOrList [h]) right).OrFormulas @ (And2 (FrameworkRestriction.FromOrList t) right).OrFormulas + |> FrameworkRestriction.FromOrList let And (rst:FrameworkRestriction list) = List.fold And2 NoRestriction rst |> simplify let private Or2 (left : FrameworkRestriction) (right : FrameworkRestriction) = - { OrFormulas = left.OrFormulas @ right.OrFormulas } + left.OrFormulas @ right.OrFormulas + |> FrameworkRestriction.FromOrList let Or (rst:FrameworkRestriction list) = List.fold Or2 EmptySet rst @@ -585,7 +628,8 @@ let parseRestrictions failImmediatly (text:string) = let negated = match operand with | { OrFormulas = [ {Literals = [ lit] } ] } -> - { OrFormulas = [ {Literals = [ { lit with IsNegated = not lit.IsNegated } ] } ] } + [ {Literals = [ { lit with IsNegated = not lit.IsNegated } ] } ] + |> FrameworkRestriction.FromOrList | _ -> failwithf "a general NOT is not implemted jet (and shouldn't be emitted for now)" negated, next else From 1390a079bd3ddec86c6528c22917e1e634ee0bb9 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 19:19:34 +0200 Subject: [PATCH 26/47] more performance by using sets and removing some conversations --- .../Dependencies/DependenciesFileParser.fs | 2 +- .../Dependencies/PackageResolver.fs | 63 +++++++++---------- .../PackageManagement/NugetConvert.fs | 2 +- .../PaketConfigFiles/DependenciesFile.fs | 6 +- src/Paket.Core/Versioning/Requirements.fs | 4 +- .../VersionRequirementSpecs.fs | 2 +- .../Resolver/ConflictGraphSpecs.fs | 2 +- .../Resolver/ConflictSourcesSpecs.fs | 2 +- tests/Paket.Tests/Resolver/PropertyTests.fs | 2 +- tests/Paket.Tests/TestHelpers.fs | 2 +- 10 files changed, 43 insertions(+), 44 deletions(-) diff --git a/src/Paket.Core/Dependencies/DependenciesFileParser.fs b/src/Paket.Core/Dependencies/DependenciesFileParser.fs index 90a9fc72bd..15fad4c285 100644 --- a/src/Paket.Core/Dependencies/DependenciesFileParser.fs +++ b/src/Paket.Core/Dependencies/DependenciesFileParser.fs @@ -398,7 +398,7 @@ module DependenciesFileParser = | _ -> None else None Parent = parent - Graph = [] + Graph = Set.empty Sources = sources Settings = InstallSettings.Parse(optionsText).AdjustWithSpecialCases packageName VersionRequirement = versionRequirement diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 8f215a61cf..286c09f89a 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -127,16 +127,16 @@ module Resolution = let getConflicts (res:Resolution) = match res with - | Resolution.Ok _ -> [] + | Resolution.Ok _ -> Set.empty | Resolution.Conflict (currentStep,_,lastPackageRequirement,_) -> currentStep.ClosedRequirements |> Set.union currentStep.OpenRequirements |> Set.add lastPackageRequirement - |> Seq.filter (fun x -> x.Name = lastPackageRequirement.Name) - |> Seq.sortBy (fun x -> x.Parent) - |> Seq.toList + |> Set.filter (fun x -> x.Name = lastPackageRequirement.Name) + //|> Seq.sortBy (fun x -> x.Parent) + //|> Seq.toList - let buildConflictReport (errorReport:StringBuilder) (conflicts:PackageRequirement list) = + let buildConflictReport (errorReport:StringBuilder) (conflicts:PackageRequirement Set) = let formatVR (vr:VersionRequirement) = vr.ToString () |> fun s -> if String.IsNullOrWhiteSpace s then ">= 0" else s @@ -149,9 +149,9 @@ module Resolution = | _ -> "" match conflicts with - | [] -> errorReport + | s when s.IsEmpty -> errorReport | conflicts -> - let hasPrereleases = List.exists (fun r -> r.VersionRequirement.PreReleases <> PreReleaseStatus.No) conflicts + let hasPrereleases = Seq.exists (fun r -> r.VersionRequirement.PreReleases <> PreReleaseStatus.No) conflicts errorReport.AddLine (sprintf " Conflict detected:") @@ -163,13 +163,10 @@ module Resolution = sprintf " - Dependencies file requested package %O: %s%s" req.Name vr pr | Package (parentName,version,_) -> sprintf " - %O %O requested package %O: %s%s" parentName version req.Name vr pr - - let rec loop conflicts (errorReport:StringBuilder) = - match conflicts with - | [] -> errorReport - | hd::tl -> loop tl (errorReport.AppendLine (getConflictMessage hd)) - loop conflicts errorReport - + + conflicts + |> Seq.fold (fun (errorReport:StringBuilder) conflict -> + errorReport.AppendLine (getConflictMessage conflict)) errorReport let getErrorText showResolvedPackages = function | Resolution.Ok _ -> "" @@ -183,12 +180,13 @@ module Resolution = else StringBuilder() match getConflicts res with - | [] -> + | c when c.IsEmpty -> errorText.AppendLinef " Could not resolve package %O. Unknown resolution error." (Seq.head currentStep.OpenRequirements) - | [c] -> - let errorText = buildConflictReport errorText [c] + | cfs when cfs.Count = 1 -> + let c = cfs.MinimumElement + let errorText = buildConflictReport errorText cfs match getVersionF c.Name |> Seq.toList with | [] -> errorText.AppendLinef " - No versions available." | avalaibleVersions -> @@ -264,7 +262,7 @@ let calcOpenRequirements (exploredPackage:ResolvedPackage,globalFrameworkRestric Name = n VersionRequirement = v Parent = Package(dependency.Name, versionToExplore, exploredPackage.Source) - Graph = [dependency] @ dependency.Graph + Graph = Set.add dependency dependency.Graph Settings = { dependency.Settings with FrameworkRestrictions = newRestrictions } }) |> Set.filter (fun d -> resolverStep.ClosedRequirements @@ -499,19 +497,19 @@ let private getCompatibleVersions let private getConflicts (currentStep:ResolverStep) (currentRequirement:PackageRequirement) (knownConflicts:HashSet * ((SemVerInfo * PackageSource list) list * bool) option>) = let allRequirements = - Set.toSeq currentStep.OpenRequirements - |> Seq.filter (fun r -> r.Graph |> List.contains currentRequirement |> not) - |> Seq.append currentStep.ClosedRequirements - |> HashSet + currentStep.OpenRequirements + |> Set.filter (fun r -> r.Graph |> Set.contains currentRequirement |> not) + |> Set.union currentStep.ClosedRequirements knownConflicts |> Seq.map (fun (conflicts,selectedVersion) -> + let isSubset = conflicts.IsSubsetOf allRequirements match selectedVersion with - | None when conflicts.IsSubsetOf allRequirements -> conflicts + | None when isSubset -> conflicts | Some(selectedVersion,_) -> let n = (Seq.head conflicts).Name match currentStep.FilteredVersions |> Map.tryFind n with - | Some(v,_) when v = selectedVersion && conflicts.IsSubsetOf allRequirements -> conflicts + | Some(v,_) when v = selectedVersion && isSubset -> conflicts | _ -> HashSet() | _ -> HashSet()) |> Seq.collect id @@ -578,7 +576,8 @@ let private boostConflicts let conflicts = conflictStatus.GetConflicts() let lastConflictReported = match conflicts with - | c::_ -> + | _ when not conflicts.IsEmpty -> + let c = conflicts.MinimumElement let selectedVersion = Map.tryFind c.Name filteredVersions let key = conflicts |> HashSet,selectedVersion stackpack.KnownConflicts.Add key |> ignore @@ -665,14 +664,14 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate let findMatchingStep priorConflictSteps = let currentNames = conflicts - |> Seq.collect (fun c -> - let graphNameList = - c.Graph |> List.map (fun (pr:PackageRequirement) -> pr.Name) - c.Name :: graphNameList) - |> Seq.toArray + |> Seq.map (fun c -> + c.Graph + |> Set.map (fun (pr:PackageRequirement) -> pr.Name) + |> Set.add c.Name) + |> Set.unionMany priorConflictSteps |> List.tryExtractOne (fun (_,_,lastRequirement:PackageRequirement,_,_) -> - currentNames |> Array.contains lastRequirement.Name) + currentNames |> Set.contains lastRequirement.Name) match findMatchingStep priorConflictSteps with | None, [] -> currentConflict @@ -708,7 +707,7 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate && currentStep.CurrentResolution.Count > 1 && not (conflicts |> Set.exists (fun r -> r = lastRequirement - || r.Graph |> List.contains lastRequirement)) -> + || r.Graph |> Set.contains lastRequirement)) -> step (Inner((continueConflict,lastStep,lastRequirement),priorConflictSteps)) stackpack lastCompatibleVersions { flags with ForceBreak = true } | _ -> diff --git a/src/Paket.Core/PackageManagement/NugetConvert.fs b/src/Paket.Core/PackageManagement/NugetConvert.fs index e5c3c151e6..538017b139 100644 --- a/src/Paket.Core/PackageManagement/NugetConvert.fs +++ b/src/Paket.Core/PackageManagement/NugetConvert.fs @@ -222,7 +222,7 @@ let createPackageRequirement sources (packageName, versionRange, restrictions) d Settings = { InstallSettings.Default with FrameworkRestrictions = restrictions } Parent = PackageRequirementSource.DependenciesFile dependenciesFileName Sources = sources - Graph = [] } + Graph = Set.empty } let createDependenciesFileR (rootDirectory : DirectoryInfo) nugetEnv mode = diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index a61e8ae28b..384503bd54 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -232,7 +232,7 @@ type DependenciesFile(fileName,groups:Map, textRepr ResolverStrategyForDirectDependencies = Some ResolverStrategy.Max ResolverStrategyForTransitives = Some ResolverStrategy.Max Parent = PackageRequirementSource.DependenciesFile fileName - Graph = [] + Graph = Set.empty Sources = group.Sources Settings = group.Options.Settings }) |> Seq.toList @@ -278,7 +278,7 @@ type DependenciesFile(fileName,groups:Map, textRepr ResolverStrategyForDirectDependencies = group.Options.ResolverStrategyForDirectDependencies ResolverStrategyForTransitives = group.Options.ResolverStrategyForTransitives Parent = PackageRequirementSource.DependenciesFile "runtimeresolution.dependencies" - Graph = [] + Graph = Set.empty Sources = group.Sources Settings = group.Options.Settings }) |> Seq.toList @@ -304,7 +304,7 @@ type DependenciesFile(fileName,groups:Map, textRepr | Some d -> d.ResolverStrategyForTransitives | None -> group.Options.ResolverStrategyForTransitives Parent = PackageRequirementSource.DependenciesFile "runtimeresolution.dependencies" - Graph = [] + Graph = Set.empty Sources = group.Sources Settings = match oldDepsInfo with diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index f0de411391..6396b85a83 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -886,7 +886,7 @@ type PackageRequirement = ResolverStrategyForDirectDependencies : ResolverStrategy option ResolverStrategyForTransitives : ResolverStrategy option Parent: PackageRequirementSource - Graph: PackageRequirement list + Graph: PackageRequirement Set Sources: PackageSource list Settings: InstallSettings } @@ -912,7 +912,7 @@ type PackageRequirement = member this.IncludingPrereleases() = this.IncludingPrereleases(PreReleaseStatus.All) - member this.Depth = this.Graph.Length + member this.Depth = this.Graph.Count static member Compare(x,y,startWithPackage:PackageFilter option,boostX,boostY) = if obj.ReferenceEquals(x, y) then 0 else diff --git a/tests/Paket.Tests/DependenciesFile/VersionRequirementSpecs.fs b/tests/Paket.Tests/DependenciesFile/VersionRequirementSpecs.fs index a88076a786..254c4ea227 100644 --- a/tests/Paket.Tests/DependenciesFile/VersionRequirementSpecs.fs +++ b/tests/Paket.Tests/DependenciesFile/VersionRequirementSpecs.fs @@ -14,7 +14,7 @@ let require packageName strategyForTransitives text : PackageRequirement = ResolverStrategyForDirectDependencies = None ResolverStrategyForTransitives = Some strategyForTransitives Parent = PackageRequirementSource.DependenciesFile "" - Graph = [] + Graph = Set.empty Sources = [] Settings = InstallSettings.Default } diff --git a/tests/Paket.Tests/Resolver/ConflictGraphSpecs.fs b/tests/Paket.Tests/Resolver/ConflictGraphSpecs.fs index 4be4207423..55e39c6d35 100644 --- a/tests/Paket.Tests/Resolver/ConflictGraphSpecs.fs +++ b/tests/Paket.Tests/Resolver/ConflictGraphSpecs.fs @@ -28,7 +28,7 @@ let graph = let defaultPackage = { Name = PackageName "" Parent = PackageRequirementSource.DependenciesFile "" - Graph = [] + Graph = Set.empty Sources = [] VersionRequirement = VersionRequirement(VersionRange.Exactly "1.0", PreReleaseStatus.No) Settings = InstallSettings.Default diff --git a/tests/Paket.Tests/Resolver/ConflictSourcesSpecs.fs b/tests/Paket.Tests/Resolver/ConflictSourcesSpecs.fs index ee229ed8da..25bf4baa81 100644 --- a/tests/Paket.Tests/Resolver/ConflictSourcesSpecs.fs +++ b/tests/Paket.Tests/Resolver/ConflictSourcesSpecs.fs @@ -23,7 +23,7 @@ let ``should resolve source files with correct sha``() = { Name = name ResolverStrategyForDirectDependencies = Some ResolverStrategy.Max ResolverStrategyForTransitives = Some ResolverStrategy.Max - Graph = [] + Graph = Set.empty Sources = [] Parent = Requirements.PackageRequirementSource.DependenciesFile "" Settings = InstallSettings.Default diff --git a/tests/Paket.Tests/Resolver/PropertyTests.fs b/tests/Paket.Tests/Resolver/PropertyTests.fs index f984625142..a270cb2703 100644 --- a/tests/Paket.Tests/Resolver/PropertyTests.fs +++ b/tests/Paket.Tests/Resolver/PropertyTests.fs @@ -135,7 +135,7 @@ let ``if it resolves then, it should satisfy all deps. if not we have a real con failwithf "brute force found %A" resolution let conflicts = conflict.GetConflicts() - conflicts |> List.isEmpty |> not + conflicts |> Set.isEmpty |> not with | exn when exn.Message.Contains "brute force" |> not -> match bruteForce (g,deps) with diff --git a/tests/Paket.Tests/TestHelpers.fs b/tests/Paket.Tests/TestHelpers.fs index b92663a8fa..d18b43df4a 100644 --- a/tests/Paket.Tests/TestHelpers.fs +++ b/tests/Paket.Tests/TestHelpers.fs @@ -96,7 +96,7 @@ let safeResolve graph (dependencies : (string * VersionRange) list) = { Name = PackageName n VersionRequirement = VersionRequirement(v, PreReleaseStatus.No) Parent = PackageRequirementSource.DependenciesFile "" - Graph = [] + Graph = Set.empty Sources = sources Settings = InstallSettings.Default ResolverStrategyForDirectDependencies = Some ResolverStrategy.Max From 613b7505b78fafc325aa0db192ebda2884c67a04 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 19:48:15 +0200 Subject: [PATCH 27/47] REVIEW: select another conflict --- src/Paket.Core/Dependencies/PackageResolver.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 286c09f89a..efbddbc6b6 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -577,7 +577,7 @@ let private boostConflicts let lastConflictReported = match conflicts with | _ when not conflicts.IsEmpty -> - let c = conflicts.MinimumElement + let c = conflicts |> Seq.minBy (fun c -> c.Parent) let selectedVersion = Map.tryFind c.Name filteredVersions let key = conflicts |> HashSet,selectedVersion stackpack.KnownConflicts.Add key |> ignore From 1d6088d573de74562f7d09c339965cd1184eb876 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 19:49:19 +0200 Subject: [PATCH 28/47] REVIEW: compare restrictions at least (because it is slowest) --- src/Paket.Core/Versioning/Requirements.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 6396b85a83..fcf1f33a58 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -933,11 +933,11 @@ type PackageRequirement = if c <> 0 then c else let c = -compare x.VersionRequirement y.VersionRequirement if c <> 0 then c else - let c = compare x.Settings.FrameworkRestrictions y.Settings.FrameworkRestrictions - if c <> 0 then c else let c = compare x.Parent y.Parent if c <> 0 then c else let c = compare x.Name y.Name + if c <> 0 then c else + let c = compare x.Settings.FrameworkRestrictions y.Settings.FrameworkRestrictions if c <> 0 then c else 0 interface System.IComparable with From 2fff14bc1408322825037119d1661eb6e9df7bd2 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 21:51:49 +0200 Subject: [PATCH 29/47] Change Profile-Code to work in parallel and thread changing environments. Push Async down into the resolver to make the resolver aware that these are costly. --- src/Paket.Core/Common/Async.fs | 2 +- src/Paket.Core/Common/Profile.fs | 52 +-- src/Paket.Core/Common/Utils.fs | 8 +- src/Paket.Core/Dependencies/NuGetV2.fs | 339 +++++++++--------- .../Dependencies/PackageResolver.fs | 39 +- src/Paket.Core/Installation/UpdateProcess.fs | 75 ++-- .../PackageAnalysis/FindOutdated.fs | 9 +- src/Paket.Core/PublicAPI.fs | 1 + src/Paket/Program.fs | 21 +- tests/Paket.Tests/TestHelpers.fs | 4 +- 10 files changed, 277 insertions(+), 273 deletions(-) diff --git a/src/Paket.Core/Common/Async.fs b/src/Paket.Core/Common/Async.fs index 0a313d76fa..220dbcd6b0 100644 --- a/src/Paket.Core/Common/Async.fs +++ b/src/Paket.Core/Common/Async.fs @@ -47,4 +47,4 @@ module AsyncExtensions = for task in tasks do ignore <| System.Threading.Tasks.Task.Factory.StartNew(fun () -> Async.StartWithContinuations(task, scont, econt, ccont, innerCts.Token)) - } \ No newline at end of file + } diff --git a/src/Paket.Core/Common/Profile.fs b/src/Paket.Core/Common/Profile.fs index fbe453b957..b85e0ff484 100644 --- a/src/Paket.Core/Common/Profile.fs +++ b/src/Paket.Core/Common/Profile.fs @@ -1,51 +1,31 @@ module Paket.Profile open System.Diagnostics +open System -type Categories = +type BlockReason = + | PackageDetails + | GetVersion + +type Category = | ResolverAlgorithm + | ResolverAlgorithmBlocked of BlockReason | NuGetRequest | NuGetDownload - | FileCopy + | FileIO | Other - -let watches = - [ ResolverAlgorithm; NuGetRequest; NuGetDownload; FileCopy; Other ] - |> List.map (fun cat -> cat, new Stopwatch()) - |> Map.ofList -let other = watches.[Other] -let mutable current = other -let reset () = - watches - |> Seq.iter (fun (kv) -> kv.Value.Reset()) - other.Start() - current <- other - +type Event = { Category: Category; Duration : TimeSpan } +let events = + System.Collections.Concurrent.ConcurrentBag() + let startCategory cat = - watches - |> Seq.iter (fun (kv) -> kv.Value.Stop()) - let prev = current - let cw = watches.[cat] - current <- cw - cw.Start() + let cw = Stopwatch.StartNew() - { new System.IDisposable with member x.Dispose () = cw.Stop(); prev.Start() } + { new System.IDisposable with member x.Dispose () = cw.Stop(); events.Add({ Category = cat; Duration = cw.Elapsed }) } -let startCategoryRaw cat = - watches - |> Seq.iter (fun (kv) -> kv.Value.Stop()) - let cw = watches.[cat] - current <- cw - cw.Start() - let startCategoryF cat f = - watches - |> Seq.iter (fun (kv) -> kv.Value.Stop()) - let prev = current - let cw = watches.[cat] - current <- prev - cw.Start() + let cw = Stopwatch.StartNew() let res = f() cw.Stop() - prev.Start() + events.Add({ Category = cat; Duration = cw.Elapsed }) res diff --git a/src/Paket.Core/Common/Utils.fs b/src/Paket.Core/Common/Utils.fs index 7a5da28a2f..08b1f35f0c 100644 --- a/src/Paket.Core/Common/Utils.fs +++ b/src/Paket.Core/Common/Utils.fs @@ -552,7 +552,7 @@ let downloadFromUrl (auth:Auth option, url : string) (filePath: string) = async { try use client = createWebClient (url,auth) - use _ = Profile.startCategory Profile.Categories.NuGetDownload + use _ = Profile.startCategory Profile.Category.NuGetDownload let task = client.DownloadFileTaskAsync (Uri url, filePath) |> Async.AwaitTask do! task with @@ -568,7 +568,7 @@ let getFromUrl (auth:Auth option, url : string, contentType : string) = if notNullOrEmpty contentType then addAcceptHeader client contentType - use _ = Profile.startCategory Profile.Categories.NuGetRequest + use _ = Profile.startCategory Profile.Category.NuGetRequest return! client.DownloadStringTaskAsync (Uri url) |> Async.AwaitTask with | exn -> @@ -586,7 +586,7 @@ let getXmlFromUrl (auth:Auth option, url : string) = addHeader client "DataServiceVersion" "1.0;NetFx" addHeader client "MaxDataServiceVersion" "2.0;NetFx" - use _ = Profile.startCategory Profile.Categories.NuGetRequest + use _ = Profile.startCategory Profile.Category.NuGetRequest return! client.DownloadStringTaskAsync (Uri url) |> Async.AwaitTask with | exn -> @@ -607,7 +607,7 @@ let safeGetFromUrl (auth:Auth option, url : string, contentType : string) = #else client.Encoding <- Encoding.UTF8 #endif - use _ = Profile.startCategory Profile.Categories.NuGetRequest + use _ = Profile.startCategory Profile.Category.NuGetRequest let! raw = client.DownloadStringTaskAsync(uri) |> Async.AwaitTask return Some raw with e -> diff --git a/src/Paket.Core/Dependencies/NuGetV2.fs b/src/Paket.Core/Dependencies/NuGetV2.fs index f89e73a1a1..d416666154 100644 --- a/src/Paket.Core/Dependencies/NuGetV2.fs +++ b/src/Paket.Core/Dependencies/NuGetV2.fs @@ -333,7 +333,7 @@ let findLocalPackage directory (packageName:PackageName) (version:SemVerInfo) = /// Reads package name from a nupkg file let getPackageNameFromLocalFile fileName = - use __ = Profile.startCategory Profile.Categories.FileCopy + use __ = Profile.startCategory Profile.Category.FileIO fixArchive fileName use zipToCreate = new FileStream(fileName, FileMode.Open, FileAccess.Read) use zip = new ZipArchive(zipToCreate, ZipArchiveMode.Read) @@ -351,7 +351,7 @@ let getDetailsFromLocalNuGetPackage isCache alternativeProjectRoot root localNuG let di = getDirectoryInfoForLocalNuGetFeed localNugetPath alternativeProjectRoot root let nupkg = findLocalPackage di.FullName packageName version - use _ = Profile.startCategory Profile.Categories.FileCopy + use _ = Profile.startCategory Profile.Category.FileIO fixArchive nupkg.FullName use zipToCreate = new FileStream(nupkg.FullName, FileMode.Open, FileAccess.Read) use zip = new ZipArchive(zipToCreate,ZipArchiveMode.Read) @@ -426,7 +426,7 @@ let ExtractPackageToUserFolder(fileName:string, packageName:PackageName, version async { let targetFolder = DirectoryInfo(Path.Combine(Constants.UserNuGetPackagesFolder,packageName.ToString(),version.Normalize())) - use _ = Profile.startCategory Profile.Categories.FileCopy + use _ = Profile.startCategory Profile.Category.FileIO if isExtracted targetFolder fileName |> not then Directory.CreateDirectory(targetFolder.FullName) |> ignore let fi = FileInfo fileName @@ -451,7 +451,7 @@ let ExtractPackageToUserFolder(fileName:string, packageName:PackageName, version /// Extracts the given package to the ./packages folder let ExtractPackage(fileName:string, targetFolder, packageName:PackageName, version:SemVerInfo, detailed) = async { - use _ = Profile.startCategory Profile.Categories.FileCopy + use _ = Profile.startCategory Profile.Category.FileIO let directory = DirectoryInfo(targetFolder) if isExtracted directory fileName then if verbose then @@ -487,7 +487,7 @@ let CopyLicenseFromCache(root, groupName, cacheFileName, packageName:PackageName if verbose then verbosefn "License %O %O already copied" packageName version else - use _ = Profile.startCategory Profile.Categories.FileCopy + use _ = Profile.startCategory Profile.Category.FileIO File.Copy(cacheFile.FullName, targetFile.FullName, true) with | exn -> traceWarnfn "Could not copy license for %O %O from %s.%s %s" packageName version cacheFileName Environment.NewLine exn.Message @@ -503,7 +503,7 @@ let CopyFromCache(root, groupName, cacheFileName, licenseCacheFile, packageName: if verbose then verbosefn "%O %O already copied" packageName version else - use _ = Profile.startCategory Profile.Categories.FileCopy + use _ = Profile.startCategory Profile.Category.FileIO CleanDir targetFolder File.Copy(cacheFileName, targetFile.FullName) try @@ -512,7 +512,7 @@ let CopyFromCache(root, groupName, cacheFileName, licenseCacheFile, packageName: return extracted with | exn -> - use _ = Profile.startCategory Profile.Categories.FileCopy + use _ = Profile.startCategory Profile.Category.FileIO File.Delete targetFile.FullName Directory.Delete(targetFolder,true) return! raise exn @@ -521,7 +521,7 @@ let CopyFromCache(root, groupName, cacheFileName, licenseCacheFile, packageName: /// Puts the package into the cache let CopyToCache(cache:Cache, fileName, force) = try - use __ = Profile.startCategory Profile.Categories.FileCopy + use __ = Profile.startCategory Profile.Category.FileIO if Cache.isInaccessible cache then if verbose then verbosefn "Cache %s is inaccessible, skipping" cache.Location @@ -571,7 +571,7 @@ let DownloadLicense(root,force,packageName:PackageName,version:SemVerInfo,licens request.UseDefaultCredentials <- true request.Proxy <- Utils.getDefaultProxyFor licenseUrl - use _ = Profile.startCategory Profile.Categories.NuGetRequest + use _ = Profile.startCategory Profile.Category.NuGetRequest use! httpResponse = request.AsyncGetResponse() use httpResponseStream = httpResponse.GetResponseStream() @@ -637,62 +637,60 @@ let GetTargetsFiles(targetFolder) = /// Finds all analyzer files in a nuget package. let GetAnalyzerFiles(targetFolder) = getFilesMatching targetFolder "*.dll" "analyzers" "analyzer dlls" -let rec private getPackageDetails alternativeProjectRoot root force (sources:PackageSource list) packageName (version:SemVerInfo) : PackageResolver.PackageDetails = - - let tryV2 source (nugetSource:NugetSource) force = async { - let! result = - getDetailsFromNuGet - force - (nugetSource.Authentication |> Option.map toBasicAuth) - nugetSource.Url - packageName - version - return Some(source,result) } - - let tryV3 source nugetSource force = async { - if nugetSource.Url.Contains("myget.org") || nugetSource.Url.Contains("nuget.org") || nugetSource.Url.Contains("visualstudio.com") || nugetSource.Url.Contains("/nuget/v3/") then - match NuGetV3.calculateNuGet2Path nugetSource.Url with - | Some url -> - let! result = - getDetailsFromNuGet - force - (nugetSource.Authentication |> Option.map toBasicAuth) - url - packageName - version - return Some(source,result) - | _ -> +let rec private getPackageDetails alternativeProjectRoot root force (sources:PackageSource list) packageName (version:SemVerInfo) : Async = + async { + let tryV2 source (nugetSource:NugetSource) force = async { + let! result = + getDetailsFromNuGet + force + (nugetSource.Authentication |> Option.map toBasicAuth) + nugetSource.Url + packageName + version + return Some(source,result) } + + let tryV3 source nugetSource force = async { + if nugetSource.Url.Contains("myget.org") || nugetSource.Url.Contains("nuget.org") || nugetSource.Url.Contains("visualstudio.com") || nugetSource.Url.Contains("/nuget/v3/") then + match NuGetV3.calculateNuGet2Path nugetSource.Url with + | Some url -> + let! result = + getDetailsFromNuGet + force + (nugetSource.Authentication |> Option.map toBasicAuth) + url + packageName + version + return Some(source,result) + | _ -> + let! result = NuGetV3.GetPackageDetails force nugetSource packageName version + return Some(source,result) + else let! result = NuGetV3.GetPackageDetails force nugetSource packageName version - return Some(source,result) - else - let! result = NuGetV3.GetPackageDetails force nugetSource packageName version - return Some(source,result) } - - let getPackageDetails force = - sources - |> List.sortBy (fun source -> - match source with // put local caches to the end - | LocalNuGet(_,Some _) -> true - | _ -> false) - |> List.map (fun source -> async { - try - match source with - | NuGetV2 nugetSource -> - return! tryV2 source nugetSource force - | NuGetV3 nugetSource when urlSimilarToTfsOrVsts nugetSource.Url -> - match NuGetV3.calculateNuGet2Path nugetSource.Url with - | Some url -> - let nugetSource : NugetSource = - { Url = url - Authentication = nugetSource.Authentication } + return Some(source,result) } + + let getPackageDetails force = + // helper to work through the list sequentially + let rec trySelectFirst workLeft = + async { + match workLeft with + | work :: rest -> + let! r = work + match r with + | Some result -> return Some result + | None -> return! trySelectFirst rest + | [] -> return None + } + sources + |> List.sortBy (fun source -> + match source with // put local caches to the end + | LocalNuGet(_,Some _) -> true + | _ -> false) + |> List.map (fun source -> async { + try + match source with + | NuGetV2 nugetSource -> return! tryV2 source nugetSource force - | _ -> - return! tryV3 source nugetSource force - | NuGetV3 nugetSource -> - try - return! tryV3 source nugetSource force - with - | exn -> + | NuGetV3 nugetSource when urlSimilarToTfsOrVsts nugetSource.Url -> match NuGetV3.calculateNuGet2Path nugetSource.Url with | Some url -> let nugetSource : NugetSource = @@ -700,60 +698,79 @@ let rec private getPackageDetails alternativeProjectRoot root force (sources:Pac Authentication = nugetSource.Authentication } return! tryV2 source nugetSource force | _ -> - raise exn return! tryV3 source nugetSource force - - | LocalNuGet(path,Some _) -> - let! result = getDetailsFromLocalNuGetPackage true alternativeProjectRoot root path packageName version - return Some(source,result) - | LocalNuGet(path,None) -> - let! result = getDetailsFromLocalNuGetPackage false alternativeProjectRoot root path packageName version - return Some(source,result) - with e -> - if verbose then - verbosefn "Source '%O' exception: %O" source e - return None }) - |> List.tryPick Async.RunSynchronously - - let source,nugetObject = - match getPackageDetails force with - | None -> - match getPackageDetails true with - | None -> - match sources |> List.map (fun (s:PackageSource) -> s.ToString()) with - | [source] -> - failwithf "Couldn't get package details for package %O %O on %O." packageName version source - | [] -> - failwithf "Couldn't get package details for package %O %O, because no sources were specified." packageName version - | sources -> - failwithf "Couldn't get package details for package %O %O on any of %A." packageName version sources - | Some packageDetails -> packageDetails - | Some packageDetails -> packageDetails - - let encodeURL (url:string) = - if String.IsNullOrWhiteSpace url then url else - let segments = url.Split [|'?'|] - let baseUrl = segments.[0] - Array.set segments 0 (baseUrl.Replace("+", "%2B")) - System.String.Join("?", segments) - - let newName = PackageName nugetObject.PackageName - if packageName <> newName then - failwithf "Package details for %O are not matching requested package %O." newName packageName - - { Name = PackageName nugetObject.PackageName - Source = source - DownloadLink = encodeURL nugetObject.DownloadUrl - Unlisted = nugetObject.Unlisted - LicenseUrl = nugetObject.LicenseUrl - DirectDependencies = nugetObject.Dependencies |> Set.ofList } - -let rec GetPackageDetails alternativeProjectRoot root force (sources:PackageSource list) groupName packageName (version:SemVerInfo) : PackageResolver.PackageDetails = - try - getPackageDetails alternativeProjectRoot root force sources packageName version - with - | _ -> getPackageDetails alternativeProjectRoot root true sources packageName version - + | NuGetV3 nugetSource -> + try + return! tryV3 source nugetSource force + with + | exn -> + match NuGetV3.calculateNuGet2Path nugetSource.Url with + | Some url -> + let nugetSource : NugetSource = + { Url = url + Authentication = nugetSource.Authentication } + return! tryV2 source nugetSource force + | _ -> + raise exn + return! tryV3 source nugetSource force + + | LocalNuGet(path,Some _) -> + let! result = getDetailsFromLocalNuGetPackage true alternativeProjectRoot root path packageName version + return Some(source,result) + | LocalNuGet(path,None) -> + let! result = getDetailsFromLocalNuGetPackage false alternativeProjectRoot root path packageName version + return Some(source,result) + with e -> + if verbose then + verbosefn "Source '%O' exception: %O" source e + return None }) + |> trySelectFirst + + let! maybePackageDetails = getPackageDetails force + let! source,nugetObject = + async { + match maybePackageDetails with + | None -> + let! m = getPackageDetails true + match m with + | None -> + match sources |> List.map (fun (s:PackageSource) -> s.ToString()) with + | [source] -> + return failwithf "Couldn't get package details for package %O %O on %O." packageName version source + | [] -> + return failwithf "Couldn't get package details for package %O %O, because no sources were specified." packageName version + | sources -> + return failwithf "Couldn't get package details for package %O %O on any of %A." packageName version sources + | Some packageDetails -> return packageDetails + | Some packageDetails -> return packageDetails + } + + let encodeURL (url:string) = + if String.IsNullOrWhiteSpace url then url else + let segments = url.Split [|'?'|] + let baseUrl = segments.[0] + Array.set segments 0 (baseUrl.Replace("+", "%2B")) + System.String.Join("?", segments) + + let newName = PackageName nugetObject.PackageName + if packageName <> newName then + failwithf "Package details for %O are not matching requested package %O." newName packageName + + return + { Name = PackageName nugetObject.PackageName + Source = source + DownloadLink = encodeURL nugetObject.DownloadUrl + Unlisted = nugetObject.Unlisted + LicenseUrl = nugetObject.LicenseUrl + DirectDependencies = nugetObject.Dependencies |> Set.ofList } } + +let rec GetPackageDetails alternativeProjectRoot root force (sources:PackageSource list) groupName packageName (version:SemVerInfo) : Async = + async { + try + return! getPackageDetails alternativeProjectRoot root force sources packageName version + with + | _ -> return! getPackageDetails alternativeProjectRoot root true sources packageName version + } let protocolCache = System.Collections.Concurrent.ConcurrentDictionary<_,_>() let getVersionsCached key f (source, auth, nugetURL, package) = @@ -794,8 +811,8 @@ let FindPackages(auth, nugetURL, packageNamePrefix, maxResults) = } /// Allows to retrieve all version no. for a package from the given sources. -let GetVersions force alternativeProjectRoot root (sources, packageName:PackageName) = - let trial force = +let GetVersions force alternativeProjectRoot root (sources, packageName:PackageName) = async { + let trial force = async { let getVersionsFailedCacheFileName (source:PackageSource) = let h = source.Url |> normalizeUrl |> hash |> abs let packageUrl = sprintf "Versions.%O.s%d.failed" packageName h @@ -853,53 +870,55 @@ let GetVersions force alternativeProjectRoot root (sources, packageName:PackageN |> Seq.toArray |> Array.map Async.Choice |> Async.Parallel - |> Async.RunSynchronously - versionResponse - |> Array.zip sources - |> Array.choose (fun ((_,s),v) -> - match v with - | Some v when Array.isEmpty v |> not -> - try - let errorFile = getVersionsFailedCacheFileName s - if errorFile.Exists then - File.Delete(errorFile.FullName) - with _ -> () - Some (s,v) - | _ -> - try - let errorFile = getVersionsFailedCacheFileName s - if errorFile.Exists |> not then - File.WriteAllText(errorFile.FullName,DateTime.Now.ToString()) - with _ -> () - None) - |> Array.map (fun (s,versions) -> versions |> Array.map (fun v -> v,s)) - |> Array.concat - - let versions = - match trial force with - | versions when Array.isEmpty versions |> not -> versions + let! result = versionResponse + return + result + |> Array.zip sources + |> Array.choose (fun ((_,s),v) -> + match v with + | Some v when Array.isEmpty v |> not -> + try + let errorFile = getVersionsFailedCacheFileName s + if errorFile.Exists then + File.Delete(errorFile.FullName) + with _ -> () + Some (s,v) + | _ -> + try + let errorFile = getVersionsFailedCacheFileName s + if errorFile.Exists |> not then + File.WriteAllText(errorFile.FullName,DateTime.Now.ToString()) + with _ -> () + None) + |> Array.map (fun (s,versions) -> versions |> Array.map (fun v -> v,s)) + |> Array.concat } + let! versions = async { + let! trial1 = trial force + match trial1 with + | versions when Array.isEmpty versions |> not -> return versions | _ -> - match trial true with - | versions when Array.isEmpty versions |> not -> versions + let! trial2 = trial true + match trial2 with + | versions when Array.isEmpty versions |> not -> return versions | _ -> match sources |> Seq.map (fun s -> s.ToString()) |> List.ofSeq with | [source] -> - failwithf "Could not find versions for package %O on %O." packageName source + return failwithf "Could not find versions for package %O on %O." packageName source | [] -> - failwithf "Could not find versions for package %O, because no sources were specified." packageName + return failwithf "Could not find versions for package %O, because no sources were specified." packageName | sources -> - failwithf "Could not find versions for package %O on any of %A." packageName sources - - versions - |> Seq.toList - |> List.map (fun (v,s) -> SemVer.Parse v,v,s) - |> List.groupBy (fun (v,_,_) -> v.Normalize()) - |> List.map (fun (_,s) -> - let sorted = s |> List.sortByDescending (fun (_,_,s) -> s.IsLocalFeed) + return failwithf "Could not find versions for package %O on any of %A." packageName sources } + return + versions + |> Seq.toList + |> List.map (fun (v,s) -> SemVer.Parse v,v,s) + |> List.groupBy (fun (v,_,_) -> v.Normalize()) + |> List.map (fun (_,s) -> + let sorted = s |> List.sortByDescending (fun (_,_,s) -> s.IsLocalFeed) - let _,v,_ = List.head sorted - SemVer.Parse v,sorted |> List.map (fun (_,_,x) -> x)) + let _,v,_ = List.head sorted + SemVer.Parse v,sorted |> List.map (fun (_,_,x) -> x)) } /// Downloads the given package to the NuGet Cache folder @@ -946,7 +965,7 @@ let DownloadPackage(alternativeProjectRoot, root, (source : PackageSource), cach let di = Utils.getDirectoryInfoForLocalNuGetFeed path alternativeProjectRoot root let nupkg = findLocalPackage di.FullName packageName version - use _ = Profile.startCategory Profile.Categories.FileCopy + use _ = Profile.startCategory Profile.Category.FileIO File.Copy(nupkg.FullName,targetFileName) | _ -> // discover the link on the fly @@ -954,7 +973,7 @@ let DownloadPackage(alternativeProjectRoot, root, (source : PackageSource), cach try if authenticated then tracefn "Downloading %O %O%s" packageName version (if groupName = Constants.MainDependencyGroup then "" else sprintf " (%O)" groupName) - let nugetPackage = GetPackageDetails alternativeProjectRoot root force [source] groupName packageName version + let! nugetPackage = GetPackageDetails alternativeProjectRoot root force [source] groupName packageName version let encodeURL (url:string) = url.Replace("+","%2B") let downloadUri = @@ -972,7 +991,7 @@ let DownloadPackage(alternativeProjectRoot, root, (source : PackageSource), cach tracefn " from %O" !downloadUrl tracefn " to %s" targetFileName - use trackDownload = Profile.startCategory Profile.Categories.NuGetDownload + use trackDownload = Profile.startCategory Profile.Category.NuGetDownload let! license = Async.StartChild(DownloadLicense(root,force,packageName,version,nugetPackage.LicenseUrl,licenseFileName), 5000) let request = HttpWebRequest.Create(downloadUri) :?> HttpWebRequest diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index efbddbc6b6..6f0d7d9c48 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -110,7 +110,7 @@ type Resolution = | Conflict of resolveStep : ResolverStep * requirementSet : PackageRequirement Set * requirement : PackageRequirement - * getPackageVersions : (PackageName -> (SemVerInfo * PackageSource list) seq) + * getPackageVersions : (PackageName -> (SemVerInfo * PackageSource list) seq Async) member private self.DebugDisplay() = match self with | Ok pkgres -> @@ -187,7 +187,8 @@ module Resolution = | cfs when cfs.Count = 1 -> let c = cfs.MinimumElement let errorText = buildConflictReport errorText cfs - match getVersionF c.Name |> Seq.toList with + let versions = getVersionF c.Name |> Async.RunSynchronously + match versions |> Seq.toList with | [] -> errorText.AppendLinef " - No versions available." | avalaibleVersions -> ( errorText.AppendLinef " - Available versions:" @@ -342,7 +343,7 @@ let private updateRestrictions (pkgConfig:PackageConfig) (package:ResolvedPackag } -let private explorePackageConfig getPackageDetailsF (pkgConfig:PackageConfig) = +let private explorePackageConfig getPackageDetailsReportBlock (pkgConfig:PackageConfig) = let dependency, version = pkgConfig.Dependency, pkgConfig.Version let packageSources = pkgConfig.Sources @@ -359,7 +360,8 @@ let private explorePackageConfig getPackageDetailsF (pkgConfig:PackageConfig) = filterRestrictions dependency.Settings.FrameworkRestrictions pkgConfig.GlobalRestrictions try let packageDetails : PackageDetails = - getPackageDetailsF packageSources pkgConfig.GroupName dependency.Name version + getPackageDetailsReportBlock packageSources pkgConfig.GroupName dependency.Name version + |> Async.RunSynchronously let filteredDependencies = DependencySetFilter.filterByRestrictions newRestrictions packageDetails.DirectDependencies let settings = @@ -392,7 +394,7 @@ type StackPack = { } -let private getExploredPackage (pkgConfig:PackageConfig) getPackageDetailsF (stackpack:StackPack) = +let private getExploredPackage (pkgConfig:PackageConfig) getPackageDetailsReportBlock (stackpack:StackPack) = let key = (pkgConfig.Dependency.Name, pkgConfig.Version) match stackpack.ExploredPackages.TryGetValue key with @@ -403,7 +405,7 @@ let private getExploredPackage (pkgConfig:PackageConfig) getPackageDetailsF (sta verbosefn " Retrieved Explored Package %O" package stackpack, Some(true, package) | false,_ -> - match explorePackageConfig getPackageDetailsF pkgConfig with + match explorePackageConfig getPackageDetailsReportBlock pkgConfig with | Some explored -> if verbose then verbosefn " Found Explored Package %O" explored @@ -418,7 +420,7 @@ let private getCompatibleVersions (currentStep:ResolverStep) groupName (currentRequirement:PackageRequirement) - (getVersionsF: PackageSource list -> ResolverStrategy -> GroupName -> PackageName -> seq) + (getVersionsF: PackageSource list -> ResolverStrategy -> GroupName -> PackageName -> Async>) globalOverride globalStrategyForDirectDependencies globalStrategyForTransitives = @@ -451,7 +453,10 @@ let private getCompatibleVersions | Specific v -> getSingleVersion v | _ -> let resolverStrategy = getResolverStrategy globalStrategyForDirectDependencies globalStrategyForTransitives allRequirementsOfCurrentPackage currentRequirement - getVersionsF currentRequirement.Sources resolverStrategy groupName currentRequirement.Name + let result = + getVersionsF currentRequirement.Sources resolverStrategy groupName currentRequirement.Name + |> Async.RunSynchronously + result let compatibleVersions = Seq.filter (isInRange id) (availableVersions) let compatibleVersions, globalOverride = @@ -628,6 +633,15 @@ type private Stage = /// Resolves all direct and transitive dependencies let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrategyForDirectDependencies, globalStrategyForTransitives, globalFrameworkRestrictions, (rootDependencies:PackageRequirement Set), updateMode : UpdateMode) = tracefn "Resolving packages for group %O:" groupName + + use d = Profile.startCategory Profile.Category.ResolverAlgorithm + + let getPackageDetailsReportBlock sources groupName packageName semVer = async { + use d = Profile.startCategory (Profile.Category.ResolverAlgorithmBlocked Profile.BlockReason.PackageDetails) + return! getPackageDetailsF sources groupName packageName semVer } + let getVersionsReportBlock sources resolverStrategy groupName packageName = async { + use d = Profile.startCategory (Profile.Category.ResolverAlgorithmBlocked Profile.BlockReason.GetVersion) + return! getVersionsF sources resolverStrategy groupName packageName } let packageFilter = match updateMode with @@ -730,7 +744,8 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate getConflicts currentStep currentRequirement stackpack.KnownConflicts let currentConflict = - let getVersionsF = getVersionsF currentRequirement.Sources ResolverStrategy.Max groupName + let getVersionsF = + getVersionsReportBlock currentRequirement.Sources ResolverStrategy.Max groupName if Seq.isEmpty conflicts then { currentConflict with Status = Resolution.Conflict (currentStep,Set.empty,currentRequirement,getVersionsF)} @@ -742,7 +757,7 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate fuseConflicts currentConflict priorConflictSteps conflicts else let compatibleVersions,globalOverride,tryRelaxed = - getCompatibleVersions currentStep groupName currentRequirement getVersionsF + getCompatibleVersions currentStep groupName currentRequirement getVersionsReportBlock currentConflict.GlobalOverride globalStrategyForDirectDependencies globalStrategyForTransitives @@ -819,7 +834,7 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate UpdateMode = updateMode } - match getExploredPackage packageDetails getPackageDetailsF stackpack with + match getExploredPackage packageDetails getPackageDetailsReportBlock stackpack with | stackpack, None -> step (Inner((currentConflict,currentStep,currentRequirement), priorConflictSteps)) stackpack compatibleVersions flags @@ -868,7 +883,7 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate let currentRequirement = getCurrentRequirement packageFilter startingStep.OpenRequirements (Dictionary()) let status = - let getVersionsF = getVersionsF currentRequirement.Sources ResolverStrategy.Max groupName + let getVersionsF = getVersionsReportBlock currentRequirement.Sources ResolverStrategy.Max groupName Resolution.Conflict(startingStep,Set.empty,currentRequirement,getVersionsF) diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs index fc6f4e958e..cc34d8ef63 100644 --- a/src/Paket.Core/Installation/UpdateProcess.fs +++ b/src/Paket.Core/Installation/UpdateProcess.fs @@ -12,21 +12,20 @@ open InstallProcess let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRuntimeGraphFromPackage (lockFile:LockFile) (dependenciesFile:DependenciesFile) updateMode semVerUpdateMode = let allVersions = Dictionary() - let getSortedAndCachedVersionsF sources resolverStrategy groupName packageName : seq = + let getSortedAndCachedVersionsF sources resolverStrategy groupName packageName : Async> = async { let key = packageName,sources match allVersions.TryGetValue key with | false,_ -> - let versions = - if verbose then - verbosefn " - fetching versions for %O" packageName + if verbose then + verbosefn " - fetching versions for %O" packageName + let! versions = getSortedVersionsF sources resolverStrategy groupName packageName if Seq.isEmpty versions then failwithf "Couldn't retrieve versions for %O." packageName allVersions.Add(key,versions) - versions - | true,versions -> versions - |> List.toSeq + return versions |> List.toSeq + | true,versions -> return versions |> List.toSeq } let dependenciesFile = let processFile createRequirementF = @@ -123,48 +122,28 @@ let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRunti v,s :: (List.map PackageSources.PackageSource.FromCache caches)) let getVersionsF sources resolverStrategy groupName packageName = - Profile.startCategoryRaw Profile.Categories.Other - try - seq { + async { + let pre = match preferredVersions |> Map.tryFind (groupName, packageName), resolverStrategy with - | Some x, ResolverStrategy.Min -> yield x + | Some x, ResolverStrategy.Min -> [x] | Some x, _ -> if not (changes |> Set.contains (groupName, packageName)) then - yield x - | _ -> () - yield! getSortedAndCachedVersionsF sources resolverStrategy groupName packageName - } |> Seq.cache - finally - Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm - - let getPackageDetailsF sources groupName packageName version = - Profile.startCategoryRaw Profile.Categories.Other - try - let exploredPackage:PackageDetails = getPackageDetailsF sources groupName packageName version - match preferredVersions |> Map.tryFind (groupName,packageName) with - | Some (preferedVersion,_) when version = preferedVersion -> { exploredPackage with Unlisted = false } - | _ -> exploredPackage - finally - Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm + [x] + else [] + | _ -> [] + let! results = getSortedAndCachedVersionsF sources resolverStrategy groupName packageName + return Seq.append pre results |> Seq.cache + } + + let getPackageDetailsF sources groupName packageName version = async { + let! (exploredPackage:PackageDetails) = getPackageDetailsF sources groupName packageName version + match preferredVersions |> Map.tryFind (groupName,packageName) with + | Some (preferedVersion,_) when version = preferedVersion -> return { exploredPackage with Unlisted = false } + | _ -> return exploredPackage } getVersionsF,getPackageDetailsF,groups - - let getRuntimeGraphFromPackageF groupName resolvedPackage = - Profile.startCategoryRaw Profile.Categories.Other - try - getRuntimeGraphFromPackage groupName resolvedPackage - finally - Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm - - let getSha1F origin s1 s2 restriction s3 = - Profile.startCategoryRaw Profile.Categories.Other - try - getSha1 origin s1 s2 restriction s3 - finally - Profile.startCategoryRaw Profile.Categories.ResolverAlgorithm - use d = Profile.startCategory Profile.Categories.ResolverAlgorithm - let resolution = dependenciesFile.Resolve(force, getSha1F, getVersionsF, getPackageDetailsF, getRuntimeGraphFromPackageF, groupsToUpdate, updateMode) - d.Dispose() + + let resolution = dependenciesFile.Resolve(force, getSha1, getVersionsF, getPackageDetailsF, getRuntimeGraphFromPackage, groupsToUpdate, updateMode) let groups = dependenciesFile.Groups @@ -221,11 +200,11 @@ let SelectiveUpdate(dependenciesFile : DependenciesFile, alternativeProjectRoot, let getSha1 origin owner repo branch auth = RemoteDownload.getSHA1OfBranch origin owner repo branch auth |> Async.RunSynchronously let root = Path.GetDirectoryName dependenciesFile.FileName - let inline getVersionsF sources resolverStrategy groupName packageName = - let versions = NuGetV2.GetVersions force alternativeProjectRoot root (sources, packageName) + let inline getVersionsF sources resolverStrategy groupName packageName = async { + let! versions = NuGetV2.GetVersions force alternativeProjectRoot root (sources, packageName) match resolverStrategy with - | ResolverStrategy.Max -> List.sortDescending versions - | ResolverStrategy.Min -> List.sort versions + | ResolverStrategy.Max -> return List.sortDescending versions + | ResolverStrategy.Min -> return List.sort versions } let dependenciesFile = detectProjectFrameworksForDependenciesFile dependenciesFile diff --git a/src/Paket.Core/PackageAnalysis/FindOutdated.fs b/src/Paket.Core/PackageAnalysis/FindOutdated.fs index 83e93a9641..b9dcd5a8b8 100644 --- a/src/Paket.Core/PackageAnalysis/FindOutdated.fs +++ b/src/Paket.Core/PackageAnalysis/FindOutdated.fs @@ -37,13 +37,12 @@ let FindOutdated strict includingPrereleases groupNameFilter environment = trial let root = Path.GetDirectoryName dependenciesFile.FileName let alternativeProjectRoot = None - let getVersionsF sources resolverStrategy groupName packageName = - let versions = NuGetV2.GetVersions force alternativeProjectRoot root (sources, packageName) + let getVersionsF sources resolverStrategy groupName packageName = async { + let! versions = NuGetV2.GetVersions force alternativeProjectRoot root (sources, packageName) match resolverStrategy with - | ResolverStrategy.Max -> List.sortDescending versions - | ResolverStrategy.Min -> List.sort versions - |> List.toSeq + | ResolverStrategy.Max -> return List.sortDescending versions |> List.toSeq + | ResolverStrategy.Min -> return List.sort versions |> List.toSeq } let dependenciesFile = UpdateProcess.detectProjectFrameworksForDependenciesFile dependenciesFile let checkedDepsGroups = diff --git a/src/Paket.Core/PublicAPI.fs b/src/Paket.Core/PublicAPI.fs index 9d3155a627..7ab6186b1f 100644 --- a/src/Paket.Core/PublicAPI.fs +++ b/src/Paket.Core/PublicAPI.fs @@ -609,6 +609,7 @@ type Dependencies(dependenciesFileName: string) = let versions = NuGetV2.GetVersions true alternativeProjectRoot root (sources, PackageName name) + |> Async.RunSynchronously |> List.map (fun (v,_) -> v.ToString()) |> List.toArray |> SemVer.SortVersions diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index 02c633efd4..dfaf1fd4f9 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -13,7 +13,7 @@ open PackageSources open System.Xml open Paket.Domain -do Paket.Profile.reset() +let sw = Stopwatch.StartNew() type PaketExiter() = interface IExiter with @@ -37,15 +37,24 @@ let processWithValidation silent validateF commandF (result : ParseResults<'T>) try commandF result finally + sw.Stop() if not silent then + let realTime = sw.Elapsed let results = - Profile.watches - |> Seq.map (fun (kv) -> kv.Key, kv.Value.Elapsed) + Profile.events + |> Seq.groupBy (fun (ev) -> ev.Category) + |> Seq.map (fun (cat, group) -> + cat, group |> Seq.map (fun ev -> ev.Duration) |> Seq.fold (+) (TimeSpan())) |> Seq.toList - let combined = results |> List.map snd |> List.fold (+) (TimeSpan()) - let elapsedTime = Utils.TimeSpanToReadableString combined + let blocked = + results + |> List.filter (function Profile.Category.ResolverAlgorithmBlocked _, _ -> true | _ -> false) + |> Seq.map snd + |> Seq.fold (+) (TimeSpan()) + let resolver = results |> List.pick (function Profile.Category.ResolverAlgorithm, s -> Some s | _ -> None) + tracefn "%s - Resolver (plain)." (Utils.TimeSpanToReadableString (resolver - blocked)) for (cat, elapsed) in results do tracefn "%s - %A." (Utils.TimeSpanToReadableString elapsed) cat - tracefn "%s - ready." elapsedTime + tracefn "%s - ready." (Utils.TimeSpanToReadableString realTime) let processCommand silent commandF result = processWithValidation silent (fun _ -> true) commandF result diff --git a/tests/Paket.Tests/TestHelpers.fs b/tests/Paket.Tests/TestHelpers.fs index d18b43df4a..368ea38c0f 100644 --- a/tests/Paket.Tests/TestHelpers.fs +++ b/tests/Paket.Tests/TestHelpers.fs @@ -61,6 +61,7 @@ let PackageDetailsFromGraph (graph : DependencyGraph) sources groupName (package LicenseUrl = "" Unlisted = false DirectDependencies = Set.ofList dependencies } + |> async.Return let VersionsFromGraph (graph : DependencyGraph) sources resolverStrategy groupName packageName = let versions = @@ -73,6 +74,7 @@ let VersionsFromGraph (graph : DependencyGraph) sources resolverStrategy groupNa match resolverStrategy with | ResolverStrategy.Max -> List.sortDescending versions | ResolverStrategy.Min -> List.sort versions + |> async.Return let GetRuntimeGraphFromGraph (graph : DependencyGraph) groupName (package:ResolvedPackage) = graph @@ -86,7 +88,7 @@ let GetRuntimeGraphFromGraph (graph : DependencyGraph) groupName (package:Resolv let VersionsFromGraphAsSeq (graph : DependencyGraph) sources resolverStrategy groupName packageName = VersionsFromGraph graph sources resolverStrategy groupName packageName - |> Seq.ofList + |> fun a -> async.Bind(a, Seq.ofList >> async.Return) let safeResolve graph (dependencies : (string * VersionRange) list) = let sources = [ PackageSource.NuGetV2Source "" ] From e6a7cf6ad588c80006aa68503dea9cf7aa713f83 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 23:16:19 +0200 Subject: [PATCH 30/47] preload dependency information, such that the resolver doesn't need to wait. --- .../Dependencies/PackageResolver.fs | 70 +++++++++++++------ 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 6f0d7d9c48..dbf5c6d305 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -110,7 +110,7 @@ type Resolution = | Conflict of resolveStep : ResolverStep * requirementSet : PackageRequirement Set * requirement : PackageRequirement - * getPackageVersions : (PackageName -> (SemVerInfo * PackageSource list) seq Async) + * getPackageVersions : (PackageName -> (SemVerInfo * PackageSource list) seq) member private self.DebugDisplay() = match self with | Ok pkgres -> @@ -187,8 +187,7 @@ module Resolution = | cfs when cfs.Count = 1 -> let c = cfs.MinimumElement let errorText = buildConflictReport errorText cfs - let versions = getVersionF c.Name |> Async.RunSynchronously - match versions |> Seq.toList with + match getVersionF c.Name |> Seq.toList with | [] -> errorText.AppendLinef " - No versions available." | avalaibleVersions -> ( errorText.AppendLinef " - Available versions:" @@ -343,7 +342,7 @@ let private updateRestrictions (pkgConfig:PackageConfig) (package:ResolvedPackag } -let private explorePackageConfig getPackageDetailsReportBlock (pkgConfig:PackageConfig) = +let private explorePackageConfig getPackageDetailsBlock (pkgConfig:PackageConfig) = let dependency, version = pkgConfig.Dependency, pkgConfig.Version let packageSources = pkgConfig.Sources @@ -360,8 +359,7 @@ let private explorePackageConfig getPackageDetailsReportBlock (pkgConfig:Package filterRestrictions dependency.Settings.FrameworkRestrictions pkgConfig.GlobalRestrictions try let packageDetails : PackageDetails = - getPackageDetailsReportBlock packageSources pkgConfig.GroupName dependency.Name version - |> Async.RunSynchronously + getPackageDetailsBlock packageSources pkgConfig.GroupName dependency.Name version let filteredDependencies = DependencySetFilter.filterByRestrictions newRestrictions packageDetails.DirectDependencies let settings = @@ -394,7 +392,7 @@ type StackPack = { } -let private getExploredPackage (pkgConfig:PackageConfig) getPackageDetailsReportBlock (stackpack:StackPack) = +let private getExploredPackage (pkgConfig:PackageConfig) getPackageDetailsBlock (stackpack:StackPack) = let key = (pkgConfig.Dependency.Name, pkgConfig.Version) match stackpack.ExploredPackages.TryGetValue key with @@ -405,7 +403,7 @@ let private getExploredPackage (pkgConfig:PackageConfig) getPackageDetailsReport verbosefn " Retrieved Explored Package %O" package stackpack, Some(true, package) | false,_ -> - match explorePackageConfig getPackageDetailsReportBlock pkgConfig with + match explorePackageConfig getPackageDetailsBlock pkgConfig with | Some explored -> if verbose then verbosefn " Found Explored Package %O" explored @@ -420,7 +418,7 @@ let private getCompatibleVersions (currentStep:ResolverStep) groupName (currentRequirement:PackageRequirement) - (getVersionsF: PackageSource list -> ResolverStrategy -> GroupName -> PackageName -> Async>) + (getVersionsF: PackageSource list -> ResolverStrategy -> GroupName -> PackageName -> seq) globalOverride globalStrategyForDirectDependencies globalStrategyForTransitives = @@ -453,10 +451,7 @@ let private getCompatibleVersions | Specific v -> getSingleVersion v | _ -> let resolverStrategy = getResolverStrategy globalStrategyForDirectDependencies globalStrategyForTransitives allRequirementsOfCurrentPackage currentRequirement - let result = - getVersionsF currentRequirement.Sources resolverStrategy groupName currentRequirement.Name - |> Async.RunSynchronously - result + getVersionsF currentRequirement.Sources resolverStrategy groupName currentRequirement.Name let compatibleVersions = Seq.filter (isInRange id) (availableVersions) let compatibleVersions, globalOverride = @@ -631,17 +626,31 @@ type private Stage = | Inner of currentConflict : (ConflictState * ResolverStep * PackageRequirement) * priorConflictSteps : (ConflictState * ResolverStep * PackageRequirement * seq * StepFlags) list /// Resolves all direct and transitive dependencies -let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrategyForDirectDependencies, globalStrategyForTransitives, globalFrameworkRestrictions, (rootDependencies:PackageRequirement Set), updateMode : UpdateMode) = +let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalStrategyForDirectDependencies, globalStrategyForTransitives, globalFrameworkRestrictions, (rootDependencies:PackageRequirement Set), updateMode : UpdateMode) = tracefn "Resolving packages for group %O:" groupName use d = Profile.startCategory Profile.Category.ResolverAlgorithm - let getPackageDetailsReportBlock sources groupName packageName semVer = async { + let startedGetPackageDetailsRequests = System.Collections.Concurrent.ConcurrentDictionary<_,System.Threading.Tasks.Task<_>>() + let startRequestGetPackageDetails sources groupName packageName semVer = + let key = (sources, groupName, packageName, semVer) + startedGetPackageDetailsRequests.GetOrAdd (key, fun _ -> + (getPackageDetailsRaw sources groupName packageName semVer : Async) + |> Async.StartAsTask) + let getPackageDetailsBlock sources groupName packageName semVer = use d = Profile.startCategory (Profile.Category.ResolverAlgorithmBlocked Profile.BlockReason.PackageDetails) - return! getPackageDetailsF sources groupName packageName semVer } - let getVersionsReportBlock sources resolverStrategy groupName packageName = async { + (startRequestGetPackageDetails sources groupName packageName semVer).GetAwaiter().GetResult() + + + let startedGetVersionsRequests = System.Collections.Concurrent.ConcurrentDictionary<_,System.Threading.Tasks.Task<_>>() + let startRequestGetVersions sources resolverStrategy groupName packageName = + let key = (sources, resolverStrategy, groupName, packageName) + startedGetVersionsRequests.GetOrAdd (key, fun _ -> + getVersionsRaw sources resolverStrategy groupName packageName + |> Async.StartAsTask) + let getVersionsBlock sources resolverStrategy groupName packageName = use d = Profile.startCategory (Profile.Category.ResolverAlgorithmBlocked Profile.BlockReason.GetVersion) - return! getVersionsF sources resolverStrategy groupName packageName } + (startRequestGetVersions sources resolverStrategy groupName packageName).GetAwaiter().GetResult() let packageFilter = match updateMode with @@ -745,7 +754,7 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate let currentConflict = let getVersionsF = - getVersionsReportBlock currentRequirement.Sources ResolverStrategy.Max groupName + getVersionsBlock currentRequirement.Sources ResolverStrategy.Max groupName if Seq.isEmpty conflicts then { currentConflict with Status = Resolution.Conflict (currentStep,Set.empty,currentRequirement,getVersionsF)} @@ -757,7 +766,7 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate fuseConflicts currentConflict priorConflictSteps conflicts else let compatibleVersions,globalOverride,tryRelaxed = - getCompatibleVersions currentStep groupName currentRequirement getVersionsReportBlock + getCompatibleVersions currentStep groupName currentRequirement getVersionsBlock currentConflict.GlobalOverride globalStrategyForDirectDependencies globalStrategyForTransitives @@ -834,7 +843,7 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate UpdateMode = updateMode } - match getExploredPackage packageDetails getPackageDetailsReportBlock stackpack with + match getExploredPackage packageDetails getPackageDetailsBlock stackpack with | stackpack, None -> step (Inner((currentConflict,currentStep,currentRequirement), priorConflictSteps)) stackpack compatibleVersions flags @@ -842,6 +851,19 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate let hasUnlisted = exploredPackage.Unlisted || flags.HasUnlisted let flags = { flags with HasUnlisted = hasUnlisted } + // Start pre-loading infos about dependencies. + for (pack,verReq,restr) in exploredPackage.Dependencies do + async { + let! versions = startRequestGetVersions currentRequirement.Sources ResolverStrategy.Max groupName pack |> Async.AwaitTask + // Preload the first version in range of this requirement + match versions |> Seq.map fst |> Seq.tryFind (verReq.IsInRange) with + | Some verToPreload -> + let! details = startRequestGetPackageDetails currentRequirement.Sources groupName pack verToPreload |> Async.AwaitTask + () + | None -> () + return () + } |> Async.Start + if exploredPackage.Unlisted && not flags.UseUnlisted then if not alreadyExplored then tracefn " %O %O was unlisted" exploredPackage.Name exploredPackage.Version @@ -880,10 +902,14 @@ let Resolve (getVersionsF, getPackageDetailsF, groupName:GroupName, globalStrate OpenRequirements = rootDependencies } + for openReq in startingStep.OpenRequirements do + startRequestGetVersions openReq.Sources ResolverStrategy.Max groupName openReq.Name + |> ignore + let currentRequirement = getCurrentRequirement packageFilter startingStep.OpenRequirements (Dictionary()) let status = - let getVersionsF = getVersionsReportBlock currentRequirement.Sources ResolverStrategy.Max groupName + let getVersionsF = getVersionsBlock currentRequirement.Sources ResolverStrategy.Max groupName Resolution.Conflict(startingStep,Set.empty,currentRequirement,getVersionsF) From 7373ae61949071ea2f39e575f547ec38ba1bb04e Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 23:30:43 +0200 Subject: [PATCH 31/47] change the keys for the cache and delete an old cache. --- .../Dependencies/PackageResolver.fs | 4 +-- src/Paket.Core/Installation/UpdateProcess.fs | 25 +++++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index dbf5c6d305..5f844d6fc1 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -633,7 +633,7 @@ let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalSt let startedGetPackageDetailsRequests = System.Collections.Concurrent.ConcurrentDictionary<_,System.Threading.Tasks.Task<_>>() let startRequestGetPackageDetails sources groupName packageName semVer = - let key = (sources, groupName, packageName, semVer) + let key = (sources, packageName, semVer) startedGetPackageDetailsRequests.GetOrAdd (key, fun _ -> (getPackageDetailsRaw sources groupName packageName semVer : Async) |> Async.StartAsTask) @@ -644,7 +644,7 @@ let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalSt let startedGetVersionsRequests = System.Collections.Concurrent.ConcurrentDictionary<_,System.Threading.Tasks.Task<_>>() let startRequestGetVersions sources resolverStrategy groupName packageName = - let key = (sources, resolverStrategy, groupName, packageName) + let key = (sources, packageName) startedGetVersionsRequests.GetOrAdd (key, fun _ -> getVersionsRaw sources resolverStrategy groupName packageName |> Async.StartAsTask) diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs index cc34d8ef63..372da0fecc 100644 --- a/src/Paket.Core/Installation/UpdateProcess.fs +++ b/src/Paket.Core/Installation/UpdateProcess.fs @@ -11,21 +11,14 @@ open Paket.Logging open InstallProcess let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRuntimeGraphFromPackage (lockFile:LockFile) (dependenciesFile:DependenciesFile) updateMode semVerUpdateMode = - let allVersions = Dictionary() - let getSortedAndCachedVersionsF sources resolverStrategy groupName packageName : Async> = async { - let key = packageName,sources - match allVersions.TryGetValue key with - | false,_ -> - if verbose then - verbosefn " - fetching versions for %O" packageName - let! versions = - getSortedVersionsF sources resolverStrategy groupName packageName - - if Seq.isEmpty versions then - failwithf "Couldn't retrieve versions for %O." packageName - allVersions.Add(key,versions) - return versions |> List.toSeq - | true,versions -> return versions |> List.toSeq } + let getSortedVersionsF sources resolverStrategy groupName packageName : Async> = async { + if verbose then + verbosefn " - fetching versions for %O" packageName + let! versions = + getSortedVersionsF sources resolverStrategy groupName packageName + if Seq.isEmpty versions then + failwithf "Couldn't retrieve versions for %O." packageName + return versions |> List.toSeq } let dependenciesFile = let processFile createRequirementF = @@ -131,7 +124,7 @@ let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRunti [x] else [] | _ -> [] - let! results = getSortedAndCachedVersionsF sources resolverStrategy groupName packageName + let! results = getSortedVersionsF sources resolverStrategy groupName packageName return Seq.append pre results |> Seq.cache } From a4e4d7787e3606b2c570e2f372857a1579e77ec9 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Tue, 23 May 2017 23:38:00 +0200 Subject: [PATCH 32/47] bugfix in new stats --- src/Paket/Program.fs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index dfaf1fd4f9..802f80cfb9 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -51,7 +51,10 @@ let processWithValidation silent validateF commandF (result : ParseResults<'T>) |> List.filter (function Profile.Category.ResolverAlgorithmBlocked _, _ -> true | _ -> false) |> Seq.map snd |> Seq.fold (+) (TimeSpan()) - let resolver = results |> List.pick (function Profile.Category.ResolverAlgorithm, s -> Some s | _ -> None) + let resolver = + match results |> List.tryPick (function Profile.Category.ResolverAlgorithm, s -> Some s | _ -> None) with + | Some s -> s + | None -> TimeSpan() tracefn "%s - Resolver (plain)." (Utils.TimeSpanToReadableString (resolver - blocked)) for (cat, elapsed) in results do tracefn "%s - %A." (Utils.TimeSpanToReadableString elapsed) cat tracefn "%s - ready." (Utils.TimeSpanToReadableString realTime) From a481deabf0e74964c15c39cfaaf6168298a40d37 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 00:40:02 +0200 Subject: [PATCH 33/47] add getPreferredVersionF to properly handle caching and preloading in combination with resolverstrategy. --- build.fsx | 2 + .../Dependencies/PackageResolver.fs | 21 ++++++--- src/Paket.Core/Installation/UpdateProcess.fs | 43 ++++++++----------- .../PackageAnalysis/FindOutdated.fs | 11 ++--- .../PaketConfigFiles/DependenciesFile.fs | 4 +- src/Paket/Paket.fsproj | 4 +- .../DependencyGroupsAndRestrictions.fs | 2 +- .../Resolver/GlobalOptimisticStrategySpecs.fs | 2 +- .../GlobalPessimisticStrategySpecs.fs | 2 +- tests/Paket.Tests/Resolver/StrategySpecs.fs | 2 +- tests/Paket.Tests/TestHelpers.fs | 18 +++----- 11 files changed, 54 insertions(+), 57 deletions(-) diff --git a/build.fsx b/build.fsx index f19d1e6e1c..24243dc85d 100644 --- a/build.fsx +++ b/build.fsx @@ -305,6 +305,8 @@ Target "MergePaketTool" (fun _ -> Target "RunIntegrationTests" (fun _ -> mergePaketTool () + // improves the speed of the test-suite by disabling the runtime resolution. + System.Environment.SetEnvironmentVariable("PAKET_DISABLE_RUNTIME_RESOLUTION", "true") !! integrationTestAssemblies |> NUnit3 (fun p -> { p with diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 5f844d6fc1..371193dbb3 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -626,7 +626,7 @@ type private Stage = | Inner of currentConflict : (ConflictState * ResolverStep * PackageRequirement) * priorConflictSteps : (ConflictState * ResolverStep * PackageRequirement * seq * StepFlags) list /// Resolves all direct and transitive dependencies -let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalStrategyForDirectDependencies, globalStrategyForTransitives, globalFrameworkRestrictions, (rootDependencies:PackageRequirement Set), updateMode : UpdateMode) = +let Resolve (getVersionsRaw, getPreferredVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalStrategyForDirectDependencies, globalStrategyForTransitives, globalFrameworkRestrictions, (rootDependencies:PackageRequirement Set), updateMode : UpdateMode) = tracefn "Resolving packages for group %O:" groupName use d = Profile.startCategory Profile.Category.ResolverAlgorithm @@ -635,7 +635,7 @@ let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalSt let startRequestGetPackageDetails sources groupName packageName semVer = let key = (sources, packageName, semVer) startedGetPackageDetailsRequests.GetOrAdd (key, fun _ -> - (getPackageDetailsRaw sources groupName packageName semVer : Async) + (getPackageDetailsRaw sources groupName packageName semVer : Async) |> Async.StartAsTask) let getPackageDetailsBlock sources groupName packageName semVer = use d = Profile.startCategory (Profile.Category.ResolverAlgorithmBlocked Profile.BlockReason.PackageDetails) @@ -643,14 +643,21 @@ let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalSt let startedGetVersionsRequests = System.Collections.Concurrent.ConcurrentDictionary<_,System.Threading.Tasks.Task<_>>() - let startRequestGetVersions sources resolverStrategy groupName packageName = + let startRequestGetVersions sources groupName packageName = let key = (sources, packageName) startedGetVersionsRequests.GetOrAdd (key, fun _ -> - getVersionsRaw sources resolverStrategy groupName packageName + getVersionsRaw sources groupName packageName |> Async.StartAsTask) let getVersionsBlock sources resolverStrategy groupName packageName = use d = Profile.startCategory (Profile.Category.ResolverAlgorithmBlocked Profile.BlockReason.GetVersion) - (startRequestGetVersions sources resolverStrategy groupName packageName).GetAwaiter().GetResult() + let versions = (startRequestGetVersions sources groupName packageName).GetAwaiter().GetResult() |> Seq.toList + d.Dispose() + let sorted = + match resolverStrategy with + | ResolverStrategy.Max -> List.sortDescending versions + | ResolverStrategy.Min -> List.sort versions + let pref = getPreferredVersionsRaw sources resolverStrategy groupName packageName + pref @ sorted |> List.toSeq let packageFilter = match updateMode with @@ -854,7 +861,7 @@ let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalSt // Start pre-loading infos about dependencies. for (pack,verReq,restr) in exploredPackage.Dependencies do async { - let! versions = startRequestGetVersions currentRequirement.Sources ResolverStrategy.Max groupName pack |> Async.AwaitTask + let! versions = startRequestGetVersions currentRequirement.Sources groupName pack |> Async.AwaitTask // Preload the first version in range of this requirement match versions |> Seq.map fst |> Seq.tryFind (verReq.IsInRange) with | Some verToPreload -> @@ -903,7 +910,7 @@ let Resolve (getVersionsRaw, getPackageDetailsRaw, groupName:GroupName, globalSt } for openReq in startingStep.OpenRequirements do - startRequestGetVersions openReq.Sources ResolverStrategy.Max groupName openReq.Name + startRequestGetVersions openReq.Sources groupName openReq.Name |> ignore let currentRequirement = getCurrentRequirement packageFilter startingStep.OpenRequirements (Dictionary()) diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs index 372da0fecc..cf83211f03 100644 --- a/src/Paket.Core/Installation/UpdateProcess.fs +++ b/src/Paket.Core/Installation/UpdateProcess.fs @@ -10,15 +10,15 @@ open Chessie.ErrorHandling open Paket.Logging open InstallProcess -let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRuntimeGraphFromPackage (lockFile:LockFile) (dependenciesFile:DependenciesFile) updateMode semVerUpdateMode = - let getSortedVersionsF sources resolverStrategy groupName packageName : Async> = async { +let selectiveUpdate force getSha1 getVersionsF getPackageDetailsF getRuntimeGraphFromPackage (lockFile:LockFile) (dependenciesFile:DependenciesFile) updateMode semVerUpdateMode = + let getSortedVersionsF sources groupName packageName : Async> = async { if verbose then verbosefn " - fetching versions for %O" packageName let! versions = - getSortedVersionsF sources resolverStrategy groupName packageName + getVersionsF sources groupName packageName if Seq.isEmpty versions then failwithf "Couldn't retrieve versions for %O." packageName - return versions |> List.toSeq } + return versions } let dependenciesFile = let processFile createRequirementF = @@ -49,7 +49,7 @@ let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRunti | SemVerUpdateMode.KeepMinor -> processFile (fun v -> sprintf "~> %d.%d.%d" v.Major v.Minor v.Patch + formatPrerelease v) | SemVerUpdateMode.KeepPatch -> processFile (fun v -> sprintf "~> %d.%d.%d.%s" v.Major v.Minor v.Patch v.Build + formatPrerelease v) - let getVersionsF,getPackageDetailsF,groupsToUpdate = + let getPreferredVersionsF,getPackageDetailsF,groupsToUpdate = let changes,groups = match updateMode with | UpdateAll -> @@ -114,19 +114,14 @@ let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRunti v,s :: (List.map PackageSources.PackageSource.FromCache caches)) - let getVersionsF sources resolverStrategy groupName packageName = - async { - let pre = - match preferredVersions |> Map.tryFind (groupName, packageName), resolverStrategy with - | Some x, ResolverStrategy.Min -> [x] - | Some x, _ -> - if not (changes |> Set.contains (groupName, packageName)) then - [x] - else [] - | _ -> [] - let! results = getSortedVersionsF sources resolverStrategy groupName packageName - return Seq.append pre results |> Seq.cache - } + let getPreferredVersionsF sources resolverStrategy groupName packageName = + match preferredVersions |> Map.tryFind (groupName, packageName), resolverStrategy with + | Some x, ResolverStrategy.Min -> [x] + | Some x, _ -> + if not (changes |> Set.contains (groupName, packageName)) then + [x] + else [] + | _ -> [] let getPackageDetailsF sources groupName packageName version = async { let! (exploredPackage:PackageDetails) = getPackageDetailsF sources groupName packageName version @@ -134,9 +129,9 @@ let selectiveUpdate force getSha1 getSortedVersionsF getPackageDetailsF getRunti | Some (preferedVersion,_) when version = preferedVersion -> return { exploredPackage with Unlisted = false } | _ -> return exploredPackage } - getVersionsF,getPackageDetailsF,groups + getPreferredVersionsF,getPackageDetailsF,groups - let resolution = dependenciesFile.Resolve(force, getSha1, getVersionsF, getPackageDetailsF, getRuntimeGraphFromPackage, groupsToUpdate, updateMode) + let resolution = dependenciesFile.Resolve(force, getSha1, getVersionsF, getPreferredVersionsF, getPackageDetailsF, getRuntimeGraphFromPackage, groupsToUpdate, updateMode) let groups = dependenciesFile.Groups @@ -193,11 +188,9 @@ let SelectiveUpdate(dependenciesFile : DependenciesFile, alternativeProjectRoot, let getSha1 origin owner repo branch auth = RemoteDownload.getSHA1OfBranch origin owner repo branch auth |> Async.RunSynchronously let root = Path.GetDirectoryName dependenciesFile.FileName - let inline getVersionsF sources resolverStrategy groupName packageName = async { - let! versions = NuGetV2.GetVersions force alternativeProjectRoot root (sources, packageName) - match resolverStrategy with - | ResolverStrategy.Max -> return List.sortDescending versions - | ResolverStrategy.Min -> return List.sort versions } + let inline getVersionsF sources groupName packageName = async { + let! result = NuGetV2.GetVersions force alternativeProjectRoot root (sources, packageName) + return result |> List.toSeq } let dependenciesFile = detectProjectFrameworksForDependenciesFile dependenciesFile diff --git a/src/Paket.Core/PackageAnalysis/FindOutdated.fs b/src/Paket.Core/PackageAnalysis/FindOutdated.fs index b9dcd5a8b8..eb6d10556f 100644 --- a/src/Paket.Core/PackageAnalysis/FindOutdated.fs +++ b/src/Paket.Core/PackageAnalysis/FindOutdated.fs @@ -37,20 +37,17 @@ let FindOutdated strict includingPrereleases groupNameFilter environment = trial let root = Path.GetDirectoryName dependenciesFile.FileName let alternativeProjectRoot = None - let getVersionsF sources resolverStrategy groupName packageName = async { + let getVersionsF sources groupName packageName = async { let! versions = NuGetV2.GetVersions force alternativeProjectRoot root (sources, packageName) - - match resolverStrategy with - | ResolverStrategy.Max -> return List.sortDescending versions |> List.toSeq - | ResolverStrategy.Min -> return List.sort versions |> List.toSeq } - + return versions |> List.toSeq } + let getPreferredVersionsF sources resolverStrategy groupName packageName = [] let dependenciesFile = UpdateProcess.detectProjectFrameworksForDependenciesFile dependenciesFile let checkedDepsGroups = match groupNameFilter with | None -> dependenciesFile.Groups | Some gname -> dependenciesFile.Groups |> Map.filter(fun k g -> k.ToString() = gname) - let newResolution = dependenciesFile.Resolve(force, getSha1, getVersionsF, NuGetV2.GetPackageDetails alternativeProjectRoot root true, RuntimeGraph.getRuntimeGraphFromNugetCache root, checkedDepsGroups, PackageResolver.UpdateMode.UpdateAll) + let newResolution = dependenciesFile.Resolve(force, getSha1, getVersionsF, getPreferredVersionsF, NuGetV2.GetPackageDetails alternativeProjectRoot root true, RuntimeGraph.getRuntimeGraphFromNugetCache root, checkedDepsGroups, PackageResolver.UpdateMode.UpdateAll) let checkedLockGroups = match groupNameFilter with diff --git a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs index 384503bd54..d314c6f427 100644 --- a/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs +++ b/src/Paket.Core/PaketConfigFiles/DependenciesFile.fs @@ -207,7 +207,7 @@ type DependenciesFile(fileName,groups:Map, textRepr try self.GetPackage (groupName,name) |> Some with _ -> None - member this.Resolve(force, getSha1, getVersionF, getPackageDetailsF, getPackageRuntimeGraph, groupsToResolve:Map, updateMode) = + member this.Resolve(force, getSha1, getVersionF, getPreferredVersionF, getPackageDetailsF, getPackageRuntimeGraph, groupsToResolve:Map, updateMode) = let resolveGroup groupName _ = let group = this.GetGroup groupName @@ -245,6 +245,7 @@ type DependenciesFile(fileName,groups:Map, textRepr let resolution = PackageResolver.Resolve( getVersionF, + getPreferredVersionF, getPackageDetailsF, groupName, group.Options.ResolverStrategyForDirectDependencies, @@ -328,6 +329,7 @@ type DependenciesFile(fileName,groups:Map, textRepr let runtimeResolution = PackageResolver.Resolve( getVersionF, + getPreferredVersionF, getPackageDetailsF, groupName, group.Options.ResolverStrategyForDirectDependencies, diff --git a/src/Paket/Paket.fsproj b/src/Paket/Paket.fsproj index 913a1c7bf8..c6069d9f40 100644 --- a/src/Paket/Paket.fsproj +++ b/src/Paket/Paket.fsproj @@ -30,8 +30,8 @@ Project paket.exe Project - restore - C:\temp\PaketRepro + auto-restore on + C:\PROJ\Yaaf\Paket\integrationtests\scenarios\i001835-auto-restore-on-twice\temp true diff --git a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs index 5bf3f2939c..e60c0f11c6 100644 --- a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs +++ b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs @@ -9,7 +9,7 @@ open Paket.PackageResolver let resolve graph updateMode (cfg : DependenciesFile) = let groups = [Constants.MainDependencyGroup, None ] |> Map.ofSeq - cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph,PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() + cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph, (fun _ _ _ _ -> []),PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() let graph1 = GraphOfNuspecs [ diff --git a/tests/Paket.Tests/Resolver/GlobalOptimisticStrategySpecs.fs b/tests/Paket.Tests/Resolver/GlobalOptimisticStrategySpecs.fs index 5a6521bd79..dd83cc0375 100644 --- a/tests/Paket.Tests/Resolver/GlobalOptimisticStrategySpecs.fs +++ b/tests/Paket.Tests/Resolver/GlobalOptimisticStrategySpecs.fs @@ -9,7 +9,7 @@ open Paket.PackageResolver let resolve graph updateMode (cfg : DependenciesFile) = let groups = [Constants.MainDependencyGroup, None ] |> Map.ofSeq - cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph,PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() + cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph, (fun _ _ _ _ -> []),PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() let graph = OfSimpleGraph [ diff --git a/tests/Paket.Tests/Resolver/GlobalPessimisticStrategySpecs.fs b/tests/Paket.Tests/Resolver/GlobalPessimisticStrategySpecs.fs index 43c489c4f0..bf0b047c23 100644 --- a/tests/Paket.Tests/Resolver/GlobalPessimisticStrategySpecs.fs +++ b/tests/Paket.Tests/Resolver/GlobalPessimisticStrategySpecs.fs @@ -9,7 +9,7 @@ open Paket.PackageResolver let resolve graph updateMode (cfg : DependenciesFile) = let groups = [Constants.MainDependencyGroup, None ] |> Map.ofSeq - cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph,PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() + cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph, (fun _ _ _ _ -> []),PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() let graph = OfSimpleGraph [ diff --git a/tests/Paket.Tests/Resolver/StrategySpecs.fs b/tests/Paket.Tests/Resolver/StrategySpecs.fs index 5796227756..8be2e207d8 100644 --- a/tests/Paket.Tests/Resolver/StrategySpecs.fs +++ b/tests/Paket.Tests/Resolver/StrategySpecs.fs @@ -9,7 +9,7 @@ open Paket.PackageResolver let resolve graph updateMode (cfg : DependenciesFile) = let groups = [Constants.MainDependencyGroup, None ] |> Map.ofSeq - cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph,PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() + cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph, (fun _ _ _ _ -> []),PackageDetailsFromGraph graph,(fun _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail() let graph = OfSimpleGraph [ diff --git a/tests/Paket.Tests/TestHelpers.fs b/tests/Paket.Tests/TestHelpers.fs index 368ea38c0f..0e2087b655 100644 --- a/tests/Paket.Tests/TestHelpers.fs +++ b/tests/Paket.Tests/TestHelpers.fs @@ -63,17 +63,14 @@ let PackageDetailsFromGraph (graph : DependencyGraph) sources groupName (package DirectDependencies = Set.ofList dependencies } |> async.Return -let VersionsFromGraph (graph : DependencyGraph) sources resolverStrategy groupName packageName = +let VersionsFromGraph (graph : DependencyGraph) sources groupName packageName = let versions = graph |> Seq.filter (fun (p, _, _, _) -> (PackageName p) = packageName) |> Seq.map (fun (_, v, _, _) -> SemVer.Parse v) - |> Seq.toList - |> List.map (fun v -> v,sources) + |> Seq.map (fun v -> v,sources) - match resolverStrategy with - | ResolverStrategy.Max -> List.sortDescending versions - | ResolverStrategy.Min -> List.sort versions + versions |> async.Return let GetRuntimeGraphFromGraph (graph : DependencyGraph) groupName (package:ResolvedPackage) = @@ -86,9 +83,8 @@ let GetRuntimeGraphFromGraph (graph : DependencyGraph) groupName (package:Resolv |> Some -let VersionsFromGraphAsSeq (graph : DependencyGraph) sources resolverStrategy groupName packageName = - VersionsFromGraph graph sources resolverStrategy groupName packageName - |> fun a -> async.Bind(a, Seq.ofList >> async.Return) +let VersionsFromGraphAsSeq (graph : DependencyGraph) sources groupName packageName = + VersionsFromGraph graph sources groupName packageName let safeResolve graph (dependencies : (string * VersionRange) list) = let sources = [ PackageSource.NuGetV2Source "" ] @@ -105,13 +101,13 @@ let safeResolve graph (dependencies : (string * VersionRange) list) = ResolverStrategyForTransitives = Some ResolverStrategy.Max }) |> Set.ofList - PackageResolver.Resolve(VersionsFromGraphAsSeq graph, PackageDetailsFromGraph graph, Constants.MainDependencyGroup, None, None, ExplicitRestriction FrameworkRestriction.NoRestriction, packages, UpdateMode.UpdateAll) + PackageResolver.Resolve(VersionsFromGraphAsSeq graph, (fun _ _ _ _ -> []), PackageDetailsFromGraph graph, Constants.MainDependencyGroup, None, None, ExplicitRestriction FrameworkRestriction.NoRestriction, packages, UpdateMode.UpdateAll) let resolve graph dependencies = (safeResolve graph dependencies).GetModelOrFail() let ResolveWithGraphR(dependenciesFile:DependenciesFile,getSha1,getVersionsF, getPackageDetailsF, getRuntimeGraph) = let groups = [Constants.MainDependencyGroup, None ] |> Map.ofSeq - dependenciesFile.Resolve(true,getSha1,getVersionsF,getPackageDetailsF,getRuntimeGraph,groups,UpdateMode.UpdateAll) + dependenciesFile.Resolve(true,getSha1,getVersionsF,(fun _ _ _ _ -> []),getPackageDetailsF,getRuntimeGraph,groups,UpdateMode.UpdateAll) let ResolveWithGraph(dependenciesFile:DependenciesFile,getSha1,getVersionsF, getPackageDetailsF) = ResolveWithGraphR(dependenciesFile,getSha1,getVersionsF, getPackageDetailsF, (fun _ _ -> None)) From d7d39f897562e6f0c138daaf74636cd82e4fa9ef Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 03:13:01 +0200 Subject: [PATCH 34/47] let the user overwrite restriction globally --- .../FrameworkRestrictionsSpecs.fs | 12 +- .../Dependencies/PackageResolver.fs | 21 ++- tests/Paket.Tests/Paket.Tests.fsproj | 1 + .../DependencyGroupsAndRestrictions.fs | 138 +++++++++++++++++- .../Resolver/ResolverRestrictionTests.fs | 2 + 5 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 tests/Paket.Tests/Resolver/ResolverRestrictionTests.fs diff --git a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs index 8ce40974a3..6c31d1731b 100644 --- a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs @@ -70,9 +70,15 @@ let ``#1215 framework dependencies propagate``() = [] let ``#1232 framework dependencies propagate``() = let lockFile = update "i001232-sql-lite" - lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "System.Data.SQLite.Core"].Settings.FrameworkRestrictions - |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V4))) + let restriction = + lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "System.Data.SQLite.Core"].Settings.FrameworkRestrictions + |> getExplicitRestriction + (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4), DotNetFramework(FrameworkVersion.V4_5))).IsSubsetOf restriction + |> shouldEqual true + (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V4_5), DotNetFramework(FrameworkVersion.V4_5_1))).IsSubsetOf restriction + |> shouldEqual true + (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_6))).IsSubsetOf restriction + |> shouldEqual true [] let ``#1494 detect platform 5.0``() = diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 371193dbb3..2878e45388 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -331,11 +331,28 @@ let private updateRestrictions (pkgConfig:PackageConfig) (package:ResolvedPackag then FrameworkRestriction.NoRestriction else + // Setting in the dependencies file + let globalPackageSettings = + match pkgConfig.RootSettings.TryGetValue package.Name with + | true, s -> + match s.FrameworkRestrictions with + | ExplicitRestriction r -> r + | _ -> FrameworkRestriction.NoRestriction + | _ -> FrameworkRestriction.NoRestriction + // Settings required for the current resolution let packageSettings = package.Settings.FrameworkRestrictions |> getExplicitRestriction + // Settings required for this current dependency let dependencySettings = pkgConfig.Dependency.Settings.FrameworkRestrictions |> getExplicitRestriction + // Settings defined globally let globalSettings = pkgConfig.GlobalRestrictions |> getExplicitRestriction - [packageSettings;dependencySettings;globalSettings] - |> Seq.fold (FrameworkRestriction.combineRestrictionsWithAnd) FrameworkRestriction.NoRestriction + let isRequired = + FrameworkRestriction.Or + [ packageSettings + FrameworkRestriction.And [dependencySettings;globalSettings]] + + // We assume the user knows what he is doing + FrameworkRestriction.And [ globalPackageSettings;isRequired ] + { package with Settings = { package.Settings with FrameworkRestrictions = ExplicitRestriction newRestrictions } diff --git a/tests/Paket.Tests/Paket.Tests.fsproj b/tests/Paket.Tests/Paket.Tests.fsproj index 59f9adb493..44d6737181 100644 --- a/tests/Paket.Tests/Paket.Tests.fsproj +++ b/tests/Paket.Tests/Paket.Tests.fsproj @@ -199,6 +199,7 @@ + diff --git a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs index e60c0f11c6..4003bfe774 100644 --- a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs +++ b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs @@ -6,6 +6,7 @@ open FsUnit open TestHelpers open Paket.Domain open Paket.PackageResolver +open Paket.Requirements let resolve graph updateMode (cfg : DependenciesFile) = let groups = [Constants.MainDependencyGroup, None ] |> Map.ofSeq @@ -300,4 +301,139 @@ nuget Chessie""" (Requirements.getExplicitRestriction netStandard.Settings.FrameworkRestrictions, (TargetProfile.SinglePlatform (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4_6_3))) |> shouldEqual false - // This also tests that "UnknownPackage" is not pulled unexpectedly (because this dependency is never relevant) \ No newline at end of file + // This also tests that "UnknownPackage" is not pulled unexpectedly (because this dependency is never relevant) + + + +let graph7 = + GraphOfNuspecs [ + """ + + + Nancy.Serialization.JsonNet + 1.4.1 + Andreas Håkansson, Steven Robbins and contributors + Andreas Håkansson, Steven Robbins and contributors + https://github.com/NancyFx/Nancy.Serialization.JsonNet/blob/master/license.txt + http://nancyfx.org + http://nancyfx.org/nancy-nuget.png + false + Provides JSON (de)serialization support using Newtonsoft.JsonNet. + Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. + Andreas Håkansson, Steven Robbins and contributors + en-US + Nancy Json JsonNet + + + + + + + """ + """ + + + Newtonsoft.Json + 10.0.2 + Json.NET + James Newton-King + James Newton-King + false + https://raw.github.com/JamesNK/Newtonsoft.Json/master/LICENSE.md + http://www.newtonsoft.com/json + http://www.newtonsoft.com/content/images/nugeticon.png + Json.NET is a popular high-performance JSON framework for .NET + en-US + json + + + + + + + + + + + + + + + + + + + + + + + + + """ + """ + + + Nancy + 1.4.3 + Andreas Håkansson, Steven Robbins and contributors + Andreas Håkansson, Steven Robbins and contributors + https://github.com/NancyFx/Nancy/blob/master/license.txt + http://nancyfx.org + http://nancyfx.org/nancy-nuget.png + false + Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. + Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. + Andreas Håkansson, Steven Robbins and contributors + en-US + Nancy + + + """ ] + +[] +let ``i001213 should not delegate restriction of transitive when globally no restriction is given``() = + let config = """ +framework: >= net40 + +source https://nuget.org/api/v2 + +nuget Newtonsoft.Json redirects: on +nuget Nancy.Serialization.JsonNet ~> 1.2 framework: >= net451""" + let resolved = + DependenciesFile.FromSource(config) + |> resolve graph7 UpdateMode.UpdateAll + let newtonsoft = resolved.[PackageName "Newtonsoft.Json"] + let nancy = resolved.[PackageName "Nancy.Serialization.JsonNet"] + getVersion newtonsoft |> shouldEqual "10.0.2" + getVersion nancy |> shouldEqual "1.4.1" + + (FrameworkRestriction.AtLeast (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4)).IsSubsetOf + (Requirements.getExplicitRestriction newtonsoft.Settings.FrameworkRestrictions) + |> shouldEqual true + + // install netstandard to net40 + Requirements.isTargetMatchingRestrictions + (Requirements.getExplicitRestriction newtonsoft.Settings.FrameworkRestrictions, + (TargetProfile.SinglePlatform (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4))) + |> shouldEqual true +[] +let ``i001213 should delegate restriction of transitive when package is not given``() = + let config = """ +framework: >= net40 + +source https://nuget.org/api/v2 + +nuget Nancy.Serialization.JsonNet ~> 1.2 framework: >= net451""" + let resolved = + DependenciesFile.FromSource(config) + |> resolve graph7 UpdateMode.UpdateAll + let newtonsoft = resolved.[PackageName "Newtonsoft.Json"] + let nancy = resolved.[PackageName "Nancy.Serialization.JsonNet"] + getVersion newtonsoft |> shouldEqual "10.0.2" + getVersion nancy |> shouldEqual "1.4.1" + + // don't install newtonsoft to net40, because restriction should be propagated. + Requirements.isTargetMatchingRestrictions + (Requirements.getExplicitRestriction newtonsoft.Settings.FrameworkRestrictions, + (TargetProfile.SinglePlatform (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4))) + |> shouldEqual false \ No newline at end of file diff --git a/tests/Paket.Tests/Resolver/ResolverRestrictionTests.fs b/tests/Paket.Tests/Resolver/ResolverRestrictionTests.fs new file mode 100644 index 0000000000..60714bf653 --- /dev/null +++ b/tests/Paket.Tests/Resolver/ResolverRestrictionTests.fs @@ -0,0 +1,2 @@ +module ResolverRestrictionTests + From e5fe35141235023740944cd0599a3cb9d77486f1 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 11:39:16 +0200 Subject: [PATCH 35/47] fix some tests and a bug in the simplifier. --- .../FrameworkRestrictionsSpecs.fs | 2 +- .../MyClassLibrary.csprojtemplate | 2 +- .../MyClassLibrary.csprojtemplate | 2 +- .../MyClassLibrary.csprojtemplate | 2 +- .../MyClassLibrary.csprojtemplate | 2 +- .../MyClassLibrary.csprojtemplate | 2 +- .../MyClassLibrary2.csprojtemplate | 2 +- .../MyClassLibrary.csprojtemplate | 2 +- .../ConsoleApplication1.fsprojtemplate | 18 +-- src/Paket.Core/Versioning/Requirements.fs | 4 +- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 19 ++++ .../DependencyGroupsAndRestrictions.fs | 106 +++++++++++++++++- .../Versioning/FrameworkRestrictionTests.fs | 9 ++ 13 files changed, 152 insertions(+), 20 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs index 6c31d1731b..c569fdb079 100644 --- a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs @@ -15,7 +15,7 @@ let ``#140 windsor should resolve framework dependent dependencies``() = let lockFile = update "i000140-resolve-framework-restrictions" lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "TaskParallelLibrary"].Settings.FrameworkRestrictions |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.Exactly(DotNetFramework(FrameworkVersion.V3_5))) + |> shouldEqual (FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V3_5), DotNetFramework(FrameworkVersion.V4))) [] let ``#1182 framework restrictions overwrite each other``() = diff --git a/integrationtests/scenarios/i001145-excludes/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001145-excludes/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate index 168a732d47..400212ae02 100644 --- a/integrationtests/scenarios/i001145-excludes/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i001145-excludes/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -62,7 +62,7 @@ - + ..\..\packages\Dapper\lib\net40\Dapper.dll diff --git a/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate index 1a20be9070..f73653c2e1 100644 --- a/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -62,7 +62,7 @@ - + ..\..\packages\Dapper\lib\net40\Dapper.dll diff --git a/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary.csprojtemplate index d7878977ed..12b9a45723 100644 --- a/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary.csprojtemplate @@ -282,7 +282,7 @@ - + ..\..\packages\Dapper\lib\net40\Dapper.dll diff --git a/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary3/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary3/MyClassLibrary.csprojtemplate index cd3e3a1ded..1cab8d97a5 100644 --- a/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary3/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i001219-props-files/before/MyClassLibrary/MyClassLibrary3/MyClassLibrary.csprojtemplate @@ -282,7 +282,7 @@ - + ..\..\packages\Dapper\lib\net40\Dapper.dll diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate index 4eecdc10f7..15f4fc9b27 100644 --- a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -76,7 +76,7 @@ - + ..\..\packages\AlphaFS\lib\net40\AlphaFS.dll diff --git a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary2.csprojtemplate b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary2.csprojtemplate index 4eecdc10f7..15f4fc9b27 100644 --- a/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary2.csprojtemplate +++ b/integrationtests/scenarios/i001270-force-redirects/before/MyClassLibrary/MyClassLibrary2/MyClassLibrary2.csprojtemplate @@ -76,7 +76,7 @@ - + ..\..\packages\AlphaFS\lib\net40\AlphaFS.dll diff --git a/integrationtests/scenarios/i001270-net461/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001270-net461/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate index 197efe975c..6fb3d8bc09 100644 --- a/integrationtests/scenarios/i001270-net461/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i001270-net461/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -64,7 +64,7 @@ - + True diff --git a/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate b/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate index 42282c2618..070551e0d8 100644 --- a/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate +++ b/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate @@ -80,7 +80,7 @@ - + ..\packages\FSharp.Core\lib\net40\FSharp.Core.dll @@ -136,7 +136,7 @@ - + True @@ -177,7 +177,7 @@ - + ..\packages\Microsoft.Azure.KeyVault.Core\lib\net40\Microsoft.Azure.KeyVault.Core.dll @@ -197,7 +197,7 @@ - + ..\packages\Microsoft.Data.Edm\lib\net40\Microsoft.Data.Edm.dll @@ -217,7 +217,7 @@ - + ..\packages\Microsoft.Data.OData\lib\net40\Microsoft.Data.OData.dll @@ -237,7 +237,7 @@ - + ..\packages\Microsoft.Data.Services.Client\lib\net40\Microsoft.Data.Services.Client.dll @@ -248,7 +248,7 @@ - + ..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll @@ -286,7 +286,7 @@ - + ..\packages\System.Spatial\lib\net40\System.Spatial.dll @@ -306,7 +306,7 @@ - + True diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index fcf1f33a58..7a907c74ee 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -317,7 +317,7 @@ module FrameworkRestriction = let rec removeNegatedLiteralsWhichOccurSinglePositive (fr:FrameworkRestriction) = let positiveSingles = fr.OrFormulas - |> List.choose (fun andFormular -> match andFormular.Literals with [ h ] -> Some h | _ -> None) + |> List.choose (fun andFormular -> match andFormular.Literals with [ { IsNegated = false } as h ] -> Some h | _ -> None) let workDone, reworked = fr.OrFormulas |> List.fold (fun (workDone, reworkedOrFormulas) andFormula -> @@ -615,7 +615,7 @@ let parseRestrictions failImmediatly (text:string) = let operands, next = parseOperand [] next if operands.Length = 0 then failwithf "Operand '%s' without argument is invalid in '%s'" (h.Substring (0, 2)) text let f, def = if isAnd then FrameworkRestriction.And, FrameworkRestriction.NoRestriction else FrameworkRestriction.Or, FrameworkRestriction.EmptySet - operands |> List.fold (fun a b -> f [a;b]) def, next + operands |> f, next | h when h.StartsWith "NOT" -> let next = h.Substring 2 diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index c4597358d8..a8cb5f17df 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -940,3 +940,22 @@ let ``should parse lock file with spaces in file names``() = OperatingSystemRestriction = None PackagePath = None AuthKey = Some "secret" } ] + + +let lockFileWithNewRestrictions = """NUGET + remote: http://www.nuget.org/api/v2 + MathNet.Numerics (3.2.3) + TaskParallelLibrary (>= 1.0.2856) - restriction: && (>= net35) (< net40) + MathNet.Numerics.FSharp (3.2.3) + MathNet.Numerics (3.2.3) + TaskParallelLibrary (1.0.2856) - restriction: && (>= net35) (< net40)""" + +[] +let ``should parse new restrictions && (>= net35) (< net40)``() = + let lockFile = LockFileParser.Parse (toLines lockFileWithNewRestrictions) + let main = lockFile.Head + let packages = lockFile.Tail + + LockFileSerializer.serializePackages main.Options (main.Packages |> List.map (fun p -> p.Name,p) |> Map.ofList) + |> normalizeLineEndings + |> shouldEqual (normalizeLineEndings lockFileWithNewRestrictions) diff --git a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs index 4003bfe774..22502d58ec 100644 --- a/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs +++ b/tests/Paket.Tests/Resolver/DependencyGroupsAndRestrictions.fs @@ -436,4 +436,108 @@ nuget Nancy.Serialization.JsonNet ~> 1.2 framework: >= net451""" Requirements.isTargetMatchingRestrictions (Requirements.getExplicitRestriction newtonsoft.Settings.FrameworkRestrictions, (TargetProfile.SinglePlatform (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4))) - |> shouldEqual false \ No newline at end of file + |> shouldEqual false + + + + +let graph8 = + GraphOfNuspecs [ + """ + + + MathNet.Numerics.FSharp + 3.2.3 + Math.NET Numerics for F# + Christoph Ruegg, Marcus Cuda, Jurgen Van Gael + Christoph Ruegg, Marcus Cuda, Jurgen Van Gael + http://numerics.mathdotnet.com/docs/License.html + http://numerics.mathdotnet.com/ + http://www.mathdotnet.com/images/MathNet128.png + false + Math.NET Numerics is the numerical foundation of the Math.NET project, aiming to provide methods and algorithms for numerical computations in science, engineering and every day use. Supports F# 3.0 on .Net 4.0, .Net 3.5 and Mono on Windows, Linux and Mac; Silverlight 5, WindowsPhone/SL 8, WindowsPhone 8.1 and Windows 8 with PCL Portable Profiles 47 and 328; Android/iOS with Xamarin. + F# Modules for Math.NET Numerics, providing methods and algorithms for numerical computations in science, engineering and every day use. + Bug fix: MatrixNormal distribution: density for non-square matrices ~Evelina Gabasova + fsharp F# math numeric statistics probability integration interpolation regression solve fit linear algebra matrix fft + + + + + + + + + """ + """ + + + MathNet.Numerics + 3.2.3 + Math.NET Numerics + Christoph Ruegg, Marcus Cuda, Jurgen Van Gael + Christoph Ruegg, Marcus Cuda, Jurgen Van Gael + http://numerics.mathdotnet.com/docs/License.html + http://numerics.mathdotnet.com/ + http://www.mathdotnet.com/images/MathNet128.png + false + Math.NET Numerics is the numerical foundation of the Math.NET project, aiming to provide methods and algorithms for numerical computations in science, engineering and every day use. Supports .Net 4.0, .Net 3.5 and Mono on Windows, Linux and Mac; Silverlight 5, WindowsPhone/SL 8, WindowsPhone 8.1 and Windows 8 with PCL Portable Profiles 47 and 328; Android/iOS with Xamarin. + Math.NET Numerics, providing methods and algorithms for numerical computations in science, engineering and every day use. + Bug fix: MatrixNormal distribution: density for non-square matrices ~Evelina Gabasova + math numeric statistics probability integration interpolation regression solve fit linear algebra matrix fft + + + + + + + + + + + + """ + """ + + + 1.0.2856.0 + Microsoft Corporation + Microsoft Corporation + http://go.microsoft.com/fwlink/?LinkID=186234 + http://msdn.microsoft.com/en-us/library/dd460717.aspx + http://i.msdn.microsoft.com/ee402630.NET_lg.png + TaskParallelLibrary + Task Parallel Library for .NET 3.5 + true + The package includes: +* Task<T> for executing asynchronous operations. +* Concurrent Collections such as ConcurrentStack, ConcurentQueue ad ConcurrentDictionary. +* PLINQ for writing parallel queries. +* additional Threading operations such as Barrier,SpinLock and SpinWait. + A complete and official Microsoft backport of the Task Parallel Library (TPL) for .NET 3.5. + This backport was shipped with the Reactive Extensions (Rx) library up until v1.0.2856.0. It can be downloaded from http://www.microsoft.com/download/en/details.aspx?id=24940 . + en-us + tpl plinq pfx task parallel extensions .net35 backport + + + """ + ] + +[] +let ``i000140 should properly resolve framework dependent dependencies``() = + let config = """ +source https://nuget.org/api/v2 + +nuget MathNet.Numerics.FSharp ~> 3.2.1""" + let resolved = + DependenciesFile.FromSource(config) + |> resolve graph8 UpdateMode.UpdateAll + let tpl = resolved.[PackageName "TaskParallelLibrary"] + let numeric = resolved.[PackageName "MathNet.Numerics"] + getVersion numeric |> shouldEqual "3.2.3" + getVersion tpl |> shouldEqual "1.0.2856.0" + + // don't install tpl to net40, because restriction should be propagated. + Requirements.isTargetMatchingRestrictions + (Requirements.getExplicitRestriction tpl.Settings.FrameworkRestrictions, + (TargetProfile.SinglePlatform (FrameworkIdentifier.DotNetFramework FrameworkVersion.V4))) + |> shouldEqual false diff --git a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs index c3fe5a237a..b8a0deafae 100644 --- a/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs +++ b/tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs @@ -5,6 +5,15 @@ open FsUnit open NUnit.Framework open Paket.Requirements +[] +let ``Simplify && (true) (< net45)`` () = + let toSimplify = + (FrameworkRestriction.And[ + FrameworkRestriction.NoRestriction + FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_5)]) + toSimplify + |> shouldEqual (FrameworkRestriction.NotAtLeast (DotNetFramework FrameworkVersion.V4_5)) + [] let ``IsSubset works for unknown Portables`` () = let p = PlatformMatching.forceExtractPlatforms "portable-net45+win8+wp8+wp81+wpa81" From 4a4090c175ba164d7d632083a31df9bc7150f91c Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 12:36:52 +0200 Subject: [PATCH 36/47] improve performance output --- src/Paket.Core/Common/Profile.fs | 8 ++- src/Paket.Core/Common/Utils.fs | 5 +- .../Dependencies/PackageResolver.fs | 4 +- src/Paket/Program.fs | 50 +++++++++++++++---- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/Paket.Core/Common/Profile.fs b/src/Paket.Core/Common/Profile.fs index b85e0ff484..64b343e356 100644 --- a/src/Paket.Core/Common/Profile.fs +++ b/src/Paket.Core/Common/Profile.fs @@ -20,8 +20,12 @@ let events = let startCategory cat = let cw = Stopwatch.StartNew() - - { new System.IDisposable with member x.Dispose () = cw.Stop(); events.Add({ Category = cat; Duration = cw.Elapsed }) } + let mutable wasDisposed = false + { new System.IDisposable with + member x.Dispose () = + if not wasDisposed then + wasDisposed <- true + cw.Stop(); events.Add({ Category = cat; Duration = cw.Elapsed }) } let startCategoryF cat f = let cw = Stopwatch.StartNew() diff --git a/src/Paket.Core/Common/Utils.fs b/src/Paket.Core/Common/Utils.fs index 08b1f35f0c..c85371bdf7 100644 --- a/src/Paket.Core/Common/Utils.fs +++ b/src/Paket.Core/Common/Utils.fs @@ -70,12 +70,15 @@ let TimeSpanToReadableString(span:TimeSpan) = let hours = notZero (span.Duration().Hours) <| String.Format("{0:0} hour{1}, ", span.Hours, pluralize span.Hours) let minutes = notZero (span.Duration().Minutes) <| String.Format("{0:0} minute{1}, ", span.Minutes, pluralize span.Minutes) let seconds = notZero (span.Duration().Seconds) <| String.Format("{0:0} second{1}", span.Seconds, pluralize span.Seconds) + let milliseconds = notZero (span.Duration().Milliseconds) <| String.Format("{0:0} millisecond{1}", span.Milliseconds, pluralize span.Milliseconds) let formatted = String.Format("{0}{1}{2}{3}", days, hours, minutes, seconds) let formatted = if formatted.EndsWith ", " then formatted.Substring(0, formatted.Length - 2) else formatted - if String.IsNullOrEmpty formatted then "0 seconds" else formatted + if not (String.IsNullOrEmpty formatted) then formatted + elif not (String.IsNullOrEmpty milliseconds) then milliseconds + else "0 milliseconds" let GetHomeDirectory() = #if DOTNETCORE diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index 2878e45388..f444d3ab8f 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -656,7 +656,9 @@ let Resolve (getVersionsRaw, getPreferredVersionsRaw, getPackageDetailsRaw, grou |> Async.StartAsTask) let getPackageDetailsBlock sources groupName packageName semVer = use d = Profile.startCategory (Profile.Category.ResolverAlgorithmBlocked Profile.BlockReason.PackageDetails) - (startRequestGetPackageDetails sources groupName packageName semVer).GetAwaiter().GetResult() + let result = (startRequestGetPackageDetails sources groupName packageName semVer).GetAwaiter().GetResult() + d.Dispose() + result let startedGetVersionsRequests = System.Collections.Concurrent.ConcurrentDictionary<_,System.Threading.Tasks.Task<_>>() diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index 802f80cfb9..356c80be6b 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -40,24 +40,56 @@ let processWithValidation silent validateF commandF (result : ParseResults<'T>) sw.Stop() if not silent then let realTime = sw.Elapsed - let results = + let groupedResults = Profile.events |> Seq.groupBy (fun (ev) -> ev.Category) |> Seq.map (fun (cat, group) -> - cat, group |> Seq.map (fun ev -> ev.Duration) |> Seq.fold (+) (TimeSpan())) + let l = group |> Seq.toList + cat, l.Length, l |> Seq.map (fun ev -> ev.Duration) |> Seq.fold (+) (TimeSpan())) |> Seq.toList let blocked = - results - |> List.filter (function Profile.Category.ResolverAlgorithmBlocked _, _ -> true | _ -> false) - |> Seq.map snd + groupedResults + |> List.filter (function Profile.Category.ResolverAlgorithmBlocked _, _, _ -> true | _ -> false) + |> Seq.map (fun (_,_,t) -> t) |> Seq.fold (+) (TimeSpan()) let resolver = - match results |> List.tryPick (function Profile.Category.ResolverAlgorithm, s -> Some s | _ -> None) with + match groupedResults |> List.tryPick (function Profile.Category.ResolverAlgorithm, _, s -> Some s | _ -> None) with | Some s -> s | None -> TimeSpan() - tracefn "%s - Resolver (plain)." (Utils.TimeSpanToReadableString (resolver - blocked)) - for (cat, elapsed) in results do tracefn "%s - %A." (Utils.TimeSpanToReadableString elapsed) cat - tracefn "%s - ready." (Utils.TimeSpanToReadableString realTime) + tracefn "Performance:" + groupedResults + |> List.sortBy (fun (cat,_,_) -> + match cat with + | Profile.Category.ResolverAlgorithm -> 1 + | Profile.Category.ResolverAlgorithmBlocked b -> 2 + | Profile.Category.FileIO -> 3 + | Profile.Category.NuGetDownload -> 4 + | Profile.Category.NuGetRequest -> 5 + | Profile.Category.Other -> 6) + |> List.iter (fun (cat, num, elapsed) -> + match cat with + | Profile.Category.ResolverAlgorithm -> + tracefn " - Resolver: %s (%d runs)" (Utils.TimeSpanToReadableString elapsed) num + tracefn " - Runtime : %s" (Utils.TimeSpanToReadableString (resolver - blocked)) + | Profile.Category.ResolverAlgorithmBlocked b -> + let reason = + match b with + | Profile.BlockReason.PackageDetails -> "retrieving package details" + | Profile.BlockReason.GetVersion -> "retrieving package versions" + tracefn " - Blocked (%s): %s" reason (Utils.TimeSpanToReadableString elapsed) + | Profile.Category.FileIO -> + tracefn " - Disk IO: %s" (Utils.TimeSpanToReadableString elapsed) + | Profile.Category.NuGetDownload -> + let avg = TimeSpan.FromTicks(elapsed.Ticks / int64 num) + tracefn " - Average Download Time: %s" (Utils.TimeSpanToReadableString avg) + | Profile.Category.NuGetRequest -> + let avg = TimeSpan.FromTicks(elapsed.Ticks / int64 num) + tracefn " - Average Request Time: %s" (Utils.TimeSpanToReadableString avg) + | Profile.Category.Other -> + tracefn " - Other: %s" (Utils.TimeSpanToReadableString elapsed) + ) + + tracefn " - Runtime: %s" (Utils.TimeSpanToReadableString realTime) let processCommand silent commandF result = processWithValidation silent (fun _ -> true) commandF result From 306e06d48fa7615bf7da92822efb3a6f2131850f Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 13:50:09 +0200 Subject: [PATCH 37/47] more performance data & fix test --- .../UpdatePackageSpecs.fs | 4 +-- src/Paket/Program.fs | 17 +++++++++--- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 27 +++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs b/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs index 33d5340f5a..6effa1c446 100644 --- a/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/UpdatePackageSpecs.fs @@ -87,12 +87,12 @@ let ``#1117 can understand portable``() = let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001117-aws","paket.lock")) let restrictions = lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "PCLStorage"].Settings.FrameworkRestrictions match restrictions with - | ExplicitRestriction l -> l.ToString() |> shouldEqual ("[portable-net45+win8+wp8+wpa81]") + | ExplicitRestriction l -> l.ToString() |> shouldEqual ("&& (< net45) (>= portable-net45+win8+wp8+wpa81)") | _ -> failwith "wrong" let restrictions = lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "Microsoft.Bcl.Async"].Settings.FrameworkRestrictions match restrictions with - | ExplicitRestriction l -> l.ToString() |> shouldEqual ("[portable-net45+win8+wp8+wpa81]") + | ExplicitRestriction l -> l.ToString() |> shouldEqual ("&& (< portable-net45+monoandroid+monotouch+xamarinios+xamarinmac+win8+wp8+wpa81) (>= portable-net45+win8+wp8+wpa81)") | _ -> failwith "wrong" [] diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index 356c80be6b..018f4b193e 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -47,10 +47,12 @@ let processWithValidation silent validateF commandF (result : ParseResults<'T>) let l = group |> Seq.toList cat, l.Length, l |> Seq.map (fun ev -> ev.Duration) |> Seq.fold (+) (TimeSpan())) |> Seq.toList - let blocked = + let blockedRaw = groupedResults |> List.filter (function Profile.Category.ResolverAlgorithmBlocked _, _, _ -> true | _ -> false) - |> Seq.map (fun (_,_,t) -> t) + let blocked = + blockedRaw + |> List.map (fun (_,_,t) -> t) |> Seq.fold (+) (TimeSpan()) let resolver = match groupedResults |> List.tryPick (function Profile.Category.ResolverAlgorithm, _, s -> Some s | _ -> None) with @@ -70,21 +72,28 @@ let processWithValidation silent validateF commandF (result : ParseResults<'T>) match cat with | Profile.Category.ResolverAlgorithm -> tracefn " - Resolver: %s (%d runs)" (Utils.TimeSpanToReadableString elapsed) num - tracefn " - Runtime : %s" (Utils.TimeSpanToReadableString (resolver - blocked)) + let realTime = resolver - blocked + tracefn " - Runtime: %s" (Utils.TimeSpanToReadableString realTime) + let blockNum = blockedRaw |> Seq.sumBy (fun (_, num, _) -> num) + let blockPaket4 = TimeSpan.FromMilliseconds(500.0 * float blockNum) + tracefn " - Runtime Paket 4 (estimated ~500ms respose*): %s" (Utils.TimeSpanToReadableString (realTime + blockPaket4)) + tracefn " * See http://stats.pingdom.com/aqicaf2upspo/1265300 for average response times." | Profile.Category.ResolverAlgorithmBlocked b -> let reason = match b with | Profile.BlockReason.PackageDetails -> "retrieving package details" | Profile.BlockReason.GetVersion -> "retrieving package versions" - tracefn " - Blocked (%s): %s" reason (Utils.TimeSpanToReadableString elapsed) + tracefn " - Blocked (%s): %s (%d times)" reason (Utils.TimeSpanToReadableString elapsed) num | Profile.Category.FileIO -> tracefn " - Disk IO: %s" (Utils.TimeSpanToReadableString elapsed) | Profile.Category.NuGetDownload -> let avg = TimeSpan.FromTicks(elapsed.Ticks / int64 num) tracefn " - Average Download Time: %s" (Utils.TimeSpanToReadableString avg) + tracefn " - Number of downloads: %d" num | Profile.Category.NuGetRequest -> let avg = TimeSpan.FromTicks(elapsed.Ticks / int64 num) tracefn " - Average Request Time: %s" (Utils.TimeSpanToReadableString avg) + tracefn " - Number of Requests: %d" num | Profile.Category.Other -> tracefn " - Other: %s" (Utils.TimeSpanToReadableString elapsed) ) diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index a8cb5f17df..93025a46f5 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -959,3 +959,30 @@ let ``should parse new restrictions && (>= net35) (< net40)``() = LockFileSerializer.serializePackages main.Options (main.Packages |> List.map (fun p -> p.Name,p) |> Map.ofList) |> normalizeLineEndings |> shouldEqual (normalizeLineEndings lockFileWithNewRestrictions) + +let lockFileWithNewComplexRestrictions = """NUGET + remote: http://www.nuget.org/api/v2 + AWSSDK.Core (3.1.5.3) + Microsoft.Net.Http (>= 2.2.29) - restriction: && (< net45) (>= portable-net45+win8+wp8+wpa81) + PCLStorage (>= 1.0.2) - restriction: && (< net45) (>= portable-net45+win8+wp8+wpa81) + Microsoft.Bcl (1.1.10) - restriction: || (&& (< net45) (>= portable-net45+win8+wp8+wpa81)) (&& (< portable-net45+monoandroid+monotouch+xamarinios+xamarinmac+win8+wp8+wpa81) (>= portable-net45+win8+wp8+wpa81)) + Microsoft.Bcl.Build (>= 1.0.14) + Microsoft.Bcl.Async (1.0.168) - restriction: && (< portable-net45+monoandroid+monotouch+xamarinios+xamarinmac+win8+wp8+wpa81) (>= portable-net45+win8+wp8+wpa81) + Microsoft.Bcl (>= 1.1.8) + Microsoft.Bcl.Build (1.0.21) - import_targets: false, restriction: && (< net45) (>= portable-net45+win8+wp8+wpa81) + Microsoft.Net.Http (2.2.29) - restriction: && (< net45) (>= portable-net45+win8+wp8+wpa81) + Microsoft.Bcl (>= 1.1.10) + Microsoft.Bcl.Build (>= 1.0.14) + PCLStorage (1.0.2) - restriction: && (< net45) (>= portable-net45+win8+wp8+wpa81) + Microsoft.Bcl (>= 1.1.6) - restriction: < portable-net45+monoandroid+monotouch+xamarinios+xamarinmac+win8+wp8+wpa81 + Microsoft.Bcl.Async (>= 1.0.165) - restriction: < portable-net45+monoandroid+monotouch+xamarinios+xamarinmac+win8+wp8+wpa81""" + +[] +let ``should parse new restrictions || (&& (< net45) (>= portable-net45+win8+wp8+wpa81)) (&& (< portable-net45+monoandroid+monotouch+xamarinios+xamarinmac+win8+wp8+wpa81) (>= portable-net45+win8+wp8+wpa81))``() = + let lockFile = LockFileParser.Parse (toLines lockFileWithNewComplexRestrictions) + let main = lockFile.Head + let packages = lockFile.Tail + + LockFileSerializer.serializePackages main.Options (main.Packages |> List.map (fun p -> p.Name,p) |> Map.ofList) + |> normalizeLineEndings + |> shouldEqual (normalizeLineEndings lockFileWithNewComplexRestrictions) From 9dd533662191ffa4c374a09914742e6f68c59fba Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 13:50:34 +0200 Subject: [PATCH 38/47] another test fixed --- .../ConsoleApplication1.fsprojtemplate | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate b/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate index 070551e0d8..965dc7f76f 100644 --- a/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate +++ b/integrationtests/scenarios/i001333-dup-refs/before/ConsoleApplication1/ConsoleApplication1.fsprojtemplate @@ -89,16 +89,7 @@ - - - - ..\packages\FSharp.Core\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll - True - True - - - - + ..\packages\FSharp.Core\lib\portable-net45+netcore45\FSharp.Core.dll @@ -116,7 +107,7 @@ - + ..\packages\FSharp.Core\lib\portable-net45+netcore45+wpa81+wp8\FSharp.Core.dll @@ -157,7 +148,7 @@ - + ..\packages\FSharp.Data\lib\portable-net45+netcore45+wpa81+wp8\FSharp.Data.dll @@ -186,7 +177,7 @@ - + ..\packages\Microsoft.Azure.KeyVault.Core\lib\portable-net45+wp8+wpa81+win\Microsoft.Azure.KeyVault.Core.dll @@ -206,7 +197,7 @@ - + ..\packages\Microsoft.Data.Edm\lib\portable-net45+wp8+win8+wpa\Microsoft.Data.Edm.dll @@ -226,7 +217,7 @@ - + ..\packages\Microsoft.Data.OData\lib\portable-net45+wp8+win8+wpa\Microsoft.Data.OData.dll @@ -266,7 +257,7 @@ - + ..\packages\Newtonsoft.Json\lib\netstandard1.0\Newtonsoft.Json.dll @@ -295,7 +286,7 @@ - + ..\packages\System.Spatial\lib\portable-net45+wp8+win8+wpa\System.Spatial.dll @@ -351,7 +342,7 @@ - + True @@ -368,7 +359,7 @@ - + ..\packages\Zlib.Portable\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch+MonoAndroid\Zlib.Portable.dll From 09220ea9d276aa049c406f077414d90254f87d0c Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 14:16:11 +0200 Subject: [PATCH 39/47] fix a parser bug and another test --- .../ConsoleApplication1.vcxprojtemplate | 6 ++--- .../TestPaketDotNet.csprojtemplate | 4 ++-- src/Paket.Core/PaketConfigFiles/LockFile.fs | 23 ++++++++++--------- tests/Paket.Tests/Lockfile/ParserSpecs.fs | 21 +++++++++++++++++ 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/integrationtests/scenarios/i001467-cpp/before/MyClassLibrary/ConsoleApplication1/ConsoleApplication1.vcxprojtemplate b/integrationtests/scenarios/i001467-cpp/before/MyClassLibrary/ConsoleApplication1/ConsoleApplication1.vcxprojtemplate index 15bd38f125..be36d7a5b2 100644 --- a/integrationtests/scenarios/i001467-cpp/before/MyClassLibrary/ConsoleApplication1/ConsoleApplication1.vcxprojtemplate +++ b/integrationtests/scenarios/i001467-cpp/before/MyClassLibrary/ConsoleApplication1/ConsoleApplication1.vcxprojtemplate @@ -119,7 +119,7 @@ - + ..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll @@ -137,7 +137,7 @@ - + ..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll @@ -146,7 +146,7 @@ - + ..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll diff --git a/integrationtests/scenarios/i001578-transitive-ref/before/TestPaketDotNet/TestPaketDotNet.csprojtemplate b/integrationtests/scenarios/i001578-transitive-ref/before/TestPaketDotNet/TestPaketDotNet.csprojtemplate index 7c044282de..6d73c4ef24 100644 --- a/integrationtests/scenarios/i001578-transitive-ref/before/TestPaketDotNet/TestPaketDotNet.csprojtemplate +++ b/integrationtests/scenarios/i001578-transitive-ref/before/TestPaketDotNet/TestPaketDotNet.csprojtemplate @@ -113,7 +113,7 @@ - + ..\packages\Octokit\lib\netcore451\Octokit.dll @@ -122,7 +122,7 @@ - + ..\packages\Octokit\lib\portable-net45+wp80+win+wpa81\Octokit.dll diff --git a/src/Paket.Core/PaketConfigFiles/LockFile.fs b/src/Paket.Core/PaketConfigFiles/LockFile.fs index 9869eaed47..fa41bb1dc9 100644 --- a/src/Paket.Core/PaketConfigFiles/LockFile.fs +++ b/src/Paket.Core/PaketConfigFiles/LockFile.fs @@ -314,28 +314,29 @@ module LockFileParser = | _, String.RemovePrefix "os: " trimmed -> InstallOption(OperatingSystemRestriction trimmed) | _, trimmed when line.StartsWith " " -> + let pos = trimmed.IndexOf " - " + let namePart, settingsPart = + if pos >= 0 then + trimmed.Substring(0, pos), trimmed.Substring (pos + 3) + else + trimmed, "" let frameworkSettings = - if trimmed.Contains " - " then - let pos = trimmed.LastIndexOf " - " + if not (String.IsNullOrEmpty settingsPart) then try - InstallSettings.Parse(trimmed.Substring(pos + 3)) + InstallSettings.Parse(settingsPart) with - | _ -> InstallSettings.Parse("framework: " + trimmed.Substring(pos + 3)) // backwards compatible + | _ -> InstallSettings.Parse("framework: " + settingsPart) // backwards compatible else InstallSettings.Default - if trimmed.Contains "(" then - let parts = trimmed.Split '(' + if namePart.Contains "(" then + let parts = namePart.Split '(' let first = parts.[0] let rest = String.Join ("(", parts |> Seq.skip 1) let versionEndPos = rest.IndexOf(")") if versionEndPos < 0 then failwithf "Missing matching ') in line '%s'" line NugetDependency (parts.[0].Trim(),rest.Substring(0, versionEndPos).Trim(),frameworkSettings) else - if trimmed.Contains(" -") then - let pos = trimmed.IndexOf(" -") - NugetDependency (trimmed.Substring(0,pos),">= 0",frameworkSettings) - else - NugetDependency (trimmed,">= 0",frameworkSettings) + NugetDependency (namePart.Trim(),">= 0",frameworkSettings) | Some "NUGET", trimmed -> NugetPackage trimmed | Some "GITHUB", trimmed -> SourceFile(GitHubLink, trimmed) | Some "GIST", trimmed -> SourceFile(GistLink, trimmed) diff --git a/tests/Paket.Tests/Lockfile/ParserSpecs.fs b/tests/Paket.Tests/Lockfile/ParserSpecs.fs index 93025a46f5..b6d678cd13 100644 --- a/tests/Paket.Tests/Lockfile/ParserSpecs.fs +++ b/tests/Paket.Tests/Lockfile/ParserSpecs.fs @@ -986,3 +986,24 @@ let ``should parse new restrictions || (&& (< net45) (>= portable-net45+win8+wp8 LockFileSerializer.serializePackages main.Options (main.Packages |> List.map (fun p -> p.Name,p) |> Map.ofList) |> normalizeLineEndings |> shouldEqual (normalizeLineEndings lockFileWithNewComplexRestrictions) + +let lockFileWithMissingVersion = """NUGET + remote: https://www.nuget.org/api/v2 + Microsoft.Bcl (1.1.10) - restriction: || (== net10) (== net11) (== net20) (== net30) (== net35) (== net40) + Microsoft.Bcl.Build (>= 1.0.14) + Microsoft.Bcl.Build (1.0.21) - import_targets: false, restriction: || (== net10) (== net11) (== net20) (== net30) (== net35) (== net40) + Microsoft.Net.Http (2.2.29) - restriction: || (== net10) (== net11) (== net20) (== net30) (== net35) (== net40) + Microsoft.Bcl (>= 1.1.10) + Microsoft.Bcl.Build (>= 1.0.14) + Octokit (0.19) + Microsoft.Net.Http - restriction: || (== net10) (== net11) (== net20) (== net30) (== net35) (== net40)""" + +[] +let ``should parse lockfile with missing version``() = + let lockFile = LockFileParser.Parse (toLines lockFileWithMissingVersion) + let main = lockFile.Head + let packages = lockFile.Tail + + LockFileSerializer.serializePackages main.Options (main.Packages |> List.map (fun p -> p.Name,p) |> Map.ofList) + |> normalizeLineEndings + |> shouldEqual (normalizeLineEndings lockFileWithMissingVersion) \ No newline at end of file From dfbd10420cef8b4d2d9e54b03fbe827f104eebf0 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 14:21:58 +0200 Subject: [PATCH 40/47] another test --- .../MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrationtests/scenarios/i001732-lowercase-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i001732-lowercase-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate index cb43b7b0d2..8773240f20 100644 --- a/integrationtests/scenarios/i001732-lowercase-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i001732-lowercase-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -62,7 +62,7 @@ - + ..\..\packages\Dapper\lib\net40\Dapper.dll From 364a5f4ff2a0fcb47f57830d129b67b82ac8ac81 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 14:51:23 +0200 Subject: [PATCH 41/47] Fix Stackoverflows in DEBUG mode by increasing the Stack-Size (in a new Thread). --- src/Paket.Core/Dependencies/PackageResolver.fs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index f444d3ab8f..a262e603e7 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -963,7 +963,22 @@ let Resolve (getVersionsRaw, getPreferredVersionsRaw, getPackageDetailsRaw, grou UnlistedSearch = false } - match step (Step((currentConflict,startingStep,currentRequirement),[])) stackpack Seq.empty flags with + let inline calculate () = step (Step((currentConflict,startingStep,currentRequirement),[])) stackpack Seq.empty flags +#if DEBUG + let mutable results = None + // Increase stack size, because we have no tail-call-elimination + let thread = new System.Threading.Thread((fun () -> + results <- Some (calculate()) + ), 1024 * 1024 * 100) + thread.Name <- sprintf "Paket Resolver Thread (Debug) - %O" (System.Guid.NewGuid()) + thread.Start(); + thread.Join(); + let stepResult = results.Value +#else + let stepResult = calculate() +#endif + + match stepResult with | { Status = Resolution.Conflict _ } as conflict -> if conflict.TryRelaxed then stackpack.KnownConflicts.Clear() From cb2f0ee9d3fd1c8e255a60878afb7f05a126d018 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 17:43:14 +0200 Subject: [PATCH 42/47] fix tests --- .../FrameworkRestrictionsSpecs.fs | 2 +- .../MyClassLibrary.csprojtemplate | 2 +- .../MyClassLibrary.csprojtemplate | 197 +++++++++++------- 3 files changed, 123 insertions(+), 78 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs index c569fdb079..c5df0125d7 100644 --- a/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/FrameworkRestrictionsSpecs.fs @@ -31,7 +31,7 @@ let ``#1190 paket add nuget should handle transitive dependencies``() = let lockFile = LockFile.LoadFrom(Path.Combine(scenarioTempPath "i001190-transitive-dependencies-with-restr","paket.lock")) lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "xunit.abstractions"].Settings.FrameworkRestrictions |> getExplicitRestriction - |> shouldEqual (FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))) + |> fun res -> res.ToString() |> shouldEqual "|| (>= dnx451) (>= dnxcore50) (>= portable-net45+win8+wp8+wpa81)" [] let ``#1190 paket add nuget should handle transitive dependencies with restrictions``() = diff --git a/integrationtests/scenarios/i000346-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i000346-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate index cb43b7b0d2..8773240f20 100644 --- a/integrationtests/scenarios/i000346-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i000346-aliases/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -62,7 +62,7 @@ - + ..\..\packages\Dapper\lib\net40\Dapper.dll diff --git a/integrationtests/scenarios/i002335-razorengine/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate b/integrationtests/scenarios/i002335-razorengine/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate index 48fbab50a0..ea303a1e1f 100644 --- a/integrationtests/scenarios/i002335-razorengine/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate +++ b/integrationtests/scenarios/i002335-razorengine/before/MyClassLibrary/MyClassLibrary/MyClassLibrary.csprojtemplate @@ -396,7 +396,7 @@ - + ..\..\packages\razor4\Microsoft.AspNetCore.Razor\lib\netstandard1.3\Microsoft.AspNetCore.Razor.dll @@ -419,7 +419,7 @@ - + ..\..\packages\razor4\Microsoft.Win32.Primitives\ref\netstandard1.3\Microsoft.Win32.Primitives.dll @@ -469,7 +469,7 @@ - + ..\..\packages\razor4\System.AppContext\ref\netstandard\_._ @@ -492,7 +492,7 @@ - + ..\..\packages\razor4\System.AppContext\lib\netstandard1.6\System.AppContext.dll @@ -503,7 +503,7 @@ - + ..\..\packages\razor4\System.Buffers\lib\netstandard1.1\System.Buffers.dll @@ -514,7 +514,7 @@ - + ..\..\packages\razor4\System.Collections\ref\netstandard1.3\System.Collections.dll @@ -530,7 +530,7 @@ - + ..\..\packages\razor4\System.Collections.Concurrent\lib\netstandard1.3\System.Collections.Concurrent.dll @@ -539,7 +539,7 @@ - + ..\..\packages\razor4\System.Collections.Concurrent\ref\netstandard1.3\System.Collections.Concurrent.dll @@ -573,7 +573,7 @@ - + ..\..\packages\razor4\System.Console\ref\netstandard1.3\System.Console.dll @@ -589,7 +589,7 @@ - + ..\..\packages\razor4\System.Diagnostics.Debug\ref\netstandard1.3\System.Diagnostics.Debug.dll @@ -623,7 +623,7 @@ - + ..\..\packages\razor4\System.Diagnostics.DiagnosticSource\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll @@ -634,7 +634,7 @@ - + ..\..\packages\razor4\System.Diagnostics.Tools\ref\netstandard1.0\System.Diagnostics.Tools.dll @@ -682,7 +682,7 @@ - + ..\..\packages\razor4\System.Diagnostics.Tracing\ref\netstandard1.5\System.Diagnostics.Tracing.dll @@ -698,7 +698,7 @@ - + ..\..\packages\razor4\System.Globalization\ref\netstandard1.3\System.Globalization.dll @@ -732,7 +732,7 @@ - + ..\..\packages\razor4\System.Globalization.Calendars\ref\netstandard1.3\System.Globalization.Calendars.dll @@ -766,7 +766,7 @@ - + ..\..\packages\razor4\System.Globalization.Extensions\ref\netstandard1.3\System.Globalization.Extensions.dll @@ -814,7 +814,7 @@ - + ..\..\packages\razor4\System.IO\ref\netstandard1.5\System.IO.dll @@ -855,7 +855,7 @@ - + ..\..\packages\razor4\System.IO.Compression\ref\netstandard1.3\System.IO.Compression.dll @@ -892,7 +892,7 @@ - + ..\..\packages\razor4\System.IO.Compression.ZipFile\lib\netstandard1.3\System.IO.Compression.ZipFile.dll @@ -901,7 +901,7 @@ - + ..\..\packages\razor4\System.IO.Compression.ZipFile\ref\netstandard1.3\System.IO.Compression.ZipFile.dll @@ -935,7 +935,7 @@ - + ..\..\packages\razor4\System.IO.FileSystem\ref\netstandard1.3\System.IO.FileSystem.dll @@ -969,7 +969,7 @@ - + ..\..\packages\razor4\System.IO.FileSystem.Primitives\lib\netstandard1.3\System.IO.FileSystem.Primitives.dll @@ -978,7 +978,7 @@ - + ..\..\packages\razor4\System.IO.FileSystem.Primitives\ref\netstandard1.3\System.IO.FileSystem.Primitives.dll @@ -1026,7 +1026,7 @@ - + ..\..\packages\razor4\System.Linq\lib\netstandard1.6\System.Linq.dll @@ -1035,7 +1035,7 @@ - + ..\..\packages\razor4\System.Linq\ref\netstandard1.6\System.Linq.dll @@ -1083,7 +1083,7 @@ - + ..\..\packages\razor4\System.Linq.Expressions\lib\netstandard1.6\System.Linq.Expressions.dll @@ -1092,7 +1092,7 @@ - + ..\..\packages\razor4\System.Linq.Expressions\ref\netstandard1.6\System.Linq.Expressions.dll @@ -1133,7 +1133,7 @@ - + ..\..\packages\razor4\System.Net.Http\ref\netstandard1.3\System.Net.Http.dll @@ -1144,7 +1144,7 @@ - + ..\..\packages\razor4\System.Net.Primitives\ref\netstandard1.3\System.Net.Primitives.dll @@ -1178,7 +1178,7 @@ - + ..\..\packages\razor4\System.Net.Sockets\ref\netstandard1.3\System.Net.Sockets.dll @@ -1194,7 +1194,7 @@ - + ..\..\packages\razor4\System.ObjectModel\lib\netstandard1.3\System.ObjectModel.dll @@ -1203,7 +1203,7 @@ - + ..\..\packages\razor4\System.ObjectModel\ref\netstandard1.3\System.ObjectModel.dll @@ -1251,7 +1251,7 @@ - + ..\..\packages\razor4\System.Reflection\ref\netstandard1.5\System.Reflection.dll @@ -1267,7 +1267,7 @@ - + ..\..\packages\razor4\System.Reflection.Emit\ref\netstandard1.1\System.Reflection.Emit.dll @@ -1281,7 +1281,7 @@ - + ..\..\packages\razor4\System.Reflection.Emit\lib\netstandard1.3\System.Reflection.Emit.dll @@ -1292,7 +1292,7 @@ - + ..\..\packages\razor4\System.Reflection.Emit.ILGeneration\ref\netstandard1.0\System.Reflection.Emit.ILGeneration.dll @@ -1306,7 +1306,7 @@ - + ..\..\packages\razor4\System.Reflection.Emit.ILGeneration\lib\netstandard1.3\System.Reflection.Emit.ILGeneration.dll @@ -1317,7 +1317,7 @@ - + ..\..\packages\razor4\System.Reflection.Emit.Lightweight\ref\netstandard1.0\System.Reflection.Emit.Lightweight.dll @@ -1331,7 +1331,7 @@ - + ..\..\packages\razor4\System.Reflection.Emit.Lightweight\lib\netstandard1.3\System.Reflection.Emit.Lightweight.dll @@ -1342,7 +1342,7 @@ - + ..\..\packages\razor4\System.Reflection.Extensions\ref\netstandard1.0\System.Reflection.Extensions.dll @@ -1358,7 +1358,7 @@ - + ..\..\packages\razor4\System.Reflection.Primitives\ref\netstandard1.0\System.Reflection.Primitives.dll @@ -1408,7 +1408,7 @@ - + ..\..\packages\razor4\System.Reflection.TypeExtensions\lib\netstandard1.5\System.Reflection.TypeExtensions.dll @@ -1417,7 +1417,7 @@ - + ..\..\packages\razor4\System.Reflection.TypeExtensions\ref\netstandard1.5\System.Reflection.TypeExtensions.dll @@ -1433,7 +1433,7 @@ - + ..\..\packages\razor4\System.Resources.ResourceManager\ref\netstandard1.0\System.Resources.ResourceManager.dll @@ -1491,7 +1491,7 @@ - + ..\..\packages\razor4\System.Runtime\ref\netstandard1.5\System.Runtime.dll @@ -1539,7 +1539,7 @@ - + ..\..\packages\razor4\System.Runtime.Extensions\ref\netstandard1.5\System.Runtime.Extensions.dll @@ -1555,7 +1555,7 @@ - + ..\..\packages\razor4\System.Runtime.Handles\ref\netstandard1.3\System.Runtime.Handles.dll @@ -1605,6 +1605,15 @@ + + + + ..\..\packages\razor4\System.Runtime.InteropServices\ref\netcoreapp1.1\System.Runtime.InteropServices.dll + False + True + + + @@ -1619,7 +1628,7 @@ - + ..\..\packages\razor4\System.Runtime.InteropServices\ref\netstandard1.5\System.Runtime.InteropServices.dll @@ -1644,7 +1653,7 @@ - + ..\..\packages\razor4\System.Runtime.InteropServices.RuntimeInformation\lib\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll @@ -1653,7 +1662,7 @@ - + ..\..\packages\razor4\System.Runtime.InteropServices.RuntimeInformation\ref\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll @@ -1662,6 +1671,15 @@ + + + + ..\..\packages\razor4\System.Runtime.InteropServices.RuntimeInformation\lib\wpa81\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + @@ -1671,7 +1689,7 @@ - + ..\..\packages\razor4\System.Runtime.Numerics\ref\netstandard1.1\System.Runtime.Numerics.dll @@ -1685,7 +1703,7 @@ - + ..\..\packages\razor4\System.Runtime.Numerics\lib\netstandard1.3\System.Runtime.Numerics.dll @@ -1764,7 +1782,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.Algorithms\ref\netstandard1.6\System.Security.Cryptography.Algorithms.dll @@ -1825,7 +1843,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.Cng\ref\netstandard1.6\System.Security.Cryptography.Cng.dll @@ -1854,7 +1872,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.Csp\ref\netstandard1.3\System.Security.Cryptography.Csp.dll @@ -1883,7 +1901,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.Encoding\ref\netstandard1.3\System.Security.Cryptography.Encoding.dll @@ -1899,7 +1917,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.OpenSsl\lib\netstandard1.6\System.Security.Cryptography.OpenSsl.dll @@ -1908,7 +1926,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.OpenSsl\ref\netstandard1.6\System.Security.Cryptography.OpenSsl.dll @@ -1937,7 +1955,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.Primitives\lib\netstandard1.3\System.Security.Cryptography.Primitives.dll @@ -1946,7 +1964,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.Primitives\ref\netstandard1.3\System.Security.Cryptography.Primitives.dll @@ -2005,7 +2023,7 @@ - + ..\..\packages\razor4\System.Security.Cryptography.X509Certificates\ref\netstandard1.4\System.Security.Cryptography.X509Certificates.dll @@ -2021,7 +2039,7 @@ - + ..\..\packages\razor4\System.Text.Encoding\ref\netstandard1.3\System.Text.Encoding.dll @@ -2037,7 +2055,7 @@ - + ..\..\packages\razor4\System.Text.Encoding.Extensions\ref\netstandard1.3\System.Text.Encoding.Extensions.dll @@ -2071,6 +2089,15 @@ + + + + ..\..\packages\razor4\System.Text.RegularExpressions\ref\netcoreapp1.1\System.Text.RegularExpressions.dll + False + True + + + @@ -2085,7 +2112,7 @@ - + ..\..\packages\razor4\System.Text.RegularExpressions\lib\netstandard1.6\System.Text.RegularExpressions.dll @@ -2094,7 +2121,7 @@ - + ..\..\packages\razor4\System.Text.RegularExpressions\ref\netstandard1.6\System.Text.RegularExpressions.dll @@ -2110,7 +2137,7 @@ - + ..\..\packages\razor4\System.Threading\lib\netstandard1.3\System.Threading.dll @@ -2119,7 +2146,7 @@ - + ..\..\packages\razor4\System.Threading\ref\netstandard1.3\System.Threading.dll @@ -2135,7 +2162,7 @@ - + ..\..\packages\razor4\System.Threading.Tasks\ref\netstandard1.3\System.Threading.Tasks.dll @@ -2151,7 +2178,7 @@ - + ..\..\packages\razor4\System.Threading.Tasks.Extensions\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll @@ -2162,7 +2189,25 @@ - + + + + True + + + + + + + + + ..\..\packages\razor4\System.Threading.Thread\lib\net46\System.Threading.Thread.dll + True + True + + + + ..\..\packages\razor4\System.Threading.Thread\lib\netstandard1.3\System.Threading.Thread.dll @@ -2171,7 +2216,7 @@ - + ..\..\packages\razor4\System.Threading.Thread\ref\netstandard1.3\System.Threading.Thread.dll @@ -2187,7 +2232,7 @@ - + ..\..\packages\razor4\System.Threading.Timer\ref\netstandard1.2\System.Threading.Timer.dll @@ -2231,7 +2276,7 @@ - + ..\..\packages\razor4\System.Xml.ReaderWriter\lib\netstandard1.3\System.Xml.ReaderWriter.dll @@ -2240,7 +2285,7 @@ - + ..\..\packages\razor4\System.Xml.ReaderWriter\ref\netstandard1.3\System.Xml.ReaderWriter.dll @@ -2263,7 +2308,7 @@ - + ..\..\packages\razor4\System.Xml.XDocument\lib\netstandard1.3\System.Xml.XDocument.dll @@ -2272,7 +2317,7 @@ - + ..\..\packages\razor4\System.Xml.XDocument\ref\netstandard1.3\System.Xml.XDocument.dll From ea40687281029ada850a7f5ef6d72b38a6c03743 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 18:57:18 +0200 Subject: [PATCH 43/47] add warning when something is not working as it should and fix caching. --- src/Paket.Core/Dependencies/NuGetV2.fs | 18 ++++-- src/Paket.Core/Dependencies/NuGetV3.fs | 3 +- src/Paket.Core/Dependencies/Nuget.fs | 56 +++++++++++++++---- .../Dependencies/PackageResolver.fs | 17 +++++- src/Paket.Core/Versioning/Requirements.fs | 6 ++ src/Paket/Paket.fsproj | 4 +- 6 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/Paket.Core/Dependencies/NuGetV2.fs b/src/Paket.Core/Dependencies/NuGetV2.fs index d416666154..8446b99fd0 100644 --- a/src/Paket.Core/Dependencies/NuGetV2.fs +++ b/src/Paket.Core/Dependencies/NuGetV2.fs @@ -208,13 +208,13 @@ let parseODataDetails(url,nugetURL,packageName:PackageName,version:SemVerInfo,ra { PackageName = officialName DownloadUrl = downloadLink - Dependencies = dependencies + SerializedDependencies = [] SourceUrl = nugetURL CacheVersion = NuGetPackageCache.CurrentCacheVersion LicenseUrl = licenseUrl Version = (SemVer.Parse v).Normalize() Unlisted = publishDate = Constants.MagicUnlistingDate } - + |> NuGet.NuGetPackageCache.withDependencies dependencies let getDetailsFromNuGetViaODataFast auth nugetURL (packageName:PackageName) (version:SemVerInfo) = async { @@ -267,7 +267,7 @@ let getDetailsFromNuGetViaOData auth nugetURL (packageName:PackageName) (version async { try let! result = getDetailsFromNuGetViaODataFast auth nugetURL packageName version - if urlSimilarToTfsOrVsts nugetURL && result.Dependencies.IsEmpty then + if urlSimilarToTfsOrVsts nugetURL && result |> NuGet.NuGetPackageCache.getDependencies |> List.isEmpty then // TODO: There is a bug in VSTS, so we can't trust this protocol. Remvoe when VSTS is fixed // TODO: TFS has the same bug return! queryPackagesProtocol packageName @@ -368,12 +368,13 @@ let getDetailsFromLocalNuGetPackage isCache alternativeProjectRoot root localNuG return { PackageName = nuspec.OfficialName DownloadUrl = packageName.ToString() - Dependencies = nuspec.Dependencies + SerializedDependencies = [] SourceUrl = di.FullName CacheVersion = NuGetPackageCache.CurrentCacheVersion LicenseUrl = nuspec.LicenseUrl Version = version.Normalize() Unlisted = isCache } + |> NuGet.NuGetPackageCache.withDependencies nuspec.Dependencies } @@ -762,14 +763,19 @@ let rec private getPackageDetails alternativeProjectRoot root force (sources:Pac DownloadLink = encodeURL nugetObject.DownloadUrl Unlisted = nugetObject.Unlisted LicenseUrl = nugetObject.LicenseUrl - DirectDependencies = nugetObject.Dependencies |> Set.ofList } } + DirectDependencies = NuGet.NuGetPackageCache.getDependencies nugetObject |> Set.ofList } } let rec GetPackageDetails alternativeProjectRoot root force (sources:PackageSource list) groupName packageName (version:SemVerInfo) : Async = async { try return! getPackageDetails alternativeProjectRoot root force sources packageName version with - | _ -> return! getPackageDetails alternativeProjectRoot root true sources packageName version + | exn -> + if verbose then + traceWarnfn "GetPackageDetails failed: %O" exn + else + traceWarnfn "Something failed in GetPackageDetails, trying again with force: %s" exn.Message + return! getPackageDetails alternativeProjectRoot root true sources packageName version } let protocolCache = System.Collections.Concurrent.ConcurrentDictionary<_,_>() diff --git a/src/Paket.Core/Dependencies/NuGetV3.fs b/src/Paket.Core/Dependencies/NuGetV3.fs index e073f400d1..be5d7af049 100644 --- a/src/Paket.Core/Dependencies/NuGetV3.fs +++ b/src/Paket.Core/Dependencies/NuGetV3.fs @@ -257,7 +257,7 @@ let getPackageDetails (source:NugetV3Source) (packageName:PackageName) (version: let optimized = dependencies |> List.map (fun (m,v,r) -> m,v, ExplicitRestriction r) return - { Dependencies = optimized + { SerializedDependencies = [] PackageName = packageName.ToString() SourceUrl = source.Url Unlisted = unlisted @@ -265,6 +265,7 @@ let getPackageDetails (source:NugetV3Source) (packageName:PackageName) (version: LicenseUrl = catalogData.LicenseUrl Version = version.Normalize() CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion } + |> NuGet.NuGetPackageCache.withDependencies optimized } let loadFromCacheOrGetDetails (force:bool) diff --git a/src/Paket.Core/Dependencies/Nuget.fs b/src/Paket.Core/Dependencies/Nuget.fs index 28b7a327e3..c38814cac3 100644 --- a/src/Paket.Core/Dependencies/Nuget.fs +++ b/src/Paket.Core/Dependencies/Nuget.fs @@ -44,10 +44,10 @@ module NuGetConfig = if File.ReadAllText(fileName) <> text then File.WriteAllText(fileName,text) - +type FrameworkRestrictionsCache = string type NuGetPackageCache = - { Dependencies : (PackageName * VersionRequirement * FrameworkRestrictions) list + { SerializedDependencies : (PackageName * VersionRequirement * FrameworkRestrictionsCache) list PackageName : string SourceUrl: string Unlisted : bool @@ -58,17 +58,45 @@ type NuGetPackageCache = static member CurrentCacheVersion = "4.0" +module NuGetPackageCache = + let withDependencies (l:(PackageName * VersionRequirement * FrameworkRestrictions) list) d = + { d with + SerializedDependencies = + l + |> List.map (fun (n,v, restrictions) -> + let restrictionString = + match restrictions with + | FrameworkRestrictions.AutoDetectFramework -> "AUTO" + | FrameworkRestrictions.ExplicitRestriction re -> + re.ToString() + n, v, restrictionString) } + let getDependencies (x:NuGetPackageCache) : (PackageName * VersionRequirement * FrameworkRestrictions) list = + x.SerializedDependencies + |> List.map (fun (n,v,restrictionString) -> + let restrictions = + if restrictionString = "AUTO" then + FrameworkRestrictions.AutoDetectFramework + else FrameworkRestrictions.ExplicitRestriction(Requirements.parseRestrictions true restrictionString) + n, v, restrictions) + let inline normalizeUrl(url:string) = url.Replace("https://","http://").Replace("www.","") -let getCacheFileName nugetURL (packageName:PackageName) (version:SemVerInfo) = +let getCacheFiles cacheVersion nugetURL (packageName:PackageName) (version:SemVerInfo) = let h = nugetURL |> normalizeUrl |> hash |> abs + let prefix = + sprintf "%O.%s.s%d" packageName (version.Normalize()) h let packageUrl = - sprintf "%O.%s.s%d.json" - packageName (version.Normalize()) h - FileInfo(Path.Combine(Constants.NuGetCacheFolder,packageUrl)) - + sprintf "%s_v%s.json" + prefix cacheVersion + let newFile = Path.Combine(Constants.NuGetCacheFolder,packageUrl) + let oldFiles = + Directory.EnumerateFiles(Constants.NuGetCacheFolder, sprintf "%s*.json" prefix) + |> Seq.filter (fun p -> Path.GetFileName p <> packageUrl) + |> Seq.toList + FileInfo(newFile), oldFiles let getDetailsFromCacheOr force nugetURL (packageName:PackageName) (version:SemVerInfo) (get : unit -> NuGetPackageCache Async) : NuGetPackageCache Async = - let cacheFile = getCacheFileName nugetURL packageName version + let cacheFile, oldFiles = getCacheFiles NuGetPackageCache.CurrentCacheVersion nugetURL packageName version + oldFiles |> Seq.iter (fun f -> File.Delete f) let get() = async { let! result = get() @@ -81,16 +109,22 @@ let getDetailsFromCacheOr force nugetURL (packageName:PackageName) (version:SemV try let cachedObject = JsonConvert.DeserializeObject json - if (cachedObject.CacheVersion <> NuGetPackageCache.CurrentCacheVersion) || - (PackageName cachedObject.PackageName <> packageName) || + if (PackageName cachedObject.PackageName <> packageName) || (cachedObject.Version <> version.Normalize()) then + traceVerbose (sprintf "Invalidating Cache '%s:%s' <> '%s:%s'" cachedObject.PackageName cachedObject.Version packageName.Name (version.Normalize())) cacheFile.Delete() return! get() else return cachedObject with - | exn -> return! get() + | exn -> + cacheFile.Delete() + if verbose then + traceWarnfn "Error while loading cache: %O" exn + else + traceWarnfn "Error while loading cache: %s" exn.Message + return! get() else return! get() } \ No newline at end of file diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index a262e603e7..e357a4f2bc 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -966,14 +966,25 @@ let Resolve (getVersionsRaw, getPreferredVersionsRaw, getPackageDetailsRaw, grou let inline calculate () = step (Step((currentConflict,startingStep,currentRequirement),[])) stackpack Seq.empty flags #if DEBUG let mutable results = None + let mutable error = None // Increase stack size, because we have no tail-call-elimination let thread = new System.Threading.Thread((fun () -> + try results <- Some (calculate()) + with e -> + // Prevent the application from crashing + error <- Some (System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture e) ), 1024 * 1024 * 100) thread.Name <- sprintf "Paket Resolver Thread (Debug) - %O" (System.Guid.NewGuid()) - thread.Start(); - thread.Join(); - let stepResult = results.Value + thread.Start() + thread.Join() + match error with + | Some e -> e.Throw() + | _ -> () + let stepResult = + match results with + | Some s -> s + | None -> failwithf "Expected to get results from the resolver thread :/." #else let stepResult = calculate() #endif diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index 7a907c74ee..ea239944f8 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -634,6 +634,12 @@ let parseRestrictions failImmediatly (text:string) = negated, next else failwithf "Expected operand after NOT, '%s'" text + | h when h.StartsWith "true" -> + let rest = (h.Substring 4).TrimStart() + FrameworkRestriction.NoRestriction, rest + | h when h.StartsWith "false" -> + let rest = (h.Substring 5).TrimStart() + FrameworkRestriction.EmptySet, rest | _ -> failwithf "Expected operator, but got '%s'" text diff --git a/src/Paket/Paket.fsproj b/src/Paket/Paket.fsproj index c6069d9f40..576d6a05d8 100644 --- a/src/Paket/Paket.fsproj +++ b/src/Paket/Paket.fsproj @@ -30,8 +30,8 @@ Project paket.exe Project - auto-restore on - C:\PROJ\Yaaf\Paket\integrationtests\scenarios\i001835-auto-restore-on-twice\temp + update + C:\PROJ\Yaaf\Paket\integrationtests\scenarios\i002294-pin-netstandard-1-6\temp true From 0ffa1d6ea5c4bc38a5421ccc94b2c685e0953d5d Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 19:14:20 +0200 Subject: [PATCH 44/47] fix test code --- .../Paket.IntegrationTests/PackSpecs.fs | 30 +++++++------ tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 45 +++++++++---------- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/integrationtests/Paket.IntegrationTests/PackSpecs.fs b/integrationtests/Paket.IntegrationTests/PackSpecs.fs index 4103adfb6a..23cbd95df7 100644 --- a/integrationtests/Paket.IntegrationTests/PackSpecs.fs +++ b/integrationtests/Paket.IntegrationTests/PackSpecs.fs @@ -11,6 +11,8 @@ open System.IO.Compression open Paket.Domain open Paket +let getDependencies = Paket.NuGet.NuGetPackageCache.getDependencies + [] let ``#1234 empty assembly name``() = let outPath = Path.Combine(scenarioTempPath "i001234-missing-assemblyname","out") @@ -96,9 +98,9 @@ let ``#1429 pack deps from template``() = NuGetV2.getDetailsFromLocalNuGetPackage false None outPath "" (PackageName "PaketBug") (SemVer.Parse "1.0.0.0") |> Async.RunSynchronously - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldNotContain (PackageName "PaketBug2") // it's not packed in same round - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldNotContain (PackageName "PaketBug") + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldNotContain (PackageName "PaketBug2") // it's not packed in same round + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldNotContain (PackageName "PaketBug") File.Delete(Path.Combine(scenarioTempPath "i001429-pack-deps","PaketBug","paket.template")) @@ -112,9 +114,9 @@ let ``#1429 pack deps``() = NuGetV2.getDetailsFromLocalNuGetPackage false None outPath "" (PackageName "PaketBug") (SemVer.Parse "1.0.0.0") |> Async.RunSynchronously - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "PaketBug2") - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldNotContain (PackageName "PaketBug") + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "PaketBug2") + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldNotContain (PackageName "PaketBug") File.Delete(Path.Combine(scenarioTempPath "i001429-pack-deps","PaketBug","paket.template")) @@ -128,8 +130,8 @@ let ``#1429 pack deps using minimum-from-lock-file``() = NuGetV2.getDetailsFromLocalNuGetPackage false None outPath "" (PackageName "PaketBug") (SemVer.Parse "1.0.0.0") |> Async.RunSynchronously - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") - let packageName, versionRequirement, restrictions = details.Dependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") + let packageName, versionRequirement, restrictions = details |> getDependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head versionRequirement |> shouldNotEqual (VersionRequirement.AllReleases) File.Delete(Path.Combine(scenarioTempPath "i001429-pack-deps-minimum-from-lock","PaketBug","paket.template")) @@ -144,8 +146,8 @@ let ``#1429 pack deps without minimum-from-lock-file uses dependencies file rang NuGetV2.getDetailsFromLocalNuGetPackage false None outPath "" (PackageName "PaketBug") (SemVer.Parse "1.0.0.0") |> Async.RunSynchronously - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") - let packageName, versionRequirement, restrictions = details.Dependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") + let packageName, versionRequirement, restrictions = details |> getDependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head versionRequirement |> shouldEqual (VersionRequirement.Parse "1.2.3") File.Delete(Path.Combine(scenarioTempPath "i001429-pack-deps-minimum-from-lock","PaketBug","paket.template")) @@ -160,8 +162,8 @@ let ``#1429 pack deps without minimum-from-lock-file uses specifc dependencies f NuGetV2.getDetailsFromLocalNuGetPackage false None outPath "" (PackageName "PaketBug") (SemVer.Parse "1.0.0.0") |> Async.RunSynchronously - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") - let packageName, versionRequirement, restrictions = details.Dependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") + let packageName, versionRequirement, restrictions = details |> getDependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head versionRequirement |> shouldEqual (VersionRequirement.Parse "[2.3.4]") File.Delete(Path.Combine(scenarioTempPath "i001429-pack-deps-specific","PaketBug","paket.template")) @@ -176,8 +178,8 @@ let ``#1429 pack deps with minimum-from-lock-file uses specifc dependencies file NuGetV2.getDetailsFromLocalNuGetPackage false None outPath "" (PackageName "PaketBug") (SemVer.Parse "1.0.0.0") |> Async.RunSynchronously - details.Dependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") - let packageName, versionRequirement, restrictions = details.Dependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head + details |> getDependencies |> List.map (fun (x,_,_) -> x) |> shouldContain (PackageName "MySql.Data") + let packageName, versionRequirement, restrictions = details |> getDependencies |> List.filter (fun (x,_,_) -> x = PackageName "MySql.Data") |> List.head versionRequirement |> shouldEqual (VersionRequirement.Parse "[2.3.4]") File.Delete(Path.Combine(scenarioTempPath "i001429-pack-deps-specific","PaketBug","paket.template")) diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index d19d67fbc8..2ebf0ab3f7 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -23,7 +23,7 @@ let ``can detect explicit dependencies for Fantomas``() = |> shouldEqual { PackageName = "Fantomas" DownloadUrl = "http://www.nuget.org/api/v2/package/Fantomas/1.6.0" - Dependencies = [PackageName "FSharp.Compiler.Service",DependenciesFileParser.parseVersionRequirement(">= 0.0.73"), makeOrList []] + SerializedDependencies = [PackageName "FSharp.Compiler.Service",DependenciesFileParser.parseVersionRequirement(">= 0.0.73"), "true"] Unlisted = false LicenseUrl = "http://github.com/dungpa/fantomas/blob/master/LICENSE.md" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion @@ -36,9 +36,9 @@ let ``can detect explicit dependencies for Rx-PlaformServices``() = |> shouldEqual { PackageName = "Rx-PlatformServices" DownloadUrl = "https://www.nuget.org/api/v2/package/Rx-PlatformServices/2.3.0" - Dependencies = - [PackageName "Rx-Interfaces",DependenciesFileParser.parseVersionRequirement(">= 2.2"), makeOrList [] - PackageName "Rx-Core",DependenciesFileParser.parseVersionRequirement(">= 2.2"), makeOrList []] + SerializedDependencies = + [PackageName "Rx-Interfaces",DependenciesFileParser.parseVersionRequirement(">= 2.2"), "true" + PackageName "Rx-Core",DependenciesFileParser.parseVersionRequirement(">= 2.2"), "true"] Unlisted = true LicenseUrl = "http://go.microsoft.com/fwlink/?LinkID=261272" Version = "2.3.0" @@ -51,8 +51,8 @@ let ``can detect explicit dependencies for EasyNetQ``() = |> shouldEqual { PackageName = "EasyNetQ" DownloadUrl = "https://www.nuget.org/api/v2/package/EasyNetQ/0.40.3.352" - Dependencies = - [PackageName "RabbitMQ.Client",DependenciesFileParser.parseVersionRequirement(">= 3.4.3"),makeOrList []] + SerializedDependencies = + [PackageName "RabbitMQ.Client",DependenciesFileParser.parseVersionRequirement(">= 3.4.3"),"true"] Unlisted = false LicenseUrl = "https://github.com/mikehadlow/EasyNetQ/blob/master/licence.txt" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion @@ -69,11 +69,11 @@ let ``can detect explicit dependencies for Fleece``() = CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion LicenseUrl = "https://raw.github.com/mausch/Fleece/master/LICENSE" Version = "0.4.0" - Dependencies = - [PackageName "FSharpPlus",DependenciesFileParser.parseVersionRequirement(">= 0.0.4"),makeOrList [] - PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"),makeOrList [] - PackageName "ReadOnlyCollectionExtensions",DependenciesFileParser.parseVersionRequirement(">= 1.2.0"),makeOrList [] - PackageName "System.Json",DependenciesFileParser.parseVersionRequirement(">= 4.0.20126.16343"),makeOrList []] + SerializedDependencies = + [PackageName "FSharpPlus",DependenciesFileParser.parseVersionRequirement(">= 0.0.4"),"true" + PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"),"true" + PackageName "ReadOnlyCollectionExtensions",DependenciesFileParser.parseVersionRequirement(">= 1.2.0"),"true" + PackageName "System.Json",DependenciesFileParser.parseVersionRequirement(">= 4.0.20126.16343"),"true"] SourceUrl = fakeUrl } [] @@ -87,12 +87,9 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() = CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion LicenseUrl = "https://github.com/mausch/ReadOnlyCollections/blob/master/license.txt" Version = "1.2.0" - Dependencies = - [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"), - makeOrList [FrameworkRestriction.Between (DotNetFramework(FrameworkVersion.V2), DotNetFramework(FrameworkVersion.V3_5))] - PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), - makeOrList - [FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V2))]] + SerializedDependencies = + [PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"), "&& (>= net20) (< net35)" + PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), ">= net20"] SourceUrl = fakeUrl } [] @@ -105,13 +102,13 @@ let ``can detect explicit dependencies for Math.Numerics``() = Version = "3.3.0" LicenseUrl = "http://numerics.mathdotnet.com/docs/License.html" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion - Dependencies = - [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), makeOrList [FrameworkRestriction.Between(DotNetFramework(FrameworkVersion.V3_5), DotNetFramework(FrameworkVersion.V4))]] + SerializedDependencies = + [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), "&& (>= net35) (< net4)" ] SourceUrl = fakeUrl } [] let ``can detect explicit dependencies for Math.Numerics.FSharp``() = - (parse "NuGetOData/Math.Numerics.FSharp.xml").Dependencies |> Seq.head + (parse "NuGetOData/Math.Numerics.FSharp.xml")|> NuGet.NuGetPackageCache.getDependencies |> Seq.head |> shouldEqual (PackageName "MathNet.Numerics", DependenciesFileParser.parseVersionRequirement("3.3.0"),makeOrList []) @@ -126,7 +123,7 @@ let ``can detect explicit dependencies for Microsoft.AspNet.WebApi.Client``() = let odata = parse "NuGetOData/Microsoft.AspNet.WebApi.Client.xml" odata.PackageName |> shouldEqual "Microsoft.AspNet.WebApi.Client" odata.DownloadUrl |> shouldEqual"https://www.nuget.org/api/v2/package/Microsoft.AspNet.WebApi.Client/5.2.3" - let dependencies = odata.Dependencies |> Array.ofList + let dependencies = odata|> NuGet.NuGetPackageCache.getDependencies |> Array.ofList dependencies.[0] |> shouldEqual (PackageName "Newtonsoft.Json", DependenciesFileParser.parseVersionRequirement(">= 6.0.4"), makeOrList [getPortableRestriction("portable-net45+win8+wp8+wp81+wpa81"); FrameworkRestriction.AtLeast(DotNetFramework(FrameworkVersion.V4_5))]) @@ -140,7 +137,7 @@ let ``can detect explicit dependencies for WindowsAzure.Storage``() = let odata = parse "NuGetOData/WindowsAzure.Storage.xml" odata.PackageName |> shouldEqual "WindowsAzure.Storage" odata.DownloadUrl |> shouldEqual"https://www.nuget.org/api/v2/package/WindowsAzure.Storage/4.4.1-preview" - let dependencies = odata.Dependencies |> Array.ofList + let dependencies = odata|> NuGet.NuGetPackageCache.getDependencies |> Array.ofList dependencies.[0] |> shouldEqual (PackageName "Microsoft.Data.OData", DependenciesFileParser.parseVersionRequirement(">= 5.6.3"), makeOrList [FrameworkRestriction.AtLeast(DNXCore(FrameworkVersion.V5_0))]) @@ -164,11 +161,11 @@ let ``can ignore unknown frameworks``() = |> shouldEqual { PackageName = "BenchmarkDotNet" DownloadUrl = "https://www.nuget.org/api/v2/package/BenchmarkDotNet/0.10.1" - Dependencies = + SerializedDependencies = [ PackageName "BenchmarkDotNet.Toolchains.Roslyn", DependenciesFileParser.parseVersionRequirement(">= 0.10.1"), - makeOrList [FrameworkRestriction.AtLeast (DotNetFramework FrameworkVersion.V4_5)] + ">= net45" ] Unlisted = false LicenseUrl = "https://github.com/dotnet/BenchmarkDotNet/blob/master/LICENSE.md" From 3874a3b5b8cd7ba082e1e1a2de86f914c635fbfa Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 19:15:42 +0200 Subject: [PATCH 45/47] fix test code --- tests/Paket.Tests/NuGetOData/ODataSpecs.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs index 2ebf0ab3f7..2ecbe2b5ba 100644 --- a/tests/Paket.Tests/NuGetOData/ODataSpecs.fs +++ b/tests/Paket.Tests/NuGetOData/ODataSpecs.fs @@ -103,7 +103,7 @@ let ``can detect explicit dependencies for Math.Numerics``() = LicenseUrl = "http://numerics.mathdotnet.com/docs/License.html" CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion SerializedDependencies = - [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), "&& (>= net35) (< net4)" ] + [PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), "&& (>= net35) (< net40)" ] SourceUrl = fakeUrl } [] From bba04194565976623206abb0b30fd1dd80354e35 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 19:59:47 +0200 Subject: [PATCH 46/47] Cleanup stuff --- src/Paket.Core/Dependencies/PackageResolver.fs | 5 ++--- src/Paket.Core/Versioning/Requirements.fs | 14 +------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/Paket.Core/Dependencies/PackageResolver.fs b/src/Paket.Core/Dependencies/PackageResolver.fs index e357a4f2bc..c55545ce98 100644 --- a/src/Paket.Core/Dependencies/PackageResolver.fs +++ b/src/Paket.Core/Dependencies/PackageResolver.fs @@ -63,7 +63,8 @@ module DependencySetFilter = //let combined = FrameworkRestriction.And [ restriction; dependencyRestrictions ] //not combined.RepresentedFrameworks.IsEmpty - // "And" is not cleap therefore we use this, because we don't want to re-use the "simplified" formula + // "And" is not cheap therefore we use this, + // because we don't want to pay the price of calculating a "simplified" formula Set.intersect restriction.RepresentedFrameworks dependencyRestrictions.RepresentedFrameworks |> Set.isEmpty |> not @@ -133,8 +134,6 @@ module Resolution = |> Set.union currentStep.OpenRequirements |> Set.add lastPackageRequirement |> Set.filter (fun x -> x.Name = lastPackageRequirement.Name) - //|> Seq.sortBy (fun x -> x.Parent) - //|> Seq.toList let buildConflictReport (errorReport:StringBuilder) (conflicts:PackageRequirement Set) = let formatVR (vr:VersionRequirement) = diff --git a/src/Paket.Core/Versioning/Requirements.fs b/src/Paket.Core/Versioning/Requirements.fs index ea239944f8..72ad539767 100644 --- a/src/Paket.Core/Versioning/Requirements.fs +++ b/src/Paket.Core/Versioning/Requirements.fs @@ -95,7 +95,7 @@ type FrameworkRestrictionP = /// For example =net46 is a subset of >=netstandard13 member x.IsSubsetOf (y:FrameworkRestrictionP) = - // better ~ 5 Mins + // better ~ 5 Mins, but below recursive logic should be even better. let inline fallBack doAssert = #if DEBUG if doAssert then @@ -113,18 +113,11 @@ type FrameworkRestrictionP = | FrameworkRestrictionP.AtLeastP y' -> // =x' is a subset of >=y' when 'y is smaller than 'x y'.IsSmallerThanOrEqual x' - //x'.SupportedPlatformsTransitiveSeq - //|> Seq.exists (Set.contains y') // these are or 'common' forms, others are not allowed | FrameworkRestrictionP.NotP(FrameworkRestrictionP.AtLeastP y') -> // =x is only a subset of = y y'.IsSmallerThanOrEqual x' |> not - //// We go down from x' and if we find y' it is a subset -> not - //x'.SupportedPlatformsTransitiveSeq - //|> Seq.exists (Set.contains y') - //|> not - //fallBack() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.ExactlyP y') -> x' <> y' // This one should never actually hit. @@ -148,13 +141,11 @@ type FrameworkRestrictionP = // >= x' is only a subset of < y' when their intersection is empty Set.intersect (x'.PlatformsSupporting) (y'.PlatformsSupporting) |> Set.isEmpty - //fallBack() | FrameworkRestrictionP.NotP(FrameworkRestrictionP.ExactlyP y') -> // >= x' is only a subset of <> y' when y' is not part of >=x' x'.PlatformsSupporting |> Set.contains y' |> not - //fallBack() // This one should never actually hit. | FrameworkRestrictionP.NotP(y') -> fallBack true | FrameworkRestrictionP.OrP (ys) -> @@ -169,7 +160,6 @@ type FrameworkRestrictionP = match y with | FrameworkRestrictionP.ExactlyP y' -> // < x is a subset of ='y when? - //x'.SupportedPlatforms.IsEmpty && x' = y' #if DEBUG assert (not (fallBack false))// TODO: can this happen? #endif @@ -663,8 +653,6 @@ let isTargetMatchingRestrictions (restriction:FrameworkRestriction, target)= /// Get all targets that should be considered with the specified restrictions let applyRestrictionsToTargets (restriction:FrameworkRestriction) (targets: TargetProfile Set) = Set.intersect targets restriction.RepresentedFrameworks - //targets - //|> List.filter (fun t -> isTargetMatchingRestrictions(restriction,t)) type ContentCopySettings = | Omit From 148d73bde7b68ea447affd545a1cc1661118a3b8 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Wed, 24 May 2017 20:42:10 +0200 Subject: [PATCH 47/47] update documentation and RELEASE_NOTES. --- RELEASE_NOTES.md | 10 +++++++++- docs/content/dependencies-file.md | 4 ++++ docs/content/nuget-dependencies.md | 10 ++++++++++ docs/content/references-files.md | 12 ++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ac241026c1..7360c767c3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,10 +1,18 @@ -#### 5.0.0-beta005 - 23.05.2017 +#### 5.0.0-beta006 - 24.05.2017 * BUGFIX: Fixed dotnetcore integration: * Paket now properly understands runtime and reference assemblies * Paket now understands the runtime graph and restores runtime dependencies * New API `InstallModel.GetRuntimeAssemblies` and `InstallModel.GetRuntimeLibraries` can be used to retrieve the correct assets for a particular RID and TFM * New command `paket generate-nuspec` * New Command: `FixNuspecs` - Can fix a list of nuspec files now +* New restriction system (https://github.com/fsprojects/Paket/pull/2336): + * Paket is now more accurate in calculating restrictions and referencing libraries + * Paket will convert (lock-)files to a new syntax (but still understands the old syntax), we might revert this within the beta phase + * This should fix a bunch of edge cases and invalid behavior in combination with portable profiles and netstandard + * Add support for net403 (required for some portable profiles) +* PERFORMANCE: Improved performance by pre-loading requests (https://github.com/fsprojects/Paket/pull/2336) +* PERFORMANCE: Report performance in a more detailed way (https://github.com/fsprojects/Paket/pull/2336) +* BREAKING CHANGE: Paket simplify no longer support simplifying restrictions (https://github.com/fsprojects/Paket/pull/2336) * BREAKING CHANGE: Paket.PowerShell is no longer supported * BREAKING CHANGE: `InstallModel` API changed and Paket.Core.dll users might need to adapt * DEPRECATED: `FixNuspec` function is now obsolete, use `FixNuspecs` instead diff --git a/docs/content/dependencies-file.md b/docs/content/dependencies-file.md index 64bd443cc6..3a6a4476c4 100644 --- a/docs/content/dependencies-file.md +++ b/docs/content/dependencies-file.md @@ -92,6 +92,10 @@ Sometimes you don't want to generate dependencies for older framework versions. nuget Example >= 2.0 // only .NET 3.5 and .NET 4.0 +It means + +> Paket, I only compile for 'net35' and 'net40', please leave out all other stuff I don't need to compile for this set of frameworks. + #### Automatic framework detection Paket can detect the target frameworks from your project and then limit the installation to these target frameworks. You can control this in the [`paket.dependencies` file](dependencies-file.html): diff --git a/docs/content/nuget-dependencies.md b/docs/content/nuget-dependencies.md index 27890d9a76..fc0cc214d1 100644 --- a/docs/content/nuget-dependencies.md +++ b/docs/content/nuget-dependencies.md @@ -183,6 +183,16 @@ Sometimes you don't want to generate dependencies for older framework versions. nuget Example >= 2.0 framework: net35, net40 // .NET 3.5 and .NET 4.0 nuget Example >= 2.0 framework: >= net45 // .NET 4.5 and above +> Note: This feature is deprecated and can be seen as an expert feature. +> Using framework restrictions on single packages might make you projects uncompilable. +> The recommended way is to globally (on a group) specifiy the frameworks you want to compile for. + +This feature basically tells paket to only consider the specified frameworks for this package. +It means + +> Paket I use 'Example' only to compile against 'net35' and 'net40'. +> I never need this package to compile for another framework like 'net45'." + ### Putting the version no. into the path If you need to be NuGet compatible and want to have the version no. in the package path you can do the following: diff --git a/docs/content/references-files.md b/docs/content/references-files.md index 7ed64c3d31..70670a8352 100644 --- a/docs/content/references-files.md +++ b/docs/content/references-files.md @@ -66,6 +66,18 @@ Sometimes you don't want to generate dependencies for older framework versions. Newtonsoft.Json framework: net35, net40 DotNetZip framework: >= net45 +> Note: This feature is deprecated and can be seen as an expert feature. +> Using framework restrictions on single packages might make you projects uncompilable. +> The recommended way is to globally (on a group) specifiy the frameworks you want to compile for. + +This feature basically tells paket to only consider the specified frameworks for this package on this particular project. +The resolution will not be modified when restrictions are specified in the reference file. +It means + +> In this project 'Newtonsoft.Json' is only required when compiling against 'net35' or 'net40'. +> I never need this package to compile for another framework like 'net45', therefore don't add references for other frameworks. + + ## Redirects settings You can instruct Paket to create assembly binding redirects for NuGet packages: