aboutsummaryrefslogtreecommitdiff
path: root/stage1/cbt.scala
blob: cb6cb1040bcc421e57d616d3afb745ca63eb98a0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package cbt
import java.io._
import java.nio.file._
import java.nio.file.Files._
import java.net._

object `package`{
  implicit class TypeInferenceSafeEquals[T](value: T){
    /** if you don't manually upcast, this will catch comparing different types */
    def ===(other: T) = value == other
    def =!=(other: T) = value != other // =!= instead of !==, because it has better precedence
  }

  val mavenCentral = new URL("https://repo1.maven.org/maven2")
  val jcenter = new URL("https://jcenter.bintray.com")
  def bintray(owner: String) = new URL(s"""https://dl.bintray.com/${URLEncoder.encode(owner, "UTF-8")}/maven""")
  private val sonatypeBase  = new URL("https://oss.sonatype.org/content/repositories/")
  val sonatypeReleases = sonatypeBase ++ "releases"
  val sonatypeSnapshots = sonatypeBase ++ "snapshots"

  private val lib = new BaseLib

  implicit class PathExtensionMethods( path: Path ){
    def /(s: String): Path = path.resolve(s)
    def ++( s: String ): Path = {
      if(s endsWith "/") throw new Exception(
        """Trying to append a String that ends in "/" to a Path would loose the trailing "/". Use .stripSuffix("/") if you need to."""
      )
      Paths.get( path.toString ++ s )
    }
  }
  implicit class FileExtensionMethods( file: File ){
    def ++( s: String ): File = {
      if(s endsWith "/") throw new Exception(
        """Trying to append a String that ends in "/" to a File would loose the trailing "/". Use .stripSuffix("/") if you need to."""
      )
      new File( file.toString ++ s )
    }
    def /(s: String): File = new File( file, s )
    def parent = lib.realpath(file ++ "/..")
    def string = file.toString
    /* recursively deletes folders*/
    def deleteRecursive: Unit = {
      val s = file.string
      // some desperate attempts to keep people from accidentally deleting their hard drive
      assert( file == file.getCanonicalFile, "deleteRecursive requires previous .getCanonicalFile" )
      assert( file.isAbsolute, "deleteRecursive requires absolute path" )
      assert( file.string != "", "deleteRecursive requires non-empty file path" )
      assert( s.split(File.separator.replace("\\","\\\\")).size > 4, "deleteRecursive requires absolute path of at least depth 4" )
      assert( !listRecursive.exists(_.isHidden), "deleteRecursive requires no files to be hidden" )
      assert( listRecursive.forall(_.canWrite), "deleteRecursive requires all files to be writable" )
      if( file.isDirectory ){
        file.listFiles.map(_.deleteRecursive)
      }
      file.delete
    }

    def listRecursive: Seq[File] = {
      file +: (
        if( file.isDirectory ) file.listFiles.flatMap(_.listRecursive).toVector else Seq[File]()
      )
    }

    def lastModifiedRecursive = listRecursive.map(_.lastModified).max

    def readAsString = new String( readAllBytes( file.toPath ) )
  }
  implicit class URLExtensionMethods( url: URL ){
    def ++( s: String ): URL = new URL( url.toString ++ s )
    def show = "/[^/@]+@".r.replaceFirstIn( url.toString, "/" ) // remove credentials when showing url for security reasons
  }
  implicit class SeqExtensions[T](seq: Seq[T]){
     def maxOption(implicit ev: Ordering[T]): Option[T] = try{ Some(seq.max) } catch {
       case e:java.lang.UnsupportedOperationException if e.getMessage === "empty.max" => None
     }
  }
  implicit class ClassLoaderExtensions(classLoader: ClassLoader){
    def canLoad(className: String) = {
      try{
        classLoader.loadClass(className)
        true
      } catch {
        case e: ClassNotFoundException => false
      }
    }
  }
  implicit class ArtifactInfoExtensions(subject: ArtifactInfo){
    import subject._
    def str = s"$groupId:$artifactId:$version"
    def show = this.getClass.getSimpleName ++ s"($str)"
  }
  implicit class DependencyExtensions(subject: Dependency){
    import subject._
    def dependencyClasspath(implicit logger: Logger, transientCache: java.util.Map[AnyRef,AnyRef], classLoaderCache: ClassLoaderCache): ClassPath
      = Dependencies(dependenciesArray.to).classpath
    def exportedClasspath: ClassPath = ClassPath(exportedClasspathArray.to)
    def classpath(implicit logger: Logger, transientCache: java.util.Map[AnyRef,AnyRef], classLoaderCache: ClassLoaderCache) = exportedClasspath ++ dependencyClasspath
    def dependencies: Seq[Dependency] = dependenciesArray.to
  }
  implicit class ContextExtensions(subject: Context){
    import subject._
    val paths = CbtPaths(cbtHome, cache)
    implicit def logger: Logger = new Logger(enabledLoggers, start)

    def classLoaderCache: ClassLoaderCache = new ClassLoaderCache( persistentCache )
    def cbtDependencies = {
      import paths._
      new CbtDependencies(mavenCache, nailgunTarget, stage1Target, stage2Target, compatibilityTarget)(logger, transientCache, classLoaderCache)
    }
    val cbtDependency = cbtDependencies.stage2Dependency

    def args: Seq[String] = argsArray.to
    def enabledLoggers: Set[String] = enabledLoggersArray.to
    def scalaVersion = Option(scalaVersionOrNull)
    def parentBuild = Option(parentBuildOrNull)
    def cbtLastModified: scala.Long = subject.cbtLastModified

    def copy(
      workingDirectory: File = workingDirectory,
      args: Seq[String] = args,
      //enabledLoggers: Set[String] = enabledLoggers,
      cbtLastModified: Long = cbtLastModified,
      scalaVersion: Option[String] = scalaVersion,
      cbtHome: File = cbtHome,
      parentBuild: Option[BuildInterface] = None,
      transientCache: java.util.Map[AnyRef,AnyRef] = transientCache,
      persistentCache: java.util.Map[AnyRef,AnyRef] = persistentCache,
      loop: Boolean = loop
    ): Context = new ContextImplementation(
      workingDirectory,
      cwd,
      args.to,
      enabledLoggers.to,
      start,
      cbtLastModified,
      scalaVersion.getOrElse(null),
      persistentCache,
      transientCache,
      cache,
      cbtHome,
      cbtRootHome,
      compatibilityTarget,
      parentBuild.getOrElse(null),
      loop
    )
  }
}