diff --git a/src/Paket.Core/InstallModel.fs b/src/Paket.Core/InstallModel.fs index 693d2a616b..f200698ed5 100644 --- a/src/Paket.Core/InstallModel.fs +++ b/src/Paket.Core/InstallModel.fs @@ -288,25 +288,7 @@ type InstallModel = | [] -> this | restrictions -> let applRestriction folder = - { folder with - Targets = - folder.Targets - |> List.filter - (function - | SinglePlatform pf -> - restrictions - |> List.exists (fun restriction -> - match restriction with - | FrameworkRestriction.Exactly fw -> pf = fw - | FrameworkRestriction.Portable r -> false - | FrameworkRestriction.AtLeast fw -> pf >= fw - | FrameworkRestriction.Between(min,max) -> pf >= min && pf < max) - | _ -> - restrictions - |> List.exists (fun restriction -> - match restriction with - | FrameworkRestriction.Portable r -> true - | _ -> false))} + { folder with Targets = applyRestrictionsToTargets restrictions folder.Targets} {this with ReferenceFileFolders = @@ -317,7 +299,7 @@ type InstallModel = TargetsFileFolders = this.TargetsFileFolders |> List.map applRestriction - |> List.filter (fun folder -> folder.Targets <> []) } + |> List.filter (fun folder -> folder.Targets <> []) } member this.GetFrameworkAssembliesLazy = lazy ([ for lib in this.ReferenceFileFolders do diff --git a/src/Paket.Core/PublicAPI.fs b/src/Paket.Core/PublicAPI.fs index 676fea3fa7..239b0a741b 100644 --- a/src/Paket.Core/PublicAPI.fs +++ b/src/Paket.Core/PublicAPI.fs @@ -17,7 +17,7 @@ type Dependencies(dependenciesFileName: string) = let listPackages (packages: System.Collections.Generic.KeyValuePair seq) = packages |> Seq.map (fun kv -> - let groupName,packageName = kv.Key + let groupName,packageName = kv.Key groupName.ToString(),packageName.ToString(),kv.Value.Version.ToString()) |> Seq.toList @@ -33,13 +33,13 @@ type Dependencies(dependenciesFileName: string) = path else let parent = dir.Parent - if parent = null then + match parent with + | null -> if withError then failwithf "Could not find '%s'. To use Paket with this solution, please run 'paket init' first." Constants.DependenciesFileName else Constants.DependenciesFileName - else - findInPath(parent, withError) + | _ -> findInPath(parent, withError) let dependenciesFileName = findInPath(DirectoryInfo path,true) verbosefn "found: %s" dependenciesFileName @@ -404,7 +404,9 @@ type Dependencies(dependenciesFileName: string) = let cancellationToken = defaultArg cancellationToken (System.Threading.CancellationToken()) let maxResults = defaultArg maxResults 1000 let sources = this.GetSources() |> Seq.map (fun kv -> kv.Value) |> List.concat |> List.distinct - if sources = [] then [PackageSources.DefaultNugetSource] else sources + match sources with + | [] -> [PackageSources.DefaultNugetSource] + | _ -> sources |> List.choose (fun x -> match x with | Nuget s -> Some s.Url | _ -> None) |> Seq.distinct |> Seq.map (fun url -> diff --git a/src/Paket.Core/Requirements.fs b/src/Paket.Core/Requirements.fs index fb1e5d3574..6aeeac5aa6 100644 --- a/src/Paket.Core/Requirements.fs +++ b/src/Paket.Core/Requirements.fs @@ -13,7 +13,7 @@ type FrameworkRestriction = | Between of FrameworkIdentifier * FrameworkIdentifier override this.ToString() = - match this with + match this with | FrameworkRestriction.Exactly r -> r.ToString() | FrameworkRestriction.Portable r -> r | FrameworkRestriction.AtLeast r -> ">= " + r.ToString() @@ -72,7 +72,7 @@ let rec optimizeRestrictions restrictions = let newRestrictions' = restrictions |> List.distinct - |> List.sort + |> List.sort let newRestrictions = match newRestrictions' |> Seq.tryFind (function | FrameworkRestriction.AtLeast r -> true | _ -> false) with @@ -81,14 +81,15 @@ let rec optimizeRestrictions restrictions = let currentVersion = match r with | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> x - | x -> failwithf "Unknown .NET moniker %O" x + | x -> failwithf "Unknown .NET moniker %O" x let isLowerVersion x = let isMatching x = if x = FrameworkVersion.V3_5 && currentVersion = FrameworkVersion.V4 then true else if x = FrameworkVersion.V4_Client && currentVersion = FrameworkVersion.V4_5 then true else - let hasFrameworksBetween = KnownTargetProfiles.DotNetFrameworkVersions |> Seq.exists (fun p -> p > x && p < currentVersion) - not hasFrameworksBetween + KnownTargetProfiles.DotNetFrameworkVersions + |> Seq.exists (fun p -> p > x && p < currentVersion) + |> not match x with | FrameworkRestriction.Exactly(DotNetFramework(x)) -> isMatching x @@ -102,7 +103,7 @@ let rec optimizeRestrictions restrictions = match n with | FrameworkRestriction.Exactly(DotNetFramework(x)) -> x | FrameworkRestriction.AtLeast(DotNetFramework(x)) -> x - | x -> failwithf "Unknown .NET moniker %O" x + | x -> failwithf "Unknown .NET moniker %O" x (newRestrictions' |> List.filter (fun x -> x <> r && x <> n)) @ [FrameworkRestriction.AtLeast(DotNetFramework(newLowest))] @@ -111,8 +112,6 @@ let rec optimizeRestrictions restrictions = let optimizeDependencies packages = - let grouped = packages |> List.groupBy (fun (n,v,_) -> n,v) - let invertedRestrictions = let expanded = [for (n,vr,r:FrameworkRestrictions) in packages do @@ -136,71 +135,66 @@ let optimizeDependencies packages = let emptyRestrictions = [for (n,vr,r:FrameworkRestrictions) in packages do - if r = [] then + if List.isEmpty r then yield n,vr] |> Set.ofList + let grouped = packages |> List.filter (fun (name,_,_) -> name <> PackageName "") |> List.groupBy (fun (n,v,_) -> n,v) [for (name,versionRequirement:VersionRequirement),group in grouped do - if name <> PackageName "" then - if not (Set.isEmpty emptyRestrictions) && Set.contains (name,versionRequirement) emptyRestrictions then - yield name,versionRequirement,[] - else - let plain = - group - |> List.map (fun (_,_,res) -> res) - |> List.concat - |> List.distinct - |> List.sort - - let localMaxDotNetRestriction = findMaxDotNetRestriction plain - let globalMax = defaultArg globalMax localMaxDotNetRestriction + if not (Set.isEmpty emptyRestrictions) && Set.contains (name,versionRequirement) emptyRestrictions then + yield name,versionRequirement,[] + else + let plain = + group + |> List.map (fun (_,_,res) -> res) + |> List.concat + |> List.distinct + |> List.sort - let dotnetRestrictions,others = List.partition (function | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true | _ -> false) plain + let localMaxDotNetRestriction = findMaxDotNetRestriction plain + let globalMax = defaultArg globalMax localMaxDotNetRestriction - let restrictions' = - dotnetRestrictions - |> List.map (fun restriction -> - match restriction with - | FrameworkRestriction.Exactly r -> - if r = localMaxDotNetRestriction && r = globalMax then - FrameworkRestriction.AtLeast r - else - restriction - | _ -> restriction) + let dotnetRestrictions,others = List.partition (function | FrameworkRestriction.Exactly(DotNetFramework(_)) -> true | FrameworkRestriction.AtLeast(DotNetFramework(_)) -> true | _ -> false) plain - let restrictions = optimizeRestrictions restrictions' + let restrictions' = + dotnetRestrictions + |> List.map (fun restriction -> + match restriction with + | FrameworkRestriction.Exactly r when r = localMaxDotNetRestriction && r = globalMax -> + FrameworkRestriction.AtLeast r + | _ -> restriction) - yield name,versionRequirement,others @ restrictions] + yield name,versionRequirement,others @ optimizeRestrictions restrictions'] let combineRestrictions 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.Exactly r' when r = r' -> [FrameworkRestriction.Exactly r] + | FrameworkRestriction.AtLeast r' when r' <= r -> [FrameworkRestriction.Exactly r] + | FrameworkRestriction.Between(min,max) when min <= r && r <= max -> [FrameworkRestriction.Exactly r] + | _ -> [] | FrameworkRestriction.Portable r -> match y with - | FrameworkRestriction.Portable r' -> if r = r' then [FrameworkRestriction.Portable r] else [] + | FrameworkRestriction.Portable r' when r = r' ->[FrameworkRestriction.Portable r] | _ -> [] | FrameworkRestriction.AtLeast r -> match y with - | FrameworkRestriction.Exactly r' -> if r <= r' then [FrameworkRestriction.Exactly r'] else [] - | FrameworkRestriction.Portable _ -> [] + | FrameworkRestriction.Exactly r' when r <= r' -> [FrameworkRestriction.Exactly r'] | FrameworkRestriction.AtLeast r' -> [FrameworkRestriction.AtLeast (max r r')] - | FrameworkRestriction.Between(min,max) -> if min <= r && r <= max then [FrameworkRestriction.Between(r,max)] else [] + | FrameworkRestriction.Between(min,max) when min <= r && r <= max -> [FrameworkRestriction.Between(r,max)] + | _ -> [] | 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 min1 <= r && r <= max1 then [FrameworkRestriction.Between(r,max1)] else [] - | FrameworkRestriction.Between(min2,max2) -> + | FrameworkRestriction.Exactly r when min1 <= r && r <= max1 -> [FrameworkRestriction.Exactly r] + | FrameworkRestriction.AtLeast r when min1 <= r && r <= max1 -> [FrameworkRestriction.Between(r,max1)] + | 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 filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestrictions) = match list1,list2 with @@ -213,6 +207,44 @@ let filterRestrictions (list1:FrameworkRestrictions) (list2:FrameworkRestriction if c <> [] then yield! c] |> optimizeRestrictions +let inline frameworkCategory (fw:FrameworkIdentifier) = + match fw with + | DotNetFramework _ -> ".NET" + | Silverlight _ -> "Silverlight" + | DNX _ -> "DNX" + | DNXCore _ -> "DNXCore" + | MonoAndroid _ -> "MonoAndroid" + | MonoMac _ -> "MonoMac" + | MonoTouch _ -> "MonoTouch" + | Windows _ -> "Windows" + | WindowsPhoneApp _ -> "WindowsPhoneApp" + | WindowsPhoneSilverlight _ -> "WindowsPhoneSilverlight" + | XamarinMac _ -> "XamarinMac" + | XamariniOS _ -> "XamariniOS" + + +/// Get if a target should be considered with the specified restrictions +let isTargetMatchingRestrictions (restrictions:FrameworkRestrictions) = function + | SinglePlatform pf -> + restrictions + |> List.exists (fun restriction -> + match restriction with + | FrameworkRestriction.Exactly fw -> pf = fw + | FrameworkRestriction.Portable _ -> false + | FrameworkRestriction.AtLeast fw -> pf >= fw && frameworkCategory pf = frameworkCategory fw + | FrameworkRestriction.Between(min,max) -> pf >= min && pf < max && frameworkCategory pf = frameworkCategory min) + | PortableProfile(_) -> + 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:FrameworkRestrictions) (targets: TargetProfile list) = + let result = targets |> List.filter (isTargetMatchingRestrictions restrictions) + result + type ContentCopySettings = | Omit | Overwrite diff --git a/tests/Paket.Tests/Paket.Tests.fsproj b/tests/Paket.Tests/Paket.Tests.fsproj index a9721aafc3..733c157d23 100644 --- a/tests/Paket.Tests/Paket.Tests.fsproj +++ b/tests/Paket.Tests/Paket.Tests.fsproj @@ -1,4 +1,4 @@ - + @@ -308,6 +308,7 @@ + diff --git a/tests/Paket.Tests/Requirements/RestrictionApplicationSpecs.fs b/tests/Paket.Tests/Requirements/RestrictionApplicationSpecs.fs new file mode 100644 index 0000000000..04237c032d --- /dev/null +++ b/tests/Paket.Tests/Requirements/RestrictionApplicationSpecs.fs @@ -0,0 +1,83 @@ +module Paket.Requirements.RestrictionApplicationSpecs + +open Paket +open FsUnit +open NUnit.Framework +open Paket.Requirements + +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] + + let DotNetFrameworkProfiles = DotNetFrameworkVersions |> List.map dotnet + + let WindowsProfiles = + [SinglePlatform(Windows "v4.5") + SinglePlatform(Windows "v4.5.1")] + + let SilverlightProfiles = + [SinglePlatform(Silverlight "v3.0") + SinglePlatform(Silverlight "v4.0") + SinglePlatform(Silverlight "v5.0")] + + let WindowsPhoneSilverlightProfiles = + [SinglePlatform(WindowsPhoneSilverlight "v7.0") + SinglePlatform(WindowsPhoneSilverlight "v7.1") + SinglePlatform(WindowsPhoneSilverlight "v8.0") + SinglePlatform(WindowsPhoneSilverlight "v8.1")] + + let AllProfiles = + DotNetFrameworkProfiles @ + WindowsProfiles @ + SilverlightProfiles @ + WindowsPhoneSilverlightProfiles @ + [SinglePlatform(MonoAndroid) + SinglePlatform(MonoTouch) + SinglePlatform(XamariniOS) + SinglePlatform(XamarinMac) + SinglePlatform(WindowsPhoneApp "v8.1") + ] + +[] +let ``>= net10 contains all but only dotnet versions (#1124)`` () = + /// https://github.com/fsprojects/Paket/issues/1124 + 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 restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles + let expected = [FrameworkVersion.V4_5_2; FrameworkVersion.V4_5_3; FrameworkVersion.V4_6] |> List.map dotnet + + restricted |> shouldEqual expected + +[] +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 + + restricted |> shouldEqual expected + +[] +let ``>= sl30 contains all but only silverlight versions`` () = + let restrictions = [FrameworkRestriction.AtLeast(Silverlight "v3.0")] + let restricted = applyRestrictionsToTargets restrictions TestTargetProfiles.AllProfiles + + restricted |> shouldEqual TestTargetProfiles.SilverlightProfiles \ No newline at end of file