Skip to content

Apply framework restriction #4284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions integrationtests/Paket.IntegrationTests/PaketCoreSpecs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ let ``#1251 full installer demo``() =
lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "FAKE"].Version
|> shouldBeGreaterThan (SemVer.Parse "4")

[<Test>]
let ``apply framework restriction`` ([<Values>] force, [<Values("https://nuget.org/api/v2", "https://api.nuget.org/v3/index.json")>] source: string) =
use __ = prepare "i001251-installer-demo"
let deps = $"""source {source}
framework: =net8.0
nuget Microsoft.AspNetCore.WebUtilities"""

let dependenciesFile = DependenciesFile.FromSource(scenarioTempPath "i001251-installer-demo",deps)
let lockFile,_,_,_ = UpdateProcess.SelectiveUpdate(dependenciesFile, alternativeProjectRoot, PackageResolver.UpdateMode.Install, SemVerUpdateMode.NoRestriction, force)

let version = lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[PackageName "Microsoft.AspNetCore.WebUtilities"].Version
Assert.Less(version, SemVer.Parse "9")

[<Test>]
let ``#1251 install FSharp.Collections.ParallelSeq``() =
use __ = prepare "i001251-installer-demo"
Expand Down
1 change: 1 addition & 0 deletions src/Paket.Core/Dependencies/NuGet.fs
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ let rec private getPackageDetails alternativeProjectRoot root force (parameters:
DownloadLink = encodeURL nugetObject.DownloadUrl
Unlisted = nugetObject.Unlisted
LicenseUrl = nugetObject.LicenseUrl
AvailableFrameworks = nugetObject.AvailableFrameworks
DirectDependencies = nugetObject.GetDependencies() } }

let rec GetPackageDetails alternativeProjectRoot root force (parameters:GetPackageDetailsParameters): Async<PackageResolver.PackageDetails> =
Expand Down
5 changes: 4 additions & 1 deletion src/Paket.Core/Dependencies/NuGetCache.fs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ type NuGetPackageCache =
Unlisted : bool
DownloadUrl : string
LicenseUrl : string
AvailableFrameworks: FrameworkIdentifier list
Version: string
CacheVersion: string }

Expand Down Expand Up @@ -375,7 +376,7 @@ let getNuSpecFromNupkg (fileName:string) =
use zip = new ZipArchive(zipToCreate, ZipArchiveMode.Read)
let zippedNuspec = zip.Entries |> Seq.find (fun f -> f.FullName.EndsWith ".nuspec")
use stream = zippedNuspec.Open()
Nuspec.Load(Path.Combine(fileName, Path.GetFileName zippedNuspec.FullName), stream)
Nuspec.Load(Path.Combine(fileName, Path.GetFileName zippedNuspec.FullName), stream, zip.Entries |> Seq.map _.FullName |> Seq.toArray)

