1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-29 09:38:11 -07:00

Compare commits

..

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

160 changed files with 1904 additions and 5146 deletions

5
.gitignore vendored
View file

@ -2,14 +2,13 @@
annotations
.idea/*
*.iml
nonBuildScript
buildScript
kobaltBuild
local.properties
classes
libs
.kobalt/
./build/
out
.DS_Store
lib/kotlin-*
build
.history

View file

@ -1,6 +1,6 @@
# 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)
[<img src="https://teamcity.jetbrains.com/app/rest/builds/buildType:(id:OpenSourceProjects_Kobalt_Build)/statusIcon">](https://teamcity.jetbrains.com/project.html?projectId=OpenSourceProjects_Kobalt&tab=projectOverview)
Kobalt is a universal build system.
@ -8,7 +8,7 @@ Kobalt is a universal build system.
To build it:
```
$ ./kobaltw assemble
./kobaltw assemble
```
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'
}
}

10
dist/kobaltw vendored
View file

@ -1,11 +1,7 @@
#!/usr/bin/env sh
case "$(uname)" in
CYGWIN*) DIRNAME=$(cygpath -d "$(dirname "$(readlink -f "$0")")");;
Darwin*) DIRNAME=$(dirname "$(readlink "$0")");;
*) DIRNAME=$(dirname "$(readlink -f "$0")");;
esac
if [ "$DIRNAME" = "." ]; then
DIRNAME="$(dirname "$0")"
DIRNAME=`dirname $(readlink -f "$0")`
if [[ "$(uname)" == "CYGWIN"* ]]; then
DIRNAME=`cygpath -d "$DIRNAME"`
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,4 +1,3 @@
import com.beust.kobalt.*
import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.Task
@ -17,31 +16,21 @@ import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
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")
repos("http://dl.bintray.com/cbeust/maven")
}
object Versions {
val kotlin = "1.2.71"
val okhttp = "3.9.1"
val okio = "1.13.0"
val retrofit = "2.3.0"
val gson = "2.8.2"
val guice = "4.2.2"
val maven = "3.5.2"
val mavenResolver = "1.1.0"
val okhttp = "3.2.0"
val okio = "1.6.0"
val retrofit = "2.1.0"
val gson = "2.6.2"
val maven = "3.3.9"
val mavenResolver = "1.0.3"
val slf4j = "1.7.3"
val kotlin = "1.1.1"
val aether = "1.0.2.v20150114"
val testng = "6.12"
val jcommander = "1.72"
// JUnit 5
val junit = "4.12"
val junitPlatform = "1.1.0"
val junitJupiter = "5.1.0"
}
fun mavenResolver(vararg m: String)
@ -64,7 +53,6 @@ val wrapper = project {
}
assemble {
jar { }
jar {
name = projectName + ".jar"
manifest {
@ -76,13 +64,6 @@ val wrapper = project {
application {
mainClass = "com.beust.kobalt.wrapper.Main"
}
bintray {
publish = true
sign = true
}
pom = createPom(name, "Wrapper for Kobalt")
}
val kobaltPluginApi = project {
@ -92,42 +73,47 @@ val kobaltPluginApi = project {
version = readVersion()
directory = "modules/kobalt-plugin-api"
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 {
compile(
"org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}",
"com.google.inject:guice:${Versions.guice}",
"com.google.inject.extensions:guice-assistedinject:4.1.0",
"com.google.inject:guice:4.0",
"com.google.inject.extensions:guice-assistedinject:4.0",
"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}",
"io.reactivex:rxjava:1.3.3",
"io.reactivex:rxjava:1.1.5",
"com.squareup.okio:okio:${Versions.okio}",
"com.google.code.gson:gson:${Versions.gson}",
"com.squareup.okhttp3:okhttp:${Versions.okhttp}",
"com.squareup.retrofit2:retrofit:${Versions.retrofit}",
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
"com.beust:jcommander:${Versions.jcommander}",
"org.eclipse.jgit:org.eclipse.jgit:4.9.0.201710071750-r",
"com.beust:jcommander:1.48",
"org.eclipse.jgit:org.eclipse.jgit:4.5.0.201609210915-r",
"org.slf4j:slf4j-simple:${Versions.slf4j}",
*mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"),
"org.apache.maven:maven-aether-provider:3.3.9",
"org.testng.testng-remote:testng-remote:1.3.2",
"org.testng:testng:${Versions.testng}",
"org.junit.platform:junit-platform-surefire-provider:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-runner:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-engine:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-console:${Versions.junitPlatform}",
"org.junit.jupiter:junit-jupiter-engine:${Versions.junitJupiter}",
"org.junit.vintage:junit-vintage-engine:${Versions.junitJupiter}",
"org.apache.commons:commons-compress:1.15",
"commons-io:commons-io:2.6",
// Java 9
"javax.xml.bind:jaxb-api:2.3.0"
"org.testng.testng-remote:testng-remote:1.3.0",
"org.testng:testng:6.10"
)
exclude(*aether("impl", "spi", "util", "api"))
}
@ -142,8 +128,12 @@ val kobaltPluginApi = project {
}
}
// install {
// libDir = "lib-test"
// }
kotlinCompiler {
args("nowarn")
args("-nowarn")
}
bintray {
@ -162,32 +152,24 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
compile("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}")
// Used by the main app
compile(
"org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}",
"com.github.spullara.mustache.java:compiler:0.9.5",
compile("com.github.spullara.mustache.java:compiler:0.9.1",
"javax.inject:javax.inject:1",
"com.google.inject:guice:${Versions.guice}",
"com.google.inject.extensions:guice-assistedinject:${Versions.guice}",
"com.beust:jcommander:${Versions.jcommander}",
"com.google.inject:guice:4.0",
"com.google.inject.extensions:guice-assistedinject:4.0",
"com.beust:jcommander:1.65",
"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.squareup.retrofit2:retrofit:${Versions.retrofit}",
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
// "com.squareup.okhttp3:okhttp-ws:3.4.2",
"biz.aQute.bnd:biz.aQute.bndlib:3.5.0",
"com.squareup.okhttp3:okhttp-ws:${Versions.okhttp}",
"biz.aQute.bnd:bndlib:2.4.0",
*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",
"org.codehaus.groovy:groovy:2.4.12",
// Java 9
"javax.xml.bind:jaxb-api:2.3.0",
"com.sun.xml.bind:jaxb-impl:2.3.0",
"com.sun.xml.bind:jaxb-core:2.3.0",
"com.sun.activation:javax.activation:1.2.0"
"com.sparkjava:spark-core:2.5",
"org.codehaus.groovy:groovy:2.4.8"
// "org.eclipse.jetty:jetty-server:${Versions.jetty}",
// "org.eclipse.jetty:jetty-servlet:${Versions.jetty}",
@ -201,9 +183,8 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
}
dependenciesTest {
compile("org.jetbrains.kotlin:kotlin-test:${Versions.kotlin}",
"org.testng:testng:${Versions.testng}",
"org.assertj:assertj-core:3.8.0",
compile("org.testng:testng:6.10",
"org.assertj:assertj-core:3.4.1",
*mavenResolver("util")
)
}
@ -217,27 +198,17 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
}
zip {
val dir = "kobalt-$version"
val files = listOf(
"dist", "$dir/bin", "kobaltw",
"dist", "$dir/bin", "kobaltw.bat",
"$buildDirectory/libs", "$dir/kobalt/wrapper", "$projectName-$version.jar",
"modules/wrapper/$buildDirectory/libs", "$dir/kobalt/wrapper", "$projectName-wrapper.jar")
(0 .. files.size - 1 step 3).forEach { i ->
include(from(files[i]), to(files[i + 1]), files[i + 2])
}
// Package the sources
val currentDir = Paths.get(".").toAbsolutePath().normalize().toString()
zipFolders("$currentDir/$buildDirectory/libs/all-sources/$projectName-$version-sources.jar",
"$currentDir/$directory/src/main/kotlin",
"$currentDir/${kobaltPluginApi.directory}/src/main/kotlin")
include(from("$buildDirectory/libs/all-sources"), to("$dir/kobalt/wrapper"), "$projectName-$version-sources.jar")
include(from("dist"), to("$dir/bin"), "kobaltw")
include(from("dist"), to("$dir/bin"), "kobaltw.bat")
include(from("$buildDirectory/libs"), to("$dir/kobalt/wrapper"),
"$projectName-$version.jar")
include(from("modules/wrapper/$buildDirectory/libs"), to("$dir/kobalt/wrapper"),
"$projectName-wrapper.jar")
}
}
kotlinCompiler {
args("nowarn")
args("-nowarn")
}
bintray {
@ -257,28 +228,6 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
}
}
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 {
val localFile =
listOf("src/main/resources/kobalt.properties",
@ -305,22 +254,3 @@ fun taskCopyVersionForWrapper(project: Project) : 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"
})
}

View file

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

View file

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

View file

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

@ -3,6 +3,7 @@ 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.IncludedFile
import com.beust.kobalt.misc.KFiles
import java.io.File

View file

@ -7,7 +7,7 @@ class Args {
var targets: List<String> = arrayListOf()
@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 " +
"dependencies")
@ -22,10 +22,6 @@ class Args {
@Parameter(names = arrayOf("--download"), description = "Force a download from the downloadUrl in the wrapper")
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 " +
"actually running them")
var dryRun: Boolean = false
@ -47,7 +43,7 @@ class Args {
var listTemplates: Boolean = false
@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
@Parameter(names = arrayOf("--logTags"),
@ -61,9 +57,6 @@ class Args {
@Parameter(names = arrayOf("--noIncremental"), description = "Turn off incremental builds")
var noIncremental: Boolean = false
@Parameter(names = arrayOf("--offline"), description = "Don't try to download dependencies even if there is no cached version")
var offline: Boolean = false
@Parameter(names = arrayOf("--plugins"), description = "Comma-separated list of plug-in Maven id's")
var pluginIds: String? = null
@ -104,8 +97,5 @@ class Args {
@Parameter(names = arrayOf("--update"), description = "Update to the latest version of Kobalt")
var update: Boolean = false
@Parameter(names = arrayOf("--version"), description = "Display the current version of Kobalt")
var version: Boolean = false
}

View file

@ -31,10 +31,6 @@ class BuildScriptConfig {
@Directive
fun kobaltOptions(vararg options: String) = Kobalt.addKobaltOptions(options)
/** Where to find additional build files */
@Directive
fun buildSourceDirs(vararg dirs: String) = Kobalt.addBuildSourceDirs(dirs)
// The following settings modify the compiler used to compile the build file, which regular users should
// probably never need to do. Projects should use kotlinCompiler { compilerVersion } to configure the
// Kotin compiler for their source files.
@ -74,18 +70,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
}
data class HostConfig(var url: String = "", var name: String = HostConfig.createRepoName(url),
var username: String? = null, var password: String? = null) {
companion object {
/**
* For repos specified in the build file (repos()) that don't have an associated unique name,
* create such a name from the URL. This is a requirement from Maven Resolver, and failing to do
* this leads to very weird resolution errors.
*/
private fun createRepoName(url: String) = url.replace("/", "_").replace("\\", "_").replace(":", "_")
}
data class HostConfig(var url: String = "", var username: String? = null, var password: String? = null) {
fun hasAuth() : Boolean {
return (! username.isNullOrBlank()) && (! password.isNullOrBlank())
}
@ -116,7 +101,6 @@ fun buildFileClasspath(vararg deps: String) {
}
fun newBuildFileClasspath(vararg deps: String) {
//FIXME newBuildFileClasspath called twice
deps.forEach { Kobalt.addBuildFileClasspath(it) }
}
@ -126,7 +110,7 @@ fun authRepos(vararg repos : HostConfig) {
}
@Directive
fun authRepo(init: HostConfig.() -> Unit) = HostConfig(name = "").apply { init() }
fun authRepo(init: HostConfig.() -> Unit) = HostConfig().apply { init() }
@Directive
fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g)
@ -143,3 +127,4 @@ fun localMaven() : String {
}
return result.toURI().toString()
}

View file

@ -3,19 +3,20 @@ package com.beust.kobalt
import com.beust.kobalt.misc.KFiles
object Constants {
const val LOG_QUIET_LEVEL = 0
const val LOG_DEFAULT_LEVEL = 1
const val LOG_MAX_LEVEL = 3
val BUILD_FILE_NAME = "Build.kt"
val BUILD_FILE_DIRECTORY = "kobalt/src"
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.1"
internal val DEFAULT_REPOS = listOf<HostConfig>(
internal val DEFAULT_REPOS = listOf<String>(
// "https://maven-central.storage.googleapis.com/",
HostConfig("https://repo1.maven.org/maven2/", "Maven"),
HostConfig("https://jcenter.bintray.com/", "JCenter")
// "https://repository.jetbrains.com/all/", // <-- contains snapshots
"http://repo1.maven.org/maven2/",
"https://jcenter.bintray.com/",
// "http://repository.jetbrains.com/all/", // <-- contains snapshots
"https://dl.bintray.com/kotlin/kotlin-eap",
"https://dl.bintray.com/kotlin/kotlin-eap-1.1"
// snapshots
// "https://oss.sonatype.org/content/repositories/snapshots/"

View file

@ -28,15 +28,15 @@ sealed class IFileSpec {
private fun isIncluded(includeMatchers: Glob, excludes: List<Glob>, rel: Path) : Boolean {
excludes.forEach {
if (it.matches(rel)) {
kobaltLog(3, " Excluding ${rel.toFile()}")
kobaltLog(3, "Excluding ${rel.toFile()}")
return false
}
}
if (includeMatchers.matches(rel)) {
kobaltLog(3, " Including ${rel.toFile().path}")
kobaltLog(3, "Including ${rel.toFile().path}")
return true
}
kobaltLog(2, " Excluding ${rel.toFile()} (not matching any include pattern")
kobaltLog(2, "Excluding ${rel.toFile()} (not matching any include pattern")
return false
}

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,16 +3,16 @@ package com.beust.kobalt
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.archive.Archives
import com.beust.kobalt.archive.MetaArchive
import com.beust.kobalt.archive.Zip
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.kobaltLog
import com.beust.kobalt.misc.*
import com.google.inject.Inject
import java.io.File
import java.io.FileInputStream
import java.io.OutputStream
import java.nio.file.Paths
import java.util.jar.JarOutputStream
import java.util.jar.Manifest
class JarGenerator @Inject constructor(val dependencyManager: DependencyManager) : ArchiveGenerator {
@ -142,7 +142,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
val allFiles = includedFiles.flatMap { file ->
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
}
@ -151,12 +151,14 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
context.logger.log(project.name, 2, "Including MANIFEST.MF file $manifestFile")
Manifest(FileInputStream(manifestFile))
} else {
null
Manifest()
}
}
val jarFactory = { os: OutputStream -> JarOutputStream(os, manifest) }
return Archives.generateArchive(project, context, zip.name, ".jar", includedFiles,
true /* expandJarFiles */, manifest)
true /* expandJarFiles */, jarFactory)
}
}

View file

