From 96c50975f205c621a097137b09f8fac2bef68706 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Wed, 14 Jul 2010 19:24:50 -0400 Subject: [PATCH] * move Environment classes to util/env module * move TrapExit, SelectMainClass to run module * rearrange some compilation-related code * Jetty-related code moved to web module --- LICENSE | 2 +- NOTICE | 2 +- util/collection/Dag.scala | 34 +++++++++++ .../src/test/scala/DagSpecification.scala | 56 +++++++++++++++++++ util/control/ExitHook.scala | 32 +++++++++++ util/process/NOTICE | 3 + 6 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 util/collection/Dag.scala create mode 100644 util/collection/src/test/scala/DagSpecification.scala create mode 100644 util/control/ExitHook.scala create mode 100644 util/process/NOTICE diff --git a/LICENSE b/LICENSE index 15f983d64..46c73ae23 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2008, 2009, 2010 Mark Harrah, Tony Sloane, Jason Zaugg +Copyright (c) 2008, 2009, 2010 Steven Blundy, Josh Cough, Mark Harrah, Stuart Roebuck, Tony Sloane, Vesa Vilhonen, Jason Zaugg All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/NOTICE b/NOTICE index 63326efeb..88899abdc 100644 --- a/NOTICE +++ b/NOTICE @@ -1,4 +1,4 @@ -Simple Build Tool (xsbt components other than sbt/) +Simple Build Tool Copyright 2008, 2009, 2010 Mark Harrah, Jason Zaugg Licensed under BSD-style license (see LICENSE) diff --git a/util/collection/Dag.scala b/util/collection/Dag.scala new file mode 100644 index 000000000..3ecc1f95b --- /dev/null +++ b/util/collection/Dag.scala @@ -0,0 +1,34 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 David MacIver, Mark Harrah + */ +package sbt; + +trait Dag[Node <: Dag[Node]]{ + self : Node => + + def dependencies : Iterable[Node] + def topologicalSort = Dag.topologicalSort(self)(_.dependencies) +} +object Dag +{ + import scala.collection.{mutable, JavaConversions}; + import JavaConversions.{asIterable, asSet} + + def topologicalSort[T](root: T)(dependencies: T => Iterable[T]) = { + val discovered = new mutable.HashSet[T] + val finished = asSet(new java.util.LinkedHashSet[T]) + + def visit(dag : T){ + if (!discovered(dag)) { + discovered(dag) = true; + dependencies(dag).foreach(visit); + finished += dag; + } + } + + visit(root); + + finished.toList; + } +} + diff --git a/util/collection/src/test/scala/DagSpecification.scala b/util/collection/src/test/scala/DagSpecification.scala new file mode 100644 index 000000000..7cf19f2df --- /dev/null +++ b/util/collection/src/test/scala/DagSpecification.scala @@ -0,0 +1,56 @@ +/* sbt -- Simple Build Tool + * Copyright 2008 Mark Harrah */ + +package sbt + +import org.scalacheck._ +import Prop._ + +import scala.collection.mutable.HashSet + +object DagSpecification extends Properties("Dag") +{ + property("No repeated nodes") = forAll{ (dag: TestDag) => isSet(dag.topologicalSort) } + property("Sort contains node") = forAll{ (dag: TestDag) => dag.topologicalSort.contains(dag) } + property("Dependencies precede node") = forAll{ (dag: TestDag) => dependenciesPrecedeNodes(dag.topologicalSort) } + + implicit lazy val arbTestDag: Arbitrary[TestDag] = Arbitrary(Gen.sized(dagGen)) + private def dagGen(nodeCount: Int): Gen[TestDag] = + { + val nodes = new HashSet[TestDag] + def nonterminalGen(p: Gen.Params): Gen[TestDag] = + { + for(i <- 0 until nodeCount; nextDeps <- Gen.someOf(nodes).apply(p)) + nodes += new TestDag(i, nextDeps) + for(nextDeps <- Gen.someOf(nodes)) yield + new TestDag(nodeCount, nextDeps) + } + Gen.parameterized(nonterminalGen) + } + + private def isSet[T](c: Seq[T]) = Set(c: _*).size == c.size + private def dependenciesPrecedeNodes(sort: List[TestDag]) = + { + val seen = new HashSet[TestDag] + def iterate(remaining: List[TestDag]): Boolean = + { + remaining match + { + case Nil => true + case node :: tail => + if(node.dependencies.forall(seen.contains) && !seen.contains(node)) + { + seen += node + iterate(tail) + } + else + false + } + } + iterate(sort) + } +} +class TestDag(id: Int, val dependencies: Iterable[TestDag]) extends Dag[TestDag] +{ + override def toString = id + "->" + dependencies.mkString("[", ",", "]") +} \ No newline at end of file diff --git a/util/control/ExitHook.scala b/util/control/ExitHook.scala new file mode 100644 index 000000000..00f7b0d66 --- /dev/null +++ b/util/control/ExitHook.scala @@ -0,0 +1,32 @@ +/* sbt -- Simple Build Tool + * Copyright 2009, 2010 Mark Harrah + */ +package sbt + +/** Defines a function to call as sbt exits.*/ +trait ExitHook extends NotNull +{ + /** Provides a name for this hook to be used to provide feedback to the user. */ + def name: String + /** Subclasses should implement this method, which is called when this hook is executed. */ + def runBeforeExiting(): Unit +} + +trait ExitHookRegistry +{ + def register(hook: ExitHook): Unit + def unregister(hook: ExitHook): Unit +} + + +class ExitHooks extends ExitHookRegistry +{ + private val exitHooks = new scala.collection.mutable.HashSet[ExitHook] + def register(hook: ExitHook) { exitHooks += hook } + def unregister(hook: ExitHook) { exitHooks -= hook } + /** Calls each registered exit hook, trapping any exceptions so that each hook is given a chance to run. */ + def runExitHooks(debug: String => Unit): List[Throwable] = + exitHooks.toList.flatMap( hook => + ErrorHandling.wideConvert( hook.runBeforeExiting() ).left.toOption + ) +} \ No newline at end of file diff --git a/util/process/NOTICE b/util/process/NOTICE new file mode 100644 index 000000000..789c9ff1f --- /dev/null +++ b/util/process/NOTICE @@ -0,0 +1,3 @@ +Simple Build Tool: Process Component +Copyright 2008, 2009, 2010 Mark Harrah, Vesa Vilhonen +Licensed under BSD-style license (see LICENSE) \ No newline at end of file