Solver now returns Package

This commit is contained in:
Mac Malone 2021-06-02 15:21:36 -04:00
parent a462864d78
commit d5d8ff588a
2 changed files with 34 additions and 26 deletions

View file

@ -26,6 +26,7 @@ structure Manifest where
path : Option FilePath := none
module : String := name.capitalize
dependencies : List Dependency := []
deriving Inhabited
namespace Manifest
@ -37,9 +38,16 @@ end Manifest
structure Package where
dir : FilePath
manifest : Manifest
deriving Inhabited
namespace Package
def name (self : Package) : String :=
self.manifest.name
def dependencies (self : Package) : List Dependency :=
self.manifest.dependencies
def sourceDir (self : Package) : FilePath :=
self.dir / self.manifest.effectivePath

View file

@ -6,12 +6,15 @@ Authors: Gabriel Ebner, Sebastian Ullrich, Mac Malone
import Leanpkg2.Git
import Leanpkg2.Proc
import Leanpkg2.TomlManifest
import Leanpkg2.BuildConfig
open System
namespace Leanpkg2
def Assignment := List (String × FilePath)
def depsPath := buildPath / "deps"
def Assignment := List (String × Package)
namespace Assignment
def empty : Assignment := []
@ -19,10 +22,10 @@ def empty : Assignment := []
def contains (a : Assignment) (s : String) : Bool :=
(a.lookup s).isSome
def insert (a : Assignment) (k : String) (v : FilePath) : Assignment :=
def insert (a : Assignment) (k : String) (v : Package) : Assignment :=
if a.contains k then a else (k, v) :: a
def fold {α} (i : α) (f : α → String → FilePathα) : Assignment → α :=
def fold {α} (i : α) (f : α → String → Packageα) : Assignment → α :=
List.foldl (fun a ⟨k, v⟩ => f a k v) i
end Assignment
@ -32,18 +35,19 @@ abbrev Solver := StateT Assignment IO
def notYetAssigned (d : String) : Solver Bool := do
¬ (← get).contains d
def resolvedPath (d : String) : Solver FilePath := do
let some path ← pure ((← get).lookup d) | unreachable!
path
def resolvedPackage (d : String) : Solver Package := do
let some pkg ← pure ((← get).lookup d) | unreachable!
pkg
def materialize (relpath : FilePath) (dep : Dependency) : Solver Unit :=
def materialize (relPath : FilePath) (dep : Dependency) : Solver Unit :=
match dep.src with
| Source.path dir => do
let depdir := dir / relpath
let depdir := dir / relPath
IO.eprintln s!"{dep.name}: using local path {depdir}"
modify (·.insert dep.name depdir)
let m ← Manifest.fromTomlFile <| depdir / leanpkgToml
modify (·.insert dep.name ⟨depdir, m⟩)
| Source.git url rev branch => do
let depdir := FilePath.mk "build" / "deps" / dep.name
let depdir := depsPath / dep.name
if ← depdir.isDir then
IO.eprint s!"{dep.name}: trying to update {depdir} to revision {rev}"
IO.eprintln (match branch with | none => "" | some branch => "@" ++ branch)
@ -56,24 +60,20 @@ def materialize (relpath : FilePath) (dep : Dependency) : Solver Unit :=
execCmd {cmd := "git", args := #["clone", url, depdir.toString]}
let hash ← gitParseOriginRevision depdir rev
execCmd {cmd := "git", args := #["checkout", "--detach", hash], cwd := depdir}
modify (·.insert dep.name depdir)
let m ← Manifest.fromTomlFile <| depdir / leanpkgToml
modify (·.insert dep.name ⟨depdir, m⟩)
def solveDepsCore (relPath : FilePath) (d : Manifest) : (maxDepth : Nat) → Solver Unit
def solveDepsCore (pkg : String) (relPath : FilePath) (deps : List Dependency) : (maxDepth : Nat) → Solver Unit
| 0 => throw <| IO.userError "maximum dependency resolution depth reached"
| maxDepth + 1 => do
let deps ← d.dependencies.filterM (notYetAssigned ·.name)
deps.forM (materialize relPath)
for dep in deps do
let p ← resolvedPath dep.name
let d' ← Manifest.fromTomlFile <| p / leanpkgToml
unless d'.name = dep.name do
throw <| IO.userError s!"{d.name} (in {relPath}) depends on {d'.name}, but resolved dependency has name {dep.name} (in {p})"
solveDepsCore p d' maxDepth
let newDeps ← deps.filterM (notYetAssigned ·.name)
newDeps.forM (materialize relPath)
for dep in newDeps do
let depPkg ← resolvedPackage dep.name
unless depPkg.name = dep.name do
throw <| IO.userError s!"{pkg} (in {relPath}) depends on {depPkg.name}, but resolved dependency has name {dep.name} (in {depPkg.dir})"
solveDepsCore depPkg.name depPkg.dir depPkg.dependencies maxDepth
def solveDeps (m : Manifest) : IO (List Package) := do
let (_, assg) ← (solveDepsCore ⟨"."⟩ m 1024).run <| Assignment.empty.insert m.name ⟨"."⟩
assg.reverse.mapM fun ⟨depname, dirname⟩ => do
if dirname == "." then
return ⟨ dirname, m ⟩
else
return ⟨ dirname, ← Manifest.fromTomlFile <| dirname / leanpkgToml ⟩
let (_, assg) ← (solveDepsCore m.name ⟨"."⟩ m.dependencies 1024).run <| Assignment.empty.insert m.name ⟨".", m⟩
assg.reverse.mapM (·.2)