Skip to content

Commit

Permalink
Rewrote repo caching
Browse files Browse the repository at this point in the history
  • Loading branch information
propensive committed Aug 12, 2023
1 parent 02d28ed commit 2fe7691
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 33 deletions.
18 changes: 10 additions & 8 deletions src/model/build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ object Installation:
val configPath: Path = Home.Config() / p"fury"
val config: File = (configPath / p"config.codl").as[File]
val vault: Directory = (cache / p"vault").as[Directory]
val snapshots: Directory = (cache / p"repos").as[Directory]
val lib: Directory = (cache / p"lib").as[Directory]
val tmp: Directory = (cache / p"tmp").as[Directory]

Installation(config, cache, vault, lib, tmp)
Installation(config, cache, vault, lib, tmp, snapshots)

catch
case error: StreamCutError =>
Expand All @@ -81,12 +82,12 @@ object Installation:
throw AppError(msg"The path was not valid because $reason", error)

case class Installation
(config: File, cache: Directory, vault: Directory, lib: Directory, tmp: Directory):
(config: File, cache: Directory, vault: Directory, lib: Directory, tmp: Directory, snapshots: Directory):

def libJar(hash: Digest[Crc32])(using Raises[IoError], Raises[PathError]): File =
unsafely(lib / t"${hash.encodeAs[Hex].lower}.jar").as[File]

inline def installation(using Installation): Installation = summon[Installation]
inline def installation(using inline installation: Installation): Installation = installation

