1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-30 09:58:12 -07:00

Compare commits

..

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

187 changed files with 2558 additions and 6654 deletions

6
.gitignore vendored
View file

@ -2,14 +2,12 @@
annotations annotations
.idea/* .idea/*
*.iml *.iml
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

View file

@ -1,14 +1,11 @@
# Kobalt # Kobalt [![Build Status](https://travis-ci.org/cbeust/kobalt.svg?branch=master)](https://travis-ci.org/cbeust/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

@ -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 +1,2 @@
#!/usr/bin/env sh #!/usr/bin/env sh
java -jar "`dirname "$0"`/../kobalt/wrapper/kobalt-wrapper.jar" $*
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" $*

Binary file not shown.

View file

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

188
gradlew vendored
View file

@ -1,188 +0,0 @@
#!/usr/bin/env sh
#
# 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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# 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\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
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.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
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" "$@"

100
gradlew.bat vendored
View file

@ -1,100 +0,0 @@
@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
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
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
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View file

@ -1,14 +1,15 @@
import com.beust.kobalt.TaskResult
import com.beust.kobalt.*
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
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.kotlin.kotlinCompiler import com.beust.kobalt.plugin.kotlin.kotlinCompiler
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.bintray
import com.beust.kobalt.plugin.publish.github import com.beust.kobalt.plugin.publish.github
import com.beust.kobalt.project
import com.beust.kobalt.test
import org.apache.maven.model.Developer import org.apache.maven.model.Developer
import org.apache.maven.model.License import org.apache.maven.model.License
import org.apache.maven.model.Model import org.apache.maven.model.Model
@ -17,41 +18,22 @@ 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 {
repos("https://dl.bintray.com/cbeust/maven")
}
object Versions { object Versions {
val kotlin = "1.2.71" val okhttp = "3.2.0"
val okhttp = "3.9.1" val okio = "1.6.0"
val okio = "1.13.0" val retrofit = "2.1.0"
val retrofit = "2.3.0" val gson = "2.6.2"
val gson = "2.8.2" val maven = "3.3.9"
val guice = "4.2.2" val mavenResolver = "1.0.3"
val maven = "3.5.2"
val mavenResolver = "1.1.0"
val slf4j = "1.7.3" val slf4j = "1.7.3"
val aether = "1.0.2.v20150114" val kotlin = "1.1.0-beta-38"
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) fun mavenResolver(vararg m: String)
= m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" } = m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" }
.toTypedArray() .toTypedArray()
fun aether(vararg m: String)
= m.map { "org.eclipse.aether:aether-$it:${Versions.aether}" }
.toTypedArray()
val wrapper = project { val wrapper = project {
name = "kobalt-wrapper" name = "kobalt-wrapper"
group = "com.beust" group = "com.beust"
@ -64,7 +46,6 @@ val wrapper = project {
} }
assemble { assemble {
jar { }
jar { jar {
name = projectName + ".jar" name = projectName + ".jar"
manifest { manifest {
@ -76,13 +57,6 @@ 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 = project {
@ -92,44 +66,46 @@ val kobaltPluginApi = project {
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"
pom = createPom(name, "A build system in Kotlin") pom = Model().apply {
name = project.name
description = "A build system in Kotlin"
url = "http://beust.com/kobalt"
licenses = listOf(License().apply {
name = "Apache 2.0"
url = "http://www.apache .org/licenses/LICENSE-2.0"
})
scm = Scm().apply {
url = "http://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"
})
}
dependencies { dependencies {
compile( compile(
"org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}", "com.google.inject:guice:4.0",
"com.google.inject:guice:${Versions.guice}", "com.google.inject.extensions:guice-assistedinject:4.0",
"com.google.inject.extensions:guice-assistedinject:4.1.0",
"javax.inject:javax.inject:1", "javax.inject:javax.inject:1",
"com.google.guava:guava:27.0.1-jre", "com.google.guava:guava:19.0",
"org.apache.maven:maven-model:${Versions.maven}", "org.apache.maven:maven-model:${Versions.maven}",
"io.reactivex:rxjava:1.3.3", "io.reactivex:rxjava:1.1.5",
"com.squareup.okio:okio:${Versions.okio}", "com.squareup.okio:okio:${Versions.okio}",
"com.google.code.gson:gson:${Versions.gson}", "com.google.code.gson:gson:${Versions.gson}",
"com.squareup.okhttp3:okhttp:${Versions.okhttp}", "com.squareup.okhttp3:okhttp:${Versions.okhttp}",
"com.squareup.retrofit2:retrofit:${Versions.retrofit}", "com.squareup.retrofit2:retrofit:${Versions.retrofit}",
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}", "com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
"com.beust:jcommander:${Versions.jcommander}", "com.beust:jcommander:1.48",
"org.eclipse.jgit:org.eclipse.jgit:4.9.0.201710071750-r", "org.eclipse.jgit:org.eclipse.jgit:4.5.0.201609210915-r",
"org.slf4j:slf4j-simple:${Versions.slf4j}", "org.slf4j:slf4j-simple:${Versions.slf4j}",
*mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"), *mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"),
"org.apache.maven:maven-aether-provider:3.3.9", "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
"javax.xml.bind:jaxb-api:2.3.0"
) )
exclude(*aether("impl", "spi", "util", "api"))
} }
@ -142,8 +118,12 @@ val kobaltPluginApi = project {
} }
} }
// install {
// libDir = "lib-test"
// }
kotlinCompiler { kotlinCompiler {
args("nowarn") args("-nowarn")
} }
bintray { bintray {
@ -162,32 +142,24 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
compile("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") compile("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}")
// 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.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}", "org.apache.maven:maven-model:${Versions.maven}",
"com.google.code.findbugs:jsr305:3.0.2", "com.google.code.findbugs:jsr305:3.0.1",
"com.google.code.gson:gson:${Versions.gson}", "com.google.code.gson:gson:${Versions.gson}",
"com.squareup.retrofit2:retrofit:${Versions.retrofit}", "com.squareup.retrofit2:retrofit:${Versions.retrofit}",
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}", "com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
// "com.squareup.okhttp3:okhttp-ws:3.4.2", "com.squareup.okhttp3:okhttp-ws:${Versions.okhttp}",
"biz.aQute.bnd:biz.aQute.bndlib:3.5.0", "biz.aQute.bnd:bndlib:2.4.0",
*mavenResolver("spi"), *mavenResolver("spi"),
"com.squareup.okhttp3:logging-interceptor:3.9.0", "com.squareup.okhttp3:logging-interceptor:3.2.0",
"com.sparkjava:spark-core:2.6.0", "com.sparkjava:spark-core:2.5",
"org.codehaus.groovy:groovy:2.4.12", "org.codehaus.groovy:groovy:2.4.8"
// 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-server:${Versions.jetty}",
// "org.eclipse.jetty:jetty-servlet:${Versions.jetty}", // "org.eclipse.jetty:jetty-servlet:${Versions.jetty}",
@ -201,9 +173,8 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
} }
dependenciesTest { dependenciesTest {
compile("org.jetbrains.kotlin:kotlin-test:${Versions.kotlin}", compile("org.testng:testng:6.10",
"org.testng:testng:${Versions.testng}", "org.assertj:assertj-core:3.4.1",
"org.assertj:assertj-core:3.8.0",
*mavenResolver("util") *mavenResolver("util")
) )
} }
@ -217,27 +188,17 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
} }
zip { zip {
val dir = "kobalt-$version" val dir = "kobalt-$version"
val files = listOf( include(from("dist"), to("$dir/bin"), "kobaltw")
"dist", "$dir/bin", "kobaltw", include(from("dist"), to("$dir/bin"), "kobaltw.bat")
"dist", "$dir/bin", "kobaltw.bat", include(from("$buildDirectory/libs"), to("$dir/kobalt/wrapper"),
"$buildDirectory/libs", "$dir/kobalt/wrapper", "$projectName-$version.jar", "$projectName-$version.jar")
"modules/wrapper/$buildDirectory/libs", "$dir/kobalt/wrapper", "$projectName-wrapper.jar") include(from("modules/wrapper/$buildDirectory/libs"), to("$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 {
@ -246,37 +207,12 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
github { github {
file("$buildDirectory/libs/$name-$version.zip", "$name/$version/$name-$version.zip") file("$buildDirectory/libs/$name-$version.zip", "$name/$version/$name-$version.zip")
autoGitTag = true
} }
test { test {
args("-log", "2", "src/test/resources/testng.xml") args("-log", "2", "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 {
@ -296,31 +232,9 @@ fun taskCopyVersionForWrapper(project: Project) : TaskResult {
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.931

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"

BIN
lib/kotlin-reflect.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/kotlin-runtime.jar Normal file

Binary file not shown.

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

@ -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")
@ -22,10 +22,6 @@ class Args {
@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
@ -47,7 +43,7 @@ class Args {
var listTemplates: Boolean = false var listTemplates: Boolean = false
@Parameter(names = arrayOf("--log"), description = "Define the log level " + @Parameter(names = arrayOf("--log"), description = "Define the log level " +
"(${Constants.LOG_QUIET_LEVEL}-${Constants.LOG_MAX_LEVEL})") "(${Constants.LOG_DEFAULT_LEVEL}-${Constants.LOG_MAX_LEVEL})")
var log: Int = Constants.LOG_DEFAULT_LEVEL var log: Int = Constants.LOG_DEFAULT_LEVEL
@Parameter(names = arrayOf("--logTags"), @Parameter(names = arrayOf("--logTags"),
@ -61,8 +57,8 @@ class Args {
@Parameter(names = arrayOf("--noIncremental"), description = "Turn off incremental builds") @Parameter(names = arrayOf("--noIncremental"), description = "Turn off incremental builds")
var noIncremental: Boolean = false var noIncremental: Boolean = false
@Parameter(names = arrayOf("--offline"), description = "Don't try to download dependencies even if there is no cached version") @Parameter(names = arrayOf("--parallel"), description = "Build all the projects in parallel whenever possible")
var offline: Boolean = false var parallel: Boolean = true
@Parameter(names = arrayOf("--plugins"), description = "Comma-separated list of plug-in Maven id's") @Parameter(names = arrayOf("--plugins"), description = "Comma-separated list of plug-in Maven id's")
var pluginIds: String? = null var pluginIds: String? = null
@ -86,14 +82,7 @@ class Args {
@Parameter(names = arrayOf("--projectInfo"), description = "Display information about the current projects") @Parameter(names = arrayOf("--projectInfo"), description = "Display information about the current projects")
var projectInfo: Boolean = false var projectInfo: Boolean = false
@Parameter(names = arrayOf("--noIncrementalKotlin"), description = "Disable incremental Kotlin compilation") @Parameter(names = arrayOf("--sequential"), description = "Build all the projects in sequence")
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 var sequential: Boolean = false
@Parameter(names = arrayOf("--server"), description = "Run in server mode") @Parameter(names = arrayOf("--server"), description = "Run in server mode")
@ -104,8 +93,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

@ -105,7 +105,7 @@ 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: CharSequence, color: String) = color + s + RESET
private fun blue(s: CharSequence) = wrap(s, BLUE) private fun blue(s: CharSequence) = wrap(s, BLUE)
private fun red(s: CharSequence) = wrap(s, RED) private fun red(s: CharSequence) = wrap(s, RED)
private fun yellow(s: CharSequence) = wrap(s, YELLOW) private fun yellow(s: CharSequence) = wrap(s, YELLOW)
@ -150,9 +150,9 @@ class AsciiTable {
append("\n") append("\n")
} }
var lineLength = 0 var lineLength = 0
rows.forEachIndexed { _, row -> rows.forEachIndexed { index, row ->
val formattedRow = row.mapIndexed { i, s -> col(widths[i], s) }.joinToString(vb) val formattedRow = row.mapIndexed { i, s -> col(widths[i], s) }.joinToString(vb)
val line = "$vb $formattedRow $vb" val line = vb + " " + formattedRow + " " + vb
result.append(line).append("\n") result.append(line).append("\n")
lineLength = line.length lineLength = line.length
} }

View file

@ -16,33 +16,26 @@ var BUILD_SCRIPT_CONFIG : BuildScriptConfig? = null
class BuildScriptConfig { class BuildScriptConfig {
/** The list of repos used to locate plug-ins. */ /** The list of repos used to locate plug-ins. */
@Directive
fun repos(vararg r: String) = newRepos(*r) fun repos(vararg r: String) = newRepos(*r)
/** The list of plug-ins to use for this build file. */ /** The list of plug-ins to use for this build file. */
@Directive
fun plugins(vararg pl: String) = newPlugins(*pl) fun plugins(vararg pl: String) = newPlugins(*pl)
/** The build file classpath. */ /** The build file classpath. */
@Directive
fun buildFileClasspath(vararg bfc: String) = newBuildFileClasspath(*bfc) fun buildFileClasspath(vararg bfc: String) = newBuildFileClasspath(*bfc)
/** Options passed to Kobalt */ // The following settings modify the compiler used to compile the build file.
@Directive // Projects should use kotlinCompiler { compilerVersion } to configure the Kotin compiler for their source files.
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 kobaltCompilerVersion : String? = null
var kobaltCompilerRepo: String? = null var kobaltCompilerRepo: String? = null
var kobaltCompilerFlags: String? = null var kobaltCompilerFlags: String? = null
} }
@Directive
fun buildScript(init: BuildScriptConfig.() -> Unit) {
BUILD_SCRIPT_CONFIG = BuildScriptConfig().apply { init() }
}
@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.toMutableList().joinToString(File.separator)
@ -74,18 +67,7 @@ data class ProxyConfig(val host: String = "", val port: Int = 0, val type: Strin
fun toAetherProxy() = Proxy(type, host, port) // TODO make support for proxy auth fun toAetherProxy() = Proxy(type, host, port) // TODO make support for proxy auth
} }
data class HostConfig(var url: String = "", var name: String = HostConfig.createRepoName(url), data class HostConfig(var url: String = "", var username: String? = null, var password: String? = null) {
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())
} }
@ -116,7 +98,6 @@ fun buildFileClasspath(vararg deps: String) {
} }
fun newBuildFileClasspath(vararg deps: String) { fun newBuildFileClasspath(vararg deps: String) {
//FIXME newBuildFileClasspath called twice
deps.forEach { Kobalt.addBuildFileClasspath(it) } deps.forEach { Kobalt.addBuildFileClasspath(it) }
} }
@ -126,7 +107,7 @@ fun authRepos(vararg repos : HostConfig) {
} }
@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)
@ -143,3 +124,4 @@ fun localMaven() : String {
} }
return result.toURI().toString() return result.toURI().toString()
} }

View file