let getCacheDataFromExtractedPackage (packageName:PackageName) (version:SemVerInfo) = async {
match TryGetFallbackNupkg packageName version with
Expand All @@ -390,6 +391,7 @@ let getCacheDataFromExtractedPackage (packageName:PackageName) (version:SemVerIn
CacheVersion = NuGetPackageCache.CurrentCacheVersion
LicenseUrl = nuspec.LicenseUrl
Version = version.Normalize()
AvailableFrameworks = nuspec.AvailableFramework
Unlisted = false }
.WithDependencies nuspec.Dependencies.Value
|> Some
Expand All @@ -406,6 +408,7 @@ let getCacheDataFromExtractedPackage (packageName:PackageName) (version:SemVerIn
SourceUrl = targetFolder.FullName
CacheVersion = NuGetPackageCache.CurrentCacheVersion
LicenseUrl = nuspec.LicenseUrl
AvailableFrameworks = nuspec.AvailableFramework
Version = version.Normalize()
Unlisted = false }
.WithDependencies nuspec.Dependencies.Value
Expand Down
1 change: 1 addition & 0 deletions src/Paket.Core/Dependencies/NuGetLocal.fs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ let getDetailsFromLocalNuGetPackage isCache alternativeProjectRoot root localNuG
CacheVersion = NuGetPackageCache.CurrentCacheVersion
LicenseUrl = nuspec.LicenseUrl
Version = version.Normalize()
AvailableFrameworks = nuspec.AvailableFramework
Unlisted = isCache }
.WithDependencies nuspec.Dependencies.Value
|> ODataSearchResult.Match
Expand Down
1 change: 1 addition & 0 deletions src/Paket.Core/Dependencies/NuGetV2.fs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ let private handleODataEntry nugetURL packageName version entry =
SourceUrl = nugetURL
CacheVersion = NuGetPackageCache.CurrentCacheVersion
LicenseUrl = licenseUrl
AvailableFrameworks = []
Version = (SemVer.Parse v).Normalize()
Unlisted = publishDate = Constants.MagicUnlistingDate }
.WithDependencies dependencies
Expand Down
1 change: 1 addition & 0 deletions src/Paket.Core/Dependencies/NuGetV3.fs
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ let getPackageDetails (source:NuGetV3Source) (packageName:PackageName) (version:
DownloadUrl = relevantPage.DownloadLink
LicenseUrl = catalogData.LicenseUrl
Version = version.Normalize()
AvailableFrameworks = []
CacheVersion = NuGetPackageCache.CurrentCacheVersion }
.WithDependencies optimized
|> ODataSearchResult.Match
Expand Down
27 changes: 17 additions & 10 deletions src/Paket.Core/Dependencies/Nuspec.fs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,15 @@ type Nuspec =
OfficialName : string
// Currently only used for testing
Version : string
AvailableFramework: FrameworkIdentifier list
LicenseUrl : string
IsDevelopmentDependency : bool
FrameworkAssemblyReferences : FrameworkAssemblyReference list }
static member All = { Version = ""; References = NuspecReferences.All; Dependencies = lazy []; FrameworkAssemblyReferences = []; OfficialName = ""; LicenseUrl = ""; IsDevelopmentDependency = false }
static member Explicit references = { Version = ""; References = NuspecReferences.Explicit references; Dependencies = lazy []; FrameworkAssemblyReferences = []; OfficialName = ""; LicenseUrl = ""; IsDevelopmentDependency = false }
static member All = { Version = ""; References = NuspecReferences.All; Dependencies = lazy []; FrameworkAssemblyReferences = []; OfficialName = ""; LicenseUrl = ""; IsDevelopmentDependency = false; AvailableFramework = [] }
static member Explicit references = { Version = ""; References = NuspecReferences.Explicit references; Dependencies = lazy []; FrameworkAssemblyReferences = []; OfficialName = ""; LicenseUrl = ""; IsDevelopmentDependency = false; AvailableFramework = [] }

/// load the file from an XmlDocument. The fileName is only used for error reporting.
static member private Load(fileName:string, doc:XmlDocument) =
static member private Load(fileName:string, doc:XmlDocument, allPackageFiles: string[]) =
let frameworks =
doc
|> getDescendants "group"
Expand Down Expand Up @@ -126,6 +127,11 @@ type Nuspec =
match doc |> getNode "package" |> optGetNode "metadata" |> optGetNode "developmentDependency" with
| Some link -> String.equalsIgnoreCase link.InnerText "true"
| None -> false
AvailableFramework =
allPackageFiles
|> Seq.choose FrameworkDetection.DetectFromPath
|> Seq.distinct
|> Seq.toList
FrameworkAssemblyReferences =
let grouped =
doc
Expand All @@ -142,30 +148,31 @@ type Nuspec =
|> 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) =
static member internal Load(fileName:string, f:Stream, allPackageFiles) =
let doc = new XmlDocument()
doc.Load f
Nuspec.Load (fileName, doc)
Nuspec.Load (fileName, doc, allPackageFiles)

/// load the file from an xml text. The fileName is only used for error reporting.
static member internal Load(fileName:string, text:string) =
static member internal Load(fileName:string, text:string, allPackageFiles) =
let doc = new XmlDocument()
doc.LoadXml text
Nuspec.Load (fileName, doc)
Nuspec.Load (fileName, doc, allPackageFiles)

/// load the file from a given file.
static member Load(fileName : string) =
static member Load(fileName: string) =
let fi = FileInfo(fileName)
if not fi.Exists then Nuspec.All
else
let allPackageFiles = fi.Directory.EnumerateFiles("*", SearchOption.AllDirectories) |> Seq.map _.FullName |> Seq.toArray
try
use f = File.OpenRead(fi.FullName)
Nuspec.Load(fileName, f)
Nuspec.Load(fileName, f, allPackageFiles)
with
| exn ->
try
let text = File.ReadAllText(fi.FullName) // work around mono bug https://github.com/fsprojects/Paket/issues/1189
Nuspec.Load(fileName, text)
Nuspec.Load(fileName, text, allPackageFiles)
with
| ex ->
raise (IOException("Cannot load " + fileName + Environment.NewLine + "Message: " + ex.Message))
24 changes: 21 additions & 3 deletions src/Paket.Core/Dependencies/PackageResolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type PackageDetails = {
DownloadLink : string
LicenseUrl : string
Unlisted : bool
AvailableFrameworks: FrameworkIdentifier list
DirectDependencies : DependencySet
}

