diff --git a/src/Paket.Core/Simplifier.fs b/src/Paket.Core/Simplifier.fs index a157ba496f..42a7349fe4 100644 --- a/src/Paket.Core/Simplifier.fs +++ b/src/Paket.Core/Simplifier.fs @@ -21,28 +21,13 @@ let private simplify file before after = let private interactiveConfirm fileName (PackageName package) = Utils.askYesNo(sprintf "Do you want to remove indirect dependency %s from file %s ?" package fileName) -let Analyze(allPackages : list, depFile : DependenciesFile, refFiles : ReferencesFile list, interactive) = +let Analyze(lockFile : LockFile, depFile : DependenciesFile, refFiles : ReferencesFile list, interactive) = + let lookupDeps packageName = + let deps = lockFile.GetAllDependenciesOf packageName + deps.Remove(packageName) |> ignore + deps |> Set.ofSeq - let depsLookup = - allPackages - |> Seq.map (fun package -> NormalizedPackageName package.Name, - package.Dependencies - |> Set.map (fun (name,_,_) -> name)) - |> Map.ofSeq - - let rec getAllDeps (package : NormalizedPackageName) = - Set.union depsLookup.[package] - (Set.unionMany (depsLookup.[package] |> Set.map NormalizedPackageName |> Set.map getAllDeps)) - - let flattenedLookup = depsLookup |> Map.map (fun key _ -> getAllDeps key) - let getSimplifiedDeps (depNameFun : 'a -> PackageName) fileName allDeps = - let lookupDeps packageName = - match flattenedLookup |> Map.tryFind (NormalizedPackageName packageName) with - | Some deps -> deps - | None -> failwithf "unable to simplify %s - lock file doesn't include package %s, try running paket update" - fileName - (let (PackageName name) = packageName in name) let indirectDeps = allDeps |> List.map depNameFun @@ -53,9 +38,7 @@ let Analyze(allPackages : list, depFile : DependenciesFile, ref allDeps |> List.filter (fun dep -> not <| Set.contains (NormalizedPackageName (depNameFun dep)) depsToRemove) let simplifiedDeps = depFile.Packages |> getSimplifiedDeps (fun p -> p.Name) depFile.FileName |> Seq.toList - let refFiles' = if depFile.Options.Strict - then refFiles - else refFiles |> List.map (fun refFile -> {refFile with NugetPackages = + let refFiles' = refFiles |> List.map (fun refFile -> {refFile with NugetPackages = refFile.NugetPackages |> getSimplifiedDeps id refFile.FileName}) DependenciesFile(depFile.FileName, depFile.Options, depFile.Sources, simplifiedDeps, depFile.RemoteFiles), refFiles' @@ -69,20 +52,16 @@ let Simplify (dependenciesFileName,interactive) = failwith "lock file not found. Create lock file by running paket install." let lockFile = LockFile.LoadFrom(lockFilePath.FullName) - let packages = lockFile.ResolvedPackages |> Seq.map (fun kv -> kv.Value) |> List.ofSeq let refFiles = ProjectFile.FindAllProjects(Path.GetDirectoryName lockFile.FileName) |> Array.choose (fun p -> ProjectFile.FindReferencesFile <| FileInfo(p.FileName)) |> Array.map ReferencesFile.FromFile let refFilesBefore = refFiles |> Array.map (fun refFile -> refFile.FileName, refFile) |> Map.ofArray - let simplifiedDepFile, simplifiedRefFiles = Analyze(packages, depFile, Array.toList refFiles, interactive) + let simplifiedDepFile, simplifiedRefFiles = Analyze(lockFile, depFile, Array.toList refFiles, interactive) printfn "" simplify depFile.FileName <| depFile.ToString() <| simplifiedDepFile.ToString() - if depFile.Options.Strict then - traceWarn ("Strict mode detected. Will not attempt to simplify " + Constants.ReferencesFile + " files.") - else - for refFile in simplifiedRefFiles do - simplify refFile.FileName <| refFilesBefore.[refFile.FileName].ToString() <| refFile.ToString() \ No newline at end of file + for refFile in simplifiedRefFiles do + simplify refFile.FileName <| refFilesBefore.[refFile.FileName].ToString() <| refFile.ToString() \ No newline at end of file diff --git a/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs b/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs index 1fda823e33..b5130da141 100644 --- a/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs +++ b/tests/Paket.Tests/Simplifier/BasicScenarioSpecs.fs @@ -5,22 +5,21 @@ open Paket open NUnit.Framework open FsUnit open Paket.Domain - -let toPackages = - List.map - (fun (name, ver, deps) -> - { Name = PackageName name - Version = SemVer.Parse ver - Source = PackageSources.DefaultNugetSource - Unlisted = false - FrameworkRestriction = None - Dependencies = deps |> List.map (fun (name, verRan) -> PackageName name, NugetVersionRangeParser.parse verRan,None) |> Set.ofList } : PackageResolver.ResolvedPackage) - -let graph1 = - ["A", "3.3.0", ["B", "3.3.0"; "C", "1.0"] - "B", "3.3.0", [] - "C", "1.0", [] - "D", "2.1", ["B", "3.0"; "C", "1.0"]] |> toPackages +open Paket.TestHelpers + + +let lockFile1 = """ +NUGET + remote: https://nuget.org/api/v2 + specs: + A (1.0) + B (1.0) + C (1.0) + B (1.0) + C (1.0) + D (1.0) + B (1.0) + C (1.0)""" |> (fun x -> LockFile.Parse("", toLines x)) let depFile1 = """ source http://nuget.org/api/v2 @@ -39,33 +38,39 @@ let refFiles1 = [ [] let ``should remove one level deep indirect dependencies from dep and ref files``() = - let depFile,refFiles = Simplifier.Analyze(graph1, cfg, refFiles1, false) + let depFile,refFiles = Simplifier.Analyze(lockFile1, cfg, refFiles1, false) - depFile.Packages |> List.length |> shouldEqual [|"A";"D"|].Length - depFile.DirectDependencies.[PackageName "A"].Range |> shouldEqual (VersionRange.Exactly "3.3.0") - depFile.DirectDependencies.[PackageName "D"].Range |> shouldEqual (VersionRange.Exactly "2.1") + depFile.Packages |> List.map (fun p -> p.Name) |> shouldEqual [PackageName"A";PackageName"D"] refFiles.Head.NugetPackages |> shouldEqual [PackageName "A";PackageName "D"] refFiles.Tail.Head.NugetPackages |> shouldEqual [PackageName "B";PackageName "C"] -let graph2 = - ["A", "1.0", ["b", "1.5"] - "b", "1.5", ["D", "2.0"] - "C", "2.0", ["e", "3.0"] - "d", "2.0", ["E", "3.0"] - "E", "3.0", ["f", "4.0"] - "F", "4.0", []] |> toPackages +let lockFile2 = """ +NUGET + remote: https://nuget.org/api/v2 + specs: + A (1.0) + B (1.0) + B (1.0) + D (1.0) + C (1.0) + E (1.0) + D (1.0) + E (1.0) + E (1.0) + F (1.0) + F (1.0)""" |> (fun x -> LockFile.Parse("", toLines x)) let depFile2 = """ source http://nuget.org/api/v2 nuget A 1.0 -nuget B 1.5 -nuget c 2.0 -nuget D 2.0 -nuget E 3.0 -nuget f 4.0""" +nuget B 1.0 +nuget C 1.0 +nuget D 1.0 +nuget E 1.0 +nuget F 1.0""" let cfg2 = DependenciesFile.FromCode(depFile2) @@ -76,11 +81,35 @@ let refFiles2 = [ [] let ``should remove all indirect dependencies from dep file recursively``() = - let depFile,refFiles = Simplifier.Analyze(graph2, cfg2, refFiles2, false) + let depFile,refFiles = Simplifier.Analyze(lockFile2, cfg2, refFiles2, false) - depFile.Packages |> List.length |> shouldEqual [|"A";"c"|].Length - depFile.DirectDependencies.[PackageName "A"].Range |> shouldEqual (VersionRange.Exactly "1.0") - depFile.DirectDependencies.[PackageName "c"].Range |> shouldEqual (VersionRange.Exactly "2.0") + depFile.Packages |> List.map (fun p -> p.Name) |> shouldEqual [PackageName"A";PackageName"C"] refFiles.Head.NugetPackages |> shouldEqual [PackageName "A";PackageName "C"] refFiles.Tail.Head.NugetPackages |> shouldEqual [PackageName "C";PackageName "D"] + + + +let strictLockFile = """REFERENCES: STRICT +NUGET + remote: https://nuget.org/api/v2 + specs: + A (1.0) + B (1.0) + B (1.0)""" + +let strictDepFile = """ +references strict +source http://nuget.org/api/v2 + +nuget A 1.0 +nuget B 1.0""" + + +[] +let ``should not remove dependency in strict mode``() = + let lockFile = strictLockFile |> (fun x -> LockFile.Parse("", toLines x)) + let cfg = DependenciesFile.FromCode(strictDepFile) + let depFile,refFiles = Simplifier.Analyze(lockFile, cfg, [], false) + + depFile.Packages |> List.map (fun p -> p.Name) |> shouldEqual [PackageName"A";PackageName"B"] \ No newline at end of file