diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..dffffe6 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,31 @@ +version: 2 +jobs: + build: + docker: + - image: circleci/openjdk:8-jdk + + working_directory: ~/repo + + environment: + JVM_OPTS: -Xmx3200m + TERM: dumb + + steps: + - checkout + - restore_cache: + keys: + - kobalt-dependencies-{{ checksum "kobalt/src/Build.kt" }} + # fallback to using the latest cache if no exact match is found + - kobalt-dependencies- + + - run: + name: Check Versions + command: ./kobaltw checkVersions + + - save_cache: + paths: ~/.kobalt + key: kobalt-dependencies-{{ checksum "kobalt/src/Build.kt" }} + + - run: + name: Assemble + command: ./kobaltw assemble \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6ec2ae2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# batch files are specific to windows and always crlf +*.bat eol=crlf diff --git a/.gitignore b/.gitignore index 58a18f4..173de82 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,9 @@ **/.idea/tasks.xml **/.idea/workspace.xml *.iws -.DS_Store +*.sublime-* .classpath +.DS_Store .gradle .kobalt .nb-gradle @@ -15,8 +16,10 @@ /build /deploy /dist +/example/libs/ /gen /gradle.properties +/lib /libs /local.properties /out @@ -24,7 +27,6 @@ /project.properties /target /test-output -Thumbs.db ehthumbs.db kobaltBuild -/example/libs/ +Thumbs.db \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 0000000..5add346 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index a852314..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/copyright/Erik_s_Copyright_Notice.xml b/.idea/copyright/Erik_s_Copyright_Notice.xml index 5cd1489..6763f1b 100644 --- a/.idea/copyright/Erik_s_Copyright_Notice.xml +++ b/.idea/copyright/Erik_s_Copyright_Notice.xml @@ -1,6 +1,6 @@ \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml index 89ab48c..2bbc8ca 100644 --- a/.idea/copyright/profiles_settings.xml +++ b/.idea/copyright/profiles_settings.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b31283..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/kobalt.xml b/.idea/kobalt.xml index 22821d8..c71b85c 100644 --- a/.idea/kobalt.xml +++ b/.idea/kobalt.xml @@ -4,9 +4,15 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 30626e1..7826943 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -38,27 +38,29 @@ - - + + + + + + + + + Java + + + Portability issuesJava + + + + + Android + + + + - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index de1fa43..48f8f9e 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,6 +3,7 @@ + \ No newline at end of file diff --git a/.idea/scopes/Copyright.xml b/.idea/scopes/Copyright.xml new file mode 100644 index 0000000..e487d4e --- /dev/null +++ b/.idea/scopes/Copyright.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/scopes/Source.xml b/.idea/scopes/Source.xml deleted file mode 100644 index f3b802c..0000000 --- a/.idea/scopes/Source.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9b93be0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,19 @@ +language: java + +jdk: + - oraclejdk8 + +before_install: + - chmod +x kobaltw + +install: true + +cache: + directories: + - $HOME/.m2 + - $HOME/.kobalt + +before_cache: + - rm -rf .kobalt/* + +script: ./kobaltw clean assemble diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..f30d392 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2016-2017, Erik C. Thauvin (erik@thauvin.net) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of this project nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7081070 --- /dev/null +++ b/README.md @@ -0,0 +1,172 @@ +# Command Line Execution plug-in for [Kobalt](http://beust.com/kobalt/home/index.html) + +[![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](http://opensource.org/licenses/BSD-3-Clause) [![release](https://img.shields.io/github/release/ethauvin/kobalt-exec.svg)](https://github.com/ethauvin/kobalt-exec/releases/latest) [![Build Status](https://travis-ci.org/ethauvin/kobalt-exec.svg?branch=master)](https://travis-ci.org/ethauvin/kobalt-exec) [![CircleCI](https://circleci.com/gh/ethauvin/kobalt-exec/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/kobalt-exec/tree/master) [![Download](https://api.bintray.com/packages/ethauvin/maven/kobalt-exec/images/download.svg)](https://bintray.com/ethauvin/maven/kobalt-exec/_latestVersion) + +The plug-in allows for the execution of system commands, similarly to the [Gradle Exec](https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Exec.html) or [Ant Exec](https://ant.apache.org/manual/Tasks/exec.html) tasks. + +To use the plug-in include the following in your `Build.kt` file: + +```kotlin +import net.thauvin.erik.kobalt.plugin.exec.* + +val bs = buildScript { + plugins("net.thauvin.erik:kobalt-exc:") +} + +val p = project { + name = "example" + + exec { + commandLine("echo", "Hello, World!") + } +} +``` +[View Example](https://github.com/ethauvin/kobalt-exec/blob/master/example/kobalt/src/Build.kt) + +To invoke the `exec` task: + +```sh +./kobaltw exec +``` + +## `commandLine` Directive + +The `commandLine` directive is used to execute command line(s) during the build process: + +```kotlin +exec { + commandLine("cmd", "/c", "stop.bat", dir = "../tomcat/bin", os = setOf(Os.WINDOWS)) + commandLine("./stop.sh", dir = "../tomcat/bin", os = setOf(Os.MAC, Os.LINUX)) + commandLine("sh", "-c", "ps aux | grep tomcat", os = setOf(Os.MAC, Os.LINUX), fail = setOf(Fail.EXIT)) + commandLine("cmd", "/c", "tasklist | find \"tomcat\"", os = setOf(Os.WINDOWS), fail = setOf(Fail.EXIT)) +} +``` + +## Parameters + +### `args` + +The full command line including the executable and all arguments. + +```kotlin +exec { + commandLine(args = "ls") + commandLine("ls", "-l") + commandLine("cmd", "/c", "dir /Q") +} +``` + +### `dir` + +The working directory in which the command should be executed. Defaults to the project directory. + +```kotlin +exec { + commandLine("cmd", "/c", "stop.bat", dir = "../tomcat/bin") + commandLine("./stop.sh", dir = "../tomcat/bin") +} +``` + +### `os` + +List of operating systems on which the command may be executed. If the current OS is contained within the list, the command will be executed. + +The following predefined values are available: + +Name | Operating System +:-------------|:------------------------- +`Os.CYGWIN` | Cygwin for Windows +`Os.FREEBSD` | FreeBSD +`Os.LINUX` | Linux +`Os.MAC` | Apple Macintosh / OS X +`Os.MINGW` | Minimalist GNU for Windows +`OS.MSYS` | MinGW Minimal System +`Os.OPENVMS` | OpenVMS +`Os.OS400` | OS/400 +`Os.SOLARIS` | Solaris / SunOS +`Os.TANDEM` | Tandem's Non-Stop +`Os.WINDOWS` | Microsoft Windows* +`Os.ZOS` | z/OS / OS/390 + +* Excluding Cygwin, MinGW and MSYS. + +```kotlin +exec { + commandLine("cmd", "/c", "stop.bat", os = setOf(Os.WINDOWS)) + commandLine("./stop.sh", os = setOf(Os.LINUX, Os.MAC)) +} +``` + +### `fail` + +List of error options to specify whether data returned to the standard streams and/or an abnormal exit value constitute build failure signaling. + +The following predefined values are available: + +Name | Failure When +:-------------|:---------------------------------------------------------------- +`Fail.EXIT` | Exit value > 0 +`Fail.NORMAL` | Exit value > 0 or any data to the standard error stream (stderr) +`Fail.OUTPUT` | Any data to the standard output stream (stdout) or stderr. +`Fail.STDERR` | Any data to stderr. +`Fail.STDOUT` | Any data to stdout. +`Fail.ALL` | Any of the conditions above. +`Fail.NONE` | Never fails. + +`Fail.NORMAL` is the default value. + +```kotlin +exec { + commandLine("cmd", "/c", "stop.bat", fail = setOf(Fail.EXIT)) + commandLine("./stop.sh", fail = setOf(Fail.EXIT, Fail.STDOUT)) +} +``` + +## taskName + +Additionally, you can specify a task name to easily identify multiple `exec` tasks. + +```kotlin +exec { + taskName = "start" + commandLine("./start.sh", os = setOf(Os.LINUX, Os.MAC)) +} + +exec { + taskName = "stop" + commandLine("./stop.sh", os = setOf(Os.LINUX, Os.MAC)) +} +``` + +```sh +./kobaltw start +./kobaltw stop +``` + +## dependsOn + + +By default the `exec` task depends on `assemble`, use the `dependsOn` parameter to change the dependencies: + +```kotlin +exec { + dependsOn = listOf("assemble", "run") + commandLine("cmd", "/c", "start.bat", fail = setOf(Fail.EXIT)) +} +``` + +## Logging / Debugging + +To view the output of the `exec` task, use: + +```sh +./kobaltw exec --log 2 +``` +You could also redirect the error stream to a file: + +```kotlin +exec { + commandLine("sh", "-c", "./stop.sh 2> error.txt", os = setOf(Os.LINUX)) + commandLine("cmd", "/c", "stop.bat 2> error.txt", os = setOf(Os.WINDOWS)) +} +``` \ No newline at end of file diff --git a/clean.sh b/clean.sh new file mode 100644 index 0000000..552252d --- /dev/null +++ b/clean.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +DEBUG=false + +rm="rm -rf" + +if [ "$DEBUG" = true ]; then + rm="echo rm -rf" +fi + +buildkt="kobalt/src/Build.kt" + +name=$(cat $buildkt | grep -m 1 "name = " | cut -d"\"" -f 2) +group=$(cat $buildkt | grep -m 1 "group = " | cut -d"\"" -f 2) + +if [ -z "$1" ]; then + version=$(cat $buildkt | grep -m 1 "version = " | cut -d"\"" -f 2) +else + version="$1" +fi + +maven="/k/maven/repository/${group//.//}/${name}/${version}" +kobalt="$HOME/.kobalt/cache/${group//.//}/${name}/${version}" +localRepo="$HOME/.kobalt/localMavenRepo/${group//.//}/${name}/${version}" + +read -p "Delete version ${version}? " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + for dir in "$kobalt" "$maven" "$localRepo"; do + if [ -d "$dir" ]; then + echo -e "Deleting : \e[32;1m$dir\e[0m" + $rm "$dir" + else + echo -e "Not Found: \e[31;1m$dir\e[0m" + fi + done +fi \ No newline at end of file diff --git a/example/kobalt/src/Build.kt b/example/kobalt/src/Build.kt index a55bb57..76e2c24 100644 --- a/example/kobalt/src/Build.kt +++ b/example/kobalt/src/Build.kt @@ -1,32 +1,25 @@ import com.beust.kobalt.* -import com.beust.kobalt.plugin.packaging.* import com.beust.kobalt.plugin.application.* -import com.beust.kobalt.plugin.java.* +import com.beust.kobalt.plugin.packaging.* import net.thauvin.erik.kobalt.plugin.exec.* -val pl = plugins(file("../kobaltBuild/libs/kobalt-exec-0.1.jar")) +// ./kobaltw exec echo ps --log 2 +// ./kobaltw exec --log 2 +// ./kobaltw echo --log 2 +// ./kobaltw ps --log 2 -val p = project { +val bs = buildScript { + repos(localMaven()) + plugins("net.thauvin.erik:kobalt-exec:") +} + +val example = project { name = "example" group = "com.example" artifactId = name version = "0.1" - sourceDirectories { - path("src/main/java") - } - - sourceDirectoriesTest { - path("src/test/java") - } - - dependencies { - } - - dependenciesTest { - } - assemble { jar { } @@ -37,7 +30,23 @@ val p = project { } exec { - commandLine(args = listOf("ls", "-l"), dir = "../libs", fail = setOf(Fail.NORMAL)) - commandLine(listOf("cmd", "/c", "echo", "Test"), os = listOf("Win", "Windows"), fail = setOf(Fail.NORMAL)) + commandLine("ls", "-l", dir = "../kobalt/wrapper", os = setOf(Os.LINUX, Os.MINGW, Os.CYGWIN)) + commandLine("cmd", "/c", "dir /Q", dir = "../kobalt/wrapper", os = setOf(Os.WINDOWS)) + } + + exec { + taskName = "echo" + dependsOn = listOf("exec", "run") + + val echo = arrayOf("echo", "Test", "Example") + commandLine(*echo, os = setOf(Os.LINUX, Os.MINGW, Os.CYGWIN)) + commandLine("cmd", "/c", *echo, os = setOf(Os.WINDOWS)) + } + + exec { + taskName = "ps" + dependsOn = listOf() // no dependencies + commandLine("sh", "-c", "ps aux | grep bash", os = setOf(Os.LINUX, Os.MINGW, Os.CYGWIN)) + commandLine("cmd", "/c", "tasklist | find \"cmd.exe\"", os = setOf(Os.WINDOWS), fail = setOf(Fail.EXIT)) } } \ No newline at end of file diff --git a/example/kobalt/wrapper/kobalt-wrapper.jar b/example/kobalt/wrapper/kobalt-wrapper.jar index f40ec90..7c076e6 100644 Binary files a/example/kobalt/wrapper/kobalt-wrapper.jar and b/example/kobalt/wrapper/kobalt-wrapper.jar differ diff --git a/example/kobalt/wrapper/kobalt-wrapper.properties b/example/kobalt/wrapper/kobalt-wrapper.properties index 0630fba..a6a4316 100644 --- a/example/kobalt/wrapper/kobalt-wrapper.properties +++ b/example/kobalt/wrapper/kobalt-wrapper.properties @@ -1 +1 @@ -kobalt.version=0.846 \ No newline at end of file +kobalt.version=1.0.90 diff --git a/example/kobaltw b/example/kobaltw old mode 100644 new mode 100755 index b27b3d8..c5186d5 --- a/example/kobaltw +++ b/example/kobaltw @@ -1 +1,2 @@ -java -jar $(dirname $0)/kobalt/wrapper/kobalt-wrapper.jar $* +#!/usr/bin/env sh +java -jar "`dirname "$0"`/kobalt/wrapper/kobalt-wrapper.jar" $* diff --git a/example/kobaltw.bat b/example/kobaltw.bat new file mode 100644 index 0000000..d578071 --- /dev/null +++ b/example/kobaltw.bat @@ -0,0 +1,4 @@ +@echo off +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +java -jar "%DIRNAME%/kobalt/wrapper/kobalt-wrapper.jar" %* diff --git a/kobalt-exec.iml b/kobalt-exec.iml new file mode 100644 index 0000000..bffb9cc --- /dev/null +++ b/kobalt-exec.iml @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kobalt/Build.kt.iml b/kobalt/Build.kt.iml index 7bc9dd6..0098d0a 100644 --- a/kobalt/Build.kt.iml +++ b/kobalt/Build.kt.iml @@ -1,12 +1,42 @@ - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kobalt/src/Build.kt b/kobalt/src/Build.kt index bd1af62..7a5bf23 100644 --- a/kobalt/src/Build.kt +++ b/kobalt/src/Build.kt @@ -1,15 +1,23 @@ +import com.beust.kobalt.buildScript +import com.beust.kobalt.localMaven +import com.beust.kobalt.file import com.beust.kobalt.plugin.packaging.assemble +import com.beust.kobalt.plugin.publish.autoGitTag import com.beust.kobalt.plugin.publish.bintray +import com.beust.kobalt.profile import com.beust.kobalt.project -import com.beust.kobalt.repos +import net.thauvin.erik.kobalt.plugin.versioneye.versionEye import org.apache.maven.model.Developer import org.apache.maven.model.License import org.apache.maven.model.Model import org.apache.maven.model.Scm -val repos = repos() +val bs = buildScript { + repos(localMaven()) + plugins("net.thauvin.erik:kobalt-versioneye:", "net.thauvin.erik:kobalt-maven-local:") +} -val dev = false +val dev by profile() val kobaltDependency = if (dev) "kobalt" else "kobalt-plugin-api" val p = project { @@ -17,11 +25,10 @@ val p = project { name = "kobalt-exec" group = "net.thauvin.erik" artifactId = name - version = "0.5.0-beta" + version = "0.7.0" pom = Model().apply { - name = project.name - description = "Command line execution plugin for the Kobalt build system" + description = "Command Line Execution plug-in for the Kobalt build system." url = "https://github.com/ethauvin/kobalt-exec" licenses = listOf(License().apply { name = "BSD 3-Clause" @@ -39,28 +46,36 @@ val p = project { }) } - sourceDirectories { - path("src/main/kotlin") - } - - sourceDirectoriesTest { - path("src/test/kotlin") - } - dependencies { - compile("com.beust:$kobaltDependency:0.842") + compile("com.beust:$kobaltDependency:") + compile("org.jetbrains.kotlin:kotlin-stdlib:1.1.51") } dependenciesTest { - compile("org.testng:testng:") - + compile("org.testng:testng:6.12") + compile("org.jetbrains.kotlin:kotlin-test:1.1.51") } assemble { - mavenJars {} + mavenJars { + fatJar = true + } + } + + autoGitTag { + enabled = true + push = false + message = "Version $version" } bintray { - publish = false + publish = true + description = "Release version $version" + vcsTag = version } -} + + versionEye { + org = "Thauvin" + team = "Owners" + } +} \ No newline at end of file diff --git a/kobalt/wrapper/kobalt-wrapper.jar b/kobalt/wrapper/kobalt-wrapper.jar index 6ca6ca5..7c076e6 100644 Binary files a/kobalt/wrapper/kobalt-wrapper.jar and b/kobalt/wrapper/kobalt-wrapper.jar differ diff --git a/kobalt/wrapper/kobalt-wrapper.properties b/kobalt/wrapper/kobalt-wrapper.properties index ef6d4d8..a6a4316 100644 --- a/kobalt/wrapper/kobalt-wrapper.properties +++ b/kobalt/wrapper/kobalt-wrapper.properties @@ -1 +1 @@ -kobalt.version=0.847 \ No newline at end of file +kobalt.version=1.0.90 diff --git a/kobaltw b/kobaltw old mode 100644 new mode 100755 index b27b3d8..c5186d5 --- a/kobaltw +++ b/kobaltw @@ -1 +1,2 @@ -java -jar $(dirname $0)/kobalt/wrapper/kobalt-wrapper.jar $* +#!/usr/bin/env sh +java -jar "`dirname "$0"`/kobalt/wrapper/kobalt-wrapper.jar" $* diff --git a/kobaltw.bat b/kobaltw.bat new file mode 100644 index 0000000..d578071 --- /dev/null +++ b/kobaltw.bat @@ -0,0 +1,4 @@ +@echo off +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +java -jar "%DIRNAME%/kobalt/wrapper/kobalt-wrapper.jar" %* diff --git a/src/main/kotlin/net/thauvin/erik/kobalt/plugin/exec/ExecPlugin.kt b/src/main/kotlin/net/thauvin/erik/kobalt/plugin/exec/ExecPlugin.kt index 7c94f19..9dccff5 100644 --- a/src/main/kotlin/net/thauvin/erik/kobalt/plugin/exec/ExecPlugin.kt +++ b/src/main/kotlin/net/thauvin/erik/kobalt/plugin/exec/ExecPlugin.kt @@ -1,7 +1,7 @@ /* * ExecPlugin.kt * - * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2016-2017, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,18 +31,21 @@ */ package net.thauvin.erik.kobalt.plugin.exec +import com.beust.kobalt.Plugins import com.beust.kobalt.TaskResult import com.beust.kobalt.api.* import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.misc.log -import java.io.BufferedReader -import java.io.File -import java.io.InputStream -import java.io.InputStreamReader +import com.google.inject.Inject +import com.google.inject.Singleton +import java.io.* +import java.util.* import java.util.concurrent.TimeUnit -class ExecPlugin : BasePlugin(), ITaskContributor { +@Singleton +class ExecPlugin @Inject constructor(val taskContributor: TaskContributor, val configActor: ConfigsActor) : + BasePlugin(), ITaskContributor, IConfigsActor by configActor { // ITaskContributor override fun tasksFor(project: Project, context: KobaltContext): List { return emptyList() @@ -54,76 +57,144 @@ class ExecPlugin : BasePlugin(), ITaskContributor { override val name = NAME - @Task(name = "exec", description = "Execute a command line process.") - fun taskExec(project: Project): TaskResult { - return executeCommands(project) + override fun apply(project: Project, context: KobaltContext) { + configurationFor(project)?.let { configs -> + configs.forEach { config -> + taskManager.addTask(this, project, config.taskName, + description = "Execute a command line process.", + group = "Other", + dependsOn = config.dependsOn, + task = { executeCommands(project, config) }) + taskContributor.addVariantTasks(this, project, context, config.taskName, + dependsOn = config.dependsOn, + runTask = { executeCommands(project, config) }) + } + } } - private fun executeCommands(project: Project): TaskResult { - var success = true - val config = configs[project.name] - val errorMessage = StringBuilder() + private fun isCygwin(): Boolean { + val path: String? = System.getenv("ORIGINAL_PATH") + return path?.contains("/cygdrive/") ?: false + } - if (config != null) { - for ((args, dir, os, fail) in config.commandLines) { - val wrkDir = File(if (dir.isNullOrBlank()) project.directory else dir) - if (wrkDir.isDirectory) { - var execute = (os.size == 0) - if (!execute) { - val curOs: String = System.getProperty("os.name") - for (name in os) { - execute = curOs.startsWith(name, true) - if (execute) break - } - } - if (execute) { - log(2, "> " + args.joinToString(" ")) - val pb = ProcessBuilder().command(args.toList()) - pb.directory(wrkDir) - val proc = pb.start() - val err = proc.waitFor(30, TimeUnit.SECONDS) - val stdout = if (proc.inputStream.available() > 0) fromStream(proc.inputStream) else emptyList() - val stderr = if (proc.errorStream.available() > 0) fromStream(proc.errorStream) else emptyList() - val cmdInfo = "Program \"" + args.joinToString(" ") + "\" (in directory \"${wrkDir.path}\"): " + private fun isMinGW(os: Os = Os.MINGW, any: Boolean = false): Boolean { + val msys: String? = System.getenv("MSYSTEM") - if (err == false) { - errorMessage.append(cmdInfo).append("TIMEOUT") - success = false - } else if (fail.isNotEmpty()) { - val all = fail.contains(Fail.ALL) - val output = fail.contains(Fail.OUTPUT) - if ((all || fail.contains(Fail.EXIT) || fail.contains(Fail.NORMAL)) && proc.exitValue() > 0) { - errorMessage.append(cmdInfo).append("EXIT ${proc.exitValue()}") - if (stderr.isNotEmpty()) errorMessage.append(", STDERR: ").append(stderr[0]) - success = false - } else if ((all || output || fail.contains(Fail.STDERR) || fail.contains(Fail.NORMAL)) - && stderr.isNotEmpty()) { - errorMessage.append(cmdInfo).append("STDERR, ").append(stderr[0]) - success = false - } else if ((all || output || fail.contains(Fail.STDOUT)) && stdout.isNotEmpty()) { - errorMessage.append(cmdInfo).append("STDOUT, ").append(stdout[0]) - success = false - } - } - } - } else { - errorMessage.append("Invalid working directory: \"${wrkDir.canonicalPath}\"") - success = false - } - - if (!success) break + if (!msys.isNullOrBlank()) { + if (any) { + return true + } else if (os.equals(Os.MSYS)) { + return msys!!.startsWith("MSYS") + } else if (os.equals(Os.MINGW)) { + return msys!!.startsWith("MINGW") } } - //@TODO until cedric fixes it. - if (!success) error(errorMessage) - - return TaskResult(success, errorMessage.toString()) + return false } - private val configs = hashMapOf() - fun addExecConfig(projectName: String, config: ExecConfig) { - configs.put(projectName, config) + private fun matchOs(os: Os): Boolean { + val curOs: String = System.getProperty("os.name").toLowerCase(Locale.US) + when (os) { + Os.WINDOWS -> { + if (!isMinGW(any = true) && !isCygwin()) { + return curOs.contains("windows") + } else { + return false + } + } + Os.MAC -> { + return (curOs.contains("mac") || curOs.contains("darwin") || curOs.contains("osx")) + } + Os.LINUX -> { + return curOs.contains("linux") + } + Os.FREEBSD -> { + return curOs.contains("freebsd") + } + Os.SOLARIS -> { + return (curOs.contains("sunos") || curOs.contains("solaris")) + } + Os.OPENVMS -> { + return curOs.contains("openvms") + } + Os.ZOS -> { + return (curOs.contains("z/os") || curOs.contains("os/390")) + } + Os.TANDEM -> { + return curOs.contains("nonstop_kernel") + } + Os.OS400 -> { + return curOs.contains("os/400") + } + Os.CYGWIN -> { + return isCygwin() + } + Os.MINGW -> { + return isMinGW() + } + Os.MSYS -> { + return isMinGW(Os.MSYS) + } + } + } + + private fun executeCommands(project: Project, config: ExecConfig): TaskResult { + var success = true + val errorMessage = StringBuilder() + + for ((args, dir, os, fail) in config.commandLines) { + val wrkDir = File(if (dir.isNullOrBlank()) project.directory else dir) + if (wrkDir.isDirectory) { + var execute = (os.isEmpty()) + if (!execute) { + for (name in os) { + execute = matchOs(name) + if (execute) break + } + } + if (execute) { + log(2, (if (!wrkDir.name.equals(".")) wrkDir.name else "") + "> " + args.joinToString(" ")) + val pb = ProcessBuilder().command(args.toList()) + pb.directory(wrkDir) + val proc = pb.start() + val err = proc.waitFor(30, TimeUnit.SECONDS) + val stdout = if (proc.inputStream.available() > 0) fromStream(proc.inputStream) else emptyList() + val stderr = if (proc.errorStream.available() > 0) fromStream(proc.errorStream) else emptyList() + val cmdInfo = "Program \"" + args.joinToString(" ") + "\" (in directory \"${wrkDir.path}\"): " + + if (!err) { + errorMessage.append(cmdInfo).append("TIMEOUT") + success = false + } else if (!fail.contains(Fail.NONE)) { + val all = fail.contains(Fail.ALL) + val output = fail.contains(Fail.OUTPUT) + if ((all || fail.contains(Fail.EXIT) || fail.contains(Fail.NORMAL)) && proc.exitValue() > 0) { + errorMessage.append(cmdInfo).append("EXIT ${proc.exitValue()}") + if (stderr.isNotEmpty()) errorMessage.append(", STDERR: ").append(stderr[0]) + success = false + } else if ((all || output || fail.contains(Fail.STDERR) || fail.contains(Fail.NORMAL)) + && stderr.isNotEmpty()) { + errorMessage.append(cmdInfo).append("STDERR, ").append(stderr[0]) + success = false + } else if ((all || output || fail.contains(Fail.STDOUT)) && stdout.isNotEmpty()) { + errorMessage.append(cmdInfo).append("STDOUT, ").append(stdout[0]) + success = false + } + } + } + } else { + errorMessage.append("Invalid working directory: \"${wrkDir.canonicalPath}\"") + success = false + } + + if (!success) break + } + + //@TODO until Cedric fixes it. + if (!success) error(errorMessage) + + return TaskResult(success) } private fun fromStream(ins: InputStream): List { @@ -142,27 +213,35 @@ class ExecPlugin : BasePlugin(), ITaskContributor { } } -enum class Fail() { - ALL, NORMAL, STDERR, STDOUT, OUTPUT, EXIT +enum class Fail { + ALL, EXIT, NONE, NORMAL, OUTPUT, STDERR, STDOUT } -data class CommandLine(var args: List = emptyList(), var dir: String = "", - var os: List = emptyList(), var fail: Set = emptySet()) - -data class ExecConfig(val project: Project) { - val commandLines = arrayListOf() - - @Directive fun commandLine(args: List = emptyList(), dir: String = "", os: List = emptyList(), - fail: Set = emptySet()) { - if (args.size > 0) commandLines.add(CommandLine(args, dir, os, fail)) - } +enum class Os { + CYGWIN, FREEBSD, LINUX, MAC, MINGW, MSYS, OPENVMS, OS400, SOLARIS, TANDEM, WINDOWS, ZOS } +data class CommandLine(var args: List = emptyList(), var dir: String = "", var os: Set = emptySet(), + var fail: Set = setOf(Fail.NORMAL)) + @Directive -fun Project.exec(init: ExecConfig.() -> Unit): ExecConfig { - with(ExecConfig(this)) { - init() - (Kobalt.findPlugin(ExecPlugin.NAME) as ExecPlugin).addExecConfig(name, this) - return this +class ExecConfig { + var taskName: String = "exec" + val commandLines = arrayListOf() + var dependsOn = listOf("assemble") + + @Suppress("unused") + fun commandLine(vararg args: String, dir: String = "", os: Set = emptySet(), + fail: Set = setOf(Fail.NORMAL)) { + if (args.isNotEmpty()) commandLines.add(CommandLine(listOf(*args), dir, os, fail)) + } +} + +@Suppress("unused") +@Directive +fun Project.exec(init: ExecConfig.() -> Unit) { + ExecConfig().let { config -> + config.init() + (Plugins.findPlugin(ExecPlugin.NAME) as ExecPlugin).addConfiguration(this, config) } } \ No newline at end of file diff --git a/src/test/kotlin/com/example/MainTest.kt b/src/test/kotlin/com/example/MainTest.kt deleted file mode 100644 index c2a547d..0000000 --- a/src/test/kotlin/com/example/MainTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * MainTest.kt - * - * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of this project nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.example - -import org.testng.annotations.Test - -class ExampleTest { - @Test - fun f() = println("Running test") -} \ No newline at end of file diff --git a/wrapper/kobalt-wrapper.jar b/wrapper/kobalt-wrapper.jar deleted file mode 100644 index 6ca6ca5..0000000 Binary files a/wrapper/kobalt-wrapper.jar and /dev/null differ diff --git a/wrapper/kobalt-wrapper.properties b/wrapper/kobalt-wrapper.properties deleted file mode 100644 index 40e4395..0000000 --- a/wrapper/kobalt-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -kobalt.version=0.843 \ No newline at end of file