mirror of https://github.com/sbt/sbt.git
cleanup
This commit is contained in:
parent
12336b79f6
commit
34df04c378
|
|
@ -1,136 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
private object DependencyTracking
|
||||
{
|
||||
import scala.collection.mutable.{Set, HashMap, Map, MultiMap}
|
||||
type DependencyMap[T] = HashMap[T, Set[T]] with MultiMap[T, T]
|
||||
def newMap[T]: DependencyMap[T] = new HashMap[T, Set[T]] with MultiMap[T, T]
|
||||
type TagMap[T] = Map[T, Array[Byte]]
|
||||
def newTagMap[T] = new HashMap[T, Array[Byte]]
|
||||
}
|
||||
|
||||
trait UpdateTracking[T] extends NotNull
|
||||
{
|
||||
def dependency(source: T, dependsOn: T): Unit
|
||||
def use(source: T, uses: T): Unit
|
||||
def product(source: T, output: T): Unit
|
||||
def tag(source: T, t: Array[Byte]): Unit
|
||||
def read: ReadTracking[T]
|
||||
// removes files from all maps, both keys and values
|
||||
def removeAll(files: Iterable[T]): Unit
|
||||
// removes sources as keys/values in source, product maps and as values in reverseDependencies map
|
||||
def pending(sources: Iterable[T]): Unit
|
||||
}
|
||||
trait ReadTracking[T] extends NotNull
|
||||
{
|
||||
def isProduct(file: T): Boolean
|
||||
def isSource(file: T): Boolean
|
||||
def isUsed(file: T): Boolean
|
||||
def dependsOn(file: T): Set[T]
|
||||
def products(file: T): Set[T]
|
||||
def sources(file: T): Set[T]
|
||||
def usedBy(file: T): Set[T]
|
||||
def tag(file: T): Array[Byte]
|
||||
def allProducts: Set[T]
|
||||
def allSources: Set[T]
|
||||
def allUsed: Set[T]
|
||||
def allTags: Seq[(T,Array[Byte])]
|
||||
}
|
||||
import DependencyTracking.{DependencyMap => DMap, newMap, newTagMap, TagMap}
|
||||
private object DefaultTracking
|
||||
{
|
||||
def apply[T](translateProducts: Boolean): DependencyTracking[T] =
|
||||
new DefaultTracking(translateProducts)(newMap, newMap, newMap, newTagMap)
|
||||
}
|
||||
private final class DefaultTracking[T](translateProducts: Boolean)
|
||||
(val reverseDependencies: DMap[T], val reverseUses: DMap[T], val sourceMap: DMap[T], val tagMap: TagMap[T])
|
||||
extends DependencyTracking[T](translateProducts)
|
||||
{
|
||||
val productMap: DMap[T] = forward(sourceMap) // map from a source to its products. Keep in sync with sourceMap
|
||||
}
|
||||
// if translateProducts is true, dependencies on a product are translated to dependencies on a source
|
||||
// if there is a source recorded as generating that product
|
||||
private abstract class DependencyTracking[T](translateProducts: Boolean) extends ReadTracking[T] with UpdateTracking[T]
|
||||
{
|
||||
val reverseDependencies: DMap[T] // map from a file to the files that depend on it
|
||||
val reverseUses: DMap[T] // map from a file to the files that use it
|
||||
val sourceMap: DMap[T] // map from a product to its sources. Keep in sync with productMap
|
||||
val productMap: DMap[T] // map from a source to its products. Keep in sync with sourceMap
|
||||
val tagMap: TagMap[T]
|
||||
|
||||
def read = this
|
||||
|
||||
final def dependsOn(file: T): Set[T] = get(reverseDependencies, file)
|
||||
final def products(file: T): Set[T] = get(productMap, file)
|
||||
final def sources(file: T): Set[T] = get(sourceMap, file)
|
||||
final def usedBy(file: T): Set[T] = get(reverseUses, file)
|
||||
final def tag(file: T): Array[Byte] = tagMap.getOrElse(file, new Array[Byte](0))
|
||||
|
||||
def isProduct(file: T): Boolean = exists(sourceMap, file)
|
||||
def isSource(file: T): Boolean = exists(productMap, file)
|
||||
def isUsed(file: T): Boolean = exists(reverseUses, file)
|
||||
|
||||
|
||||
final def allProducts = sourceMap.keysIterator.toSet
|
||||
final def allSources = productMap.keysIterator.toSet
|
||||
final def allUsed = reverseUses.keysIterator.toSet
|
||||
final def allTags = tagMap.toSeq
|
||||
|
||||
private def exists(map: DMap[T], value: T): Boolean = map.contains(value)
|
||||
private def get(map: DMap[T], value: T): Set[T] = map.getOrElse[collection.Set[T]](value, Set.empty[T]).toSet
|
||||
|
||||
final def dependency(sourceFile: T, dependsOn: T)
|
||||
{
|
||||
val actualDependencies =
|
||||
if(!translateProducts)
|
||||
Seq(dependsOn)
|
||||
else
|
||||
sourceMap.getOrElse[Iterable[T]](dependsOn, Seq(dependsOn))
|
||||
actualDependencies.foreach { actualDependency => reverseDependencies.add(actualDependency, sourceFile) }
|
||||
}
|
||||
final def product(sourceFile: T, product: T)
|
||||
{
|
||||
productMap.add(sourceFile, product)
|
||||
sourceMap.add(product, sourceFile)
|
||||
}
|
||||
final def use(sourceFile: T, usesFile: T) { reverseUses.add(usesFile, sourceFile) }
|
||||
final def tag(sourceFile: T, t: Array[Byte]) { tagMap(sourceFile) = t }
|
||||
|
||||
private def removeOneWay(a: DMap[T], files: Iterable[T]): Unit =
|
||||
a.values.foreach { _ --= files }
|
||||
private def remove(a: DMap[T], b: DMap[T], file: T): Unit =
|
||||
for(x <- a.removeKey(file)) b --= x
|
||||
private def removeAll(files: Iterable[T], a: DMap[T], b: DMap[T]): Unit =
|
||||
files.foreach { file => remove(a, b, file); remove(b, a, file) }
|
||||
final def removeAll(files: Iterable[T])
|
||||
{
|
||||
removeAll(files, forward(reverseDependencies), reverseDependencies)
|
||||
removeAll(files, productMap, sourceMap)
|
||||
removeAll(files, forward(reverseUses), reverseUses)
|
||||
tagMap --= files
|
||||
}
|
||||
def pending(sources: Iterable[T])
|
||||
{
|
||||
removeOneWay(reverseDependencies, sources)
|
||||
removeOneWay(reverseUses, sources)
|
||||
removeAll(sources, productMap, sourceMap)
|
||||
tagMap --= sources
|
||||
}
|
||||
protected final def forward(map: DMap[T]): DMap[T] =
|
||||
{
|
||||
val f = newMap[T]
|
||||
for( (key, values) <- map; value <- values) f.add(value, key)
|
||||
f
|
||||
}
|
||||
override def toString =
|
||||
(graph("Reverse source dependencies", reverseDependencies) ::
|
||||
graph("Sources and products", productMap) ::
|
||||
graph("Reverse uses", reverseUses) ::
|
||||
Nil) mkString "\n"
|
||||
def graph(title: String, map: DMap[T]) =
|
||||
"\"" + title + "\" {\n\t" + graphEntries(map) + "\n}"
|
||||
def graphEntries(map: DMap[T]) = map.map{ case (key, values) => values.map(key + " -> " + _).mkString("\n\t") }.mkString("\n\t")
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import scala.collection.mutable.{HashMap, Map, MultiMap, Set}
|
||||
import scala.reflect.Manifest
|
||||
import sbinary.{DefaultProtocol, Format}
|
||||
import DefaultProtocol._
|
||||
import TrackingFormat._
|
||||
import CacheIO.{fromFile, toFile}
|
||||
import DependencyTracking.{DependencyMap => DMap, newMap, TagMap}
|
||||
|
||||
private class TrackingFormat[T](directory: File, translateProducts: Boolean)(implicit tFormat: Format[T], mf: Manifest[T]) extends NotNull
|
||||
{
|
||||
val indexFile = new File(directory, "index")
|
||||
val dependencyFile = new File(directory, "dependencies")
|
||||
def read(): DependencyTracking[T] =
|
||||
{
|
||||
val indexMap = CacheIO.fromFile[Map[Int,T]](indexFile, new HashMap[Int,T])
|
||||
val indexedFormat = wrap[T,Int](ignore => error("Read-only"), i => indexMap.getOrElse(i, error("Index " + i + " not found")))
|
||||
val trackFormat = trackingFormat(translateProducts)(indexedFormat)
|
||||
fromFile(trackFormat, DefaultTracking[T](translateProducts))(dependencyFile)
|
||||
}
|
||||
def write(tracking: DependencyTracking[T])
|
||||
{
|
||||
val index = new IndexMap[T]
|
||||
val indexedFormat = wrap[T,Int](t => index(t), ignore => error("Write-only"))
|
||||
val trackFormat = trackingFormat(translateProducts)(indexedFormat)
|
||||
toFile(trackFormat)(tracking)(dependencyFile)
|
||||
toFile(index.indices)(indexFile)
|
||||
}
|
||||
}
|
||||
private object TrackingFormat
|
||||
{
|
||||
implicit def mutableMapFormat[S, T](implicit binS : Format[S], binT : Format[T]) : Format[HashMap[S, T]] =
|
||||
new LengthEncoded[HashMap[S, T], (S, T)] {
|
||||
def build(size : Int, ts : Iterator[(S, T)]) : HashMap[S, T] = {
|
||||
val b = new HashMap[S, T]
|
||||
b ++= ts
|
||||
b
|
||||
}
|
||||
}
|
||||
implicit def depMapFormat[T](implicit bin: Format[T]) : Format[DMap[T]] =
|
||||
new LengthEncoded[DMap[T], (T, Set[T])] {
|
||||
def build(size : Int, ts : Iterator[(T, Set[T])]) : DMap[T] = {
|
||||
val b = newMap[T]
|
||||
b ++= ts
|
||||
b
|
||||
}
|
||||
}
|
||||
def trackingFormat[T](translateProducts: Boolean)(implicit tFormat: Format[T]): Format[DependencyTracking[T]] =
|
||||
asProduct4((a: DMap[T],b: DMap[T],c: DMap[T], d:TagMap[T]) => new DefaultTracking(translateProducts)(a,b,c,d) : DependencyTracking[T]
|
||||
)(dt => (dt.reverseDependencies, dt.reverseUses, dt.sourceMap, dt.tagMap))
|
||||
}
|
||||
|
||||
private final class IndexMap[T] extends NotNull
|
||||
{
|
||||
private[this] var lastIndex = 0
|
||||
private[this] val map = new HashMap[T, Int]
|
||||
private[this] def nextIndex = { lastIndex += 1; lastIndex }
|
||||
def indices = HashMap(map.map( (_: (T,Int)).swap ).toSeq : _*)
|
||||
def apply(t: T) = map.getOrElseUpdate(t, nextIndex)
|
||||
}
|
||||
Loading…
Reference in New Issue