Skip to content
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

[WIP] Add resolver settings to keep semver level #3755

Open
wants to merge 3 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
2 changes: 2 additions & 0 deletions src/Paket.Core/Dependencies/DependenciesFileParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ module DependenciesFileParser =
let setting =
match trimmed.Replace(":","").Trim() with
| String.EqualsIC "max" -> Some ResolverStrategy.Max
| String.EqualsIC "latest-patch" -> Some ResolverStrategy.LatestPatch
| String.EqualsIC "latest-minor" -> Some ResolverStrategy.LatestMinor
| String.EqualsIC "min" -> Some ResolverStrategy.Min
| _ -> None

Expand Down
47 changes: 38 additions & 9 deletions src/Paket.Core/Dependencies/PackageResolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ type GetPackageDetailsParameters =
GetPackageDetailsParameters.ofParamsEx false sources groupName packageName version

type GetPackageVersionsParameters =
{ Package : SourcePackageInfo }
static member ofParams sources groupName packageName =
{ Package : SourcePackageInfo
MinVersion : SemVerInfo option }
static member ofParams sources groupName packageName minVersion =
SourcePackageInfo.ofParams sources groupName packageName
|> fun p -> { Package = p }
|> fun p -> { Package = p; MinVersion = minVersion }

type PackageDetailsFunc = GetPackageDetailsParameters -> Async<PackageDetails>
type PackageDetailsSyncFunc = GetPackageDetailsParameters -> PackageDetails
Expand Down Expand Up @@ -585,7 +586,8 @@ let private getCompatibleVersions
let resolverStrategy = getResolverStrategy globalStrategyForDirectDependencies globalStrategyForTransitives rootDependencies allRequirementsOfCurrentPackage currentRequirement

let allVersions =
getVersionsF resolverStrategy (GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName currentRequirement.Name)
let versionParams = GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName currentRequirement.Name currentRequirement.MinVersionSetting
getVersionsF resolverStrategy versionParams
|> Seq.map (fun (v, sources) -> VersionCache.ofParams v sources false)