@ -67,7 +67,7 @@ open class Jvm constructor(
return toolsJar
}
if (javaHome!!.name.equals("jre", true)) {
_javaHome = javaHome!!.parentFile
javaHome = javaHome!!.parentFile
toolsJar = File(javaHome, "lib/tools.jar")
if (toolsJar.exists()) {
return toolsJar
@ -78,7 +78,7 @@ open class Jvm constructor(
val version = SystemProperties.Companion.javaVersion
if (javaHome!!.name.toRegex().matches("jre\\d+")
|| javaHome!!.name == "jre$version") {
_javaHome = File(javaHome!!.parentFile, "jdk$version")
javaHome = File(javaHome!!.parentFile, "jdk$version")
toolsJar = File(javaHome, "lib/tools.jar")
if (toolsJar.exists()) {
return toolsJar

View file

@ -28,6 +28,7 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
val depManager: DependencyManager,
val settings: KobaltSettings,
val executors: KobaltExecutors,
val pluginInfo: PluginInfo,
val incrementalManagerFactory: IncrementalManager.IFactory,
val taskManager: TaskManager) {
@ -170,9 +171,6 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider<TaskManage
val dependencies = arrayListOf<IClasspathDependency>()
// @Inject
// lateinit var pluginInfo: PluginInfo
fun installPlugins(dependencies: List<IClasspathDependency>, scriptClassLoader: ClassLoader) {
val executor = executors.newExecutor("Plugins", 5)
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
JarUtils.extractTextFile(JarFile(file), PluginInfo.PLUGIN_XML)
}
val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java)
if (pluginXml != null) {
val pluginClassLoader = URLClassLoader(arrayOf(file.toURI().toURL()))
val thisPluginInfo = PluginInfo.readPluginXml(pluginXml, pluginClassLoader, scriptClassLoader)

View file

@ -3,8 +3,13 @@ package com.beust.kobalt
import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.MavenId
import com.beust.kobalt.maven.aether.*
import com.beust.kobalt.misc.*
import com.beust.kobalt.maven.aether.AetherDependency
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.beust.kobalt.misc.warn
import com.google.inject.Inject
import org.eclipse.aether.artifact.DefaultArtifact
import org.eclipse.aether.graph.DependencyNode
@ -29,7 +34,7 @@ class ResolveDependency @Inject constructor(
private fun latestMavenArtifact(group: String, artifactId: String, extension: String = "jar"): DependencyNode {
val artifact = DefaultArtifact(group, artifactId, extension, "(0,]")
val resolved = aether.resolveRange(artifact)
val resolved = aether.resolveVersion(artifact)
if (resolved != null) {
val newArtifact = DefaultArtifact(artifact.groupId, artifact.artifactId, artifact.extension,
resolved.highestVersion.toString())
@ -69,7 +74,7 @@ class ResolveDependency @Inject constructor(
kobaltLog(1, AsciiArt.logBox(listOf(dep.id, url, dep.jarFile.get()).map { " $it" }))
display(root.children)
kobaltLog(1, "")
println("")
}
private fun display(nodes: List<Node<Dep>>) {
@ -81,12 +86,10 @@ class ResolveDependency @Inject constructor(
else leftMiddle
val indent = level * increment
for(i in 0..indent - 2) {
if (!KobaltLogger.isQuiet) {
if (i == 0 || ((i + 1) % increment == 0)) print(vertical)
else print(" ")
}
if (i == 0 || ((i + 1) % increment == 0)) print(vertical)
else print(" ")
}
kobaltLog(1, left + " " + dep.id + (if (dep.optional) " (optional)" else ""))
println(left + " " + dep.id + (if (dep.optional) " (optional)" else ""))
display(node.children)
}
}

View file

@ -2,16 +2,8 @@ package com.beust.kobalt
class SystemProperties {
companion object {
val javaBase : String
get() {
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 javaBase = System.getProperty("java.home") ?:
(System.getenv("JAVA_HOME") ?: throw IllegalArgumentException("JAVA_HOME not defined"))
val javaVersion = System.getProperty("java.version")
val homeDir = System.getProperty("user.home")
val tmpDir = System.getProperty("java.io.tmpdir")

View file

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

View file

@ -126,62 +126,61 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null,
var generatedSourceDirectory: File? = null
private fun findBuildTypeBuildConfig(project: Project, variant: Variant?) : BuildConfig? {
val buildTypeName = variant?.buildType?.name
return project.buildTypes[buildTypeName]?.buildConfig
}
private fun findProductFlavorBuildConfig(project: Project, variant: Variant?) : BuildConfig? {
val buildTypeName = variant?.productFlavor?.name
return project.productFlavors[buildTypeName]?.buildConfig
}
// private fun findBuildTypeBuildConfig(project: Project, variant: Variant?) : BuildConfig? {
// val buildTypeName = variant?.buildType?.name
// return project.buildTypes[buildTypeName]?.buildConfig
// }
//
// private fun findProductFlavorBuildConfig(project: Project, variant: Variant?) : BuildConfig? {
// val buildTypeName = variant?.productFlavor?.name
// return project.productFlavors[buildTypeName]?.buildConfig
// }
/**
* Return a list of the BuildConfigs found on the productFlavor{}, buildType{} and project{} (in that order).
*/
private fun findBuildConfigs(project: Project, variant: Variant?) : List<BuildConfig> {
val result = listOf(
findBuildTypeBuildConfig(project, variant),
findProductFlavorBuildConfig(project, variant),
project.buildConfig)
.filterNotNull()
return result
}
// private fun findBuildConfigs(project: Project, variant: Variant?) : List<BuildConfig> {
// val result = listOf(
// findBuildTypeBuildConfig(project, variant),
// findProductFlavorBuildConfig(project, variant),
// project.buildConfig)
// .filterNotNull()
//
// return result
// }
/**
* Generate BuildConfig.java if requested. Also look up if any BuildConfig is defined on the current build type,
* product flavor or main project, and use them to generateAndSave any additional field (in that order to
* respect the priorities). Return the generated file if it was generated, null otherwise.
*/
fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? {
val buildConfigs = findBuildConfigs(project, this)
if (buildConfigs.size > 0) {
val pkg = project.packageName ?: project.group
?: throw KobaltException(
"packageName needs to be defined on the project in order to generateAndSave BuildConfig")
val contributor = ActorUtils.selectAffinityActor(project, context,
context.pluginInfo.buildConfigContributors)
if (contributor != null) {
val code = contributor.generateBuildConfig(project, context, pkg, this, buildConfigs)
val result = KFiles.makeDir(KFiles.generatedSourceDir(project, this, "buildConfig"))
// Make sure the generatedSourceDirectory doesn't contain the project.directory since
// that directory will be added when trying to find recursively all the sources in it
generatedSourceDirectory = result.relativeTo(File(project.directory))
val outputGeneratedSourceDirectory = File(result, pkg.replace('.', File.separatorChar))
val outputDir = File(outputGeneratedSourceDirectory, "BuildConfig." + contributor.buildConfigSuffix)
KFiles.saveFile(outputDir, code)
context.logger.log(project.name, 2, "Generated ${outputDir.path}")
return result
} else {
throw KobaltException("Couldn't find a contributor to generateAndSave BuildConfig")
}
} else {
return null
}
}
// fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? {
// val buildConfigs = findBuildConfigs(project, this)
//
// if (buildConfigs.size > 0) {
// val pkg = project.packageName ?: project.group
// ?: throw KobaltException(
// "packageName needs to be defined on the project in order to generateAndSave BuildConfig")
//
// val contributor = ActorUtils.selectAffinityActor(context.pluginInfo.buildConfigContributors, project)
// if (contributor != null) {
// val code = contributor.generateBuildConfig(project, context, pkg, this, buildConfigs)
// val result = KFiles.makeDir(KFiles.generatedSourceDir(project, this, "buildConfig"))
// // Make sure the generatedSourceDirectory doesn't contain the project.directory since
// // that directory will be added when trying to find recursively all the sources in it
// generatedSourceDirectory = result.relativeTo(File(project.directory))
// val outputGeneratedSourceDirectory = File(result, pkg.replace('.', File.separatorChar))
// val outputDir = File(outputGeneratedSourceDirectory, "BuildConfig." + contributor.buildConfigSuffix)
// KFiles.saveFile(outputDir, code)
// context.logger.log(project.name, 2, "Generated ${outputDir.path}")
// return result
// } else {
// throw KobaltException("Couldn't find a contributor to generateAndSave BuildConfig")
// }
// } else {
// return null
// }
// }
override fun toString() = toTask("")

View file

@ -12,5 +12,4 @@ data class CompilerActionInfo(val directory: String?,
val outputDir: File,
val compilerArgs: List<String>,
val friendPaths: List<String>,
val forceRecompile: Boolean,
val compilerSeparateProcess: Boolean = false)
val forceRecompile: Boolean)

View file

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

View file

@ -5,7 +5,7 @@ import com.beust.kobalt.Variant
/**
* 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,
buildConfigs: List<BuildConfig>) : String

View file

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

View file

@ -61,7 +61,7 @@ interface IDependencyManager {
return excluded?.map { it.id }?.contains(dep.id) ?: false
}
val accept = dependencies.isEmpty() || dependencies.any {
val accept = dependencies.any {
// Is this dependency excluded?
val isExcluded = isNodeExcluded(p0, it) || isDepExcluded(p0, project?.excludedDependencies)

View file

@ -1,11 +1,10 @@
package com.beust.kobalt.api
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.
*
* Currently not used.
*/
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> {
val taskResult = closure.invoke(project)
return TaskResult2(taskResult.success, errorMessage = taskResult.errorMessage, value = this)
return TaskResult2(taskResult.success, taskResult.errorMessage, this)
}
override fun toString() =
"[DynamicTask ${project.name}:$name dependsOn=$dependsOn reverseDependsOn=$reverseDependsOn]"
override fun toString() = "[DynamicTask $name dependsOn=$dependsOn reverseDependsOn=$reverseDependsOn]"
}

View file

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

@ -91,8 +91,7 @@ open class Project(
@Directive
fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies {
dependencies = Dependencies(this, testDependencies, arrayListOf(),
testProvidedDependencies, compileOnlyDependencies, compileRuntimeDependencies,
excludedDependencies, nativeDependencies)
testProvidedDependencies, compileRuntimeDependencies, excludedDependencies, nativeDependencies)
dependencies!!.init()
return dependencies!!
}
@ -129,18 +128,6 @@ open class Project(
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]"
}
@ -155,7 +142,6 @@ class Dependencies(val project: Project,
val dependencies: ArrayList<IClasspathDependency>,
val optionalDependencies: ArrayList<IClasspathDependency>,
val providedDependencies: ArrayList<IClasspathDependency>,
val compileOnlyDependencies: ArrayList<IClasspathDependency>,
val runtimeDependencies: ArrayList<IClasspathDependency>,
val excludedDependencies: ArrayList<IClasspathDependency>,
val nativeDependencies: ArrayList<IClasspathDependency>) {
@ -246,9 +232,6 @@ class Dependencies(val project: Project,
addToDependencies(project, dependencies, arrayOf(dep), excludeConfig = excludeConfig)
}
@Directive
fun compileOnly(vararg dep: String) = addToDependencies(project, compileOnlyDependencies, dep)
@Directive
fun compileOptional(vararg dep: String) {
addToDependencies(project, optionalDependencies, dep, optional = true)
@ -258,6 +241,7 @@ class Dependencies(val project: Project,
@Directive
fun provided(vararg dep: String) {
addToDependencies(project, providedDependencies, dep)
addToDependencies(project, dependencies, dep)
}
@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,
group: String = AnnotationDefault.GROUP,
dependsOn: List<String> = emptyList(),

View file

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

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

@ -6,7 +6,7 @@ import com.beust.kobalt.glob
class War(override val project: Project, override var name: String = Archives.defaultArchiveName(project) + ".war")
: Jar(project, name), AttributeHolder {
init {
include(from("src/main/webapp"), to(""), glob("**"))
include(from("src/main/webapp"),to(""), glob("**"))
include(from("kobaltBuild/classes"), to("WEB-INF/classes"), glob("**"))
}
}

View file

@ -1,13 +1,23 @@
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.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 var fatJar: Boolean = false): AttributeHolder, IncludeFromTo() {
open var fatJar: Boolean = false): AttributeHolder {
val excludes = arrayListOf<Glob>()
@Directive
fun from(s: String) = From(s)
@Directive
fun to(s: String) = To(s)
@Directive
fun exclude(vararg files: String) {
files.forEach { excludes.add(Glob(it)) }
@ -18,10 +28,34 @@ open class Zip(open val project: Project, open var name: String = Archives.defau
specs.forEach { excludes.add(it) }
}
@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)))
}
/**
* 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
open val attributes = arrayListOf(Pair("Manifest-Version", "1.0"))
override fun addAttribute(k: String, v: String) {
attributes.add(Pair(k, v))
}
}

View file

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

View file

@ -11,8 +11,7 @@ import java.util.concurrent.ConcurrentHashMap
*/
class BuildListeners : IBuildListener, IBuildReportContributor {
class ProfilerInfo(val taskName: String, val durationMillis: Long)
class ProjectInfo(val projectName: String, var durationMillis: Long = 0,
var shortMessage: String? = null, var longMessage: String? = null)
class ProjectInfo(val projectName: String, var durationMillis: Long = 0)
private val startTimes = ConcurrentHashMap<String, Long>()
private val timings = arrayListOf<ProfilerInfo>()
@ -30,21 +29,18 @@ class BuildListeners : IBuildListener, IBuildReportContributor {
}
// IBuildListener
override fun taskEnd(project: Project, context: KobaltContext, taskName: String, info: IBuildListener.TaskEndInfo) {
val success = info.success
override fun taskEnd(project: Project, context: KobaltContext, taskName: String, success: Boolean) {
if (! success) hasFailures = true
startTimes[taskName]?.let {
val taskTime = System.currentTimeMillis() - it
timings.add(ProfilerInfo(taskName, taskTime))
projectInfos[project.name]?.let {
it.durationMillis += taskTime
if (info.shortMessage != null && it.shortMessage == null) it.shortMessage = info.shortMessage
if (info.longMessage != null && it.longMessage == null) it.longMessage = info.longMessage
it.durationMillis += taskTime.toLong()
}
}
}
private val projectStatuses = arrayListOf<Pair<Project, String>>()
private val projectStatuses = arrayListOf<Pair<Project, ProjectBuildStatus>>()
// IBuildListener
override fun projectStart(project: Project, context: KobaltContext) {
@ -53,9 +49,7 @@ class BuildListeners : IBuildListener, IBuildReportContributor {
// IBuildListener
override fun projectEnd(project: Project, context: KobaltContext, status: ProjectBuildStatus) {
val shortMessage = projectInfos[project.name]?.shortMessage
val statusText = status.toString() + (if (shortMessage != null) " ($shortMessage)" else "")
projectStatuses.add(Pair(project, statusText))
projectStatuses.add(Pair(project, status))
}
// 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 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)
// Only print the build report if there is more than one project and at least one of them failed
if (timings.any()) {
// 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")
projectStatuses.forEach { pair ->
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)))
.joinToString(AsciiArt.verticalBar)
table.append(" " + AsciiArt.verticalBar + " " + cl + " " + AsciiArt.verticalBar + "\n")

View file

@ -70,12 +70,7 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
copyResources(project, context, SourceSet.of(isTest))
val fullClasspath = dependencyManager.calculateDependencies(project, context,
scopes = if (isTest) {
listOf(Scope.COMPILE, Scope.COMPILEONLY, Scope.TEST)
} else {
listOf(Scope.COMPILE, Scope.COMPILEONLY)
})
scopes = if (isTest) listOf(Scope.COMPILE, Scope.TEST) else listOf(Scope.COMPILE))
File(project.directory, buildDirectory.path).mkdirs()
@ -201,7 +196,7 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
.filter(File::exists)
.forEach {
context.logger.log(project.name, 2, "Copying from $it to $absOutputDir")
KFiles.copyRecursively(it, absOutputDir, replaceExisting = true)
KFiles.copyRecursively(it, absOutputDir, deleteFirst = false)
}
} else {
context.logger.log(project.name, 2, "No resources to copy for $sourceSet")

View file

@ -2,7 +2,7 @@ package com.beust.kobalt.internal
class DocUrl {
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
val PUBLISH_PLUGIN_URL = url("plug-ins/index.html#publishing")

View file

@ -1,14 +1,18 @@
package com.beust.kobalt.internal
import com.beust.kobalt.*
import com.beust.kobalt.misc.*
import com.beust.kobalt.AsciiTable
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 java.lang.reflect.InvocationTargetException
import java.util.*
import java.util.concurrent.*
open class TaskResult2<T>(success: Boolean, testResult: TestResult? = null,
errorMessage: String? = null, val value: T) : TaskResult(success, testResult, errorMessage) {
open class TaskResult2<T>(success: Boolean, errorMessage: String?, val value: T) : TaskResult(success, errorMessage) {
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)
.toInt().toString() + ")"
} else {
kobaltLog(1, "DONOTCOMMIT")
println("DONOTCOMMIT")
}
}
return hl.name + duration
}
historyLog.forEach { hl ->
kobaltLog(1, "CURRENT LOG: " + currentLog + " HISTORY LINE: " + hl)
println("CURRENT LOG: " + currentLog + " HISTORY LINE: " + hl)
if (hl.start) {
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))
} else currentLog?.let { cl ->
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)
} else {
kobaltLog(1, " ADDING COMPRESSED LINE $cl")
println(" ADDING COMPRESSED LINE $cl")
compressed.add(cl)
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
}
kobaltLog(1, displayRegularLog(table).build())
println(displayRegularLog(table).build())
}
}
@ -394,7 +398,7 @@ fun main(argv: Array<String>) {
object: IWorker<String> {
override fun call(): TaskResult2<String>? {
kobaltLog(1, " Running worker $it")
return TaskResult2(true, value = it)
return TaskResult2(true, null, it)
}
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.misc.KFiles
import com.google.common.annotations.VisibleForTesting
import com.google.inject.Inject
import java.io.File
import java.util.*
@ -16,27 +15,14 @@ abstract class GenericTestRunner: ITestRunnerContributor {
abstract val dependencyName : String
abstract val mainClass: 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>,
testConfig: TestConfig) : List<String>
open fun onFinish(project: Project) {}
open val extraClasspath: List<String> = emptyList()
open fun filterTestClasses(project: Project, context: KobaltContext, classes: List<String>) : List<String> = classes
open fun filterTestClasses(classes: List<String>) : List<String> = classes
override fun run(project: Project, context: KobaltContext, configName: String,
classpath: List<IClasspathDependency>) : TaskResult {
val tr = runTests(project, context, classpath, configName)
return TaskResult(tr.success, testResult = tr)
}
classpath: List<IClasspathDependency>)
= TaskResult(runTests(project, context, classpath, configName))
override fun affinity(project: Project, context: KobaltContext) : Int {
val result =
@ -69,7 +55,7 @@ abstract class GenericTestRunner: ITestRunnerContributor {
// }
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 })
}
/**
@ -109,19 +95,18 @@ abstract class GenericTestRunner: ITestRunnerContributor {
* @return true if all the tests passed
*/
open fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
configName: String) : TestResult {
configName: String) : Boolean {
var result = false
context.logger.log(project.name, 1, "Running tests with $runnerName")
context.logger.log(project.name, 1, "Running default TestNG runner")
val testConfig = project.testConfigs.firstOrNull { it.name == configName }
var errorCode = -1
if (testConfig != null) {
val args = args(project, context, classpath, testConfig)
if (args.size > 0) {
val java = jvm.javaExecutable
val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable
val jvmArgs = calculateAllJvmArgs(project, context, testConfig, classpath,
Kobalt.INJECTOR.getInstance (PluginInfo::class.java))
val allArgs = arrayListOf<String>().apply {
@ -137,7 +122,12 @@ abstract class GenericTestRunner: ITestRunnerContributor {
context.logger.log(project.name, 2, "Running tests with classpath size ${classpath.size}")
context.logger.log(project.name, 2, "Launching " + allArgs.joinToString(" "))
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
} else {
context.logger.log(project.name, 1, " No tests to run")
@ -146,16 +136,7 @@ abstract class GenericTestRunner: ITestRunnerContributor {
} else {
throw KobaltException("Couldn't find a test configuration named \"$configName\"")
}
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)
return result
}
/*
@ -163,14 +144,13 @@ abstract class GenericTestRunner: ITestRunnerContributor {
*/
@VisibleForTesting
fun calculateAllJvmArgs(project: Project, context: KobaltContext,
testConfig: TestConfig, classpath: List<IClasspathDependency>, pluginInfo: IPluginInfo) : List<String> {
val fullClasspath = classpath.map { it.jarFile.get().absolutePath } + extraClasspath
testConfig: TestConfig, classpath: List<IClasspathDependency>, pluginInfo: IPluginInfo) : List<String> {
// Default JVM args
val jvmFlags = arrayListOf<String>().apply {
addAll(testConfig.jvmArgs)
add("-ea")
add("-classpath")
add(fullClasspath.joinToString(File.pathSeparator))
add(classpath.map { it.jarFile.get().absolutePath }.joinToString(File.pathSeparator))
}
// 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.KobaltContext
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() {
override val mainClass = "org.junit.runner.JUnitCore"
override val annotationPackage = "org.junit"
override val dependencyName = "junit"
override val runnerName = "JUnit 4"
override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
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

@ -28,6 +28,7 @@ class JvmCompiler @Inject constructor(val dependencyManager: DependencyManager)
.distinct()
// 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 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.Task
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.Md5
import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.KFiles
@ -26,6 +27,7 @@ import javax.inject.Singleton
*/
@Singleton
open class JvmCompilerPlugin @Inject constructor(
open val localRepo: LocalRepo,
open val files: KFiles,
open val dependencyManager: DependencyManager,
open val executors: KobaltExecutors,
@ -89,7 +91,7 @@ open class JvmCompilerPlugin @Inject constructor(
dependencyFilter = dependencyManager.createDependencyFilter(project, project.testDependencies),
scopes = listOf(Scope.TEST))
val compileDependencies = dependencyManager.calculateDependencies(project, context,
scopes = listOf(Scope.COMPILE, Scope.COMPILEONLY))
scopes = listOf(Scope.COMPILE))
val allDependencies = (testDependencies + compileDependencies).distinct()
return testContributor.run(project, context, configName, allDependencies.toList())
} else {
@ -157,10 +159,6 @@ open class JvmCompilerPlugin @Inject constructor(
if (compilerContributors.isEmpty()) {
throw KobaltException("Couldn't find any compiler for project ${project.name}")
} else {
// Generate BuildConfig if applicable
context.variant.maybeGenerateBuildConfig(project, context)
val allCompilers = compilerContributors.flatMap { it.compilersFor(project, context)}.sorted()
/**
@ -174,10 +172,7 @@ open class JvmCompilerPlugin @Inject constructor(
if (wi.value.sourceSuffixes.contains("java")) ij = 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
}
@ -187,8 +182,8 @@ open class JvmCompilerPlugin @Inject constructor(
var done = false
// The directory where the classes get compiled
val buildDirectory =
if (isTest) File(KFiles.joinDir(project.buildDirectory, KFiles.TEST_CLASSES_DIR))
else File(KFiles.joinDir(project.classesDir(context)))
if (isTest) File(project.buildDirectory, KFiles.TEST_CLASSES_DIR)
else File(project.classesDir(context))
allCompilersSorted.doWhile({ ! done }) { compiler ->
val compilerResults = compilerUtils.invokeCompiler(project, context, compiler,
@ -226,7 +221,7 @@ open class JvmCompilerPlugin @Inject constructor(
}
@Task(name = "doc", description = "Generate the documentation for the project", group = GROUP_DOCUMENTATION,
runBefore = arrayOf("assemble"), runAfter = arrayOf("clean"))
runBefore = arrayOf("assemble"))
fun taskJavadoc(project: Project): TaskResult {
val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors)
if (docGenerator != null) {

View file

@ -78,7 +78,7 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
val compilerInterceptors = arrayListOf<ICompilerInterceptor>()
val sourceDirectoriesInterceptors = arrayListOf<ISourceDirectoryInterceptor>()
val buildDirectoryInterceptors = arrayListOf<IBuildDirectoryInterceptor>()
// val runnerContributors = arrayListOf<IRunnerContributor>()
val runnerContributors = arrayListOf<IRunnerContributor>()
val testRunnerContributors = arrayListOf<ITestRunnerContributor>()
val classpathInterceptors = arrayListOf<IClasspathInterceptor>()
val compilerContributors = arrayListOf<ICompilerContributor>()
@ -197,7 +197,7 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
if (this is IPlugin) plugins.add(this)
if (this is IProjectContributor) projectContributors.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 ISourceDirectoryInterceptor) sourceDirectoriesInterceptors.add(this)
if (this is ITaskContributor) taskContributors.add(this)
@ -225,7 +225,7 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
listOf(projectContributors, classpathContributors, templateContributors,
repoContributors, compilerFlagContributors, compilerInterceptors,
sourceDirectoriesInterceptors, buildDirectoryInterceptors,
/* runnerContributors, */ testRunnerContributors, classpathInterceptors,
runnerContributors, testRunnerContributors, classpathInterceptors,
compilerContributors, docContributors, sourceDirContributors,
testSourceDirContributors, buildConfigFieldContributors,
taskContributors, incrementalTaskContributors, assemblyContributors,
@ -252,7 +252,7 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
compilerInterceptors.addAll(pluginInfo.compilerInterceptors)
sourceDirectoriesInterceptors.addAll(pluginInfo.sourceDirectoriesInterceptors)
buildDirectoryInterceptors.addAll(pluginInfo.buildDirectoryInterceptors)
// runnerContributors.addAll(pluginInfo.runnerContributors)
runnerContributors.addAll(pluginInfo.runnerContributors)
testRunnerContributors.addAll(pluginInfo.testRunnerContributors)
classpathInterceptors.addAll(pluginInfo.classpathInterceptors)
compilerContributors.addAll(pluginInfo.compilerContributors)

View file

@ -25,7 +25,7 @@ class KobaltSettingsXml {
@XmlElement(name = "localMavenRepo") @JvmField
var localMavenRepo: String = homeDir(KFiles.KOBALT_DOT_DIR, "localMavenRepo")
@XmlElement(name = "defaultRepos") @JvmField
@XmlElement(name = "defaulRepos") @JvmField
var defaultRepos: DefaultReposXml? = null
@XmlElement(name = "proxies") @JvmField
@ -42,9 +42,6 @@ class KobaltSettingsXml {
@XmlElement(name = "kobaltCompilerSeparateProcess") @JvmField
var kobaltCompilerSeparateProcess: Boolean = false
@XmlElement(name = "autoUpdate") @JvmField
var autoUpdate: Boolean = false
}
class ProxiesXml {
@ -88,11 +85,6 @@ class KobaltSettings @Inject constructor(val xmlFile: KobaltSettingsXml) {
*/
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
* 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 runtime: File get() = getKotlinCompilerJar("runtime")
val compiler: File get() = getKotlinCompilerJar("compiler-embeddable")
}

View file

@ -1,21 +1,16 @@
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
* uses the regular JUnitRunner.
*/
class KotlinTestRunner : JUnitRunner() {
override val dependencyName = "io.kotlintest"
override val runnerName = "Kotlin Test"
/**
* KotlinTestRunner runs tests in the init{} initializer, so ignore all the extra
* classes generated by the Kotlin compiler.
*/
override fun filterTestClasses(projet: Project, context: KobaltContext, classes: List<String>)
= classes.filter { !it.contains("$") }
override fun filterTestClasses(classes: List<String>) = classes.filter { ! it.contains("$") }
}

View file

@ -2,7 +2,9 @@ package com.beust.kobalt.internal
import com.beust.kobalt.Args
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.Singleton
import java.util.*
@ -67,7 +69,7 @@ class ParallelLogger @Inject constructor(val args: Args) : ILogger {
private fun debug(s: CharSequence) {
if (args.log >= 3) {
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 {
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)
logger.log(project.name, 1,
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) {
lastResult = thisResult
}
runBuildListenersForTask(project, context, task.name, start = false,
success = thisResult.success, testResult = thisResult.testResult)
success = thisResult.success)
}
}
graph.freeNodes.forEach { graph.removeNode(it) }
@ -69,7 +69,7 @@ class ParallelProjectRunner(val tasksByNames: (Project) -> ListMultimap<String,
runBuildListenersForProject(project, context, false,
if (lastResult.success) ProjectBuildStatus.SUCCESS else ProjectBuildStatus.FAILED)
return TaskResult2(lastResult.success, errorMessage = lastResult.errorMessage, value = this)
return TaskResult2(lastResult.success, lastResult.errorMessage, this)
}
}

View file

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

View file

@ -17,7 +17,7 @@ import javax.inject.Singleton
@Singleton
class TaskManager @Inject constructor(val args: Args,
val incrementalManagerFactory: IncrementalManager.IFactory,
val kobaltLog: ParallelLogger) {
val pluginInfo: PluginInfo, val kobaltLog: ParallelLogger) {
private val dependsOn = TreeMultimap.create<String, String>()
private val reverseDependsOn = 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 {
// Check whether tasks passed at command line exist
passedTaskNames.forEach {
@ -90,7 +87,6 @@ class TaskManager @Inject constructor(val args: Args,
throw KobaltException("Unknown task: $it")
}
val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java)
var taskInfos = calculateDependentTaskNames(passedTaskNames, allProjects)
// Remove non existing tasks (e.g. dynamic task defined for a single project)
@ -272,8 +268,7 @@ class TaskManager @Inject constructor(val args: Args,
object : BasePluginTask(plugin, name, description, group, project) {
override fun call(): TaskResult2<ITask> {
val taskResult = task(project)
return TaskResult2(taskResult.success, errorMessage = taskResult.errorMessage, value = this,
testResult = taskResult.testResult)
return TaskResult2(taskResult.success, taskResult.errorMessage, this)
}
})
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()
BaseProjectRunner.runBuildListenersForTask(it.project, context, name, start = false, success = tr.success)
success = success and tr.success
tr.errorMessage?.let {
errorMessages.add(it)
}
if (tr.errorMessage != null) errorMessages.add(tr.errorMessage)
}
return TaskResult2(success, errorMessage = errorMessages.joinToString("\n"), value = tasks[0])
return TaskResult2(success, errorMessages.joinToString("\n"), tasks[0])
}
// override val timeOut : Long = 10000

View file

@ -2,52 +2,38 @@ package com.beust.kobalt.internal
import com.beust.kobalt.AsciiArt
import com.beust.kobalt.TestConfig
import com.beust.kobalt.TestResult
import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.aether.AetherDependency
import com.beust.kobalt.misc.*
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.StringVersion
import com.beust.kobalt.misc.runCommand
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.FileReader
import java.io.IOException
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.XPathConstants
import javax.xml.xpath.XPathFactory
class TestNgRunner : GenericTestRunner() {
override val mainClass = "org.testng.TestNG"
override val dependencyName = "testng"
override val annotationPackage = "org.testng"
override val runnerName = "TestNG"
private fun defaultOutputWithoutProjectDir(project: Project)
= KFiles.joinDir(project.buildDirectory, "test-output")
private fun defaultOutput(project: Project)
= KFiles.joinDir(project.directory, project.buildDirectory, "test-output")
override val dependencyName = "testng"
override val annotationPackage = "org.testng"
fun defaultOutput(project: Project) = KFiles.joinDir(project.buildDirectory, "test-output")
override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) = arrayListOf<String>().apply {
if (KobaltLogger.isQuiet) {
add("-log")
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))
add(defaultOutput(project))
}
if (testConfig.testArgs.size == 0) {
@ -73,50 +59,11 @@ class TestNgRunner : GenericTestRunner() {
}
}
/**
* 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 {
configName: String): Boolean {
val testConfig = project.testConfigs.firstOrNull { it.name == configName }
@ -137,7 +84,7 @@ class TestNgRunner : GenericTestRunner() {
}
return result
} else {
return TestResult(true)
return true
}
}
@ -154,8 +101,7 @@ class TestNgRunner : GenericTestRunner() {
}
private fun displayPrettyColors(project: Project, context: KobaltContext,
classpath: List<IClasspathDependency>, testConfig: TestConfig, versions: Pair<String, String>)
: TestResult {
classpath: List<IClasspathDependency>, testConfig: TestConfig, versions: Pair<String, String>): Boolean {
val port = 2345
// launchRemoteServer(project, context, classpath, testConfig, versions, port)
@ -178,8 +124,8 @@ class TestNgRunner : GenericTestRunner() {
try {
var message = mh.receiveMessage()
kobaltLog(1, "")
kobaltLog(1, green("PASSED") + " | " + red("FAILED") + " | " + yellow("SKIPPED"))
println("")
println(green("PASSED") + " | " + red("FAILED") + " | " + yellow("SKIPPED"))
while (message != null) {
message = mh.receiveMessage()
if (message is TestResultMessage) {
@ -190,21 +136,19 @@ class TestNgRunner : GenericTestRunner() {
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))
}
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}")
println("Exception: ${ex.message}")
}
kobaltLog(1, "\nPassed: " + passed.size + ", Failed: " + failed.size + ", Skipped: " + skipped.size)
println("\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)
println(" " + it.cls + "." + it.method + "\n " + top)
}
return TestResult(failed.isEmpty() && skipped.isEmpty())
return failed.isEmpty() && skipped.isEmpty()
}
fun launchRemoteServer(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
@ -214,7 +158,7 @@ class TestNgRunner : GenericTestRunner() {
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")
val testng = create("org.testng:testng:6.10")
transitiveClosure(kotlin.collections.listOf(jf, tr /*, testng */))
}
@ -257,12 +201,10 @@ 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("")
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
import com.beust.kobalt.misc.KFiles
import java.io.File
import java.nio.file.Files
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.
* @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) {
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
/**
* @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

@ -106,10 +106,6 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
val result = arrayListOf<IClasspathDependency>().apply {
if (scopes.contains(Scope.COMPILE)) {
addAll(project.compileDependencies)
addAll(project.compileProvidedDependencies)
}
if (scopes.contains(Scope.COMPILEONLY)) {
addAll(project.compileOnlyDependencies)
}
if (scopes.contains(Scope.RUNTIME)) {
addAll(project.compileRuntimeDependencies)
@ -179,13 +175,13 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
* TODO: This should be private, everyone should be calling calculateDependencies().
*/
fun transitiveClosure(dependencies : List<IClasspathDependency>,
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER,
dependencyFilter: DependencyFilter? = null,
requiredBy: String? = null): List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
dependencies.forEach { dependency ->
result.add(dependency)
if (dependency.isMaven) {
val resolved = resolver.resolveToIds(dependency.id, null, filter).map { create(it) }
val resolved = resolver.resolveToIds(dependency.id, null, dependencyFilter).map { create(it) }
result.addAll(resolved)
}
}

View file

@ -1,18 +1,16 @@
package com.beust.kobalt.maven
import com.beust.kobalt.OperatingSystem
import com.beust.kobalt.misc.LocalProperties
import com.beust.kobalt.misc.error
import com.beust.kobalt.misc.kobaltLog
import com.beust.kobalt.misc.warn
import com.google.inject.Inject
import com.google.inject.Singleton
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
@Singleton
class Gpg @Inject constructor(val localProperties: LocalProperties) {
class Gpg {
val COMMANDS = listOf("gpg", "gpg2")
fun findGpgCommand() : String? {
@ -44,21 +42,6 @@ class Gpg @Inject constructor(val localProperties: LocalProperties) {
ascFile.delete()
val allArgs = arrayListOf<String>()
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(file.absolutePath)

View file

@ -1,8 +1,9 @@
package com.beust.kobalt.maven
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.misc.LocalProperties
import java.io.*
import java.net.HttpURLConnection
import java.net.URL
@ -20,7 +21,27 @@ class Kurl(val hostInfo: HostConfig) {
}
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()

View file

@ -17,12 +17,8 @@ class MavenId private constructor(val groupId: String, val artifactId: String, v
val classifier: String?, val version: String?) {
companion object {
fun isMavenId(id: String) = if (id.startsWith("file://")) {
false
} else {
with(id.split(':')) {
size >= 3 && size <= 5
}
fun isMavenId(id: String) = with(id.split(':')) {
size >= 3 && size <= 5
}
fun isRangedVersion(s: String): Boolean {
@ -36,14 +32,14 @@ class MavenId private constructor(val groupId: String, val artifactId: String, v
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
* will run through IMavenIdInterceptors.
*/
fun create(originalId: String) : MavenId {
val id = toMavenId(originalId)
val id = toKobaltId(originalId)
var originalMavenId = createNoInterceptors(id)
var interceptedMavenId = originalMavenId
val interceptors = Kobalt.context?.pluginInfo?.mavenIdInterceptors

View file

@ -1,12 +1,13 @@
package com.beust.kobalt.maven
import com.beust.kobalt.misc.kobaltLog
import org.w3c.dom.Element
import org.xml.sax.InputSource
import java.io.File
import java.io.FileReader
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.transform.sax.SAXSource
@ -146,7 +147,7 @@ class Dependency {
private fun expandVariable(s: String, pom: Pom2) : String {
val variable = extractVariable(s)
if (variable != null) {
kobaltLog(2, "Expanding variable $variable")
println("Expanding variable $variable")
val value = pom.pomProject.propertyValue(variable)
return s
} else {

View file

@ -1,19 +1,19 @@
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.Kobalt
import com.beust.kobalt.maven.CompletedFuture
import com.beust.kobalt.maven.LocalDep
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.MavenId
import com.beust.kobalt.misc.StringVersion
import com.beust.kobalt.misc.warn
import org.eclipse.aether.artifact.Artifact
import org.eclipse.aether.artifact.DefaultArtifact
import org.eclipse.aether.resolution.DependencyResolutionException
import java.io.File
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> {
val aether: KobaltMavenResolver get() = Kobalt.INJECTOR.getInstance(KobaltMavenResolver::class.java)
@ -26,29 +26,18 @@ class AetherDependency(val artifact: Artifact, override val optional: Boolean =
private fun toId(a: Artifact) = a.toString()
override val jarFile: Future<File>
get() {
resolveSourcesIfNeeded()
return if (artifact.file != null) {
CompletedFuture(artifact.file)
} else {
val td = aether.resolve(artifact)
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
}
}
get() = if (artifact.file != null) {
CompletedFuture(artifact.file)
} else {
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)
}
}
}
override fun toMavenDependencies(scope: String?) : org.apache.maven.model.Dependency {
val passedScope = scope
@ -88,7 +77,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 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.google.common.eventbus.EventBus
import com.beust.kobalt.Args
import org.eclipse.aether.DefaultRepositorySystemSession
import org.eclipse.aether.RepositorySystem
import org.eclipse.aether.repository.LocalRepository
@ -33,9 +32,8 @@ object Booter {
// }
fun newRepositorySystemSession(system: RepositorySystem, repo: File, settings: KobaltSettings,
args: Args, eventBus: EventBus): DefaultRepositorySystemSession {
eventBus: EventBus): DefaultRepositorySystemSession {
val session = MavenRepositorySystemUtils.newSession(settings)
session.isOffline = args.offline
val localRepo = LocalRepository(repo.absolutePath)
session.localRepositoryManager = system.newLocalRepositoryManager(session, localRepo)

View file

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

View file

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

View file

@ -1,15 +1,10 @@
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.internal.KobaltSettings
import com.beust.kobalt.internal.getProxy
import com.beust.kobalt.maven.Kurl
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.MavenId
import com.beust.kobalt.misc.LocalProperties
import com.google.common.eventbus.EventBus
import com.google.inject.Inject
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.VersionRangeRequest
import org.eclipse.aether.resolution.VersionRangeResult
import org.eclipse.aether.util.repository.AuthenticationBuilder
import java.util.*
class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
val args: Args,
localRepo: LocalRepo, eventBus: EventBus) {
companion object {
@ -36,76 +28,29 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
MavenId.toId(it.groupId, it.artifactId, it.extension, it.classifier, it.version)
}
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 = Filters.EXCLUDE_OPTIONAL_FILTER) : Artifact
fun resolveToArtifact(id: String, scope: Scope? = null, filter: DependencyFilter? = null) : Artifact
= resolve(id, scope, filter).root.artifact
fun resolve(passedId: String, scope: Scope? = null,
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_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)
fun resolve(id: String, scope: Scope? = null, filter: DependencyFilter? = null): DependencyResult {
val dependencyRequest = DependencyRequest(createCollectRequest(id, scope), filter)
val result = system.resolveDependencies(session, dependencyRequest)
// GraphUtil.displayGraph(listOf(result.root), { it -> it.children },
// { it: DependencyNode, indent: String -> println(indent + it.toString()) })
// GraphUtil.displayGraph(listOf(result.root), { it -> it.children },
// { it: DependencyNode, indent: String -> println(indent + it.toString()) })
return result
}
fun resolve(artifact: Artifact, scope: Scope? = null,
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER)
fun resolve(artifact: Artifact, scope: Scope? = null, filter: DependencyFilter? = null)
= resolve(artifactToId(artifact), scope, filter)
fun resolveToIds(id: String, scope: Scope? = null,
filter: DependencyFilter = Filters.EXCLUDE_OPTIONAL_FILTER,
fun resolveToIds(id: String, scope: Scope? = null, filter: DependencyFilter? = null,
seen: HashSet<String> = hashSetOf<String>()) : List<String> {
val rr = resolve(id, scope, filter)
val children =
rr.root.children.filter {
filter.accept(DefaultDependencyNode(it.dependency), emptyList())
filter == null || filter.accept(DefaultDependencyNode(it.dependency), emptyList())
}.filter {
it.dependency.scope != Scope.SYSTEM.scope
}
@ -129,7 +74,7 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
directDependencies(id, scope)
}
fun resolveRange(artifact: Artifact): VersionRangeResult? {
fun resolveVersion(artifact: Artifact): VersionRangeResult? {
val request = VersionRangeRequest(artifact, kobaltRepositories, null)
val result = system.resolveVersionRange(session, request)
return result
@ -138,26 +83,16 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
/**
* 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 session = Booter.newRepositorySystemSession(system, localRepo.localRepo, settings, args, 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 session = Booter.newRepositorySystemSession(system, localRepo.localRepo, settings, eventBus)
private val kobaltRepositories: List<RemoteRepository>
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
RemoteRepository.Builder(repository).apply {
setProxy(proxyConfigs.getProxy(repository.protocol)?.toAetherProxy())
@ -165,16 +100,8 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings,
}
}
private fun createRepos(repos: List<String>) : List<RemoteRepository>
= kobaltRepositories + repos.map { createRepo(HostConfig(it)) }
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)
private fun createCollectRequest(id: String, scope: Scope? = null) = CollectRequest().apply {
root = Dependency(DefaultArtifact(MavenId.toKobaltId(id)), scope?.scope)
repositories = kobaltRepositories
}
}

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 PROVIDED : Scope(JavaScopes.PROVIDED, Project::compileProvidedDependencies)
object COMPILEONLY : Scope("compileOnly", Project::compileOnlyDependencies)
object SYSTEM : Scope(JavaScopes.SYSTEM, { project -> emptyList() })
object RUNTIME : Scope(JavaScopes.RUNTIME, Project::compileRuntimeDependencies)
object TEST : Scope(JavaScopes.TEST, Project::testDependencies)

View file

@ -1,39 +1,23 @@
package com.beust.kobalt.misc
import com.beust.kobalt.homeDir
import java.io.File
import java.util.regex.Pattern
class Section(val start: Int, val end: Int) {
override fun toString() = "$start-$end"
fun main(argv: Array<String>) {
val lines = File(homeDir("kotlin/kobalt/kobalt/src/Build.kt")).readLines()
val result = BlockExtractor(Pattern.compile("val.*buildScript.*\\{"), '{', '}').extractBlock(lines)
// BlockExtractor("plugins", '(', ')').extractBlock(lines)
}
class IncludedBuildSourceDir(val line: Int, val dirs: List<String>)
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()
}
}
class BuildScriptInfo(val content: String, val startLine: Int, val endLine: Int)
/**
* Used to extract a keyword followed by opening and closing tags out of a list of strings,
* e.g. buildScript { ... }.
*/
class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char) {
fun extractBlock(file: File, lines: List<String>): BuildScriptInfo? {
fun extractBlock(lines: List<String>): BuildScriptInfo? {
var currentLineNumber = 0
// First line of the buildScript block
var startLine = 0
@ -42,9 +26,8 @@ class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char)
var foundKeyword = false
var foundClosing = false
var count = 0
val buildScript = arrayListOf<String>()
val result = StringBuffer()
val topLines = arrayListOf<String>()
val finalTopLines = arrayListOf<String>()
fun updateCount(line: String) {
val currentLine = StringBuffer()
@ -63,57 +46,38 @@ class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char)
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 ->
currentLineNumber++
val found = regexp.matcher(line).matches()
if (found) {
startLine = currentLineNumber
foundKeyword = true
count = 1
buildScript.add(line)
finalTopLines.addAll(topLines)
result.append(topLines.joinToString("\n")).append("\n")
result.append(line).append("\n")
} else {
if (line.startsWith("import")) {
if (isAllowedImport(line)) {
imports.add(line)
}
} else {
val allowedImports = listOf("com.beust", "java")
val disallowedImports = listOf("com.beust.kobalt.plugin")
if (! line.startsWith("import") ||
(line.startsWith("import") && allowedImports.any { line.contains(it) }
&& ! disallowedImports.any { line.contains(it) })) {
topLines.add(line)
}
updateCount(line)
}
if (foundKeyword && foundClosing && count == 0) {
sections.add(Section(startLine, endLine))
foundKeyword = false
foundClosing = false
count = 0
startLine = 0
endLine = 0
return BuildScriptInfo(result.toString(), startLine, endLine)
}
currentLineNumber++
}
if (sections.isNotEmpty()) {
val result = (imports.distinct() + buildScript).joinToString("\n") + "\n"
return BuildScriptInfo(file, lines, sections, imports, finalTopLines)
if (foundKeyword && foundClosing && count == 0) {
return BuildScriptInfo(result.toString(), startLine, endLine)
} else {
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 {
val latestDep = depManager.create(dep.shortId, false, project.directory)
val artifact = (latestDep as AetherDependency).artifact
val rangeResult = resolver.resolveRange(artifact)
if (rangeResult != null) {
val highest = rangeResult.highestVersion?.toString()
if (highest != null && highest != dep.id
&& StringVersion(highest) > StringVersion(dep.version)) {
newVersions.add(artifact.groupId + ":" + artifact.artifactId + ":" + highest)
val versions = resolver.resolveVersion(artifact)
val releases = versions?.versions?.filter { !it.toString().contains("SNAP")}
val highest = if (releases != null && releases.any()) {
releases.last().toString()
} else {
versions?.highestVersion.toString()
}
if (highest != dep.id
&& StringVersion(highest) > StringVersion(dep.version)) {
newVersions.add(artifact.groupId + ":" + artifact.artifactId + ":" + highest)
}
} catch(e: KobaltException) {
kobaltLog(1, " Cannot resolve ${dep.shortId}. ignoring")

View file

@ -6,13 +6,12 @@ import com.google.inject.Inject
import java.io.File
class Git @Inject constructor() {
fun maybeTagRelease(project: Project, uploadResult: TaskResult, enabled: Boolean, annotated: Boolean,
push: Boolean, tag: String, message: String) : TaskResult {
fun maybeTagRelease(project: Project, uploadResult: TaskResult, enabled: Boolean, annotated: Boolean, tag: String, message: String) : TaskResult {
val result =
if (uploadResult.success && enabled) {
val tagSuccess = tagRelease(project, annotated, push, tag, message)
val tagSuccess = tagRelease(project, annotated, tag, message)
if (! tagSuccess) {
TaskResult(false, errorMessage = "Couldn't tag the project")
TaskResult(false, "Couldn't tag the project")
} else {
TaskResult()
}
@ -22,7 +21,7 @@ class Git @Inject constructor() {
return result
}
private fun tagRelease(project: Project, annotated: Boolean, push: Boolean, tag: String, message: String) : Boolean {
private fun tagRelease(project: Project, annotated: Boolean, tag: String, message: String) : Boolean {
val version = if (tag.isNullOrBlank()) project.version else tag
val success = try {
log(2, "Tagging this release as \"$version\"")
@ -38,9 +37,7 @@ class Git @Inject constructor() {
} else {
git.tag().setName(version).setMessage(message).call()
}
if (push) {
git.push().setPushTags().call()
}
git.push().setPushTags().call()
true
} catch(ex: Exception) {
warn("Couldn't create tag ${version}: ${ex.message}", ex)

View file

@ -1,11 +1,8 @@
package com.beust.kobalt.misc
import com.beust.kobalt.Args
import com.beust.kobalt.KobaltException
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.internal.DocUrl
import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.build.VersionCheckTimestampFile
import com.beust.kobalt.maven.Http
import com.beust.kobalt.maven.aether.Exceptions
import com.google.gson.Gson
@ -19,15 +16,12 @@ import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
import rx.Observable
import java.io.File
import java.time.Duration
import java.time.Instant
import java.util.*
import java.util.concurrent.Callable
import java.util.concurrent.Future
class GithubApi2 @Inject constructor(
val executors: KobaltExecutors, val localProperties: LocalProperties, val http: Http,
val settings:KobaltSettings, val args: Args) {
val executors: KobaltExecutors, val localProperties: LocalProperties, val http: Http, val settings:KobaltSettings) {
companion object {
const val PROPERTY_ACCESS_TOKEN = "github.accessToken"
@ -86,12 +80,12 @@ class GithubApi2 @Inject constructor(
.execute()
val code = response.code()
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)
} else {
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()
.forEach { action ->
kobaltLog(1, "\n${zipFile.name} successfully uploaded")
@ -115,42 +109,39 @@ class GithubApi2 @Inject constructor(
val latestKobaltVersion: Future<String>
get() {
val callable = Callable<String> {
var result = Kobalt.version
if (! args.dev && Duration.ofMinutes(10L) >
Duration.between(VersionCheckTimestampFile.timestamp, Instant.now())) {
kobaltLog(2, "Skipping GitHub latest release check, too soon.")
} else {
val username = localProperties.getNoThrows(PROPERTY_USERNAME)
val accessToken = localProperties.getNoThrows(PROPERTY_ACCESS_TOKEN)
try {
val req =
if (username != null && accessToken != null) {
service.getReleases(username, "kobalt", accessToken)
} else {
service.getReleasesNoAuth("cbeust", "kobalt")
}
val ex = req.execute()
val errorBody = ex.errorBody()
if (errorBody != null) {
val jsonError = JsonParser().parse(errorBody.string())
warn("Couldn't call Github.getReleases(): $jsonError")
} else {
val releases = ex.body()
if (releases != null) {
releases.firstOrNull()?.let {
result = try {
listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() }
} catch(ex: NoSuchElementException) {
throw KobaltException("Couldn't find the latest release")
}
}
var result = "0"
val username = localProperties.getNoThrows(PROPERTY_USERNAME, DOC_URL)
val accessToken = localProperties.getNoThrows(PROPERTY_ACCESS_TOKEN, DOC_URL)
try {
val req =
if (username != null && accessToken != null) {
service.getReleases(username, "kobalt", accessToken)
} else {
warn("Didn't receive any body in the response to GitHub.getReleases()")
service.getReleasesNoAuth("cbeust", "kobalt")
}
val ex = req.execute()
val errorBody = ex.errorBody()
if (errorBody != null) {
val jsonError = JsonParser().parse(errorBody.string())
warn("Couldn't call Github.getReleases(): $jsonError")
} else {
val releases = ex.body()
if (releases != null) {
releases.firstOrNull()?.let {
try {
result = listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() }
} catch(ex: NoSuchElementException) {
throw KobaltException("Couldn't find the latest release")
}
}
} else {
warn("Didn't receive any body in the response to GitHub.getReleases()")
}
} catch(e: Exception) {
kobaltLog(1, "Couldn't retrieve releases from github: " + e.message)
Exceptions.printStackTrace(e)
}
} catch(e: Exception) {
kobaltLog(1, "Couldn't retrieve releases from github: " + e.message)
Exceptions.printStackTrace(e)
// val error = parseRetrofitError(e)
// val details = if (error.errors != null) {
// error.errors[0]
@ -161,7 +152,6 @@ class GithubApi2 @Inject constructor(
// // using cbeust/kobalt, like above. Right now, just bailing.
// kobaltLog(2, "Couldn't retrieve releases from github, ${error.message ?: e}: "
// + details?.code + " field: " + details?.field)
}
}
result
}

View file

@ -1,7 +1,9 @@
package com.beust.kobalt.misc
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) {
fun mkdirs(dir: String) {
@ -45,8 +47,8 @@ class Io(val dryRun: Boolean = false) {
if (! dryRun) {
KFiles.copyRecursively(from, toDir)
require(from.exists(), { -> "$from should exist" })
require(from.isDirectory, { -> kobaltLog(1, "$from should be a directory")})
require(toDir.isDirectory, { -> kobaltLog(1, "$toDir should be a file")})
require(from.isDirectory, { -> println("$from should be a directory")})
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) {
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 {
if (it.isDirectory) {

View file

@ -1,16 +1,16 @@
package com.beust.kobalt.misc
import com.beust.kobalt.From
import com.beust.kobalt.Glob
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 java.io.File
import java.io.FileOutputStream
import java.io.InputStreamReader
import java.io.*
import java.nio.file.Paths
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.jar.JarInputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
class JarUtils {
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,
onError: (Exception) -> Unit = DEFAULT_HANDLER) {
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) {
val foundFiles = file.allFromFiles(directory)
foundFiles.forEach { foundFile ->
@ -48,24 +51,50 @@ class JarUtils {
// Directory
val includedFile = IncludedFile(From(""), To(""), listOf(IFileSpec.GlobSpec("**")))
addSingleFile(localFile.path, includedFile, metaArchive, expandJarFiles)
addSingleFile(localFile.path, includedFile, outputStream, expandJarFiles)
} else {
try {
if (file.expandJarFiles && foundFile.name.endsWith(".jar") && !file.from.contains("resources")) {
kobaltLog(2, " Writing contents of jar file $foundFile")
metaArchive.addArchive(foundFile)
} else {
val toPath = File(file.to).normalize().path
val finalPath = if (toPath.isEmpty()) null else (toPath + "/")
metaArchive.addFile(File(directory, fromFile.path), foundFile, finalPath)
if (file.expandJarFiles && foundFile.name.endsWith(".jar") && ! file.from.contains("resources")) {
kobaltLog(2, " Writing contents of jar file $foundFile")
val stream = JarInputStream(FileInputStream(localFile))
var entry = stream.nextEntry
while (entry != null) {
if (!entry.isDirectory && !KFiles.isExcluded(entry.name, DEFAULT_JAR_EXCLUDES)) {
val ins = JarFile(localFile).getInputStream(entry)
addEntry(ins, JarEntry(entry), outputStream, onError)
}
entry = stream.nextEntry
}
} catch(ex: Exception) {
onError(ex)
} else {
val entryFileName = KFiles.fixSlashes(file.to(foundFile.path))
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) {
onError(ex)
} finally {
bis?.close()
}
}
fun extractTextFile(zip : ZipFile, fileName: String) : String? {
val enumEntries = zip.entries()
while (enumEntries.hasMoreElements()) {
@ -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,22 @@ package com.beust.kobalt.misc
import com.beust.kobalt.*
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.maven.Md5
import org.apache.commons.io.FileUtils
import java.io.*
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import java.util.*
import java.util.jar.JarInputStream
import java.util.regex.Pattern
class KFiles {
/**
* 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>
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")
if (envJar != null) {
debug("Using kobalt jar $envJar")
@ -47,21 +30,19 @@ class KFiles {
if (jarFile.exists()) {
return listOf(jarFile.absolutePath)
} 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-wrapper.properties: kobalt.version=0.827
// When Kobalt can't find the newest jar file, it will instead use the classes produced by IDEA
// in the directories specified here:
val previousVersion = latestInstalledVersion().version
val leftSuffix = Kobalt.version.substring(0, Kobalt.version.lastIndexOf(".") + 1)
val previousVersion = leftSuffix +
(Kobalt.version.split(".").let { it[it.size - 1] }.toInt() - 1).toString()
val previousJar = joinDir(distributionsDir, "kobalt-" + previousVersion,
"kobalt/wrapper/kobalt-$previousVersion.jar")
latestInstalledVersion()
val result = listOf("", "modules/kobalt-plugin-api", "modules/wrapper").map {
File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "kobaltBuild", "classes"))) //kobalt build dirs
.absolutePath
} + listOf("modules/kobalt", "modules/kobalt-plugin-api", "modules/wrapper").map {
File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "target", "classes"))) //maven build dirs
.absolutePath
File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "kobaltBuild", "classes")))
.absolutePath
} + listOf(previousJar)
debug("Couldn't find ${jarFile.absolutePath}, using\n " + result.joinToString(" "))
return result.filter { File(it).exists() }
@ -111,12 +92,10 @@ class KFiles {
*/
fun joinDir(vararg ts: String): String = ts.toMutableList().joinToString(File.separator)
val LIBS_DIR = "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): String = KFiles.makeDir(KFiles.buildDir(project).path, "libs").path
/**
* The paths elements are expected to be a directory. Make that directory and join the
@ -136,7 +115,7 @@ class KFiles {
*/
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(f: File) = KFiles.fixSlashes(f.path)
fun fixSlashes(s: String) = s.replace('\\', '/')
fun makeDir(dir: String, s: String? = null) =
@ -216,12 +195,76 @@ class KFiles {
}
}
fun copyRecursively(from: File, to: File, replaceExisting: Boolean = true, deleteFirst: Boolean = false,
onError: (File, IOException) -> OnErrorAction = { _, 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) {}
/**
* Copy/pasted from kotlin/io/Utils.kt to add support for overwriting.
*/
private fun hackCopyRecursively(from: File, dst: File,
replaceExisting: Boolean,
onError: (File, IOException) -> OnErrorAction =
{ _, exception -> throw exception }
): Boolean {
if (!from.exists()) {
return onError(from, NoSuchFileException(file = from, reason = "The source file doesn't exist")) !=
OnErrorAction.TERMINATE
}
try {
// We cannot break for loop from inside a lambda, so we have to use an exception here
for (src in from.walkTopDown().onFail { f, e ->
if (onError(f, e) == OnErrorAction.TERMINATE) throw TerminateException(f)
}) {
if (!src.exists()) {
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
}
}
/**
* The build location for build scripts is .kobalt/build
*/
fun findBuildScriptDir(parent: String = ".") : File {
val result = File(joinAndMakeDir(parent, KFiles.dotKobaltDir.path, KFiles.SCRIPT_BUILD_DIR))
kobaltLog(2, " Script jar files in: $result")
fun findBuildScriptLocation(buildFile: BuildFile, jarFile: String) : String {
val result = joinDir(buildFile.dotKobaltDir.path, KFiles.SCRIPT_BUILD_DIR, jarFile)
kobaltLog(2, "Build file dotKobaltDir: " + buildFile.dotKobaltDir)
kobaltLog(2, "Script jar file: $result")
return result
}
@ -245,18 +288,22 @@ class KFiles {
private fun isWindows() = System.getProperty("os.name").contains("Windows")
fun copy(from: Path?, to: Path?, option: StandardCopyOption = StandardCopyOption.REPLACE_EXISTING) {
try {
if (from != null && to != null) {
if (!Files.exists(to) || Md5.toMd5(from.toFile()) != Md5.toMd5(to.toFile())) {
kobaltLog(3, "Copy from $from to $to")
Files.copy(from, to, option)
} else {
kobaltLog(3, " Not copying, indentical files: $from $to")
if (isWindows() && to!!.toFile().exists()) {
kobaltLog(2, "Windows detected, not overwriting $to")
} else {
try {
if (from != null && to != null) {
if (!Files.exists(to) || Md5.toMd5(from.toFile()) != Md5.toMd5(to.toFile())) {
kobaltLog(3, "Copy from $from to $to")
Files.copy(from, to, option)
} else {
kobaltLog(3, " Not copying, indentical files: $from $to")
}
}
} catch(ex: IOException) {
// Windows is anal about this
kobaltLog(1, "Couldn't copy $from to $to: ${ex.message}")
}
} catch(ex: IOException) {
// Windows is anal about this
kobaltLog(1, "Couldn't copy $from to $to: ${ex.message}")
}
}
@ -340,36 +387,18 @@ class KFiles {
}
}
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)
fun findBuildFile(projectRoot: String = "."): File {
val deprecatedLocation = File(Constants.BUILD_FILE_NAME)
val result: File =
if (deprecatedLocation.exists()) {
warn(Constants.BUILD_FILE_NAME + " is in a deprecated location, please move it to "
+ Constants.BUILD_FILE_DIRECTORY)
deprecatedLocation
} else {
File(KFiles.joinDir(project.directory, includedFile.from, it.path))
File(KFiles.joinDir(projectRoot, Constants.BUILD_FILE_DIRECTORY, Constants.BUILD_FILE_NAME))
}
}
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> {

View file

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

View file

@ -24,7 +24,7 @@ class KobaltWrapperProperties @Inject constructor() {
}
private fun defaultUrlFor(version: String) =
"https://beust.com/kobalt/kobalt-$version.zip"
"http://beust.com/kobalt/kobalt-$version.zip"
private val file: File
get() = File("$WRAPPER_DIR/$KOBALT_WRAPPER_PROPERTIES")

View file

@ -6,9 +6,6 @@ import java.nio.file.Files
import java.nio.file.Paths
import java.util.*
/**
* Encapsulate read access to local.properties.
*/
@Singleton
class LocalProperties {
val localProperties: Properties by lazy {
@ -25,11 +22,11 @@ class LocalProperties {
result
}
fun getNoThrows(name: String): String? = localProperties.getProperty(name)
fun getNoThrows(name: String, docUrl: String? = null) = localProperties.getProperty(name)
fun get(name: String, docUrl: String? = null) : String {
val result = getNoThrows(name)
val result = getNoThrows(name, docUrl)
?: throw KobaltException("Couldn't find $name in local.properties", docUrl = docUrl)
return result
return result as String
}
}

View file

@ -19,7 +19,6 @@ class RunCommandInfo {
*/
var useErrorStreamAsErrorIndicator : Boolean = true
var useInputStreamAsErrorIndicator : Boolean = false
var ignoreExitValue : Boolean = false
var errorCallback: Function1<List<String>, Unit> = NewRunCommand.DEFAULT_ERROR
var successCallback: Function1<List<String>, Unit> = NewRunCommand.DEFAULT_SUCCESS
@ -79,31 +78,19 @@ open class NewRunCommand(val info: RunCommandInfo) {
val process = pb.start()
// Run the command and collect the return code and streams
val processFinished = process.waitFor(120, TimeUnit.SECONDS)
if (!processFinished)
kobaltError("process timed out!")
val input =
if (process.inputStream.available() > 0) fromStream(process.inputStream)
else listOf()
val error =
if (process.errorStream.available() > 0) fromStream(process.errorStream)
else listOf()
kobaltLog(3, "info contains errors: " + (info.containsErrors != null))
val returnCode = process.waitFor(30, TimeUnit.SECONDS)
val input = if (process.inputStream.available() > 0) fromStream(process.inputStream)
else listOf()
val error = if (process.errorStream.available() > 0) fromStream(process.errorStream)
else listOf()
// Check to see if the command succeeded
val isSuccess =
if (info.containsErrors != null) ! info.containsErrors!!(error)
else isSuccess(if (info.ignoreExitValue) true else processFinished, input, error)
else isSuccess(returnCode, input, error)
if (isSuccess) {
if (!info.useErrorStreamAsErrorIndicator) {
info.successCallback(error + input)
} else {
info.successCallback(input)
}
info.successCallback(input)
} else {
info.errorCallback(error + input)
}
@ -116,12 +103,12 @@ open class NewRunCommand(val info: RunCommandInfo) {
* have various ways to signal errors.
*/
open protected fun isSuccess(isSuccess: Boolean, input: List<String>, error: List<String>) : Boolean {
var hasErrors: Boolean = ! isSuccess
var hasErrors = ! isSuccess
if (info.useErrorStreamAsErrorIndicator && ! hasErrors) {
hasErrors = hasErrors || error.isNotEmpty()
hasErrors = hasErrors || error.size > 0
}
if (info.useInputStreamAsErrorIndicator && ! hasErrors) {
hasErrors = hasErrors || input.isNotEmpty()
hasErrors = hasErrors || input.size > 0
}
return ! hasErrors

View file

@ -12,7 +12,7 @@ data class Node<T>(val value: T) {
}
private fun p(s: String) {
kobaltLog(1, s)
println(s)
}
fun dump(r: T, children: List<Node<T>>, indent: Int) {

View file

@ -0,0 +1,90 @@
package com.beust.kobalt.misc
import java.io.BufferedReader
import java.io.File
import java.io.InputStream
import java.io.InputStreamReader
import java.util.concurrent.TimeUnit
open class RunCommand(val command: String) {
val DEFAULT_SUCCESS = { output: List<String> -> }
// val DEFAULT_SUCCESS_VERBOSE = { output: List<String> -> kobaltLog(2, "Success:\n " + output.joinToString("\n"))}
val defaultSuccess = DEFAULT_SUCCESS
val DEFAULT_ERROR = {
output: List<String> -> error(output.joinToString("\n "))
}
var directory = File(".")
var env = hashMapOf<String, String>()
/**
* Some commands fail but return 0, so the only way to find out if they failed is to look
* at the error stream. However, some commands succeed but output text on the error stream.
* This field is used to specify how errors are caught.
*/
var useErrorStreamAsErrorIndicator = true
var useInputStreamAsErrorIndicator = false
fun useErrorStreamAsErrorIndicator(f: Boolean) : RunCommand {
useErrorStreamAsErrorIndicator = f
return this
}
open fun run(args: List<String>,
errorCallback: Function1<List<String>, Unit> = DEFAULT_ERROR,
successCallback: Function1<List<String>, Unit> = defaultSuccess) : Int {
val allArgs = arrayListOf<String>()
allArgs.add(command)
allArgs.addAll(args)
val pb = ProcessBuilder(allArgs)
pb.directory(directory)
kobaltLog(2, "Running command in directory ${directory.absolutePath}" +
"\n " + allArgs.joinToString(" "))
val process = pb.start()
pb.environment().let { pbEnv ->
env.forEach {it ->
pbEnv.put(it.key, it.value)
}
}
val callSucceeded = process.waitFor(30, TimeUnit.SECONDS)
val input = if (process.inputStream.available() > 0) fromStream(process.inputStream) else emptyList()
val error = if (process.errorStream.available() > 0) fromStream(process.errorStream) else emptyList()
val isSuccess = isSuccess(callSucceeded, input, error)
if (isSuccess) {
successCallback(input)
} else {
errorCallback(error + input)
}
return if (isSuccess) 0 else 1
}
open protected fun isSuccess(callSucceeded: Boolean, input: List<String>, error: List<String>) : Boolean {
var hasErrors = ! callSucceeded
if (useErrorStreamAsErrorIndicator && ! hasErrors) {
hasErrors = hasErrors || error.size > 0
}
if (useInputStreamAsErrorIndicator && ! hasErrors) {
hasErrors = hasErrors || input.size > 0
}
return ! hasErrors
}
private fun fromStream(ins: InputStream) : List<String> {
val result = arrayListOf<String>()
val br = BufferedReader(InputStreamReader(ins))
var line = br.readLine()
while (line != null) {
result.add(line)
line = br.readLine()
}
return result
// val result = CharStreams.toString(InputStreamReader(ins, Charset.defaultCharset()))
// return result.split("\n")
}
}

View file

@ -29,12 +29,8 @@ class StringVersion(val version: String) : Comparable<StringVersion> {
if (v1 < v2) return -1
else if (v1 > v2) return 1
} catch(ex: NumberFormatException) {
if (version == other.toString()) {
return 0
} else {
log(2, "Couldn't parse version $version or $other")
return -1
}
warn("Couldn't parse version $version or $other")
return -1
}
}
return 0

View file

@ -1,79 +0,0 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.71'
id 'com.github.johnrengelman.shadow' version '5.0.0'
}
dependencies {
implementation project(':wrapper')
implementation project(':kobalt-plugin-api')
implementation "biz.aQute.bnd:biz.aQute.bndlib:$bndlib"
implementation 'com.github.spullara.mustache.java:compiler:0.9.5'
implementation "com.google.code.findbugs:jsr305:$findbugs"
implementation "com.sparkjava:spark-core:$spark"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp"
implementation 'com.sun.activation:javax.activation:1.2.0'
implementation "com.sun.xml.bind:jaxb-core:$jaxb"
implementation "com.sun.xml.bind:jaxb-impl:$jaxb"
implementation "javax.inject:javax.inject:$inject"
implementation "javax.xml.bind:jaxb-api:$jaxb"
implementation "org.apache.maven.resolver:maven-resolver-spi:$mavenResolver"
implementation "org.codehaus.groovy:groovy:$groovy"
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.retrofit2:converter-gson:$retrofit"
implementation "com.squareup.retrofit2:retrofit:$retrofit"
implementation "org.apache.maven:maven-model:$maven"
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlin"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin"
testImplementation 'org.assertj:assertj-core:3.8.0'
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin"
testImplementation "org.testng:testng:$testng"
}
sourceSets {
main.kotlin.srcDirs += "${rootProject.projectDir}../../src/main/kotlin"
test.kotlin.srcDirs += "${rootProject.projectDir}../../src/test/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,231 +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</artifactId>
<packaging>jar</packaging>
<version>1.1.0</version>
<dependencies>
<dependency>
<groupId>com.beust</groupId>
<artifactId>kobalt-plugin-api</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.beust</groupId>
<artifactId>wrapper</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-compiler-embeddable</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.github.spullara.mustache.java</groupId>
<artifactId>compiler</artifactId>
<version>0.9.5</version>
<scope>compile</scope>
</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.maven.resolver</groupId>
<artifactId>maven-resolver-spi</artifactId>
<version>${mavenresolver.version}</version>
</dependency>
<!-- java 9 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</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>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.beust.kobalt.MainKt</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,38 +0,0 @@
jar {
manifest {
attributes 'Main-Class': 'com.beust.kobalt.wrapper.Main'
}
}
publishing {
publications {
maven(MavenPublication) {
from(components.java)
artifact sourcesJar
artifact javadocJar
pom {
name = project.name
description = 'Wrapper for Kobalt'
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,28 +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>wrapper</artifactId>
<packaging>jar</packaging>
<version>1.1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -36,7 +36,6 @@ public class Main {
private final Properties wrapperProperties = new Properties();
private static int logQuietLevel = 0;
private static int logLevel = 1;
private boolean noOverwrite = false;
@ -47,6 +46,7 @@ public class Main {
private int installAndLaunchMain(String[] argv) throws IOException, InterruptedException {
String version = getVersion();
initWrapperFile(version);
List<String> kobaltArgv = new ArrayList<>();
boolean noLaunch = false;
@ -77,7 +77,6 @@ public class Main {
}
int result = 0;
if (! exit) {
initWrapperFile(version);
Path kobaltJarFile = installDistribution();
if (!noLaunch) {
result = launchMain(kobaltJarFile, kobaltArgv);
@ -118,7 +117,7 @@ public class Main {
}
private static String downloadUrl(String version) {
return "https://beust.com/kobalt/kobalt-" + version + ".zip";
return "http://beust.com/kobalt/kobalt-" + version + ".zip";
}
private void initWrapperFile(String version) throws IOException {
@ -133,7 +132,7 @@ public class Main {
}
private String getWrapperVersion() {
return wrapperProperties.getProperty(PROPERTY_VERSION, "N/A");
return wrapperProperties.getProperty(PROPERTY_VERSION);
}
private String getWrapperDownloadUrl(String version) {
@ -345,11 +344,6 @@ public class Main {
try {
Files.createDirectories(entryPath.getParent());
Files.copy(zipFile.getInputStream(entry), entryPath, StandardCopyOption.REPLACE_EXISTING);
if (!isWindows() && entry.getName().endsWith(KOBALTW)) {
if (!entryPath.toFile().setExecutable(true)) {
log(1, "Couldn't make distribution " + KOBALTW + " executable");
}
}
} catch (FileSystemException ex) {
log(2, "Couldn't copy to " + entryPath);
}
@ -493,7 +487,7 @@ public class Main {
}
private static void p(int level, String s, boolean newLine) {
if (level != logQuietLevel && level <= logLevel) {
if (level <= logLevel) {
if (newLine) System.out.println(s);
else System.out.print(s);
}

34
pom.xml
View file

@ -1,34 +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>
<groupId>com.beust</groupId>
<artifactId>kobalt-pom</artifactId>
<packaging>pom</packaging>
<version>1.1.0</version>
<modules>
<module>modules/kobalt-plugin-api</module>
<module>modules/wrapper</module>
<module>modules/kobalt</module>
</modules>
<repositories>
<repository>
<id>testng</id>
<url>https://dl.bintray.com/cbeust/maven</url>
</repository>
</repositories>
<properties>
<kotlin.version>1.2.71</kotlin.version>
<okio.version>1.13.0</okio.version>
<okhttp3.version>3.9.1</okhttp3.version>
<mavenresolver.version>1.1.0</mavenresolver.version>
<junit.version>1.1.0</junit.version>
<junitJupiter.version>5.1.0</junitJupiter.version>
<testng.version>6.12</testng.version>
<slf4j.version>1.7.3</slf4j.version>
</properties>
</project>

View file

@ -1,5 +0,0 @@
rootProject.name = 'kobalt-pom'
include(':kobalt-plugin-api', ':wrapper', ':kobalt')
project(':kobalt-plugin-api').projectDir = file('modules/kobalt-plugin-api')
project(':wrapper').projectDir = file('modules/wrapper')
project(':kobalt').projectDir = file('modules/kobalt')

View file

@ -3,74 +3,74 @@ package com.beust.kobalt
import com.beust.jcommander.JCommander
import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.app.MainModule
import com.beust.kobalt.app.UpdateKobalt
import com.beust.kobalt.api.PluginTask
import com.beust.kobalt.app.*
import com.beust.kobalt.app.remote.KobaltClient
import com.beust.kobalt.app.remote.KobaltServer
import com.beust.kobalt.app.remote.RemoteDependencyData
import com.beust.kobalt.internal.Gc
import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.Http
import com.beust.kobalt.maven.dependency.FileDependency
import com.beust.kobalt.misc.*
import com.google.common.collect.HashMultimap
import java.io.File
import java.net.URLClassLoader
import java.nio.file.Paths
import javax.inject.Inject
fun main(argv: Array<String>) {
val result = Main.mainNoExit(argv)
val result = mainNoExit(argv)
if (result != 0) {
System.exit(result)
}
}
class Main @Inject constructor(
private fun parseArgs(argv: Array<String>): Main.RunInfo {
val args = Args()
val result = JCommander(args)
result.parse(*argv)
KobaltLogger.LOG_LEVEL = if (args.log < 0) {
Constants.LOG_DEFAULT_LEVEL
} else if (args.log > Constants.LOG_MAX_LEVEL) {
Constants.LOG_MAX_LEVEL
} else args.log
return Main.RunInfo(result, args)
}
fun mainNoExit(argv: Array<String>): Int {
val (jc, args) = parseArgs(argv)
Kobalt.init(MainModule(args, KobaltSettings.readSettingsXml()))
val result = Kobalt.INJECTOR.getInstance(Main::class.java).run {
val runResult = run(jc, args, argv)
pluginInfo.cleanUp()
executors.shutdown()
runResult
}
return result
}
private class Main @Inject constructor(
val plugins: Plugins,
val taskManager: TaskManager,
val http: Http,
val files: KFiles,
val executors: KobaltExecutors,
val dependencyManager: DependencyManager,
val checkVersions: CheckVersions,
val github: GithubApi2,
val updateKobalt: UpdateKobalt,
val client: KobaltClient,
val pluginInfo: PluginInfo,
val options: Options) {
companion object {
fun mainNoExit(argv: Array<String>): Int {
val (jc, args) = parseArgs(argv)
if (args.usage) {
jc.usage()
return 0
}
if (args.version) {
println("Kobalt ${Kobalt.version}")
return 0
}
Kobalt.init(MainModule(args, KobaltSettings.readSettingsXml()))
val result = launchMain(Kobalt.INJECTOR.getInstance(Main::class.java), jc, args, argv)
return result
}
private fun parseArgs(argv: Array<String>): Main.RunInfo {
val args = Args()
val result = JCommander(args)
result.parse(*argv)
KobaltLogger.setLogLevel(args)
return Main.RunInfo(result, args)
}
/**
* Entry point for tests, which can instantiate their main object with their own module and injector.
*/
fun launchMain(main: Main, jc: JCommander, args: Args, argv: Array<String>) : Int {
return main.run {
val runResult = run(jc, args, argv)
pluginInfo.cleanUp()
executors.shutdown()
runResult
}
}
}
val projectGenerator: ProjectGenerator,
val serverFactory: KobaltServer.IFactory,
val projectFinder: ProjectFinder,
val dependencyData: RemoteDependencyData,
val resolveDependency: ResolveDependency) {
data class RunInfo(val jc: JCommander, val args: Args)
@ -98,21 +98,21 @@ class Main @Inject constructor(
//
// Install plug-ins requested from the command line
//
installCommandLinePlugins(args)
val pluginClassLoader = installCommandLinePlugins(args)
if (args.client) {
client.run()
return 0
}
var result = 1
var result = 0
val latestVersionFuture = github.latestKobaltVersion
try {
result = runWithArgs(jc, args, argv)
result = runWithArgs(jc, args, argv, pluginClassLoader)
} catch(ex: Throwable) {
error("", ex.cause ?: ex)
result = 1
}
if (!args.update) {
@ -121,16 +121,130 @@ class Main @Inject constructor(
return result
}
private fun runWithArgs(jc: JCommander, args: Args, argv: Array<String>): Int {
val p = if (args.buildFile != null) File(args.buildFile) else File(".")
private fun runWithArgs(jc: JCommander, args: Args, argv: Array<String>, pluginClassLoader: ClassLoader): Int {
// val file = File("/Users/beust/.kobalt/repository/com/google/guava/guava/19.0-rc2/guava-19.0-rc2.pom")
// val md5 = Md5.toMd5(file)
// val md52 = MessageDigest.getInstance("MD5").digest(file.readBytes()).toHexString()
var result = 0
val p = if (args.buildFile != null) File(args.buildFile) else KFiles.findBuildFile()
args.buildFile = p.absolutePath
val buildFile = BuildFile(Paths.get(p.absolutePath), p.name)
if (!args.update) {
kobaltLog(1, AsciiArt.banner + Kobalt.version + "\n")
println(AsciiArt.banner + Kobalt.version + "\n")
}
return options.run(jc, args, argv)
if (args.templates != null) {
//
// --init: create a new build project and install the wrapper
// Make sure the wrapper won't call us back with --noLaunch
//
projectGenerator.run(args, pluginClassLoader)
// The wrapper has to call System.exit() in order to set the exit code,
// so make sure we call it last (or possibly launch it in a separate JVM).
com.beust.kobalt.wrapper.Main.main(arrayOf("--noLaunch") + argv)
} else if (args.usage) {
jc.usage()
} else {
// Options that don't need Build.kt to be parsed first
if (args.gc) {
Gc().run()
} else if (args.update) {
// --update
updateKobalt.updateKobalt()
} else if (args.serverMode) {
// --server
val port = serverFactory.create(args.force, args.port, { cleanUp() }).call()
} else {
//
// Everything below requires to parse the build file first
//
if (!buildFile.exists()) {
error(buildFile.path.toFile().path + " does not exist")
} else {
val allProjects = projectFinder.initForBuildFile(buildFile, args)
addOptionsFromBuild(args, Kobalt.optionsFromBuild)
if (args.listTemplates) {
// --listTemplates
Templates().displayTemplates(pluginInfo)
} else if (args.projectInfo) {
// --projectInfo
allProjects.forEach {
it.compileDependencies.filter { it.isMaven }.forEach {
resolveDependency.run(it.id)
}
}
} else if (args.dependency != null) {
// --resolve
args.dependency?.let { resolveDependency.run(it) }
} else if (args.tasks) {
// --tasks
displayTasks()
} else if (args.checkVersions) {
// --checkVersions
checkVersions.run(allProjects)
} else if (args.download) {
// --download
updateKobalt.downloadKobalt()
} else {
//
// Launch the build
//
val runTargetResult = taskManager.runTargets(args.targets, allProjects)
if (result == 0) {
result = if (runTargetResult.taskResult.success) 0 else 1
}
// Shutdown all plug-ins
plugins.shutdownPlugins()
// Run the build report contributors
pluginInfo.buildReportContributors.forEach {
it.generateReport(Kobalt.context!!)
}
}
}
}
}
return result
}
private fun addOptionsFromBuild(args: Args, optionsFromBuild: ArrayList<String>) {
optionsFromBuild.forEach {
when(it) {
Args.SEQUENTIAL -> args.sequential = true
else -> throw IllegalArgumentException("Unsupported option found in kobaltOptions(): " + it)
}
}
}
private fun cleanUp() {
pluginInfo.cleanUp()
taskManager.cleanUp()
}
private fun displayTasks() {
//
// List of tasks, --tasks
//
val tasksByPlugins = HashMultimap.create<String, PluginTask>()
taskManager.annotationTasks.forEach {
tasksByPlugins.put(it.plugin.name, it)
}
val sb = StringBuffer("List of tasks\n")
tasksByPlugins.keySet().forEach { name ->
sb.append("\n " + AsciiArt.horizontalDoubleLine + " $name "
+ AsciiArt.horizontalDoubleLine + "\n")
tasksByPlugins[name].distinctBy {
it.name
}.sortedBy {
it.name
}.forEach { task ->
sb.append(" ${task.name}\t\t${task.doc}\n")
}
}
println(sb.toString())
}
}

View file

@ -1,210 +0,0 @@
package com.beust.kobalt
import com.beust.jcommander.JCommander
import com.beust.kobalt.api.ITask
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.app.ProjectFinder
import com.beust.kobalt.app.ProjectGenerator
import com.beust.kobalt.app.Templates
import com.beust.kobalt.app.UpdateKobalt
import com.beust.kobalt.app.remote.KobaltServer
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.internal.build.BuildSources
import com.beust.kobalt.internal.build.SingleFileBuildSources
import com.beust.kobalt.misc.CheckVersions
import com.beust.kobalt.misc.kobaltLog
import com.beust.kobalt.wrapper.Main
import com.google.common.collect.HashMultimap
import com.google.inject.Inject
import java.io.File
/**
* Some options require a build file, others shouldn't have one and some don't care. This
* class captures these requirements.
*/
open class Option(open val enabled: () -> Boolean, open val action: () -> Unit,
open val requireBuildFile: Boolean = true)
class OptionalBuildOption(override val enabled: () -> Boolean, override val action: () -> Unit)
: Option(enabled, action, false)
class Options @Inject constructor(
val plugins: Plugins,
val checkVersions: CheckVersions,
val projectGenerator: ProjectGenerator,
val pluginInfo: PluginInfo,
val serverFactory: KobaltServer.IFactory,
val updateKobalt: UpdateKobalt,
val projectFinder: ProjectFinder,
val taskManager: TaskManager,
val resolveDependency: ResolveDependency
) {
fun run(jc: JCommander, args: Args, argv: Array<String>): Int {
val p = if (args.buildFile != null) File(args.buildFile) else File(".")
// val buildFile = BuildFile(Paths.get(p.absolutePath), p.name)
val buildSources = if (p.isDirectory) BuildSources(p.absoluteFile) else SingleFileBuildSources(p)
val pluginClassLoader = javaClass.classLoader
//
// Attempt to parse the build file in order to correctly set up repos, plug-ins, etc...
// If the build file can't be parsed, don't give up just yet since some options don't need
// a correct build file to work.
//
var buildError: Throwable? = null
val allProjects =
try {
projectFinder.initForBuildFile(buildSources, args).projects
} catch(ex: Exception) {
buildError = ex
listOf<Project>()
}
fun runIfSuccessfulBuild(buildError: Throwable?, action: () -> Unit) {
buildError?.let { throw it }
action()
}
// Modify `args` with options found in buildScript { kobaltOptions(...) }, if any
addOptionsFromBuild(args, Kobalt.optionsFromBuild)
val options = listOf<Option>(
OptionalBuildOption( { -> args.templates != null }, {
//
// --init: create a new build project and install the wrapper
// Make sure the wrapper won't call us back with --noLaunch
//
projectGenerator.run(args, pluginClassLoader)
// The wrapper has to call System.exit() in order to set the exit code,
// so make sure we call it last (or possibly launch it in a separate JVM).
Main.main(arrayOf("--noLaunch") + argv)
}),
OptionalBuildOption( { -> args.usage }, { jc.usage() }),
OptionalBuildOption( { -> args.update }, {
/* --update*/
updateKobalt.updateKobalt() }),
OptionalBuildOption( { -> args.serverMode }, {
// --server
val port = serverFactory.create(args.force, args.port, { cleanUp() }).call()
}),
OptionalBuildOption( { -> args.listTemplates}, {
// --listTemplates
Templates().displayTemplates(pluginInfo)
}),
Option( { -> args.projectInfo }, {
// --projectInfo
runIfSuccessfulBuild(buildError) {
allProjects.forEach {
it.compileDependencies.filter { it.isMaven }.forEach {
resolveDependency.run(it.id)
}
}
}
}),
Option( { args.dependency != null }, {
// --resolve
args.dependency?.let { resolveDependency.run(it) }
}),
Option( { args.tasks }, {
// --tasks
runIfSuccessfulBuild(buildError) {
displayTasks(allProjects, Kobalt.context!!)
}
}),
Option( { args.checkVersions }, {
// --checkVersions
runIfSuccessfulBuild(buildError) {
checkVersions.run(allProjects)
}
}),
Option( { args.download }, {
// --download
updateKobalt.downloadKobalt()
})
)
var processedOption = false
options.forEach {
if (it.enabled()) {
if ((it.requireBuildFile && buildSources.exists()) || ! it.requireBuildFile) {
it.action()
processedOption = true
} else if (it.requireBuildFile && ! buildSources.exists()) {
throw KobaltException("Couldn't find a build file")
}
}
}
var result = 0
if (! processedOption) {
//
// Launch the build
//
if (! buildSources.exists()) {
throw KobaltException("Could not find build file: " + buildSources)
}
runIfSuccessfulBuild(buildError) {
val runTargetResult = taskManager.runTargets(args.targets, allProjects)
if (result == 0) {
result = if (runTargetResult.taskResult.success) 0 else 1
}
// Shutdown all plug-ins
plugins.shutdownPlugins()
// Run the build report contributors
pluginInfo.buildReportContributors.forEach {
it.generateReport(Kobalt.context!!)
}
}
}
return result
}
private fun cleanUp() {
pluginInfo.cleanUp()
taskManager.cleanUp()
Kobalt.cleanUp()
}
private fun addOptionsFromBuild(args: Args, optionsFromBuild: ArrayList<String>) {
optionsFromBuild.forEach {
when(it) {
Args.SEQUENTIAL -> args.sequential = true
else -> throw IllegalArgumentException("Unsupported option found in kobaltOptions(): " + it)
}
}
}
private fun displayTasks(projects: List<Project>, context: KobaltContext) {
//
// List of tasks, --tasks
//
val tasksByPlugins = HashMultimap.create<String, ITask>()
projects.forEach { project ->
pluginInfo.taskContributors.forEach {
val tasks = it.tasksFor(project, context)
tasks.forEach {
tasksByPlugins.put(it.plugin.name, it)
}
}
}
listOf(taskManager.annotationTasks, taskManager.dynamicTasks).forEach { tasks ->
tasks.forEach {
tasksByPlugins.put(it.plugin.name, it)
}
}
val sb = StringBuffer("List of tasks\n")
tasksByPlugins.keySet().forEach { name ->
sb.append("\n " + AsciiArt.horizontalDoubleLine + " $name "
+ AsciiArt.horizontalDoubleLine + "\n")
tasksByPlugins[name].distinctBy(ITask::name).sortedBy(ITask::name).forEach { task ->
sb.append(" ${task.name}\t\t${task.doc}\n")
}
}
kobaltLog(1, sb.toString())
}
}

View file

@ -1,6 +1,7 @@
package com.beust.kobalt.app
import com.beust.kobalt.Args
import com.beust.kobalt.Constants
import com.beust.kobalt.Plugins
import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.Kobalt
@ -11,7 +12,7 @@ import com.beust.kobalt.internal.IncrementalManager
import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.ParallelLogger
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.build.IBuildSources
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.internal.build.VersionFile
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.PomGenerator
@ -23,6 +24,7 @@ import com.beust.kobalt.plugin.kotlin.kotlinCompilePrivate
import com.google.inject.assistedinject.Assisted
import java.io.File
import java.net.URL
import java.nio.file.Paths
import javax.inject.Inject
/**
@ -30,16 +32,16 @@ import javax.inject.Inject
* 1) Extract the repos() and plugins() statements in a separate .kt and compile it into preBuildScript.jar.
* 2) Actually build the whole Build.kt file after adding to the classpath whatever phase 1 found (plugins, repos)
*/
class BuildFileCompiler @Inject constructor(@Assisted("buildSources") val buildSources: IBuildSources,
class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val buildFiles: List<BuildFile>,
@Assisted val pluginInfo: PluginInfo, val files: KFiles, val plugins: Plugins,
val dependencyManager: DependencyManager, val pluginProperties: PluginProperties,
val executors: KobaltExecutors, val buildScriptUtil: BuildScriptUtil, val settings: KobaltSettings,
val incrementalManagerFactory: IncrementalManager.IFactory, val args: Args,
val resolver: KobaltMavenResolver, val pomGeneratorFactory: PomGenerator.IFactory,
val parallelLogger: ParallelLogger, val buildFiles: BuildFiles) {
val parallelLogger: ParallelLogger) {
interface IFactory {
fun create(@Assisted("buildSources") buildSources: IBuildSources, pluginInfo: PluginInfo) : BuildFileCompiler
fun create(@Assisted("buildFiles") buildFiles: List<BuildFile>, pluginInfo: PluginInfo) : BuildFileCompiler
}
private val SCRIPT_JAR = "buildScript.jar"
@ -75,67 +77,62 @@ class BuildFileCompiler @Inject constructor(@Assisted("buildSources") val buildS
return projectResult
}
val parsedBuildFiles = arrayListOf<ParsedBuildFile>()
class FindProjectResult(val context: KobaltContext, val projects: List<Project>, val pluginUrls: List<URL>,
val buildContentRoots: List<String>, val taskResult: TaskResult)
val taskResult: TaskResult)
private fun findProjects(context: KobaltContext): FindProjectResult {
val root = buildSources.root
var errorTaskResult: TaskResult? = null
val projects = arrayListOf<Project>()
buildFiles.forEach { buildFile ->
val parsedBuildFile = parseBuildFile(context, buildFile)
parsedBuildFiles.add(parsedBuildFile)
val pluginUrls = parsedBuildFile.pluginUrls
val buildScriptJarFile = File(KFiles.findBuildScriptLocation(buildFile, SCRIPT_JAR))
// If buildScript.jar was generated by a different version, wipe our temporary build directory
val buildScriptJarDir = KFiles.findBuildScriptDir(root.absolutePath)
buildScriptJarDir.let { dir ->
if (! VersionFile.isSameVersionFile(dir)) {
kobaltLog(1, "Detected new installation, wiping $dir")
dir.listFiles().map(File::delete)
//
// Save the current build script absolute directory
//
context.internalContext.absoluteDir = buildFile.absoluteDir
// If the script jar files were generated by a different version, wipe them in case the API
// changed in-between
buildScriptJarFile.parentFile.let { dir ->
if (! VersionFile.isSameVersionFile(dir)) {
kobaltLog(1, "Detected new installation, wiping $dir")
dir.listFiles().map(File::delete)
}
}
}
// Parse the build files in kobalt/src/*.kt, which will analyze all the buildScriptInfo{} sections
// and possibly add new source build directories. The output of this process is a new Build.kt
// file that contains the aggregation of all the build files with the profiles applied and with
// the included build files inserted at the correct line.
val parseResult = buildFiles.parseBuildFiles(root.absolutePath, context)
val newBuildKt = parseResult.buildKt
//
// Save the current build script absolute directory
//
context.internalContext.absoluteDir = buildSources.root
val buildScriptJarFile = File(KFiles.findBuildScriptDir(root.absolutePath), SCRIPT_JAR)
//
// Compile the newly generated Build.kt file
//
val pluginUrls = Plugins.dynamicPlugins.map { it.jarFile.get().toURI().toURL() }
val containsProfiles = false
val taskResult = maybeCompileBuildFile(context, listOf(newBuildKt.absolutePath),
buildScriptJarFile, pluginUrls, context.internalContext.forceRecompile,
containsProfiles)
//
// Run the new Build.kt
//
if (taskResult.success) {
projects.addAll(buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, pluginUrls, context))
} else {
if (errorTaskResult == null) {
errorTaskResult = taskResult
// Write the modified Build.kt (e.g. maybe profiles were applied) to a temporary file,
// compile it, jar it in buildScript.jar and run it
val modifiedBuildFile = KFiles.createTempBuildFileInTempDirectory(deleteOnExit = true)
KFiles.saveFile(modifiedBuildFile, parsedBuildFile.buildScriptCode)
val taskResult = maybeCompileBuildFile(context, BuildFile(Paths.get(modifiedBuildFile.path),
"Modified ${Constants.BUILD_FILE_NAME}", buildFile.realPath),
buildScriptJarFile, pluginUrls, context.internalContext.forceRecompile,
parsedBuildFile.containsProfiles)
if (taskResult.success) {
projects.addAll(buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, pluginUrls, context))
} else {
if (errorTaskResult == null) {
errorTaskResult = taskResult
}
}
// Clear the absolute dir
context.internalContext.absoluteDir = null
}
// Clear the absolute dir
context.internalContext.absoluteDir = null
return FindProjectResult(context, projects, pluginUrls, parseResult.buildSourceDirectories,
if (errorTaskResult != null) errorTaskResult else TaskResult())
val pluginUrls = parsedBuildFiles.flatMap { it.pluginUrls }
return FindProjectResult(context, projects, pluginUrls,
if (errorTaskResult != null) errorTaskResult!! else TaskResult())
}
fun maybeCompileBuildFile(context: KobaltContext, sourceFiles: List<String>, buildScriptJarFile: File,
private fun maybeCompileBuildFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File,
pluginUrls: List<URL>, forceRecompile: Boolean, containsProfiles: Boolean) : TaskResult {
kobaltLog(2, "Compiling into $buildScriptJarFile")
kobaltLog(2, "Running build file ${buildFile.name} jar: $buildScriptJarFile")
// If the user specifed --profiles, always recompile the build file since we don't know if
// the current buildScript.jar we have contains the correct value for these profiles
@ -143,15 +140,16 @@ class BuildFileCompiler @Inject constructor(@Assisted("buildSources") val buildS
// in this case, we won't recompile the build file. A potential solution for this would be
// to have a side file that describes which profiles the current buildScript.jar was
// compiled with.
if (! containsProfiles && !forceRecompile && buildScriptUtil.isUpToDate(buildSources, buildScriptJarFile)) {
val bs = BuildScriptJarFile(buildScriptJarFile)
if (! containsProfiles && !forceRecompile && buildScriptUtil.isUpToDate(buildFile, buildScriptJarFile)) {
kobaltLog(2, " Build file $buildScriptJarFile is up to date")
return TaskResult()
} else {
val reason =
if (containsProfiles) "profiles were found"
if (containsProfiles) "it contains profiles"
else if (forceRecompile) "forceRecompile is true"
else "it's been modified"
kobaltLog(2, " Need to recompile $buildSources because $reason")
else "it is not up to date"
kobaltLog(2, " Need to recompile ${buildFile.name} because $reason")
buildScriptJarFile.deleteRecursively()
val buildFileClasspath = Kobalt.buildFileClasspath.map { it.jarFile.get() }.map { it.absolutePath }
@ -159,11 +157,12 @@ class BuildFileCompiler @Inject constructor(@Assisted("buildSources") val buildS
classpath(files.kobaltJar)
classpath(pluginUrls.map { it.file })
classpath(buildFileClasspath)
sourceFiles(sourceFiles)
sourceFiles(listOf(buildFile.path.toFile().absolutePath))
output = buildScriptJarFile
noIncrementalKotlin = true
}.compile(context = context)
//
// Generate the file that contains the list of active profiles for this build file
//
@ -172,4 +171,12 @@ class BuildFileCompiler @Inject constructor(@Assisted("buildSources") val buildS
return result
}
}
/**
* Generate the script file with only the plugins()/repos() directives and run it. Then return
* - the source code for the modified Build.kt (after profiles are applied)
* - the URL's of all the plug-ins that were found.
*/
private fun parseBuildFile(context: KobaltContext, buildFile: BuildFile) =
ParsedBuildFile(buildFile, context, buildScriptUtil, dependencyManager, files)
}

View file

@ -1,265 +0,0 @@
package com.beust.kobalt.app
import com.beust.kobalt.Args
import com.beust.kobalt.KobaltException
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.homeDir
import com.beust.kobalt.internal.KobaltPluginXml
import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.build.BuildSources
import com.beust.kobalt.misc.*
import com.google.inject.Inject
import java.io.File
import java.net.URL
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes
import java.util.*
import java.util.regex.Pattern
/**
* Parse all the files found in kobalt/src/ *kt, extract their buildScriptInfo blocks,
* save the location where they appear (file, start/end).
* Compile each of these buildScriptInfo separately, note which new build files they add
* and at which location.
* Go back over all the files from kobalt/src/ *kt, insert each new build file in it,
* save it as a modified, concatenated big build file in .kobalt/build/Built.kt.
* Compile .kobalt/build/Build.kt into buildScript.jar.
*
* And while doing all that, apply all the active profiles.
*/
class BuildFiles @Inject constructor(val factory: BuildFileCompiler.IFactory,
val buildScriptUtil: BuildScriptUtil) {
var containsProfiles = false
val projects = arrayListOf<Project>()
class BuildFileWithBuildScript(val file: File, val buildScriptInfo: BuildScriptInfo)
class BuildFileParseResult(val projectRoot: String, val buildKt: File,
val buildSourceDirectories: List<String>)
/**
* @return the new Build.kt
*/
fun parseBuildFiles(projectDir: String, context: KobaltContext) : BuildFileParseResult {
val profiles = Profiles(context)
val bsiMap = hashMapOf<File, BuildFileWithBuildScript>()
val newSourceDirs = arrayListOf<IncludedBuildSourceDir>()
//
// Create a map of File -> FileWithBuildScript
//
val filesWithBuildScript = parseBuildScriptInfos(projectDir, context, profiles)
filesWithBuildScript.forEach {
bsiMap.put(it.file, it)
}
//
// Add any source directory we found
//
if (filesWithBuildScript.any()) {
filesWithBuildScript.forEach { af ->
val bsi = af.buildScriptInfo
newSourceDirs.addAll(bsi.includedBuildSourceDirs)
}
log(2, " Found buildScriptInfos: " + filesWithBuildScript)
} else {
log(2, " No buildScriptInfos")
}
//
// Go through all the build files and insert the content of included directories wherever appropriate
//
val imports = arrayListOf<String>()
val code = arrayListOf<String>()
val sourceDir = sourceDir(projectDir)
findFiles(sourceDir, { it.name.endsWith(".kt") }).forEach { file ->
code.add("\n// $file")
val analyzedFile = bsiMap[file]
val bsi = analyzedFile?.buildScriptInfo
file.readLines().forEachIndexed { lineNumber, line ->
if (bsi == null || ! bsi.isInSection(lineNumber)) {
//
// Not a buildScriptInfo section, just copy the line as is
//
profiles.correctProfileLine(line).let { pair ->
val cpl = pair.first
containsProfiles = containsProfiles or pair.second
(if (cpl.startsWith("import")) imports else code).add(cpl)
}
} else {
//
// We're inside a buildScriptInfo section, see if it includes any buildSourceDirs
// and if it does, include these build files here
//
val isd = bsi.includedBuildSourceDirsForLine(lineNumber)
log(2, " Skipping buildScript{} line $lineNumber from file $file")
if (isd.any()) {
// If we found any new buildSourceDirs, all all the files found in these directories
// to the big Build.kt
val allBuildFiles = isd.flatMap { findBuildSourceFiles(projectDir + File.separator + it) }
val sbf = includeFileContent(context, allBuildFiles, profiles)
imports.addAll(sbf.imports)
code.addAll(sbf.code)
}
}
}
}
//
// Create the big Build.kt out of the imports and code we've found so far
//
val newBuildFile = with(File(KFiles.findBuildScriptDir(projectDir), "Build.kt")) {
parentFile.mkdirs()
val imp = arrayListOf<String>().apply {
addAll(imports)
}.toMutableSet().toMutableList()
Collections.sort(imp)
writeText(imp.joinToString("\n"))
appendText(code.joinToString("\n"))
this
}
val newDirs = listOf(File(BuildFiles.buildContentRoot(projectDir)).relativeTo(File(projectDir)).path) +
newSourceDirs.flatMap{ it.dirs.map { BuildFiles.buildContentRoot(it)} }
return BuildFileParseResult(projectDir, newBuildFile, newDirs)
}
class SplitBuildFile(val imports: List<String>, val code: List<String>, val containsProfiles: Boolean)
private fun includeFileContent(context: KobaltContext, files: List<File>, profiles: Profiles) : SplitBuildFile {
val imports = arrayListOf<String>()
val code = arrayListOf<String>()
files.forEach {
code.add("// $it")
val sbf = profiles.applyProfiles(it.readLines())
containsProfiles = containsProfiles or sbf.containsProfiles
imports.addAll(sbf.imports)
code.addAll(sbf.code)
}
return SplitBuildFile(imports, code, containsProfiles)
}
companion object {
val BUILD_SCRIPT_REGEXP: Pattern = Pattern.compile("^val.*buildScript.*\\{")
val BLOCK_EXTRACTOR = BlockExtractor(BUILD_SCRIPT_REGEXP, '{', '}')
/**
* The content root for a build file module.
*/
fun buildContentRoot(root: String) = root + File.separatorChar + "kobalt"
}
fun parseBuildScriptInfos(projectDir: String, context: KobaltContext, profiles: Profiles)
: List<BuildFileWithBuildScript> {
val root = sourceDir(projectDir)
val files = findBuildSourceFiles(projectDir)
val toProcess = arrayListOf<File>().apply { addAll(files) }
// Parse each build file and associate it with a BuildScriptInfo if any buildScript{} is found
val analyzedFiles = arrayListOf<BuildFileWithBuildScript>()
toProcess.forEach { buildFile ->
val splitBuildFile = profiles.applyProfiles(buildFile.readLines())
containsProfiles = containsProfiles or splitBuildFile.containsProfiles
val bsi = BLOCK_EXTRACTOR.extractBlock(buildFile, (splitBuildFile.imports + splitBuildFile.code))
if (bsi != null) analyzedFiles.add(BuildFileWithBuildScript(buildFile, bsi))
}
// Run every buildScriptInfo section in its own source file
var counter = 0
analyzedFiles.forEach { af ->
val buildScriptInfo = af.buildScriptInfo
buildScriptInfo.sections.forEach { section ->
//
// Create a source file with just this buildScriptInfo{}
//
val bs = af.file.readLines().subList(section.start, section.end + 1)
val source = (buildScriptInfo.imports + buildScriptInfo.topLines + bs).joinToString("\n")
val sourceFile = Files.createTempFile(null, ".kt").toFile().apply {
writeText(source)
}
val buildScriptJarFile = File(KFiles.findBuildScriptDir(projectDir), "preBuildScript-$counter.jar").apply {
delete()
}
counter++
//
// Compile it to preBuildScript-xxx.jar
//
kobaltLog(2, " Compiling buildScriptInfo $sourceFile to $buildScriptJarFile")
val taskResult = factory.create(BuildSources(root), context.pluginInfo).maybeCompileBuildFile(context,
listOf(sourceFile.path),
buildScriptJarFile, emptyList<URL>(),
context.internalContext.forceRecompile,
containsProfiles)
if (! taskResult.success) {
throw KobaltException("Couldn't compile $sourceFile: ${taskResult.errorMessage}")
}
log(2, "Created $buildScriptJarFile")
//
// Run preBuildScript.jar to initialize plugins and repos
//
val currentDirs = arrayListOf<String>().apply { addAll(Kobalt.buildSourceDirs) }
buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, listOf<URL>(), context)
val newDirs = arrayListOf<String>().apply { addAll(Kobalt.buildSourceDirs) }
newDirs.removeAll(currentDirs)
if (newDirs.any()) {
buildScriptInfo.addBuildSourceDir(IncludedBuildSourceDir(section.start, newDirs))
}
}
}
return analyzedFiles
}
private fun sourceDir(root: String) = File(KFiles.joinDir(buildContentRoot(root), "src"))
private fun findFiles(file: File, accept: (File) -> Boolean) : List<File> {
val result = arrayListOf<File>()
// It's possible for no build file to be present (e.g. testing)
if (file.exists()) {
Files.walkFileTree(Paths.get(file.path), object : SimpleFileVisitor<Path>() {
override fun visitFile(file: Path, attrs: BasicFileAttributes?): FileVisitResult {
if (accept(file.toFile())) result.add(file.toFile())
return FileVisitResult.CONTINUE
}
})
}
return result
}
private fun findBuildSourceFiles(root: String) : List<File> {
val result = arrayListOf<File>()
result.addAll(findFiles(sourceDir(root), { it.name.endsWith(".kt") }))
return result
}
}
fun main(argv: Array<String>) {
val args = Args().apply {
noIncrementalKotlin = true
}
val context = KobaltContext(args)
KobaltLogger.LOG_LEVEL = 3
context.pluginInfo = PluginInfo(KobaltPluginXml(), null, null)
Kobalt.init(MainModule(args, KobaltSettings.readSettingsXml()))
val bf = Kobalt.INJECTOR.getInstance(BuildFiles::class.java)
bf.parseBuildFiles(homeDir("kotlin/klaxon/"), context)
}

View file

@ -9,7 +9,7 @@ import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.IncrementalTask
import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.internal.build.IBuildSources
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.Topological
import com.beust.kobalt.misc.kobaltLog
@ -123,9 +123,9 @@ class BuildScriptUtil @Inject constructor(val plugins: Plugins, val files: KFile
}
}
fun isUpToDate(buildSources: IBuildSources, jarFile: File) =
buildSources.exists() && jarFile.exists()
&& buildSources.findSourceFiles().all { it.lastModified() < jarFile.lastModified() }
fun isUpToDate(buildFile: BuildFile, jarFile: File) =
buildFile.exists() && jarFile.exists()
&& buildFile.lastModified < jarFile.lastModified()
/**
* Make sure all the projects have a unique name.

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