diff --git a/src/Paket.Core/Installation/RestoreProcess.fs b/src/Paket.Core/Installation/RestoreProcess.fs index 972eb5bbf3..2936f10bbd 100644 --- a/src/Paket.Core/Installation/RestoreProcess.fs +++ b/src/Paket.Core/Installation/RestoreProcess.fs @@ -314,20 +314,22 @@ let createPaketPropsFile (lockFile:LockFile) (cliTools:ResolvedPackage seq) (pac | ExplicitRestriction fw -> ExplicitRestriction fw | _ -> group.Options.Settings.FrameworkRestrictions let condition = getExplicitRestriction restrictions - p,condition,packageSettings) - |> Seq.groupBy (fun (_,c,__) -> c) - |> Seq.collect (fun (condition,packages) -> - let condition = + + p,condition,packageSettings,group.Options.Settings.ReferenceCondition) + |> Seq.groupBy (fun (_,c,__,rc) -> c,rc) + |> Seq.collect (fun ((condition,referenceCondition),packages) -> + let targets = match condition with - | FrameworkRestriction.HasNoRestriction -> "" - | restrictions -> restrictions.ToMSBuildCondition() + | FrameworkRestriction.HasNoRestriction -> Set.empty + | restrictions -> restrictions.RepresentedFrameworks + let condition = PlatformMatching.getCondition referenceCondition targets let condition = if condition = "" || condition = "true" then "" else sprintf " AND (%s)" condition let packageReferences = packages - |> Seq.collect (fun (p,_,packageSettings) -> + |> Seq.collect (fun (p,_,packageSettings,__) -> [yield sprintf """ """ p.Name yield sprintf """ %O""" p.Version let excludeAssets = @@ -447,6 +449,7 @@ let createProjectReferencesFiles (lockFile:LockFile) (projectFile:ProjectFile) ( let combinedOmitContent = combineOmitContent resolvedPackage.Settings packageSettings let combinedImportTargets = combineImportTargets resolvedPackage.Settings packageSettings let aliases = if direct then packageSettings.Settings.Aliases |> Seq.tryHead else None + let condition = kv.Value.Options.Settings.ReferenceCondition |> Option.defaultValue "true" let privateAssetsAll = match combinedCopyLocal with @@ -481,7 +484,8 @@ let createProjectReferencesFiles (lockFile:LockFile) (projectFile:ProjectFile) ( copyLocal omitContent importTargets - alias] + alias + condition] |> String.concat "," list.Add line diff --git a/src/Paket.Core/PublicAPI.fs b/src/Paket.Core/PublicAPI.fs index 8740ad2285..654b084212 100644 --- a/src/Paket.Core/PublicAPI.fs +++ b/src/Paket.Core/PublicAPI.fs @@ -600,6 +600,13 @@ type Dependencies(dependenciesFileName: string) = |> Seq.map (fun kv -> kv.Key.ToString()) |> Seq.toList + member __.GetConditions(): string list = + let dependenciesFile = DependenciesFile.ReadFromFile dependenciesFileName + dependenciesFile.Groups + |> Seq.choose (fun kv -> kv.Value.Options.Settings.ReferenceCondition) + |> Seq.distinct + |> Seq.toList + /// Returns the direct dependencies for the given package. member this.GetDirectDependenciesForPackage(groupName,packageName:string): (string * string * string) list = let resolvedPackages = this.GetLockFile().GetGroupedResolution() @@ -854,7 +861,7 @@ type Dependencies(dependenciesFileName: string) = use fileStream = File.Open (nuspecFile, FileMode.Create) doc.Save fileStream - static member FixNuspecs (projectFile: ProjectFile, referencesFile:ReferencesFile, nuspecFileList:string list) = + static member FixNuspecs (projectFile: ProjectFile, referencesFile:ReferencesFile, nuspecFileList:string list, conditions:string list) = let attr (name: string) (node: XmlNode) = match node.Attributes.[name] with | null -> None @@ -880,8 +887,14 @@ type Dependencies(dependenciesFileName: string) = |> List.map (fun proj -> proj.NameWithoutExtension) |> Set.ofList let depsFile = deps.GetDependenciesFile() + let groupMatchesConditions groupName = + let group = depsFile.GetGroup(groupName) + match group.Options.Settings.ReferenceCondition with + | None -> true + | Some condition -> conditions |> List.contains condition let allFrameworkRestrictions = locked.GetPackageHull referencesFile + |> Seq.filter (fun kvp -> fst kvp.Key |> groupMatchesConditions) |> Seq.map(fun kvp -> snd kvp.Key, fst kvp.Key, kvp.Value.Settings.FrameworkRestrictions.GetExplicitRestriction()) @@ -898,6 +911,7 @@ type Dependencies(dependenciesFileName: string) = let projectReferencedDeps = referencesFile.Groups + |> Seq.filter (fun (KeyValue(group, _)) -> group |> groupMatchesConditions) |> Seq.collect (fun (KeyValue(group, packages)) -> packages.NugetPackages |> Seq.map (fun p -> group, p)) let groupsForProjectReferencedDeps = diff --git a/src/Paket.Core/embedded/Paket.Restore.targets b/src/Paket.Core/embedded/Paket.Restore.targets index bbeec153f5..0749ac7968 100644 --- a/src/Paket.Core/embedded/Paket.Restore.targets +++ b/src/Paket.Core/embedded/Paket.Restore.targets @@ -240,8 +240,9 @@ $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6]) $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7]) $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[8]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[9]) - + %(PaketReferencesFileLinesInfo.PackageVersion) All runtime @@ -250,7 +251,6 @@ %(PaketReferencesFileLinesInfo.Aliases) true true - @@ -314,7 +314,17 @@ - + + + + + <_DefinedConditionProperties Include="@(_ConditionProperties)" Condition="$(%(Identity)) == 'true'"/> + + + <_ConditionsParameter> + <_ConditionsParameter Condition="@(_DefinedConditionProperties) != ''">--conditions @(_DefinedConditionProperties) + + diff --git a/src/Paket/Commands.fs b/src/Paket/Commands.fs index 1794bf3222..6910575295 100644 --- a/src/Paket/Commands.fs +++ b/src/Paket/Commands.fs @@ -412,6 +412,7 @@ type FixNuspecsArgs = | [] Files of nuspecPaths:string list | [] ReferencesFile of referencePath:string | [] ProjectFile of referencePath:string + | [] Conditions of conditions:string list with interface IArgParserTemplate with member this.Usage = @@ -419,6 +420,7 @@ with | Files _ -> ".nuspec files to fix transitive dependencies within" | ReferencesFile _ -> "paket.references to use" | ProjectFile _ -> "the project file to use" + | Conditions _ -> "group conditions to filter by" type GenerateNuspecArgs = | [] Project of project:string @@ -451,6 +453,12 @@ with interface IArgParserTemplate with member __.Usage = "" +type ShowConditionsArgs = + | [] NoArgs +with + interface IArgParserTemplate with + member __.Usage = "" + type FindPackageVersionsArgs = | [] NuGet of package_ID:string | [] NuGet_Legacy of package_ID:string @@ -696,6 +704,7 @@ type Command = | [] GenerateNuspec of ParseResults | [] ShowInstalledPackages of ParseResults | [] ShowGroups of ParseResults + | [] ShowConditions of ParseResults | [] Pack of ParseResults | [] Push of ParseResults | [] GenerateIncludeScripts of ParseResults @@ -729,6 +738,7 @@ with | GenerateNuspec _ -> "generate a default nuspec for a project including its direct dependencies" | ShowInstalledPackages _ -> "show installed top-level packages" | ShowGroups _ -> "show groups" + | ShowConditions _ -> "show conditions defined on groups" | Pack _ -> "create NuGet packages from paket.template files" | Push _ -> "push a NuGet package" | GenerateIncludeScripts _ -> "[obsolete]" diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index 1d5f8f8b2f..f945a69df1 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -680,12 +680,16 @@ let fixNuspecs silent (results : ParseResults<_>) = results.GetResult FixNuspecsArgs.Files |> List.collect (fun s -> s.Split([|';'|], StringSplitOptions.RemoveEmptyEntries) |> Array.toList) |> List.map (fun s -> s.Trim()) + let conditions = + results.GetResult FixNuspecsArgs.Conditions + |> List.collect (fun s -> s.Split([|';'|], StringSplitOptions.RemoveEmptyEntries) |> Array.toList) + |> List.map (fun s -> s.Trim()) match results.TryGetResult FixNuspecsArgs.ProjectFile with | Some projectFile -> let projectFile = Paket.ProjectFile.LoadFromFile(projectFile) let refFile = RestoreProcess.FindOrCreateReferencesFile projectFile - Dependencies.FixNuspecs (projectFile, refFile, nuspecFiles) + Dependencies.FixNuspecs (projectFile, refFile, nuspecFiles, conditions) | None -> match results.TryGetResult FixNuspecsArgs.ReferencesFile with | Some referenceFile -> @@ -736,6 +740,11 @@ let showGroups (results : ParseResults) = for groupName in dependenciesFile.GetGroups() do tracefn "%s" groupName +let showConditions (results : ParseResults) = + let dependenciesFile = Dependencies.Locate() + for condition in dependenciesFile.GetConditions() do + tracefn "%s" condition + let findPackageVersions (results : ParseResults<_>) = let maxResults = let arg = (results.TryGetResult FindPackageVersionsArgs.Max_Results, @@ -894,6 +903,7 @@ let handleCommand silent command = | FixNuspecs r -> processCommand silent (fixNuspecs silent) r | ShowInstalledPackages r -> processCommand silent showInstalledPackages r | ShowGroups r -> processCommand silent showGroups r + | ShowConditions r -> processCommand silent showConditions r | Pack r -> processCommand silent pack r | Push r -> processCommand silent (push paketVersion) r | GenerateIncludeScripts r -> diff --git a/tests/Paket.Tests/InstallModel/PaketPropsTests.fs b/tests/Paket.Tests/InstallModel/PaketPropsTests.fs index 03675ba766..2550579e4a 100644 --- a/tests/Paket.Tests/InstallModel/PaketPropsTests.fs +++ b/tests/Paket.Tests/InstallModel/PaketPropsTests.fs @@ -19,8 +19,8 @@ let checkTargetFrameworkCondition msbuildCondition (itemGroup: XElement) = let checkTargetFrameworkNoRestriction itemGroup = checkTargetFrameworkCondition "" itemGroup -let checkTargetFrameworkRestriction r itemGroup = - let msbuildCond = r |> Paket.Requirements.getExplicitRestriction |> fun c -> c.ToMSBuildCondition() +let checkTargetFrameworkRestriction rc r itemGroup = + let msbuildCond = r |> Paket.Requirements.getExplicitRestriction |> fun c -> PlatformMatching.getCondition rc c.RepresentedFrameworks checkTargetFrameworkCondition (sprintf " AND (%s)" msbuildCond) itemGroup let checkContainsPackageRefs pkgRefs (group: XElement) = @@ -186,11 +186,127 @@ group Other1 match itemGroups with | [groupMain; otherGroup] -> groupMain - |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions + |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.ReferenceCondition lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions groupMain |> checkContainsPackageRefs [ "FSharp.Core","3.1.2.5"; "Argu","4.2.1" ] otherGroup - |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other1"].Options.Settings.FrameworkRestrictions + |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other1"].Options.Settings.ReferenceCondition lockFile.Groups.[Domain.GroupName "Other1"].Options.Settings.FrameworkRestrictions + otherGroup + |> checkContainsPackageRefs [ "FSharp.Core","4.3.4"; "FsCheck","2.8.2" ] + | l -> + Assert.Fail(sprintf "expected two ItemGroup but was '%A'" l) + +[] +let ``should create props file for design mode with group conditions``() = + + let lockFile = """CONDITION: COND_MAIN +NUGET + remote: https://api.nuget.org/v3/index.json + Argu (4.2.1) + FSharp.Core (>= 3.1.2) + FSharp.Core (3.1.2.5) + +GROUP Other1 +CONDITION: COND_OTHER1 +NUGET + remote: https://api.nuget.org/v3/index.json + FsCheck (2.8.2) + FSharp.Core (>= 3.1.2.5) + FSharp.Core (4.3.4) +""" + + let refFileContent = """ +FSharp.Core +Argu + +group Other1 + FSharp.Core + FsCheck +""" + + let lockFile = LockFile.Parse("", toLines lockFile) + + let refFile = ReferencesFile.FromLines(toLines refFileContent) + + let packages = + [ for kv in refFile.Groups do + let packagesInGroup,_ = lockFile.GetOrderedPackageHull(kv.Key, refFile) + yield! packagesInGroup ] + + let outPath = System.IO.Path.GetTempFileName() + Paket.RestoreProcess.createPaketPropsFile lockFile Seq.empty packages (FileInfo outPath) + + let doc = XDocument.Load(outPath, LoadOptions.PreserveWhitespace) + + let itemGroups = doc.Root.Elements (xname "ItemGroup") |> Seq.toList + + match itemGroups with + | [groupMain; otherGroup] -> + groupMain + |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.ReferenceCondition lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions + groupMain + |> checkContainsPackageRefs [ "FSharp.Core","3.1.2.5"; "Argu","4.2.1" ] + otherGroup + |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other1"].Options.Settings.ReferenceCondition lockFile.Groups.[Domain.GroupName "Other1"].Options.Settings.FrameworkRestrictions + otherGroup + |> checkContainsPackageRefs [ "FSharp.Core","4.3.4"; "FsCheck","2.8.2" ] + | l -> + Assert.Fail(sprintf "expected two ItemGroup but was '%A'" l) + +[] +let ``should create props file for design mode with group restrictions and conditions``() = + + let lockFile = """CONDITION: COND_MAIN +RESTRICTION: && (>= net461) (< net47) +NUGET + remote: https://api.nuget.org/v3/index.json + Argu (4.2.1) + FSharp.Core (>= 3.1.2) + FSharp.Core (3.1.2.5) + +GROUP Other1 +CONDITION: COND_OTHER1 +RESTRICTION: == netstandard2.0 +NUGET + remote: https://api.nuget.org/v3/index.json + FsCheck (2.8.2) + FSharp.Core (>= 3.1.2.5) + FSharp.Core (4.3.4) +""" + + let refFileContent = """ +FSharp.Core +Argu + +group Other1 + FSharp.Core + FsCheck +""" + + let lockFile = LockFile.Parse("", toLines lockFile) + + let refFile = ReferencesFile.FromLines(toLines refFileContent) + + let packages = + [ for kv in refFile.Groups do + let packagesInGroup,_ = lockFile.GetOrderedPackageHull(kv.Key, refFile) + yield! packagesInGroup ] + + let outPath = System.IO.Path.GetTempFileName() + Paket.RestoreProcess.createPaketPropsFile lockFile Seq.empty packages (FileInfo outPath) + + let doc = XDocument.Load(outPath, LoadOptions.PreserveWhitespace) + + let itemGroups = doc.Root.Elements (xname "ItemGroup") |> Seq.toList + + match itemGroups with + | [groupMain; otherGroup] -> + groupMain + |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.ReferenceCondition lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions + groupMain + |> checkContainsPackageRefs [ "FSharp.Core","3.1.2.5"; "Argu","4.2.1" ] + otherGroup + |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other1"].Options.Settings.ReferenceCondition lockFile.Groups.[Domain.GroupName "Other1"].Options.Settings.FrameworkRestrictions otherGroup |> checkContainsPackageRefs [ "FSharp.Core","4.3.4"; "FsCheck","2.8.2" ] | l -> @@ -243,17 +359,17 @@ group Other2 match itemGroups with | [groupMain; otherGroup20And21; otherGroupOnly21] -> groupMain - |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions + |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.ReferenceCondition lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.FrameworkRestrictions groupMain |> checkContainsPackageRefs [ "FSharp.Core","3.1.2.5"; "Argu","4.2.1" ] otherGroup20And21 - |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other2"].Options.Settings.FrameworkRestrictions + |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other2"].Options.Settings.ReferenceCondition lockFile.Groups.[Domain.GroupName "Other2"].Options.Settings.FrameworkRestrictions otherGroup20And21 |> checkContainsPackageRefs [ "FSharp.Core","4.3.4" ] otherGroupOnly21 - |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other2"].Resolution.[Domain.PackageName "FsCheck"].Settings.FrameworkRestrictions + |> checkTargetFrameworkRestriction lockFile.Groups.[Domain.GroupName "Other2"].Options.Settings.ReferenceCondition lockFile.Groups.[Domain.GroupName "Other2"].Resolution.[Domain.PackageName "FsCheck"].Settings.FrameworkRestrictions otherGroupOnly21 |> checkContainsPackageRefs [ "FsCheck","2.8.2" ] | l -> @@ -286,11 +402,11 @@ Newtonsoft.Json let doc = XDocument.Load(outPath, LoadOptions.PreserveWhitespace) let itemGroups = doc.Root.Elements (xname "ItemGroup") |> Seq.toList - + match itemGroups with | [groupMain] -> groupMain - |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[Domain.PackageName "Newtonsoft.Json"].Settings.FrameworkRestrictions + |> checkTargetFrameworkRestriction lockFile.Groups.[Constants.MainDependencyGroup].Options.Settings.ReferenceCondition lockFile.Groups.[Constants.MainDependencyGroup].Resolution.[Domain.PackageName "Newtonsoft.Json"].Settings.FrameworkRestrictions groupMain |> checkContainsPackageRefs [ "Newtonsoft.Json","11.0.2" ] | l ->