match currentRequirement.VersionRequirement.Range with
Expand Down Expand Up @@ -1079,6 +1081,26 @@ let Resolve (getVersionsRaw : PackageVersionsFunc, getPreferredVersionsRaw : Pre
let sorted =
match resolverStrategy with
| ResolverStrategy.Max -> List.sortDescending versions
| ResolverStrategy.LatestPatch ->
match versionParams.MinVersion with
| Some minVersion ->
let preferred =
versions
|> List.filter (fun (v,s) -> v.Major = minVersion.Major && v.Minor = minVersion.Minor)
|> List.sortDescending

preferred @ List.sortDescending versions
| None -> List.sortDescending versions
| ResolverStrategy.LatestMinor ->
match versionParams.MinVersion with
| Some minVersion ->
let preferred =
versions
|> List.filter (fun (v,s) -> v.Major = minVersion.Major)
|> List.sortDescending

preferred @ List.sortDescending versions
| None -> List.sortDescending versions
| ResolverStrategy.Min -> List.sort versions

yield! sorted }
Expand Down Expand Up @@ -1174,7 +1196,8 @@ let Resolve (getVersionsRaw : PackageVersionsFunc, getPreferredVersionsRaw : Pre

let currentConflict =
let getVersionsF packName =
getVersionsBlock ResolverStrategy.Max (GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName packName) currentStep
let versionParameters = GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName packName currentRequirement.MinVersionSetting
getVersionsBlock ResolverStrategy.Max versionParameters currentStep

if Seq.isEmpty conflicts then
{ currentConflict with
Expand Down Expand Up @@ -1296,7 +1319,8 @@ let Resolve (getVersionsRaw : PackageVersionsFunc, getPreferredVersionsRaw : Pre
if not alreadyExplored then
for (pack,verReq,restr) in exploredPackage.Dependencies do
async {
let requestVersions = startRequestGetVersions (GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName pack)
let versionParameters = GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName pack currentRequirement.MinVersionSetting
let requestVersions = startRequestGetVersions versionParameters
requestVersions.Work.TryReprioritize true WorkPriority.LikelyRequired
let! versions = (requestVersions).Work.Task |> Async.AwaitTask
// Preload the first version in range of this requirement
Expand Down Expand Up @@ -1369,7 +1393,8 @@ let Resolve (getVersionsRaw : PackageVersionsFunc, getPreferredVersionsRaw : Pre
step (Step((currentConflict,nextStep,currentRequirement), (currentConflict,currentStep,currentRequirement,compatibleVersions,flags)::priorConflictSteps)) stackpack currentConflict.VersionsToExplore flags
else
let getVersionsF packName =
getVersionsBlock ResolverStrategy.Max (GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName packName) currentStep
let versionParameters = GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName packName currentRequirement.MinVersionSetting
getVersionsBlock ResolverStrategy.Max versionParameters currentStep

let conflictingPackageName,vr =
match Seq.tryHead conflictingResolvedPackages with
Expand Down Expand Up @@ -1399,13 +1424,17 @@ let Resolve (getVersionsRaw : PackageVersionsFunc, getPreferredVersionsRaw : Pre
}

for openReq in startingStep.OpenRequirements do
startRequestGetVersions (GetPackageVersionsParameters.ofParams openReq.Sources groupName openReq.Name)
let versionParamters = GetPackageVersionsParameters.ofParams openReq.Sources groupName openReq.Name openReq.MinVersionSetting
startRequestGetVersions versionParamters
|> ignore

let currentRequirement = getCurrentRequirement packageFilter startingStep.OpenRequirements (Dictionary())

let status =
let getVersionsF packName = getVersionsBlock ResolverStrategy.Max (GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName packName) startingStep
let getVersionsF packName =
let versionParameters = GetPackageVersionsParameters.ofParams currentRequirement.Sources groupName packName currentRequirement.MinVersionSetting
getVersionsBlock ResolverStrategy.Max versionParameters startingStep

ResolutionRaw.ConflictRaw { ResolveStep = startingStep; RequirementSet = Set.empty; Requirement = currentRequirement; GetPackageVersions = getVersionsF }


Expand Down
13 changes: 11 additions & 2 deletions src/Paket.Core/PaketConfigFiles/DependenciesFile.fs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,12 @@ type DependenciesFile(fileName,groups:Map<GroupName,DependenciesGroup>, textRepr
match strategy with
| None -> this
| Some strategy ->
let strategyString = sprintf "strategy: %s" (match strategy with ResolverStrategy.Max -> "max" | ResolverStrategy.Min -> "min")
let strategyString =
match strategy with
| ResolverStrategy.Max -> "strategy: max"
| ResolverStrategy.LatestPatch -> "strategy: latest-patch"
| ResolverStrategy.LatestMinor -> "strategy: latest-minor"
| ResolverStrategy.Min -> "strategy: min"

let list = new System.Collections.Generic.List<_>()
list.AddRange textRepresentation
Expand All @@ -478,7 +483,11 @@ type DependenciesFile(fileName,groups:Map<GroupName,DependenciesGroup>, textRepr
match strategy with
| None -> this
| Some strategy ->
let strategyString = sprintf "lowest_matching: %s" (match strategy with ResolverStrategy.Max -> "false" | ResolverStrategy.Min -> "true")
let strategyString =
match strategy with
| ResolverStrategy.Max -> "lowest_matching: max"
| ResolverStrategy.Min -> "lowest_matching: min"
| _ -> failwithf "Strategy %O is invalid for lowest_matching setting." strategy

let list = new System.Collections.Generic.List<_>()
list.AddRange textRepresentation
Expand Down
5 changes: 5 additions & 0 deletions src/Paket.Core/PaketConfigFiles/LockFile.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@ module LockFileSerializer =
| None -> ()
match options.ResolverStrategyForTransitives with
| Some ResolverStrategy.Min -> yield "STRATEGY: MIN"
| Some ResolverStrategy.LatestPatch -> yield "STRATEGY: LATEST-PATCH"
| Some ResolverStrategy.LatestMinor -> yield "STRATEGY: LATEST-MINOR"
| Some ResolverStrategy.Max -> yield "STRATEGY: MAX"
| None -> ()
match options.ResolverStrategyForDirectDependencies with
| Some ResolverStrategy.Min -> yield "LOWEST_MATCHING: TRUE"
| Some ResolverStrategy.Max -> yield "LOWEST_MATCHING: FALSE"
| Some x -> failwithf "Strategy %O is invalid as lowest_matching setting." x
| None -> ()
match options.Settings.CopyLocal with
| Some x -> yield "COPY-LOCAL: " + x.ToString().ToUpper()
Expand Down Expand Up @@ -346,6 +349,8 @@ module LockFileParser =
let setting =
match trimmed.Trim() with
| String.EqualsIC "min" -> Some ResolverStrategy.Min
| String.EqualsIC "latest-patch" -> Some ResolverStrategy.LatestPatch
| String.EqualsIC "latest-minor" -> Some ResolverStrategy.LatestMinor
| String.EqualsIC "max" -> Some ResolverStrategy.Max
| _ -> None

Expand Down
3 changes: 2 additions & 1 deletion src/Paket.Core/PublicAPI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,8 @@ type Dependencies(dependenciesFileName: string) =
|> List.distinct

let versions =
NuGet.GetVersions true alternativeProjectRoot root (GetPackageVersionsParameters.ofParams sources (GroupName "") (PackageName name))
let versionParameters = GetPackageVersionsParameters.ofParams sources (GroupName "") (PackageName name) None
NuGet.GetVersions true alternativeProjectRoot root versionParameters
|> Async.RunSynchronously
|> List.map (fun (v,_) -> v.ToString())
|> List.toArray
Expand Down
12 changes: 12 additions & 0 deletions src/Paket.Core/Versioning/Requirements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,18 @@ type PackageRequirement =

member this.Depth = this.Graph.Count

member this.MinVersionSetting =
match this.VersionRequirement with
| VersionRequirement(v,_) ->
match v with
| Minimum v -> Some v
| GreaterThan v -> Some v
| Maximum _ -> None
| LessThan _ -> None
| Specific v -> Some v
| OverrideAll _ -> None
| Range(_,v,_,_) -> Some v

member this.SettingString = (sprintf "%O %s %s %O %s" this.VersionRequirement (if this.ResolverStrategyForTransitives.IsSome then (sprintf "%O" this.ResolverStrategyForTransitives) else "") (if this.ResolverStrategyForDirectDependencies.IsSome then (sprintf "%O" this.ResolverStrategyForDirectDependencies) else "") this.Settings (if this.TransitivePrereleases then "TransitivePrereleases-true" else ""))

member this.HasPackageSettings = String.IsNullOrWhiteSpace this.SettingString |> not
Expand Down
4 changes: 3 additions & 1 deletion src/Paket.Core/Versioning/VersionRange.fs
Original file line number Diff line number Diff line change
Expand Up @@ -389,4 +389,6 @@ type VersionRequirement =
[<RequireQualifiedAccess>]
type ResolverStrategy =
| Max
| Min
| LatestPatch
| LatestMinor
| Min
9 changes: 9 additions & 0 deletions tests/Paket.Tests/DependenciesFile/ParserSpecs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,15 @@ let ``should read config with min and max strategy``() =
cfg.Groups.[GroupName "Test"].Options.ResolverStrategyForTransitives |> shouldEqual (Some ResolverStrategy.Max)

cfg.Groups.[Constants.MainDependencyGroup].Sources |> shouldEqual [PackageSource.NuGetV2Source "http://www.nuget.org/api/v2"]


[<Test>]
let ``should read config with latest-patch and latest-minor strategy``() =
let cfg = DependenciesFile.FromSource(strategyConfig "latest-patch" "latest-minor")
cfg.Groups.[Constants.MainDependencyGroup].Options.ResolverStrategyForTransitives |> shouldEqual (Some ResolverStrategy.LatestPatch)
cfg.Groups.[GroupName "Test"].Options.ResolverStrategyForTransitives |> shouldEqual (Some ResolverStrategy.LatestMinor)

cfg.Groups.[Constants.MainDependencyGroup].Sources |> shouldEqual [PackageSource.NuGetV2Source "http://www.nuget.org/api/v2"]

let noStrategyConfig = sprintf """
strategy %s
Expand Down
28 changes: 28 additions & 0 deletions tests/Paket.Tests/Lockfile/ParserSpecs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,34 @@ NUGET
packages.Length |> shouldEqual 1
lockFile.Options.ResolverStrategyForTransitives |> shouldEqual (Some ResolverStrategy.Max)

[<Test>]
let ``should parse strategy latest-patch lock file``() =
let lockFile = """STRATEGY: LATEST-PATCH
NUGET
remote: "D:\code\temp with space"
specs:
Castle.Windsor (2.1)
"""
let lockFile = LockFileParser.Parse(toLines lockFile) |> List.head
let packages = List.rev lockFile.Packages

packages.Length |> shouldEqual 1
lockFile.Options.ResolverStrategyForTransitives |> shouldEqual (Some ResolverStrategy.LatestPatch)

[<Test>]
let ``should parse strategy latest-minor lock file``() =
let lockFile = """STRATEGY: LATEST-MINOR
NUGET
remote: "D:\code\temp with space"
specs:
Castle.Windsor (2.1)
"""
let lockFile = LockFileParser.Parse(toLines lockFile) |> List.head
let packages = List.rev lockFile.Packages

packages.Length |> shouldEqual 1
lockFile.Options.ResolverStrategyForTransitives |> shouldEqual (Some ResolverStrategy.LatestMinor)

[<Test>]
let ``should parse no strategy lock file``() =
let lockFile = """NUGET
Expand Down
1 change: 1 addition & 0 deletions tests/Paket.Tests/Paket.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
<Compile Include="Resolver\AddingDependenciesSpecs.fs" />
<Compile Include="Resolver\GlobalPessimisticStrategySpecs.fs" />
<Compile Include="Resolver\GlobalOptimisticStrategySpecs.fs" />
<Compile Include="Resolver\GlobalKeepLatestPatchStrategySpecs.fs" />
<Compile Include="Resolver\StrategySpecs.fs" />
<Compile Include="Resolver\PropertyTestGenerators.fs" />
<Compile Include="Resolver\PropertyTests.fs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module DependencyGroupsAndRestrictions
module Paket.Resolver.DependencyGroupsAndRestrictions

open Paket
open NUnit.Framework
Expand Down
128 changes: 128 additions & 0 deletions tests/Paket.Tests/Resolver/GlobalKeepLatestPatchStrategySpecs.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
module Paket.Resolver.GlobalKeepLatestPatchStrategySpecs

open Paket
open NUnit.Framework
open FsUnit
open TestHelpers
open Paket.Domain
open Paket.PackageResolver

let resolve graph updateMode (cfg : DependenciesFile) =
let groups = [Constants.MainDependencyGroup, None ] |> Map.ofSeq
cfg.Resolve(true,noSha1,VersionsFromGraphAsSeq graph, (fun _ _ -> []),PackageDetailsFromGraph graph,(fun _ _ _ -> None),groups,updateMode).[Constants.MainDependencyGroup].ResolvedPackages.GetModelOrFail()

let graph =
OfSimpleGraph [
"Nancy.Bootstrappers.Windsor","0.23",["Castle.Windsor",VersionRequirement(VersionRange.AtLeast "3.2.1",PreReleaseStatus.No)]
"Castle.Windsor","3.2.1",[]
"Castle.Windsor","3.2.2",[]
"Castle.Windsor","3.3.0",[]
"Castle.Windsor","4.1.0",[]
]

let config1 = sprintf """
strategy %s
source http://www.nuget.org/api/v2

nuget Nancy.Bootstrappers.Windsor ~> 0.23
"""

[<Test>]
let ``should resolve simple config1 with latest-patch``() =
let resolved =
DependenciesFile.FromSource(config1 "latest-patch")
|> resolve graph UpdateMode.UpdateAll
getVersion resolved.[PackageName "Castle.Windsor"] |> shouldEqual "3.2.2"
getVersion resolved.[PackageName "Nancy.Bootstrappers.Windsor"] |> shouldEqual "0.23"


[<Test>]
let ``should resolve simple config1 with latest-minor``() =
let resolved =
DependenciesFile.FromSource(config1 "latest-minor")
|> resolve graph UpdateMode.UpdateAll
getVersion resolved.[PackageName "Castle.Windsor"] |> shouldEqual "3.3.0"
getVersion resolved.[PackageName "Nancy.Bootstrappers.Windsor"] |> shouldEqual "0.23"

let config2 = sprintf """
strategy %s
source http://www.nuget.org/api/v2

nuget Castle.Windsor
nuget Nancy.Bootstrappers.Windsor ~> 0.23
"""

[<Test>]
let ``should resolve simple config2 with latest-patch``() =
let resolved =
DependenciesFile.FromSource(config2 "latest-patch")
|> resolve graph UpdateMode.UpdateAll
getVersion resolved.[PackageName "Castle.Windsor"] |> shouldEqual "3.2.2"
getVersion resolved.[PackageName "Nancy.Bootstrappers.Windsor"] |> shouldEqual "0.23"


[<Test>]
let ``should resolve simple config2 with latest-minor``() =
let resolved =
DependenciesFile.FromSource(config2 "latest-minor")
|> resolve graph UpdateMode.UpdateAll
getVersion resolved.[PackageName "Castle.Windsor"] |> shouldEqual "3.3.0"
getVersion resolved.[PackageName "Nancy.Bootstrappers.Windsor"] |> shouldEqual "0.23"

let config3 = sprintf """
strategy %s
source http://www.nuget.org/api/v2

nuget Nancy.Bootstrappers.Windsor ~> 0.23
nuget Castle.Windsor
"""

[<Test>]
let ``should resolve simple config3 with latest-patch``() =
let resolved =
DependenciesFile.FromSource(config3 "latest-patch")
|> resolve graph UpdateMode.UpdateAll
getVersion resolved.[PackageName "Castle.Windsor"] |> shouldEqual "3.2.2"
getVersion resolved.[PackageName "Nancy.Bootstrappers.Windsor"] |> shouldEqual "0.23"


[<Test>]
let ``should resolve simple config3 with latest-minor``() =
let resolved =
DependenciesFile.FromSource(config3 "latest-minor")
|> resolve graph UpdateMode.UpdateAll
getVersion resolved.[PackageName "Castle.Windsor"] |> shouldEqual "3.3.0"
getVersion resolved.[PackageName "Nancy.Bootstrappers.Windsor"] |> shouldEqual "0.23"

let graph2 =
OfSimpleGraph [
"Nancy.Bootstrappers.Windsor","0.23",["Castle.Windsor",VersionRequirement(VersionRange.AtLeast "3.2.1",PreReleaseStatus.No)]
"Castle.Windsor","3.2.0",["Castle.Core",VersionRequirement(VersionRange.AtLeast "3.2.0",PreReleaseStatus.No)]
"Castle.Windsor","3.2.1",["Castle.Core",VersionRequirement(VersionRange.AtLeast "3.2.0",PreReleaseStatus.No)]
"Castle.Windsor","3.3.0",["Castle.Core",VersionRequirement(VersionRange.AtLeast "3.3.0",PreReleaseStatus.No)]
"Castle.Windsor-NLog","3.2.0.1",["Castle.Core-NLog",VersionRequirement(VersionRange.AtLeast "3.2.0",PreReleaseStatus.No)]
"Castle.Windsor-NLog","3.3.0",["Castle.Core-NLog",VersionRequirement(VersionRange.AtLeast "3.3.0",PreReleaseStatus.No)]
"Castle.Core-NLog","3.2.0",["Castle.Core",VersionRequirement(VersionRange.AtLeast "3.2.0",PreReleaseStatus.No)]
"Castle.Core-NLog","3.3.0",["Castle.Core",VersionRequirement(VersionRange.AtLeast "3.3.0",PreReleaseStatus.No)]
"Castle.Core-NLog","3.3.1",["Castle.Core",VersionRequirement(VersionRange.AtLeast "3.3.1",PreReleaseStatus.No)]
"Castle.Core","3.2.0",[]
"Castle.Core","3.2.1",[]
"Castle.Core","3.2.2",[]
"Castle.Core","3.3.0",[]
"Castle.Core","3.3.1",[]
]

let config5 = sprintf """
strategy %s
source http://www.nuget.org/api/v2

nuget Nancy.Bootstrappers.Windsor !~> 0.23
"""

[<Test>]
let ``should override global strategy with latest-patch``() =
let resolved =
DependenciesFile.FromSource(config5 "latest-patch")
|> resolve graph2 UpdateMode.UpdateAll
getVersion resolved.[PackageName "Castle.Windsor"] |> shouldEqual "3.2.1"
getVersion resolved.[PackageName "Nancy.Bootstrappers.Windsor"] |> shouldEqual "0.23"
Loading