diff options
-rw-r--r-- | stage1/Stage1Lib.scala | 20 | ||||
-rw-r--r-- | stage1/cbt.scala | 8 | ||||
-rw-r--r-- | stage1/resolver.scala | 1 | ||||
-rw-r--r-- | stage2/Lib.scala | 54 | ||||
-rw-r--r-- | stage2/PackageJars.scala | 2 |
5 files changed, 60 insertions, 25 deletions
diff --git a/stage1/Stage1Lib.scala b/stage1/Stage1Lib.scala index 83febe8..565a06c 100644 --- a/stage1/Stage1Lib.scala +++ b/stage1/Stage1Lib.scala @@ -184,8 +184,9 @@ class Stage1Lib( logger: Logger ) extends BaseLib{ val arrayClass = classOf[Array[String]] val unitClass = classOf[Unit] - iterateClasses( classesRootDirectory, classLoader, true ).filter( - _.getDeclaredMethods().exists( m => + iterateClasses( classesRootDirectory, classLoader, true ).filter( c => + !c.isInterface && + c.getDeclaredMethods().exists( m => m.getName == "main" && m.getParameterTypes.toList == List(arrayClass) && m.getReturnType == unitClass @@ -481,6 +482,21 @@ ${sourceFiles.sorted.mkString(" \\\n")} StandardOpenOption.APPEND ) } + def cached[T]( targetDirectory: File, inputLastModified: Long )( action: () => T ): (Option[T],Long) = { + val t = targetDirectory + val start = System.currentTimeMillis + def lastSucceeded = t.lastModified + def outputLastModified = t.listRecursive.diff(t :: Nil).map(_.lastModified).maxOption.getOrElse(0l) + def updateSucceeded(time: Long) = Files.setLastModifiedTime( t.toPath, FileTime.fromMillis(time) ) + ( + ( inputLastModified >= lastSucceeded ).option{ + val result: T = action() + updateSucceeded( start ) + result + }, + outputLastModified + ) + } } import scala.reflect._ diff --git a/stage1/cbt.scala b/stage1/cbt.scala index cb6cb10..b97ad44 100644 --- a/stage1/cbt.scala +++ b/stage1/cbt.scala @@ -20,6 +20,13 @@ object `package`{ private val lib = new BaseLib + implicit class CbtBooleanExtensions(condition: Boolean){ + def option[T](value: =>T): Option[T] = if(condition) Some(value) else None + } + implicit class CbtStringExtensions(string: String){ + def escape = string.replace("\\","\\\\").replace("\"","\\\"") + def quote = s""""$escape"""" + } implicit class PathExtensionMethods( path: Path ){ def /(s: String): Path = path.resolve(s) def ++( s: String ): Path = { @@ -64,6 +71,7 @@ object `package`{ def lastModifiedRecursive = listRecursive.map(_.lastModified).max def readAsString = new String( readAllBytes( file.toPath ) ) + def quote = s"new _root_.java.io.File(${string.quote})" } implicit class URLExtensionMethods( url: URL ){ def ++( s: String ): URL = new URL( url.toString ++ s ) diff --git a/stage1/resolver.scala b/stage1/resolver.scala index 105177e..47d4460 100644 --- a/stage1/resolver.scala +++ b/stage1/resolver.scala @@ -172,6 +172,7 @@ case class Dependencies( dependencies: Seq[Dependency] )(implicit val logger: Lo case class PostBuildDependency(target: File, _dependencies: Seq[DependencyImplementation])(implicit val logger: Logger, val transientCache: java.util.Map[AnyRef,AnyRef], val classLoaderCache: ClassLoaderCache) extends DependencyImplementation{ override final lazy val lastModified = (target++".last-success").lastModified def moduleKey = target.string + override def show = s"PostBuildDependency($target)" override def targetClasspath = exportedClasspath override def exportedClasspath = ClassPath( Seq(target) ) override def dependencies = _dependencies diff --git a/stage2/Lib.scala b/stage2/Lib.scala index d5a964a..1c34c9c 100644 --- a/stage2/Lib.scala +++ b/stage2/Lib.scala @@ -283,7 +283,35 @@ final class Lib(val logger: Logger) extends Stage1Lib(logger){ m } - def createJar( jarFile: File, files: Seq[File], baseDirectory: Option[File] = None, mainClass: Option[String] = None ): Option[File] = { + def autoRelative( files: Seq[File], collector: PartialFunction[(File,String), String] = { case (_,r) => r }): Seq[(File, String)] = { + val map = files.sorted.flatMap{ base => + val b = base.getCanonicalFile.string + if( base.isDirectory ){ + base.listRecursive.map{ f => + f -> f.getCanonicalFile.string.stripPrefix(b).stripPrefix(File.separator) + } + } else { + Seq( base -> base.getName ) + } + }.collect{ + case v@(file, _) if collector.isDefinedAt(v) => file -> collector(v) + } + val relatives = map.unzip._2 + val duplicateFiles = (relatives diff relatives.distinct).distinct + assert( + duplicateFiles.isEmpty, + { + val rs = relatives.toSet + "Conflicting:\n\n" + + map.filter(rs contains _._2).groupBy(_._2).mapValues(_.map(_._1).sorted).toSeq.sortBy(_._1).map{ + case (name, files) => s"$name:\n" ++ files.mkString("\n") + }.mkString("\n\n") + } + ) + map + } + + def createJar( jarFile: File, files: Seq[File], mainClass: Option[String] = None ): Option[File] = { deleteIfExists(jarFile.toPath) if( files.isEmpty ){ None @@ -293,32 +321,14 @@ final class Lib(val logger: Logger) extends Stage1Lib(logger){ val jar = new JarOutputStream(new FileOutputStream(jarFile), createManifest(mainClass)) try{ assert( files.forall(_.exists) ) - val names = for { - base <- files.map(realpath) - file <- base.listRecursive if file.isFile - } yield { - val name = { - Some(base).filter(_.isDirectory) orElse baseDirectory map (_.string) map ( - file.string stripPrefix _ stripPrefix File.separator - ) getOrElse ( - throw new Exception( - "Trying to add absolute path to jar: " + file - ) - ) - } - val entry = new JarEntry( name ) + autoRelative(files).collect{ + case (file, relative) if file.isFile => + val entry = new JarEntry( relative ) entry.setTime(file.lastModified) jar.putNextEntry(entry) jar.write( readAllBytes( file.toPath ) ) jar.closeEntry - name } - - val duplicateFiles = (names diff names.distinct).distinct - assert( - duplicateFiles.isEmpty, - s"Conflicting file names when trying to create $jarFile: "++duplicateFiles.mkString(", ") - ) } finally { jar.close } diff --git a/stage2/PackageJars.scala b/stage2/PackageJars.scala index 910741d..221920b 100644 --- a/stage2/PackageJars.scala +++ b/stage2/PackageJars.scala @@ -18,7 +18,7 @@ trait PackageJars extends BaseBuild with ArtifactInfo{ def srcJar: Option[File] = taskCache[PackageJars]("srcJar").memoize{ lib.createJar( - jarTarget / jarFilePrefix++"-sources.jar", nonEmptySourceFiles, Some(projectDirectory) + jarTarget / jarFilePrefix++"-sources.jar", nonEmptySourceFiles ) } |