Expand Down Expand Up @@ -65,6 +66,7 @@ type ResolvedPackage = {
Kind : ResolvedPackageKind
Settings : InstallSettings
Source : PackageSource
AvailableFrameworks : FrameworkIdentifier list
} with
override this.ToString () = sprintf "%O %O" this.Name this.Version

Expand Down Expand Up @@ -506,6 +508,7 @@ let private explorePackageConfig (getPackageDetailsBlock:PackageDetailsSyncFunc)
Kind = if Set.contains packageDetails.Name pkgConfig.CliTools then ResolvedPackageKind.DotnetCliTool
else ResolvedPackageKind.Package
IsRuntimeDependency = false
AvailableFrameworks = packageDetails.AvailableFrameworks
}
with
| exn ->
Expand Down Expand Up @@ -1351,7 +1354,18 @@ let Resolve (getVersionsRaw : PackageVersionsFunc, getPreferredVersionsRaw : Pre
conflictingWithOpen
|> Seq.append conflictingWithClosed)

let conflictingFramework =
match exploredPackage.AvailableFrameworks with
| [] -> []
| _ ->
exploredPackage.AvailableFrameworks
|> Seq.exists (fun framework -> exploredPackage.Settings.FrameworkRestrictions.IsSupersetOf(FrameworkRestriction.Exactly(framework)))
|> function
| false -> [exploredPackage.Name, VersionRequirement (VersionRange.Maximum exploredPackage.Version, PreReleaseStatus.All)]
| true -> []

let canTakePackage =
Seq.isEmpty conflictingFramework &&
Seq.isEmpty conflictingResolvedPackages &&
Seq.isEmpty conflictingDepsRanges

Expand Down Expand Up @@ -1381,9 +1395,13 @@ let Resolve (getVersionsRaw : PackageVersionsFunc, getPreferredVersionsRaw : Pre
getVersionsBlock ResolverStrategy.Max (GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName packName) currentStep

let conflictingPackageName,vr =
match Seq.tryHead conflictingResolvedPackages with
| Some (conflictingPackage,(_,vr,_)) -> conflictingPackage.Name,vr
| None -> Seq.head conflictingDepsRanges
conflictingFramework
|> Seq.tryHead
|> Option.defaultWith (fun () ->
match Seq.tryHead conflictingResolvedPackages with
| Some (conflictingPackage,(_,vr,_)) -> conflictingPackage.Name,vr
| None -> Seq.head conflictingDepsRanges
)

let currentConflict =
{ currentConflict with
Expand Down
1 change: 1 addition & 0 deletions src/Paket.Core/PaketConfigFiles/LockFile.fs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ module LockFileParser =
Settings = settings
Version = SemVer.Parse version
Kind = kind
AvailableFrameworks = []
// TODO: write stuff into the lockfile and read it here
IsRuntimeDependency = isRuntimeDependency } :: currentGroup.Packages }::otherGroups
| None -> failwith "no source has been specified."
Expand Down
1 change: 1 addition & 0 deletions tests/Paket.Tests/InstallModel/Xml/RxXaml.fs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ let ``should generate Xml for Rx-XAML 2.2.4 with correct framework assembly refe
Dependencies = lazy []
LicenseUrl = ""
IsDevelopmentDependency = false
AvailableFramework = []
FrameworkAssemblyReferences =
[{ AssemblyName = "WindowsBase"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4_5)] }
{ AssemblyName = "WindowsBase"; FrameworkRestrictions = makeOrList [FrameworkRestriction.Exactly(DotNetFramework FrameworkVersion.V4)] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ let ``should generate Xml for System.Net.Http 2.2.8``() =
Dependencies = lazy []
LicenseUrl = ""
IsDevelopmentDependency = false
AvailableFramework = []
FrameworkAssemblyReferences =
[{ 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))] }]})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ let ``should generate Xml for System.Net.Http 2.2.8``() =
Dependencies = lazy []
LicenseUrl = ""
IsDevelopmentDependency = false
AvailableFramework = []
FrameworkAssemblyReferences =
[{ 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))] }]})
Expand Down
7 changes: 7 additions & 0 deletions tests/Paket.Tests/NuGetOData/ODataSpecs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ let ``can detect explicit dependencies for Fantomas``() =
LicenseUrl = "http://github.com/dungpa/fantomas/blob/master/LICENSE.md"
CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion
Version = "1.6.0"
AvailableFrameworks = []
SourceUrl = fakeUrl }

