1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-05-12 15:02:00 -07:00

Compare commits

..

No commits in common. "master" and "0.412" have entirely different histories.

327 changed files with 5884 additions and 15557 deletions

8
.gitignore vendored
View file

@ -1,15 +1,13 @@
.gradle .gradle
annotations annotations
.idea/* .idea/*
*.iml !.idea/modules.xml
nonBuildScript buildScript
kobaltBuild kobaltBuild
local.properties local.properties
classes classes
libs libs
.kobalt/ .kobalt/
./build/
out out
.DS_Store .DS_Store
lib/kotlin-*
build
.history

11
.idea/modules.xml generated Normal file
View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/kobalt/Build.kt.iml" filepath="$PROJECT_DIR$/kobalt/Build.kt.iml" />
<module fileurl="file://$PROJECT_DIR$/kobalt.iml" filepath="$PROJECT_DIR$/kobalt.iml" />
<module fileurl="file://$PROJECT_DIR$/modules/kobalt-plugin-api/kobalt-plugin-api.iml" filepath="$PROJECT_DIR$/modules/kobalt-plugin-api/kobalt-plugin-api.iml" />
<module fileurl="file://$PROJECT_DIR$/modules/wrapper/kobalt-wrapper.iml" filepath="$PROJECT_DIR$/modules/wrapper/kobalt-wrapper.iml" />
</modules>
</component>
</project>

12
.travis.yml Normal file
View file

@ -0,0 +1,12 @@
cache:
directories:
- $HOME/.m2
language: java
jdk:
- oraclejdk8
install: true
script: ./kobaltw test --log 1

View file

@ -1,15 +1,11 @@
# Kobalt # Kobalt
[<img src="https://teamcity.jetbrains.com/app/rest/builds/buildType:(id:OpenSourceProjects_Kobalt_Build)/statusIcon.svg">](https://teamcity.jetbrains.com/project.html?projectId=OpenSourceProjects_Kobalt&tab=projectOverview)
Kobalt is a universal build system. Kobalt is a universal build system.
To build it: To build it:
``` ```
$ ./kobaltw assemble ./kobaltw assemble
``` ```
Please see [the web site](http://beust.com/kobalt/) for the full documentation. Please see [the web site](http://beust.com/kobalt/) for the full documentation.

View file

@ -2,13 +2,10 @@ To do:
Android: Android:
- [ ] Dex dependencies into kobaltBuild/intermediates/pre-dexed and preserve those across builds
General General
- [ ] KFiles.findSourceFiles should cache its results
- [ ] createCompilerAction should calculate source files once and for all, including contributors and interceptors
- [ ] Need a -resolve with no dependency which gives the tree for the whole project
- [ ] If jitpack specified with http and not https, 301 is not handled correctly
- [ ] Apt should run from serviceloader - [ ] Apt should run from serviceloader
- [ ] Console mode with watch service, so recompilation can occur as soon as a source file is modified - [ ] Console mode with watch service, so recompilation can occur as soon as a source file is modified
- [ ] ProjectGenerator: support migration from pom.xml (starting with dependencies) - [ ] ProjectGenerator: support migration from pom.xml (starting with dependencies)
@ -26,7 +23,6 @@ General
Done: Done:
- [x] Dex dependencies into kobaltBuild/intermediates/pre-dexed and preserve those across builds
- [x] Compile with javax.tool - [x] Compile with javax.tool
- [x] Android: multiple -source/-target flags - [x] Android: multiple -source/-target flags
- [x] Dokka: allow multiple format outputs e.g `outputFormat("html", "javadoc")` - [x] Dokka: allow multiple format outputs e.g `outputFormat("html", "javadoc")`

View file

@ -1,8 +0,0 @@
ulimit -s 1082768
#java -Xmx2048m -jar $(dirname $0)/kobalt/wrapper/kobalt-wrapper.jar $* clean
java -Xmx2048m -jar $(dirname $0)/kobalt/wrapper/kobalt-wrapper.jar $* clean assemble test --parallel

View file

@ -1,58 +0,0 @@
allprojects {
group = 'com.beust'
version = '1.1.0'
}
subprojects {
apply plugin: 'java'
apply plugin: 'maven-publish'
ext {
bndlib = '3.5.0'
findbugs = '3.0.2'
groovy = '2.4.12'
gson = '2.8.2'
guice = '4.2.2'
inject = '1'
jaxb = '2.3.0'
jcommander = '1.72'
kotlin = '1.2.71'
maven = '3.5.2'
mavenResolver = '1.1.0'
okhttp = '3.9.1'
okio = '1.13.0'
retrofit = '2.3.0'
slf4j = '1.7.3'
spark = '2.6.0'
testng = '6.12'
junit = '4.12'
junitJupiter = '5.1.0'
junitPlatform = '1.1.0'
}
repositories {
mavenCentral()
mavenLocal()
jcenter()
maven {
url = 'https://dl.bintray.com/cbeust/maven'
}
maven {
url = 'https://repo.maven.apache.org/maven2'
}
}
sourceCompatibility = '1.7'
task sourcesJar(type: Jar) {
from sourceSets.main.allJava
archiveClassifier = 'sources'
}
task javadocJar(type: Jar) {
from javadoc
archiveClassifier = 'javadoc'
}
}

11
dist/kobaltw vendored
View file

@ -1,11 +0,0 @@
#!/usr/bin/env sh
case "$(uname)" in
CYGWIN*) DIRNAME=$(cygpath -d "$(dirname "$(readlink -f "$0")")");;
Darwin*) DIRNAME=$(dirname "$(readlink "$0")");;
*) DIRNAME=$(dirname "$(readlink -f "$0")");;
esac
if [ "$DIRNAME" = "." ]; then
DIRNAME="$(dirname "$0")"
fi
java -jar "${DIRNAME}/../kobalt/wrapper/kobalt-wrapper.jar" $*

4
dist/kobaltw.bat vendored
View file

@ -1,4 +0,0 @@
@echo off
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
java -jar "%~dp0/../kobalt/wrapper/kobalt-wrapper.jar" %*

92
gradle/build.gradle Normal file
View file

@ -0,0 +1,92 @@
buildscript {
ext.kotlin_version = '1.0.0-beta-2423'
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}"
}
}
plugins {
id "com.jfrog.bintray" version "1.2"
}
version = '0.121'
//apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'com.jfrog.bintray'
apply from: 'gradle/publishing.gradle'
repositories {
jcenter()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}",
"org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlin_version}",
'org.jetbrains.kotlinx:kotlinx.dom:0.0.4',
'org.jetbrains.dokka:dokka-fatjar:0.9.2',
// "org.jetbrains.kotlin:kotlin-compiler:${kotlin_version}",
"com.android.tools.build:builder:2.0.0-alpha3",
'com.beust:jcommander:1.48',
'com.squareup.okhttp:okhttp:2.5.0',
'org.jsoup:jsoup:1.8.3',
'com.google.inject:guice:4.0',
'com.google.inject.extensions:guice-assistedinject:4.0',
'javax.inject:javax.inject:1',
'com.google.guava:guava:19.0-rc2',
'org.apache.maven:maven-model:3.3.3',
'com.github.spullara.mustache.java:compiler:0.9.1',
'io.reactivex:rxjava:1.0.16',
'com.google.code.gson:gson:2.4',
'com.squareup.retrofit:retrofit:1.9.0',
'com.squareup.okio:okio:1.6.0',
project("modules/wrapper")
// compile files("/Users/beust/.kobalt/repository/com/beust/kobalt-example-plugin/build/libs/kobalt-example-plugin.jar")
testCompile 'org.testng:testng:6.9.9'
// testCompile 'junit:junit:4.12'
}
task sourceJar(type: Jar) {
group 'Build'
description 'An archive of the source code'
classifier 'sources'
from sourceSets.main.allSource
}
artifacts {
file('build/libs/kobalt.jar')
sourceJar
}
test {
useTestNG()
beforeTest { descriptor ->
logger.lifecycle(" Running test: " + descriptor)
}
}
compileKotlin {
kotlinOptions.suppressWarnings = true
}
apply plugin: 'application'
mainClassName = 'com.beust.kobalt.KobaltPackage'
jar {
manifest {
attributes "Main-Class": "$mainClassName"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}

View file

@ -0,0 +1 @@
../gradlew check

60
gradle/publishing.gradle Normal file
View file

@ -0,0 +1,60 @@
import java.text.SimpleDateFormat
Date buildTimeAndDate = new Date()
ext {
buildTime = new SimpleDateFormat('yyyy-MM-dd').format(buildTimeAndDate)
buildDate = new SimpleDateFormat('HH:mm:ss.SSSZ').format(buildTimeAndDate)
}
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'
jar {
manifest {
attributes(
'Built-By': System.properties['user.name'],
'Created-By': System.properties['java.version'] + " (" + System.properties['java.vendor'] + " " + System.getProperty("java.vm.version") + ")",
'Build-Date': project.buildTime,
'Build-Time': project.buildDate,
'Specification-Title': project.name,
'Specification-Version': project.version,
)
}
}
publishing {
publications {
mavenCustom(MavenPublication) {
from components.java
artifact sourceJar
groupId 'com.beust'
artifactId 'kobalt'
version project.version
}
}
}
task install(dependsOn: publishToMavenLocal)
Properties properties = new Properties()
if (new File('local.properties').exists()) {
properties.load(project.rootProject.file('local.properties').newDataInputStream())
}
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
publications = ['mavenCustom']
pkg {
repo = 'maven'
name = 'klaxon'
desc = 'JSON parsing for Kotlin'
licenses = ['Apache-2.0']
labels = ['kotlin']
version {
name = project.version //Bintray logical version name
}
}
}

Binary file not shown.

View file

@ -1,5 +1,6 @@
#Sun Oct 04 21:38:45 EDT 2015
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-all.zip

90
gradlew vendored
View file

@ -1,20 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env bash
#
# Copyright 2015 the original author or authors.
#
# 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.
#
############################################################################## ##############################################################################
## ##
@ -22,30 +6,12 @@
## ##
############################################################################## ##############################################################################
# Attempt to set APP_HOME # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
# Resolve links: $0 may be a link DEFAULT_JVM_OPTS=""
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle" APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@ -64,7 +30,6 @@ die () {
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false
case "`uname`" in case "`uname`" in
CYGWIN* ) CYGWIN* )
cygwin=true cygwin=true
@ -75,11 +40,31 @@ case "`uname`" in
MINGW* ) MINGW* )
msys=true msys=true
;; ;;
NONSTOP* )
nonstop=true
;;
esac esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@ -105,7 +90,7 @@ location of your Java installation."
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n` MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@ -129,7 +114,6 @@ fi
if $cygwin ; then if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@ -170,19 +154,11 @@ if $cygwin ; then
esac esac
fi fi
# Escape application args # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
save () { function splitJvmOpts() {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done JVM_OPTS=("$@")
echo " "
} }
APP_ARGS=$(save "$@") eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, following the shell quoting and substitution rules exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

30
gradlew.bat vendored
View file

@ -1,19 +1,3 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@ -24,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
@ -62,9 +46,10 @@ echo location of your Java installation.
goto fail goto fail
:init :init
@rem Get command-line arguments, handling Windows variants @rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args :win9xME_args
@rem Slurp the command line arguments. @rem Slurp the command line arguments.
@ -75,6 +60,11 @@ set _SKIP=2
if "x%~1" == "x" goto execute if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%* set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute :execute
@rem Setup the command line @rem Setup the command line

17
kobalt.iml Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="kobalt" external.linked.project.path="$USER_HOME$" external.root.project.path="$USER_HOME$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="0.121" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kobalt (Compile)" level="project" />
<orderEntry type="library" scope="TEST" name="kobalt (Test)" level="project" />
<orderEntry type="module" module-name="kobalt-plugin-api" />
<orderEntry type="module" module-name="kobalt-wrapper" />
</component>
</module>

13
kobalt/Build.kt.iml Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file:///Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kobalt.jar" level="project" />
</component>
</module>

View file

@ -1,61 +1,29 @@
import com.beust.kobalt.* import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.License
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.api.Scm
import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.homeDir
import com.beust.kobalt.plugin.application.application import com.beust.kobalt.plugin.application.application
import com.beust.kobalt.plugin.java.javaCompiler import com.beust.kobalt.plugin.java.javaCompiler
import com.beust.kobalt.plugin.java.javaProject
import com.beust.kobalt.plugin.kotlin.kotlinCompiler import com.beust.kobalt.plugin.kotlin.kotlinCompiler
import com.beust.kobalt.plugin.kotlin.kotlinProject
import com.beust.kobalt.plugin.packaging.assemble import com.beust.kobalt.plugin.packaging.assemble
import com.beust.kobalt.plugin.publish.autoGitTag
import com.beust.kobalt.plugin.publish.bintray
import com.beust.kobalt.plugin.publish.github import com.beust.kobalt.plugin.publish.github
import org.apache.maven.model.Developer import com.beust.kobalt.plugin.publish.bintray
import org.apache.maven.model.License import com.beust.kobalt.repos
import org.apache.maven.model.Model import com.beust.kobalt.test
import org.apache.maven.model.Scm
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
val bs = buildScript { val r = repos("http://dl.bintray.com/kotlin/kotlinx.dom")
repos("https://dl.bintray.com/cbeust/maven")
}
object Versions { val wrapper = javaProject {
val kotlin = "1.2.71"
val okhttp = "3.9.1"
val okio = "1.13.0"
val retrofit = "2.3.0"
val gson = "2.8.2"
val guice = "4.2.2"
val maven = "3.5.2"
val mavenResolver = "1.1.0"
val slf4j = "1.7.3"
val aether = "1.0.2.v20150114"
val testng = "6.12"
val jcommander = "1.72"
// JUnit 5
val junit = "4.12"
val junitPlatform = "1.1.0"
val junitJupiter = "5.1.0"
}
fun mavenResolver(vararg m: String)
= m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" }
.toTypedArray()
fun aether(vararg m: String)
= m.map { "org.eclipse.aether:aether-$it:${Versions.aether}" }
.toTypedArray()
val wrapper = project {
name = "kobalt-wrapper" name = "kobalt-wrapper"
group = "com.beust"
artifactId = name
version = readVersion() version = readVersion()
directory = "modules/wrapper" directory = "modules/wrapper"
@ -64,7 +32,6 @@ val wrapper = project {
} }
assemble { assemble {
jar { }
jar { jar {
name = projectName + ".jar" name = projectName + ".jar"
manifest { manifest {
@ -76,60 +43,41 @@ val wrapper = project {
application { application {
mainClass = "com.beust.kobalt.wrapper.Main" mainClass = "com.beust.kobalt.wrapper.Main"
} }
bintray {
publish = true
sign = true
} }
pom = createPom(name, "Wrapper for Kobalt")
}
val kobaltPluginApi = project { val kobaltPluginApi = kotlinProject {
name = "kobalt-plugin-api" name = "kobalt-plugin-api"
group = "com.beust" group = "com.beust"
artifactId = name artifactId = name
version = readVersion() version = readVersion()
directory = "modules/kobalt-plugin-api" directory = "modules/kobalt-plugin-api"
description = "A build system in Kotlin" description = "A build system in Kotlin"
url = "https://beust.com/kobalt" url = "http://beust.com/kobalt"
licenses = arrayListOf(License("Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0"))
scm = Scm(url = "http://github.com/cbeust/kobalt",
connection = "https://github.com/cbeust/kobalt.git",
developerConnection = "git@github.com:cbeust/kobalt.git")
pom = createPom(name, "A build system in Kotlin") dependenciesTest {
compile("org.testng:testng:6.9.9")
}
dependencies { dependencies {
compile( compile("org.jetbrains.kotlinx:kotlinx.dom:0.0.4",
"org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}",
"com.google.inject:guice:${Versions.guice}",
"com.google.inject.extensions:guice-assistedinject:4.1.0",
"javax.inject:javax.inject:1",
"com.google.guava:guava:27.0.1-jre",
"org.apache.maven:maven-model:${Versions.maven}",
"io.reactivex:rxjava:1.3.3",
"com.squareup.okio:okio:${Versions.okio}",
"com.google.code.gson:gson:${Versions.gson}",
"com.squareup.okhttp3:okhttp:${Versions.okhttp}",
"com.squareup.retrofit2:retrofit:${Versions.retrofit}",
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
"com.beust:jcommander:${Versions.jcommander}",
"org.eclipse.jgit:org.eclipse.jgit:4.9.0.201710071750-r",
"org.slf4j:slf4j-simple:${Versions.slf4j}",
*mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"),
"org.apache.maven:maven-aether-provider:3.3.9",
"org.testng.testng-remote:testng-remote:1.3.2",
"org.testng:testng:${Versions.testng}",
"org.junit.platform:junit-platform-surefire-provider:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-runner:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-engine:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-console:${Versions.junitPlatform}",
"org.junit.jupiter:junit-jupiter-engine:${Versions.junitJupiter}",
"org.junit.vintage:junit-vintage-engine:${Versions.junitJupiter}",
"org.apache.commons:commons-compress:1.15",
"commons-io:commons-io:2.6",
// Java 9 "com.squareup.okhttp:okhttp:2.5.0",
"javax.xml.bind:jaxb-api:2.3.0" "com.squareup.okio:okio:1.6.0",
"com.google.inject:guice:4.0",
"com.google.inject.extensions:guice-assistedinject:4.0",
"javax.inject:javax.inject:1",
"com.google.guava:guava:19.0-rc2",
"org.apache.maven:maven-model:3.3.3",
"io.reactivex:rxjava:1.0.16",
"com.google.code.gson:gson:2.4",
"com.squareup.retrofit:retrofit:1.9.0",
"com.beust:jcommander:1.48"
) )
exclude(*aether("impl", "spi", "util", "api"))
} }
@ -142,8 +90,12 @@ val kobaltPluginApi = project {
} }
} }
// install {
// libDir = "lib-test"
// }
kotlinCompiler { kotlinCompiler {
args("nowarn") args("-nowarn")
} }
bintray { bintray {
@ -151,7 +103,7 @@ val kobaltPluginApi = project {
} }
} }
val kobaltApp = project(kobaltPluginApi, wrapper) { val kobaltApp = kotlinProject(kobaltPluginApi, wrapper) {
name = "kobalt" name = "kobalt"
group = "com.beust" group = "com.beust"
artifactId = name artifactId = name
@ -159,53 +111,24 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
dependencies { dependencies {
// Used by the plugins // Used by the plugins
compile("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") compile("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.0.0-beta-4584")
// Used by the main app // Used by the main app
compile( compile("com.github.spullara.mustache.java:compiler:0.9.1",
"org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}", "com.squareup.okhttp:okhttp:2.5.0",
"com.github.spullara.mustache.java:compiler:0.9.5",
"javax.inject:javax.inject:1", "javax.inject:javax.inject:1",
"com.google.inject:guice:${Versions.guice}", "com.google.inject:guice:4.0",
"com.google.inject.extensions:guice-assistedinject:${Versions.guice}", "com.google.inject.extensions:guice-assistedinject:4.0",
"com.beust:jcommander:${Versions.jcommander}", "com.beust:jcommander:1.48",
"org.apache.maven:maven-model:${Versions.maven}", "com.squareup.retrofit:retrofit:1.9.0",
"com.google.code.findbugs:jsr305:3.0.2", "org.apache.maven:maven-model:3.3.3",
"com.google.code.gson:gson:${Versions.gson}", "com.google.code.findbugs:jsr305:3.0.1",
"com.squareup.retrofit2:retrofit:${Versions.retrofit}", "org.codehaus.plexus:plexus-utils:3.0.22")
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
// "com.squareup.okhttp3:okhttp-ws:3.4.2",
"biz.aQute.bnd:biz.aQute.bndlib:3.5.0",
*mavenResolver("spi"),
"com.squareup.okhttp3:logging-interceptor:3.9.0",
"com.sparkjava:spark-core:2.6.0",
"org.codehaus.groovy:groovy:2.4.12",
// Java 9
"javax.xml.bind:jaxb-api:2.3.0",
"com.sun.xml.bind:jaxb-impl:2.3.0",
"com.sun.xml.bind:jaxb-core:2.3.0",
"com.sun.activation:javax.activation:1.2.0"
// "org.eclipse.jetty:jetty-server:${Versions.jetty}",
// "org.eclipse.jetty:jetty-servlet:${Versions.jetty}",
// "org.glassfish.jersey.core:jersey-server:${Versions.jersey}",
// "org.glassfish.jersey.containers:jersey-container-servlet-core:${Versions.jersey}",
// "org.glassfish.jersey.containers:jersey-container-jetty-http:${Versions.jersey}",
// "org.glassfish.jersey.media:jersey-media-moxy:${Versions.jersey}",
// "org.wasabi:wasabi:0.1.182"
)
} }
dependenciesTest { dependenciesTest {
compile("org.jetbrains.kotlin:kotlin-test:${Versions.kotlin}", compile("org.testng:testng:6.9.9")
"org.testng:testng:${Versions.testng}",
"org.assertj:assertj-core:3.8.0",
*mavenResolver("util")
)
} }
assemble { assemble {
@ -216,28 +139,16 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
} }
} }
zip { zip {
val dir = "kobalt-$version" include("kobaltw")
val files = listOf( include(from("$buildDirectory/libs"), to("kobalt/wrapper"),
"dist", "$dir/bin", "kobaltw", "$projectName-$version.jar")
"dist", "$dir/bin", "kobaltw.bat", include(from("modules/wrapper/$buildDirectory/libs"), to("kobalt/wrapper"),
"$buildDirectory/libs", "$dir/kobalt/wrapper", "$projectName-$version.jar", "$projectName-wrapper.jar")
"modules/wrapper/$buildDirectory/libs", "$dir/kobalt/wrapper", "$projectName-wrapper.jar")
(0 .. files.size - 1 step 3).forEach { i ->
include(from(files[i]), to(files[i + 1]), files[i + 2])
}
// Package the sources
val currentDir = Paths.get(".").toAbsolutePath().normalize().toString()
zipFolders("$currentDir/$buildDirectory/libs/all-sources/$projectName-$version-sources.jar",
"$currentDir/$directory/src/main/kotlin",
"$currentDir/${kobaltPluginApi.directory}/src/main/kotlin")
include(from("$buildDirectory/libs/all-sources"), to("$dir/kobalt/wrapper"), "$projectName-$version-sources.jar")
} }
} }
kotlinCompiler { kotlinCompiler {
args("nowarn") args("-nowarn")
} }
bintray { bintray {
@ -249,78 +160,30 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
} }
test { test {
args("-log", "2", "src/test/resources/testng.xml") args("-log", "1", "src/test/resources/testng.xml")
}
autoGitTag {
enabled = true
}
}
fun zipFolders(zipFilePath: String, vararg foldersPath: String) {
val zip = Paths.get(zipFilePath)
Files.deleteIfExists(zip)
Files.createDirectories(zip.parent)
val zipPath = Files.createFile(zip)
ZipOutputStream(Files.newOutputStream(zipPath)).use {
foldersPath.map {Paths.get(it)}.forEach { folderPath ->
Files.walk(folderPath)
.filter { path -> !Files.isDirectory(path) }
.forEach { path ->
val zipEntry = ZipEntry(folderPath.relativize(path).toString())
try {
it.putNextEntry(zipEntry)
Files.copy(path, it)
it.closeEntry()
} catch (e: Exception) {
}
}
}
} }
} }
fun readVersion() : String { fun readVersion() : String {
val localFile = val p = java.util.Properties()
listOf("src/main/resources/kobalt.properties", var localFile = java.io.File("src/main/resources/kobalt.properties")
homeDir("kotlin", "kobalt", "src/main/resources/kobalt.properties")).first { File(it).exists() } if (! localFile.exists()) {
with(java.util.Properties()) { localFile = File(homeDir("kotlin", "kobalt", "src/main/resources/kobalt.properties"))
load(java.io.FileReader(localFile))
return getProperty("kobalt.version")
} }
p.load(java.io.FileReader(localFile))
return p.getProperty("kobalt.version")
} }
@Task(name = "copyVersionForWrapper", reverseDependsOn = arrayOf("assemble"), runAfter = arrayOf("clean")) @Task(name = "copyVersionForWrapper", runBefore = arrayOf("assemble"), runAfter = arrayOf("compile"), description = "")
fun taskCopyVersionForWrapper(project: Project) : TaskResult { fun taskCopyVersionForWrapper(project: Project) : TaskResult {
if (project.name == "kobalt-wrapper") { if (project.name == "kobalt-wrapper") {
val toString = "modules/wrapper/kobaltBuild/classes" val toString = "modules/wrapper/kobaltBuild/classes"
File(toString).mkdirs() File(toString).mkdirs()
val from = Paths.get("src/main/resources/kobalt.properties") val from = Paths.get("src/main/resources/kobalt.properties")
val to = Paths.get("$toString/kobalt.properties") val to = Paths.get("$toString/kobalt.properties")
// Only copy if necessary so we don't break incremental compilation
if (! to.toFile().exists() || (from.toFile().readLines() != to.toFile().readLines())) {
Files.copy(from, Files.copy(from,
to, to,
StandardCopyOption.REPLACE_EXISTING) StandardCopyOption.REPLACE_EXISTING)
} }
}
return TaskResult() return TaskResult()
} }
fun createPom(projectName: String, projectDescription: String) = Model().apply {
name = projectName
description = projectDescription
url = "https://beust.com/kobalt"
licenses = listOf(License().apply {
name = "Apache-2.0"
url = "https://www.apache.org/licenses/LICENSE-2.0"
})
scm = Scm().apply {
url = "https://github.com/cbeust/kobalt"
connection = "https://github.com/cbeust/kobalt.git"
developerConnection = "git@github.com:cbeust/kobalt.git"
}
developers = listOf(Developer().apply {
name = "Cedric Beust"
email = "cedric@beust.com"
})
}

Binary file not shown.

View file

@ -1 +1 @@
kobalt.version=1.0.122 kobalt.version=0.411

View file

@ -1,2 +1,2 @@
#!/usr/bin/env sh #!/usr/bin/env bash
java -jar "`dirname "$0"`/kobalt/wrapper/kobalt-wrapper.jar" $* java -jar $(dirname $0)/kobalt/wrapper/kobalt-wrapper.jar $*

View file

@ -1,8 +0,0 @@
#!/usr/bin/env sh
JAR=$(ls -1 -t kobaltBuild/libs/*.jar | grep -Ev "(sources|javadoc)" | head -1)
TEMPDIR=$(mktemp -d)
cp -pf "$JAR" "$TEMPDIR"
TEMPJAR=$TEMPDIR/$(basename "$JAR")
export KOBALT_JAR=$TEMPJAR
java -jar "$TEMPJAR" "$@"
rm -rf "$TEMPDIR"

View file

@ -1,4 +1,2 @@
@echo off @echo off
set DIRNAME=%~dp0 java -jar %~dp0/kobalt/wrapper/kobalt-wrapper.jar %*
if "%DIRNAME%" == "" set DIRNAME=.
java -jar "%DIRNAME%/kobalt/wrapper/kobalt-wrapper.jar" %*

View file

@ -1,85 +0,0 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.71'
id 'com.github.johnrengelman.shadow' version '5.0.0'
}
dependencies {
implementation "biz.aQute.bnd:biz.aQute.bndlib:$bndlib"
implementation "com.google.code.findbugs:jsr305:$findbugs"
implementation "com.sparkjava:spark-core:$spark"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp"
implementation 'commons-io:commons-io:2.6'
implementation 'io.reactivex:rxjava:1.3.3'
implementation "javax.inject:javax.inject:$inject"
implementation "javax.xml.bind:jaxb-api:$jaxb"
implementation 'org.apache.commons:commons-compress:1.15'
implementation 'org.apache.maven:maven-aether-provider:3.3.9'
implementation "org.apache.maven.resolver:maven-resolver-api:$mavenResolver"
implementation "org.apache.maven.resolver:maven-resolver-connector-basic:$mavenResolver"
implementation "org.apache.maven.resolver:maven-resolver-impl:$mavenResolver"
implementation "org.apache.maven.resolver:maven-resolver-spi:$mavenResolver"
implementation "org.apache.maven.resolver:maven-resolver-transport-file:$mavenResolver"
implementation "org.apache.maven.resolver:maven-resolver-transport-http:$mavenResolver"
implementation "org.apache.maven.resolver:maven-resolver-util:$mavenResolver"
implementation "org.codehaus.groovy:groovy:$groovy"
implementation 'org.eclipse.jgit:org.eclipse.jgit:4.9.0.201710071750-r'
implementation "org.junit.jupiter:junit-jupiter-engine:$junitJupiter"
implementation "org.junit.platform:junit-platform-console:$junitPlatform"
implementation "org.junit.platform:junit-platform-engine:$junitPlatform"
implementation "org.junit.platform:junit-platform-runner:$junitPlatform"
implementation "org.junit.platform:junit-platform-surefire-provider:$junitPlatform"
implementation "org.junit.vintage:junit-vintage-engine:$junitJupiter"
implementation "org.slf4j:slf4j-simple:$slf4j"
implementation "org.testng:testng:$testng"
implementation 'org.testng.testng-remote:testng-remote:1.3.2'
implementation "com.beust:jcommander:$jcommander"
implementation "com.google.code.gson:gson:$gson"
implementation "com.google.inject:guice:$guice"
implementation "com.google.inject.extensions:guice-assistedinject:$guice"
implementation "com.squareup.okio:okio:$okio"
implementation "com.squareup.retrofit2:converter-gson:$retrofit"
implementation "com.squareup.retrofit2:retrofit:$retrofit"
implementation "org.apache.maven:maven-model:$maven"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin"
}
shadowJar {
classifier = null
}
test {
useTestNG()
}
publishing {
publications {
shadow(MavenPublication) { publication ->
project.shadow.component(publication)
artifact sourcesJar
artifact javadocJar
pom {
name = project.name
description = 'A build system in Kotlin'
url = 'https://beust.com/kobalt'
licenses {
license {
name = 'Apache-2.0'
url = 'https://www.apache.org/licenses/LICENSE-2.0'
}
}
developers {
developer {
name = 'Cedric Beust'
email = 'cedric@beust.com'
}
}
scm {
connection = 'scm:https://github.com/cbeust/kobalt.git'
developerConnection = 'scm:git@github.com:cbeust/kobalt.git'
url = 'https://github.com/cbeust/kobalt'
}
}
}
}
}

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kobalt (Compile)" level="project" />
<orderEntry type="library" name="kobalt-plugin-api (Compile)" level="project" />
<orderEntry type="library" scope="TEST" name="kobalt-plugin-api (Test)" level="project" />
</component>
</module>

View file

@ -1,279 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.beust</groupId>
<artifactId>kobalt-pom</artifactId>
<version>1.1.0</version>
<relativePath>../..</relativePath>
</parent>
<artifactId>kobalt-plugin-api</artifactId>
<packaging>jar</packaging>
<version>1.1.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
<version>3.3.9</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.aether</groupId>
<artifactId>impl</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.aether</groupId>
<artifactId>spi</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.aether</groupId>
<artifactId>util</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.aether</groupId>
<artifactId>api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-spi</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-util</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-file</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>${okio.version}</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.2</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-assistedinject</artifactId>
<version>4.2.2</version>
</dependency>
<dependency>
<groupId>com.beust</groupId>
<artifactId>jcommander</artifactId>
<version>1.72</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-gson</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>biz.aQute.bndlib</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>${okhttp3.version}</version>
</dependency>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>2.4.12</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junitJupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junitJupiter.version}</version>
</dependency>
<dependency>
<groupId>org.testng.testng-remote</groupId>
<artifactId>testng-remote</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>4.9.0.201710071750-r</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- java 9 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,21 +0,0 @@
package com.beust.kobalt
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.archive.Zip
import com.beust.kobalt.misc.KFiles
import java.io.File
interface ArchiveGenerator {
fun findIncludedFiles(project: Project, context: KobaltContext, zip: Zip) : List<IncludedFile>
val suffix: String
fun generateArchive(project: Project, context: KobaltContext, zip: Zip, files: List<IncludedFile>) : File
fun fullArchiveName(project: Project, context: KobaltContext, archiveName: String?) : File {
val fullArchiveName = context.variant.archiveName(project, archiveName, suffix)
val archiveDir = File(KFiles.libsDir(project))
val result = File(archiveDir.path, fullArchiveName)
return result
}
}

View file

@ -7,7 +7,7 @@ class Args {
var targets: List<String> = arrayListOf() var targets: List<String> = arrayListOf()
@Parameter(names = arrayOf("-bf", "--buildFile"), description = "The build file") @Parameter(names = arrayOf("-bf", "--buildFile"), description = "The build file")
var buildFile: String? = "kobalt/src/Build.kt" var buildFile: String? = null
@Parameter(names = arrayOf("--checkVersions"), description = "Check if there are any newer versions of the " + @Parameter(names = arrayOf("--checkVersions"), description = "Check if there are any newer versions of the " +
"dependencies") "dependencies")
@ -16,86 +16,38 @@ class Args {
@Parameter(names = arrayOf("--client")) @Parameter(names = arrayOf("--client"))
var client: Boolean = false var client: Boolean = false
@Parameter(names = arrayOf("--dev"), description = "Turn on dev mode, resulting in a more verbose log output") @Parameter(names = arrayOf("--dev"), description = "Turn of dev mode, resulting in a more verbose log output")
var dev: Boolean = false var dev: Boolean = false
@Parameter(names = arrayOf("--download"), description = "Force a download from the downloadUrl in the wrapper") @Parameter(names = arrayOf("--download"), description = "Force a download from the downloadUrl in the wrapper")
var download: Boolean = false var download: Boolean = false
@Parameter(names = arrayOf("--downloadSources"),
description = "Force a download of sources and javadocs when resolving dependencies")
var downloadSources: Boolean = false
@Parameter(names = arrayOf("--dryRun"), description = "Display all the tasks that will get run without " + @Parameter(names = arrayOf("--dryRun"), description = "Display all the tasks that will get run without " +
"actually running them") "actually running them")
var dryRun: Boolean = false var dryRun: Boolean = false
@Parameter(names = arrayOf("--force"), description = "Force a new server to be launched even if another one" +
" is already running")
var force: Boolean = false
@Parameter(names = arrayOf("--gc"), description = "Delete old files")
var gc: Boolean = false
@Parameter(names = arrayOf("--help", "--usage"), description = "Display the help") @Parameter(names = arrayOf("--help", "--usage"), description = "Display the help")
var usage: Boolean = false var usage: Boolean = false
@Parameter(names = arrayOf("-i", "--init"), description = "Invoke the templates named, separated by a comma") @Parameter(names = arrayOf("-i", "--init"), description = "Create a build file based on the current project")
var templates: String? = null var init: Boolean = false
@Parameter(names = arrayOf("--listTemplates"), description = "List the available templates") @Parameter(names = arrayOf("--log"), description = "Define the log level (1-3)")
var listTemplates: Boolean = false var log: Int = 1
@Parameter(names = arrayOf("--log"), description = "Define the log level " + companion object {
"(${Constants.LOG_QUIET_LEVEL}-${Constants.LOG_MAX_LEVEL})") const val DEFAULT_SERVER_PORT = 1234
var log: Int = Constants.LOG_DEFAULT_LEVEL }
@Parameter(names = arrayOf("--logTags"),
description = "Comma-separated list of tags to enable logging for")
var logTags: String = ""
@Parameter(names = arrayOf("--forceIncremental"),
description = "Force the build to be incremental even if the build file was modified")
var forceIncremental: Boolean = false
@Parameter(names = arrayOf("--noIncremental"), description = "Turn off incremental builds")
var noIncremental: Boolean = false
@Parameter(names = arrayOf("--offline"), description = "Don't try to download dependencies even if there is no cached version")
var offline: Boolean = false
@Parameter(names = arrayOf("--plugins"), description = "Comma-separated list of plug-in Maven id's")
var pluginIds: String? = null
@Parameter(names = arrayOf("--pluginJarFiles"), description = "Comma-separated list of plug-in jar files")
var pluginJarFiles: String? = null
@Parameter(names = arrayOf("--port"), description = "Port, if --server was specified") @Parameter(names = arrayOf("--port"), description = "Port, if --server was specified")
var port: Int? = null var port: Int = DEFAULT_SERVER_PORT
@Parameter(names = arrayOf("--profiles"), description = "Comma-separated list of profiles to run") @Parameter(names = arrayOf("--profiles"), description = "Comma-separated list of profiles to run")
var profiles: String? = null var profiles: String? = null
@Parameter(names = arrayOf("--profiling"), description = "Display task timings at the end of the build") @Parameter(names = arrayOf("--resolve"), description = "Resolve the given dependency and display its tree")
var profiling: Boolean = false
@Parameter(names = arrayOf("--resolve"),
description = "Resolve the given dependency and display its tree")
var dependency: String? = null var dependency: String? = null
@Parameter(names = arrayOf("--projectInfo"), description = "Display information about the current projects")
var projectInfo: Boolean = false
@Parameter(names = arrayOf("--noIncrementalKotlin"), description = "Disable incremental Kotlin compilation")
var noIncrementalKotlin: Boolean = false
companion object {
const val SEQUENTIAL = "--sequential"
}
@Parameter(names = arrayOf(Args.SEQUENTIAL), description = "Build all the projects in sequence")
var sequential: Boolean = false
@Parameter(names = arrayOf("--server"), description = "Run in server mode") @Parameter(names = arrayOf("--server"), description = "Run in server mode")
var serverMode: Boolean = false var serverMode: Boolean = false
@ -104,8 +56,5 @@ class Args {
@Parameter(names = arrayOf("--update"), description = "Update to the latest version of Kobalt") @Parameter(names = arrayOf("--update"), description = "Update to the latest version of Kobalt")
var update: Boolean = false var update: Boolean = false
@Parameter(names = arrayOf("--version"), description = "Display the current version of Kobalt")
var version: Boolean = false
} }

View file

@ -1,18 +1,9 @@
package com.beust.kobalt package com.beust.kobalt
import com.beust.kobalt.misc.log
import java.util.* import java.util.*
/**
* Make Kobalt's output awesome and unique.
*
* I spend so much time staring at build outputs I decided I might as well make them pretty.
* Note that I also experimented with colors but it's hard to come up with a color scheme that
* will work with all the various backgrounds developers use, so I decided to be conservative
* and stick to simple red/yellow for errors and warnings.
*
* @author Cedric Beust <cedric@beust.com>
* @since 10/1/2015
*/
class AsciiArt { class AsciiArt {
companion object { companion object {
private val BANNERS = arrayOf( private val BANNERS = arrayOf(
@ -35,13 +26,19 @@ class AsciiArt {
val horizontalSingleLine = "\u2500\u2500\u2500\u2500\u2500" val horizontalSingleLine = "\u2500\u2500\u2500\u2500\u2500"
val horizontalDoubleLine = "\u2550\u2550\u2550\u2550\u2550" val horizontalDoubleLine = "\u2550\u2550\u2550\u2550\u2550"
val verticalBar = "\u2551"
// fun horizontalLine(n: Int) = StringBuffer().apply { // fun horizontalLine(n: Int) = StringBuffer().apply {
// repeat(n, { append("\u2500") }) // repeat(n, { append("\u2500") })
// }.toString() // }.toString()
// Repeat fun box(strings: List<String>) : List<String> {
val ul = "\u2554"
val ur = "\u2557"
val h = "\u2550"
val v = "\u2551"
val bl = "\u255a"
val br = "\u255d"
fun r(n: Int, w: String) : String { fun r(n: Int, w: String) : String {
with(StringBuffer()) { with(StringBuffer()) {
repeat(n, { append(w) }) repeat(n, { append(w) })
@ -49,45 +46,27 @@ class AsciiArt {
} }
} }
val h = "\u2550"
val ul = "\u2554"
val ur = "\u2557"
val bottomLeft = "\u255a"
val bottomRight = "\u255d"
// Bottom left with continuation
val bottomLeft2 = "\u2560"
// Bottom right with continuation
val bottomRight2 = "\u2563"
fun upperBox(max: Int) = ul + r(max + 2, h) + ur
fun lowerBox(max: Int, bl: String = bottomLeft, br : String = bottomRight) = bl + r(max + 2, h) + br
private fun box(strings: List<String>, bl: String = bottomLeft, br: String = bottomRight) : List<String> {
val v = verticalBar
val maxString: String = strings.maxBy { it.length } ?: "" val maxString: String = strings.maxBy { it.length } ?: ""
val max = maxString.length val max = maxString.length
val result = arrayListOf(upperBox(max)) val result = arrayListOf(ul + r(max + 2, h) + ur)
result.addAll(strings.map { "$v ${center(it, max - 2)} $v" }) result.addAll(strings.map { "$v ${center(it, max - 2)} $v" })
result.add(lowerBox(max, bl, br)) result.add(bl + r(max + 2, h) + br)
return result return result
} }
fun logBox(strings: List<String>, bl: String = bottomLeft, br: String = bottomRight, indent: Int = 0): String { private fun fill(n: Int) = StringBuffer().apply { repeat(n, { append(" ")})}.toString()
return buildString {
val boxLines = box(strings, bl, br) val defaultLog : (s: String) -> Unit = { log(1, " $it") }
boxLines.withIndex().forEach { iv ->
append(fill(indent)).append(iv.value) fun logBox(strings: List<String>, print: (String) -> Unit = defaultLog) {
if (iv.index < boxLines.size - 1) append("\n") box(strings).forEach {
} print(it)
} }
} }
fun logBox(s: String, bl: String = bottomLeft, br: String = bottomRight, indent: Int = 0) fun logBox(s: String, print: (String) -> Unit = defaultLog) {
= logBox(listOf(s), bl, br, indent) logBox(listOf(s), print)
}
fun fill(n: Int) = buildString { repeat(n, { append(" ")})}.toString()
fun center(s: String, width: Int) : String { fun center(s: String, width: Int) : String {
val diff = width - s.length val diff = width - s.length
@ -105,60 +84,14 @@ class AsciiArt {
const val CYAN = "\u001B[36m" const val CYAN = "\u001B[36m"
const val WHITE = "\u001B[37m" const val WHITE = "\u001B[37m"
fun wrap(s: CharSequence, color: String) = color + s + RESET private fun wrap(s: String, color: String) = color + s + RESET
private fun blue(s: CharSequence) = wrap(s, BLUE) private fun blue(s: String) = wrap(s, BLUE)
private fun red(s: CharSequence) = wrap(s, RED) private fun red(s: String) = wrap(s, RED)
private fun yellow(s: CharSequence) = wrap(s, YELLOW) private fun yellow(s: String) = wrap(s, YELLOW)
fun taskColor(s: CharSequence) = s fun taskColor(s: String) = s
fun errorColor(s: CharSequence) = red(s) fun errorColor(s: String) = red(s)
fun warnColor(s: CharSequence) = red(s) fun warnColor(s: String) = red(s)
} }
} }
class AsciiTable {
class Builder {
private val headers = arrayListOf<String>()
fun header(name: String) = headers.add(name)
fun headers(vararg names: String) = headers.addAll(names)
private val widths = arrayListOf<Int>()
fun columnWidth(w: Int) : Builder {
widths.add(w)
return this
}
private val rows = arrayListOf<List<String>>()
fun addRow(row: List<String>) = rows.add(row)
private fun col(width: Int, s: String) : String {
val format = " %1\$-${width.toString()}s"
val result = String.format(format, s)
return result
}
val vb = AsciiArt.verticalBar
fun build() : String {
val formattedHeaders =
headers.mapIndexed { index, s ->
val s2 = col(widths[index], s)
s2
}.joinToString(vb)
val result = StringBuffer().apply {
append(AsciiArt.logBox(formattedHeaders, AsciiArt.bottomLeft2, AsciiArt.bottomRight2))
append("\n")
}
var lineLength = 0
rows.forEachIndexed { _, row ->
val formattedRow = row.mapIndexed { i, s -> col(widths[i], s) }.joinToString(vb)
val line = "$vb $formattedRow $vb"
result.append(line).append("\n")
lineLength = line.length
}
result.append(AsciiArt.lowerBox(lineLength - 4))
return result.toString()
}
}
}

View file

@ -4,9 +4,8 @@ import com.beust.kobalt.api.IPlugin
import com.beust.kobalt.api.PluginTask import com.beust.kobalt.api.PluginTask
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
abstract class BasePluginTask(override val plugin: IPlugin, public abstract class BasePluginTask(override val plugin: IPlugin,
override val name: String, override val name: String,
override val doc: String, override val doc: String,
override val group: String,
override val project: Project) override val project: Project)
: PluginTask() : PluginTask()

View file

@ -3,89 +3,34 @@ package com.beust.kobalt
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.maven.DepFactory
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.maven.dependency.FileDependency
import com.beust.kobalt.misc.KobaltLogger
import org.eclipse.aether.repository.Proxy
import java.io.File import java.io.File
import java.net.InetSocketAddress
var BUILD_SCRIPT_CONFIG : BuildScriptConfig? = null
class BuildScriptConfig {
/** The list of repos used to locate plug-ins. */
@Directive
fun repos(vararg r: String) = newRepos(*r)
/** The list of plug-ins to use for this build file. */
@Directive
fun plugins(vararg pl: String) = newPlugins(*pl)
/** The build file classpath. */
@Directive
fun buildFileClasspath(vararg bfc: String) = newBuildFileClasspath(*bfc)
/** Options passed to Kobalt */
@Directive
fun kobaltOptions(vararg options: String) = Kobalt.addKobaltOptions(options)
/** Where to find additional build files */
@Directive
fun buildSourceDirs(vararg dirs: String) = Kobalt.addBuildSourceDirs(dirs)
// The following settings modify the compiler used to compile the build file, which regular users should
// probably never need to do. Projects should use kotlinCompiler { compilerVersion } to configure the
// Kotin compiler for their source files.
var kobaltCompilerVersion : String? = null
var kobaltCompilerRepo: String? = null
var kobaltCompilerFlags: String? = null
}
@Directive @Directive
fun homeDir(vararg dirs: String) : String = SystemProperties.homeDir + fun homeDir(vararg dirs: String) : String = SystemProperties.homeDir +
File.separator + dirs.toMutableList().joinToString(File.separator) File.separator + dirs.toArrayList().joinToString(File.separator)
@Directive
fun localMavenRepo() = homeDir(".m2" + File.separator + "repository/")
@Directive @Directive
fun file(file: String) : String = FileDependency.PREFIX_FILE + file fun file(file: String) : String = FileDependency.PREFIX_FILE + file
@Directive
fun plugins(vararg dependency : IClasspathDependency) { fun plugins(vararg dependency : IClasspathDependency) {
dependency.forEach { Plugins.addDynamicPlugin(it) } dependency.forEach { Plugins.addDynamicPlugin(it) }
} }
fun plugins(vararg dependencies : String) {
KobaltLogger.logger.warn("Build.kt",
"Invoking plugins() directly is deprecated, use the buildScript{} directive")
newPlugins(*dependencies)
}
@Directive @Directive
fun newPlugins(vararg dependencies : String) { fun plugins(vararg dependencies : String) {
val factory = Kobalt.INJECTOR.getInstance(DependencyManager::class.java) val factory = Kobalt.INJECTOR.getInstance(DepFactory::class.java)
dependencies.forEach { dependencies.forEach {
Plugins.addDynamicPlugin(factory.create(it)) Plugins.addDynamicPlugin(factory.create(it))
} }
} }
data class ProxyConfig(val host: String = "", val port: Int = 0, val type: String = "", val nonProxyHosts: String = "") { data class HostConfig(var url: String = "", var username: String? = null, var password: String? = null) {
fun toProxy() = java.net.Proxy(java.net.Proxy.Type.HTTP, InetSocketAddress(host, port))
fun toAetherProxy() = Proxy(type, host, port) // TODO make support for proxy auth
}
data class HostConfig(var url: String = "", var name: String = HostConfig.createRepoName(url),
var username: String? = null, var password: String? = null) {
companion object {
/**
* For repos specified in the build file (repos()) that don't have an associated unique name,
* create such a name from the URL. This is a requirement from Maven Resolver, and failing to do
* this leads to very weird resolution errors.
*/
private fun createRepoName(url: String) = url.replace("/", "_").replace("\\", "_").replace(":", "_")
}
fun hasAuth() : Boolean { fun hasAuth() : Boolean {
return (! username.isNullOrBlank()) && (! password.isNullOrBlank()) return (! username.isNullOrBlank()) && (! password.isNullOrBlank())
} }
@ -99,47 +44,18 @@ data class HostConfig(var url: String = "", var name: String = HostConfig.create
} }
} }
@Directive
fun repos(vararg repos : String) { fun repos(vararg repos : String) {
KobaltLogger.logger.warn("Build.kt",
"Invoking repos() directly is deprecated, use the buildScript{} directive")
newRepos(*repos)
}
fun newRepos(vararg repos: String) {
repos.forEach { Kobalt.addRepo(HostConfig(it)) } repos.forEach { Kobalt.addRepo(HostConfig(it)) }
} }
fun buildFileClasspath(vararg deps: String) {
KobaltLogger.logger.warn("Build.kt",
"Invoking buildFileClasspath() directly is deprecated, use the buildScript{} directive")
newBuildFileClasspath(*deps)
}
fun newBuildFileClasspath(vararg deps: String) {
//FIXME newBuildFileClasspath called twice
deps.forEach { Kobalt.addBuildFileClasspath(it) }
}
@Directive @Directive
fun authRepos(vararg repos : HostConfig) { fun authRepos(vararg repos : HostConfig) {
repos.forEach { Kobalt.addRepo(it) } repos.forEach { Kobalt.addRepo(it) }
} }
@Directive @Directive
fun authRepo(init: HostConfig.() -> Unit) = HostConfig(name = "").apply { init() } fun authRepo(init: HostConfig.() -> Unit) = HostConfig().apply { init() }
@Directive @Directive
fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g) fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g)
/**
* The location of the local Maven repository.
*/
@Directive
fun localMaven() : String {
val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java)
val initial = Kobalt.INJECTOR.getInstance(KobaltSettings::class.java).localMavenRepo
val result = pluginInfo.localMavenRepoPathInterceptors.fold(initial) { current, interceptor ->
File(interceptor.repoPath(current.absolutePath))
}
return result.toURI().toString()
}

View file

@ -1,25 +1,15 @@
package com.beust.kobalt package com.beust.kobalt
import com.beust.kobalt.misc.KFiles
object Constants { object Constants {
const val LOG_QUIET_LEVEL = 0
const val LOG_DEFAULT_LEVEL = 1
const val LOG_MAX_LEVEL = 3
val BUILD_FILE_NAME = "Build.kt" val BUILD_FILE_NAME = "Build.kt"
val BUILD_FILE_DIRECTORY = "kobalt/src" val BUILD_FILE_DIRECTORY = "kobalt/src"
val BUILD_FILE_PATH = KFiles.joinDir(BUILD_FILE_DIRECTORY, BUILD_FILE_NAME)
val KOTLIN_COMPILER_VERSION = "1.2.70"
internal val DEFAULT_REPOS = listOf<HostConfig>( internal val DEFAULT_REPOS = listOf(
// "https://maven-central.storage.googleapis.com/", "http://repo1.maven.org/maven2/",
HostConfig("https://repo1.maven.org/maven2/", "Maven"), "https://maven-central.storage.googleapis.com/",
HostConfig("https://jcenter.bintray.com/", "JCenter") "https://repository.jboss.org/nexus/content/repositories/root_repository/",
// "https://repository.jetbrains.com/all/", // <-- contains snapshots "https://jcenter.bintray.com/",
"http://repository.jetbrains.com/all/"
// snapshots
// "https://oss.sonatype.org/content/repositories/snapshots/"
// , "https://repository.jboss.org/nexus/content/repositories/root_repository/"
) )
} }

View file

@ -1,39 +0,0 @@
package com.beust.kobalt
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.internal.JvmCompilerPlugin
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@Directive
fun project(vararg projects: Project, init: Project.() -> Unit): Project {
return Project("").apply {
init()
(Kobalt.findPlugin(JvmCompilerPlugin.PLUGIN_NAME) as JvmCompilerPlugin)
.addDependentProjects(this, projects.toList())
}
}
@Directive
fun buildScript(init: BuildScriptConfig.() -> Unit): BuildScriptConfig {
val buildScriptConfig = BuildScriptConfig().apply { init() }
BUILD_SCRIPT_CONFIG = buildScriptConfig
return buildScriptConfig
}
@Directive
fun profile(): ReadWriteProperty<Nothing?, Boolean> {
val result = object: ReadWriteProperty<Nothing?, Boolean> {
var value: Boolean = false
override operator fun getValue(thisRef: Nothing?, property: KProperty<*>): Boolean {
return value
}
override operator fun setValue(thisRef: Nothing?, property: KProperty<*>, value: Boolean) {
this.value = value
}
}
return result
}

View file

@ -1,6 +1,6 @@
package com.beust.kobalt package com.beust.kobalt
import com.beust.kobalt.misc.kobaltLog import com.beust.kobalt.misc.log
import java.io.File import java.io.File
import java.nio.file.* import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes import java.nio.file.attribute.BasicFileAttributes
@ -10,17 +10,14 @@ import java.nio.file.attribute.BasicFileAttributes
* and GlobSpec (a spec defined by a glob, e.g. ** slash *Test.class) * and GlobSpec (a spec defined by a glob, e.g. ** slash *Test.class)
*/ */
sealed class IFileSpec { sealed class IFileSpec {
abstract fun toFiles(baseDir: String?, filePath: String, excludes: List<Glob> = emptyList<Glob>()): List<File> abstract fun toFiles(filePath: String, excludes: List<Glob> = emptyList<Glob>()): List<File>
class FileSpec(val spec: String) : IFileSpec() { class FileSpec(val spec: String) : IFileSpec() {
override fun toFiles(baseDir: String?, filePath: String, excludes: List<Glob>) = listOf(File(spec)) override public fun toFiles(filePath: String, excludes: List<Glob>) = listOf(File(spec))
override fun toString() = spec override public fun toString() = spec
} }
/**
* A glob matcher, see http://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29
*/
class GlobSpec(val spec: List<String>) : IFileSpec() { class GlobSpec(val spec: List<String>) : IFileSpec() {
constructor(spec: String) : this(arrayListOf(spec)) constructor(spec: String) : this(arrayListOf(spec))
@ -28,43 +25,32 @@ sealed class IFileSpec {
private fun isIncluded(includeMatchers: Glob, excludes: List<Glob>, rel: Path) : Boolean { private fun isIncluded(includeMatchers: Glob, excludes: List<Glob>, rel: Path) : Boolean {
excludes.forEach { excludes.forEach {
if (it.matches(rel)) { if (it.matches(rel)) {
kobaltLog(3, " Excluding ${rel.toFile()}") log(2, "Excluding ${rel.toFile()}")
return false return false
} }
} }
if (includeMatchers.matches(rel)) { if (includeMatchers.matches(rel)) {
kobaltLog(3, " Including ${rel.toFile().path}") log(2, "Including ${rel.toFile()}")
return true return true
} }
kobaltLog(2, " Excluding ${rel.toFile()} (not matching any include pattern") log(2, "Excluding ${rel.toFile()} (not matching any include pattern")
return false return false
} }
override fun toFiles(baseDir: String?, filePath: String, excludes: List<Glob>): List<File> { override public fun toFiles(filePath: String, excludes: List<Glob>): List<File> {
val result = arrayListOf<File>() val result = arrayListOf<File>()
val includes = Glob(*spec.toTypedArray()) val includes = Glob(*spec.toTypedArray())
if (File(baseDir, filePath).isDirectory) { if (File(filePath).isDirectory) {
val orgRootDir = (if (File(filePath).isAbsolute) Paths.get(filePath) Files.walkFileTree(Paths.get(filePath), object : SimpleFileVisitor<Path>() {
else if (baseDir != null) Paths.get(baseDir, filePath) override public fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult {
else Paths.get(filePath)).run { normalize() } val rel = Paths.get(filePath).relativize(path)
// Paths.get(".").normalize() returns an empty string, which is not a valid file :-( if (isIncluded(includes, excludes, rel)) {
val rootDir = if (orgRootDir.toFile().path.isEmpty()) Paths.get("./") else orgRootDir
if (rootDir.toFile().exists()) {
Files.walkFileTree(rootDir, object : SimpleFileVisitor<Path>() {
override fun visitFile(p: Path, attrs: BasicFileAttributes): FileVisitResult {
val path = p.normalize()
val rel = orgRootDir.relativize(path)
if (isIncluded(includes, excludes, path)) {
kobaltLog(3, " including file " + rel.toFile() + " from rootDir $rootDir")
result.add(rel.toFile()) result.add(rel.toFile())
} }
return FileVisitResult.CONTINUE return FileVisitResult.CONTINUE
} }
}) })
} else {
throw AssertionError("Directory \"$rootDir\" should exist")
}
} else { } else {
if (isIncluded(includes, excludes, Paths.get(filePath))) { if (isIncluded(includes, excludes, Paths.get(filePath))) {
result.add(File(filePath)) result.add(File(filePath))
@ -74,7 +60,7 @@ sealed class IFileSpec {
return result return result
} }
override fun toString(): String { override public fun toString(): String {
var result = "" var result = ""
spec.apply { spec.apply {
if (!isEmpty()) { if (!isEmpty()) {

View file

@ -1,43 +0,0 @@
package com.beust.kobalt
import com.beust.kobalt.api.annotation.Directive
import java.io.File
/**
* Base classes for directives that support install(from,to) (e.g. install{} or jar{}).
*/
open class IncludeFromTo {
/**
* Prefix path to be removed from the zip file. For example, if you add "build/lib/a.jar" to the zip
* file and the excludePrefix is "build/lib", then "a.jar" will be added at the root of the zip file.
*/
val includedFiles = arrayListOf<IncludedFile>()
@Directive
fun from(s: String) = From(s)
@Directive
fun to(s: String) = To(s)
@Directive
fun copy(from: From, to: To) {
val dir = File(from.path).absoluteFile.parentFile
includedFiles.add(IncludedFile(from(dir.absolutePath), to, listOf(IFileSpec.FileSpec(from.path))))
}
@Directive
fun include(vararg files: String) {
includedFiles.add(IncludedFile(files.map { IFileSpec.FileSpec(it) }))
}
@Directive
fun include(from: From, to: To, vararg specs: String) {
includedFiles.add(IncludedFile(from, to, specs.map { IFileSpec.FileSpec(it) }))
}
@Directive
fun include(from: From, to: To, vararg specs: IFileSpec.GlobSpec) {
includedFiles.add(IncludedFile(from, to, listOf(*specs)))
}
}

View file

@ -1,44 +0,0 @@
package com.beust.kobalt
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.toString
import java.io.File
import java.nio.file.Paths
class IncludedFile(val fromOriginal: From, val toOriginal: To, val specs: List<IFileSpec>,
val expandJarFiles: Boolean = false) {
constructor(specs: List<IFileSpec>, expandJarFiles: Boolean = false) : this(From(""), To(""), specs, expandJarFiles)
fun from(s: String) = File(if (fromOriginal.isCurrentDir()) s else KFiles.joinDir(from, s))
val from: String get() = fromOriginal.path.replace("\\", "/")
fun to(s: String) = File(if (toOriginal.isCurrentDir()) s else KFiles.joinDir(to, s))
val to: String get() = toOriginal.path.replace("\\", "/")
override fun toString() = toString("IncludedFile",
"files - ", specs.map { it.toString() },
"from", from,
"to", to)
fun allFromFiles(directory: String? = null): List<File> {
val result = arrayListOf<File>()
specs.forEach { spec ->
// val fullDir = if (directory == null) from else KFiles.joinDir(directory, from)
spec.toFiles(directory, from).forEach { source ->
result.add(if (source.isAbsolute) source else File(source.path))
}
}
return result.map { Paths.get(it.path).normalize().toFile()}
}
}
open class Direction(open val p: String) {
override fun toString() = path
fun isCurrentDir() = path == "./"
val path: String get() =
if (p.isEmpty()) "./"
else if (p.startsWith("/") || p.endsWith("/")) p
else p + "/"
}
class From(override val p: String) : Direction(p)
class To(override val p: String) : Direction(p)

View file

@ -1,17 +1,16 @@
package com.beust.kobalt package com.beust.kobalt
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
/** /**
* @param inputChecksum The checksum for the input to this task. It gets compared against the previous checksum * @param inputChecksum The checksum for the input to this task. It gets compared against the checksum of
* calculated by Kobalt. If they differ, the task gets run. If they are equal, outputChecksums are then compared. * if they differ, the task gets run. If they are equal, outputChecksums are then compared.
* @param outputChecksum The checksum for the output of this task. If null, the output is absent * @param outputChecksum The checksum for the output of this task. If null, the output is absent
* and the task will be run. If non null, it gets compared against the checksum of the previous run and * and the task will be run. If non null, it gets compared against the checksum of the previous run and
* if they differ, the task gets run. * if they differ, the task gets run. Note that this parameter is a closure and not a direct value
* because Kobalt needs to call it twice: once before the task and once after a successful execution (to store it).
* @param task The task to run. * @param task The task to run.
*/ */
class IncrementalTaskInfo(val inputChecksum: () -> String?, class IncrementalTaskInfo(val inputChecksum: String?,
val outputChecksum: () -> String?, val outputChecksum: () -> String?,
val task: (Project) -> TaskResult, val task: (Project) -> TaskResult)
val context: KobaltContext)

View file

@ -1,162 +0,0 @@
package com.beust.kobalt
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.archive.Archives
import com.beust.kobalt.archive.MetaArchive
import com.beust.kobalt.archive.Zip
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.kobaltLog
import com.google.inject.Inject
import java.io.File
import java.io.FileInputStream
import java.nio.file.Paths
import java.util.jar.Manifest
class JarGenerator @Inject constructor(val dependencyManager: DependencyManager) : ArchiveGenerator {
companion object {
fun findIncludedFiles(directory: String, files: List<IncludedFile>, excludes: List<Glob>,
throwOnError: Boolean = true)
: List<IncludedFile> {
val result = arrayListOf<IncludedFile>()
files.forEach { includedFile ->
val includedSpecs = arrayListOf<IFileSpec>()
includedFile.specs.forEach { spec ->
val fromPath = includedFile.from
if (File(directory, fromPath).exists()) {
spec.toFiles(directory, fromPath).forEach { file ->
val fullFile = File(KFiles.joinDir(directory, fromPath, file.path))
if (! fullFile.exists() && throwOnError) {
throw AssertionError("File should exist: $fullFile")
}
if (!KFiles.isExcluded(fullFile, excludes)) {
val normalized = Paths.get(file.path).normalize().toFile().path
includedSpecs.add(IFileSpec.FileSpec(normalized))
} else {
kobaltLog(2, "Not adding ${file.path} to jar file because it's excluded")
}
}
} else {
kobaltLog(2, " Directory $fromPath doesn't exist, not including it in the jar")
}
}
if (includedSpecs.size > 0) {
kobaltLog(3, "Including specs $includedSpecs")
result.add(IncludedFile(From(includedFile.from), To(includedFile.to), includedSpecs))
}
}
return result
}
}
override val suffix = ".jar"
override fun findIncludedFiles(project: Project, context: KobaltContext, zip: Zip) : List<IncludedFile> {
//
// Add all the applicable files for the current project
//
val buildDir = KFiles.buildDir(project)
val result = arrayListOf<IncludedFile>()
val classesDir = KFiles.makeDir(buildDir.path, "classes")
if (zip.includedFiles.isEmpty()) {
// If no includes were specified, assume the user wants a simple jar file made of the
// classes of the project, so we specify a From("build/classes/"), To("") and
// a list of files containing everything under it
val relClassesDir = Paths.get(project.directory).relativize(Paths.get(classesDir.path))
val prefixPath = Paths.get(project.directory).relativize(Paths.get(classesDir.path + "/"))
// Class files
val files = KFiles.findRecursively(classesDir).map { File(relClassesDir.toFile(), it) }
val filesNotExcluded : List<File> = files.filter {
! KFiles.Companion.isExcluded(KFiles.joinDir(project.directory, it.path), zip.excludes)
}
val fileSpecs = arrayListOf<IFileSpec>()
filesNotExcluded.forEach {
fileSpecs.add(IFileSpec.FileSpec(it.path.toString().substring(prefixPath.toString().length + 1)))
}
result.add(IncludedFile(From(prefixPath.toString()), To(""), fileSpecs))
// Resources, if applicable
context.variant.resourceDirectories(project).forEach {
result.add(IncludedFile(From(it.path), To(""), listOf(IFileSpec.GlobSpec("**"))))
}
} else {
//
// The user specified an include, just use it verbatim
//
val includedFiles = findIncludedFiles(project.directory, zip.includedFiles, zip.excludes, false)
result.addAll(includedFiles)
}
//
// If fatJar is true, add all the transitive dependencies as well: compile, runtime and dependent projects
//
if (zip.fatJar) {
val seen = hashSetOf<String>()
@Suppress("UNCHECKED_CAST")
val allDependencies = project.compileDependencies + project.compileRuntimeDependencies +
context.variant.buildType.compileDependencies +
context.variant.buildType.compileRuntimeDependencies +
context.variant.productFlavor.compileDependencies +
context.variant.productFlavor.compileRuntimeDependencies
val transitiveDependencies = dependencyManager.calculateDependencies(project, context,
scopes = listOf(Scope.COMPILE), passedDependencies = allDependencies)
transitiveDependencies.map {
it.jarFile.get()
}.forEach { file : File ->
if (! seen.contains(file.path)) {
seen.add(file.path)
if (! KFiles.Companion.isExcluded(file, zip.excludes)) {
result.add(IncludedFile(specs = arrayListOf(IFileSpec.FileSpec(file.absolutePath)),
expandJarFiles = true))
}
}
}
}
return result
}
override fun generateArchive(project: Project, context: KobaltContext, zip: Zip,
includedFiles: List<IncludedFile>) : File {
//
// Generate the manifest
// If manifest attributes were specified in the build file, use those to generateAndSave the manifest. Otherwise,
// try to find a META-INF/MANIFEST.MF and use that one if we find any. Otherwise, use the default manifest.
//
val manifest =
if (zip.attributes.size > 1) {
context.logger.log(project.name, 2, "Creating MANIFEST.MF from " + zip.attributes.size + " attributes")
Manifest().apply {
zip.attributes.forEach { attribute ->
mainAttributes.putValue(attribute.first, attribute.second)
}
}
} else {
fun findManifestFile(project: Project, includedFiles: List<IncludedFile>): File? {
val allFiles = includedFiles.flatMap { file ->
file.allFromFiles(project.directory).map { file.from(it.path) }
}
val manifestFiles = allFiles.filter { it.path.contains(MetaArchive.MANIFEST_MF) }
return if (manifestFiles.any()) manifestFiles[0] else null
}
val manifestFile = findManifestFile(project, includedFiles)
if (manifestFile != null) {
context.logger.log(project.name, 2, "Including MANIFEST.MF file $manifestFile")
Manifest(FileInputStream(manifestFile))
} else {
null
}
}
return Archives.generateArchive(project, context, zip.name, ".jar", includedFiles,
true /* expandJarFiles */, manifest)
}
}

View file

@ -2,18 +2,18 @@ package com.beust.kobalt
import java.io.File import java.io.File
abstract class JavaInfo { abstract public class JavaInfo {
val javaExecutable: File? public var javaExecutable: File? = null
get() = findExecutable("java") get() = findExecutable("java")
val javacExecutable: File? public var javacExecutable: File? = null
get() = findExecutable("javac") get() = findExecutable("javac")
val javadocExecutable: File? public var javadocExecutable: File? = null
get() = findExecutable("javadoc") get() = findExecutable("javadoc")
abstract var javaHome: File? abstract public var javaHome: File?
abstract var runtimeJar: File? abstract public var runtimeJar: File?
abstract var toolsJar: File? abstract public var toolsJar: File?
abstract fun findExecutable(command: String) : File abstract public fun findExecutable(command: String) : File
companion object { companion object {
fun create(javaBase: File?): Jvm { fun create(javaBase: File?): Jvm {

View file

@ -1,18 +1,18 @@
package com.beust.kobalt package com.beust.kobalt
import com.beust.kobalt.misc.kobaltLog import com.beust.kobalt.misc.log
import com.beust.kobalt.misc.warn import com.beust.kobalt.misc.warn
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
open class Jvm constructor( public open class Jvm constructor(
val os: OperatingSystem, val os: OperatingSystem,
var javaBase: File? = null) : JavaInfo() { var javaBase: File? = null) : JavaInfo() {
private var _javaHome: File? = null private var _javaHome: File? = null
override var javaHome: File? = null override public var javaHome: File? = null
get() = _javaHome!! get() = _javaHome!!
override var runtimeJar: File? = null override public var runtimeJar: File? = null
private fun findRuntimeJar() : File? { private fun findRuntimeJar() : File? {
var runtimeJar = File(javaBase, "lib/rt.jar") var runtimeJar = File(javaBase, "lib/rt.jar")
if (runtimeJar.exists()) { if (runtimeJar.exists()) {
@ -21,7 +21,7 @@ open class Jvm constructor(
runtimeJar = File(javaBase, "jre/lib/rt.jar") runtimeJar = File(javaBase, "jre/lib/rt.jar")
return if (runtimeJar.exists()) runtimeJar else null return if (runtimeJar.exists()) runtimeJar else null
} }
override var toolsJar: File? = null override public var toolsJar: File? = null
private var userSupplied: Boolean? = false private var userSupplied: Boolean? = false
private var javaVersion: String? = null private var javaVersion: String? = null
@ -67,7 +67,7 @@ open class Jvm constructor(
return toolsJar return toolsJar
} }
if (javaHome!!.name.equals("jre", true)) { if (javaHome!!.name.equals("jre", true)) {
_javaHome = javaHome!!.parentFile javaHome = javaHome!!.parentFile
toolsJar = File(javaHome, "lib/tools.jar") toolsJar = File(javaHome, "lib/tools.jar")
if (toolsJar.exists()) { if (toolsJar.exists()) {
return toolsJar return toolsJar
@ -78,7 +78,7 @@ open class Jvm constructor(
val version = SystemProperties.Companion.javaVersion val version = SystemProperties.Companion.javaVersion
if (javaHome!!.name.toRegex().matches("jre\\d+") if (javaHome!!.name.toRegex().matches("jre\\d+")
|| javaHome!!.name == "jre$version") { || javaHome!!.name == "jre$version") {
_javaHome = File(javaHome!!.parentFile, "jdk$version") javaHome = File(javaHome!!.parentFile, "jdk$version")
toolsJar = File(javaHome, "lib/tools.jar") toolsJar = File(javaHome, "lib/tools.jar")
if (toolsJar.exists()) { if (toolsJar.exists()) {
return toolsJar return toolsJar
@ -89,15 +89,15 @@ open class Jvm constructor(
return null return null
} }
// open fun isIbmJvm(): Boolean { // open public fun isIbmJvm(): Boolean {
// return false // return false
// } // }
override fun findExecutable(command: String): File { override public fun findExecutable(command: String): File {
if (javaHome != null) { if (javaHome != null) {
val jdkHome = if (javaHome!!.endsWith("jre")) javaHome!!.parentFile else javaHome val jdkHome = if (javaHome!!.endsWith("jre")) javaHome!!.parentFile else javaHome
val exec = File(jdkHome, "bin/" + command) val exec = File(jdkHome, "bin/" + command)
val executable = File(os.getExecutableName(exec.absolutePath)) var executable = File(os.getExecutableName(exec.absolutePath))
if (executable.isFile) { if (executable.isFile) {
return executable return executable
} }
@ -110,7 +110,7 @@ open class Jvm constructor(
val pathExecutable = os.findInPath(command) val pathExecutable = os.findInPath(command)
if (pathExecutable != null) { if (pathExecutable != null) {
kobaltLog(2, "Unable to find the $command executable using home: " + log(2, "Unable to find the $command executable using home: " +
"$javaHome but found it on the PATH: $pathExecutable.") "$javaHome but found it on the PATH: $pathExecutable.")
return pathExecutable return pathExecutable
} }

View file

@ -3,32 +3,29 @@ package com.beust.kobalt
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.api.annotation.IncrementalTask import com.beust.kobalt.api.annotation.IncrementalTask
import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.internal.IncrementalManager
import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.TaskManager import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DepFactory
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.misc.JarUtils import com.beust.kobalt.misc.JarUtils
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.KobaltExecutors
import com.beust.kobalt.misc.kobaltLog import com.beust.kobalt.misc.log
import com.google.inject.Provider import com.google.inject.Provider
import java.io.File
import java.lang.reflect.Method import java.lang.reflect.Method
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.net.URLClassLoader
import java.util.* import java.util.*
import java.util.jar.JarFile import java.util.jar.JarFile
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManager>, public class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManager>,
val files: KFiles, val files: KFiles,
val depManager: DependencyManager, val depFactory: DepFactory,
val settings: KobaltSettings, val localRepo: LocalRepo,
val executors: KobaltExecutors, val executors: KobaltExecutors,
val incrementalManagerFactory: IncrementalManager.IFactory, val pluginInfo: PluginInfo,
val taskManager: TaskManager) { val taskManager: TaskManager) {
companion object { companion object {
@ -50,8 +47,6 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
fun findPlugin(name: String) : IPlugin? = pluginMap[name] fun findPlugin(name: String) : IPlugin? = pluginMap[name]
} }
fun shutdownPlugins() = plugins.forEach { it.shutdown() }
fun applyPlugins(context: KobaltContext, projects: List<Project>) { fun applyPlugins(context: KobaltContext, projects: List<Project>) {
plugins.forEach { plugin -> plugins.forEach { plugin ->
addPluginInstance(plugin) addPluginInstance(plugin)
@ -64,7 +59,7 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
} }
// Call apply() on each plug-in that accepts a project // Call apply() on each plug-in that accepts a project
kobaltLog(2, "Applying plug-in \"${plugin.name}\"") log(2, "Applying plug-in \"${plugin.name}\"")
projects.filter { plugin.accept(it) }.forEach { project -> projects.filter { plugin.accept(it) }.forEach { project ->
plugin.apply(project, context) plugin.apply(project, context)
} }
@ -80,26 +75,7 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
// Collect all the tasks from the task contributors // Collect all the tasks from the task contributors
context.pluginInfo.taskContributors.forEach { context.pluginInfo.taskContributors.forEach {
projects.forEach { project -> taskManager.dynamicTasks.addAll(it.tasksFor(context).map { TaskManager.PluginDynamicTask(it.plugin, it) })
taskManager.dynamicTasks.addAll(it.tasksFor(project, context))
}
}
// ... and from the incremental task contributors
val incrementalManager = incrementalManagerFactory.create()
context.pluginInfo.incrementalTaskContributors.forEach {
projects.forEach { project ->
it.incrementalTasksFor(project, context).forEach {
// Convert the closure (Project) -> IncrementalTaskInfo to (Project) -> TaskResult
// and create a DynamicTask out of it
val closure =
incrementalManager.toIncrementalTaskClosure(it.name, it.incrementalClosure, Variant())
val task = DynamicTask(it.plugin, it.name, it.doc, it.group, it.project, it.dependsOn,
it.reverseDependsOn, it.runBefore, it.runAfter, it.alwaysRunAfter,
closure)
taskManager.dynamicTasks.add(task)
}
}
} }
// Now that we have collected all static and dynamic tasks, turn them all into plug-in tasks // Now that we have collected all static and dynamic tasks, turn them all into plug-in tasks
@ -110,7 +86,7 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
: List<Pair<Method, T>> { : List<Pair<Method, T>> {
val result = arrayListOf<Pair<Method, T>>() val result = arrayListOf<Pair<Method, T>>()
var currentClass : Class<in Any>? = plugin.javaClass var currentClass : Class<in Any> = plugin.javaClass
// Tasks can come from two different places: plugin classes and build files. // Tasks can come from two different places: plugin classes and build files.
// When a task is read from a build file, ScriptCompiler adds it right away to plugin.methodTasks. // When a task is read from a build file, ScriptCompiler adds it right away to plugin.methodTasks.
@ -170,34 +146,20 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
val dependencies = arrayListOf<IClasspathDependency>() val dependencies = arrayListOf<IClasspathDependency>()
// @Inject fun installPlugins(dependencies: List<IClasspathDependency>, classLoader: ClassLoader) {
// lateinit var pluginInfo: PluginInfo
fun installPlugins(dependencies: List<IClasspathDependency>, scriptClassLoader: ClassLoader) {
val executor = executors.newExecutor("Plugins", 5) val executor = executors.newExecutor("Plugins", 5)
dependencies.forEach { dependencies.forEach {
// //
// Load all the jar files synchronously (can't compile the build script until // Load all the jar files synchronously (can't compile the build script until
// they are installed locally). // they are installed locally).
depManager.create(it.id) depFactory.create(it.id, executor)
// //
// Open the jar, parse its kobalt-plugin.xml and add the resulting PluginInfo to pluginInfo // Open the jar, parse its kobalt-plugin.xml and add the resulting PluginInfo to pluginInfo
// //
val file = it.jarFile.get() val pluginXml = JarUtils.extractTextFile(JarFile(it.jarFile.get()), PluginInfo.PLUGIN_XML)
val pluginXml = if (file.isDirectory) {
// The plug-in can point to a directory (e.g. plugin("classes")), in which case we just
// read kobalt-plugin.xml directly
File(file, PluginInfo.PLUGIN_XML).readText()
} else {
// The plug-in is pointing to a jar file, read kobalt-plugin.xml from it
JarUtils.extractTextFile(JarFile(file), PluginInfo.PLUGIN_XML)
}
val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java)
if (pluginXml != null) { if (pluginXml != null) {
val pluginClassLoader = URLClassLoader(arrayOf(file.toURI().toURL())) val thisPluginInfo = PluginInfo.readPluginXml(pluginXml, classLoader)
val thisPluginInfo = PluginInfo.readPluginXml(pluginXml, pluginClassLoader, scriptClassLoader)
pluginInfo.addPluginInfo(thisPluginInfo) pluginInfo.addPluginInfo(thisPluginInfo)
thisPluginInfo.plugins.forEach { thisPluginInfo.plugins.forEach {
Plugins.addPluginInstance(it) Plugins.addPluginInstance(it)

View file

@ -3,20 +3,18 @@ package com.beust.kobalt
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.maven.LocalRepo import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.MavenId import com.beust.kobalt.maven.MavenId
import com.beust.kobalt.maven.aether.* import com.beust.kobalt.maven.RepoFinder
import com.beust.kobalt.misc.* import com.beust.kobalt.maven.SimpleDep
import com.beust.kobalt.maven.dependency.MavenDependency
import com.beust.kobalt.misc.Node
import com.beust.kobalt.misc.log
import com.google.inject.Inject import com.google.inject.Inject
import org.eclipse.aether.artifact.DefaultArtifact
import org.eclipse.aether.graph.DependencyNode
import java.util.* import java.util.*
/** /**
* Display information about a Maven id. * Display information about a Maven id.
*/ */
class ResolveDependency @Inject constructor( class ResolveDependency @Inject constructor(val repoFinder: RepoFinder, val localRepo: LocalRepo) {
val localRepo: LocalRepo,
val aether: KobaltMavenResolver,
val executors: KobaltExecutors) {
val increment = 8 val increment = 8
val leftFirst = "\u2558" val leftFirst = "\u2558"
val leftMiddle = "\u255f" val leftMiddle = "\u255f"
@ -25,51 +23,26 @@ class ResolveDependency @Inject constructor(
class Dep(val dep: IClasspathDependency, val level: Int) class Dep(val dep: IClasspathDependency, val level: Int)
fun run(id: String) = displayDependenciesFor(id) fun run(id: String) {
val repoResult = repoFinder.findCorrectRepo(id)
private fun latestMavenArtifact(group: String, artifactId: String, extension: String = "jar"): DependencyNode {
val artifact = DefaultArtifact(group, artifactId, extension, "(0,]")
val resolved = aether.resolveRange(artifact)
if (resolved != null) {
val newArtifact = DefaultArtifact(artifact.groupId, artifact.artifactId, artifact.extension,
resolved.highestVersion.toString())
val artifactResult = aether.resolve(KobaltMavenResolver.artifactToId(newArtifact), null)
return artifactResult.root
} else {
throw KobaltException("Couldn't find latest artifact for $group:$artifactId")
}
}
class PairResult(val dependency: IClasspathDependency, val repoUrl: String)
fun latestArtifact(group: String, artifactId: String, extension: String = "jar"): PairResult
= latestMavenArtifact(group, artifactId, extension).let {
PairResult(AetherDependency(it.artifact), "(TBD repo)")
}
private fun displayDependenciesFor(id: String) {
val mavenId = MavenId.create(id)
val resolved : PairResult =
if (mavenId.hasVersion) {
val node = aether.resolve(id, filter = Filters.EXCLUDE_OPTIONAL_FILTER)
PairResult(AetherDependency(node.root.artifact), node.artifactResults[0].repository.toString())
} else {
latestArtifact(mavenId.groupId, mavenId.artifactId)
}
displayDependencies(resolved.dependency, resolved.repoUrl)
}
private fun displayDependencies(dep: IClasspathDependency, url: String) {
val indent = -1 val indent = -1
val originalDep = MavenDependency.create(id)
val mavenId = MavenId.create(id)
val packaging = if (mavenId.packaging != null) "@" + mavenId.packaging else ""
// We want to display the dependencies of the id we found, not the one we queries
val dep = MavenDependency.create(originalDep.shortId + repoResult.version + packaging)
val root = Node(Dep(dep, indent)) val root = Node(Dep(dep, indent))
val seen = hashSetOf(dep.id) val seen = hashSetOf(id)
root.addChildren(findChildren(root, seen)) root.addChildren(findChildren(root, seen))
kobaltLog(1, AsciiArt.logBox(listOf(dep.id, url, dep.jarFile.get()).map { " $it" })) val simpleDep = SimpleDep(mavenId)
val url = repoResult.hostConfig.url + simpleDep.toJarFile(repoResult)
val localFile = localRepo.toFullPath(simpleDep.toJarFile(repoResult))
AsciiArt.logBox(listOf(id, url, localFile).map { " $it" }, {s -> println(s) })
display(root.children) display(root.children)
kobaltLog(1, "") println("")
} }
private fun display(nodes: List<Node<Dep>>) { private fun display(nodes: List<Node<Dep>>) {
@ -81,12 +54,10 @@ class ResolveDependency @Inject constructor(
else leftMiddle else leftMiddle
val indent = level * increment val indent = level * increment
for(i in 0..indent - 2) { for(i in 0..indent - 2) {
if (!KobaltLogger.isQuiet) { if (i % increment == 0) print(vertical)
if (i == 0 || ((i + 1) % increment == 0)) print(vertical)
else print(" ") else print(" ")
} }
} println(left + " " + dep.id)
kobaltLog(1, left + " " + dep.id + (if (dep.optional) " (optional)" else ""))
display(node.children) display(node.children)
} }
} }
@ -99,18 +70,13 @@ class ResolveDependency @Inject constructor(
if (! seen.contains(it.id)) { if (! seen.contains(it.id)) {
val dep = Dep(it, root.value.level + 1) val dep = Dep(it, root.value.level + 1)
val node = Node(dep) val node = Node(dep)
kobaltLog(2, "Found dependency ${dep.dep.id} level: ${dep.level}") log(2, "Found dependency ${dep.dep.id} level: ${dep.level}")
result.add(node) result.add(node)
seen.add(it.id) seen.add(it.id)
try {
node.addChildren(findChildren(node, seen)) node.addChildren(findChildren(node, seen))
} catch(ex: Exception) {
if (! it.optional) warn("Couldn't resolve " + node)
// else don't warn about missing optional dependencies
} }
} }
} log(2, "Children for ${root.value.dep.id}: ${result.size}")
kobaltLog(2, "Children for ${root.value.dep.id}: ${result.size}")
return result return result
} }
} }

View file

@ -1,17 +1,9 @@
package com.beust.kobalt package com.beust.kobalt
class SystemProperties { public class SystemProperties {
companion object { companion object {
val javaBase : String val javaBase = System.getProperty("java.home") ?:
get() { (System.getenv("JAVA_HOME") ?: throw IllegalArgumentException("JAVA_HOME not defined"))
val jh = System.getenv("JAVA_HOME")
?: System.getProperty("java.home")
?: throw IllegalArgumentException("JAVA_HOME not defined")
val result =
if (jh.toLowerCase().endsWith("jre")) jh.substring(0, jh.length - 4)
else jh
return result
}
val javaVersion = System.getProperty("java.version") val javaVersion = System.getProperty("java.version")
val homeDir = System.getProperty("user.home") val homeDir = System.getProperty("user.home")
val tmpDir = System.getProperty("java.io.tmpdir") val tmpDir = System.getProperty("java.io.tmpdir")

View file

@ -1,8 +1,3 @@
package com.beust.kobalt package com.beust.kobalt
class TestResult(val success: Boolean, val shortMessage: String? = null, val longMessage: String? = null) open public class TaskResult(val success: Boolean = true, val errorMessage: String? = null)
open class TaskResult(val success: Boolean = true,
val testResult: TestResult? = null,
val errorMessage: String? = null
)

View file

@ -1,40 +0,0 @@
package com.beust.kobalt
import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.Directive
class TestConfig(val project: Project, val isDefault : Boolean = false) {
val testArgs = arrayListOf<String>()
val jvmArgs = arrayListOf<String>()
val testIncludes = arrayListOf("**/*Test.class")
val testExcludes = arrayListOf<String>()
@Directive
var name: String = ""
@Directive
fun args(vararg arg: String) {
testArgs.addAll(arg)
}
@Directive
fun jvmArgs(vararg arg: String) {
jvmArgs.addAll(arg)
}
@Directive
fun include(vararg arg: String) {
testIncludes.apply {
clear()
addAll(arg)
}
}
@Directive
fun exclude(vararg arg: String) {
testExcludes.apply {
clear()
addAll(arg)
}
}
}

View file

@ -3,16 +3,39 @@ package com.beust.kobalt
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Directive
class TestConfig(val project: Project) {
val testArgs = arrayListOf<String>()
val jvmArgs = arrayListOf<String>()
val testIncludes = arrayListOf("**/*Test.class")
val testExcludes = arrayListOf<String>()
fun args(vararg arg: String) {
testArgs.addAll(arg)
}
fun jvmArgs(vararg arg: String) {
jvmArgs.addAll(arg)
}
fun includes(vararg arg: String) {
testIncludes.apply {
clear()
addAll(arg)
}
}
fun excludes(vararg arg: String) {
testExcludes.apply {
clear()
addAll(arg)
}
}
}
@Directive @Directive
fun Project.test(init: TestConfig.() -> Unit): TestConfig = let { project -> fun Project.test(init: TestConfig.() -> Unit) = let { project ->
with(testConfigs) { with(testConfigs) {
val tf = TestConfig(project).apply { init() } clear()
if (! map { it.name }.contains(tf.name)) { add(TestConfig(project).apply { init() })
add(tf)
tf
} else {
throw KobaltException("Test configuration \"${tf.name}\" already exists, give it a different "
+ "name with test { name = ... }")
}
} }
} }

View file

@ -2,11 +2,9 @@ package com.beust.kobalt
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.internal.ActorUtils import com.beust.kobalt.internal.ActorUtils
import com.beust.kobalt.internal.ParallelLogger
import com.beust.kobalt.internal.SourceSet
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.log
import java.io.File import java.io.File
import java.util.*
/** /**
* Capture the product flavor and the build type of a build. * Capture the product flavor and the build type of a build.
@ -29,71 +27,53 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
/** /**
* for {internal, release}, return [internalRelease, internal, release] * for {internal, release}, return [internalRelease, internal, release]
*/ */
fun allDirectories(): List<String> { fun allDirectories(project: Project): List<String> {
return arrayListOf<String>().apply { val result = arrayListOf<String>()
add(toCamelcaseDir()) result.add(toCamelcaseDir())
add(productFlavor.name) if (productFlavor != null) result.add(productFlavor.name)
add(buildType.name) if (buildType != null) result.add(buildType.name)
} return result
} }
fun sourceDirectories(project: Project, context: KobaltContext, sourceSet: SourceSet) : List<File> { fun sourceDirectories(project: Project, context: KobaltContext) : List<File> {
val result = arrayListOf<File>() val compilers = ActorUtils.selectAffinityActors(project, context, context.pluginInfo.compilerContributors)
val compilerContributors = ActorUtils.selectAffinityActors(project, context, val sourceSuffixes = compilers.flatMap { it.sourceSuffixes }
context.pluginInfo.compilerContributors) val result = sourceSuffixes.flatMap {
compilerContributors.forEach { sourceDirectories(project, it)
it.compilersFor(project, context).forEach { compiler -> }.toHashSet()
result.addAll(sourceDirectories(project, compiler.sourceDirectory, variantFirst = true, return result.toList()
sourceSet = sourceSet))
}
}
return result.filter { ! KFiles.isResource(it.path) }.toList()
} }
/** /**
* Might be used by plug-ins. * suffix is either "java" (to find source files) or "res" (to find resources)
*/ */
fun resourceDirectories(project: Project, sourceSet: SourceSet = SourceSet.MAIN) private fun sourceDirectories(project: Project, suffix: String) : List<File> {
= sourceDirectories(project, "resources", variantFirst = false, sourceSet = sourceSet)
.filter { KFiles.isResource(it.path) }
/**
* suffix is either "java" (to find source files) or "resources" (to find resources).
* The priority directory is always returned first. For example, if a "pro" product flavor
* is requested, "src/pro/kotlin" will appear in the result before "src/main/kotlin". Later,
* files that have already been seen get skipped, which is how compilation and resources
* receive the correct priority in the final jar.
*/
private fun sourceDirectories(project: Project, suffix: String, variantFirst: Boolean, sourceSet: SourceSet)
: List<File> {
val result = arrayListOf<File>() val result = arrayListOf<File>()
val sourceDirectories = sourceSet.correctSourceSet(project) val sourceDirectories = project.sourceDirectories.map { File(it) }
.filter { File(project.directory, it).exists() }
.map(::File)
if (isDefault) { if (isDefault) {
result.addAll(sourceDirectories) result.addAll(sourceDirectories)
} else { } else {
result.addAll(allDirectories(project).map {
File(KFiles.joinDir("src", it, suffix))
}.filter {
it.exists()
})
// // The ordering of files is: 1) build type 2) product flavor 3) default // // The ordering of files is: 1) build type 2) product flavor 3) default
val kobaltLog = Kobalt.INJECTOR.getInstance(ParallelLogger::class.java)
buildType.let { buildType.let {
val dir = File(KFiles.joinDir("src", it.name, suffix)) val dir = File(KFiles.joinDir("src", it.name, suffix))
kobaltLog.log(project.name, 3, "Adding source for build type ${it.name}: ${dir.path}") log(3, "Adding source for build type ${it.name}: ${dir.path}")
result.add(dir) result.add(dir)
} }
productFlavor.let { productFlavor.let {
val dir = File(KFiles.joinDir("src", it.name, suffix)) val dir = File(KFiles.joinDir("src", it.name, suffix))
kobaltLog.log(project.name, 3, "Adding source for product flavor ${it.name}: ${dir.path}") log(3, "Adding source for product flavor ${it.name}: ${dir.path}")
result.add(dir) result.add(dir)
} }
result.addAll(allDirectories()
.map { File(KFiles.joinDir("src", it, suffix)) }
.filter(File::exists))
// Now that all the variant source directories have been added, add the project's default ones // Now that all the variant source directories have been added, add the project's default ones
result.addAll(sourceDirectories) result.addAll(sourceDirectories)
return result
} }
// Generated directory, if applicable // Generated directory, if applicable
@ -101,11 +81,7 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
result.add(it) result.add(it)
} }
val filteredResult = result.filter { File(project.directory, it.path).exists() } return result
val sortedResult = if (variantFirst) filteredResult
else filteredResult.reversed().toList()
val deduplicatedResult = LinkedHashSet(sortedResult).toList()
return deduplicatedResult
} }
fun archiveName(project: Project, archiveName: String?, suffix: String) : String { fun archiveName(project: Project, archiveName: String?, suffix: String) : String {
@ -113,27 +89,28 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
if (isDefault) { if (isDefault) {
archiveName ?: project.name + "-" + project.version + suffix archiveName ?: project.name + "-" + project.version + suffix
} else { } else {
val base = archiveName?.substring(0, archiveName.length - suffix.length) val base = if (archiveName != null) archiveName.substring(0, archiveName.length - suffix.length)
?: project.name + "-" + project.version else project.name + "-" + project.version
val flavor = if (productFlavor.name.isEmpty()) "" else "-" + productFlavor.name val result: String =
val type = if (buildType.name.isEmpty()) "" else "-" + buildType.name base + "-${productFlavor.name}" + "-${buildType.name}"
val result: String = base + flavor + type + suffix
result result
} }
return result return result
} }
val shortArchiveName = if (isDefault) "" else "-" + productFlavor.name + "-" + buildType.name
var generatedSourceDirectory: File? = null var generatedSourceDirectory: File? = null
private fun findBuildTypeBuildConfig(project: Project, variant: Variant?) : BuildConfig? { private fun findBuildTypeBuildConfig(project: Project, variant: Variant?) : BuildConfig? {
val buildTypeName = variant?.buildType?.name val buildTypeName = variant?.buildType?.name
return project.buildTypes[buildTypeName]?.buildConfig return project.buildTypes.getRaw(buildTypeName)?.buildConfig ?: null
} }
private fun findProductFlavorBuildConfig(project: Project, variant: Variant?) : BuildConfig? { private fun findProductFlavorBuildConfig(project: Project, variant: Variant?) : BuildConfig? {
val buildTypeName = variant?.productFlavor?.name val buildTypeName = variant?.productFlavor?.name
return project.productFlavors[buildTypeName]?.buildConfig return project.productFlavors.getRaw(buildTypeName)?.buildConfig ?: null
} }
/** /**
@ -151,7 +128,7 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
/** /**
* Generate BuildConfig.java if requested. Also look up if any BuildConfig is defined on the current build type, * Generate BuildConfig.java if requested. Also look up if any BuildConfig is defined on the current build type,
* product flavor or main project, and use them to generateAndSave any additional field (in that order to * product flavor or main project, and use them to generate any additional field (in that order to
* respect the priorities). Return the generated file if it was generated, null otherwise. * respect the priorities). Return the generated file if it was generated, null otherwise.
*/ */
fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? { fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? {
@ -160,23 +137,24 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
if (buildConfigs.size > 0) { if (buildConfigs.size > 0) {
val pkg = project.packageName ?: project.group val pkg = project.packageName ?: project.group
?: throw KobaltException( ?: throw KobaltException(
"packageName needs to be defined on the project in order to generateAndSave BuildConfig") "packageName needs to be defined on the project in order to generate BuildConfig")
val contributor = ActorUtils.selectAffinityActor(project, context, val contributor = ActorUtils.selectAffinityActor(context.pluginInfo.buildConfigContributors, project)
context.pluginInfo.buildConfigContributors)
if (contributor != null) { if (contributor != null) {
val code = contributor.generateBuildConfig(project, context, pkg, this, buildConfigs) val code = contributor.generateBuildConfig(project, context, pkg, this, buildConfigs)
val result = KFiles.makeDir(KFiles.generatedSourceDir(project, this, "buildConfig")) val result = KFiles.makeDir(KFiles.generatedSourceDir(project, this, "buildConfig"))
// Make sure the generatedSourceDirectory doesn't contain the project.directory since // Make sure the generatedSourceDirectory doesn't contain the project.directory since
// that directory will be added when trying to find recursively all the sources in it // that directory will be added when trying to find recursively all the sources in it
generatedSourceDirectory = result.relativeTo(File(project.directory)) generatedSourceDirectory = File(result.relativeTo(File(project.directory)))
val outputGeneratedSourceDirectory = File(result, pkg.replace('.', File.separatorChar)) val outputGeneratedSourceDirectory = File(result, pkg.replace('.', File.separatorChar))
val outputDir = File(outputGeneratedSourceDirectory, "BuildConfig." + contributor.buildConfigSuffix) val compilers = ActorUtils.selectAffinityActors(project, context, context.pluginInfo.compilerContributors)
val outputDir = File(outputGeneratedSourceDirectory,
"BuildConfig" + compilers[0].sourceSuffixes[0])
KFiles.saveFile(outputDir, code) KFiles.saveFile(outputDir, code)
context.logger.log(project.name, 2, "Generated ${outputDir.path}") log(2, "Generated ${outputDir.path}")
return result return result
} else { } else {
throw KobaltException("Couldn't find a contributor to generateAndSave BuildConfig") throw KobaltException("Couldn't find a contributor to generate BuildConfig")
} }
} else { } else {
return null return null
@ -185,10 +163,9 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
override fun toString() = toTask("") override fun toString() = toTask("")
companion object { companion object {
val DEFAULT_PRODUCT_FLAVOR = ProductFlavorConfig("") val DEFAULT_PRODUCT_FLAVOR = ProductFlavorConfig("")
val DEFAULT_BUILD_TYPE = BuildTypeConfig("") val DEFAULT_BUILD_TYPE = BuildTypeConfig(null, "")
fun allVariants(project: Project): List<Variant> { fun allVariants(project: Project): List<Variant> {
val result = arrayListOf<Variant>() val result = arrayListOf<Variant>()
@ -221,7 +198,7 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
} }
fun toCamelcaseDir() : String { fun toCamelcaseDir() : String {
fun lci(s : String) = if (s.isEmpty() || s.length == 1) s else s[0].toLowerCase() + s.substring(1) fun lci(s : String) = if (s.length == 0 || s.length == 1) s else s[0].toLowerCase() + s.substring(1)
return lci(productFlavor.name) + buildType.name.capitalize() return lci(productFlavor.name) + buildType.name.capitalize()
} }

View file

@ -3,7 +3,7 @@ package com.beust.kobalt.api
import com.beust.kobalt.Plugins import com.beust.kobalt.Plugins
import com.beust.kobalt.internal.TaskManager import com.beust.kobalt.internal.TaskManager
abstract class BasePlugin : IPlugin { abstract public class BasePlugin : IPlugin {
lateinit var context: KobaltContext lateinit var context: KobaltContext
override fun accept(project: Project) = true override fun accept(project: Project) = true
@ -12,8 +12,6 @@ abstract class BasePlugin : IPlugin {
this.context = context this.context = context
} }
override fun shutdown() {}
override lateinit var taskManager: TaskManager override lateinit var taskManager: TaskManager
lateinit var plugins: Plugins lateinit var plugins: Plugins
} }

View file

@ -1,11 +0,0 @@
package com.beust.kobalt.api
class BuildTypeConfig(val name: String) : IBuildConfig, IDependencyHolder by DependencyHolder() {
var minifyEnabled = false
var applicationIdSuffix: String? = null
var proguardFile: String? = null
override var buildConfig : BuildConfig? = BuildConfig()
}

View file

@ -8,9 +8,7 @@ import java.io.File
data class CompilerActionInfo(val directory: String?, data class CompilerActionInfo(val directory: String?,
val dependencies: List<IClasspathDependency>, val dependencies: List<IClasspathDependency>,
val sourceFiles: List<String>, val sourceFiles: List<String>,
val suffixesBeingCompiled: List<String>,
val outputDir: File, val outputDir: File,
val compilerArgs: List<String>, val compilerArgs: List<String>)
val friendPaths: List<String>,
val forceRecompile: Boolean,
val compilerSeparateProcess: Boolean = false)

View file

@ -1,19 +0,0 @@
package com.beust.kobalt.api
import java.util.*
/**
* Actors that have one config object per project can implement `IConfigActor` by delegating to
* `ConfigActor`. Then they can easily add and look up configurations per project.
*/
interface IConfigActor<T> {
val configurations : HashMap<String, T>
fun configurationFor(project: Project?) = if (project != null) configurations[project.name] else null
fun addConfiguration(project: Project, configuration: T) = configurations.put(project.name, configuration)
}
open class ConfigActor<T>: IConfigActor<T> {
override val configurations : HashMap<String, T> = hashMapOf()
}

View file

@ -0,0 +1,12 @@
package com.beust.kobalt.api
/**
* A plug-in that has some per-project configuration in the build file.
*/
abstract public class ConfigPlugin<T> : BasePlugin() {
private val configurations = hashMapOf<String, T>()
fun configurationFor(project: Project?) = if (project != null) configurations[project.name] else null
fun addConfiguration(project: Project, configuration: T) = configurations.put(project.name, configuration)
}

View file

@ -1,19 +0,0 @@
package com.beust.kobalt.api
import com.google.common.collect.ArrayListMultimap
import com.google.common.collect.ListMultimap
/**
* Actors that have more than config object per project can use this helper class.
*/
interface IConfigsActor<T> {
val configurations : ListMultimap<String, T>
fun configurationFor(project: Project?) = if (project != null) configurations[project.name] else null
fun addConfiguration(project: Project, configuration: T) = configurations.put(project.name, configuration)
}
open class ConfigsActor<T>: IConfigsActor<T> {
override val configurations = ArrayListMultimap.create<String, T>()
}

View file

@ -0,0 +1,14 @@
package com.beust.kobalt.api
import com.google.common.collect.ArrayListMultimap
/**
* A plug-in that has some per-project list of configurations in the build file.
*/
abstract public class ConfigsPlugin<T> : BasePlugin() {
private val configurations = ArrayListMultimap.create<String, T>()
fun configurationFor(project: Project) = configurations[project.name]
fun addConfiguration(project: Project, configuration: T) = configurations.put(project.name, configuration)
}

View file

@ -1,47 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.api.annotation.Directive
import java.util.*
/**
* Various elements in a build file let you specify dependencies: projects, buildType and productFlavor.
* They all implement this interface and delegate to an instance of the `DependencyHolder` concrete class.
*/
interface IDependencyHolder {
var project: Project
val compileDependencies : ArrayList<IClasspathDependency>
val optionalDependencies : ArrayList<IClasspathDependency>
val compileProvidedDependencies : ArrayList<IClasspathDependency>
val compileOnlyDependencies : ArrayList<IClasspathDependency>
val compileRuntimeDependencies : ArrayList<IClasspathDependency>
val excludedDependencies : ArrayList<IClasspathDependency>
val nativeDependencies : ArrayList<IClasspathDependency>
@Directive
var dependencies: Dependencies?
@Directive
fun dependencies(init: Dependencies.() -> Unit) : Dependencies
}
open class DependencyHolder : IDependencyHolder {
override lateinit var project: Project
override val compileDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val optionalDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val compileProvidedDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val compileOnlyDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val compileRuntimeDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val excludedDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val nativeDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override var dependencies : Dependencies? = null
override fun dependencies(init: Dependencies.() -> Unit) : Dependencies {
dependencies = Dependencies(project, compileDependencies, optionalDependencies, compileProvidedDependencies,
compileOnlyDependencies, compileRuntimeDependencies, excludedDependencies, nativeDependencies)
dependencies!!.init()
return dependencies!!
}
}

View file

@ -1,10 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.TaskResult
/**
* Plug-ins that will be invoked during the "assemble" task.
*/
interface IAssemblyContributor : IContributor {
fun assemble(project: Project, context: KobaltContext) : TaskResult
}

View file

@ -5,12 +5,7 @@ import com.beust.kobalt.Variant
/** /**
* Plug-ins that can generate a BuildConfig file. * Plug-ins that can generate a BuildConfig file.
*/ */
interface IBuildConfigContributor : IProjectAffinity { interface IBuildConfigContributor : ISimpleAffinity<Project> {
fun generateBuildConfig(project: Project, context: KobaltContext, packageName: String, variant: Variant, fun generateBuildConfig(project: Project, context: KobaltContext, packageName: String, variant: Variant,
buildConfigs: List<BuildConfig>) : String buildConfigs: List<BuildConfig>) : String
/**
* The suffix of the generated BuildConfig, e.g. ".java".
*/
val buildConfigSuffix: String
} }

View file

@ -5,6 +5,6 @@ class BuildConfigField(val type: String, val name: String, val value: Any)
/** /**
* Plug-ins that want to add fields to BuildConfig need to implement this interface. * Plug-ins that want to add fields to BuildConfig need to implement this interface.
*/ */
interface IBuildConfigFieldContributor : IContributor { interface IBuildConfigFieldContributor {
fun fieldsFor(project: Project, context: KobaltContext) : List<BuildConfigField> fun fieldsFor(project: Project, context: KobaltContext) : List<BuildConfigField>
} }

View file

@ -3,7 +3,7 @@ package com.beust.kobalt.api
/** /**
* Plug-ins can alter the build directory by implementing this interface. * Plug-ins can alter the build directory by implementing this interface.
*/ */
interface IBuildDirectoryInterceptor : IInterceptor { interface IBuildDirectoryIncerceptor : IInterceptor {
fun intercept(project: Project, context: KobaltContext, buildDirectory: String) : String fun intercept(project: Project, context: KobaltContext, buildDirectory: String) : String
} }

View file

@ -1,20 +0,0 @@
package com.beust.kobalt.api
/**
* Plug-ins that listen to build events.
*/
interface IBuildListener : IListener {
class TaskEndInfo(val success: Boolean, val shortMessage: String? = null,
val longMessage: String? = null)
fun taskStart(project: Project, context: KobaltContext, taskName: String) {}
fun taskEnd(project: Project, context: KobaltContext, taskName: String, info: TaskEndInfo) {}
fun projectStart(project: Project, context: KobaltContext) {}
fun projectEnd(project: Project, context: KobaltContext, status: ProjectBuildStatus) {}
}
enum class ProjectBuildStatus {
SUCCESS, FAILED, SKIPPED
}

View file

@ -1,8 +0,0 @@
package com.beust.kobalt.api
/**
* Plug-ins that produce build reports.
*/
interface IBuildReportContributor : IContributor {
fun generateReport(context: KobaltContext)
}

View file

@ -1,10 +1,12 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.api.IClasspathDependency
/** /**
* Plugins that export classpath entries need to implement this interface. * Plugins that export classpath entries need to implement this interface.
*/ */
interface IClasspathContributor : IContributor { interface IClasspathContributor : IContributor {
fun classpathEntriesFor(project: Project?, context: KobaltContext) : Collection<IClasspathDependency> fun entriesFor(project: Project?) : Collection<IClasspathDependency>
} }

View file

@ -8,34 +8,20 @@ import java.util.concurrent.Future
* Encapsulate a dependency that can be put on the classpath. This interface * Encapsulate a dependency that can be put on the classpath. This interface
* has two subclasses: FileDependency, a physical file, and MavenDependency, * has two subclasses: FileDependency, a physical file, and MavenDependency,
* which represents a dependency living in a Maven repo. * which represents a dependency living in a Maven repo.
*
* You can instantiate either of these concrete classes with DependencyManager#createMaven
* and DependencyManager#createFile.
*/ */
interface IClasspathDependency { interface IClasspathDependency {
/** Identifier for this dependency */ /** Identifier for this dependency */
val id: String val id: String
/** Version for this identifier */
val version: String
/** @return true if this dependency represents a Maven coordinate */
val isMaven: Boolean
/** @return true if this dependency is optional */
val optional: Boolean
/** Absolute path to the jar file on the local file system */ /** Absolute path to the jar file on the local file system */
val jarFile: Future<File> val jarFile: Future<File>
/** Convert to a Maven <dependency> model tag */ /** Convert to a Maven <dependency> model tag */
fun toMavenDependencies(scope: String? = null) : Dependency fun toMavenDependencies() : Dependency
/** The list of dependencies for this element (not the transitive closure) */ /** The list of dependencies for this element (not the transitive closure */
fun directDependencies(): List<IClasspathDependency> fun directDependencies(): List<IClasspathDependency>
/** Used to only keep the most recent version for an artifact if no version was specified */ /** Used to only keep the most recent version for an artifact if no version was specified */
val shortId: String val shortId: String
val excluded: ArrayList<Dependencies.ExcludeConfig>
} }

View file

@ -2,67 +2,7 @@ package com.beust.kobalt.api
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
interface ICompilerDescription : Comparable<ICompilerDescription> { interface ICompilerContributor : IProjectAffinity {
/**
* The name of the language compiled by this compiler.
*/
val name: String
/**
* The suffixes handled by this compiler (without the dot, e.g. "java" or "kt").
*/
val sourceSuffixes: List<String> val sourceSuffixes: List<String>
/**
* The trailing end of the source directory (e.g. "kotlin" in "src/main/kotlin")
*/
val sourceDirectory: String
/**
* Run the compilation based on the info.
*/
fun compile(project: Project, context: KobaltContext, info: CompilerActionInfo) : TaskResult
companion object {
val DEFAULT_PRIORITY: Int = 10
}
/**
* The priority of this compiler. Lower priority compilers are run first.
*/
val priority: Int get() = DEFAULT_PRIORITY
override fun compareTo(other: ICompilerDescription) = priority.compareTo(other.priority)
/**
* Can this compiler be passed directories or does it need individual source files?
*/
val canCompileDirectories: Boolean get() = false
}
interface ICompilerContributor : IProjectAffinity, IContributor {
fun compilersFor(project: Project, context: KobaltContext): List<ICompilerDescription>
}
interface ICompiler {
fun compile(project: Project, context: KobaltContext, info: CompilerActionInfo) : TaskResult fun compile(project: Project, context: KobaltContext, info: CompilerActionInfo) : TaskResult
} }
class CompilerDescription(override val name: String, override val sourceDirectory: String,
override val sourceSuffixes: List<String>, val compiler: ICompiler,
override val priority: Int = ICompilerDescription.DEFAULT_PRIORITY,
override val canCompileDirectories: Boolean = false) : ICompilerDescription {
override fun compile(project: Project, context: KobaltContext, info: CompilerActionInfo): TaskResult {
val result =
if (info.sourceFiles.isNotEmpty()) {
compiler.compile(project, context, info)
} else {
context.logger.log(project.name, 2, "$name couldn't find any source files to compile")
TaskResult()
}
return result
}
override fun toString() = name + " compiler"
}

View file

@ -3,27 +3,6 @@ package com.beust.kobalt.api
/** /**
* Plugins that add compiler flags. * Plugins that add compiler flags.
*/ */
class FlagContributor(val flagPriority: Int = DEFAULT_FLAG_PRIORITY, interface ICompilerFlagContributor : IContributor {
val closure: (project: Project, context: KobaltContext, currentFlags: List<String>, fun flagsFor(project: Project, context: KobaltContext, currentFlags: List<String>): List<String>
suffixesBeingCompiled: List<String>) -> List<String>) : IContributor {
companion object {
val DEFAULT_FLAG_PRIORITY = 20
}
fun flagsFor(project: Project, context: KobaltContext, currentFlags: List<String>,
suffixesBeingCompiled: List<String>) = closure(project, context, currentFlags, suffixesBeingCompiled)
}
interface IFlagBase {
val flagPriority: Int get() = FlagContributor.DEFAULT_FLAG_PRIORITY
}
interface ICompilerFlagContributor : IContributor, IFlagBase {
fun compilerFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>,
suffixesBeingCompiled: List<String>): List<String>
}
interface IDocFlagContributor : IContributor, IFlagBase {
fun docFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>,
suffixesBeingCompiled: List<String>): List<String>
} }

View file

@ -1,88 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.maven.aether.Filters.EXCLUDE_OPTIONAL_FILTER
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.kobaltLog
import org.eclipse.aether.graph.DependencyFilter
import org.eclipse.aether.graph.DependencyNode
/**
* Manage the creation of dependencies and also provide dependencies for projects.
*/
interface IDependencyManager {
/**
* Parse the id and return the correct IClasspathDependency
*/
fun create(id: String, optional: Boolean = false, projectDirectory: String? = null): IClasspathDependency
/**
* Create an IClasspathDependency from a Maven id.
*/
fun createMaven(id: String, optional: Boolean = false): IClasspathDependency
/**
* Create an IClasspathDependency from a path.
*/
fun createFile(path: String): IClasspathDependency
/**
* @return the source dependencies for this project, including the contributors.
*/
fun dependencies(project: Project, context: KobaltContext, scopes: List<Scope>): List<IClasspathDependency>
/**
* @return the test dependencies for this project, including the contributors.
*/
fun testDependencies(project: Project, context: KobaltContext): List<IClasspathDependency>
/**
* @return the classpath for this project, including the IClasspathContributors.
* allDependencies is typically either compileDependencies or testDependencies
*/
fun calculateDependencies(project: Project?, context: KobaltContext,
dependencyFilter: DependencyFilter =
createDependencyFilter(project, project?.compileDependencies ?: emptyList()),
scopes: List<Scope> = listOf(Scope.COMPILE),
vararg passedDependencies: List<IClasspathDependency>): List<IClasspathDependency>
/**
* Create an Aether dependency filter that uses the dependency configuration included in each
* IClasspathDependency.
*/
fun createDependencyFilter(project: Project?, dependencies: List<IClasspathDependency>) : DependencyFilter {
return DependencyFilter { p0, p1 ->
fun isNodeExcluded(node: DependencyNode, passedDep: IClasspathDependency) : Boolean {
val dep = create(KobaltMavenResolver.artifactToId(node.artifact))
return passedDep.excluded.any { ex -> ex.isExcluded(dep)}
}
fun isDepExcluded(node: DependencyNode, excluded: List<IClasspathDependency>?) : Boolean {
val dep = create(KobaltMavenResolver.artifactToId(node.artifact))
return excluded?.map { it.id }?.contains(dep.id) ?: false
}
val accept = dependencies.isEmpty() || dependencies.any {
// Is this dependency excluded?
val isExcluded = isNodeExcluded(p0, it) || isDepExcluded(p0, project?.excludedDependencies)
// Is the parent dependency excluded?
val isParentExcluded =
if (p1.any()) {
isNodeExcluded(p1[0], it) || isDepExcluded(p1[0], project?.excludedDependencies)
} else {
false
}
// Only accept if no exclusions were found
! isExcluded && ! isParentExcluded
}
if (! accept) {
kobaltLog(2, "Excluding $p0")
}
if (accept) EXCLUDE_OPTIONAL_FILTER.accept(p0, p1)
else accept
}
}
}

View file

@ -2,7 +2,7 @@ package com.beust.kobalt.api
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
interface IDocContributor : IProjectAffinity, IContributor { interface IDocContributor : IProjectAffinity {
fun generateDoc(project: Project, context: KobaltContext, info: CompilerActionInfo) : TaskResult fun generateDoc(project: Project, context: KobaltContext, info: CompilerActionInfo) : TaskResult
} }

View file

@ -1,12 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.IncrementalTaskInfo
/**
* Plug-ins that will be invoked during the "assemble" task and wish to return an incremental task instead
* of a regular one.
*/
interface IIncrementalAssemblyContributor : IContributor {
fun assemble(project: Project, context: KobaltContext) : IncrementalTaskInfo
}

View file

@ -1,28 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.IncrementalTaskInfo
/**
* Plug-ins that need to add incremental dynamic tasks (tasks that are not methods annotated with @Task) need
* to implement this interface.
*/
interface IIncrementalTaskContributor : IContributor {
fun incrementalTasksFor(project: Project, context: KobaltContext) : List<IncrementalDynamicTask>
}
class IncrementalDynamicTask(val context: KobaltContext,
val plugin: IPlugin,
val name: String,
val doc: String,
val group: String,
val project: Project,
val dependsOn: List<String> = listOf<String>(),
val reverseDependsOn: List<String> = listOf<String>(),
val runBefore: List<String> = listOf<String>(),
val runAfter: List<String> = listOf<String>(),
val alwaysRunAfter: List<String> = listOf<String>(),
val incrementalClosure: (Project) -> IncrementalTaskInfo) {
override fun toString() = "[IncrementalDynamicTask $name dependsOn=$dependsOn reverseDependsOn=$reverseDependsOn]"
}

View file

@ -0,0 +1,15 @@
package com.beust.kobalt.api
import java.io.OutputStream
/**
* Plugins that want to participate in the --init process (they can generate files to initialize
* a new project).
*/
interface IInitContributor<T> : ISimpleAffinity<T> {
/**
* Generate the Build.kt file into the given OutputStream.
*/
fun generateBuildFile(os: OutputStream)
}

View file

@ -1,13 +0,0 @@
package com.beust.kobalt.api
/**
* Plug-ins that add flags to the JVM used to run apps should implement this interface.
*/
interface IJvmFlagContributor : IContributor {
/**
* The list of JVM flags that will be added to the JVM when the app gets run. @param[currentFlags] is only here
* for convenience, in case you need to look at the current JVM flags before adding your own flags.
*/
fun jvmFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>) : List<String>
}

View file

@ -1,8 +0,0 @@
package com.beust.kobalt.api
/**
* Plug-ins that want to override the local maven repo path.
*/
interface ILocalMavenRepoPathInterceptor : IInterceptor {
fun repoPath(currentPath: String) : String
}

View file

@ -2,29 +2,9 @@ package com.beust.kobalt.api
import com.beust.kobalt.internal.TaskManager import com.beust.kobalt.internal.TaskManager
interface IPlugin : IPluginActor { public interface IPlugin : IPluginActor {
/**
* The name of this plug-in.
*/
val name: String val name: String
/**
* @return true if this plug-in decided it should be enabled for this project.
*/
fun accept(project: Project) : Boolean fun accept(project: Project) : Boolean
/**
* Invoked on all plug-ins before the Kobalt execution stops.
*/
fun shutdown()
/**
* Main entry point for a plug-in to initialize itself based on a project and a context.
*/
fun apply(project: Project, context: KobaltContext) {} fun apply(project: Project, context: KobaltContext) {}
/**
* Injected by Kobalt to manage tasks.
*/
var taskManager : TaskManager var taskManager : TaskManager
} }

View file

@ -1,15 +1,7 @@
package com.beust.kobalt.api package com.beust.kobalt.api
interface IPluginActor { interface IPluginActor
/**
* Clean up any state that your actor might have saved so it can be run again.
*/
fun cleanUpActors() {}
}
interface IContributor : IPluginActor interface IContributor : IPluginActor
interface IInterceptor : IPluginActor interface IInterceptor : IPluginActor
interface IListener : IPluginActor

View file

@ -1,11 +1,10 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.IClasspathDependency
/** /**
* Plugins that can run a project (task "run" or "test") should implement this interface. * Plugins that can run a project (task "run" or "test") should implement this interface.
*
* Currently not used.
*/ */
interface IRunnerContributor : IContributor, IProjectAffinity { interface IRunnerContributor : IContributor, IProjectAffinity {
/** /**

View file

@ -8,5 +8,5 @@ interface ISimpleAffinity<T> : IAffinity {
* @return an integer indicating the affinity of your actor. The actor that returns * @return an integer indicating the affinity of your actor. The actor that returns
* the highest affinity gets selected. * the highest affinity gets selected.
*/ */
fun affinity(project: T) : Int fun affinity(arg: T) : Int
} }

View file

@ -5,7 +5,7 @@ import java.io.File
/** /**
* Plug-ins can alter the source directories by implementing this interface. * Plug-ins can alter the source directories by implementing this interface.
*/ */
interface ISourceDirectoryInterceptor : IInterceptor { interface ISourceDirectoryIncerceptor : IInterceptor {
fun intercept(project: Project, context: KobaltContext, sourceDirectories: List<File>) : List<File> fun intercept(project: Project, context: KobaltContext, sourceDirectories: List<File>) : List<File>
} }

View file

@ -5,16 +5,6 @@ import java.io.File
/** /**
* Plug-ins that add source directories to be compiled need to implement this interface. * Plug-ins that add source directories to be compiled need to implement this interface.
*/ */
interface ISourceDirectoryContributor : IContributor { interface ISourceDirectoryContributor {
fun sourceDirectoriesFor(project: Project, context: KobaltContext): List<File> fun sourceDirectoriesFor(project: Project, context: KobaltContext): List<File>
} }
/**
* @return the source directories for this project including source contributors.
*/
fun KobaltContext.sourceDirectories(project: Project) : Set<File> {
val result = pluginInfo.sourceDirContributors.flatMap {
it.sourceDirectoriesFor(project, this)
}
return result.toSet()
}

View file

@ -1,32 +1,17 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
import com.beust.kobalt.internal.TaskResult2
/** /**
* Plug-ins that need to add dynamic tasks (tasks that are not methods annotated with @Task) need * Plug-ins that need to add dynamic tasks (tasks that are not methods annotated with @Task) need
* to implement this interface. * to implement this interface.
*/ */
interface ITaskContributor : IContributor { interface ITaskContributor : IContributor {
fun tasksFor(project: Project, context: KobaltContext) : List<DynamicTask> fun tasksFor(context: KobaltContext) : List<DynamicTask>
} }
class DynamicTask(override val plugin: IPlugin, override val name: String, override val doc: String, class DynamicTask(val plugin: IPlugin, val name: String, val description: String = "",
override val group: String,
override val project: Project,
val dependsOn: List<String> = listOf<String>(),
val reverseDependsOn: List<String> = listOf<String>(),
val runBefore: List<String> = listOf<String>(), val runBefore: List<String> = listOf<String>(),
val runAfter: List<String> = listOf<String>(), val runAfter: List<String> = listOf<String>(),
val alwaysRunAfter: List<String> = listOf<String>(), val alwaysRunAfter: List<String> = listOf<String>(),
val closure: (Project) -> TaskResult) : ITask { val closure: (Project) -> TaskResult)
override fun call(): TaskResult2<ITask> {
val taskResult = closure.invoke(project)
return TaskResult2(taskResult.success, errorMessage = taskResult.errorMessage, value = this)
}
override fun toString() =
"[DynamicTask ${project.name}:$name dependsOn=$dependsOn reverseDependsOn=$reverseDependsOn]"
}

View file

@ -1,45 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.Args
/**
* Plugins that want to participate in the --init process (they can generate files to initialize
* a new project).
*/
interface ITemplateContributor : IContributor {
companion object {
val DIRECTORY_NAME = "templates"
}
val templates: List<ITemplate>
}
interface ITemplate {
/**
* The name of this template. This is the name that will be looked up when passed to the --init
* argument.
*/
val templateName: String
/**
* Description of this template.
*/
val templateDescription: String
/**
* The plug-in this template belongs to.
*/
val pluginName: String
/**
* Instructions to display to the user after a template has been generated.
*/
val instructions : String get() = "Build this project with `./kobaltw assemble`"
/**
* Generate the files for this template. The parameter is the arguments that were passed to the kobaltw
* command.
*/
fun generateTemplate(args: Args, classLoader: ClassLoader)
}

View file

@ -1,12 +0,0 @@
package com.beust.kobalt.api
/**
* Plug-ins that add flags to the JVM used to run tests should implement this interface.
*/
interface ITestJvmFlagContributor : IContributor {
/**
* The list of JVM flags that will be added to the JVM when the tests get run. @param[currentFlags] is only here
* for convenience, in case you need to look at the current JVM flags before adding your own flags.
*/
fun testJvmFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>) : List<String>
}

View file

@ -1,14 +0,0 @@
package com.beust.kobalt.api
/**
* Plug-ins that add flags to the JVM used to run tests should implement this interface.
*/
interface ITestJvmFlagInterceptor : IInterceptor {
/**
* @return the list of all flags that should be used. If you only want to add flags to the current list,
* just return the concatenation of @param[currentFlags] and your own list (or use ITestJvmFlagContributor).
* If you actually alter the list of flags, make sure you don't remove anything critical from @param[currentFlags].
*/
fun testJvmFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>) : List<String>
}

View file

@ -7,9 +7,8 @@ import com.beust.kobalt.TaskResult
*/ */
interface ITestRunnerContributor : IContributor, IProjectAffinity { interface ITestRunnerContributor : IContributor, IProjectAffinity {
/** /**
* Run the tests. If [[configName]] is not empty, a specific test configuration is requested. * Run the project.
*/ */
fun run(project: Project, context: KobaltContext, configName: String, fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>) : TaskResult
classpath: List<IClasspathDependency>) : TaskResult
} }

View file

@ -3,16 +3,9 @@ package com.beust.kobalt.api
import java.io.File import java.io.File
/** /**
* Plug-ins that add test source directories to be compiled need to implement this interface. * Plug-ins that add tets source directories to be compiled need to implement this interface.
*/ */
interface ITestSourceDirectoryContributor : IContributor { interface ITestSourceDirectoryContributor {
fun testSourceDirectoriesFor(project: Project, context: KobaltContext): List<File> fun testSourceDirectoriesFor(project: Project, context: KobaltContext): List<File>
} }
fun KobaltContext.testSourceDirectories(project: Project) : List<File> {
val result = pluginInfo.testSourceDirContributors.flatMap {
it.testSourceDirectoriesFor(project, this)
}
return result
}

View file

@ -1,55 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.Args
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.kobaltLog
import java.io.*
import java.net.URL
import java.util.jar.JarInputStream
/**
* Base class for templates that decompress a jar file.
*/
interface InputStreamJarTemplate : ITemplate {
val inputStream: InputStream
override fun generateTemplate(args: Args, classLoader: ClassLoader) {
val destDir = File(".")
JarInputStream(inputStream).use { ins ->
var entry = ins.nextEntry
while (entry != null) {
val f = File(destDir.path + File.separator + entry.name)
if (entry.isDirectory) {
f.mkdir()
entry = ins.nextEntry
continue
}
kobaltLog(2, " Extracting: $entry to ${f.absolutePath}")
FileOutputStream(f).use { fos ->
KFiles.copy(ins, fos)
}
entry = ins.nextEntry
}
}
}
}
abstract class ResourceJarTemplate(jarName: String, val classLoader: ClassLoader) : InputStreamJarTemplate {
override val inputStream : InputStream = classLoader.getResource(jarName).openConnection().inputStream
}
abstract class FileJarTemplate(val fileName: String) : InputStreamJarTemplate {
override val inputStream = FileInputStream(File(fileName))
}
abstract class HttpJarTemplate(val url: String) : InputStreamJarTemplate {
override val inputStream : InputStream
get() {
try {
return URL(url).openConnection().inputStream
} catch(ex: IOException) {
throw IllegalArgumentException("Couldn't connect to $url")
}
}
}

View file

@ -1,15 +1,20 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DepFactory
import com.beust.kobalt.misc.KobaltExecutors
import java.io.File import java.io.File
import java.util.concurrent.Future import java.util.concurrent.Future
class JarFinder { public class JarFinder {
companion object { companion object {
/** /**
* @return a Future for the jar file corresponding to this id. * @return a Future for the jar file corresponding to this id.
*/ */
fun byIdFuture(id: String) : Future<File> = DependencyManager.create(id).jarFile fun byIdFuture(id: String) : Future<File> {
val executor = Kobalt.INJECTOR.getInstance(KobaltExecutors::class.java).miscExecutor
val depFactory = Kobalt.INJECTOR.getInstance(DepFactory::class.java)
return depFactory.create(id, executor).jarFile
}
/** /**
* @return the jar file corresponding to this id. This might cause a network call. * @return the jar file corresponding to this id. This might cause a network call.

View file

@ -3,78 +3,38 @@ package com.beust.kobalt.api
import com.beust.kobalt.Constants import com.beust.kobalt.Constants
import com.beust.kobalt.HostConfig import com.beust.kobalt.HostConfig
import com.beust.kobalt.Plugins import com.beust.kobalt.Plugins
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.google.inject.Guice
import com.google.inject.Injector import com.google.inject.Injector
import com.google.inject.Module
import java.io.InputStream import java.io.InputStream
import java.time.Duration import java.time.Duration
import java.util.* import java.util.*
class Kobalt { public class Kobalt {
companion object { companion object {
// This injector will eventually be replaced with a different injector initialized with the
// correct arguments (or with a TestModule) but it's necessary to give it a default value
// here so the kobalt-plugin.xml file can be read since this is done very early
lateinit var INJECTOR : Injector lateinit var INJECTOR : Injector
fun init(module: Module) {
Kobalt.INJECTOR = Guice.createInjector(module)
//
// Add all the plugins read in kobalt-plugin.xml to the Plugins singleton, so that code
// in the build file that calls Plugins.findPlugin() can find them (code in the
// build file do not have access to the KobaltContext).
//
val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java)
pluginInfo.plugins.forEach { Plugins.addPluginInstance(it) }
}
var context: KobaltContext? = null var context: KobaltContext? = null
/** /**
* @return the repos calculated from various places where repos can be specified. * @return the repos from the build files and from the contributors.
*/ */
val repos : Set<HostConfig> val repos : Set<HostConfig>
get() { get() {
val settingsRepos = Kobalt.context?.settings?.defaultRepos?.map { HostConfig(it) } ?: emptyList() val result = HashSet(reposFromBuildFiles)
// Repos from <default-repos> in the settings
val result = ArrayList(
(if (settingsRepos.isEmpty()) Constants.DEFAULT_REPOS
else settingsRepos)
)
// Repo from <kobalt-compiler-repo> in the settings
Kobalt.context?.settings?.kobaltCompilerRepo?.let {
result.add(HostConfig(it))
}
// Repos from the repo contributors
Kobalt.context?.pluginInfo?.repoContributors?.forEach { Kobalt.context?.pluginInfo?.repoContributors?.forEach {
result.addAll(it.reposFor(null)) result.addAll(it.reposFor(null))
} }
return result
// Repos from the build file
result.addAll(reposFromBuildFiles)
result.forEach {
KobaltMavenResolver.initAuthentication(it)
}
return result.toHashSet()
} }
val reposFromBuildFiles = hashSetOf<HostConfig>() val reposFromBuildFiles = HashSet<HostConfig>(Constants.DEFAULT_REPOS.map { HostConfig(it) })
fun addRepo(repo: HostConfig) = reposFromBuildFiles.add( fun addRepo(repo: HostConfig) = reposFromBuildFiles.add(
if (repo.url.endsWith("/")) repo if (repo.url.endsWith("/")) repo
else repo.copy(url = (repo.url + "/"))) else repo.copy(url = (repo.url + "/")))
val buildFileClasspath = arrayListOf<IClasspathDependency>()
fun addBuildFileClasspath(dep: String) {
val dependencyManager = Kobalt.INJECTOR.getInstance(DependencyManager::class.java)
buildFileClasspath.add(dependencyManager.create(dep))
}
private val KOBALT_PROPERTIES = "kobalt.properties" private val KOBALT_PROPERTIES = "kobalt.properties"
private val PROPERTY_KOBALT_VERSION = "kobalt.version" private val PROPERTY_KOBALT_VERSION = "kobalt.version"
private val PROPERTY_KOBALT_VERSION_CHECK_TIMEOUT = "kobalt.version.checkTimeout" // ISO-8601 private val PROPERTY_KOBALT_VERSION_CHECK_TIMEOUT = "kobalt.version.checkTimeout" // ISO-8601
@ -114,28 +74,10 @@ class Kobalt {
properties.forEach { es -> System.setProperty(es.key.toString(), es.value.toString()) } properties.forEach { es -> System.setProperty(es.key.toString(), es.value.toString()) }
} }
val version: String val version = kobaltProperties.getProperty(PROPERTY_KOBALT_VERSION)
get() = kobaltProperties.getProperty(PROPERTY_KOBALT_VERSION) val versionCheckTimeout = Duration.parse(
kobaltProperties.getProperty(PROPERTY_KOBALT_VERSION_CHECK_TIMEOUT) ?: "P1D")
// Note: Duration is Java 8 only, might need an alternative if we want to support Java < 8
val versionCheckTimeout: Duration
get() = Duration.parse( kobaltProperties.getProperty(PROPERTY_KOBALT_VERSION_CHECK_TIMEOUT) ?: "P1D")
fun findPlugin(name: String) = Plugins.findPlugin(name) fun findPlugin(name: String) = Plugins.findPlugin(name)
val optionsFromBuild = arrayListOf<String>()
fun addKobaltOptions(options: Array<out String>) {
optionsFromBuild.addAll(options)
}
val buildSourceDirs = arrayListOf<String>()
fun addBuildSourceDirs(dirs: Array<out String>) {
buildSourceDirs.addAll(dirs)
}
fun cleanUp() {
buildSourceDirs.clear()
buildFileClasspath.clear()
}
} }
} }

View file

@ -1,77 +1,25 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.Args import com.beust.kobalt.Args
import com.beust.kobalt.KobaltException
import com.beust.kobalt.Plugins import com.beust.kobalt.Plugins
import com.beust.kobalt.Variant import com.beust.kobalt.Variant
import com.beust.kobalt.internal.ILogger
import com.beust.kobalt.internal.IncrementalManager
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.MavenId
import com.beust.kobalt.maven.PomGenerator
import com.beust.kobalt.maven.SimpleDep
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.KobaltExecutors
import java.io.File
class KobaltContext(val args: Args) { public class KobaltContext(val args: Args) {
lateinit var variant: Variant var variant: Variant = Variant()
val profiles = arrayListOf<String>() val profiles = arrayListOf<String>()
init { init {
args.profiles?.split(',')?.filterNotNull()?.forEach { args.profiles?.split(",")?.filterNotNull()?.forEach {
profiles.add(it) profiles.add(it)
} }
} }
fun findPlugin(name: String) = Plugins.findPlugin(name) fun findPlugin(name: String) = Plugins.findPlugin(name)
/**
* Files that can be resolved in the local cache.
*/
enum class FileType { JAR, POM, SOURCES, JAVADOC, OTHER }
/**
* @param{id} is the Maven coordinate (e.g. "org.testng:testng:6.9.11"). If you are looking for a file
* that is not described by the enum (e.g. "aar"), use OTHER and make sure your @param{id} contains
* the fully qualified id (e.g. "com.example:example::aar:1.0").
*/
fun fileFor(id: String, fileType: FileType) : File {
val dep = SimpleDep(MavenId.create(id))
fun toQualifier(dep: SimpleDep, ext: String, qualifier: String?) =
dep.groupId + ":" + dep.artifactId +
":$ext" +
(if (qualifier != null) ":$qualifier" else "") +
":" + dep.version
val fullId =
when (fileType) {
FileType.JAR -> toQualifier(dep, "jar", null)
FileType.POM -> toQualifier(dep, "pom", null)
FileType.SOURCES -> toQualifier(dep, "", "sources")
FileType.JAVADOC -> toQualifier(dep, "", "javadoc")
FileType.OTHER -> id
}
val resolved = resolver.resolveToArtifact(fullId)
if (resolved != null) {
return resolved.file
} else {
throw KobaltException("Couldn't resolve $id")
}
}
/**
* @return the content of the pom.xml for the given project.
*/
fun generatePom(project: Project) = pomGeneratorFactory.create(project).generate()
/** All the projects that are being built during this run */
val allProjects = arrayListOf<Project>()
/** For internal use only */
val internalContext = InternalContext()
// //
// Injected // Injected
// //
@ -80,37 +28,5 @@ class KobaltContext(val args: Args) {
lateinit var dependencyManager: DependencyManager lateinit var dependencyManager: DependencyManager
lateinit var executors: KobaltExecutors lateinit var executors: KobaltExecutors
lateinit var settings: KobaltSettings lateinit var settings: KobaltSettings
lateinit var incrementalManager: IncrementalManager
lateinit var resolver: KobaltMavenResolver
lateinit var pomGeneratorFactory: PomGenerator.IFactory
lateinit var logger: ILogger
} }
class InternalContext {
/**
* When an incremental task decides it's up to date, it sets this boolean to true so that subsequent
* tasks in that project can be skipped as well. This is an internal field that should only be set by Kobalt.
*/
private val incrementalSuccesses = hashSetOf<String>()
fun previousTaskWasIncrementalSuccess(projectName: String) = incrementalSuccesses.contains(projectName) ?: false
fun setIncrementalSuccess(projectName: String) = incrementalSuccesses.add(projectName)
/**
* Keep track of whether the build file was modified. If this boolean is true, incremental compilation
* will be disabled.
*/
var buildFileOutOfDate: Boolean = false
/**
* The absolute directory of the current project.
*/
var absoluteDir: File? = null
/**
* If true, will force a recompile of the files even if using the incremental compile
*/
var forceRecompile: Boolean = false
var noIncrementalKotlin: Boolean = false
}

View file

@ -1,20 +1,16 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.internal.TaskResult2 import com.beust.kobalt.internal.TaskResult2
import com.beust.kobalt.misc.toString
import java.util.concurrent.Callable import java.util.concurrent.Callable
interface ITask : Callable<TaskResult2<ITask>> { abstract public class PluginTask : Callable<TaskResult2<PluginTask>> {
val plugin: IPlugin abstract val plugin: IPlugin
val project: Project open val name: String = ""
val name: String open val doc: String = ""
val doc: String abstract val project: Project
val group: String
}
abstract class PluginTask : ITask { override public fun toString() : String {
override val name: String = "" return toString("PluginTask", "plugin", plugin.name, "id", project.name + ":" + name)
override open val doc: String = "" }
override open val group: String = "other"
override fun toString() = project.name + ":" + name
} }

View file

@ -1,9 +0,0 @@
package com.beust.kobalt.api
class ProductFlavorConfig(val name: String) : IBuildConfig,
IDependencyHolder by DependencyHolder() {
var applicationId: String? = null
override var buildConfig : BuildConfig? = BuildConfig()
}

View file

@ -2,47 +2,55 @@ package com.beust.kobalt.api
import com.beust.kobalt.TestConfig import com.beust.kobalt.TestConfig
import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.dependency.MavenDependency
import com.beust.kobalt.maven.aether.AetherDependency
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.kobaltLog
import org.apache.maven.model.Model
import java.io.File import java.io.File
import java.util.* import java.util.*
import java.util.concurrent.Future
import java.util.concurrent.FutureTask
import java.util.regex.Pattern
open class Project( open class Project(
@Directive open var name: String = "", @Directive open var name: String,
@Directive open var version: String? = null, @Directive open var version: String? = null,
@Directive open var directory: String = ".", @Directive open var directory: String = ".",
@Directive open var buildDirectory: String = KFiles.KOBALT_BUILD_DIR, @Directive open var buildDirectory: String = KFiles.KOBALT_BUILD_DIR,
@Directive open var group: String? = null, @Directive open var group: String? = null,
@Directive open var artifactId: String? = null, @Directive open var artifactId: String? = null,
@Directive open var packaging: String? = null, @Directive open var packaging: String? = null,
@Directive open var dependencies: Dependencies? = null,
@Directive open var description : String = "", @Directive open var description : String = "",
@Directive open var scm : Scm? = null,
@Directive open var url: String? = null, @Directive open var url: String? = null,
@Directive open var pom: Model? = null, @Directive open var licenses: List<License> = arrayListOf<License>(),
@Directive open var dependsOn: ArrayList<Project> = arrayListOf<Project>(), @Directive open var packageName: String? = group) : IBuildConfig {
@Directive open var testsDependOn: ArrayList<Project> = arrayListOf<Project>(),
@Directive open var packageName: String? = group)
: IBuildConfig, IDependencyHolder by DependencyHolder() {
init {
this.project = this
}
fun allProjectDependedOn() = project.dependsOn + project.testsDependOn
class ProjectExtra(project: Project) { class ProjectExtra(project: Project) {
val suffixesFound : Set<String> by lazy {
val sf = hashSetOf<String>()
Kobalt.context?.let {
project.sourceDirectories.forEach { source ->
val sourceDir = File(KFiles.joinDir(project.directory, source))
KFiles.findRecursively(sourceDir, { file ->
val ind = file.lastIndexOf(".")
if (ind >= 0) {
sf.add(file.substring(ind + 1))
}
false
})
}
}
sf
}
val dependsOn = arrayListOf<Project>()
var isDirty = false var isDirty = false
/** /**
* @return true if any of the projects we depend on is dirty. * @return true if any of the projects we depend on is dirty.
*/ */
fun dependsOnDirtyProjects(project: Project) = project.allProjectDependedOn().any { it.projectExtra.isDirty } fun dependsOnDirtyProjects(project: Project) = project.projectExtra.dependsOn.any { it.projectExtra.isDirty }
init {
}
} }
/** /**
@ -51,19 +59,23 @@ open class Project(
*/ */
val projectExtra = ProjectExtra(this) val projectExtra = ProjectExtra(this)
val testConfigs = arrayListOf<TestConfig>() val testConfigs = arrayListOf(TestConfig(this))
// If one is specified by default, we only generateAndSave a BuildConfig, find a way to fix that
override var buildConfig : BuildConfig? = null //BuildConfig() override var buildConfig : BuildConfig? = null //BuildConfig()
val projectProperties = ProjectProperties() val projectProperties = ProjectProperties()
override fun equals(other: Any?) = name == (other as Project).name override fun equals(other: Any?): Boolean {
override fun hashCode() = name.hashCode() return name == (other as Project).name
}
override fun hashCode(): Int {
return name.hashCode()
}
companion object { companion object {
val DEFAULT_SOURCE_DIRECTORIES = setOf("src/main/java", "src/main/kotlin", "src/main/resources") val DEFAULT_SOURCE_DIRECTORIES = hashSetOf("src/main/java", "src/main/kotlin", "src/main/resources")
val DEFAULT_SOURCE_DIRECTORIES_TEST = setOf("src/test/java", "src/test/kotlin", "src/test/resources") val DEFAULT_SOURCE_DIRECTORIES_TEST = hashSetOf("src/test/java", "src/test/kotlin")
} }
// //
@ -75,24 +87,47 @@ open class Project(
return Sources(this, sourceDirectories).apply { init() } return Sources(this, sourceDirectories).apply { init() }
} }
var sourceDirectories = hashSetOf<String>().apply { addAll(DEFAULT_SOURCE_DIRECTORIES)} private fun existing(dirs: Set<String>) = dirs.filter { File(directory, it).exists() }.toHashSet()
var sourceDirectories = hashSetOf<String>()
get() = existing(if (field.isEmpty()) DEFAULT_SOURCE_DIRECTORIES else field)
set(value) { field = value }
@Directive @Directive
fun sourceDirectoriesTest(init: Sources.() -> Unit) : Sources { fun sourceDirectoriesTest(init: Sources.() -> Unit) : Sources {
return Sources(this, sourceDirectoriesTest).apply { init() } return Sources(this, sourceDirectoriesTest).apply { init() }
} }
var sourceDirectoriesTest = hashSetOf<String>().apply { addAll(DEFAULT_SOURCE_DIRECTORIES_TEST)} var sourceDirectoriesTest = hashSetOf<String>()
get() = existing(if (field.isEmpty()) DEFAULT_SOURCE_DIRECTORIES_TEST else field)
set(value) { field = value }
init {
sourceDirectories = hashSetOf()
sourceDirectoriesTest = hashSetOf()
}
// //
// Dependencies // Dependencies
// //
@Directive
fun dependencies(init: Dependencies.() -> Unit) : Dependencies {
dependencies = Dependencies(this, compileDependencies, compileProvidedDependencies, compileRuntimeDependencies,
excludedDependencies)
dependencies!!.init()
return dependencies!!
}
val compileDependencies : ArrayList<IClasspathDependency> = arrayListOf()
val compileProvidedDependencies : ArrayList<IClasspathDependency> = arrayListOf()
val compileRuntimeDependencies : ArrayList<IClasspathDependency> = arrayListOf()
val excludedDependencies : ArrayList<IClasspathDependency> = arrayListOf()
@Directive @Directive
fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies { fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies {
dependencies = Dependencies(this, testDependencies, arrayListOf(), dependencies = Dependencies(this, testDependencies, testProvidedDependencies, compileRuntimeDependencies,
testProvidedDependencies, compileOnlyDependencies, compileRuntimeDependencies, excludedDependencies)
excludedDependencies, nativeDependencies)
dependencies!!.init() dependencies!!.init()
return dependencies!! return dependencies!!
} }
@ -100,9 +135,6 @@ open class Project(
val testDependencies : ArrayList<IClasspathDependency> = arrayListOf() val testDependencies : ArrayList<IClasspathDependency> = arrayListOf()
val testProvidedDependencies : ArrayList<IClasspathDependency> = arrayListOf() val testProvidedDependencies : ArrayList<IClasspathDependency> = arrayListOf()
fun testsDependOn(vararg projects: Project) = testsDependOn.addAll(projects)
fun dependsOn(vararg projects: Project) = dependsOn.addAll(projects)
/** Used to disambiguate various name properties */ /** Used to disambiguate various name properties */
@Directive @Directive
val projectName: String get() = name val projectName: String get() = name
@ -113,8 +145,6 @@ open class Project(
productFlavors.put(name, pf) productFlavors.put(name, pf)
} }
var defaultConfig : BuildConfig? = null
val buildTypes = hashMapOf<String, BuildTypeConfig>() val buildTypes = hashMapOf<String, BuildTypeConfig>()
fun addBuildType(name: String, bt: BuildTypeConfig) { fun addBuildType(name: String, bt: BuildTypeConfig) {
@ -128,20 +158,6 @@ open class Project(
}) })
return result return result
} }
class Dep(val file: File, val id: String)
/**
* @return a list of the transitive dependencies (absolute paths to jar files) for the given dependencies.
* Can be used for example as `collect(compileDependencies)`.
*/
@Directive
fun collect(dependencies: List<IClasspathDependency>) : List<Dep> {
return (Kobalt.context?.dependencyManager?.transitiveClosure(dependencies) ?: emptyList())
.map { Dep(it.jarFile.get(), it.id) }
}
override fun toString() = "[Project $name]"
} }
class Sources(val project: Project, val sources: HashSet<String>) { class Sources(val project: Project, val sources: HashSet<String>) {
@ -151,130 +167,49 @@ class Sources(val project: Project, val sources: HashSet<String>) {
} }
} }
class Dependencies(val project: Project, class Dependencies(val project: Project, val dependencies: ArrayList<IClasspathDependency>,
val dependencies: ArrayList<IClasspathDependency>,
val optionalDependencies: ArrayList<IClasspathDependency>,
val providedDependencies: ArrayList<IClasspathDependency>, val providedDependencies: ArrayList<IClasspathDependency>,
val compileOnlyDependencies: ArrayList<IClasspathDependency>,
val runtimeDependencies: ArrayList<IClasspathDependency>, val runtimeDependencies: ArrayList<IClasspathDependency>,
val excludedDependencies: ArrayList<IClasspathDependency>, val excludedDependencies: ArrayList<IClasspathDependency>) {
val nativeDependencies: ArrayList<IClasspathDependency>) {
/** /**
* Add the dependencies to the given ArrayList and return a list of future jar files corresponding to * Add the dependencies to the given ArrayList and return a list of jar files corresponding to
* these dependencies. Futures are necessary here since this code is invoked from the build file and * these dependencies.
* we might not have set up the extra IRepositoryContributors just yet. By the time these
* future tasks receive a get(), the repos will be correct.
*/ */
private fun addToDependencies(project: Project, dependencies: ArrayList<IClasspathDependency>, private fun addToDependencies(dependencies: ArrayList<IClasspathDependency>, dep: Array<out String>)
dep: Array<out String>, optional: Boolean = false, excludeConfig: ExcludeConfig? = null): List<Future<File>> : List<File>
= with(dep.map { = with(dep.map { MavenDependency.create(it)}) {
val resolved =
if (KobaltMavenResolver.isRangeVersion(it)) {
// Range id
val node = Kobalt.INJECTOR.getInstance(KobaltMavenResolver::class.java).resolveToArtifact(it)
val result = KobaltMavenResolver.artifactToId(node)
kobaltLog(2, "Resolved range id $it to $result")
result
} else {
it
}
DependencyManager.create(resolved, optional, project.directory)
}) {
dependencies.addAll(this) dependencies.addAll(this)
if (excludeConfig != null) { this.map { it.jarFile.get() }
this.forEach { it.excluded.add(excludeConfig) }
}
this.map { FutureTask { it.jarFile.get() } }
} }
@Directive @Directive
fun compile(vararg dep: String) = addToDependencies(project, dependencies, dep) fun compile(vararg dep: String) = addToDependencies(dependencies, dep)
class ExcludeConfig {
val ids = arrayListOf<String>()
@Directive @Directive
fun exclude(vararg passedIds: String) = ids.addAll(passedIds) fun provided(vararg dep: String) = addToDependencies(providedDependencies, dep)
class ArtifactConfig(
var groupId: String? = null,
var artifactId: String? = null,
var version: String? = null
)
val artifacts = arrayListOf<ArtifactConfig>()
@Directive @Directive
fun exclude(groupId: String? = null, artifactId: String? = null, version: String? = null) fun runtime(vararg dep: String) = addToDependencies(runtimeDependencies, dep)
= artifacts.add(ArtifactConfig(groupId, artifactId, version))
fun match(pattern: String?, id: String) : Boolean { @Directive
return pattern == null || Pattern.compile(pattern).matcher(id).matches() fun exclude(vararg dep: String) = addToDependencies(excludedDependencies, dep)
} }
/** class Scm(val connection: String, val developerConnection: String, val url: String)
* @return true if the dependency is excluded with any of the exclude() directives. The matches
* are performed by a regular expression match against the dependency.
*/
fun isExcluded(dep: IClasspathDependency) : Boolean {
// Straight id match
var result = ids.any { match(it, dep.id) }
// Match on any combination of (groupId, artifactId, version)
if (! result && dep.isMaven) {
val mavenDep = dep as AetherDependency
val artifact = mavenDep.artifact
result = artifacts.any {
val match1 = it.groupId == null || match(it.groupId, artifact.groupId)
val match2 = it.artifactId == null || match(it.artifactId, artifact.artifactId)
val match3 = it.version == null || match(it.version, artifact.version)
match1 && match2 && match3
}
}
class License(val name: String, val url: String) {
fun toMavenLicense() : org.apache.maven.model.License {
val result = org.apache.maven.model.License()
result.name = name
result.url = url
return result return result
} }
}
@Directive
fun compile(dep: String, init: ExcludeConfig.() -> Unit) {
val excludeConfig = ExcludeConfig().apply {
init()
}
addToDependencies(project, dependencies, arrayOf(dep), excludeConfig = excludeConfig)
}
@Directive
fun compileOnly(vararg dep: String) = addToDependencies(project, compileOnlyDependencies, dep)
@Directive
fun compileOptional(vararg dep: String) {
addToDependencies(project, optionalDependencies, dep, optional = true)
addToDependencies(project, dependencies, dep, optional = true)
}
@Directive
fun provided(vararg dep: String) {
addToDependencies(project, providedDependencies, dep)
}
@Directive
fun runtime(vararg dep: String) = addToDependencies(project, runtimeDependencies, dep)
@Directive
fun exclude(vararg dep: String) = addToDependencies(project, excludedDependencies, dep)
@Directive
fun native(vararg dep: String) = addToDependencies(project, nativeDependencies, dep)
} }
class BuildConfig { class BuildConfig {
class Field(val name: String, val type: String, val value: Any) { class Field(val name: String, val type: String, val value: Any)
override fun hashCode() = name.hashCode()
override fun equals(other: Any?) = (other as Field).name == name
}
val fields = arrayListOf<Field>() val fields = arrayListOf<Field>()
@ -293,22 +228,32 @@ interface IBuildConfig {
} }
} }
fun Project.defaultConfig(init: BuildConfig.() -> Unit) = let { project -> class ProductFlavorConfig(val name: String) : IBuildConfig {
BuildConfig().apply { var applicationId: String? = null
init() override var buildConfig : BuildConfig? = BuildConfig()
project.defaultConfig = this
} }
}
@Directive
fun Project.buildType(name: String, init: BuildTypeConfig.() -> Unit) = BuildTypeConfig(name).apply {
init()
addBuildType(name, this)
}
@Directive @Directive
fun Project.productFlavor(name: String, init: ProductFlavorConfig.() -> Unit) = ProductFlavorConfig(name).apply { fun Project.productFlavor(name: String, init: ProductFlavorConfig.() -> Unit) = ProductFlavorConfig(name).apply {
init() init()
addProductFlavor(name, this) addProductFlavor(name, this)
} }
class BuildTypeConfig(val project: Project?, val name: String) : IBuildConfig {
var minifyEnabled = false
var applicationIdSuffix: String? = null
var proguardFile: String? = null
// fun getDefaultProguardFile(name: String) : String {
// val androidPlugin = Plugins.findPlugin(AndroidPlugin.PLUGIN_NAME) as AndroidPlugin
// return Proguard(androidPlugin.androidHome(project)).getDefaultProguardFile(name)
// }
override var buildConfig : BuildConfig? = BuildConfig()
}
@Directive
fun Project.buildType(name: String, init: BuildTypeConfig.() -> Unit) = BuildTypeConfig(this, name).apply {
init()
addBuildType(name, this)
}

View file

@ -2,6 +2,8 @@ package com.beust.kobalt.api
import com.beust.kobalt.misc.toString import com.beust.kobalt.misc.toString
data class Task(val pluginName: String, val taskName: String) { data public class Task(val pluginName: String, val taskName: String) {
override fun toString() = toString("Task", pluginName, taskName) override public fun toString() : String {
return toString("Task", pluginName, taskName)
}
} }

View file

@ -3,7 +3,6 @@ package com.beust.kobalt.api
import com.beust.kobalt.IncrementalTaskInfo import com.beust.kobalt.IncrementalTaskInfo
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
import com.beust.kobalt.Variant import com.beust.kobalt.Variant
import com.beust.kobalt.api.annotation.AnnotationDefault
import com.beust.kobalt.internal.IncrementalManager import com.beust.kobalt.internal.IncrementalManager
import com.google.inject.Inject import com.google.inject.Inject
@ -11,8 +10,7 @@ import com.google.inject.Inject
* Plug-ins that are ITaskContributor can use this class to manage their collection of tasks and * Plug-ins that are ITaskContributor can use this class to manage their collection of tasks and
* implement the interface by delegating to an instance of this class (if injection permits). * implement the interface by delegating to an instance of this class (if injection permits).
*/ */
class TaskContributor @Inject constructor(val incrementalManagerFactory: IncrementalManager.IFactory) class TaskContributor @Inject constructor(val incrementalManager: IncrementalManager) : ITaskContributor {
: ITaskContributor {
val dynamicTasks = arrayListOf<DynamicTask>() val dynamicTasks = arrayListOf<DynamicTask>()
/** /**
@ -24,63 +22,37 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme
* depends on variants of that task. * depends on variants of that task.
*/ */
fun addVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String, fun addVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String,
group: String = AnnotationDefault.GROUP,
dependsOn: List<String> = emptyList(),
reverseDependsOn : List<String> = emptyList(),
runBefore : List<String> = emptyList(),
runAfter : List<String> = emptyList(),
runTask: (Project) -> TaskResult) {
Variant.allVariants(project).forEach { variant ->
val variantTaskName = variant.toTask(taskName)
dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, group, project,
dependsOn = dependsOn.map { variant.toTask(it) },
reverseDependsOn = reverseDependsOn.map { variant.toTask(it) },
runBefore = runBefore.map { variant.toTask(it) },
runAfter = runAfter.map { variant.toTask(it) },
closure = { p: Project ->
context.variant = variant
runTask(project)
}))
}
}
fun addTask(plugin: IPlugin, project: Project, taskName: String, description: String,
group: String = AnnotationDefault.GROUP,
dependsOn: List<String> = emptyList(),
reverseDependsOn : List<String> = emptyList(),
runBefore : List<String> = emptyList(), runBefore : List<String> = emptyList(),
runAfter : List<String> = emptyList(), runAfter : List<String> = emptyList(),
alwaysRunAfter : List<String> = emptyList(), alwaysRunAfter : List<String> = emptyList(),
runTask: (Project) -> TaskResult) { runTask: (Project) -> TaskResult) {
dynamicTasks.add(DynamicTask(plugin, taskName, description, group, project, Variant.allVariants(project).forEach { variant ->
dependsOn = dependsOn, val variantTaskName = variant.toTask(taskName)
reverseDependsOn = reverseDependsOn, dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName,
runBefore = runBefore, runBefore = runBefore.map { variant.toTask(it) },
runAfter = runAfter, runAfter = runAfter.map { variant.toTask(it) },
alwaysRunAfter = alwaysRunAfter, alwaysRunAfter = alwaysRunAfter.map { variant.toTask(it) },
closure = { p: Project -> closure = { p: Project ->
context.variant = variant
runTask(project) runTask(project)
})) }))
} }
}
fun addIncrementalVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String, fun addIncrementalVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String,
group: String = AnnotationDefault.GROUP,
dependsOn: List<String> = emptyList(),
reverseDependsOn : List<String> = emptyList(),
runBefore : List<String> = emptyList(), runBefore : List<String> = emptyList(),
runAfter : List<String> = emptyList(), runAfter : List<String> = emptyList(),
alwaysRunAfter : List<String> = emptyList(),
runTask: (Project) -> IncrementalTaskInfo) { runTask: (Project) -> IncrementalTaskInfo) {
Variant.allVariants(project).forEach { variant -> Variant.allVariants(project).forEach { variant ->
val variantTaskName = variant.toTask(taskName) val variantTaskName = variant.toTask(taskName)
context.variant = variant dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName,
dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, group, project,
dependsOn = dependsOn.map { variant.toTask(it) },
reverseDependsOn = reverseDependsOn.map { variant.toTask(it) },
runBefore = runBefore.map { variant.toTask(it) }, runBefore = runBefore.map { variant.toTask(it) },
runAfter = runAfter.map { variant.toTask(it) }, runAfter = runAfter.map { variant.toTask(it) },
closure = incrementalManagerFactory.create().toIncrementalTaskClosure(taskName, runTask, variant))) alwaysRunAfter = alwaysRunAfter.map { variant.toTask(it) },
closure = incrementalManager.toIncrementalTaskClosure(taskName, runTask)))
} }
} }
override fun tasksFor(project: Project, context: KobaltContext) : List<DynamicTask> = dynamicTasks override fun tasksFor(context: KobaltContext) : List<DynamicTask> = dynamicTasks
} }

View file

@ -6,61 +6,33 @@ package com.beust.kobalt.api.annotation
*/ */
annotation class Directive annotation class Directive
object AnnotationDefault {
const val GROUP = "other"
}
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
annotation class Task( annotation class Task(
/* This task's name */
val name: String, val name: String,
/* The documentation for this task */
val description: String = "", val description: String = "",
/** Used to show the task in the correct group in the IDE */ /** Tasks that this task depends on */
val group: String = AnnotationDefault.GROUP,
/** Dependency: tasks this task depends on */
val dependsOn: Array<String> = arrayOf(),
/** Dependency: tasks this task will be made dependend upon */
val reverseDependsOn: Array<String> = arrayOf(),
/** Ordering: tasks that need to be run before this one */
val runBefore: Array<String> = arrayOf(), val runBefore: Array<String> = arrayOf(),
/** Ordering: tasks this task runs after */ /** Tasks that this task will run after if they get run */
val runAfter: Array<String> = arrayOf(), val runAfter: Array<String> = arrayOf(),
/** Wrapper tasks */ /** Tasks that this task will always run after */
val alwaysRunAfter: Array<String> = arrayOf() val alwaysRunAfter: Array<String> = arrayOf()
) )
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
annotation class IncrementalTask( annotation class IncrementalTask(
/* This task's name */
val name: String, val name: String,
/* The documentation for this task */
val description: String = "", val description: String = "",
/** Used to show the task in the correct group in the IDE */
val group: String = AnnotationDefault.GROUP,
/** Dependency: tasks this task depends on */
val dependsOn: Array<String> = arrayOf(),
/** Dependency: tasks this task will be made dependend upon */
val reverseDependsOn: Array<String> = arrayOf(),
/** Tasks that this task depends on */ /** Tasks that this task depends on */
val runBefore: Array<String> = arrayOf(), val runBefore: Array<String> = arrayOf(),
/** Ordering: tasks this task runs after */ /** Tasks that this task will run after if they get run */
val runAfter: Array<String> = arrayOf(), val runAfter: Array<String> = arrayOf(),
/** Wrapper tasks */ /** Tasks that this task will always run after */
val alwaysRunAfter: Array<String> = arrayOf() val alwaysRunAfter: Array<String> = arrayOf()
) )

View file

@ -1,83 +0,0 @@
package com.beust.kobalt.archive
import com.beust.kobalt.*
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.ExportedProjectProperty
import com.beust.kobalt.misc.JarUtils
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.kobaltLog
import java.io.File
import java.util.*
class Archives {
companion object {
@ExportedProjectProperty(doc = "The name of the jar file", type = "String")
const val JAR_NAME = "jarName"
@ExportedProjectProperty(doc = "The name of the a jar file with a main() method", type = "String")
const val JAR_NAME_WITH_MAIN_CLASS = "jarNameWithMainClass"
fun defaultArchiveName(project: Project) = project.name +
if (project.version.isNullOrBlank()) "" else "-${project.version}"
fun generateArchive(project: Project,
context: KobaltContext,
archiveName: String?,
suffix: String,
includedFiles: List<IncludedFile>,
expandJarFiles : Boolean = false,
manifest: java.util.jar.Manifest? = null) : File {
val fullArchiveName = context.variant.archiveName(project, archiveName, suffix)
val archiveDir = File(KFiles.libsDir(project))
val result = File(archiveDir.path, fullArchiveName)
context.logger.log(project.name, 3, "Creating $result")
if (! Features.USE_TIMESTAMPS || isOutdated(project.directory, includedFiles, result)) {
try {
MetaArchive(result, manifest).use { metaArchive ->
JarUtils.addFiles(project.directory, includedFiles, metaArchive, expandJarFiles)
context.logger.log(project.name, 2, "Added ${includedFiles.size} files to $result")
context.logger.log(project.name, 1, " Created $result")
}
} catch (e: Throwable) {
// make sure that incomplete archive is deleted
// otherwise incremental build does not work on next run
result.delete()
throw e
}
} else {
context.logger.log(project.name, 3, " $result is up to date")
}
return result
}
private fun isOutdated(directory: String, includedFiles: List<IncludedFile>, output: File): Boolean {
if (! output.exists()) return true
val lastModified = output.lastModified()
includedFiles.forEach { root ->
val allFiles = root.allFromFiles(directory)
allFiles.forEach { relFile ->
val file = if (relFile.isAbsolute)
relFile // e.g. jar file or classes folder (of another project) when building a fat jar
else
File(KFiles.joinDir(directory, root.from, relFile.path))
if (file.isFile) {
if (file.lastModified() > lastModified) {
kobaltLog(3, " TS - Outdated $file and $output "
+ Date(file.lastModified()) + " " + Date(output.lastModified()))
return true
}
} else if (file.isDirectory) {
// e.g. classes folder (of another project) when building a fat jar
val includedFile = IncludedFile(From(""), To(""), listOf(IFileSpec.GlobSpec("**")))
if (isOutdated(file.absolutePath, listOf(includedFile), output))
return true
}
}
}
return false
}
}
}

View file

@ -1,6 +0,0 @@
package com.beust.kobalt.archive
interface AttributeHolder {
fun addAttribute(k: String, v: String)
}

View file

@ -1,28 +0,0 @@
package com.beust.kobalt.archive
import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.Directive
/**
* A jar is exactly like a zip with the addition of a manifest and an optional fatJar boolean.
*/
open class Jar(override val project: Project,
override var name : String = Archives.defaultArchiveName(project) + ".jar",
override var fatJar: Boolean = false) : Zip(project, name, fatJar), AttributeHolder {
@Directive
fun manifest(init: Manifest.(p: Manifest) -> Unit) : Manifest {
val m = Manifest(this)
m.init(m)
return m
}
// Need to specify the version or attributes will just be dropped
@Directive
override val attributes = arrayListOf(Pair("Manifest-Version", "1.0"))
override fun addAttribute(k: String, v: String) {
attributes.add(Pair(k, v))
}
}

View file

@ -1,11 +0,0 @@
package com.beust.kobalt.archive
import com.beust.kobalt.api.annotation.Directive
class Manifest(val jar: AttributeHolder) {
@Directive
fun attributes(k: String, v: String) {
jar.addAttribute(k, v)
}
}

View file

@ -1,125 +0,0 @@
package com.beust.kobalt.archive
import com.beust.kobalt.Glob
import com.beust.kobalt.misc.KFiles
import org.apache.commons.compress.archivers.ArchiveEntry
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream
import java.io.Closeable
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.jar.Manifest
import org.apache.commons.compress.archivers.zip.ZipFile as ApacheZipFile
/**
* Abstraction of a zip/jar/war archive that automatically manages the addition of expanded jar files.
* Uses ZipArchiveOutputStream for fast inclusion of expanded jar files.
*/
class MetaArchive(outputFile: File, val manifest: Manifest?) : Closeable {
companion object {
const val MANIFEST_MF = "META-INF/MANIFEST.MF"
}
private val zos= ZipArchiveOutputStream(outputFile).apply {
encoding = "UTF-8"
}
init {
// If no manifest was passed, create an empty one so it's the first one in the archive
val m = manifest ?: Manifest()
val manifestFile = File.createTempFile("kobalt", "tmpManifest")
addEntry(ZipArchiveEntry("META-INF/"), null)
if (manifest != null) {
FileOutputStream(manifestFile).use { fos ->
m.write(fos)
}
}
val entry = zos.createArchiveEntry(manifestFile, MetaArchive.MANIFEST_MF)
addEntry(entry, FileInputStream(manifestFile))
}
fun addFile(f: File, entryFile: File, path: String?) {
maybeCreateParentDirectories(f)
addFile2(f, entryFile, path)
}
private fun addFile2(f: File, entryFile: File, path: String?) {
val file = f.normalize()
FileInputStream(file).use { inputStream ->
val actualPath = KFiles.fixSlashes(if (path != null) path + entryFile.path else entryFile.path)
ZipArchiveEntry(actualPath).let { entry ->
maybeCreateParentDirectories(File(actualPath))
maybeAddEntry(entry) {
addEntry(entry, inputStream)
}
}
}
}
private val createdDirs = hashSetOf<String>()
/**
* For an entry a/b/c/File, an entry needs to be created for each individual directory:
* a/
* a/b/
* a/b/c
* a/b/c/File
*/
private fun maybeCreateParentDirectories(file: File) {
val toCreate = arrayListOf<String>()
var current = file.parentFile
while (current != null && current.path != ".") {
if (!createdDirs.contains(current.path)) {
toCreate.add(0, KFiles.fixSlashes(current) + "/")
createdDirs.add(current.path)
}
current = current.parentFile
}
toCreate.forEach { dir ->
addEntry(ZipArchiveEntry(dir), null)
}
}
fun addArchive(jarFile: File) {
ApacheZipFile(jarFile).use { jar ->
val jarEntries = jar.entries
for (entry in jarEntries) {
maybeAddEntry(entry) {
zos.addRawArchiveEntry(entry, jar.getRawInputStream(entry))
}
}
}
}
private fun okToAdd(name: String) : Boolean {
val result = !KFiles.isExcluded(name,
Glob("META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA", MANIFEST_MF))
// if (name.startsWith("META-INF")) println((if (result) "ADDING" else "NOT ADDING") + " $name")
return result
}
override fun close() = zos.close()
private fun addEntry(entry: ArchiveEntry, inputStream: FileInputStream?) {
zos.putArchiveEntry(entry)
inputStream?.use { ins ->
ins.copyTo(zos, 50 * 1024)
}
zos.closeArchiveEntry()
}
private val seen = hashSetOf<String>()
private fun maybeAddEntry(entry: ArchiveEntry, action:() -> Unit) {
entry.name.let { name ->
if (!seen.contains(name) && okToAdd(name)) {
action()
}
seen.add(name)
}
}
}

Some files were not shown because too many files have changed in this diff Show more