Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .fury/config
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
#
# For more information, please visit https://propensive.com/fury/
#
layerRef QmafRvj9EPQ2iskiiJcmupwRdZeyTTGCUq4NosJP9hYEAq
layerRef QmYV5YS9HvjTpWid9KL76HDntKwmtbRT4qdzMCgXMGcbq5
# vim: set noai ts=12 sw=12:
Binary file modified .fury/layers.db
Binary file not shown.
7 changes: 3 additions & 4 deletions src/build/build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ case class LayerCli(cli: Cli)(implicit log: Log) {
ttl <- Try(call(ExpiryArg).toOption.getOrElse(if(public) 30 else 7))
_ <- layer.verifyConf(false, conf, Pointer.Root, quiet = raw, force)

ref <- if(!public) Layer.store(layer)
ref <- if(!public) layer.ref
else for {
token <- ManagedConfig().token.ascribe(NotAuthenticated()).orElse(ConfigCli(cli).doAuth)
ref <- Layer.share(ManagedConfig().service, layer, token, ttl)
Expand All @@ -667,7 +667,7 @@ case class LayerCli(cli: Cli)(implicit log: Log) {
layer <- Layer.retrieve(conf)
call <- cli.call()
_ <- layer.verifyConf(true, conf, Pointer.Root, quiet = false, force = false)
ref <- Layer.store(layer)
ref <- layer.ref
_ <- ~log.info(msg"Writing layer database to ${layout.layerDb.relativizeTo(layout.baseDir)}")
_ <- Layer.writeDb(layer, layout)
gitDir <- ~GitDir(layout)
Expand Down Expand Up @@ -723,7 +723,7 @@ case class LayerCli(cli: Cli)(implicit log: Log) {
layer <- Layer.get(conf.layerRef, conf.published)
previous <- layer.previous.ascribe(CannotUndo())
layer <- Layer.get(previous, None)
layerRef <- Layer.store(layer)
layerRef <- layer.ref
_ <- ~log.info(msg"Reverted to layer $layerRef")
_ <- Layer.saveFuryConf(conf.copy(layerRef = layerRef), layout)
} yield log.await()
Expand Down Expand Up @@ -812,7 +812,6 @@ case class LayerCli(cli: Cli)(implicit log: Log) {
published <- imported.remote.ascribe(ImportHasNoRemote())
(newPub, newRef) <- getNewLayer(imported.layerRef, published, version, pointer / importId)
newLayer <- Layer.get(newRef, Some(newPub))
//_ <- ~log.info(msg"newLayer = ${artifact.layerRef}/$newPub")

newLayer <- if(recursive) ~updateAll(newLayer, pointer / importId,
newLayer.imports.map(_.id).to[List], recursive, None) else ~newLayer
Expand Down
11 changes: 5 additions & 6 deletions src/core/hierarchy.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ case class Hierarchy(layer: Layer, path: Pointer, children: Map[ImportId, Hierar
def update(pointer: Pointer, newLayer: Layer)(implicit log: Log): Try[Hierarchy] =
if(pointer.isEmpty) Success(copy(layer = newLayer))
else children.get(pointer.head).ascribe(CantResolveLayer(pointer)).flatMap { hierarchy =>
hierarchy.update(pointer.tail, newLayer).flatMap { h => h.layerRef.map { ref =>
hierarchy.update(pointer.tail, newLayer).flatMap { h => h.layer.ref.map { ref =>
copy(
children = children.updated(pointer.head, h),
layer = Layer(_.imports(pointer.head).layerRef)(layer) = ref
Expand All @@ -58,17 +58,16 @@ case class Hierarchy(layer: Layer, path: Pointer, children: Map[ImportId, Hierar

def save(pointer: Pointer, layout: Layout)(implicit log: Log): Try[LayerRef] =
children.values.to[List].traverse(_.save(pointer, layout)).flatMap { _ =>
layerRef.flatMap { ref =>
layer.ref.flatMap { ref =>
if(path.isEmpty) Layer.saveFuryConf(FuryConf(ref, pointer), layout).map(ref.waive) else Success(ref)
}
}

lazy val layerRef: Try[LayerRef] = Layer.store(layer)(Log())
def focus(pointer: Pointer): Try[Focus] = layerRef >> (Focus(_, pointer, None))
def focus(pointer: Pointer): Try[Focus] = layer.ref >> (Focus(_, pointer, None))

def focus(pointer: Pointer, projectId: ProjectId): Try[Focus] =
layerRef >> (Focus(_, pointer, Some((projectId, None))))
layer.ref >> (Focus(_, pointer, Some((projectId, None))))

def focus(pointer: Pointer, projectId: ProjectId, moduleId: ModuleId): Try[Focus] =
layerRef >> (Focus(_, pointer, Some((projectId, Some(moduleId)))))
layer.ref >> (Focus(_, pointer, Some((projectId, Some(moduleId)))))
}
3 changes: 3 additions & 0 deletions src/core/layer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ case class Layer(version: Int,
mainRepo: Option[RepoId] = None,
previous: Option[LayerRef] = None) { layer =>

lazy val ref: Try[LayerRef] = Layer.store(this)(Log())

def apply(id: ProjectId) = projects.findBy(id)
def moduleRefs: SortedSet[ModuleRef] = projects.flatMap(_.moduleRefs)
def mainProject: Try[Option[Project]] = main.map(projects.findBy(_)).to[List].sequence.map(_.headOption)
Expand Down Expand Up @@ -379,6 +381,7 @@ object Layer extends Lens.Partial[Layer] {

def saveFuryConf(conf: FuryConf, layout: Layout)(implicit log: Log): Try[FuryConf] = for {
confStr <- ~Ogdl.serialize(Ogdl(conf))
_ <- ~Trigger.notify(layout.baseDir, System.currentTimeMillis())
_ <- layout.confFile.writeSync(confComments+confStr+vimModeline)
} yield conf

Expand Down
5 changes: 4 additions & 1 deletion src/core/source.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ sealed abstract class Source extends Key(msg"source") {
def dir: Path
def glob: Glob
def repoIdentifier: RepoId
def local: Boolean

def base(snapshots: Snapshots, layout: Layout): Try[Path]
def dir(snapshots: Snapshots, layout: Layout): Try[Path] = base(snapshots, layout).map(dir in _)

def files(snapshots: Snapshots, layout: Layout): Try[Stream[Path]] =
dir(snapshots, layout).map { dir => glob(dir, dir.walkTree) }

Expand All @@ -103,6 +104,7 @@ sealed abstract class Source extends Key(msg"source") {
case class RepoSource(repoId: RepoId, dir: Path, glob: Glob) extends Source {
def key: String = str"${repoId}:${dir.value}//$glob"
def completion: String = str"${repoId}:${dir.value}"
def local: Boolean = false
def repoIdentifier: RepoId = repoId
def hash(layer: Layer): Try[Digest] = layer.repos.findBy(repoId).map((dir, _).digest[Md5])
def base(snapshots: Snapshots, layout: Layout): Try[Path] =
Expand All @@ -111,6 +113,7 @@ case class RepoSource(repoId: RepoId, dir: Path, glob: Glob) extends Source {

case class LocalSource(dir: Path, glob: Glob) extends Source {
def key: String = str"${dir.value}//$glob"
def local: Boolean = true
def completion: String = dir.value
def hash(layer: Layer): Try[Digest] = Success((-1, dir).digest[Md5])
def repoIdentifier: RepoId = RepoId("local")
Expand Down
15 changes: 14 additions & 1 deletion src/core/structure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ sealed trait MenuStructure {
def show: Boolean
def shortcut: Char
def needsLayer: Boolean

def apply(path: List[String]): Option[MenuStructure] = path match {
case Nil => Some(this)
case "" :: tail => apply(tail)
case head :: tail => submenu(head).flatMap(_(tail))
}

def submenu(item: String): Option[MenuStructure]
}

case class Action(
Expand All @@ -35,7 +43,9 @@ case class Action(
show: Boolean = true,
shortcut: Char = '\u0000',
needsLayer: Boolean = true)
extends MenuStructure
extends MenuStructure {
def submenu(item: String): Option[MenuStructure] = None
}

case class Menu(
command: Symbol,
Expand All @@ -47,6 +57,9 @@ case class Menu(
)(val items: MenuStructure*)
extends MenuStructure {


def submenu(item: String): Option[MenuStructure] = items.find(_.command.name == item)

def apply(cli: Cli, ctx: Cli, reentrant: Boolean = false): Try[ExitStatus] = {
val hasLayer: Boolean = cli.layout.map(_.confFile.exists).getOrElse(false)
if(cli.args.args == Seq("interrupt")) {
Expand Down
50 changes: 50 additions & 0 deletions src/core/trigger.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*

Fury, version 0.33.0. Copyright 2018-20 Jon Pretty, Propensive OÜ.

The primary distribution site is: https://propensive.com/

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.

*/
package fury.core

import fury.io._, fury.text._

import scala.concurrent._
import scala.collection.mutable.HashMap

import scala.util._

object Trigger {

private case class Waiting(timestamp: Long, promises: Set[Promise[Long]])

private val waiting: HashMap[Path, Waiting] = HashMap()

def listen(path: Path): Promise[Long] = Trigger.synchronized {
val promise = Promise[Long]()
Log().info(msg"Listening for updates to $path")
waiting(path) = waiting.get(path).fold(Waiting(0L, Set(promise))) { wait =>
wait.copy(promises = wait.promises + promise)
}
promise
}

def notify(path: Path, timestamp: Long): Unit = Trigger.synchronized {
Log().info(msg"Notifying ${waiting.get(path).fold(0)(_.promises.size)} listeners to $path")
waiting.get(path).foreach(_.promises.foreach(_.complete(Success(timestamp))))
waiting(path) = Waiting(System.currentTimeMillis, Set())
}

def shutdown(): Unit = Trigger.synchronized {
waiting.values.foreach(_.promises.foreach(_.complete(Success(0L))))
}
}
1 change: 1 addition & 0 deletions src/core/uniqueness.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ sealed trait Uniqueness[Ref, Origin] {
def allOrigins: Set[Origin]
def one: Option[Origin]
def any: Option[Origin]
def some: Origin = any.orElse(one).get
}

object Uniqueness {
Expand Down
3 changes: 3 additions & 0 deletions src/frontend/main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ object FuryServer {

def main(args: Array[String]): Unit = {
def exit(code: Int) = {
Rest.shutdown()
Trigger.shutdown()
Lifecycle.shutdown()
System.exit(code)
}
Expand All @@ -73,6 +75,7 @@ object FuryServer {
env: Environment)
: Unit =
exit {
Rest.start(env)
val pid = Pid(args.head.toInt)
implicit val log: Log = Log.log(pid)

Expand Down
7 changes: 5 additions & 2 deletions src/frontend/menu.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,11 @@ object FuryMenu {
Action('list, msg"list sources for the module", SourceCli(_).list, shortcut = 'l')
),

Action('stop, msg"gracefully shut down the Fury server", ((_: Cli) => Lifecycle.shutdown()),
needsLayer = false),
Action('stop, msg"gracefully shut down the Fury server", { (_: Cli) =>
Rest.shutdown()
Trigger.shutdown()
Lifecycle.shutdown()
}, needsLayer = false),

Menu('repo, msg"manage source repositories for the layer", 'list, shortcut = 'r')(
Action('add, msg"add a source repository to the layer", RepoCli(_).add, shortcut = 'a'),
Expand Down
Loading