@ -3,19 +3,20 @@ package com.beust.kobalt
import com.beust.kobalt.misc.KFiles 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_DEFAULT_LEVEL = 1
const val LOG_MAX_LEVEL = 3 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 BUILD_FILE_PATH = KFiles.joinDir(BUILD_FILE_DIRECTORY, BUILD_FILE_NAME)
val KOTLIN_COMPILER_VERSION = "1.2.70" val KOTLIN_COMPILER_VERSION = "1.1.0-beta-38"
internal val DEFAULT_REPOS = listOf<HostConfig>( internal val DEFAULT_REPOS = listOf<String>(
// "https://maven-central.storage.googleapis.com/", // "https://maven-central.storage.googleapis.com/",
HostConfig("https://repo1.maven.org/maven2/", "Maven"), "http://repo1.maven.org/maven2/",
HostConfig("https://jcenter.bintray.com/", "JCenter") "https://jcenter.bintray.com/",
// "https://repository.jetbrains.com/all/", // <-- contains snapshots // "http://repository.jetbrains.com/all/", // <-- contains snapshots
"https://dl.bintray.com/kotlin/kotlin-eap",
"https://dl.bintray.com/kotlin/kotlin-eap-1.1"
// snapshots // snapshots
// "https://oss.sonatype.org/content/repositories/snapshots/" // "https://oss.sonatype.org/content/repositories/snapshots/"

View file

@ -4,8 +4,6 @@ import com.beust.kobalt.api.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
import com.beust.kobalt.internal.JvmCompilerPlugin import com.beust.kobalt.internal.JvmCompilerPlugin
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@Directive @Directive
fun project(vararg projects: Project, init: Project.() -> Unit): Project { fun project(vararg projects: Project, init: Project.() -> Unit): Project {
@ -16,24 +14,3 @@ fun project(vararg projects: Project, init: Project.() -> Unit): Project {
} }
} }
@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,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

@ -3,22 +3,21 @@ package com.beust.kobalt
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.archive.Archives import com.beust.kobalt.archive.Archives
import com.beust.kobalt.archive.MetaArchive import com.beust.kobalt.archive.Jar
import com.beust.kobalt.archive.Zip
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.Scope import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.*
import com.beust.kobalt.misc.kobaltLog
import com.google.inject.Inject import com.google.inject.Inject
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.OutputStream
import java.nio.file.Paths import java.nio.file.Paths
import java.util.jar.JarOutputStream
import java.util.jar.Manifest import java.util.jar.Manifest
class JarGenerator @Inject constructor(val dependencyManager: DependencyManager) : ArchiveGenerator { class JarGenerator @Inject constructor(val dependencyManager: DependencyManager) {
companion object { companion object {
fun findIncludedFiles(directory: String, files: List<IncludedFile>, excludes: List<Glob>, fun findIncludedFiles(directory: String, files: List<IncludedFile>, excludes: List<Glob>)
throwOnError: Boolean = true)
: List<IncludedFile> { : List<IncludedFile> {
val result = arrayListOf<IncludedFile>() val result = arrayListOf<IncludedFile>()
files.forEach { includedFile -> files.forEach { includedFile ->
@ -28,7 +27,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
if (File(directory, fromPath).exists()) { if (File(directory, fromPath).exists()) {
spec.toFiles(directory, fromPath).forEach { file -> spec.toFiles(directory, fromPath).forEach { file ->
val fullFile = File(KFiles.joinDir(directory, fromPath, file.path)) val fullFile = File(KFiles.joinDir(directory, fromPath, file.path))
if (! fullFile.exists() && throwOnError) { if (! fullFile.exists()) {
throw AssertionError("File should exist: $fullFile") throw AssertionError("File should exist: $fullFile")
} }
@ -53,9 +52,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
} }
} }
override val suffix = ".jar" fun findIncludedFiles(project: Project, context: KobaltContext, jar: Jar) : List<IncludedFile> {
override fun findIncludedFiles(project: Project, context: KobaltContext, zip: Zip) : List<IncludedFile> {
// //
// Add all the applicable files for the current project // Add all the applicable files for the current project
// //
@ -63,7 +60,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
val result = arrayListOf<IncludedFile>() val result = arrayListOf<IncludedFile>()
val classesDir = KFiles.makeDir(buildDir.path, "classes") val classesDir = KFiles.makeDir(buildDir.path, "classes")
if (zip.includedFiles.isEmpty()) { if (jar.includedFiles.isEmpty()) {
// If no includes were specified, assume the user wants a simple jar file made of the // 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 // classes of the project, so we specify a From("build/classes/"), To("") and
// a list of files containing everything under it // a list of files containing everything under it
@ -73,7 +70,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
// Class files // Class files
val files = KFiles.findRecursively(classesDir).map { File(relClassesDir.toFile(), it) } val files = KFiles.findRecursively(classesDir).map { File(relClassesDir.toFile(), it) }
val filesNotExcluded : List<File> = files.filter { val filesNotExcluded : List<File> = files.filter {
! KFiles.Companion.isExcluded(KFiles.joinDir(project.directory, it.path), zip.excludes) ! KFiles.Companion.isExcluded(KFiles.joinDir(project.directory, it.path), jar.excludes)
} }
val fileSpecs = arrayListOf<IFileSpec>() val fileSpecs = arrayListOf<IFileSpec>()
filesNotExcluded.forEach { filesNotExcluded.forEach {
@ -89,14 +86,16 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
// //
// The user specified an include, just use it verbatim // The user specified an include, just use it verbatim
// //
val includedFiles = findIncludedFiles(project.directory, zip.includedFiles, zip.excludes, false) val includedFiles = findIncludedFiles(project.directory, jar.includedFiles, jar.excludes)
result.addAll(includedFiles) result.addAll(includedFiles)
} }
// //
// If fatJar is true, add all the transitive dependencies as well: compile, runtime and dependent projects // If fatJar is true, add all the transitive dependencies as well: compile, runtime and dependent projects
// //
if (zip.fatJar) { if (jar.fatJar) {
context.logger.log(project.name, 2, "Finding included files for fat jar")
val seen = hashSetOf<String>() val seen = hashSetOf<String>()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val allDependencies = project.compileDependencies + project.compileRuntimeDependencies + val allDependencies = project.compileDependencies + project.compileRuntimeDependencies +
@ -111,7 +110,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
}.forEach { file : File -> }.forEach { file : File ->
if (! seen.contains(file.path)) { if (! seen.contains(file.path)) {
seen.add(file.path) seen.add(file.path)
if (! KFiles.Companion.isExcluded(file, zip.excludes)) { if (! KFiles.Companion.isExcluded(file, jar.excludes)) {
result.add(IncludedFile(specs = arrayListOf(IFileSpec.FileSpec(file.absolutePath)), result.add(IncludedFile(specs = arrayListOf(IFileSpec.FileSpec(file.absolutePath)),
expandJarFiles = true)) expandJarFiles = true))
} }
@ -122,18 +121,19 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
return result return result
} }
override fun generateArchive(project: Project, context: KobaltContext, zip: Zip, fun generateJar(project: Project, context: KobaltContext, jar: Jar) : File {
includedFiles: List<IncludedFile>) : File { val includedFiles = findIncludedFiles(project, context, jar)
// //
// Generate the manifest // Generate the manifest
// If manifest attributes were specified in the build file, use those to generateAndSave the manifest. Otherwise, // 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. // try to find a META-INF/MANIFEST.MF and use that one if we find any. Otherwise, use the default manifest.
// //
val manifest = val manifest =
if (zip.attributes.size > 1) { if (jar.attributes.size > 1) {
context.logger.log(project.name, 2, "Creating MANIFEST.MF from " + zip.attributes.size + " attributes") context.logger.log(project.name, 2, "Creating MANIFEST.MF from " + jar.attributes.size + " attributes")
Manifest().apply { Manifest().apply {
zip.attributes.forEach { attribute -> jar.attributes.forEach { attribute ->
mainAttributes.putValue(attribute.first, attribute.second) mainAttributes.putValue(attribute.first, attribute.second)
} }
} }
@ -142,7 +142,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
val allFiles = includedFiles.flatMap { file -> val allFiles = includedFiles.flatMap { file ->
file.allFromFiles(project.directory).map { file.from(it.path) } file.allFromFiles(project.directory).map { file.from(it.path) }
} }
val manifestFiles = allFiles.filter { it.path.contains(MetaArchive.MANIFEST_MF) } val manifestFiles = allFiles.filter { it.path.contains("META-INF/MANIFEST.MF") }
return if (manifestFiles.any()) manifestFiles[0] else null return if (manifestFiles.any()) manifestFiles[0] else null
} }
@ -151,12 +151,14 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
context.logger.log(project.name, 2, "Including MANIFEST.MF file $manifestFile") context.logger.log(project.name, 2, "Including MANIFEST.MF file $manifestFile")
Manifest(FileInputStream(manifestFile)) Manifest(FileInputStream(manifestFile))
} else { } else {
null Manifest()
} }
} }
return Archives.generateArchive(project, context, zip.name, ".jar", includedFiles, val jarFactory = { os: OutputStream -> JarOutputStream(os, manifest) }
true /* expandJarFiles */, manifest)
return Archives.generateArchive(project, context, jar.name, ".jar", includedFiles,
true /* expandJarFiles */, jarFactory)
} }
} }

View file

@ -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

View file

@ -28,6 +28,7 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
val depManager: DependencyManager, val depManager: DependencyManager,
val settings: KobaltSettings, val settings: KobaltSettings,
val executors: KobaltExecutors, val executors: KobaltExecutors,
val pluginInfo: PluginInfo,
val incrementalManagerFactory: IncrementalManager.IFactory, val incrementalManagerFactory: IncrementalManager.IFactory,
val taskManager: TaskManager) { val taskManager: TaskManager) {
@ -170,9 +171,6 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
val dependencies = arrayListOf<IClasspathDependency>() val dependencies = arrayListOf<IClasspathDependency>()
// @Inject
// lateinit var pluginInfo: PluginInfo
fun installPlugins(dependencies: List<IClasspathDependency>, scriptClassLoader: ClassLoader) { fun installPlugins(dependencies: List<IClasspathDependency>, scriptClassLoader: ClassLoader) {
val executor = executors.newExecutor("Plugins", 5) val executor = executors.newExecutor("Plugins", 5)
dependencies.forEach { dependencies.forEach {
@ -193,8 +191,6 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
// The plug-in is pointing to a jar file, read kobalt-plugin.xml from it // The plug-in is pointing to a jar file, read kobalt-plugin.xml from it
JarUtils.extractTextFile(JarFile(file), PluginInfo.PLUGIN_XML) 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 pluginClassLoader = URLClassLoader(arrayOf(file.toURI().toURL()))
val thisPluginInfo = PluginInfo.readPluginXml(pluginXml, pluginClassLoader, scriptClassLoader) val thisPluginInfo = PluginInfo.readPluginXml(pluginXml, pluginClassLoader, scriptClassLoader)

View file

@ -3,8 +3,12 @@ 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.aether.AetherDependency
import com.beust.kobalt.misc.* import com.beust.kobalt.maven.aether.Filters
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.beust.kobalt.misc.KobaltExecutors
import com.beust.kobalt.misc.Node
import com.beust.kobalt.misc.kobaltLog
import com.google.inject.Inject import com.google.inject.Inject
import org.eclipse.aether.artifact.DefaultArtifact import org.eclipse.aether.artifact.DefaultArtifact
import org.eclipse.aether.graph.DependencyNode import org.eclipse.aether.graph.DependencyNode
@ -29,7 +33,7 @@ class ResolveDependency @Inject constructor(
private fun latestMavenArtifact(group: String, artifactId: String, extension: String = "jar"): DependencyNode { private fun latestMavenArtifact(group: String, artifactId: String, extension: String = "jar"): DependencyNode {
val artifact = DefaultArtifact(group, artifactId, extension, "(0,]") val artifact = DefaultArtifact(group, artifactId, extension, "(0,]")
val resolved = aether.resolveRange(artifact) val resolved = aether.resolveVersion(artifact)
if (resolved != null) { if (resolved != null) {
val newArtifact = DefaultArtifact(artifact.groupId, artifact.artifactId, artifact.extension, val newArtifact = DefaultArtifact(artifact.groupId, artifact.artifactId, artifact.extension,
resolved.highestVersion.toString()) resolved.highestVersion.toString())
@ -69,7 +73,7 @@ class ResolveDependency @Inject constructor(
kobaltLog(1, AsciiArt.logBox(listOf(dep.id, url, dep.jarFile.get()).map { " $it" })) kobaltLog(1, AsciiArt.logBox(listOf(dep.id, url, dep.jarFile.get()).map { " $it" }))
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 +85,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 == 0 || ((i + 1) % increment == 0)) print(vertical) if (i == 0 || ((i + 1) % increment == 0)) print(vertical)
else print(" ") else print(" ")
} }
} println(left + " " + dep.id + (if (dep.optional) " (optional)" else ""))
kobaltLog(1, left + " " + dep.id + (if (dep.optional) " (optional)" else ""))
display(node.children) display(node.children)
} }
} }
@ -102,12 +104,7 @@ class ResolveDependency @Inject constructor(
kobaltLog(2, "Found dependency ${dep.dep.id} level: ${dep.level}") kobaltLog(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
}
} }
} }
kobaltLog(2, "Children for ${root.value.dep.id}: ${result.size}") kobaltLog(2, "Children for ${root.value.dep.id}: ${result.size}")

View file

@ -2,16 +2,8 @@ package com.beust.kobalt
class SystemProperties { 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,13 +3,43 @@ 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 isDefault : Boolean = false) {
val testArgs = arrayListOf<String>()
val jvmArgs = arrayListOf<String>()
val testIncludes = arrayListOf("**/*Test.class")
val testExcludes = arrayListOf<String>()
var name: String = ""
fun args(vararg arg: String) {
testArgs.addAll(arg)
}
fun jvmArgs(vararg arg: String) {
jvmArgs.addAll(arg)
}
fun include(vararg arg: String) {
testIncludes.apply {
clear()
addAll(arg)
}
}
fun exclude(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() } val tf = TestConfig(project).apply { init() }
if (! map { it.name }.contains(tf.name)) { if (! map { it.name }.contains(tf.name)) {
add(tf) add(tf)
tf
} else { } else {
throw KobaltException("Test configuration \"${tf.name}\" already exists, give it a different " throw KobaltException("Test configuration \"${tf.name}\" already exists, give it a different "
+ "name with test { name = ... }") + "name with test { name = ... }")

View file

@ -29,7 +29,7 @@ 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 { return arrayListOf<String>().apply {
add(toCamelcaseDir()) add(toCamelcaseDir())
add(productFlavor.name) add(productFlavor.name)
@ -88,7 +88,7 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
result.add(dir) result.add(dir)
} }
result.addAll(allDirectories() result.addAll(allDirectories(project)
.map { File(KFiles.joinDir("src", it, suffix)) } .map { File(KFiles.joinDir("src", it, suffix)) }
.filter(File::exists)) .filter(File::exists))
@ -113,8 +113,8 @@ 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 flavor = if (productFlavor.name.isEmpty()) "" else "-" + productFlavor.name
val type = if (buildType.name.isEmpty()) "" else "-" + buildType.name val type = if (buildType.name.isEmpty()) "" else "-" + buildType.name
val result: String = base + flavor + type + suffix val result: String = base + flavor + type + suffix
@ -124,16 +124,18 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
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[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[buildTypeName]?.buildConfig ?: null
} }
/** /**
@ -162,8 +164,7 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
?: 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 generateAndSave 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"))
@ -221,7 +222,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

@ -11,6 +11,4 @@ data class CompilerActionInfo(val directory: String?,
val suffixesBeingCompiled: 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 friendPaths: List<String>)
val forceRecompile: Boolean,
val compilerSeparateProcess: Boolean = false)

View file

@ -13,7 +13,6 @@ interface IDependencyHolder {
val compileDependencies : ArrayList<IClasspathDependency> val compileDependencies : ArrayList<IClasspathDependency>
val optionalDependencies : ArrayList<IClasspathDependency> val optionalDependencies : ArrayList<IClasspathDependency>
val compileProvidedDependencies : ArrayList<IClasspathDependency> val compileProvidedDependencies : ArrayList<IClasspathDependency>
val compileOnlyDependencies : ArrayList<IClasspathDependency>
val compileRuntimeDependencies : ArrayList<IClasspathDependency> val compileRuntimeDependencies : ArrayList<IClasspathDependency>
val excludedDependencies : ArrayList<IClasspathDependency> val excludedDependencies : ArrayList<IClasspathDependency>
val nativeDependencies : ArrayList<IClasspathDependency> val nativeDependencies : ArrayList<IClasspathDependency>
@ -30,7 +29,6 @@ open class DependencyHolder : IDependencyHolder {
override val compileDependencies : ArrayList<IClasspathDependency> = arrayListOf() override val compileDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val optionalDependencies : ArrayList<IClasspathDependency> = arrayListOf() override val optionalDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val compileProvidedDependencies : ArrayList<IClasspathDependency> = arrayListOf() override val compileProvidedDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val compileOnlyDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val compileRuntimeDependencies : ArrayList<IClasspathDependency> = arrayListOf() override val compileRuntimeDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val excludedDependencies : ArrayList<IClasspathDependency> = arrayListOf() override val excludedDependencies : ArrayList<IClasspathDependency> = arrayListOf()
override val nativeDependencies : ArrayList<IClasspathDependency> = arrayListOf() override val nativeDependencies : ArrayList<IClasspathDependency> = arrayListOf()
@ -39,7 +37,7 @@ open class DependencyHolder : IDependencyHolder {
override fun dependencies(init: Dependencies.() -> Unit) : Dependencies { override fun dependencies(init: Dependencies.() -> Unit) : Dependencies {
dependencies = Dependencies(project, compileDependencies, optionalDependencies, compileProvidedDependencies, dependencies = Dependencies(project, compileDependencies, optionalDependencies, compileProvidedDependencies,
compileOnlyDependencies, compileRuntimeDependencies, excludedDependencies, nativeDependencies) compileRuntimeDependencies, excludedDependencies, nativeDependencies)
dependencies!!.init() dependencies!!.init()
return dependencies!! return dependencies!!
} }

View file

@ -5,7 +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

View file

@ -4,12 +4,8 @@ package com.beust.kobalt.api
* Plug-ins that listen to build events. * Plug-ins that listen to build events.
*/ */
interface IBuildListener : IListener { 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 taskStart(project: Project, context: KobaltContext, taskName: String) {}
fun taskEnd(project: Project, context: KobaltContext, taskName: String, info: TaskEndInfo) {} fun taskEnd(project: Project, context: KobaltContext, taskName: String, success: Boolean) {}
fun projectStart(project: Project, context: KobaltContext) {} fun projectStart(project: Project, context: KobaltContext) {}
fun projectEnd(project: Project, context: KobaltContext, status: ProjectBuildStatus) {} fun projectEnd(project: Project, context: KobaltContext, status: ProjectBuildStatus) {}

View file

@ -36,6 +36,4 @@ interface 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

@ -1,6 +1,7 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
import com.beust.kobalt.misc.warn
interface ICompilerDescription : Comparable<ICompilerDescription> { interface ICompilerDescription : Comparable<ICompilerDescription> {
/** /**
@ -57,12 +58,10 @@ class CompilerDescription(override val name: String, override val sourceDirecto
if (info.sourceFiles.isNotEmpty()) { if (info.sourceFiles.isNotEmpty()) {
compiler.compile(project, context, info) compiler.compile(project, context, info)
} else { } else {
context.logger.log(project.name, 2, "$name couldn't find any source files to compile") warn("Couldn't find any source files to compile")
TaskResult() TaskResult()
} }
return result return result
} }
override fun toString() = name + " compiler"
} }

View file

@ -1,11 +1,8 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.maven.aether.Filters.EXCLUDE_OPTIONAL_FILTER import com.beust.kobalt.maven.aether.Filters
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.beust.kobalt.maven.aether.Scope import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.kobaltLog
import org.eclipse.aether.graph.DependencyFilter import org.eclipse.aether.graph.DependencyFilter
import org.eclipse.aether.graph.DependencyNode
/** /**
* Manage the creation of dependencies and also provide dependencies for projects. * Manage the creation of dependencies and also provide dependencies for projects.
@ -29,7 +26,7 @@ interface IDependencyManager {
/** /**
* @return the source dependencies for this project, including the contributors. * @return the source dependencies for this project, including the contributors.
*/ */
fun dependencies(project: Project, context: KobaltContext, scopes: List<Scope>): List<IClasspathDependency> fun dependencies(project: Project, context: KobaltContext): List<IClasspathDependency>
/** /**
* @return the test dependencies for this project, including the contributors. * @return the test dependencies for this project, including the contributors.
@ -41,48 +38,7 @@ interface IDependencyManager {
* allDependencies is typically either compileDependencies or testDependencies * allDependencies is typically either compileDependencies or testDependencies
*/ */
fun calculateDependencies(project: Project?, context: KobaltContext, fun calculateDependencies(project: Project?, context: KobaltContext,
dependencyFilter: DependencyFilter = dependencyFilter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER,
createDependencyFilter(project, project?.compileDependencies ?: emptyList()),
scopes: List<Scope> = listOf(Scope.COMPILE), scopes: List<Scope> = listOf(Scope.COMPILE),
vararg passedDependencies: List<IClasspathDependency>): List<IClasspathDependency> 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

@ -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

@ -23,10 +23,9 @@ class DynamicTask(override val plugin: IPlugin, override val name: String, overr
override fun call(): TaskResult2<ITask> { override fun call(): TaskResult2<ITask> {
val taskResult = closure.invoke(project) val taskResult = closure.invoke(project)
return TaskResult2(taskResult.success, errorMessage = taskResult.errorMessage, value = this) return TaskResult2(taskResult.success, taskResult.errorMessage, this)
} }
override fun toString() = override fun toString() = "[DynamicTask $name dependsOn=$dependsOn reverseDependsOn=$reverseDependsOn]"
"[DynamicTask ${project.name}:$name dependsOn=$dependsOn reverseDependsOn=$reverseDependsOn]"
} }

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

@ -0,0 +1,41 @@
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.File
import java.io.FileOutputStream
import java.util.jar.JarInputStream
/**
* Base class for templates that simply decompress a jar file to generate their project.
*/
abstract class JarTemplate(val jarName: String) : ITemplate {
companion object {
fun extractFile(ins: JarInputStream, destDir: File) {
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
}
}
}
override fun generateTemplate(args: Args, classLoader: ClassLoader) {
kobaltLog(2, "Generating template with class loader $classLoader")
val destDir = File(".")
val ins = JarInputStream(classLoader.getResource(jarName).openConnection().inputStream)
extractFile(ins, destDir)
}
}

View file

@ -5,7 +5,6 @@ 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.internal.PluginInfo
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.google.inject.Guice import com.google.inject.Guice
import com.google.inject.Injector import com.google.inject.Injector
import com.google.inject.Module import com.google.inject.Module
@ -36,12 +35,12 @@ class Kobalt {
*/ */
val repos : Set<HostConfig> val repos : Set<HostConfig>
get() { get() {
val settingsRepos = Kobalt.context?.settings?.defaultRepos?.map { HostConfig(it) } ?: emptyList() val settingsRepos = Kobalt.context?.settings?.defaultRepos ?: emptyList()
// Repos from <default-repos> in the settings // Repos from <default-repos> in the settings
val result = ArrayList( val result = ArrayList(
(if (settingsRepos.isEmpty()) Constants.DEFAULT_REPOS (if (settingsRepos.isEmpty()) Constants.DEFAULT_REPOS
else settingsRepos) else settingsRepos)
) .map { HostConfig(it) })
// Repo from <kobalt-compiler-repo> in the settings // Repo from <kobalt-compiler-repo> in the settings
Kobalt.context?.settings?.kobaltCompilerRepo?.let { Kobalt.context?.settings?.kobaltCompilerRepo?.let {
@ -56,9 +55,6 @@ class Kobalt {
// Repos from the build file // Repos from the build file
result.addAll(reposFromBuildFiles) result.addAll(reposFromBuildFiles)
result.forEach {
KobaltMavenResolver.initAuthentication(it)
}
return result.toHashSet() return result.toHashSet()
} }
@ -122,20 +118,5 @@ class Kobalt {
get() = Duration.parse( kobaltProperties.getProperty(PROPERTY_KOBALT_VERSION_CHECK_TIMEOUT) ?: "P1D") 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

@ -105,12 +105,4 @@ class InternalContext {
* The absolute directory of the current project. * The absolute directory of the current project.
*/ */
var absoluteDir: File? = null 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

@ -3,7 +3,6 @@ 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.DependencyManager
import com.beust.kobalt.maven.aether.AetherDependency
import com.beust.kobalt.maven.aether.KobaltMavenResolver 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 com.beust.kobalt.misc.kobaltLog
@ -12,7 +11,6 @@ import java.io.File
import java.util.* import java.util.*
import java.util.concurrent.Future import java.util.concurrent.Future
import java.util.concurrent.FutureTask 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 = "",
@ -26,7 +24,6 @@ open class Project(
@Directive open var url: String? = null, @Directive open var url: String? = null,
@Directive open var pom: Model? = null, @Directive open var pom: Model? = null,
@Directive open var dependsOn: ArrayList<Project> = arrayListOf<Project>(), @Directive open var dependsOn: ArrayList<Project> = arrayListOf<Project>(),
@Directive open var testsDependOn: ArrayList<Project> = arrayListOf<Project>(),
@Directive open var packageName: String? = group) @Directive open var packageName: String? = group)
: IBuildConfig, IDependencyHolder by DependencyHolder() { : IBuildConfig, IDependencyHolder by DependencyHolder() {
@ -34,15 +31,13 @@ open class Project(
this.project = this this.project = this
} }
fun allProjectDependedOn() = project.dependsOn + project.testsDependOn
class ProjectExtra(project: Project) { class ProjectExtra(project: 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.dependsOn.any { it.projectExtra.isDirty }
} }
/** /**
@ -91,8 +86,7 @@ open class Project(
@Directive @Directive
fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies { fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies {
dependencies = Dependencies(this, testDependencies, arrayListOf(), dependencies = Dependencies(this, testDependencies, arrayListOf(),
testProvidedDependencies, compileOnlyDependencies, compileRuntimeDependencies, testProvidedDependencies, compileRuntimeDependencies, excludedDependencies, nativeDependencies)
excludedDependencies, nativeDependencies)
dependencies!!.init() dependencies!!.init()
return dependencies!! return dependencies!!
} }
@ -100,9 +94,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
@ -129,18 +120,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]" override fun toString() = "[Project $name]"
} }
@ -155,7 +134,6 @@ class Dependencies(val project: Project,
val dependencies: ArrayList<IClasspathDependency>, val dependencies: ArrayList<IClasspathDependency>,
val optionalDependencies: 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>) { val nativeDependencies: ArrayList<IClasspathDependency>) {
@ -167,7 +145,7 @@ class Dependencies(val project: Project,
* future tasks receive a get(), the repos will be correct. * future tasks receive a get(), the repos will be correct.
*/ */
private fun addToDependencies(project: Project, dependencies: ArrayList<IClasspathDependency>, private fun addToDependencies(project: Project, dependencies: ArrayList<IClasspathDependency>,
dep: Array<out String>, optional: Boolean = false, excludeConfig: ExcludeConfig? = null): List<Future<File>> dep: Array<out String>, optional: Boolean = false): List<Future<File>>
= with(dep.map { = with(dep.map {
val resolved = val resolved =
if (KobaltMavenResolver.isRangeVersion(it)) { if (KobaltMavenResolver.isRangeVersion(it)) {
@ -182,73 +160,12 @@ class Dependencies(val project: Project,
DependencyManager.create(resolved, optional, project.directory) DependencyManager.create(resolved, optional, project.directory)
}) { }) {
dependencies.addAll(this) dependencies.addAll(this)
if (excludeConfig != null) {
this.forEach { it.excluded.add(excludeConfig) }
}
this.map { FutureTask { it.jarFile.get() } } this.map { FutureTask { it.jarFile.get() } }
} }
@Directive @Directive
fun compile(vararg dep: String) = addToDependencies(project, dependencies, dep) fun compile(vararg dep: String) = addToDependencies(project, dependencies, dep)
class ExcludeConfig {
val ids = arrayListOf<String>()
@Directive
fun exclude(vararg passedIds: String) = ids.addAll(passedIds)
class ArtifactConfig(
var groupId: String? = null,
var artifactId: String? = null,
var version: String? = null
)
val artifacts = arrayListOf<ArtifactConfig>()
@Directive
fun exclude(groupId: String? = null, artifactId: String? = null, version: String? = null)
= artifacts.add(ArtifactConfig(groupId, artifactId, version))
fun match(pattern: String?, id: String) : Boolean {
return pattern == null || Pattern.compile(pattern).matcher(id).matches()
}
/**
* @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
}
}
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 @Directive
fun compileOptional(vararg dep: String) { fun compileOptional(vararg dep: String) {
addToDependencies(project, optionalDependencies, dep, optional = true) addToDependencies(project, optionalDependencies, dep, optional = true)
@ -258,6 +175,7 @@ class Dependencies(val project: Project,
@Directive @Directive
fun provided(vararg dep: String) { fun provided(vararg dep: String) {
addToDependencies(project, providedDependencies, dep) addToDependencies(project, providedDependencies, dep)
addToDependencies(project, dependencies, dep)
} }
@Directive @Directive

View file

@ -44,25 +44,6 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme
} }
} }
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(),
runAfter : List<String> = emptyList(),
alwaysRunAfter: List<String> = emptyList(),
runTask: (Project) -> TaskResult) {
dynamicTasks.add(DynamicTask(plugin, taskName, description, group, project,
dependsOn = dependsOn,
reverseDependsOn = reverseDependsOn,
runBefore = runBefore,
runAfter = runAfter,
alwaysRunAfter = alwaysRunAfter,
closure = { p: 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, group: String = AnnotationDefault.GROUP,
dependsOn: List<String> = emptyList(), dependsOn: List<String> = emptyList(),

View file

@ -1,24 +1,25 @@
package com.beust.kobalt.archive package com.beust.kobalt.archive
import com.beust.kobalt.* import com.beust.kobalt.Features
import com.beust.kobalt.IFileSpec
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.ExportedProjectProperty import com.beust.kobalt.api.annotation.ExportedProjectProperty
import com.beust.kobalt.misc.JarUtils import com.beust.kobalt.misc.*
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.kobaltLog
import java.io.File import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.util.* import java.util.*
import java.util.zip.ZipOutputStream
class Archives { class Archives {
companion object { companion object {
@ExportedProjectProperty(doc = "The name of the jar file", type = "String") @ExportedProjectProperty(doc = "The name of the jar file", type = "String")
const val JAR_NAME = "jarName" 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 + private val DEFAULT_STREAM_FACTORY = { os : OutputStream -> ZipOutputStream(os) }
if (project.version.isNullOrBlank()) "" else "-${project.version}"
fun defaultArchiveName(project: Project) = project.name + "-" + project.version
fun generateArchive(project: Project, fun generateArchive(project: Project,
context: KobaltContext, context: KobaltContext,
@ -26,15 +27,15 @@ class Archives {
suffix: String, suffix: String,
includedFiles: List<IncludedFile>, includedFiles: List<IncludedFile>,
expandJarFiles : Boolean = false, expandJarFiles : Boolean = false,
manifest: java.util.jar.Manifest? = null) : File { outputStreamFactory: (OutputStream) -> ZipOutputStream = DEFAULT_STREAM_FACTORY) : File {
val fullArchiveName = context.variant.archiveName(project, archiveName, suffix) val fullArchiveName = context.variant.archiveName(project, archiveName, suffix)
val archiveDir = File(KFiles.libsDir(project)) val archiveDir = File(KFiles.libsDir(project))
val result = File(archiveDir.path, fullArchiveName) val result = File(archiveDir.path, fullArchiveName)
context.logger.log(project.name, 3, "Creating $result") context.logger.log(project.name, 3, "Creating $result")
if (! Features.USE_TIMESTAMPS || isOutdated(project.directory, includedFiles, result)) { if (! Features.USE_TIMESTAMPS || isOutdated(project.directory, includedFiles, result)) {
try { try {
MetaArchive(result, manifest).use { metaArchive -> outputStreamFactory(FileOutputStream(result)).use {
JarUtils.addFiles(project.directory, includedFiles, metaArchive, expandJarFiles) JarUtils.addFiles(project.directory, includedFiles, it, expandJarFiles)
context.logger.log(project.name, 2, "Added ${includedFiles.size} files to $result") context.logger.log(project.name, 2, "Added ${includedFiles.size} files to $result")
context.logger.log(project.name, 1, " Created $result") context.logger.log(project.name, 1, " Created $result")
} }

View file

@ -8,7 +8,7 @@ import com.beust.kobalt.api.annotation.Directive
*/ */
open class Jar(override val project: Project, open class Jar(override val project: Project,
override var name : String = Archives.defaultArchiveName(project) + ".jar", override var name : String = Archives.defaultArchiveName(project) + ".jar",
override var fatJar: Boolean = false) : Zip(project, name, fatJar), AttributeHolder { var fatJar: Boolean = false) : Zip(project, name), AttributeHolder {
@Directive @Directive
fun manifest(init: Manifest.(p: Manifest) -> Unit) : Manifest { fun manifest(init: Manifest.(p: Manifest) -> Unit) : Manifest {
val m = Manifest(this) val m = Manifest(this)
@ -18,7 +18,7 @@ open class Jar(override val project: Project,
// Need to specify the version or attributes will just be dropped // Need to specify the version or attributes will just be dropped
@Directive @Directive
override val attributes = arrayListOf(Pair("Manifest-Version", "1.0")) val attributes = arrayListOf(Pair("Manifest-Version", "1.0"))
override fun addAttribute(k: String, v: String) { override fun addAttribute(k: String, v: String) {
attributes.add(Pair(k, v)) attributes.add(Pair(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)
}
}
}

View file

@ -1,13 +1,22 @@
package com.beust.kobalt.archive package com.beust.kobalt.archive
import com.beust.kobalt.* import com.beust.kobalt.Glob
import com.beust.kobalt.IFileSpec
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
import com.beust.kobalt.misc.From
import com.beust.kobalt.misc.IncludedFile
import com.beust.kobalt.misc.To
open class Zip(open val project: Project, open var name: String = Archives.defaultArchiveName(project) + ".zip", open class Zip(open val project: Project, open var name: String = Archives.defaultArchiveName(project) + ".zip") {
open var fatJar: Boolean = false): AttributeHolder, IncludeFromTo() {
val excludes = arrayListOf<Glob>() val excludes = arrayListOf<Glob>()
@Directive
fun from(s: String) = From(s)
@Directive
fun to(s: String) = To(s)
@Directive @Directive
fun exclude(vararg files: String) { fun exclude(vararg files: String) {
files.forEach { excludes.add(Glob(it)) } files.forEach { excludes.add(Glob(it)) }
@ -19,9 +28,26 @@ open class Zip(open val project: Project, open var name: String = Archives.defau
} }
@Directive @Directive
open val attributes = arrayListOf(Pair("Manifest-Version", "1.0")) fun include(vararg files: String) {
includedFiles.add(IncludedFile(files.map { IFileSpec.FileSpec(it) }))
}
override fun addAttribute(k: String, v: String) { @Directive
attributes.add(Pair(k, v)) 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)))
} }
/**
* 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>()
}

View file

@ -1,6 +1,7 @@
package com.beust.kobalt.internal package com.beust.kobalt.internal
import com.beust.kobalt.api.IProjectAffinity import com.beust.kobalt.api.IProjectAffinity
import com.beust.kobalt.api.ISimpleAffinity
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
@ -18,5 +19,11 @@ class ActorUtils {
fun <T : IProjectAffinity> selectAffinityActors(project: Project, context: KobaltContext, actors: List<T>) fun <T : IProjectAffinity> selectAffinityActors(project: Project, context: KobaltContext, actors: List<T>)
= actors.filter { it.affinity(project, context) > 0 } = actors.filter { it.affinity(project, context) > 0 }
.sortedByDescending { it.affinity(project, context) } .sortedByDescending { it.affinity(project, context) }
/**
* Return the plug-in actor with the highest affinity.
*/
fun <T : ISimpleAffinity<A>, A> selectAffinityActor(actors: List<T>, arg: A) = actors.maxBy { it.affinity(arg) }
} }
} }

View file

@ -1,7 +1,5 @@
package com.beust.kobalt.internal package com.beust.kobalt.internal
import com.beust.kobalt.TestResult
import com.beust.kobalt.api.IBuildListener
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.api.ProjectBuildStatus import com.beust.kobalt.api.ProjectBuildStatus
@ -27,14 +25,9 @@ abstract class BaseProjectRunner {
} }
fun runBuildListenersForTask(project: Project, context: KobaltContext, taskName: String, start: Boolean, fun runBuildListenersForTask(project: Project, context: KobaltContext, taskName: String, start: Boolean,
success: Boolean = false, testResult: TestResult? = null) { success: Boolean = false) {
context.pluginInfo.buildListeners.forEach { context.pluginInfo.buildListeners.forEach {
if (start) { if (start) it.taskStart(project, context, taskName) else it.taskEnd(project, context, taskName, success)
it.taskStart(project, context, taskName)
} else {
val info = IBuildListener.TaskEndInfo(success, testResult?.shortMessage, testResult?.longMessage)
it.taskEnd(project, context, taskName, info)
}
} }
} }

View file

@ -11,8 +11,7 @@ import java.util.concurrent.ConcurrentHashMap
*/ */
class BuildListeners : IBuildListener, IBuildReportContributor { class BuildListeners : IBuildListener, IBuildReportContributor {
class ProfilerInfo(val taskName: String, val durationMillis: Long) class ProfilerInfo(val taskName: String, val durationMillis: Long)
class ProjectInfo(val projectName: String, var durationMillis: Long = 0, class ProjectInfo(val projectName: String, var durationMillis: Long = 0)
var shortMessage: String? = null, var longMessage: String? = null)
private val startTimes = ConcurrentHashMap<String, Long>() private val startTimes = ConcurrentHashMap<String, Long>()
private val timings = arrayListOf<ProfilerInfo>() private val timings = arrayListOf<ProfilerInfo>()
@ -30,21 +29,18 @@ class BuildListeners : IBuildListener, IBuildReportContributor {
} }
// IBuildListener // IBuildListener
override fun taskEnd(project: Project, context: KobaltContext, taskName: String, info: IBuildListener.TaskEndInfo) { override fun taskEnd(project: Project, context: KobaltContext, taskName: String, success: Boolean) {
val success = info.success
if (! success) hasFailures = true if (! success) hasFailures = true
startTimes[taskName]?.let { startTimes[taskName]?.let {
val taskTime = System.currentTimeMillis() - it val taskTime = System.currentTimeMillis() - it
timings.add(ProfilerInfo(taskName, taskTime)) timings.add(ProfilerInfo(taskName, taskTime))
projectInfos[project.name]?.let { projectInfos[project.name]?.let {
it.durationMillis += taskTime it.durationMillis += taskTime.toLong()
if (info.shortMessage != null && it.shortMessage == null) it.shortMessage = info.shortMessage
if (info.longMessage != null && it.longMessage == null) it.longMessage = info.longMessage
} }
} }
} }
private val projectStatuses = arrayListOf<Pair<Project, String>>() private val projectStatuses = arrayListOf<Pair<Project, ProjectBuildStatus>>()
// IBuildListener // IBuildListener
override fun projectStart(project: Project, context: KobaltContext) { override fun projectStart(project: Project, context: KobaltContext) {
@ -53,9 +49,7 @@ class BuildListeners : IBuildListener, IBuildReportContributor {
// IBuildListener // IBuildListener
override fun projectEnd(project: Project, context: KobaltContext, status: ProjectBuildStatus) { override fun projectEnd(project: Project, context: KobaltContext, status: ProjectBuildStatus) {
val shortMessage = projectInfos[project.name]?.shortMessage projectStatuses.add(Pair(project, status))
val statusText = status.toString() + (if (shortMessage != null) " ($shortMessage)" else "")
projectStatuses.add(Pair(project, statusText))
} }
// IBuildReportContributor // IBuildReportContributor
@ -76,15 +70,10 @@ class BuildListeners : IBuildListener, IBuildReportContributor {
} }
// Calculate the longest short message so we can create a column long enough to contain it
val width = 12 + (projectInfos.values.map { it.shortMessage?.length ?: 0 }.maxBy { it } ?: 0)
fun col1(s: String) = String.format(" %1\$-30s", s) fun col1(s: String) = String.format(" %1\$-30s", s)
fun col2(s: String) = String.format(" %1\$-${width}s", s) fun col2(s: String) = String.format(" %1\$-13s", s)
fun col3(s: String) = String.format(" %1\$-8s", s) fun col3(s: String) = String.format(" %1\$-8s", s)
// Only print the build report if there is more than one project and at least one of them failed // Only print the build report if there is more than one project and at least one of them failed
if (timings.any()) { if (timings.any()) {
// if (timings.size > 1 && hasFailures) { // if (timings.size > 1 && hasFailures) {
@ -94,7 +83,7 @@ class BuildListeners : IBuildListener, IBuildReportContributor {
table.append(AsciiArt.logBox(listOf(line), AsciiArt.bottomLeft2, AsciiArt.bottomRight2, indent = 10) + "\n") table.append(AsciiArt.logBox(listOf(line), AsciiArt.bottomLeft2, AsciiArt.bottomRight2, indent = 10) + "\n")
projectStatuses.forEach { pair -> projectStatuses.forEach { pair ->
val projectName = pair.first.name val projectName = pair.first.name
val cl = listOf(col1(projectName), col2(pair.second), val cl = listOf(col1(projectName), col2(pair.second.toString()),
col3(formatMillisLeft(projectInfos[projectName]!!.durationMillis, 8))) col3(formatMillisLeft(projectInfos[projectName]!!.durationMillis, 8)))
.joinToString(AsciiArt.verticalBar) .joinToString(AsciiArt.verticalBar)
table.append(" " + AsciiArt.verticalBar + " " + cl + " " + AsciiArt.verticalBar + "\n") table.append(" " + AsciiArt.verticalBar + " " + cl + " " + AsciiArt.verticalBar + "\n")

View file

@ -30,7 +30,7 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
} }
val sourceFiles = KFiles.findSourceFiles(project.directory, val sourceFiles = KFiles.findSourceFiles(project.directory,
contributedSourceDirs.map { it.path }, compiler.sourceSuffixes) contributedSourceDirs.map { it.path }, compiler.sourceSuffixes)
if (sourceFiles.isNotEmpty()) { if (sourceFiles.size > 0) {
// TODO: createCompilerActionInfo recalculates the source files, only compute them // TODO: createCompilerActionInfo recalculates the source files, only compute them
// once and pass them // once and pass them
val info = createCompilerActionInfo(project, context, compiler, isTest, val info = createCompilerActionInfo(project, context, compiler, isTest,
@ -70,17 +70,14 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
copyResources(project, context, SourceSet.of(isTest)) copyResources(project, context, SourceSet.of(isTest))
val fullClasspath = dependencyManager.calculateDependencies(project, context, val fullClasspath = dependencyManager.calculateDependencies(project, context,
scopes = if (isTest) { scopes = listOf(Scope.COMPILE, Scope.TEST))
listOf(Scope.COMPILE, Scope.COMPILEONLY, Scope.TEST)
} else {
listOf(Scope.COMPILE, Scope.COMPILEONLY)
})
File(project.directory, buildDirectory.path).mkdirs() File(project.directory, buildDirectory.path).mkdirs()
// Remove all the excluded dependencies from the classpath // Remove all the excluded dependencies from the classpath
var classpath = fullClasspath var classpath = fullClasspath.filter {
! isDependencyExcluded(it, project.excludedDependencies)
}
// The classpath needs to contain $buildDirectory/classes as well so that projects that contain // The classpath needs to contain $buildDirectory/classes as well so that projects that contain
// multiple languages can use classes compiled by the compiler run before them. // multiple languages can use classes compiled by the compiler run before them.
@ -124,8 +121,7 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
// depending on the compiler's ability, sourceFiles can actually contain a list of directories // depending on the compiler's ability, sourceFiles can actually contain a list of directories
// instead of individual source files. // instead of individual source files.
val projectDirectory = File(project.directory) val projectDirectory = File(project.directory)
val sourceFiles = val sourceFiles = if (compiler.canCompileDirectories) {
if (compiler.canCompileDirectories) {
allSourceDirectories.map { File(projectDirectory, it.path).path } allSourceDirectories.map { File(projectDirectory, it.path).path }
} else { } else {
files.findRecursively(projectDirectory, allSourceDirectories, files.findRecursively(projectDirectory, allSourceDirectories,
@ -173,7 +169,7 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
// Finally, alter the info with the compiler interceptors before returning it // Finally, alter the info with the compiler interceptors before returning it
val initialActionInfo = CompilerActionInfo(projectDirectory.path, classpath, allSources, val initialActionInfo = CompilerActionInfo(projectDirectory.path, classpath, allSources,
sourceSuffixes, buildDirectory, emptyList() /* the flags will be provided by flag contributors */, sourceSuffixes, buildDirectory, emptyList() /* the flags will be provided by flag contributors */,
emptyList(), context.internalContext.forceRecompile) emptyList())
val result = context.pluginInfo.compilerInterceptors.fold(initialActionInfo, { ai, interceptor -> val result = context.pluginInfo.compilerInterceptors.fold(initialActionInfo, { ai, interceptor ->
interceptor.intercept(project, context, ai) interceptor.intercept(project, context, ai)
}) })
@ -201,7 +197,7 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
.filter(File::exists) .filter(File::exists)
.forEach { .forEach {
context.logger.log(project.name, 2, "Copying from $it to $absOutputDir") context.logger.log(project.name, 2, "Copying from $it to $absOutputDir")
KFiles.copyRecursively(it, absOutputDir, replaceExisting = true) KFiles.copyRecursively(it, absOutputDir, deleteFirst = false)
} }
} else { } else {
context.logger.log(project.name, 2, "No resources to copy for $sourceSet") context.logger.log(project.name, 2, "No resources to copy for $sourceSet")
@ -229,4 +225,15 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
} }
return result return result
} }
companion object {
/**
* Naïve implementation: just exclude all dependencies that start with one of the excluded dependencies.
* Should probably make exclusion more generic (full on string) or allow exclusion to be specified
* formally by groupId or artifactId.
*/
fun isDependencyExcluded(dep: IClasspathDependency, excluded: List<IClasspathDependency>)
= excluded.any { excluded -> dep.id.startsWith(excluded.id) }
}
} }

View file

@ -2,7 +2,7 @@ package com.beust.kobalt.internal
class DocUrl { class DocUrl {
companion object { companion object {
private const val HOST = "https://beust.com/kobalt/" private const val HOST = "http://beust.com/kobalt/"
private fun url(path: String) = HOST + path private fun url(path: String) = HOST + path
val PUBLISH_PLUGIN_URL = url("plug-ins/index.html#publishing") val PUBLISH_PLUGIN_URL = url("plug-ins/index.html#publishing")

View file

@ -1,14 +1,18 @@
package com.beust.kobalt.internal package com.beust.kobalt.internal
import com.beust.kobalt.* import com.beust.kobalt.AsciiTable
import com.beust.kobalt.misc.* import com.beust.kobalt.KobaltException
import com.beust.kobalt.TaskResult
import com.beust.kobalt.misc.NamedThreadFactory
import com.beust.kobalt.misc.error
import com.beust.kobalt.misc.kobaltLog
import com.beust.kobalt.misc.warn
import com.google.common.collect.HashMultimap import com.google.common.collect.HashMultimap
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.util.* import java.util.*
import java.util.concurrent.* import java.util.concurrent.*
open class TaskResult2<T>(success: Boolean, testResult: TestResult? = null, open class TaskResult2<T>(success: Boolean, errorMessage: String?, val value: T) : TaskResult(success, errorMessage) {
errorMessage: String? = null, val value: T) : TaskResult(success, testResult, errorMessage) {
override fun toString() = com.beust.kobalt.misc.toString("TaskResult", "value", value, "success", success) override fun toString() = com.beust.kobalt.misc.toString("TaskResult", "value", value, "success", success)
} }
@ -299,14 +303,14 @@ class DynamicGraphExecutor<T>(val graph : DynamicGraph<T>, val factory: IThreadW
duration = " (" + ((hl.timestamp - start) / 1000) duration = " (" + ((hl.timestamp - start) / 1000)
.toInt().toString() + ")" .toInt().toString() + ")"
} else { } else {
kobaltLog(1, "DONOTCOMMIT") println("DONOTCOMMIT")
} }
} }
return hl.name + duration return hl.name + duration
} }
historyLog.forEach { hl -> historyLog.forEach { hl ->
kobaltLog(1, "CURRENT LOG: " + currentLog + " HISTORY LINE: " + hl) println("CURRENT LOG: " + currentLog + " HISTORY LINE: " + hl)
if (hl.start) { if (hl.start) {
projectStart[hl.name] = hl.timestamp projectStart[hl.name] = hl.timestamp
} }
@ -314,10 +318,10 @@ class DynamicGraphExecutor<T>(val graph : DynamicGraph<T>, val factory: IThreadW
currentLog = CompressedLog(hl.timestamp, hashMapOf(hl.threadId to hl.name)) currentLog = CompressedLog(hl.timestamp, hashMapOf(hl.threadId to hl.name))
} else currentLog?.let { cl -> } else currentLog?.let { cl ->
if (! hl.start || hl.timestamp - cl.timestamp < 1000) { if (! hl.start || hl.timestamp - cl.timestamp < 1000) {
kobaltLog(1, " CURRENT LOG IS WITHING ONE SECOND: $hl") println(" CURRENT LOG IS WITHING ONE SECOND: $hl")
cl.threadMap[hl.threadId] = toName(hl) cl.threadMap[hl.threadId] = toName(hl)
} else { } else {
kobaltLog(1, " ADDING COMPRESSED LINE $cl") println(" ADDING COMPRESSED LINE $cl")
compressed.add(cl) compressed.add(cl)
currentLog = CompressedLog(hl.timestamp, hashMapOf(hl.threadId to toName(hl))) currentLog = CompressedLog(hl.timestamp, hashMapOf(hl.threadId to toName(hl)))
} }
@ -374,7 +378,7 @@ class DynamicGraphExecutor<T>(val graph : DynamicGraph<T>, val factory: IThreadW
return table return table
} }
kobaltLog(1, displayRegularLog(table).build()) println(displayRegularLog(table).build())
} }
} }
@ -394,7 +398,7 @@ fun main(argv: Array<String>) {
object: IWorker<String> { object: IWorker<String> {
override fun call(): TaskResult2<String>? { override fun call(): TaskResult2<String>? {
kobaltLog(1, " Running worker $it") kobaltLog(1, " Running worker $it")
return TaskResult2(true, value = it) return TaskResult2(true, null, it)
} }
override val priority: Int get() = 0 override val priority: Int get() = 0

View file

@ -4,7 +4,6 @@ import com.beust.kobalt.*
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.google.common.annotations.VisibleForTesting import com.google.common.annotations.VisibleForTesting
import com.google.inject.Inject
import java.io.File import java.io.File
import java.util.* import java.util.*
@ -16,27 +15,14 @@ abstract class GenericTestRunner: ITestRunnerContributor {
abstract val dependencyName : String abstract val dependencyName : String
abstract val mainClass: String abstract val mainClass: String
abstract val annotationPackage: String abstract val annotationPackage: String
abstract val runnerName: String
open var shortMessage: String? = null
open var longMessage: String? = null
@Inject
private lateinit var jvm: Jvm
abstract fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, abstract fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) : List<String> testConfig: TestConfig) : List<String>
open fun onFinish(project: Project) {} open fun filterTestClasses(classes: List<String>) : List<String> = classes
open val extraClasspath: List<String> = emptyList()
open fun filterTestClasses(project: Project, context: KobaltContext, classes: List<String>) : List<String> = classes
override fun run(project: Project, context: KobaltContext, configName: String, override fun run(project: Project, context: KobaltContext, configName: String,
classpath: List<IClasspathDependency>) : TaskResult { classpath: List<IClasspathDependency>)
val tr = runTests(project, context, classpath, configName) = TaskResult(runTests(project, context, classpath, configName))
return TaskResult(tr.success, testResult = tr)
}
override fun affinity(project: Project, context: KobaltContext) : Int { override fun affinity(project: Project, context: KobaltContext) : Int {
val result = val result =
@ -69,7 +55,7 @@ abstract class GenericTestRunner: ITestRunnerContributor {
// } // }
context.logger.log(project.name, 2, "Found ${result.size} test classes") context.logger.log(project.name, 2, "Found ${result.size} test classes")
return filterTestClasses(project, context, result.map { it.second }) return filterTestClasses(result.map { it.second })
} }
/** /**
@ -108,20 +94,17 @@ abstract class GenericTestRunner: ITestRunnerContributor {
/** /**
* @return true if all the tests passed * @return true if all the tests passed
*/ */
open fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
configName: String) : TestResult { configName: String) : Boolean {
var result = false var result = false
context.logger.log(project.name, 1, "Running tests with $runnerName")
val testConfig = project.testConfigs.firstOrNull { it.name == configName } val testConfig = project.testConfigs.firstOrNull { it.name == configName }
var errorCode = -1
if (testConfig != null) { if (testConfig != null) {
val args = args(project, context, classpath, testConfig) val args = args(project, context, classpath, testConfig)
if (args.size > 0) { if (args.size > 0) {
val java = jvm.javaExecutable val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable
val jvmArgs = calculateAllJvmArgs(project, context, testConfig, classpath, val jvmArgs = calculateAllJvmArgs(project, context, testConfig, classpath,
Kobalt.INJECTOR.getInstance (PluginInfo::class.java)) Kobalt.INJECTOR.getInstance (PluginInfo::class.java))
val allArgs = arrayListOf<String>().apply { val allArgs = arrayListOf<String>().apply {
@ -137,7 +120,12 @@ abstract class GenericTestRunner: ITestRunnerContributor {
context.logger.log(project.name, 2, "Running tests with classpath size ${classpath.size}") context.logger.log(project.name, 2, "Running tests with classpath size ${classpath.size}")
context.logger.log(project.name, 2, "Launching " + allArgs.joinToString(" ")) context.logger.log(project.name, 2, "Launching " + allArgs.joinToString(" "))
val process = pb.start() val process = pb.start()
errorCode = process.waitFor() val errorCode = process.waitFor()
if (errorCode == 0) {
context.logger.log(project.name, 1, "All tests passed")
} else {
context.logger.log(project.name, 1, "Test failures")
}
result = result || errorCode == 0 result = result || errorCode == 0
} else { } else {
context.logger.log(project.name, 1, " No tests to run") context.logger.log(project.name, 1, " No tests to run")
@ -146,16 +134,7 @@ abstract class GenericTestRunner: ITestRunnerContributor {
} else { } else {
throw KobaltException("Couldn't find a test configuration named \"$configName\"") throw KobaltException("Couldn't find a test configuration named \"$configName\"")
} }
return result
onFinish(project)
if (errorCode == 0) {
context.logger.log(project.name, 1, "All tests passed")
} else {
context.logger.log(project.name, 1, longMessage!!)
}
return TestResult(result, shortMessage, longMessage)
} }
/* /*
@ -164,13 +143,12 @@ abstract class GenericTestRunner: ITestRunnerContributor {
@VisibleForTesting @VisibleForTesting
fun calculateAllJvmArgs(project: Project, context: KobaltContext, fun calculateAllJvmArgs(project: Project, context: KobaltContext,
testConfig: TestConfig, classpath: List<IClasspathDependency>, pluginInfo: IPluginInfo) : List<String> { testConfig: TestConfig, classpath: List<IClasspathDependency>, pluginInfo: IPluginInfo) : List<String> {
val fullClasspath = classpath.map { it.jarFile.get().absolutePath } + extraClasspath
// Default JVM args // Default JVM args
val jvmFlags = arrayListOf<String>().apply { val jvmFlags = arrayListOf<String>().apply {
addAll(testConfig.jvmArgs) addAll(testConfig.jvmArgs)
add("-ea") add("-ea")
add("-classpath") add("-classpath")
add(fullClasspath.joinToString(File.pathSeparator)) add(classpath.map { it.jarFile.get().absolutePath }.joinToString(File.pathSeparator))
} }
// JVM flags from the contributors // JVM flags from the contributors

View file

@ -1,152 +0,0 @@
package com.beust.kobalt.internal
import com.beust.jcommander.JCommander
import com.beust.jcommander.Parameter
import com.beust.kobalt.TestConfig
import com.beust.kobalt.api.IAffinity
import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.KobaltLogger
import com.google.inject.Inject
import org.junit.platform.engine.TestExecutionResult
import org.junit.platform.engine.discovery.DiscoverySelectors
import org.junit.platform.engine.reporting.ReportEntry
import org.junit.platform.engine.support.descriptor.MethodSource
import org.junit.platform.launcher.LauncherDiscoveryRequest
import org.junit.platform.launcher.TestExecutionListener
import org.junit.platform.launcher.TestIdentifier
import org.junit.platform.launcher.TestPlan
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder
import org.junit.platform.launcher.core.LauncherFactory
import java.io.File
import java.nio.file.Paths
/**
* Runner for JUnit 5 tests. This class also contains a main() entry point since JUnit 5 no longer supplies one.
*/
class JUnit5Runner @Inject constructor(kFiles: KFiles) : GenericTestRunner() {
override val dependencyName = "jupiter"
override val annotationPackage = "org.junit.jupiter.api"
override val mainClass = "com.beust.kobalt.internal.JUnit5RunnerKt"
override val runnerName = "JUnit 5"
override fun affinity(project: Project, context: KobaltContext) : Int {
val result =
if (project.testDependencies.any { it.id.contains("junit5") || it.id.contains("jupiter") })
IAffinity.DEFAULT_POSITIVE_AFFINITY + 100
else 0
return result
}
override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, testConfig: TestConfig): List<String> {
val testClassDir = KFiles.joinDir(project.buildDirectory, KFiles.TEST_CLASSES_DIR)
val classDir = KFiles.joinDir(project.buildDirectory, KFiles.CLASSES_DIR)
val args = listOf("--testClassDir", testClassDir,
"--classDir", classDir,
"--log", KobaltLogger.LOG_LEVEL.toString())
return args
}
override val extraClasspath = kFiles.kobaltJar
}
private class Args {
@Parameter(names = arrayOf("--log"))
var log: Int = 1
@Parameter(names = arrayOf("--testClassDir"))
var testClassDir: String = "kobaltBuild/test-classes"
@Parameter(names = arrayOf("--classDir"))
var classDir: String = "kobaltBuild/classes"
}
fun main(argv: Array<String>) {
val args = Args()
val jc = JCommander(args)
jc.parse(*argv)
val testClassDir = File(args.testClassDir).absolutePath
val classDir = File(args.classDir).absolutePath
val request : LauncherDiscoveryRequest = LauncherDiscoveryRequestBuilder()
.selectors(DiscoverySelectors.selectClasspathRoots(setOf(
Paths.get(testClassDir),
Paths.get(classDir)
)))
.selectors(DiscoverySelectors.selectDirectory(testClassDir))
.build()
fun testName(id: TestIdentifier) : String? {
val result =
if (id.source.isPresent) {
val source = id.source.get()
if (source is MethodSource) {
source.className + "." + source.methodName
} else {
null
}
} else {
null
}
return result
}
var passed = 0
var failed = 0
var skipped = 0
var aborted = 0
fun log(level: Int, s: String) {
if (level <= args.log) println(s)
}
val listener = object: TestExecutionListener {
override fun executionFinished(testIdentifier: TestIdentifier, testExecutionResult: TestExecutionResult) {
val testName = testName(testIdentifier)
if (testName != null) {
when(testExecutionResult.status) {
TestExecutionResult.Status.FAILED -> {
log(1, "FAILED: $testName, reason: " + testExecutionResult.throwable.get().toString())
failed++
}
TestExecutionResult.Status.ABORTED -> {
log(1, "ABORTED: $testName, reason: " + testExecutionResult.throwable.get().toString())
aborted++
}
TestExecutionResult.Status.SUCCESSFUL -> {
log(2, "PASSED: $testName")
passed++
} else -> {
}
}
}
}
override fun executionSkipped(testIdentifier: TestIdentifier, reason: String) {
testName(testIdentifier)?.let {
log(1, "Skipping $it because $reason")
skipped++
}
}
override fun executionStarted(testIdentifier: TestIdentifier) {
testName(testIdentifier)?.let {
log(2, "Starting $it")
}
}
override fun testPlanExecutionStarted(testPlan: TestPlan?) {}
override fun dynamicTestRegistered(testIdentifier: TestIdentifier?) {}
override fun reportingEntryPublished(testIdentifier: TestIdentifier?, entry: ReportEntry?) {}
override fun testPlanExecutionFinished(testPlan: TestPlan?) {}
}
LauncherFactory.create().execute(request, listener)
log(1, "TEST RESULTS: $passed PASSED, $failed FAILED, $skipped SKIPPED, $aborted ABORTED")
}

View file

@ -4,29 +4,16 @@ import com.beust.kobalt.TestConfig
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.DependencyManager
import com.google.inject.Inject
import java.lang.reflect.Modifier
import java.net.URLClassLoader
open class JUnitRunner() : GenericTestRunner() { open class JUnitRunner() : GenericTestRunner() {
override val mainClass = "org.junit.runner.JUnitCore" override val mainClass = "org.junit.runner.JUnitCore"
override val annotationPackage = "org.junit" override val annotationPackage = "org.junit"
override val dependencyName = "junit" override val dependencyName = "junit"
override val runnerName = "JUnit 4"
override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) = findTestClasses(project, context, testConfig) testConfig: TestConfig) = findTestClasses(project, context, testConfig)
@Inject
lateinit var dependencyManager: DependencyManager
override fun filterTestClasses(project: Project, context: KobaltContext, classes: List<String>) : List<String> {
val deps = dependencyManager.testDependencies(project, context)
val cl = URLClassLoader(deps.map { it.jarFile.get().toURI().toURL() }.toTypedArray())
return classes.filter { !Modifier.isAbstract(cl.loadClass(it).modifiers) }
}
} }

View file

@ -23,11 +23,12 @@ class JvmCompiler @Inject constructor(val dependencyManager: DependencyManager)
flags: List<String>): TaskResult { flags: List<String>): TaskResult {
// Dependencies // Dependencies
val allDependencies = (info.dependencies + dependencyManager.calculateDependencies(project, context!!, val allDependencies = (info.dependencies
passedDependencies = info.dependencies)) + dependencyManager.calculateDependencies(project, context!!, passedDependencies = info.dependencies))
.distinct() .distinct()
// Plugins that add flags to the compiler // Plugins that add flags to the compiler
val currentFlags = arrayListOf<String>().apply { addAll(info.compilerArgs) }
val contributorFlags : List<String> = if (project != null) flags else emptyList() val contributorFlags : List<String> = if (project != null) flags else emptyList()
val addedFlags = contributorFlags + ArrayList(info.compilerArgs) val addedFlags = contributorFlags + ArrayList(info.compilerArgs)

View file

@ -9,6 +9,7 @@ import com.beust.kobalt.api.annotation.ExportedProjectProperty
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.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.Md5 import com.beust.kobalt.maven.Md5
import com.beust.kobalt.maven.aether.Scope import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
@ -26,6 +27,7 @@ import javax.inject.Singleton
*/ */
@Singleton @Singleton
open class JvmCompilerPlugin @Inject constructor( open class JvmCompilerPlugin @Inject constructor(
open val localRepo: LocalRepo,
open val files: KFiles, open val files: KFiles,
open val dependencyManager: DependencyManager, open val dependencyManager: DependencyManager,
open val executors: KobaltExecutors, open val executors: KobaltExecutors,
@ -86,11 +88,12 @@ open class JvmCompilerPlugin @Inject constructor(
if (testContributor != null && testContributor.affinity(project, context) > 0) { if (testContributor != null && testContributor.affinity(project, context) > 0) {
// val td1 = dependencyManager.testDependencies(project, context) // val td1 = dependencyManager.testDependencies(project, context)
val testDependencies = dependencyManager.calculateDependencies(project, context, val testDependencies = dependencyManager.calculateDependencies(project, context,
dependencyFilter = dependencyManager.createDependencyFilter(project, project.testDependencies),
scopes = listOf(Scope.TEST)) scopes = listOf(Scope.TEST))
val compileDependencies = dependencyManager.calculateDependencies(project, context, val compileDependencies = dependencyManager.calculateDependencies(project, context,
scopes = listOf(Scope.COMPILE, Scope.COMPILEONLY)) scopes = listOf(Scope.COMPILE))
val allDependencies = (testDependencies + compileDependencies).distinct() val allDependencies = (compileDependencies + testDependencies)
.toHashSet()
.filter { ! CompilerUtils.isDependencyExcluded(it, project.excludedDependencies) }
return testContributor.run(project, context, configName, allDependencies.toList()) return testContributor.run(project, context, configName, allDependencies.toList())
} else { } else {
context.logger.log(project.name, 2, context.logger.log(project.name, 2,
@ -157,10 +160,6 @@ open class JvmCompilerPlugin @Inject constructor(
if (compilerContributors.isEmpty()) { if (compilerContributors.isEmpty()) {
throw KobaltException("Couldn't find any compiler for project ${project.name}") throw KobaltException("Couldn't find any compiler for project ${project.name}")
} else { } else {
// Generate BuildConfig if applicable
context.variant.maybeGenerateBuildConfig(project, context)
val allCompilers = compilerContributors.flatMap { it.compilersFor(project, context)}.sorted() val allCompilers = compilerContributors.flatMap { it.compilersFor(project, context)}.sorted()
/** /**
@ -174,10 +173,7 @@ open class JvmCompilerPlugin @Inject constructor(
if (wi.value.sourceSuffixes.contains("java")) ij = wi.index if (wi.value.sourceSuffixes.contains("java")) ij = wi.index
if (wi.value.sourceSuffixes.contains("kt")) ik = wi.index if (wi.value.sourceSuffixes.contains("kt")) ik = wi.index
} }
if (ik >= 0 && ij >= 0) {
Collections.swap(result, ik, ij) Collections.swap(result, ik, ij)
}
return result return result
} }
@ -187,8 +183,8 @@ open class JvmCompilerPlugin @Inject constructor(
var done = false var done = false
// The directory where the classes get compiled // The directory where the classes get compiled
val buildDirectory = val buildDirectory =
if (isTest) File(KFiles.joinDir(project.buildDirectory, KFiles.TEST_CLASSES_DIR)) if (isTest) File(project.buildDirectory, KFiles.TEST_CLASSES_DIR)
else File(KFiles.joinDir(project.classesDir(context))) else File(project.classesDir(context))
allCompilersSorted.doWhile({ ! done }) { compiler -> allCompilersSorted.doWhile({ ! done }) { compiler ->
val compilerResults = compilerUtils.invokeCompiler(project, context, compiler, val compilerResults = compilerUtils.invokeCompiler(project, context, compiler,
@ -225,8 +221,7 @@ open class JvmCompilerPlugin @Inject constructor(
} }
} }
@Task(name = "doc", description = "Generate the documentation for the project", group = GROUP_DOCUMENTATION, @Task(name = "doc", description = "Generate the documentation for the project", group = GROUP_DOCUMENTATION)
runBefore = arrayOf("assemble"), runAfter = arrayOf("clean"))
fun taskJavadoc(project: Project): TaskResult { fun taskJavadoc(project: Project): TaskResult {
val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors) val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors)
if (docGenerator != null) { if (docGenerator != null) {

View file

@ -72,13 +72,13 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
val plugins = arrayListOf<IPlugin>() val plugins = arrayListOf<IPlugin>()
val projectContributors = arrayListOf<IProjectContributor>() val projectContributors = arrayListOf<IProjectContributor>()
val classpathContributors = arrayListOf<IClasspathContributor>() val classpathContributors = arrayListOf<IClasspathContributor>()
val templateContributors = arrayListOf<ITemplateContributor>() val initContributors = arrayListOf<ITemplateContributor>()
val repoContributors = arrayListOf<IRepoContributor>() val repoContributors = arrayListOf<IRepoContributor>()
val compilerFlagContributors = arrayListOf<ICompilerFlagContributor>() val compilerFlagContributors = arrayListOf<ICompilerFlagContributor>()
val compilerInterceptors = arrayListOf<ICompilerInterceptor>() val compilerInterceptors = arrayListOf<ICompilerInterceptor>()
val sourceDirectoriesInterceptors = arrayListOf<ISourceDirectoryInterceptor>() val sourceDirectoriesInterceptors = arrayListOf<ISourceDirectoryInterceptor>()
val buildDirectoryInterceptors = arrayListOf<IBuildDirectoryInterceptor>() val buildDirectoryInterceptors = arrayListOf<IBuildDirectoryInterceptor>()
// val runnerContributors = arrayListOf<IRunnerContributor>() val runnerContributors = arrayListOf<IRunnerContributor>()
val testRunnerContributors = arrayListOf<ITestRunnerContributor>() val testRunnerContributors = arrayListOf<ITestRunnerContributor>()
val classpathInterceptors = arrayListOf<IClasspathInterceptor>() val classpathInterceptors = arrayListOf<IClasspathInterceptor>()
val compilerContributors = arrayListOf<ICompilerContributor>() val compilerContributors = arrayListOf<ICompilerContributor>()
@ -193,11 +193,11 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
if (this is ICompilerFlagContributor) compilerFlagContributors.add(this) if (this is ICompilerFlagContributor) compilerFlagContributors.add(this)
if (this is ICompilerInterceptor) compilerInterceptors.add(this) if (this is ICompilerInterceptor) compilerInterceptors.add(this)
if (this is IDocContributor) docContributors.add(this) if (this is IDocContributor) docContributors.add(this)
if (this is ITemplateContributor) templateContributors.add(this) if (this is ITemplateContributor) initContributors.add(this)
if (this is IPlugin) plugins.add(this) if (this is IPlugin) plugins.add(this)
if (this is IProjectContributor) projectContributors.add(this) if (this is IProjectContributor) projectContributors.add(this)
if (this is IRepoContributor) repoContributors.add(this) if (this is IRepoContributor) repoContributors.add(this)
// if (this is IRunnerContributor) runnerContributors.add(this) if (this is IRunnerContributor) runnerContributors.add(this)
if (this is ISourceDirectoryContributor) sourceDirContributors.add(this) if (this is ISourceDirectoryContributor) sourceDirContributors.add(this)
if (this is ISourceDirectoryInterceptor) sourceDirectoriesInterceptors.add(this) if (this is ISourceDirectoryInterceptor) sourceDirectoriesInterceptors.add(this)
if (this is ITaskContributor) taskContributors.add(this) if (this is ITaskContributor) taskContributors.add(this)
@ -222,10 +222,10 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
} }
fun cleanUp() { fun cleanUp() {
listOf(projectContributors, classpathContributors, templateContributors, listOf(projectContributors, classpathContributors, initContributors,
repoContributors, compilerFlagContributors, compilerInterceptors, repoContributors, compilerFlagContributors, compilerInterceptors,
sourceDirectoriesInterceptors, buildDirectoryInterceptors, sourceDirectoriesInterceptors, buildDirectoryInterceptors,
/* runnerContributors, */ testRunnerContributors, classpathInterceptors, runnerContributors, testRunnerContributors, classpathInterceptors,
compilerContributors, docContributors, sourceDirContributors, compilerContributors, docContributors, sourceDirContributors,
testSourceDirContributors, buildConfigFieldContributors, testSourceDirContributors, buildConfigFieldContributors,
taskContributors, incrementalTaskContributors, assemblyContributors, taskContributors, incrementalTaskContributors, assemblyContributors,
@ -246,13 +246,13 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
plugins.addAll(pluginInfo.plugins) plugins.addAll(pluginInfo.plugins)
classpathContributors.addAll(pluginInfo.classpathContributors) classpathContributors.addAll(pluginInfo.classpathContributors)
projectContributors.addAll(pluginInfo.projectContributors) projectContributors.addAll(pluginInfo.projectContributors)
templateContributors.addAll(pluginInfo.templateContributors) initContributors.addAll(pluginInfo.initContributors)
repoContributors.addAll(pluginInfo.repoContributors) repoContributors.addAll(pluginInfo.repoContributors)
compilerFlagContributors.addAll(pluginInfo.compilerFlagContributors) compilerFlagContributors.addAll(pluginInfo.compilerFlagContributors)
compilerInterceptors.addAll(pluginInfo.compilerInterceptors) compilerInterceptors.addAll(pluginInfo.compilerInterceptors)
sourceDirectoriesInterceptors.addAll(pluginInfo.sourceDirectoriesInterceptors) sourceDirectoriesInterceptors.addAll(pluginInfo.sourceDirectoriesInterceptors)
buildDirectoryInterceptors.addAll(pluginInfo.buildDirectoryInterceptors) buildDirectoryInterceptors.addAll(pluginInfo.buildDirectoryInterceptors)
// runnerContributors.addAll(pluginInfo.runnerContributors) runnerContributors.addAll(pluginInfo.runnerContributors)
testRunnerContributors.addAll(pluginInfo.testRunnerContributors) testRunnerContributors.addAll(pluginInfo.testRunnerContributors)
classpathInterceptors.addAll(pluginInfo.classpathInterceptors) classpathInterceptors.addAll(pluginInfo.classpathInterceptors)
compilerContributors.addAll(pluginInfo.compilerContributors) compilerContributors.addAll(pluginInfo.compilerContributors)

View file

@ -25,7 +25,7 @@ class KobaltSettingsXml {
@XmlElement(name = "localMavenRepo") @JvmField @XmlElement(name = "localMavenRepo") @JvmField
var localMavenRepo: String = homeDir(KFiles.KOBALT_DOT_DIR, "localMavenRepo") var localMavenRepo: String = homeDir(KFiles.KOBALT_DOT_DIR, "localMavenRepo")
@XmlElement(name = "defaultRepos") @JvmField @XmlElement(name = "defaulRepos") @JvmField
var defaultRepos: DefaultReposXml? = null var defaultRepos: DefaultReposXml? = null
@XmlElement(name = "proxies") @JvmField @XmlElement(name = "proxies") @JvmField
@ -42,9 +42,6 @@ class KobaltSettingsXml {
@XmlElement(name = "kobaltCompilerSeparateProcess") @JvmField @XmlElement(name = "kobaltCompilerSeparateProcess") @JvmField
var kobaltCompilerSeparateProcess: Boolean = false var kobaltCompilerSeparateProcess: Boolean = false
@XmlElement(name = "autoUpdate") @JvmField
var autoUpdate: Boolean = false
} }
class ProxiesXml { class ProxiesXml {
@ -88,11 +85,6 @@ class KobaltSettings @Inject constructor(val xmlFile: KobaltSettingsXml) {
*/ */
val localMavenRepo = KFiles.makeDir(xmlFile.localMavenRepo) val localMavenRepo = KFiles.makeDir(xmlFile.localMavenRepo)
/**
* If true, Kobalt will automatically update itself if a new version is found.
*/
val autoUpdate = xmlFile.autoUpdate
/** /**
* If true, the Kotlin compiler will always be launched in a separate JVM, even if the requested * If true, the Kotlin compiler will always be launched in a separate JVM, even if the requested
* version is the same as the internal version. * version is the same as the internal version.

View file

@ -16,5 +16,6 @@ class KotlinJarFiles @Inject constructor(val dependencyManager: DependencyManage
} }
val stdlib: File get() = getKotlinCompilerJar("stdlib") val stdlib: File get() = getKotlinCompilerJar("stdlib")
val runtime: File get() = getKotlinCompilerJar("runtime")
val compiler: File get() = getKotlinCompilerJar("compiler-embeddable") val compiler: File get() = getKotlinCompilerJar("compiler-embeddable")
} }

View file

@ -1,21 +1,16 @@
package com.beust.kobalt.internal package com.beust.kobalt.internal
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
/** /**
* KotlinTestRunner triggers if it finds a dependency on io.kotlintest but other than that, it just * KotlinTestRunner triggers if it finds a dependency on io.kotlintest but other than that, it just
* uses the regular JUnitRunner. * uses the regular JUnitRunner.
*/ */
class KotlinTestRunner : JUnitRunner() { class KotlinTestRunner : JUnitRunner() {
override val dependencyName = "io.kotlintest" override val dependencyName = "io.kotlintest"
override val runnerName = "Kotlin Test"
/** /**
* KotlinTestRunner runs tests in the init{} initializer, so ignore all the extra * KotlinTestRunner runs tests in the init{} initializer, so ignore all the extra
* classes generated by the Kotlin compiler. * classes generated by the Kotlin compiler.
*/ */
override fun filterTestClasses(projet: Project, context: KobaltContext, classes: List<String>) override fun filterTestClasses(classes: List<String>) = classes.filter { ! it.contains("$") }
= classes.filter { !it.contains("$") }
} }

View file

@ -2,7 +2,9 @@ package com.beust.kobalt.internal
import com.beust.kobalt.Args import com.beust.kobalt.Args
import com.beust.kobalt.KobaltException import com.beust.kobalt.KobaltException
import com.beust.kobalt.misc.* import com.beust.kobalt.misc.kobaltError
import com.beust.kobalt.misc.kobaltLog
import com.beust.kobalt.misc.kobaltWarn
import com.google.inject.Inject import com.google.inject.Inject
import com.google.inject.Singleton import com.google.inject.Singleton
import java.util.* import java.util.*
@ -65,9 +67,9 @@ class ParallelLogger @Inject constructor(val args: Args) : ILogger {
} }
private fun debug(s: CharSequence) { private fun debug(s: CharSequence) {
if (args.log >= 3) { if (args.log >= 2) {
val time = System.currentTimeMillis() - startTime!! val time = System.currentTimeMillis() - startTime!!
kobaltLog(1, " ### [$time] $s") println(" ### [$time] $s")
} }
} }
@ -125,6 +127,6 @@ class ParallelLogger @Inject constructor(val args: Args) : ILogger {
runningProjects.forEach { runningProjects.forEach {
emptyProjectLog(it) emptyProjectLog(it)
} }
kobaltLog(1, "") println("")
} }
} }

View file

@ -54,12 +54,12 @@ class ParallelProjectRunner(val tasksByNames: (Project) -> ListMultimap<String,
runBuildListenersForTask(project, context, task.name, start = true) runBuildListenersForTask(project, context, task.name, start = true)
logger.log(project.name, 1, logger.log(project.name, 1,
AsciiArt.taskColor(AsciiArt.horizontalSingleLine + " ${project.name}:${task.name}")) AsciiArt.taskColor(AsciiArt.horizontalSingleLine + " ${project.name}:${task.name}"))
val thisResult = if (dryRun) TaskResult2(true, value = task) else task.call() val thisResult = if (dryRun) TaskResult2(true, null, task) else task.call()
if (lastResult.success) { if (lastResult.success) {
lastResult = thisResult lastResult = thisResult
} }
runBuildListenersForTask(project, context, task.name, start = false, runBuildListenersForTask(project, context, task.name, start = false,
success = thisResult.success, testResult = thisResult.testResult) success = thisResult.success)
} }
} }
graph.freeNodes.forEach { graph.removeNode(it) } graph.freeNodes.forEach { graph.removeNode(it) }
@ -69,7 +69,7 @@ class ParallelProjectRunner(val tasksByNames: (Project) -> ListMultimap<String,
runBuildListenersForProject(project, context, false, runBuildListenersForProject(project, context, false,
if (lastResult.success) ProjectBuildStatus.SUCCESS else ProjectBuildStatus.FAILED) if (lastResult.success) ProjectBuildStatus.SUCCESS else ProjectBuildStatus.FAILED)
return TaskResult2(lastResult.success, errorMessage = lastResult.errorMessage, value = this) return TaskResult2(lastResult.success, lastResult.errorMessage, this)
} }
} }
@ -94,7 +94,7 @@ class ParallelProjectRunner(val tasksByNames: (Project) -> ListMultimap<String,
val projectGraph = DynamicGraph<ProjectTask>().apply { val projectGraph = DynamicGraph<ProjectTask>().apply {
projects.forEach { project -> projects.forEach { project ->
addNode(ProjectTask(project, args.dryRun)) addNode(ProjectTask(project, args.dryRun))
project.allProjectDependedOn().forEach { project.dependsOn.forEach {
addEdge(ProjectTask(project, args.dryRun), ProjectTask(it, args.dryRun)) addEdge(ProjectTask(project, args.dryRun), ProjectTask(it, args.dryRun))
} }
} }

View file

@ -39,7 +39,7 @@ class SequentialProjectRunner(val tasksByNames: (Project) -> ListMultimap<String
klog(1, AsciiArt.logBox("Building $projectName", indent = 5)) klog(1, AsciiArt.logBox("Building $projectName", indent = 5))
// Does the current project depend on any failed projects? // Does the current project depend on any failed projects?
val fp = project.allProjectDependedOn().filter { failedProjects.contains(it.name) }.map(Project::name) val fp = project.dependsOn.filter { failedProjects.contains(it.name) }.map(Project::name)
if (fp.size > 0) { if (fp.size > 0) {
klog(2, "Marking project $projectName as skipped") klog(2, "Marking project $projectName as skipped")

View file

@ -6,6 +6,5 @@ package com.beust.kobalt.internal
*/ */
class SpekRunner : JUnitRunner() { class SpekRunner : JUnitRunner() {
override val dependencyName = "org.jetbrains.spek" override val dependencyName = "org.jetbrains.spek"
override val runnerName = "Spek"
} }

View file

@ -17,7 +17,7 @@ import javax.inject.Singleton
@Singleton @Singleton
class TaskManager @Inject constructor(val args: Args, class TaskManager @Inject constructor(val args: Args,
val incrementalManagerFactory: IncrementalManager.IFactory, val incrementalManagerFactory: IncrementalManager.IFactory,
val kobaltLog: ParallelLogger) { val pluginInfo: PluginInfo, val kobaltLog: ParallelLogger) {
private val dependsOn = TreeMultimap.create<String, String>() private val dependsOn = TreeMultimap.create<String, String>()
private val reverseDependsOn = TreeMultimap.create<String, String>() private val reverseDependsOn = TreeMultimap.create<String, String>()
private val runBefore = TreeMultimap.create<String, String>() private val runBefore = TreeMultimap.create<String, String>()
@ -80,9 +80,6 @@ class TaskManager @Inject constructor(val args: Args,
} }
} }
// @Inject
// lateinit var pluginInfo: PluginInfo
fun runTargets(passedTaskNames: List<String>, allProjects: List<Project>): RunTargetResult { fun runTargets(passedTaskNames: List<String>, allProjects: List<Project>): RunTargetResult {
// Check whether tasks passed at command line exist // Check whether tasks passed at command line exist
passedTaskNames.forEach { passedTaskNames.forEach {
@ -90,7 +87,6 @@ class TaskManager @Inject constructor(val args: Args,
throw KobaltException("Unknown task: $it") throw KobaltException("Unknown task: $it")
} }
val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java)
var taskInfos = calculateDependentTaskNames(passedTaskNames, allProjects) var taskInfos = calculateDependentTaskNames(passedTaskNames, allProjects)
// Remove non existing tasks (e.g. dynamic task defined for a single project) // Remove non existing tasks (e.g. dynamic task defined for a single project)
@ -149,7 +145,7 @@ class TaskManager @Inject constructor(val args: Args,
val topological = Topological<Project>().apply { val topological = Topological<Project>().apply {
projects.forEach { project -> projects.forEach { project ->
addNode(project) addNode(project)
project.allProjectDependedOn().forEach { project.dependsOn.forEach {
addEdge(project, it) addEdge(project, it)
} }
} }
@ -164,7 +160,7 @@ class TaskManager @Inject constructor(val args: Args,
return result return result
} else { } else {
val rootProject = projects.find { it.name == ti.project }!! val rootProject = projects.find { it.name == ti.project }!!
val allProjects = DynamicGraph.transitiveClosure(rootProject, Project::allProjectDependedOn) val allProjects = DynamicGraph.transitiveClosure(rootProject, { p -> p.dependsOn })
val sortedProjects = sortProjectsTopologically(allProjects) val sortedProjects = sortProjectsTopologically(allProjects)
val sortedMaps = sortedProjects.map { TaskInfo(it.name, "compile")} val sortedMaps = sortedProjects.map { TaskInfo(it.name, "compile")}
val result = sortedMaps.subList(0, sortedMaps.size - 1) + listOf(ti) val result = sortedMaps.subList(0, sortedMaps.size - 1) + listOf(ti)
@ -272,8 +268,7 @@ class TaskManager @Inject constructor(val args: Args,
object : BasePluginTask(plugin, name, description, group, project) { object : BasePluginTask(plugin, name, description, group, project) {
override fun call(): TaskResult2<ITask> { override fun call(): TaskResult2<ITask> {
val taskResult = task(project) val taskResult = task(project)
return TaskResult2(taskResult.success, errorMessage = taskResult.errorMessage, value = this, return TaskResult2(taskResult.success, taskResult.errorMessage, this)
testResult = taskResult.testResult)
} }
}) })
dependsOn.forEach { dependsOn(it, name) } dependsOn.forEach { dependsOn(it, name) }
@ -320,11 +315,9 @@ class TaskWorker(val tasks: List<ITask>, val dryRun: Boolean, val pluginInfo: Pl
val tr = if (dryRun) TaskResult() else it.call() val tr = if (dryRun) TaskResult() else it.call()
BaseProjectRunner.runBuildListenersForTask(it.project, context, name, start = false, success = tr.success) BaseProjectRunner.runBuildListenersForTask(it.project, context, name, start = false, success = tr.success)
success = success and tr.success success = success and tr.success
tr.errorMessage?.let { if (tr.errorMessage != null) errorMessages.add(tr.errorMessage)
errorMessages.add(it)
} }
} return TaskResult2(success, errorMessages.joinToString("\n"), tasks[0])
return TaskResult2(success, errorMessage = errorMessages.joinToString("\n"), value = tasks[0])
} }
// override val timeOut : Long = 10000 // override val timeOut : Long = 10000

View file

@ -1,53 +1,28 @@
package com.beust.kobalt.internal package com.beust.kobalt.internal
import com.beust.kobalt.AsciiArt
import com.beust.kobalt.TestConfig import com.beust.kobalt.TestConfig
import com.beust.kobalt.TestResult
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.aether.AetherDependency import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.* import com.beust.kobalt.misc.warn
import org.testng.remote.RemoteArgs
import org.testng.remote.strprotocol.JsonMessageSender
import org.testng.remote.strprotocol.MessageHelper
import org.testng.remote.strprotocol.MessageHub
import org.testng.remote.strprotocol.TestResultMessage
import org.w3c.dom.Attr
import org.w3c.dom.NodeList
import org.xml.sax.InputSource
import java.io.File import java.io.File
import java.io.FileReader
import java.io.IOException
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.XPathConstants
import javax.xml.xpath.XPathFactory
class TestNgRunner : GenericTestRunner() { class TestNgRunner : GenericTestRunner() {
override val mainClass = "org.testng.TestNG" override val mainClass = "org.testng.TestNG"
override val dependencyName = "testng"
override val annotationPackage = "org.testng"
override val runnerName = "TestNG"
private fun defaultOutputWithoutProjectDir(project: Project) override val dependencyName = "testng"
= KFiles.joinDir(project.buildDirectory, "test-output")
private fun defaultOutput(project: Project) override val annotationPackage = "org.testng"
= KFiles.joinDir(project.directory, project.buildDirectory, "test-output")
fun defaultOutput(project: Project) = KFiles.joinDir(project.buildDirectory, "test-output")
override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) = arrayListOf<String>().apply { testConfig: TestConfig) = arrayListOf<String>().apply {
var addOutput = true
if (KobaltLogger.isQuiet) { testConfig.testArgs.forEach { arg ->
add("-log") if (arg == "-d") addOutput = false
add("0")
}
if (testConfig.testArgs.none { it == "-d" }) {
add("-d")
// Don't include the project directory here since the generic runner will cd to that directory before
// running the tests
add(defaultOutputWithoutProjectDir(project))
} }
if (testConfig.testArgs.size == 0) { if (testConfig.testArgs.size == 0) {
@ -57,7 +32,11 @@ class TestNgRunner : GenericTestRunner() {
add(testngXml.absolutePath) add(testngXml.absolutePath)
} else { } else {
val testClasses = findTestClasses(project, context, testConfig) val testClasses = findTestClasses(project, context, testConfig)
if (testClasses.isNotEmpty()) { if (testClasses.size > 0) {
if (addOutput) {
add("-d")
add(defaultOutput(project))
}
addAll(testConfig.testArgs) addAll(testConfig.testArgs)
add("-testclass") add("-testclass")
@ -69,200 +48,11 @@ class TestNgRunner : GenericTestRunner() {
} }
} }
} else { } else {
if (addOutput) {
add("-d")
add(defaultOutput(project))
}
addAll(testConfig.testArgs) addAll(testConfig.testArgs)
} }
} }
/**
* Extract test results from testng-results.xml and initialize shortMessage.
*/
override fun onFinish(project: Project) {
File(defaultOutput(project), "testng-results.xml").let { file ->
val ins = InputSource(FileReader(file))
val doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(ins)
val root = doc.documentElement
var failed = 0
var skipped = 0
var passed = 0
val xp = XPathFactory.newInstance().newXPath()
val testMethods = xp.compile("/testng-results/suite/test/class/test-method[@status='FAIL']")
.evaluate(doc, XPathConstants.NODESET)
as NodeList
val failedMethods = arrayListOf<String>()
repeat(testMethods.length) {
val tm = testMethods.item(it)
failedMethods.add(tm.attributes.getNamedItem("signature").textContent)
}
repeat(root.attributes.length) {
val attribute = root.attributes.item(it)
if (attribute is Attr) when (attribute.name) {
"failed" -> failed = Integer.parseInt(attribute.value)
"skipped" -> skipped = Integer.parseInt(attribute.value)
"passed" -> passed = Integer.parseInt(attribute.value)
}
}
if (failed == 0) {
shortMessage = "$passed tests"
} else if (failed > 0) {
shortMessage = "$failed failed" + (if (skipped > 0) ", $skipped skipped" else "") + " tests"
longMessage = "Failed tests:\n " + failedMethods.joinToString("\n ")
}
}
}
val VERSION_6_10 = StringVersion("6.10")
fun _runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
// override fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
configName: String): TestResult {
val testConfig = project.testConfigs.firstOrNull { it.name == configName }
if (testConfig != null) {
context.logger.log(project.name, 1, "Running enhanced TestNG runner")
val testngDependency = (project.testDependencies.filter { it.id.contains("testng") }
.firstOrNull() as AetherDependency).version
val versions = findRemoteRunnerVersion(testngDependency)
val useOldRunner = System.getProperty("testng.oldRunner") != null
val result =
if (versions != null && ! useOldRunner) {
context.logger.log(project.name, 1, "Modern TestNG, displaying colors")
displayPrettyColors(project, context, classpath, testConfig, versions)
} else {
context.logger.log(project.name, 1, "Older TestNG ($testngDependency), using the old runner")
super.runTests(project, context, classpath, configName)
}
return result
} else {
return TestResult(true)
}
}
private fun findRemoteRunnerVersion(testngVersion: String) : Pair<String, String>? {
val tng = StringVersion(testngVersion)
val result =
if (tng >= VERSION_6_10) Pair(testngVersion, "testng-remote6_10")
else if (tng >= StringVersion("6.9.10")) Pair("6.9.10", "testng-remote6_9_10")
else if (tng >= StringVersion("6.9.7")) Pair("6.9.7", "testng-remote6_9_7")
else if (tng >= StringVersion("6.5.1")) Pair("6.5.1", "testng-remote6_5_0")
else if (tng >= StringVersion("6.0")) Pair("6.0", "testng-remote6_0")
else null
return result
}
private fun displayPrettyColors(project: Project, context: KobaltContext,
classpath: List<IClasspathDependency>, testConfig: TestConfig, versions: Pair<String, String>)
: TestResult {
val port = 2345
// launchRemoteServer(project, context, classpath, testConfig, versions, port)
val mh = MessageHub(JsonMessageSender("localhost", port, true))
mh.setDebug(true)
mh.initReceiver()
val passed = arrayListOf<String>()
data class FailedTest(val method: String, val cls: String, val stackTrace: String)
val failed = arrayListOf<FailedTest>()
val skipped = arrayListOf<String>()
fun d(n: Int, color: String)
= AsciiArt.wrap(String.format("%4d", n), color)
fun red(s: String) = AsciiArt.wrap(s, AsciiArt.RED)
fun green(s: String) = AsciiArt.wrap(s, AsciiArt.GREEN)
fun yellow(s: String) = AsciiArt.wrap(s, AsciiArt.YELLOW)
try {
var message = mh.receiveMessage()
kobaltLog(1, "")
kobaltLog(1, green("PASSED") + " | " + red("FAILED") + " | " + yellow("SKIPPED"))
while (message != null) {
message = mh.receiveMessage()
if (message is TestResultMessage) {
when (message.result) {
MessageHelper.PASSED_TEST -> passed.add(message.name)
MessageHelper.FAILED_TEST -> failed.add(FailedTest(message.testClass,
message.method, message.stackTrace))
MessageHelper.SKIPPED_TEST -> skipped.add(message.name)
}
}
if (!KobaltLogger.isQuiet) {
print("\r " + d(passed.size, AsciiArt.GREEN)
+ " | " + d(failed.size, AsciiArt.RED)
+ " | " + d(skipped.size, AsciiArt.YELLOW))
}
}
} catch(ex: IOException) {
kobaltLog(1, "Exception: ${ex.message}")
}
kobaltLog(1, "\nPassed: " + passed.size + ", Failed: " + failed.size + ", Skipped: " + skipped.size)
failed.forEach {
val top = it.stackTrace.substring(0, it.stackTrace.indexOf("\n"))
kobaltLog(1, " " + it.cls + "." + it.method + "\n " + top)
}
return TestResult(failed.isEmpty() && skipped.isEmpty())
}
fun launchRemoteServer(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig, versions: Pair<String, String>, port: Int) {
val testngVersion = versions.first
val remoteRunnerVersion = versions.second
val dep = with(context.dependencyManager) {
val jf = create("org.testng.testng-remote:testng-remote:1.3.0")
val tr = create("org.testng.testng-remote:$remoteRunnerVersion:1.3.0")
val testng = create("org.testng:testng:6.11")
transitiveClosure(kotlin.collections.listOf(jf, tr /*, testng */))
}
val cp = (classpath + dep).distinct().map { it.jarFile.get() }
.joinToString(File.pathSeparator)
val calculatedArgs = args(project, context, classpath, testConfig)
val jvmArgs = arrayListOf("-classpath", cp)
if (testConfig.jvmArgs.any()) {
jvmArgs.addAll(testConfig.jvmArgs)
}
val remoteArgs = listOf(
"org.testng.remote.RemoteTestNG",
"-serport", port.toString(),
"-version", testngVersion,
"-dontexit",
RemoteArgs.PROTOCOL,
"json")
val passedArgs = jvmArgs + remoteArgs + calculatedArgs
Thread {
runCommand {
command = "java"
directory = File(project.directory)
args = passedArgs
}
}.start()
// Thread {
// val args2 = arrayOf("-serport", port.toString(), "-dontexit", RemoteArgs.PROTOCOL, "json",
// "-version", "6.10",
// "src/test/resources/testng.xml")
// RemoteTestNG.main(args2)
// }.start()
}
}
fun main(args: Array<String>) {
fun d(n: Int, color: String)
= AsciiArt.wrap(String.format("%4d", n), color)
if (!KobaltLogger.isQuiet) {
println("PASSED | FAILED | SKIPPED")
repeat(20) { i ->
print("\r " + d(i, AsciiArt.GREEN) + " | " + d(i * 2, AsciiArt.RED) + " | " + d(i, AsciiArt.YELLOW))
Thread.sleep(500)
}
println("")
}
} }

View file

@ -1,8 +1,10 @@
package com.beust.kobalt.internal.build package com.beust.kobalt.internal.build
import com.beust.kobalt.misc.KFiles
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.attribute.BasicFileAttributes
/** /**
* Sometimes, build files are moved to temporary files, so we give them a specific name for clarity. * Sometimes, build files are moved to temporary files, so we give them a specific name for clarity.
* @param path is the path where that file was moved, @param realPath is where the actual file is. * @param path is the path where that file was moved, @param realPath is where the actual file is.
@ -10,5 +12,23 @@ import java.nio.file.Path
class BuildFile(val path: Path, val name: String, val realPath: Path = path) { class BuildFile(val path: Path, val name: String, val realPath: Path = path) {
fun exists() : Boolean = Files.exists(path) fun exists() : Boolean = Files.exists(path)
val lastModified : Long
get() = Files.readAttributes(realPath, BasicFileAttributes::class.java).lastModifiedTime().toMillis()
val directory : File get() = path.toFile().parentFile val directory : File get() = path.toFile().parentFile
/**
* @return the .kobalt directory where this build file will be compiled.
*/
val dotKobaltDir: File get() = File(directory.parentFile.parentFile, KFiles.KOBALT_DOT_DIR).apply {
mkdirs()
}
/**
* @return the absolute directory of this project's location, assuming the build file is in
* $project/kobalt/src/Build.kt.
*/
val absoluteDir : File? get() {
return path.parent?.parent?.parent?.toFile()
}
} }

View file

@ -1,61 +0,0 @@
package com.beust.kobalt.internal.build
import com.beust.kobalt.homeDir
import java.io.File
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes
/**
* The abstraction to represent a directory that contains source files. @param{root} is typically
* the root of the project and build files are searched under root/kobalt/src/ *kt.
*/
interface IBuildSources {
fun findSourceFiles() : List<File>
val root: File
fun exists(): Boolean
}
class SingleFileBuildSources(val file: File) : IBuildSources {
override fun exists() = file.exists()
override fun findSourceFiles() = listOf(file)
override val root: File = file.parentFile.parentFile.parentFile
override fun toString() : String = file.path
}
class BuildSources(val file: File = File("")) : IBuildSources {
override val root = file
override fun findSourceFiles() : List<File> {
return findBuildFiles(listOf(file))
}
override fun exists() = findSourceFiles().isNotEmpty()
override fun toString() = "{BuildSources " + findSourceFiles().joinToString(", ") + "}"
fun findBuildFiles(roots: List<File>) : List<File> {
val result = arrayListOf<File>()
roots.forEach { file ->
Files.walkFileTree(Paths.get(file.path), object : SimpleFileVisitor<Path>() {
override fun preVisitDirectory(dir: Path?, attrs: BasicFileAttributes?): FileVisitResult {
if (dir != null) {
val path = dir.toFile()
if (path.name == "src" && path.parentFile.name == "kobalt") {
val sources = path.listFiles().filter { it.name.endsWith(".kt") }
result.addAll(sources)
}
}
return FileVisitResult.CONTINUE
}
})
}
return result
}
}
fun main(args: Array<String>) {
val sources = BuildSources(File(homeDir("kotlin/kobalt"))).findSourceFiles()
println("sources: " + sources)
}

View file

@ -0,0 +1,14 @@
package com.beust.kobalt.internal.remote
import com.beust.kobalt.Constants
import java.io.PrintWriter
import java.net.Socket
fun main(argv: Array<String>) {
Socket("localhost", 1234).use { socket ->
(PrintWriter(socket.outputStream, true)).use { out ->
out.println("""{ "name" : "getDependencies", "buildFile":
"/Users/beust/kotlin/kobalt/kobalt/src/${Constants.BUILD_FILE_NAME}"}""")
}
}
}

View file

@ -70,14 +70,12 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
/** /**
* @return the source dependencies for this project, including the contributors. * @return the source dependencies for this project, including the contributors.
*/ */
override fun dependencies(project: Project, context: KobaltContext, scopes: List<Scope>) override fun dependencies(project: Project, context: KobaltContext) = dependencies(project, context, false)
= privateDependencies(project, context, listOf(Scope.COMPILE))
/** /**
* @return the test dependencies for this project, including the contributors. * @return the test dependencies for this project, including the contributors.
*/ */
override fun testDependencies(project: Project, context: KobaltContext) override fun testDependencies(project: Project, context: KobaltContext) = dependencies(project, context, true)
= privateDependencies(project, context, listOf(Scope.COMPILE, Scope.TEST))
/** /**
* Transitive dependencies for the compilation of this project. * Transitive dependencies for the compilation of this project.
@ -87,10 +85,8 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
// project.compileDependencies + project.compileRuntimeDependencies) // project.compileDependencies + project.compileRuntimeDependencies)
/** /**
* @return the classpath for this project, including the IClasspathContributors. Excluded dependencies * @return the classpath for this project, including the IClasspathContributors.
* are removed from the result. * allDependencies is typically either compileDependencies or testDependencies. If no dependencies
*
* @param{allDependencies} is typically either compileDependencies or testDependencies. If no dependencies
* are passed, they are calculated from the scope filters. * are passed, they are calculated from the scope filters.
*/ */
override fun calculateDependencies(project: Project?, context: KobaltContext, override fun calculateDependencies(project: Project?, context: KobaltContext,
@ -106,10 +102,6 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
val result = arrayListOf<IClasspathDependency>().apply { val result = arrayListOf<IClasspathDependency>().apply {
if (scopes.contains(Scope.COMPILE)) { if (scopes.contains(Scope.COMPILE)) {
addAll(project.compileDependencies) addAll(project.compileDependencies)
addAll(project.compileProvidedDependencies)
}
if (scopes.contains(Scope.COMPILEONLY)) {
addAll(project.compileOnlyDependencies)
} }
if (scopes.contains(Scope.RUNTIME)) { if (scopes.contains(Scope.RUNTIME)) {
addAll(project.compileRuntimeDependencies) addAll(project.compileRuntimeDependencies)
@ -138,30 +130,10 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
result.addAll(runClasspathContributors(project, context)) result.addAll(runClasspathContributors(project, context))
result.addAll(dependentProjectDependencies(project, context, dependencyFilter, scopes)) result.addAll(dependentProjectDependencies(project, context, dependencyFilter, scopes))
/**
* Naïve implementation: just exclude all dependencies that start with one of the excluded dependencies.
* Should probably make exclusion more generic (full on string) or allow exclusion to be specified
* formally by groupId or artifactId.
*/
fun isDependencyExcluded(dep: IClasspathDependency, excluded: List<IClasspathDependency>): Boolean {
excluded.any { excluded -> dep.id == excluded.id }.let { result ->
if (result) {
context.logger.log(project?.name ?: "", 2, " Excluding dependency $dep")
}
return result
}
}
// Dependencies get reordered by transitiveClosure() but since we just added a bunch of new ones, // Dependencies get reordered by transitiveClosure() but since we just added a bunch of new ones,
// we need to reorder them again in case we're adding dependencies that are already present // we need to reorder them again in case we're adding dependencies that are already present
// but with a different version // but with a different version
val shortResult = val reordered = reorderDependencies(result)
if (project != null) {
result.filter { ! isDependencyExcluded(it, project.excludedDependencies) }
} else {
result
}.toHashSet()
val reordered = reorderDependencies(shortResult)
return reordered return reordered
} }
@ -179,14 +151,14 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
* TODO: This should be private, everyone should be calling calculateDependencies(). * TODO: This should be private, everyone should be calling calculateDependencies().
*/ */
fun transitiveClosure(dependencies : List<IClasspathDependency>, fun transitiveClosure(dependencies : List<IClasspathDependency>,
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER, dependencyFilter: DependencyFilter? = null,
requiredBy: String? = null): List<IClasspathDependency> { requiredBy: String? = null): List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>() val result = arrayListOf<IClasspathDependency>()
dependencies.forEach { dependency -> dependencies.forEach {
result.add(dependency) result.add(it)
if (dependency.isMaven) { if (it.isMaven) {
val resolved = resolver.resolveToIds(dependency.id, null, filter).map { create(it) } val resolved = resolver.resolveToIds(it.id, null, dependencyFilter)
result.addAll(resolved) result.addAll(resolved.map { create(it) })
} }
} }
val reordered = reorderDependencies(result) val reordered = reorderDependencies(result)
@ -232,45 +204,30 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
} }
} }
val isTest = scopes.contains(Scope.TEST)
project.dependsOn.forEach { p -> project.dependsOn.forEach { p ->
maybeAddClassDir(KFiles.joinDir(p.directory, p.classesDir(context))) maybeAddClassDir(KFiles.joinDir(p.directory, p.classesDir(context)))
val isTest = scopes.contains(Scope.TEST)
if (isTest) maybeAddClassDir(KFiles.makeOutputTestDir(project).path) if (isTest) maybeAddClassDir(KFiles.makeOutputTestDir(project).path)
val otherDependencies = calculateDependencies(p, context, dependencyFilter, scopes) val otherDependencies = calculateDependencies(p, context, dependencyFilter, scopes)
result.addAll(otherDependencies) result.addAll(otherDependencies)
}
if (isTest) {
project.testsDependOn.forEach { p ->
val otherDependencies = calculateDependencies(p, context, dependencyFilter, scopes)
result.addAll(otherDependencies)
}
} }
return result return result
} }
} }
private fun privateDependencies(project: Project, context: KobaltContext, passedScopes: List<Scope>) private fun dependencies(project: Project, context: KobaltContext, isTest: Boolean)
: List<IClasspathDependency> { : List<IClasspathDependency> {
val isTest = passedScopes.contains(Scope.TEST)
val transitive = hashSetOf<IClasspathDependency>() val transitive = hashSetOf<IClasspathDependency>()
with(project) { with(project) {
val scopeFilters : ArrayList<Scope> = arrayListOf(Scope.COMPILE) val scopeFilters : ArrayList<Scope> = arrayListOf(Scope.COMPILE)
context.variant.let { variant -> context.variant.let { variant ->
val deps: ArrayList<ArrayList<IClasspathDependency>> = val deps = arrayListOf(compileDependencies, compileProvidedDependencies,
if (passedScopes.contains(Scope.COMPILE)) {
arrayListOf(compileDependencies, compileProvidedDependencies,
variant.buildType.compileDependencies, variant.buildType.compileDependencies,
variant.buildType.compileProvidedDependencies, variant.buildType.compileProvidedDependencies,
variant.productFlavor.compileDependencies, variant.productFlavor.compileDependencies,
variant.productFlavor.compileProvidedDependencies) variant.productFlavor.compileProvidedDependencies
} else if (passedScopes.contains(Scope.RUNTIME)) { )
arrayListOf(compileRuntimeDependencies)
} else {
arrayListOf(arrayListOf<IClasspathDependency>())
}
val runtimeDeps = arrayListOf(compileRuntimeDependencies)
if (isTest) { if (isTest) {
deps.add(testDependencies) deps.add(testDependencies)
deps.add(testProvidedDependencies) deps.add(testProvidedDependencies)
@ -279,9 +236,9 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
val filter = val filter =
if (isTest) OrDependencyFilter(Filters.COMPILE_FILTER, Filters.TEST_FILTER) if (isTest) OrDependencyFilter(Filters.COMPILE_FILTER, Filters.TEST_FILTER)
else Filters.COMPILE_FILTER else Filters.COMPILE_FILTER
runtimeDeps.filter { it.any() }.forEach { deps.filter { it.any() }.forEach {
transitive.addAll(calculateDependencies(project, context, filter, transitive.addAll(calculateDependencies(project, context, filter,
passedScopes, // scopes = Scope.toScopes(isTest), scopes = Scope.toScopes(isTest),
passedDependencies = it)) passedDependencies = it))
} }
} }

View file

@ -1,18 +1,16 @@
package com.beust.kobalt.maven package com.beust.kobalt.maven
import com.beust.kobalt.OperatingSystem import com.beust.kobalt.OperatingSystem
import com.beust.kobalt.misc.LocalProperties
import com.beust.kobalt.misc.error import com.beust.kobalt.misc.error
import com.beust.kobalt.misc.kobaltLog import com.beust.kobalt.misc.kobaltLog
import com.beust.kobalt.misc.warn import com.beust.kobalt.misc.warn
import com.google.inject.Inject
import com.google.inject.Singleton import com.google.inject.Singleton
import java.io.BufferedReader import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.InputStreamReader import java.io.InputStreamReader
@Singleton @Singleton
class Gpg @Inject constructor(val localProperties: LocalProperties) { class Gpg {
val COMMANDS = listOf("gpg", "gpg2") val COMMANDS = listOf("gpg", "gpg2")
fun findGpgCommand() : String? { fun findGpgCommand() : String? {
@ -44,21 +42,6 @@ class Gpg @Inject constructor(val localProperties: LocalProperties) {
ascFile.delete() ascFile.delete()
val allArgs = arrayListOf<String>() val allArgs = arrayListOf<String>()
allArgs.add(gpg) allArgs.add(gpg)
fun maybeAdd(prop: String, f: (String) -> Unit) = localProperties.getNoThrows(prop)?.let {
f(it)
}
maybeAdd("gpg.password") {
allArgs.addAll(listOf("--passphrase", it, "--batch", "--yes"))
}
maybeAdd("gpg.keyId") {
allArgs.addAll(listOf("--local-user", it))
}
maybeAdd("gpg.secretKeyRingFile") {
allArgs.addAll(listOf("--secret-keyring", "\"$it\""))
}
allArgs.add("-ab") allArgs.add("-ab")
allArgs.add(file.absolutePath) allArgs.add(file.absolutePath)

View file

@ -1,8 +1,9 @@
package com.beust.kobalt.maven package com.beust.kobalt.maven
import com.beust.kobalt.HostConfig import com.beust.kobalt.HostConfig
import com.beust.kobalt.maven.aether.KobaltMavenResolver import com.beust.kobalt.KobaltException
import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.maven.dependency.FileDependency
import com.beust.kobalt.misc.LocalProperties
import java.io.* import java.io.*
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
@ -20,7 +21,27 @@ class Kurl(val hostInfo: HostConfig) {
} }
init { init {
KobaltMavenResolver.initAuthentication(hostInfo) // See if the URL needs to be authenticated. Look in local.properties for keys
// of the format authUrl.<host>.user=xxx and authUrl.<host>.password=xxx
val properties = LocalProperties().localProperties
val host = java.net.URL(hostInfo.url).host
properties.entries.forEach {
val key = it.key.toString()
if (key == "$KEY.$host.$VALUE_USER") {
hostInfo.username = properties.getProperty(key)
} else if (key == "$KEY.$host.$VALUE_PASSWORD") {
hostInfo.password = properties.getProperty(key)
}
}
fun error(s1: String, s2: String) {
throw KobaltException("Found \"$s1\" but not \"$s2\" in local.properties for $KEY.$host",
docUrl = "http://beust.com/kobalt/documentation/index.html#maven-repos-authenticated")
}
if (! hostInfo.username.isNullOrBlank() && hostInfo.password.isNullOrBlank()) {
error("username", "password")
} else if(hostInfo.username.isNullOrBlank() && ! hostInfo.password.isNullOrBlank()) {
error("password", "username")
}
} }
override fun toString() = hostInfo.toString() override fun toString() = hostInfo.toString()

View file

@ -1,8 +1,11 @@
package com.beust.kobalt.maven package com.beust.kobalt.maven
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.Versions
import com.google.inject.Inject import com.google.inject.Inject
import java.io.File import java.io.File
import java.util.*
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
@ -10,7 +13,42 @@ open class LocalRepo @Inject constructor(val kobaltSettings: KobaltSettings) {
val localRepo: File val localRepo: File
get() = kobaltSettings.localCache get() = kobaltSettings.localCache
fun toFullPath(path: String): String = File(localRepo, path).absolutePath fun existsPom(d: LocalDep, v: String) : Boolean {
return File(d.toAbsolutePomFile(v)).exists()
}
fun existsJar(d: LocalDep, v: String) : Boolean {
return File(d.toAbsoluteJarFilePath(v)).exists()
}
/**
* If the dependency is local, return the correct version for it
*/
fun findLocalVersion(groupId: String, artifactId: String, packaging: String? = null) : String? {
// No version: look at all the directories under group/artifactId, pick the latest and see
// if it contains a maven and jar file
val dir = toFullPath(KFiles.joinDir(groupId.replace(".", File.separator), artifactId))
val files = File(dir).listFiles()
if (files != null) {
val directories = files.filter { it.isDirectory }
if (directories.size > 0) {
Collections.sort(directories, { f1, f2 ->
val v1 = Versions.toLongVersion(f1.name)
val v2 = Versions.toLongVersion(f2.name)
v2.compareTo(v1) // we want the most recent at position 0
})
val result = directories[0].name
val newDep = LocalDep(MavenId.create(groupId, artifactId, packaging, null, result), this)
if (existsPom(newDep, result) && existsJar(newDep, result)) {
return result
}
}
}
return null
}
fun toFullPath(path: String) = File(localRepo, path).absolutePath
} }

View file

@ -17,13 +17,9 @@ class MavenId private constructor(val groupId: String, val artifactId: String, v
val classifier: String?, val version: String?) { val classifier: String?, val version: String?) {
companion object { companion object {
fun isMavenId(id: String) = if (id.startsWith("file://")) { fun isMavenId(id: String) = with(id.split(':')) {
false
} else {
with(id.split(':')) {
size >= 3 && size <= 5 size >= 3 && size <= 5
} }
}
fun isRangedVersion(s: String): Boolean { fun isRangedVersion(s: String): Boolean {
return s.first() in listOf('[', '(') && s.last() in listOf(']', ')') return s.first() in listOf('[', '(') && s.last() in listOf(']', ')')
@ -36,14 +32,14 @@ class MavenId private constructor(val groupId: String, val artifactId: String, v
MavenId(groupId, artifactId, extension, classifier, version) MavenId(groupId, artifactId, extension, classifier, version)
} }
fun toMavenId(id: String) = if (id.endsWith(":")) id + "(0,]" else id fun toKobaltId(id: String) = if (id.endsWith(":")) id + "(0,]" else id
/** /**
* The main entry point to create Maven Id's. Id's created by this function * The main entry point to create Maven Id's. Id's created by this function
* will run through IMavenIdInterceptors. * will run through IMavenIdInterceptors.
*/ */
fun create(originalId: String) : MavenId { fun create(originalId: String) : MavenId {
val id = toMavenId(originalId) val id = toKobaltId(originalId)
var originalMavenId = createNoInterceptors(id) var originalMavenId = createNoInterceptors(id)
var interceptedMavenId = originalMavenId var interceptedMavenId = originalMavenId
val interceptors = Kobalt.context?.pluginInfo?.mavenIdInterceptors val interceptors = Kobalt.context?.pluginInfo?.mavenIdInterceptors

View file

@ -31,13 +31,13 @@ class Md5 {
var fileCount = 0 var fileCount = 0
filesOrDirectories.filter(File::exists).forEach { file -> filesOrDirectories.filter(File::exists).forEach { file ->
if (file.isFile) { if (file.isFile) {
kobaltLog(3, " Calculating checksum of $file") kobaltLog(2, " Calculating checksum of $file")
val bytes = toBytes(file) val bytes = toBytes(file)
md5.update(bytes, 0, bytes.size) md5.update(bytes, 0, bytes.size)
fileCount++ fileCount++
} else { } else {
val files = KFiles.findRecursively(file) // , { f -> f.endsWith("java")}) val files = KFiles.findRecursively(file) // , { f -> f.endsWith("java")})
kobaltLog(3, " Calculating checksum of ${files.size} files in $file") kobaltLog(2, " Calculating checksum of ${files.size} files in $file")
files.map { files.map {
File(file, it) File(file, it)
}.filter { }.filter {

View file

@ -1,12 +1,13 @@
package com.beust.kobalt.maven package com.beust.kobalt.maven
import com.beust.kobalt.misc.kobaltLog
import org.w3c.dom.Element import org.w3c.dom.Element
import org.xml.sax.InputSource import org.xml.sax.InputSource
import java.io.File import java.io.File
import java.io.FileReader import java.io.FileReader
import javax.xml.bind.JAXBContext import javax.xml.bind.JAXBContext
import javax.xml.bind.annotation.* import javax.xml.bind.annotation.XmlAnyElement
import javax.xml.bind.annotation.XmlElement
import javax.xml.bind.annotation.XmlRootElement
import javax.xml.parsers.SAXParserFactory import javax.xml.parsers.SAXParserFactory
import javax.xml.transform.sax.SAXSource import javax.xml.transform.sax.SAXSource
@ -146,7 +147,7 @@ class Dependency {
private fun expandVariable(s: String, pom: Pom2) : String { private fun expandVariable(s: String, pom: Pom2) : String {
val variable = extractVariable(s) val variable = extractVariable(s)
if (variable != null) { if (variable != null) {
kobaltLog(2, "Expanding variable $variable") println("Expanding variable $variable")
val value = pom.pomProject.propertyValue(variable) val value = pom.pomProject.propertyValue(variable)
return s return s
} else { } else {

View file

@ -23,10 +23,6 @@ class PomGenerator @Inject constructor(@Assisted val project: Project) {
* Generate the POM file and save it. * Generate the POM file and save it.
*/ */
fun generateAndSave() { fun generateAndSave() {
requireNotNull(project.version, { "version is mandatory on project ${project.name}" })
requireNotNull(project.group, { "group is mandatory on project ${project.name}" })
requireNotNull(project.artifactId, { "artifactId is mandatory on project ${project.name}" })
val buildDir = KFiles.makeDir(project.directory, project.buildDirectory) val buildDir = KFiles.makeDir(project.directory, project.buildDirectory)
val outputDir = KFiles.makeDir(buildDir.path, "libs") val outputDir = KFiles.makeDir(buildDir.path, "libs")
val NO_CLASSIFIER = null val NO_CLASSIFIER = null
@ -42,6 +38,10 @@ class PomGenerator @Inject constructor(@Assisted val project: Project) {
* @return the text content of the POM file. * @return the text content of the POM file.
*/ */
fun generate() : String { fun generate() : String {
requireNotNull(project.version, { "version mandatory on project ${project.name}" })
requireNotNull(project.group, { "group mandatory on project ${project.name}" })
requireNotNull(project.artifactId, { "artifactId mandatory on project ${project.name}" })
val pom = (project.pom ?: Model()).apply { val pom = (project.pom ?: Model()).apply {
// Make sure the pom has reasonable default values // Make sure the pom has reasonable default values
if (name == null) name = project.name if (name == null) name = project.name

View file

@ -1,19 +1,18 @@
package com.beust.kobalt.maven.aether package com.beust.kobalt.maven.aether
import com.beust.kobalt.Args
import com.beust.kobalt.api.Dependencies
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.maven.CompletedFuture import com.beust.kobalt.maven.CompletedFuture
import com.beust.kobalt.misc.StringVersion import com.beust.kobalt.maven.LocalDep
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.MavenId
import com.beust.kobalt.misc.Versions
import com.beust.kobalt.misc.warn import com.beust.kobalt.misc.warn
import org.eclipse.aether.artifact.Artifact import org.eclipse.aether.artifact.Artifact
import org.eclipse.aether.artifact.DefaultArtifact
import org.eclipse.aether.resolution.DependencyResolutionException
import java.io.File import java.io.File
import java.util.concurrent.Future import java.util.concurrent.Future
class AetherDependency(val artifact: Artifact, override val optional: Boolean = false, val args: Args? = null) class AetherDependency(val artifact: Artifact, override val optional: Boolean = false)
: IClasspathDependency, Comparable<AetherDependency> { : IClasspathDependency, Comparable<AetherDependency> {
val aether: KobaltMavenResolver get() = Kobalt.INJECTOR.getInstance(KobaltMavenResolver::class.java) val aether: KobaltMavenResolver get() = Kobalt.INJECTOR.getInstance(KobaltMavenResolver::class.java)
@ -26,30 +25,19 @@ class AetherDependency(val artifact: Artifact, override val optional: Boolean =
private fun toId(a: Artifact) = a.toString() private fun toId(a: Artifact) = a.toString()
override val jarFile: Future<File> override val jarFile: Future<File>
get() { get() = if (artifact.file != null) {
resolveSourcesIfNeeded()
return if (artifact.file != null) {
CompletedFuture(artifact.file) CompletedFuture(artifact.file)
} else { } else {
val td = aether.resolve(artifact) val localRepo = Kobalt.INJECTOR.getInstance(LocalRepo::class.java)
val file = File(LocalDep(MavenId.create(id), localRepo).toAbsoluteJarFilePath(version))
if (file.exists()) {
CompletedFuture(file)
} else {
val td = aether.resolve(artifact, null)
CompletedFuture(td.root.artifact.file) CompletedFuture(td.root.artifact.file)
} }
} }
private fun resolveSourcesIfNeeded() {
if (args?.downloadSources ?: false) {
listOf(artifact.toSourcesArtifact(), artifact.toJavaDocArtifact()).forEach { artifact ->
if (artifact.file == null) {
try {
aether.resolve(artifact)
} catch(e: DependencyResolutionException) {
// Ignore
}
}
}
}
}
override fun toMavenDependencies(scope: String?) : org.apache.maven.model.Dependency { override fun toMavenDependencies(scope: String?) : org.apache.maven.model.Dependency {
val passedScope = scope val passedScope = scope
val op = this.optional val op = this.optional
@ -77,10 +65,9 @@ class AetherDependency(val artifact: Artifact, override val optional: Boolean =
override val shortId = artifact.groupId + ":" + artifact.artifactId + ":" + artifact.classifier override val shortId = artifact.groupId + ":" + artifact.artifactId + ":" + artifact.classifier
override val excluded = arrayListOf<Dependencies.ExcludeConfig>()
override fun compareTo(other: AetherDependency): Int { override fun compareTo(other: AetherDependency): Int {
return StringVersion(artifact.version).compareTo(StringVersion(other.artifact.version)) return Versions.toLongVersion(artifact.version).compareTo(Versions.toLongVersion(
other.artifact.version))
} }
override fun hashCode() = id.hashCode() override fun hashCode() = id.hashCode()
@ -88,7 +75,4 @@ class AetherDependency(val artifact: Artifact, override val optional: Boolean =
override fun equals(other: Any?) = if (other is AetherDependency) other.id == id else false override fun equals(other: Any?) = if (other is AetherDependency) other.id == id else false
override fun toString() = id override fun toString() = id
fun Artifact.toSourcesArtifact() = DefaultArtifact(groupId, artifactId, "sources", extension, version)
fun Artifact.toJavaDocArtifact() = DefaultArtifact(groupId, artifactId, "javadoc", extension, version)
} }

View file

@ -2,7 +2,6 @@ package com.beust.kobalt.maven.aether
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
import com.google.common.eventbus.EventBus import com.google.common.eventbus.EventBus
import com.beust.kobalt.Args
import org.eclipse.aether.DefaultRepositorySystemSession import org.eclipse.aether.DefaultRepositorySystemSession
import org.eclipse.aether.RepositorySystem import org.eclipse.aether.RepositorySystem
import org.eclipse.aether.repository.LocalRepository import org.eclipse.aether.repository.LocalRepository
@ -33,9 +32,8 @@ object Booter {
// } // }
fun newRepositorySystemSession(system: RepositorySystem, repo: File, settings: KobaltSettings, fun newRepositorySystemSession(system: RepositorySystem, repo: File, settings: KobaltSettings,
args: Args, eventBus: EventBus): DefaultRepositorySystemSession { eventBus: EventBus): DefaultRepositorySystemSession {
val session = MavenRepositorySystemUtils.newSession(settings) val session = MavenRepositorySystemUtils.newSession(settings)
session.isOffline = args.offline
val localRepo = LocalRepository(repo.absolutePath) val localRepo = LocalRepository(repo.absolutePath)
session.localRepositoryManager = system.newLocalRepositoryManager(session, localRepo) session.localRepositoryManager = system.newLocalRepositoryManager(session, localRepo)

View file

@ -16,6 +16,12 @@ class ConsoleRepositoryListener @JvmOverloads constructor(out: PrintStream? = nu
val LOG_LEVEL = 4 val LOG_LEVEL = 4
} }
private val out: PrintStream
init {
this.out = out ?: System.out
}
override fun artifactDeployed(event: RepositoryEvent?) { override fun artifactDeployed(event: RepositoryEvent?) {
kobaltLog(LOG_LEVEL, "Deployed " + event!!.artifact + " to " + event.repository) kobaltLog(LOG_LEVEL, "Deployed " + event!!.artifact + " to " + event.repository)
} }

View file

@ -1,8 +1,6 @@
package com.beust.kobalt.maven.aether package com.beust.kobalt.maven.aether
import com.beust.kobalt.misc.kobaltLog
import org.eclipse.aether.graph.DependencyFilter import org.eclipse.aether.graph.DependencyFilter
import org.eclipse.aether.graph.DependencyNode
import org.eclipse.aether.util.artifact.JavaScopes import org.eclipse.aether.util.artifact.JavaScopes
object Filters { object Filters {
@ -11,15 +9,7 @@ object Filters {
} }
val TEST_FILTER = DependencyFilter { p0, p1 -> p0.dependency.scope == JavaScopes.TEST } val TEST_FILTER = DependencyFilter { p0, p1 -> p0.dependency.scope == JavaScopes.TEST }
val EXCLUDE_OPTIONAL_FILTER = object: DependencyFilter { val EXCLUDE_OPTIONAL_FILTER = DependencyFilter { p0, p1 ->
override fun accept(p0: DependencyNode, p1: MutableList<DependencyNode>): Boolean { p0.dependency != null && ! p0.dependency.optional
val result = p0.dependency != null && ! p0.dependency.optional
if (! result) {
kobaltLog(3, "Excluding from optional filter: $p0")
}
return result
}
override fun toString() = "EXCLUDE_OPTIONAL_FILTER"
} }
} }

View file

@ -1,15 +1,10 @@
package com.beust.kobalt.maven.aether package com.beust.kobalt.maven.aether
import com.beust.kobalt.Args
import com.beust.kobalt.HostConfig
import com.beust.kobalt.KobaltException
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.getProxy import com.beust.kobalt.internal.getProxy
import com.beust.kobalt.maven.Kurl
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.misc.LocalProperties
import com.google.common.eventbus.EventBus import com.google.common.eventbus.EventBus
import com.google.inject.Inject import com.google.inject.Inject
import org.eclipse.aether.artifact.Artifact import org.eclipse.aether.artifact.Artifact
@ -24,11 +19,8 @@ import org.eclipse.aether.resolution.DependencyRequest
import org.eclipse.aether.resolution.DependencyResult import org.eclipse.aether.resolution.DependencyResult
import org.eclipse.aether.resolution.VersionRangeRequest import org.eclipse.aether.resolution.VersionRangeRequest
import org.eclipse.aether.resolution.VersionRangeResult import org.eclipse.aether.resolution.VersionRangeResult
import org.eclipse.aether.util.repository.AuthenticationBuilder
import java.util.*
class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings, class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
val args: Args,
localRepo: LocalRepo, eventBus: EventBus) { localRepo: LocalRepo, eventBus: EventBus) {
companion object { companion object {
@ -36,87 +28,34 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
MavenId.toId(it.groupId, it.artifactId, it.extension, it.classifier, it.version) MavenId.toId(it.groupId, it.artifactId, it.extension, it.classifier, it.version)
} }
fun isRangeVersion(id: String) = id.contains(",") fun isRangeVersion(id: String) = id.contains(",")
fun initAuthentication(hostInfo: HostConfig) {
// See if the URL needs to be authenticated. Look in local.properties for keys
// of the format authUrl.<host>.user=xxx and authUrl.<host>.password=xxx
val properties = LocalProperties().localProperties
val host = java.net.URL(hostInfo.url).host
properties.entries.forEach {
val key = it.key.toString()
if (key == "${Kurl.KEY}.$host.${Kurl.VALUE_USER}") {
hostInfo.username = properties.getProperty(key)
} else if (key == "${Kurl.KEY}.$host.${Kurl.VALUE_PASSWORD}") {
hostInfo.password = properties.getProperty(key)
}
}
fun error(s1: String, s2: String) {
throw KobaltException("Found \"$s1\" but not \"$s2\" in local.properties for ${Kurl.KEY}.$host",
docUrl = "https://beust.com/kobalt/documentation/index.html#maven-repos-authenticated")
}
if (! hostInfo.username.isNullOrBlank() && hostInfo.password.isNullOrBlank()) {
error("username", "password")
} else if(hostInfo.username.isNullOrBlank() && ! hostInfo.password.isNullOrBlank()) {
error("password", "username")
} }
} fun resolveToArtifact(id: String, scope: Scope? = null, filter: DependencyFilter? = null) : Artifact
}
fun resolveToArtifact(id: String, scope: Scope? = null,
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER) : Artifact
= resolve(id, scope, filter).root.artifact = resolve(id, scope, filter).root.artifact
fun resolve(passedId: String, scope: Scope? = null, fun resolve(id: String, scope: Scope? = null, filter: DependencyFilter? = null): DependencyResult {
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER, val dependencyRequest = DependencyRequest(createCollectRequest(id, scope), filter)
repos: List<String> = emptyList()): DependencyResult {
val mavenId = MavenId.toMavenId(passedId)
val id =
if (isRangeVersion(mavenId)) {
val artifact = DefaultArtifact(mavenId)
val request = VersionRangeRequest(artifact, createRepos(repos), null)
val rr = system.resolveVersionRange(session, request)
if (rr.highestVersion != null) {
val newArtifact = DefaultArtifact(artifact.groupId, artifact.artifactId, artifact.classifier,
artifact.extension, rr.highestVersion.toString())
artifactToId(newArtifact)
} else {
throw KobaltException("Couldn't resolve $passedId")
}
} else {
passedId
}
val collectRequest = createCollectRequest(id, scope, repos)
val dependencyRequest = DependencyRequest(collectRequest, filter)
val result = system.resolveDependencies(session, dependencyRequest) val result = system.resolveDependencies(session, dependencyRequest)
// GraphUtil.displayGraph(listOf(result.root), { it -> it.children }, // GraphUtil.displayGraph(listOf(result.root), { it -> it.children },
// { it: DependencyNode, indent: String -> println(indent + it.toString()) }) // { it: DependencyNode, indent: String -> println(indent + it.toString()) })
return result return result
} }
fun resolve(artifact: Artifact, scope: Scope? = null, fun resolve(artifact: Artifact, scope: Scope? = null, filter: DependencyFilter? = null)
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER)
= resolve(artifactToId(artifact), scope, filter) = resolve(artifactToId(artifact), scope, filter)
fun resolveToIds(id: String, scope: Scope? = null, fun resolveToIds(id: String, scope: Scope? = null, filter: DependencyFilter? = null) : List<String> {
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER,
seen: HashSet<String> = hashSetOf<String>()) : List<String> {
val rr = resolve(id, scope, filter) val rr = resolve(id, scope, filter)
val children = val children =
rr.root.children.filter { rr.root.children.filter {
filter.accept(DefaultDependencyNode(it.dependency), emptyList()) filter == null || filter.accept(DefaultDependencyNode(it.dependency), emptyList())
}.filter { }.filter {
it.dependency.scope != Scope.SYSTEM.scope it.dependency.scope != Scope.SYSTEM.scope
} }
val result = listOf(artifactToId(rr.root.artifact)) + children.flatMap { val result = listOf(artifactToId(rr.root.artifact)) + children.flatMap {
val thisId = artifactToId(it.artifact) val thisId = artifactToId(it.artifact)
if (! seen.contains(thisId)) { resolveToIds(thisId, scope, filter)
seen.add(thisId)
resolveToIds(thisId, scope, filter, seen)
} else {
emptyList()
}
} }
return result return result
} }
@ -129,7 +68,7 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
directDependencies(id, scope) directDependencies(id, scope)
} }
fun resolveRange(artifact: Artifact): VersionRangeResult? { fun resolveVersion(artifact: Artifact): VersionRangeResult? {
val request = VersionRangeRequest(artifact, kobaltRepositories, null) val request = VersionRangeRequest(artifact, kobaltRepositories, null)
val result = system.resolveVersionRange(session, request) val result = system.resolveVersionRange(session, request)
return result return result
@ -138,26 +77,16 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
/** /**
* Create an IClasspathDependency from a Kobalt id. * Create an IClasspathDependency from a Kobalt id.
*/ */
fun create(id: String, optional: Boolean) = AetherDependency(DefaultArtifact(id), optional, args) fun create(id: String, optional: Boolean) = AetherDependency(DefaultArtifact(id), optional)
private val system = Booter.newRepositorySystem() private val system = Booter.newRepositorySystem()
private val session = Booter.newRepositorySystemSession(system, localRepo.localRepo, settings, args, eventBus) private val session = Booter.newRepositorySystemSession(system, localRepo.localRepo, settings, eventBus)
private fun createRepo(hostConfig: HostConfig) : RemoteRepository {
val builder = RemoteRepository.Builder(hostConfig.name, "default", hostConfig.url)
if (hostConfig.hasAuth()) {
val auth = AuthenticationBuilder()
.addUsername(hostConfig.username)
.addPassword(hostConfig.password)
.build()
builder.setAuthentication(auth)
}
return builder.build()
}
private val kobaltRepositories: List<RemoteRepository> private val kobaltRepositories: List<RemoteRepository>
get() = Kobalt.repos.map { get() = Kobalt.repos.map {
createRepo(it).let { repository -> RemoteRepository.Builder(null, "default", it.url)
// .setSnapshotPolicy(RepositoryPolicy(false, null, null))
.build().let { repository ->
val proxyConfigs = settings.proxyConfigs ?: return@map repository val proxyConfigs = settings.proxyConfigs ?: return@map repository
RemoteRepository.Builder(repository).apply { RemoteRepository.Builder(repository).apply {
setProxy(proxyConfigs.getProxy(repository.protocol)?.toAetherProxy()) setProxy(proxyConfigs.getProxy(repository.protocol)?.toAetherProxy())
@ -165,16 +94,8 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
} }
} }
private fun createRepos(repos: List<String>) : List<RemoteRepository> private fun createCollectRequest(id: String, scope: Scope? = null) = CollectRequest().apply {
= kobaltRepositories + repos.map { createRepo(HostConfig(it)) } root = Dependency(DefaultArtifact(MavenId.toKobaltId(id)), scope?.scope)
repositories = kobaltRepositories
private fun createCollectRequest(id: String, scope: Scope? = null, repos: List<String> = emptyList())
= CollectRequest().apply {
val allIds = arrayListOf(MavenId.toMavenId(id))
dependencies = allIds.map { Dependency(DefaultArtifact(it), scope?.scope) }
root = Dependency(DefaultArtifact(MavenId.toMavenId(id)), scope?.scope)
repositories = createRepos(repos)
} }
} }

View file

@ -12,7 +12,6 @@ sealed class Scope(val scope: String, val dependencyLambda: (Project) -> List<IC
object COMPILE : Scope(JavaScopes.COMPILE, Project::compileDependencies) object COMPILE : Scope(JavaScopes.COMPILE, Project::compileDependencies)
object PROVIDED : Scope(JavaScopes.PROVIDED, Project::compileProvidedDependencies) object PROVIDED : Scope(JavaScopes.PROVIDED, Project::compileProvidedDependencies)
object COMPILEONLY : Scope("compileOnly", Project::compileOnlyDependencies)
object SYSTEM : Scope(JavaScopes.SYSTEM, { project -> emptyList() }) object SYSTEM : Scope(JavaScopes.SYSTEM, { project -> emptyList() })
object RUNTIME : Scope(JavaScopes.RUNTIME, Project::compileRuntimeDependencies) object RUNTIME : Scope(JavaScopes.RUNTIME, Project::compileRuntimeDependencies)
object TEST : Scope(JavaScopes.TEST, Project::testDependencies) object TEST : Scope(JavaScopes.TEST, Project::testDependencies)

View file

@ -1,6 +1,5 @@
package com.beust.kobalt.maven.dependency package com.beust.kobalt.maven.dependency
import com.beust.kobalt.api.Dependencies
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.maven.CompletedFuture import com.beust.kobalt.maven.CompletedFuture
import org.apache.maven.model.Dependency import org.apache.maven.model.Dependency
@ -32,8 +31,6 @@ open class FileDependency(open val fileName: String, override val optional: Bool
override fun directDependencies() = arrayListOf<IClasspathDependency>() override fun directDependencies() = arrayListOf<IClasspathDependency>()
override val excluded = arrayListOf<Dependencies.ExcludeConfig>()
override fun compareTo(other: FileDependency) = fileName.compareTo(other.fileName) override fun compareTo(other: FileDependency) = fileName.compareTo(other.fileName)
override fun toString() = fileName override fun toString() = fileName

View file

@ -1,31 +1,14 @@
package com.beust.kobalt.misc package com.beust.kobalt.misc
import com.beust.kobalt.homeDir
import java.io.File import java.io.File
import java.util.regex.Pattern import java.util.regex.Pattern
class Section(val start: Int, val end: Int) { fun main(argv: Array<String>) {
override fun toString() = "$start-$end" val lines = File(homeDir("kotlin/kobalt/kobalt/src/Build.kt")).readLines()
} val result = BlockExtractor(Pattern.compile("val.*buildScript.*\\{"), '{', '}').extractBlock(lines)
class IncludedBuildSourceDir(val line: Int, val dirs: List<String>) // BlockExtractor("plugins", '(', ')').extractBlock(lines)
class BuildScriptInfo(val file: File, val fullBuildFile: List<String>, val sections: List<Section>,
val imports: List<String>, val topLines: List<String>) {
fun isInSection(lineNumber: Int): Boolean {
sections.forEach {
if (lineNumber >= it.start && lineNumber <= it.end) return true
}
return false
}
val includedBuildSourceDirs = arrayListOf<IncludedBuildSourceDir>()
fun addBuildSourceDir(dir: IncludedBuildSourceDir) = includedBuildSourceDirs.add(dir)
fun includedBuildSourceDirsForLine(line: Int): List<String> {
val result = includedBuildSourceDirs.find { it.line == line }?.dirs
return result ?: emptyList()
}
} }
/** /**
@ -33,18 +16,11 @@ class BuildScriptInfo(val file: File, val fullBuildFile: List<String>, val secti
* e.g. buildScript { ... }. * e.g. buildScript { ... }.
*/ */
class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char) { class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char) {
fun extractBlock(file: File, lines: List<String>): BuildScriptInfo? { fun extractBlock(lines: List<String>): String? {
var currentLineNumber = 0
// First line of the buildScript block
var startLine = 0
// Last line of the buildScript block
var endLine = 0
var foundKeyword = false var foundKeyword = false
var foundClosing = false var foundClosing = false
var count = 0 var count = 0
val buildScript = arrayListOf<String>() val result = StringBuffer()
val topLines = arrayListOf<String>()
val finalTopLines = arrayListOf<String>()
fun updateCount(line: String) { fun updateCount(line: String) {
val currentLine = StringBuffer() val currentLine = StringBuffer()
@ -57,63 +33,33 @@ class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char)
if (count == 0) { if (count == 0) {
currentLine.append(closing).append("\n") currentLine.append(closing).append("\n")
foundClosing = true foundClosing = true
endLine = currentLineNumber
} }
} }
if (foundKeyword && count > 0) currentLine.append(c) if (foundKeyword && count > 0) currentLine.append(c)
} }
if (currentLine.isNotEmpty() && foundKeyword) buildScript.add(currentLine.toString()) if (currentLine.isNotEmpty()) result.append(currentLine.toString()).append("\n")
} }
val imports = arrayListOf<String>()
val sections = arrayListOf<Section>()
lines.forEach { line -> lines.forEach { line ->
val found = regexp.matcher(line).matches() val found = regexp.matcher(line).matches()
if (found) { if (found) {
startLine = currentLineNumber
foundKeyword = true foundKeyword = true
count = 1 count = 1
buildScript.add(line) result.append(line).append("\n")
finalTopLines.addAll(topLines)
} else { } else {
if (line.startsWith("import")) {
if (isAllowedImport(line)) {
imports.add(line)
}
} else {
topLines.add(line)
}
updateCount(line) updateCount(line)
} }
if (foundKeyword && foundClosing && count == 0) { if (foundKeyword && foundClosing && count == 0) {
sections.add(Section(startLine, endLine)) return result.toString()
foundKeyword = false }
foundClosing = false
count = 0
startLine = 0
endLine = 0
} }
currentLineNumber++ if (foundKeyword && foundClosing && count == 0) {
} return result.toString()
if (sections.isNotEmpty()) {
val result = (imports.distinct() + buildScript).joinToString("\n") + "\n"
return BuildScriptInfo(file, lines, sections, imports, finalTopLines)
} else { } else {
return null return null
} }
} }
companion object {
private val allowedImports = listOf("com.beust", "java")
private val disallowedImports = listOf("com.beust.kobalt.plugin")
fun isAllowedImport(line: String) : Boolean {
return allowedImports.any { line.contains(it) } && !disallowedImports.any { line.contains(it) }
}
}
} }

View file

@ -26,14 +26,16 @@ class CheckVersions @Inject constructor(val depManager: DependencyManager,
try { try {
val latestDep = depManager.create(dep.shortId, false, project.directory) val latestDep = depManager.create(dep.shortId, false, project.directory)
val artifact = (latestDep as AetherDependency).artifact val artifact = (latestDep as AetherDependency).artifact
val rangeResult = resolver.resolveRange(artifact) val versions = resolver.resolveVersion(artifact)
val releases = versions?.versions?.filter { !it.toString().contains("SNAP")}
if (rangeResult != null) { val highest = if (releases != null && releases.any()) {
val highest = rangeResult.highestVersion?.toString() releases.last().toString()
if (highest != null && highest != dep.id } else {
&& StringVersion(highest) > StringVersion(dep.version)) { versions?.highestVersion.toString()
newVersions.add(artifact.groupId + ":" + artifact.artifactId + ":" + highest)
} }
if (highest != dep.id
&& Versions.toLongVersion(highest) > Versions.toLongVersion(dep.version)) {
newVersions.add(artifact.groupId + ":" + artifact.artifactId + ":" + highest)
} }
} catch(e: KobaltException) { } catch(e: KobaltException) {
kobaltLog(1, " Cannot resolve ${dep.shortId}. ignoring") kobaltLog(1, " Cannot resolve ${dep.shortId}. ignoring")

View file

@ -6,13 +6,12 @@ import com.google.inject.Inject
import java.io.File import java.io.File
class Git @Inject constructor() { class Git @Inject constructor() {
fun maybeTagRelease(project: Project, uploadResult: TaskResult, enabled: Boolean, annotated: Boolean, fun maybeTagRelease(project: Project, uploadResult: TaskResult, autoGitTag: Boolean) : TaskResult {
push: Boolean, tag: String, message: String) : TaskResult {
val result = val result =
if (uploadResult.success && enabled) { if (uploadResult.success && autoGitTag) {
val tagSuccess = tagRelease(project, annotated, push, tag, message) val tagSuccess = tagRelease(project)
if (! tagSuccess) { if (! tagSuccess) {
TaskResult(false, errorMessage = "Couldn't tag the project") TaskResult(false, "Couldn't tag the project")
} else { } else {
TaskResult() TaskResult()
} }
@ -22,28 +21,20 @@ class Git @Inject constructor() {
return result return result
} }
private fun tagRelease(project: Project, annotated: Boolean, push: Boolean, tag: String, message: String) : Boolean { private fun tagRelease(project: Project) : Boolean {
val version = if (tag.isNullOrBlank()) project.version else tag
val success = try { val success = try {
log(2, "Tagging this release as \"$version\"") log(2, "Tagging this release as \"${project.version}\"")
val repo = org.eclipse.jgit.storage.file.FileRepositoryBuilder() val repo = org.eclipse.jgit.storage.file.FileRepositoryBuilder()
.setGitDir(File(KFiles.joinDir(project.directory, ".git"))) .setGitDir(File(KFiles.joinDir(project.directory, ".git")))
.readEnvironment() .readEnvironment()
.findGitDir() .findGitDir()
.build() .build()
val git = org.eclipse.jgit.api.Git(repo) val git = org.eclipse.jgit.api.Git(repo)
// jGit library will complain and not tag if setAnnotated(false) val ref = git.tag().setName(project.version).call()
var ref = if (annotated) {
git.tag().setAnnotated(annotated).setName(version).setMessage(message).call()
} else {
git.tag().setName(version).setMessage(message).call()
}
if (push) {
git.push().setPushTags().call() git.push().setPushTags().call()
}
true true
} catch(ex: Exception) { } catch(ex: Exception) {
warn("Couldn't create tag ${version}: ${ex.message}", ex) warn("Couldn't create tag ${project.version}: ${ex.message}", ex)
false false
} }

View file

@ -1,11 +1,8 @@
package com.beust.kobalt.misc package com.beust.kobalt.misc
import com.beust.kobalt.Args
import com.beust.kobalt.KobaltException import com.beust.kobalt.KobaltException
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.internal.DocUrl import com.beust.kobalt.internal.DocUrl
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.build.VersionCheckTimestampFile
import com.beust.kobalt.maven.Http import com.beust.kobalt.maven.Http
import com.beust.kobalt.maven.aether.Exceptions import com.beust.kobalt.maven.aether.Exceptions
import com.google.gson.Gson import com.google.gson.Gson
@ -19,15 +16,12 @@ import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.* import retrofit2.http.*
import rx.Observable import rx.Observable
import java.io.File import java.io.File
import java.time.Duration
import java.time.Instant
import java.util.* import java.util.*
import java.util.concurrent.Callable import java.util.concurrent.Callable
import java.util.concurrent.Future import java.util.concurrent.Future
class GithubApi2 @Inject constructor( class GithubApi2 @Inject constructor(
val executors: KobaltExecutors, val localProperties: LocalProperties, val http: Http, val executors: KobaltExecutors, val localProperties: LocalProperties, val http: Http, val settings:KobaltSettings) {
val settings:KobaltSettings, val args: Args) {
companion object { companion object {
const val PROPERTY_ACCESS_TOKEN = "github.accessToken" const val PROPERTY_ACCESS_TOKEN = "github.accessToken"
@ -86,12 +80,12 @@ class GithubApi2 @Inject constructor(
.execute() .execute()
val code = response.code() val code = response.code()
if (code != Http.CREATED) { if (code != Http.CREATED) {
val error = Gson().fromJson(response.errorBody()?.string(), RetrofitError::class.java) val error = Gson().fromJson(response.errorBody().string(), RetrofitError::class.java)
throw KobaltException("Couldn't upload release, ${error.message}: " + error.errors[0].code) throw KobaltException("Couldn't upload release, ${error.message}: " + error.errors[0].code)
} else { } else {
val body = response.body() val body = response.body()
uploadAsset(accessToken, body?.uploadUrl!!, Http.TypedFile("application/zip", zipFile), tagName) uploadAsset(accessToken, body.uploadUrl!!, Http.TypedFile("application/zip", zipFile), tagName)
.toBlocking() .toBlocking()
.forEach { action -> .forEach { action ->
kobaltLog(1, "\n${zipFile.name} successfully uploaded") kobaltLog(1, "\n${zipFile.name} successfully uploaded")
@ -115,13 +109,10 @@ class GithubApi2 @Inject constructor(
val latestKobaltVersion: Future<String> val latestKobaltVersion: Future<String>
get() { get() {
val callable = Callable<String> { val callable = Callable<String> {
var result = Kobalt.version var result = "0"
if (! args.dev && Duration.ofMinutes(10L) >
Duration.between(VersionCheckTimestampFile.timestamp, Instant.now())) { val username = localProperties.getNoThrows(PROPERTY_USERNAME, DOC_URL)
kobaltLog(2, "Skipping GitHub latest release check, too soon.") val accessToken = localProperties.getNoThrows(PROPERTY_ACCESS_TOKEN, DOC_URL)
} else {
val username = localProperties.getNoThrows(PROPERTY_USERNAME)
val accessToken = localProperties.getNoThrows(PROPERTY_ACCESS_TOKEN)
try { try {
val req = val req =
if (username != null && accessToken != null) { if (username != null && accessToken != null) {
@ -138,8 +129,8 @@ class GithubApi2 @Inject constructor(
val releases = ex.body() val releases = ex.body()
if (releases != null) { if (releases != null) {
releases.firstOrNull()?.let { releases.firstOrNull()?.let {
result = try { try {
listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() } result = listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() }
} catch(ex: NoSuchElementException) { } catch(ex: NoSuchElementException) {
throw KobaltException("Couldn't find the latest release") throw KobaltException("Couldn't find the latest release")
} }
@ -162,7 +153,6 @@ class GithubApi2 @Inject constructor(
// kobaltLog(2, "Couldn't retrieve releases from github, ${error.message ?: e}: " // kobaltLog(2, "Couldn't retrieve releases from github, ${error.message ?: e}: "
// + details?.code + " field: " + details?.field) // + details?.code + " field: " + details?.field)
} }
}
result result
} }

View file

@ -1,7 +1,9 @@
package com.beust.kobalt.misc package com.beust.kobalt.misc
import java.io.File import java.io.File
import java.nio.file.* import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
class Io(val dryRun: Boolean = false) { class Io(val dryRun: Boolean = false) {
fun mkdirs(dir: String) { fun mkdirs(dir: String) {
@ -45,8 +47,8 @@ class Io(val dryRun: Boolean = false) {
if (! dryRun) { if (! dryRun) {
KFiles.copyRecursively(from, toDir) KFiles.copyRecursively(from, toDir)
require(from.exists(), { -> "$from should exist" }) require(from.exists(), { -> "$from should exist" })
require(from.isDirectory, { -> kobaltLog(1, "$from should be a directory")}) require(from.isDirectory, { -> println("$from should be a directory")})
require(toDir.isDirectory, { -> kobaltLog(1, "$toDir should be a file")}) require(toDir.isDirectory, { -> println("$toDir should be a file")})
} }
} }
@ -56,7 +58,7 @@ class Io(val dryRun: Boolean = false) {
private fun rmDir(dir: File, keep: (File) -> Boolean, indent : String) { private fun rmDir(dir: File, keep: (File) -> Boolean, indent : String) {
kobaltLog("rm -rf $dir") kobaltLog("rm -rf $dir")
require(dir.isDirectory, { -> kobaltLog(1, "$dir should be a directory")}) require(dir.isDirectory, { -> println("$dir should be a directory")})
dir.listFiles({ p0 -> ! keep(p0!!) }).forEach { dir.listFiles({ p0 -> ! keep(p0!!) }).forEach {
if (it.isDirectory) { if (it.isDirectory) {

View file

@ -1,16 +1,16 @@
package com.beust.kobalt.misc package com.beust.kobalt.misc
import com.beust.kobalt.From import com.beust.kobalt.Glob
import com.beust.kobalt.IFileSpec import com.beust.kobalt.IFileSpec
import com.beust.kobalt.IncludedFile
import com.beust.kobalt.To
import com.beust.kobalt.archive.MetaArchive
import com.google.common.io.CharStreams import com.google.common.io.CharStreams
import java.io.File import java.io.*
import java.io.FileOutputStream import java.nio.file.Paths
import java.io.InputStreamReader import java.util.jar.JarEntry
import java.util.jar.JarFile import java.util.jar.JarFile
import java.util.jar.JarInputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
class JarUtils { class JarUtils {
companion object { companion object {
@ -21,15 +21,18 @@ class JarUtils {
} }
} }
fun addFiles(directory: String, files: List<IncludedFile>, metaArchive: MetaArchive, fun addFiles(directory: String, files: List<IncludedFile>, target: ZipOutputStream,
expandJarFiles: Boolean, expandJarFiles: Boolean,
onError: (Exception) -> Unit = DEFAULT_HANDLER) { onError: (Exception) -> Unit = DEFAULT_HANDLER) {
files.forEach { files.forEach {
addSingleFile(directory, it, metaArchive, expandJarFiles, onError) addSingleFile(directory, it, target, expandJarFiles, onError)
} }
} }
fun addSingleFile(directory: String, file: IncludedFile, metaArchive: MetaArchive, private val DEFAULT_JAR_EXCLUDES =
Glob("META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA")
fun addSingleFile(directory: String, file: IncludedFile, outputStream: ZipOutputStream,
expandJarFiles: Boolean, onError: (Exception) -> Unit = DEFAULT_HANDLER) { expandJarFiles: Boolean, onError: (Exception) -> Unit = DEFAULT_HANDLER) {
val foundFiles = file.allFromFiles(directory) val foundFiles = file.allFromFiles(directory)
foundFiles.forEach { foundFile -> foundFiles.forEach { foundFile ->
@ -48,21 +51,47 @@ class JarUtils {
// Directory // Directory
val includedFile = IncludedFile(From(""), To(""), listOf(IFileSpec.GlobSpec("**"))) val includedFile = IncludedFile(From(""), To(""), listOf(IFileSpec.GlobSpec("**")))
addSingleFile(localFile.path, includedFile, metaArchive, expandJarFiles) addSingleFile(localFile.path, includedFile, outputStream, expandJarFiles)
} else { } else {
try {
if (file.expandJarFiles && foundFile.name.endsWith(".jar") && ! file.from.contains("resources")) { if (file.expandJarFiles && foundFile.name.endsWith(".jar") && ! file.from.contains("resources")) {
kobaltLog(2, " Writing contents of jar file $foundFile") kobaltLog(2, " Writing contents of jar file $foundFile")
metaArchive.addArchive(foundFile) val stream = JarInputStream(FileInputStream(localFile))
} else { var entry = stream.nextEntry
val toPath = File(file.to).normalize().path while (entry != null) {
val finalPath = if (toPath.isEmpty()) null else (toPath + "/") if (!entry.isDirectory && !KFiles.isExcluded(entry.name, DEFAULT_JAR_EXCLUDES)) {
metaArchive.addFile(File(directory, fromFile.path), foundFile, finalPath) val ins = JarFile(localFile).getInputStream(entry)
addEntry(ins, JarEntry(entry), outputStream, onError)
} }
entry = stream.nextEntry
}
} else {
val entryFileName = file.to(foundFile.path).path.replace("\\", "/")
val entry = JarEntry(entryFileName)
entry.time = localFile.lastModified()
addEntry(FileInputStream(localFile), entry, outputStream, onError)
}
}
}
}
private fun addEntry(inputStream: InputStream, entry: ZipEntry, outputStream: ZipOutputStream,
onError: (Exception) -> Unit = DEFAULT_HANDLER) {
var bis: BufferedInputStream? = null
try {
outputStream.putNextEntry(entry)
bis = BufferedInputStream(inputStream)
val buffer = ByteArray(50 * 1024)
while (true) {
val count = bis.read(buffer)
if (count == -1) break
outputStream.write(buffer, 0, count)
}
outputStream.closeEntry()
} catch(ex: Exception) { } catch(ex: Exception) {
onError(ex) onError(ex)
} } finally {
} bis?.close()
} }
} }
@ -105,3 +134,39 @@ class JarUtils {
} }
} }
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 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()}
}
}
class From(override val p: String) : Direction(p)
class To(override val p: String) : Direction(p)

View file

@ -3,39 +3,24 @@ package com.beust.kobalt.misc
import com.beust.kobalt.* import com.beust.kobalt.*
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.maven.Md5 import com.beust.kobalt.maven.Md5
import org.apache.commons.io.FileUtils import java.io.File
import java.io.* import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.util.*
import java.util.jar.JarInputStream
import java.util.regex.Pattern
class KFiles { class KFiles {
/** /**
* This actually returns a list of strings because in development mode, we are not pointing to a single * This actually returns a list of strings because in development mode, we are not pointing to a single
* jar file but to a set of classes/directories. * jar file but to a set of /classes directories.
*/ */
val kobaltJar : List<String> val kobaltJar : List<String>
get() { get() {
val PATTERN = Pattern.compile("kobalt-([-.0-9]+)")
fun latestInstalledVersion() : StringVersion {
val versions = File(distributionsDir).listFiles().map { it.name }.map {
val matcher = PATTERN.matcher(it)
val result =
if (matcher.matches()) matcher.group(1)
else null
result
}.filterNotNull().map(::StringVersion)
Collections.sort(versions, reverseOrder())
return versions[0]
}
val envJar = System.getenv("KOBALT_JAR") val envJar = System.getenv("KOBALT_JAR")
if (envJar != null) { if (envJar != null) {
debug("Using kobalt jar $envJar") debug("Using kobalt jar $envJar")
@ -47,20 +32,16 @@ class KFiles {
if (jarFile.exists()) { if (jarFile.exists()) {
return listOf(jarFile.absolutePath) return listOf(jarFile.absolutePath)
} else { } else {
// In development mode, keep your kobalt.properties version to a nonexistent version // In development mode, keep your kobalt.properties version one above kobalt-wrapper.properties:
// kobalt.properties: kobalt.version=0.828 // kobalt.properties: kobalt.version=0.828
// kobalt-wrapper.properties: kobalt.version=0.827 // kobalt-wrapper.properties: kobalt.version=0.827
// When Kobalt can't find the newest jar file, it will instead use the classes produced by IDEA // When Kobalt can't find the newest jar file, it will instead use the classes produced by IDEA
// in the directories specified here: // in the directories specified here:
val previousVersion = latestInstalledVersion().version val previousVersion = "0." + (Kobalt.version.split(".")[1].toInt() - 1).toString()
val previousJar = joinDir(distributionsDir, "kobalt-" + previousVersion, val previousJar = joinDir(distributionsDir, "kobalt-" + previousVersion,
"kobalt/wrapper/kobalt-$previousVersion.jar") "kobalt/wrapper/kobalt-" + previousVersion + ".jar")
latestInstalledVersion()
val result = listOf("", "modules/kobalt-plugin-api", "modules/wrapper").map { val result = listOf("", "modules/kobalt-plugin-api", "modules/wrapper").map {
File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "kobaltBuild", "classes"))) //kobalt build dirs File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "kobaltBuild", "classes")))
.absolutePath
} + listOf("modules/kobalt", "modules/kobalt-plugin-api", "modules/wrapper").map {
File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "target", "classes"))) //maven build dirs
.absolutePath .absolutePath
} + listOf(previousJar) } + listOf(previousJar)
debug("Couldn't find ${jarFile.absolutePath}, using\n " + result.joinToString(" ")) debug("Couldn't find ${jarFile.absolutePath}, using\n " + result.joinToString(" "))
@ -111,12 +92,10 @@ class KFiles {
*/ */
fun joinDir(vararg ts: String): String = ts.toMutableList().joinToString(File.separator) fun joinDir(vararg ts: String): String = ts.toMutableList().joinToString(File.separator)
val LIBS_DIR = "libs"
/** /**
* Where assemblies get generated ("kobaltBuild/libs") * Where assemblies get generated ("kobaltBuild/libs")
*/ */
fun libsDir(project: Project): String = KFiles.makeDir(KFiles.buildDir(project).path, LIBS_DIR).path fun libsDir(project: Project) = KFiles.makeDir(KFiles.buildDir(project).path, "libs").path
/** /**
* The paths elements are expected to be a directory. Make that directory and join the * The paths elements are expected to be a directory. Make that directory and join the
@ -136,18 +115,15 @@ class KFiles {
*/ */
fun joinFileAndMakeDir(vararg ts: String) = joinDir(joinAndMakeDir(ts.slice(0..ts.size - 2)), ts[ts.size - 1]) fun joinFileAndMakeDir(vararg ts: String) = joinDir(joinAndMakeDir(ts.slice(0..ts.size - 2)), ts[ts.size - 1])
fun fixSlashes(f: File) = f.normalize().path.replace('\\', '/')
fun fixSlashes(s: String) = s.replace('\\', '/')
fun makeDir(dir: String, s: String? = null) = fun makeDir(dir: String, s: String? = null) =
(if (s != null) File(dir, s) else File(dir)).apply { mkdirs() } (if (s != null) File(dir, s) else File(dir)).apply { mkdirs() }
fun findRecursively(rootDir: File) : List<String> = fun findRecursively(rootDir: File) : List<String> =
findRecursively(rootDir, arrayListOf(), { _ -> true }) findRecursively(rootDir, arrayListOf(), { s -> true })
fun findRecursively(rootDir: File, directories: List<File>, fun findRecursively(rootDir: File, directories: List<File>,
function: Function1<String, Boolean>): List<String> { function: Function1<String, Boolean>): List<String> {
val result = arrayListOf<String>() var result = arrayListOf<String>()
val allDirs = arrayListOf<File>() val allDirs = arrayListOf<File>()
if (directories.isEmpty()) { if (directories.isEmpty()) {
@ -160,8 +136,6 @@ class KFiles {
allDirs.forEach { dir -> allDirs.forEach { dir ->
if (! dir.exists()) { if (! dir.exists()) {
kobaltLog(2, "Couldn't find directory $dir") kobaltLog(2, "Couldn't find directory $dir")
} else if (! dir.isDirectory) {
throw IllegalArgumentException("$dir is not a directory")
} else { } else {
val files = findRecursively(dir, function) val files = findRecursively(dir, function)
files.map { Paths.get(it) }.forEach { files.map { Paths.get(it) }.forEach {
@ -181,7 +155,7 @@ class KFiles {
} }
fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> { fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> {
val result = arrayListOf<String>() var result = arrayListOf<String>()
directory.listFiles().forEach { directory.listFiles().forEach {
if (it.isFile && function(it.path)) { if (it.isFile && function(it.path)) {
result.add(it.path) result.add(it.path)
@ -192,59 +166,98 @@ class KFiles {
return result return result
} }
fun copyRecursively(from: File, to: File, replaceExisting: Boolean = true, deleteFirst: Boolean = false,
onError: (File, IOException) -> OnErrorAction = { file, exception -> throw exception }) {
// Need to wait until copyRecursively supports an overwrite: Boolean = false parameter
// Until then, wipe everything first
if (deleteFirst) to.deleteRecursively()
// to.mkdirs()
hackCopyRecursively(from, to, replaceExisting = replaceExisting, onError = onError)
}
/** Private exception class, used to terminate recursive copying */
private class TerminateException(file: File) : FileSystemException(file) {}
/** /**
* List the files contained in a directory or a jar file. * Copy/pasted from kotlin/io/Utils.kt to add support for overwriting.
*/ */
fun listFiles(file: File, block: (String) -> Unit) { private fun hackCopyRecursively(from: File, dst: File,
if (file.isDirectory) { replaceExisting: Boolean,
KFiles.findRecursively(file).forEach { checkTimestamp: Boolean = false,
block(it) onError: (File, IOException) -> OnErrorAction =
{ file, exception -> throw exception }
): Boolean {
if (!from.exists()) {
return onError(from, NoSuchFileException(file = from, reason = "The source file doesn't exist")) !=
OnErrorAction.TERMINATE
} }
} else if (file.name.endsWith(".jar")) { try {
FileInputStream(file).use { // We cannot break for loop from inside a lambda, so we have to use an exception here
JarInputStream(it).use { stream -> for (src in from.walkTopDown().onFail { f, e ->
var entry = stream.nextJarEntry if (onError(f, e) == OnErrorAction.TERMINATE) throw TerminateException(f)
while (entry != null) { }) {
block(entry.name) if (!src.exists()) {
entry = stream.nextJarEntry; if (onError(src, NoSuchFileException(file = src, reason = "The source file doesn't exist")) ==
OnErrorAction.TERMINATE)
return false
} else {
val relPath = src.relativeTo(from)
val dstFile = File(KFiles.joinDir(dst.path, relPath.path))
if (dstFile.exists() && !replaceExisting && !(src.isDirectory && dstFile.isDirectory)) {
if (onError(dstFile, FileAlreadyExistsException(file = src,
other = dstFile,
reason = "The destination file already exists")) == OnErrorAction.TERMINATE)
return false
} else if (src.isDirectory) {
dstFile.mkdirs()
} else {
if (Features.USE_TIMESTAMPS && dstFile.exists() && Md5.toMd5(src) == Md5.toMd5(dstFile)) {
kobaltLog(3, " Identical files, not copying $src to $dstFile")
} else {
val target = src.copyTo(dstFile, true)
if (target.length() != src.length()) {
if (onError(src,
IOException("src.length() != dst.length()")) == OnErrorAction.TERMINATE)
return false
} }
} }
} }
}
}
return true
} catch (e: TerminateException) {
return false
}
}
} else { private fun findDotDir(buildFile: BuildFile) : File {
throw KobaltException("Can't list files of a file: " + file) val result = File(buildFile.directory.parentFile.parentFile, KOBALT_DOT_DIR).apply {
mkdirs()
} }
return result
} }
/** /**
* The build location for build scripts is .kobalt/build * The build location for build scripts is .kobalt/build
*/ */
fun findBuildScriptDir(parent: String = ".") : File { fun findBuildScriptLocation(buildFile: BuildFile, jarFile: String) : String {
val result = File(joinAndMakeDir(parent, KFiles.dotKobaltDir.path, KFiles.SCRIPT_BUILD_DIR)) val result = joinDir(buildFile.dotKobaltDir.absolutePath, KFiles.SCRIPT_BUILD_DIR, jarFile)
kobaltLog(2, " Script jar files in: $result") kobaltLog(2, "Script jar file: $result")
return result return result
} }
fun saveFile(file: File, text: String) { fun saveFile(file: File, text: String) {
var canCreate = true file.absoluteFile.parentFile.mkdirs()
with(file.absoluteFile.parentFile) {
if (!exists()) {
val success = mkdirs()
if (!success) {
warn("Couldn't create directory to save $file")
canCreate = false
}
}
}
if (canCreate) {
file.writeText(text) file.writeText(text)
kobaltLog(2, "Created $file") kobaltLog(2, "Created $file")
} }
}
private fun isWindows() = System.getProperty("os.name").contains("Windows") private fun isWindows() = System.getProperty("os.name").contains("Windows");
fun copy(from: Path?, to: Path?, option: StandardCopyOption = StandardCopyOption.REPLACE_EXISTING) { fun copy(from: Path?, to: Path?, option: StandardCopyOption = StandardCopyOption.REPLACE_EXISTING) {
if (isWindows() && to!!.toFile().exists()) {
kobaltLog(2, "Windows detected, not overwriting $to")
} else {
try { try {
if (from != null && to != null) { if (from != null && to != null) {
if (!Files.exists(to) || Md5.toMd5(from.toFile()) != Md5.toMd5(to.toFile())) { if (!Files.exists(to) || Md5.toMd5(from.toFile()) != Md5.toMd5(to.toFile())) {
@ -259,6 +272,7 @@ class KFiles {
kobaltLog(1, "Couldn't copy $from to $to: ${ex.message}") kobaltLog(1, "Couldn't copy $from to $to: ${ex.message}")
} }
} }
}
fun copy(from: InputStream, to: OutputStream) { fun copy(from: InputStream, to: OutputStream) {
var read = from.read() var read = from.read()
@ -268,18 +282,12 @@ class KFiles {
} }
} }
fun createTempBuildFileInTempDirectory(deleteOnExit: Boolean = false) : File = fun createTempFile(suffix : String = "", deleteOnExit: Boolean = false) : File =
File(createTempDirectory("kobalt", deleteOnExit), Constants.BUILD_FILE_NAME).let { File.createTempFile("kobalt", suffix, File(SystemProperties.tmpDir)).let {
if (deleteOnExit) it.deleteOnExit() if (deleteOnExit) it.deleteOnExit()
return it return it
} }
fun createTempDirectory(prefix : String = "kobalt", deleteOnExit: Boolean = false) : File =
Files.createTempDirectory(prefix).let {
if (deleteOnExit) it.toFile().deleteOnExit()
return it.toFile()
}
fun src(filePath: String): String = KFiles.joinDir(KOBALT_DIR, SRC, filePath) fun src(filePath: String): String = KFiles.joinDir(KOBALT_DIR, SRC, filePath)
fun makeDir(project: Project, suffix: String) : File { fun makeDir(project: Project, suffix: String) : File {
@ -292,6 +300,8 @@ class KFiles {
fun isExcluded(file: String, excludes: Glob) = isExcluded(file, listOf(excludes)) fun isExcluded(file: String, excludes: Glob) = isExcluded(file, listOf(excludes))
fun isExcluded(file: File, excludes: Glob) = isExcluded(file.path, listOf(excludes))
fun isExcluded(file: File, excludes: List<Glob>) = isExcluded(file.path, excludes) fun isExcluded(file: File, excludes: List<Glob>) = isExcluded(file.path, excludes)
fun isExcluded(file: String, excludes: List<Glob>): Boolean = excludes.any { it.matches(file) } fun isExcluded(file: String, excludes: List<Glob>): Boolean = excludes.any { it.matches(file) }
@ -339,37 +349,6 @@ class KFiles {
return false return false
} }
} }
val dotKobaltDir = File(KFiles.joinAndMakeDir(KFiles.KOBALT_DOT_DIR))
/**
* Turn the IncludedFiles into actual Files
*/
fun materializeIncludedFiles(project: Project, includedFiles: List<IncludedFile>) : List<File> {
val result = includedFiles.fold(arrayListOf<File>()) { files, includedFile: IncludedFile ->
val foundFiles = includedFile.allFromFiles(project.directory)
val absFiles = foundFiles.map {
if (it.isAbsolute) {
it
} else if (File(includedFile.from).isAbsolute) {
File(includedFile.from, it.path)
} else {
File(KFiles.joinDir(project.directory, includedFile.from, it.path))
}
}
files.addAll(absFiles)
files
}
return result
}
fun copyRecursively(from: File, to: File, replaceExisting: Boolean = true, deleteFirst: Boolean = false) {
// fun copy(relativePath: String, sourceDir: File, targetDir: File) =
// sourceDir.resolve(relativePath).copyRecursively(targetDir.resolve(relativePath), overwrite = true)
if (from.isFile) FileUtils.copyFileToDirectory(from, to)
else FileUtils.copyDirectory(from, to)
}
} }
fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> { fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> {

View file

@ -2,16 +2,14 @@ package com.beust.kobalt.misc
import com.beust.kobalt.Args import com.beust.kobalt.Args
import com.beust.kobalt.AsciiArt import com.beust.kobalt.AsciiArt
import com.beust.kobalt.Constants
import com.beust.kobalt.KobaltException import com.beust.kobalt.KobaltException
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.maven.aether.Exceptions import com.beust.kobalt.maven.aether.Exceptions
import java.lang.Exception
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
fun Any.log(level: Int, text: CharSequence, newLine : Boolean = true) { fun Any.log(level: Int, text: CharSequence, newLine : Boolean = true) {
if (level <= KobaltLogger.LOG_LEVEL && !KobaltLogger.isQuiet) { if (level <= KobaltLogger.LOG_LEVEL) {
KobaltLogger.logger.log(javaClass.simpleName, text, newLine) KobaltLogger.logger.log(javaClass.simpleName, text, newLine)
} }
} }
@ -26,11 +24,11 @@ fun Any.kobaltLog(tag: String, text: CharSequence, newLine : Boolean = true) {
} }
fun Any.logWrap(level: Int, text1: CharSequence, text2: CharSequence, function: () -> Unit) { fun Any.logWrap(level: Int, text1: CharSequence, text2: CharSequence, function: () -> Unit) {
if (level <= KobaltLogger.LOG_LEVEL && !KobaltLogger.isQuiet) { if (level <= KobaltLogger.LOG_LEVEL) {
KobaltLogger.logger.log(javaClass.simpleName, text1, newLine = false) KobaltLogger.logger.log(javaClass.simpleName, text1, newLine = false)
} }
function() function()
if (level <= KobaltLogger.LOG_LEVEL && !KobaltLogger.isQuiet) { if (level <= KobaltLogger.LOG_LEVEL) {
KobaltLogger.logger.log(javaClass.simpleName, text2, newLine = true) KobaltLogger.logger.log(javaClass.simpleName, text2, newLine = true)
} }
} }
@ -52,22 +50,12 @@ fun Any.error(text: CharSequence, e: Throwable? = null) {
object KobaltLogger { object KobaltLogger {
var LOG_LEVEL: Int = 1 var LOG_LEVEL: Int = 1
val isQuiet: Boolean get() = (LOG_LEVEL == Constants.LOG_QUIET_LEVEL)
val logger: Logger get() = val logger: Logger get() =
if (Kobalt.context != null) { if (Kobalt.context != null) {
Logger(Kobalt.context!!.args.dev) Logger(Kobalt.context!!.args.dev)
} else { } else {
Logger(false) Logger(false)
} }
fun setLogLevel(args: Args) {
LOG_LEVEL = when {
args.log < Constants.LOG_QUIET_LEVEL -> Constants.LOG_DEFAULT_LEVEL
args.log > Constants.LOG_MAX_LEVEL -> Constants.LOG_MAX_LEVEL
else -> args.log
}
}
} }
class Logger(val dev: Boolean) { class Logger(val dev: Boolean) {
@ -86,8 +74,7 @@ class Logger(val dev: Boolean) {
fun error(tag: String, message: CharSequence, e: Throwable? = null) { fun error(tag: String, message: CharSequence, e: Throwable? = null) {
val docUrl = if (e is KobaltException && e.docUrl != null) e.docUrl else null val docUrl = if (e is KobaltException && e.docUrl != null) e.docUrl else null
val text = val text = if (! message.isBlank()) message
if (message.isNotBlank()) message
else if (e != null && (! e.message.isNullOrBlank())) e.message else if (e != null && (! e.message.isNullOrBlank())) e.message
else { e?.toString() } else { e?.toString() }
val shortMessage = "***** E $text " + if (docUrl != null) " Documentation: $docUrl" else "" val shortMessage = "***** E $text " + if (docUrl != null) " Documentation: $docUrl" else ""
@ -100,10 +87,7 @@ class Logger(val dev: Boolean) {
} }
fun warn(tag: String, message: CharSequence, e: Throwable? = null) { fun warn(tag: String, message: CharSequence, e: Throwable? = null) {
val fullMessage = "***** WARNING " + val fullMessage = "***** WARNING " + (e?.message ?: message)
if (message.isNotBlank()) message
else if (e != null && (!e.message.isNullOrBlank())) e.message
else e?.toString()
println(AsciiArt.Companion.warnColor(getPattern("W", fullMessage, fullMessage, tag))) println(AsciiArt.Companion.warnColor(getPattern("W", fullMessage, fullMessage, tag)))
if (KobaltLogger.LOG_LEVEL > 1 && e != null) { if (KobaltLogger.LOG_LEVEL > 1 && e != null) {
Exceptions.printStackTrace(e) Exceptions.printStackTrace(e)

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