object Workspace:
def apply
Expand Down Expand Up @@ -132,11 +133,12 @@ case class Workspace(dir: Directory, buildDoc: CodlDoc, build: Build, local: May

def apply
(path: WorkPath)
(using Installation, Internet, WorkingDirectory, Log)
: Directory raises GitRefError | GitError | PathError | IoError =
mounts.keys.find(_.precedes(path)) match
case None => (dir.path + path).as[Directory]
case Some(mount) => Cache(mounts(mount).repo)
(using Installation, Internet, Stdio, Monitor, FrontEnd, WorkingDirectory, Log)
: Directory raises GitRefError | GitError | PathError | IoError | UndecodableCharError | UnencodableCharError | StreamCutError | NotFoundError | NumberError | InvalidRefError | MarkdownError | CodlReadError | DateError | UrlError =
mounts.keys.find(_.precedes(path)).match
case None => dir.path + path
case Some(mount) => Cache(mounts(mount).repo).dir.path + path
.as[Directory]


enum Phase:
Expand Down
32 changes: 22 additions & 10 deletions src/model/cache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import parasite.*
import perforate.*
import fulminate.*
import punctuation.*
import gossamer.*
import rudiments.*
import serpentine.*, hierarchies.unixOrWindows
import spectacular.*
Expand All @@ -36,19 +37,30 @@ import turbulence.*
import scala.collection.mutable as scm

object Cache:
private val ecosystems: scm.HashMap[Ecosystem, Vault] = scm.HashMap()
private val snapshots: scm.HashMap[Snapshot, Workspace] = scm.HashMap()

def apply
(snapshot: Snapshot)
(using installation: Installation, internet: Internet, workDir: WorkingDirectory, log: Log)
(using Raises[IoError], Raises[GitError], Raises[GitRefError], Raises[PathError])
: Directory =
val path = installation.cache / PathName(snapshot.commit.show)
if path.exists() && path.is[Directory] && (path / p".git").exists() then path.as[Directory]
else
val process = Git.cloneCommit(snapshot.url.encode, path, CommitHash(snapshot.commit.show))
process.complete()
path.as[Directory]
(using installation: Installation)
(using Internet, Log, Stdio, Monitor, FrontEnd, WorkingDirectory, Raises[UndecodableCharError], Raises[UnencodableCharError], Raises[NotFoundError], Raises[GitRefError], Raises[NumberError], Raises[InvalidRefError], Raises[DateError], Raises[UrlError], Raises[CodlReadError], Raises[MarkdownError], Raises[PathError], Raises[IoError], Raises[StreamCutError], Raises[GitError], GitCommand)
: Workspace =
snapshots.get(snapshot).getOrElse:
val destination = unsafely(installation.snapshots.path / PathName(snapshot.commit.show))

val directory = if !destination.exists() then
val process = Git.cloneCommit(snapshot.url.encode, destination, snapshot.commit)

follow:
process.progress.collect:
case Progress.Receiving(percent) => TaskEvent.Progress(t"receiving", percent)
case Progress.Unpacking(percent) => TaskEvent.Progress(t"unpacking", percent)
case Progress.Resolving(percent) => TaskEvent.Progress(t"resolving", percent)

private val ecosystems: scm.HashMap[Ecosystem, Vault] = scm.HashMap()
process.complete().workTree.avow(using Unsafe).path
else destination

Workspace(destination)

def apply
(ecosystem: Ecosystem)
Expand Down
42 changes: 27 additions & 15 deletions src/model/frontend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,42 +30,54 @@ import scala.collection.mutable as scm
import language.experimental.captureChecking

enum FrontEndEvent:
case Redraw(columns: Int, rows: Int)
case LogMessage(message: Message)
case TrackTask(id: Text)
case UpdateTask(id: Text, progress: Double)
case RemoveTask(id: Text)
case TaskUpdate(taskId: FrontEnd.TaskId, event: TaskEvent)

export FrontEndEvent.*
enum TaskEvent:
case Progress(stage: Text, progress: Double)
case Complete()

export FrontEndEvent.*, TaskEvent.*

def frontEnd
[ResultType]
(using monitor: Monitor, stdio: Stdio, cancel: Raises[CancelError])
(block: FrontEnd ?=> ResultType)
: ResultType^ =

val tasks: scm.HashMap[FrontEnd.TaskId, Double] = scm.HashMap()
val funnel: Funnel[FrontEndEvent] = Funnel()
val tasks: scm.HashMap[Text, Double] = scm.HashMap()

val async = Async[Unit]:
funnel.stream.foreach:
case LogMessage(message) => Io.println(message.out)
case TrackTask(id) => Io.println(msg"Started tracking $id".out)
case UpdateTask(id, progress) => Io.println(msg"Progress for $id = ${(progress*100).toInt}".out)
case RemoveTask(id) => tasks -= id
case Redraw(columns, rows) =>
acquiesce()
Io.println(t"Redrawing...")
case LogMessage(message) => Io.println(message.out)
case TaskUpdate(taskId, Complete()) => tasks.remove(taskId)
case TaskUpdate(taskId, Progress(stage, progress)) => tasks(taskId) = progress

block(using FrontEnd(funnel, async, tasks)).tap: _ =>
funnel.stop()
async.await()

object FrontEnd:
class TaskId()

@capability
case class FrontEnd
(private val funnel: Funnel[FrontEndEvent], private val async: Async[Unit],
private val tasks: scm.HashMap[Text, Double]):
private val tasks: scm.HashMap[FrontEnd.TaskId, Double]):

def log(message: Message): Unit = funnel.put(LogMessage(message))

def log(message: Message)(using frontEnd: FrontEnd): Unit = frontEnd.log(message)
def follow(stream: LazyList[TaskEvent])(using Monitor): Unit =
val taskId = FrontEnd.TaskId()

Async:
stream.map:
case Progress(stage, progress) => TaskUpdate(taskId, Progress(stage, progress))
case Complete() => TaskUpdate(taskId, Complete())
.foreach(funnel.put(_))

def log(message: Message)(using frontEnd: FrontEnd): Unit = frontEnd.log(message)

def follow(stream: LazyList[TaskEvent])(using frontEnd: FrontEnd, monitor: Monitor): Unit =
frontEnd.follow(stream)

0 comments on commit 2fe7691

Please sign in to comment.