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

Convert FindRefs command to ROP #529

Merged
merged 3 commits into from
Jan 8, 2015
Merged
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
58 changes: 38 additions & 20 deletions src/Paket.Core/FindReferences.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,43 @@ open Logging
open Paket.Domain
open Paket.Rop

let FindReferencesForPackage (dependenciesFileName, package:PackageName) =
let root = Path.GetDirectoryName dependenciesFileName
let projectFiles = ProjectFile.FindAllProjects root
let lockFile = LockFile.LoadFrom((DependenciesFile.FindLockfile dependenciesFileName).FullName)

[for project,referencesFile in InstallProcess.findAllReferencesFiles root |> returnOrFail do
let installedPackages =
referencesFile
|> lockFile.GetPackageHull
|> Seq.map NormalizedPackageName
|> Set.ofSeq

if installedPackages.Contains(NormalizedPackageName package) then
yield project.FileName ]

let ShowReferencesFor (dependenciesFileName, packages : PackageName list) =
packages
|> Seq.map (fun package -> package,FindReferencesForPackage(dependenciesFileName,package))
let private findReferencesFor package (lockFile: LockFile) projects = rop {
let! referencedIn =
projects
|> Seq.map (fun (project, referencesFile) -> rop {
let! installedPackages =
referencesFile
|> lockFile.GetPackageHullSafe

let referenced =
installedPackages
|> Set.map NormalizedPackageName
|> Set.contains (NormalizedPackageName package)

return if referenced then Some project.FileName else None })
|> Rop.collect

return referencedIn |> List.choose id
}

let FindReferencesForPackage package environment = rop {
let! lockFile = environment |> PaketEnv.ensureLockFileExists

return! findReferencesFor package lockFile environment.Projects
}

let ShowReferencesFor packages environment = rop {
let! lockFile = environment |> PaketEnv.ensureLockFileExists
let! projectsPerPackage =
packages
|> Seq.map (fun package -> rop {
let! projects = findReferencesFor package lockFile environment.Projects
return package, projects })
|> Rop.collect

projectsPerPackage
|> Seq.iter (fun (PackageName k, vs) ->
tracefn "%s" k
vs |> Seq.iter (tracefn "%s")
tracefn "")
vs |> Seq.iter (tracefn "%s")
tracefn "")
}
56 changes: 39 additions & 17 deletions src/Paket.Core/LockFile.fs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,27 @@ module LockFileParser =
/// Allows to parse and analyze paket.lock files.
type LockFile(fileName:string,options,resolution:PackageResolution,remoteFiles:ResolvedSourceFile list) =

let dependenciesByPackageLazy = lazy (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why lazy? Can't be just a unit -> map function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memorization, it only needs to be calculated once.

let allDependenciesOf package =
let usedPackages = HashSet<_>()

let rec addPackage packageName =
let identity = NormalizedPackageName packageName
match resolution.TryFind identity with
| Some package ->
if usedPackages.Add packageName then
if not options.Strict then
for d,_,_ in package.Dependencies do
addPackage d
| None -> ()

addPackage package

usedPackages

resolution
|> Map.map (fun _ package -> allDependenciesOf package.Name))

member __.SourceFiles = remoteFiles
member __.ResolvedPackages = resolution
member __.FileName = fileName
Expand All @@ -308,24 +329,17 @@ type LockFile(fileName:string,options,resolution:PackageResolution,remoteFiles:R
usedPackages

/// Gets all dependencies of the given package
member this.GetAllDependenciesOf(package) =
let usedPackages = HashSet<_>()

let rec addPackage (packageName:PackageName) =
let identity = NormalizedPackageName packageName
match resolution.TryFind identity with
| Some package ->
if usedPackages.Add packageName then
if not this.Options.Strict then
for d,_,_ in package.Dependencies do
addPackage d
| None ->
let (PackageName name) = packageName
failwithf "Package %s was referenced, but it was not found in the paket.lock file." name

addPackage package
member this.GetAllDependenciesOf(package) =
match this.GetAllDependenciesOfSafe package with
| Some packages -> packages
| None ->
let (PackageName name) = package
failwithf "Package %s was referenced, but it was not found in the paket.lock file." name

usedPackages
/// Gets all dependencies of the given package
member this.GetAllDependenciesOfSafe(package) =
dependenciesByPackageLazy.Value
|> Map.tryFind (NormalizedPackageName package)

member this.GetAllNormalizedDependenciesOf(package:PackageName) =
this.GetAllDependenciesOf(package)
Expand Down Expand Up @@ -396,3 +410,11 @@ type LockFile(fileName:string,options,resolution:PackageResolution,remoteFiles:R
with exn -> failwithf "%s - in %s" exn.Message referencesFile.FileName)

usedPackages

member this.GetPackageHullSafe referencesFile =
referencesFile.NugetPackages
|> Seq.map (fun package ->
this.GetAllDependenciesOfSafe(package)
|> Rop.failIfNone (ReferenceNotFoundInLockFile(referencesFile.FileName, package)))
|> Rop.collect
|> Rop.lift (Seq.concat >> Set.ofSeq)
14 changes: 12 additions & 2 deletions src/Paket.Core/PublicAPI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ type Dependencies(dependenciesFileName: string) =
/// Get the root path
member this.RootPath with get() = Path.GetDirectoryName(dependenciesFileName)

/// Get the root directory
member private this.RootDirectory with get() = DirectoryInfo(this.RootPath)

/// Binds the given processing ROP function to current environment and executes it.
/// Throws on failure.
member private this.Process f =
PaketEnv.fromRootDirectory(this.RootDirectory)
>>= f
|> returnOrFail

/// Adds the given package without version requirements to the dependencies file.
member this.Add(package: string): unit = this.Add(package,"")

Expand Down Expand Up @@ -199,8 +209,8 @@ type Dependencies(dependenciesFileName: string) =

/// Shows all references for the given packages.
member this.ShowReferencesFor(packages: string list): unit =
FindReferences.ShowReferencesFor(dependenciesFileName,packages |> List.map PackageName)
FindReferences.ShowReferencesFor (packages |> List.map PackageName) |> this.Process

/// Finds all references for a given package.
member this.FindReferencesFor(package: string): string list =
FindReferences.FindReferencesForPackage(dependenciesFileName, PackageName package)
FindReferences.FindReferencesForPackage (PackageName package) |> this.Process
1 change: 1 addition & 0 deletions src/Paket.Core/Rop.fs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ let (<!>) = lift
let (<*>) = apply

type RopBuilder() =
member __.Zero() = succeed ()
member __.Bind(m, f) = bind f m
member __.Return(x) = succeed x
member __.ReturnFrom(x) = x
Expand Down