[<Test>]
Expand All @@ -57,6 +58,7 @@ let ``can detect explicit dependencies for Rx-PlaformServices``() =
LicenseUrl = "http://go.microsoft.com/fwlink/?LinkID=261272"
Version = "2.3.0"
CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion
AvailableFrameworks = []
SourceUrl = fakeUrl }
|> ODataSearchResult.Match)

Expand All @@ -72,6 +74,7 @@ let ``can detect explicit dependencies for EasyNetQ``() =
LicenseUrl = "https://github.com/mikehadlow/EasyNetQ/blob/master/licence.txt"
CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion
Version = "0.40.3.352"
AvailableFrameworks = []
SourceUrl = fakeUrl }
|> ODataSearchResult.Match)

Expand All @@ -90,6 +93,7 @@ let ``can detect explicit dependencies for Fleece``() =
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"]
AvailableFrameworks = []
SourceUrl = fakeUrl }

[<Test>]
Expand All @@ -106,6 +110,7 @@ let ``can detect explicit dependencies for ReadOnlyCollectionExtensions``() =
SerializedDependencies =
[PackageName "LinqBridge",DependenciesFileParser.parseVersionRequirement(">= 1.3.0"), "&& (>= net20) (< net35)"
PackageName "ReadOnlyCollectionInterfaces",DependenciesFileParser.parseVersionRequirement("1.0.0"), ">= net20"]
AvailableFrameworks = []
SourceUrl = fakeUrl }

[<Test>]
Expand All @@ -120,6 +125,7 @@ let ``can detect explicit dependencies for Math.Numerics``() =
CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion
SerializedDependencies =
[PackageName "TaskParallelLibrary",DependenciesFileParser.parseVersionRequirement(">= 1.0.2856"), "&& (>= net35) (< net40)" ]
AvailableFrameworks = []
SourceUrl = fakeUrl }
|> ODataSearchResult.Match)

Expand Down Expand Up @@ -166,4 +172,5 @@ let ``can ignore unknown frameworks``() =
LicenseUrl = "https://github.com/dotnet/BenchmarkDotNet/blob/master/LICENSE.md"
CacheVersion = NuGet.NuGetPackageCache.CurrentCacheVersion
Version = "0.10.1"
AvailableFrameworks = []
SourceUrl = fakeUrl }
1 change: 1 addition & 0 deletions tests/Paket.Tests/Resolver/PropertyTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ let bruteForce ((g,deps):ResolverPuzzle) =
Settings = InstallSettings.Default
Source = PackageSources.DefaultNuGetSource
Kind = ResolvedPackageKind.Package
AvailableFrameworks = []
IsRuntimeDependency = false }

let deps' = packageDeps @ deps
Expand Down
3 changes: 2 additions & 1 deletion tests/Paket.Tests/TestHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ let OfGraphWithRestriction (g:seq<string * string * (string * VersionRequirement
let GraphOfNuspecs (g:seq<string>) : DependencyGraph =
g
|> Seq.map (fun nuspecText ->
let nspec = Nuspec.Load("in-memory", nuspecText)
let nspec = Nuspec.Load("in-memory", nuspecText, [||])
nspec.OfficialName, nspec.Version, nspec.Dependencies.Value |> List.map (fun (a,b,c) -> a.CompareString, b, c), RuntimeGraph.Empty)
|> Seq.toList

Expand All @@ -60,6 +60,7 @@ let PackageDetailsFromGraph (graph : DependencyGraph) (parameters:GetPackageDeta
DownloadLink = ""
LicenseUrl = ""
Unlisted = false
AvailableFrameworks = []
DirectDependencies = Set.ofList dependencies }
|> async.Return

Expand Down
1 change: 1 addition & 0 deletions tests/Paket.Tests/Versioning/FrameworkRestrictionTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ let ``__unknowntfm__ should not match everything`` () =
Dependencies = lazy []
LicenseUrl = ""
IsDevelopmentDependency = false
AvailableFramework = []
FrameworkAssemblyReferences = []})
let target = TargetProfile.PortableProfile PortableProfileType.Profile344
let newModel = model.ApplyFrameworkRestrictions (FrameworkRestriction.ExactlyPlatform target)
Expand Down