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

Compare commits

..

289 commits

Author SHA1 Message Date
37a89d206b Centralized versions in main Gradle build file. 2019-03-30 11:17:29 -07:00
bf68749d3e
Merge pull request #501 from ethauvin/master
Grade build
2019-03-30 00:25:51 -07:00
12a0618a90 Ignore build directories. 2019-03-30 00:08:00 -07:00
4a477f5563 Made gradew executable. 2019-03-29 23:53:42 -07:00
a5c0bd921f Added Gradle project based on the POM. 2019-03-29 23:52:02 -07:00
Cedric Beust
200a81b9fc
Merge pull request #500 from pabl0rg/fix-unsafe-dependency-fetching
Fix unsafe dependency fetching
2019-03-29 09:29:53 -07:00
Juan Liska
a38a7187e8 add maven build dirs to classpath in “dev mode”
dev mode = when requested kobalt version jar not found
2019-03-29 10:21:22 -06:00
Juan Liska
ae6258acb8 use https to fetch artifacts 2019-03-29 10:21:22 -06:00
Juan Liska
4644b66d79 create maven build files for kobalt 2019-03-29 10:21:22 -06:00
Cedric Beust
f96e349608
Merge pull request #498 from pabl0rg/upgrade-guava-27.0.1
upgrade guava to 27.0.1 to resolve multimap ordering
2019-03-12 10:49:03 -07:00
Juan Liska
935a866f52 upgrade guava to 27.0.1 to resolve multimap ordering 2019-03-12 11:43:20 -06:00
Cedric Beust
5f7efabe20
Merge pull request #497 from pabl0rg/upgrade-guice-4.2.2
upgrade guice to 4.2.2
2019-03-12 10:40:22 -07:00
Juan Liska
a09594ea06 upgrade guice to 4.2.2 2019-03-12 11:34:21 -06:00
Cedric Beust
e06fc29190 1.0.122. 2018-11-23 14:19:17 -08:00
Cedric Beust
e6b72c282f
Merge pull request #494 from pabl0rg/improve-external-compiler-invocation
Improve external compiler invocation
2018-11-23 07:15:34 -08:00
Juan Liska
a0d33fcaae bump version to 1.0.121 2018-11-23 06:04:54 -06:00
Juan Liska
6934dec51a only add stdlib to classpath when project does not specify a kotlin version
when the project specifies a kotlin version, that version’s stdlib will be added to the classpath by other means
2018-11-23 06:04:48 -06:00
Juan Liska
c33800b189 don’t add deprecated kotlin runtime jar to project templates 2018-11-23 06:04:43 -06:00
Juan Liska
1ff46b5842 don’t add deprecated kotlin runtime jar to classpath 2018-11-23 06:04:38 -06:00
Juan Liska
0cc2c23a32 extend timeout to 2 mins, log error when process times out 2018-11-23 06:04:24 -06:00
Cedric Beust
0f0a780b43 1.0.120. 2018-11-10 08:13:27 -08:00
Cedric Beust
7827aeeb43 Fix project directory. 2018-11-10 08:13:02 -08:00
Cedric Beust
a6097dc136 Better test results. 2018-11-10 08:11:08 -08:00
Cedric Beust
e22b5b77e6 1.0.119. 2018-11-06 10:37:50 -08:00
Cedric Beust
2e73ece52c Fix bad test directory. 2018-11-06 10:37:42 -08:00
Cedric Beust
5c3642b7d7 1.0.118. 2018-10-30 13:37:02 -07:00
Cedric Beust
71540a4426 Fix test results being read in the wrong directory. 2018-10-30 13:36:51 -07:00
Cedric Beust
61534e1e81 1.0.117. 2018-10-15 14:46:41 -07:00
Cedric Beust
b7dd3afde7 Warning. 2018-10-15 14:46:09 -07:00
Cedric Beust
43bb71b486 Better JUnit 5 detection. 2018-10-15 14:46:04 -07:00
Cedric Beust
55bba514b3 Bump kotlinc version. 2018-10-12 13:46:10 -07:00
Cedric Beust
58aae0bfe3 1.0.116. 2018-10-10 13:38:09 -07:00
Cedric Beust
7b902eb673
Merge pull request #488 from pabl0rg/improve-kotlin-compiler-version-tests
Improve kotlin compiler version tests, upgrade to kotlin 1.2.70
2018-09-17 09:22:05 -07:00
Juan Liska
65aedfebdc bump version to 1.0.115 2018-09-17 05:09:43 -06:00
Juan Liska
7cf19b3f95 fix test assertion, enable kobalt logging for tests 2018-09-17 05:00:28 -06:00
Juan Liska
39801a5a24 upgrade default compiler to 1.2.70 2018-09-17 04:55:10 -06:00
Juan Liska
42bd2ecdf1 extend timeout, add logging 2018-09-16 10:01:59 -06:00
Juan Liska
3475377185 add Args parameter to newReposityrSystemSession call 2018-09-16 09:57:37 -06:00
Juan Liska
e1adc87281 add a test for kotlinCompiler version setting 2018-09-16 09:48:37 -06:00
Cedric Beust
cdd30873d0 1.0.114. 2018-03-21 15:17:41 -07:00
Cedric Beust
b368aedef2 MetaArchive fix. 2018-03-21 15:17:20 -07:00
Cedric Beust
8d938bac2e 1.0.113. 2018-03-21 10:15:44 -07:00
Cedric Beust
50b31114f6 Remove warning when failing to parse the version number.
Fixes https://github.com/cbeust/kobalt/issues/475
2018-03-21 10:15:44 -07:00
Cedric Beust
c6b180dd71
Merge pull request #478 from avently/master
Added "offline" argument to prevent remote resolving of dependencies
2018-03-21 10:15:29 -07:00
Avently
f1a025036f Added "offline" argument to prevent remote resolving of dependencies 2018-03-21 18:25:44 +03:00
Cedric Beust
2241323498 Bump JUnit 5 versions. 2018-03-17 12:52:54 -07:00
Cedric Beust
6c031cd3c1 1.0.112. 2018-02-23 00:59:25 -08:00
Cedric Beust
a6f36de6a6 Create directories before actual entries in the jar file. 2018-02-23 00:59:13 -08:00
Cedric Beust
df89933cc8 1.0.111. 2018-02-21 16:50:30 -08:00
Cedric Beust
f95075c1ae Update KobaltClient to the correct WebSocket library. 2018-02-21 16:47:32 -08:00
Cedric Beust
49bc2b3a15 1.0.110. 2018-02-13 16:07:44 -08:00
Cedric Beust
03e94157c7 Revert. 2018-02-13 16:07:40 -08:00
Cedric Beust
700a8fbca8 1.0.108. 2018-02-13 13:58:25 -08:00
Cedric Beust
7df320b4c7 Reverting to Kotlin 1.2.10.
Until https://youtrack.jetbrains.com/issue/KT-22542 is fixed.

Fixes https://github.com/cbeust/kobalt/issues/472
2018-02-13 13:58:13 -08:00
Cedric Beust
82fa2081fc Unused. 2018-02-13 13:57:05 -08:00
Cedric Beust
ae82395fdf Bump bndlib. 2018-02-13 12:53:57 -08:00
Cedric Beust
4af7e2d36a 1.0.107. 2018-02-13 12:53:50 -08:00
Cedric Beust
645901d988 Fix build directory for the application plug-in.
Fixes https://github.com/cbeust/kobalt/issues/473
2018-02-13 12:53:32 -08:00
Cedric Beust
3d23f38239 1.0.105. 2018-02-05 09:17:24 -08:00
Cedric Beust
c2174fe1e7 Warnings. 2018-02-05 09:16:47 -08:00
Cedric Beust
11a1f427a0 1.0.106. 2018-02-04 04:42:56 -08:00
Cedric Beust
4281a1cad8 Fix empty new line in manifest. 2018-02-04 04:39:02 -08:00
Cedric Beust
d7a95d0c0c Warnings 2018-02-03 11:40:07 -08:00
Cedric Beust
7d27cd144d Exclude MANIFESTS from other jar files. 2018-02-03 11:17:44 -08:00
Cedric Beust
c1364c82a0 1.4.0. 2018-02-03 10:33:33 -08:00
Cedric Beust
52f5ceb3d6 Add MANIFEST.MF at the top of the jar file 2018-02-03 10:28:45 -08:00
Cedric Beust
7a2c4f34da Merge branch 'master' of github.com:cbeust/kobalt 2018-01-26 23:59:54 -08:00
Cedric Beust
32bf92e8c8
Merge pull request #470 from ethauvin/master
No longer create directories, etc. when --help or --version are used.
2018-01-26 23:59:16 -08:00
Cedric Beust
d2d0c7603d 1.0.103. 2018-01-26 23:23:34 -08:00
Cedric Beust
7d3549ec27 Kotlin 1.2.21. 2018-01-26 23:23:24 -08:00
Cedric Beust
026b0e209f Reverting back to Kotlin 1.2.10. 2018-01-26 23:15:16 -08:00
Cedric Beust
cce09756af 1.0.101. 2018-01-26 16:43:18 -08:00
Cedric Beust
323bfae756 Fix the Osgi plug-in. 2018-01-26 16:41:15 -08:00
22d983d559 Added --version argument to app. 2018-01-20 17:04:56 -08:00
41ba68c630 No longer create directories, etc. when --help or --version are used. 2018-01-20 16:15:31 -08:00
Cedric Beust
18c6f38948 Kotlin 1.2.20. 2018-01-17 13:52:26 -08:00
Cedric Beust
964fa3bc0f 1.0.100. 2018-01-08 15:17:13 -08:00
Cedric Beust
576cd56f88 No longer used. 2018-01-08 15:16:57 -08:00
Cedric Beust
2806f5e11b Revert to 1.0.94 while investigating issues with Kotlin 1.2.10. 2018-01-04 15:01:20 -08:00
Cedric Beust
cfbf0143f4 1.0.100. 2018-01-04 14:29:37 -08:00
Cedric Beust
126e7fb500 Bump Kotlin to 1.2.10. 2018-01-04 14:19:41 -08:00
Cedric Beust
0d0dcbbc54 1.0.94. 2018-01-02 16:43:38 -08:00
Cedric Beust
96d11d3dbf 1.0.93. 2017-12-09 09:07:05 -08:00
Cedric Beust
ae59e1d7ff Merge branch 'master' of github.com:cbeust/kobalt 2017-12-09 09:00:09 -08:00
Cedric Beust
84ee57a979 Sign artifacts. 2017-12-09 08:59:51 -08:00
Cedric Beust
fdee66ab93 For 'run', don't use the error stream as an error indicator. 2017-12-09 08:59:23 -08:00
Cedric Beust
6d7490a34d 1.0.92. 2017-11-20 13:42:48 -08:00
Cedric Beust
3d2e5b069d BuildConfig not being generated. (#464). 2017-11-20 13:41:36 -08:00
Cedric Beust
294799ee5d 1.0.91. 2017-11-08 10:50:34 -08:00
Cedric Beust
6ede80e9ce
Merge pull request #463 from ethauvin/master
Added ignore parameters to the application plugin.
2017-11-08 09:16:10 -08:00
20a01f8de0 Added ignoreInputStream, ignoreErrorStream and ignoreExitvalue to the application plugin. 2017-11-08 01:05:16 -08:00
Cedric Beust
72740079ce
Merge pull request #461 from ethauvin/master
Fixed finding tools.jar under Windows when JAVA_HOME is set to JRE.
2017-11-07 09:47:18 -08:00
Cedric Beust
e39be51cb8
Merge pull request #462 from McPringle/master
Code Review Changes
2017-11-06 11:38:57 -08:00
Marcus Fihlon
f4f3827fd1
💬 Adding trimming of line in format string
Before:
    ***** WARNING Old profile syntax detected for "                val debug = false", please update to "val debug by profile()"

    After:
    ***** WARNING Old profile syntax detected for "val debug = false", please update to "val debug by profile()
2017-11-06 19:54:54 +01:00
Marcus Fihlon
70f01fa691
Merge branch 'master' of github.com:cbeust/kobalt 2017-11-06 19:51:32 +01:00
Marcus Fihlon
2e2444c2bc
👌 Code review change
Thanks to @ethauvin for his very good hint!
2017-11-06 19:49:28 +01:00
be40f5c81d Fixed finding tools.jar under Windows when JAVA_HOME is set to JRE. 2017-11-05 17:11:11 -08:00
Cedric Beust
05f8e2f41a
Merge pull request #458 from McPringle/master
Fixing the WAR filename could contain a `null` version #456
2017-11-05 07:02:08 -08:00
Marcus Fihlon
5aef25a4a7
🐛 Fixing the WAR filename contains if version information is missing #456 2017-11-05 03:08:12 -06:00
Cedric Beust
e7ae50fe81
Merge pull request #454 from ethauvin/master
Java 9 initial compatibility
2017-11-04 13:36:08 -07:00
702a34dd4b Made executable in git index. 2017-11-04 12:14:30 -07:00
bd8ba4c497 Added kobatw-test wrapper to build the kobalt project using the jar in kobaltBuild/libs for testing. 2017-11-03 19:03:21 -07:00
a115111168 Added missing jaxb dependency for plugin API. 2017-11-03 19:01:38 -07:00
a431f4850b Syntax fix. 2017-11-03 13:15:15 -07:00
a1aa6d8eea Resolving merge conflict. 2017-11-02 17:47:40 -07:00
49db5a798e Fixed coroutinesSate syntax. 2017-11-02 17:40:14 -07:00
82b89edaee
Merge pull request #455 from pabl0rg/upgrade-to-kotlinc-1-1-51
upgrade to kotlinc 1.1.51
2017-11-02 17:26:42 -07:00
Juan Liska
f6de041fd8 bump kotlin compiler version string const 2017-11-02 17:35:49 -06:00
Juan Liska
629949edd4 upgrade to kotlinc 1.1.51 2017-11-02 17:26:29 -06:00
e8dcfc6d4b More syntax fix. 2017-11-01 10:13:39 -07:00
05d0ff04fb Fixed various syntax. 2017-10-31 23:17:42 -07:00
c99a9eb6cd First try at running under Java 9. 2017-10-31 21:44:57 -07:00
Cedric Beust
86e39cbb58 1.0.90. 2017-09-16 18:25:57 -07:00
Cedric Beust
f92ac752c1 1.0.89/ 2017-07-25 10:40:08 -07:00
Cedric Beust
084f4b5385 Silly oversight, 2017-07-25 10:39:53 -07:00
Cedric Beust
b109674f1a Merge branch 'master' of github.com:cbeust/kobalt 2017-07-25 10:31:29 -07:00
Cedric Beust
f782fa2236 1.0.88. 2017-07-25 10:23:52 -07:00
Cedric Beust
4405cf154c OsgiPlugin bug. 2017-07-25 10:23:17 -07:00
Cedric Beust
aac60fa0a3 Merge pull request #452 from MrTact/kotlin-template-deps
Fixes #451 -- add stdlib and runtime deps to the Kotlin project template
2017-07-19 20:21:01 -07:00
Tim Keating
be29f2c0b3 PR feedback: use version constant instead of hard-coded strings 2017-07-19 22:05:45 -05:00
Tim Keating
9e6b3d26db Fixes #451 -- add stdlib and runtime deps to the Kotlin project template 2017-07-18 00:26:01 -05:00
Cedric Beust
76bd010168 1.0.87. 2017-05-31 09:07:52 -07:00
Cedric Beust
c1c2057de4 Merge pull request #445 from albinekcom/patch-1
Update README
2017-05-21 06:32:07 -07:00
Albin "albinek" Sadowski
11cd3226e9 Update README 2017-05-21 09:51:03 +02:00
Cedric Beust
4efe8125d7 Merge pull request #444 from ethauvin/master
Added push parameter to autoGitTag
2017-05-10 12:44:17 -07:00
b944039fdc Added push parameter to autoGitTag. 2017-05-10 11:46:41 -07:00
Cedric Beust
a38b05fc92 Merge pull request #443 from ethauvin/master
Fixed repo name to use config param if available
2017-05-10 11:10:57 -07:00
bcb9cc4e87 Fixed repo name to use config param if available. 2017-05-10 11:08:15 -07:00
Cedric Beust
a1b952ca69 1.0.86. 2017-05-10 09:58:54 -07:00
Cedric Beust
a47b570d16 Fix the bogus default value for getProperty(). 2017-05-10 09:58:54 -07:00
Cedric Beust
75fbfb9613 Refactoring. 2017-05-09 13:12:22 -07:00
Cedric Beust
61af72e26d 1.0.85. 2017-05-09 10:56:06 -07:00
Cedric Beust
1d7f04bf47 Build fix. 2017-05-09 10:56:00 -07:00
Cedric Beust
d1039ce9af 1.0.84. 2017-05-08 15:47:59 -07:00
Cedric Beust
a95f8d91c1 Merge pull request #442 from ethauvin/master
Added support for configuring gpg's via local.properties
2017-05-08 15:47:50 -07:00
3b56122f92 Added support for configuring gpg's passphrase, key id and secret key ring location via local.properties. 2017-05-05 15:46:13 -07:00
Cedric Beust
91bb1b955c Warnings. 2017-05-05 12:47:29 -07:00
Cedric Beust
2227783905 Merge pull request #441 from ethauvin/master
Fixed vcs_tag
2017-05-05 11:20:00 -07:00
f43c186da1 Cleanup. 2017-05-05 10:33:21 -07:00
706f27de40 Added Bintray's package name and issue tracker URL. 2017-05-05 08:45:21 -07:00
62e1d55b53 Fixed vcs_tag.
Grab project description and url from pom, if not already specified.
2017-05-04 16:22:22 -07:00
Cedric Beust
686d98cdc9 Rename. 2017-05-04 09:39:52 -07:00
Cedric Beust
b74c4d65b2 Fix warnings. 2017-05-04 09:36:38 -07:00
Cedric Beust
4ff98d6d37 Merge pull request #440 from ethauvin/master
Removed sources directory from apt generated directory path
2017-05-04 09:32:17 -07:00
e468d1cb4d Removed sources directory from apt generated directory path. 2017-05-04 00:12:16 -07:00
Cedric Beust
2439da3545 Merge pull request #439 from ethauvin/master
Made doc run after clean
2017-05-03 20:43:31 -07:00
c69a41db66 Made doc run after clean. 2017-05-03 20:13:58 -07:00
407d2bb436 Cleanup. 2017-05-03 20:13:13 -07:00
Cedric Beust
74d6670882 1.0.83. 2017-05-03 11:32:55 -07:00
Cedric Beust
d095840121 Fix fixSlashes().
Fixes https://github.com/cbeust/kobalt/pull/438
2017-05-03 11:32:41 -07:00
Cedric Beust
8ea67e70cd Merge pull request #438 from ethauvin/master
Implemented javadoc options
2017-05-03 11:00:44 -07:00
e4650dd953 Implemented javadoc options. 2017-05-03 09:46:02 -07:00
Cedric Beust
2e7de257aa Better javadoc default args. 2017-05-02 14:17:39 -07:00
Cedric Beust
8fa360949b Simplify. 2017-05-02 14:07:44 -07:00
Cedric Beust
083d707345 1.0.82. 2017-05-02 11:24:38 -07:00
Cedric Beust
13f544d67c Add javadoc { args() }. 2017-05-02 11:24:21 -07:00
Cedric Beust
c0ed9a5a03 Not used. 2017-05-02 11:19:38 -07:00
Cedric Beust
dcfa18ceb8 1.0.81 2017-05-01 11:11:20 -07:00
Cedric Beust
bc4bee8461 OSGi improvements. 2017-05-01 11:11:11 -07:00
Cedric Beust
4385a81308 1.0.80. 2017-04-28 10:18:11 -07:00
Cedric Beust
60a7c88377 Restructure. 2017-04-28 10:18:11 -07:00
Cedric Beust
f674ed65d6 Don’t include stubs in the jar file.
Fixes https://github.com/cbeust/kobalt/issues/437
2017-04-28 10:18:11 -07:00
Cedric Beust
fff392d573 Log. 2017-04-28 10:18:11 -07:00
Cedric Beust
14aab6bee1 Merge pull request #436 from ethauvin/master
Fixed config.taskName
2017-04-27 19:28:40 -07:00
d0d5e75243 Fixed config.taskName. 2017-04-27 19:13:20 -07:00
Cedric Beust
5629806df2 Refactor. 2017-04-27 16:29:05 -07:00
Cedric Beust
7ea182b42e 1.0.79. 2017-04-27 16:22:33 -07:00
Cedric Beust
bfe4140143 Fix the run dependency. 2017-04-27 16:21:44 -07:00
Cedric Beust
0e6bc67c4b Fix manifest path. 2017-04-27 16:21:35 -07:00
Cedric Beust
67da9b8dc6 Better toString(). 2017-04-27 16:21:25 -07:00
Cedric Beust
96eabbe99b 1.0.78. 2017-04-27 13:32:32 -07:00
Cedric Beust
6cab82e280 Refactor. 2017-04-27 13:32:21 -07:00
Cedric Beust
9b08f57917 Fix the case where no MANIFEST exists. 2017-04-27 13:31:19 -07:00
Cedric Beust
742fff6105 Not used. 2017-04-27 11:34:24 -07:00
Cedric Beust
5829ae49bb Fix the duplicate MANIFEST.MF bug. 2017-04-27 11:34:19 -07:00
Cedric Beust
18653c4da1 Better log message. 2017-04-27 10:57:51 -07:00
Cedric Beust
b937aa6ad8 Created the generated source directory.
Fixes https://github.com/cbeust/kobalt/issues/433
2017-04-27 10:57:44 -07:00
Cedric Beust
3ebc40d58f Update Guava. 2017-04-26 14:20:22 -07:00
Cedric Beust
161e5db53c OsgiPlugin. 2017-04-26 14:19:55 -07:00
Cedric Beust
a367621ee4 1.0.77. 2017-04-25 10:59:51 -07:00
Cedric Beust
c3c3b0863a Kotlin 1.1.2. 2017-04-25 10:59:40 -07:00
Cedric Beust
5e12e028bd Be consistent with using taskContributor everywhere. 2017-04-25 10:40:16 -07:00
Cedric Beust
ba6ab5592e Allow multiple install{} tags.
Fixes https://github.com/cbeust/kobalt/issues/430.
2017-04-25 10:24:10 -07:00
Cedric Beust
5b1c9150a5 Better error message. 2017-04-24 16:04:20 -07:00
Cedric Beust
4a5a6442ec 1.0.76. 2017-04-24 15:03:11 -07:00
Cedric Beust
93f5c541f4 Support for multiple application{} directives.
Fixes https://github.com/cbeust/kobalt/issues/430.
2017-04-24 14:58:54 -07:00
Cedric Beust
65f423ffea 1.0.75. 2017-04-24 11:39:43 -07:00
Cedric Beust
523b9c055a Not used. 2017-04-24 11:37:52 -07:00
Cedric Beust
ae6d1d51e1 Refactor. 2017-04-24 11:35:09 -07:00
Cedric Beust
cccff9e7b0 Refactor. 2017-04-24 11:34:54 -07:00
Cedric Beust
bb2e09f680 Kill the Kobalt server after 10 minutes of inactivity. 2017-04-24 09:56:53 -07:00
Cedric Beust
fd80166186 Warn if tools.jar can’t be found. 2017-04-24 09:53:37 -07:00
Cedric Beust
7e86b5ae86 Delete server file on exit. 2017-04-24 09:49:12 -07:00
Cedric Beust
ec7d24a6f8 Make sure JAVA_HOME points to the JDK and not the JRE.
Should fix https://github.com/cbeust/kobalt/issues/428.
2017-04-24 09:48:23 -07:00
Cedric Beust
0f658cf010 1.0.74. 2017-04-22 21:34:15 -07:00
Cedric Beust
0f80fe6d68 Merge branch 'master' of github.com:cbeust/kobalt 2017-04-22 21:28:44 -07:00
Cedric Beust
9ec708ebf3 Bug with kapt when no Java files are present. 2017-04-22 21:28:31 -07:00
Cedric Beust
2a545b6638 Merge branch 'master' of github.com:cbeust/kobalt 2017-04-22 13:25:20 -07:00
Cedric Beust
6a08d3caa8 Fix slashes in the zip file. 2017-04-22 13:23:24 -07:00
Cedric Beust
cc481a4a7f GH-423: Overwrite files on Windows too.
Fixes https://github.com/cbeust/kobalt/issues/423
2017-04-21 23:02:59 -07:00
Cedric Beust
c768507ed5 Reformat. 2017-04-21 22:18:56 -07:00
Cedric Beust
2abeef347e Merge pull request #425 from ethauvin/newest
Made warn() work like error() with provided message
2017-04-21 22:16:17 -07:00
Cedric Beust
35769f099f Merge branch 'master' of github.com:cbeust/kobalt 2017-04-21 21:28:58 -07:00
Cedric Beust
3a41868824 1.0.73. 2017-04-21 21:25:52 -07:00
Cedric Beust
a10777ee1d Fix the duplicate compiler args bug. 2017-04-21 21:25:35 -07:00
d157be9a18 Made warn() work like error() with provided message. 2017-04-21 20:04:27 -07:00
Cedric Beust
49e69d0964 Merge branch 'master' of github.com:cbeust/kobalt 2017-04-21 12:17:34 -07:00
Cedric Beust
1342428eb0 Reformat. 2017-04-20 11:17:28 -07:00
Cedric Beust
e1c1da55c6 Fix duplication of parameters. 2017-04-20 11:17:23 -07:00
Cedric Beust
1d015a6f93 1.0.72. 2017-04-19 11:16:28 -07:00
Cedric Beust
43844cbf80 Fix class path look up in kapt3. 2017-04-19 11:16:05 -07:00
Cedric Beust
5bcb8185b8 Refactor. 2017-04-19 11:14:34 -07:00
Cedric Beust
abc9002292 1.0.71. 2017-04-19 08:29:01 -07:00
Cedric Beust
35fe4f6494 Add tools.jar on the annotation plug-in classpath. 2017-04-19 08:20:02 -07:00
Cedric Beust
1febd47368 Better JAVA_HOME detection. 2017-04-19 08:19:46 -07:00
Cedric Beust
3686c4e110 1.0.70. 2017-04-18 20:02:08 -07:00
Cedric Beust
5d03544e31 GH-417: Don’t run abstract test classes with JUnit 4.
Fixes https://github.com/cbeust/kobalt/issues/417
2017-04-18 20:01:43 -07:00
Cedric Beust
104e71335e Read the apt() dependency correctly. 2017-04-18 08:36:17 -07:00
Cedric Beust
37709b571c Inject the Jvm object. 2017-04-18 08:16:13 -07:00
Cedric Beust
dc1ebfb15d Don’t display tasks if the build file can’t be compiled. 2017-04-17 18:54:37 -07:00
Cedric Beust
fd58ed58e4 1.0.69. 2017-04-17 17:47:24 -07:00
Cedric Beust
da332b1716 Don’t use variants for apt. 2017-04-17 17:46:56 -07:00
Cedric Beust
007e616e7f 1.0.68. 2017-04-17 16:43:06 -07:00
Cedric Beust
b331672c3d Fix nowarn. 2017-04-17 16:30:25 -07:00
Cedric Beust
9e1c9bd87b Add support for kapt3. 2017-04-17 16:27:12 -07:00
Cedric Beust
afacd86267 GH-409: Run —update or —server even if the build file is incorrect.
Fixes https://github.com/cbeust/kobalt/issues/409
2017-04-17 09:27:17 -07:00
Cedric Beust
e11bdfa2b9 1.0.67. 2017-04-17 08:40:15 -07:00
Cedric Beust
0938bcc3bf GH-413: Duplicate compilation.
Fixes https://github.com/cbeust/kobalt/pull/413
2017-04-17 08:38:53 -07:00
Cedric Beust
dcdbbdc6c3 Merge pull request #413 from dmitry-zhuravlev/master
+ server should send buildFileClasspath to plugin. close #410
2017-04-17 08:26:04 -07:00
Dmitry Zhuravlev
5720356814 + added cleanup for buildFileClasspath collection
+ added FIXME: newBuildFileClasspath called twice
2017-04-17 12:30:12 +03:00
Dmitry Zhuravlev
6d46ba2d0e Merge branch 'master' of https://github.com/cbeust/kobalt 2017-04-17 11:49:15 +03:00
Cedric Beust
e9b8212dbd Fix build. 2017-04-16 20:30:44 -07:00
Cedric Beust
6816ba8a3b Sanitize repo names from repos(). 2017-04-16 20:13:28 -07:00
Cedric Beust
a7006d5cd7 kapt3 work. 2017-04-16 19:21:50 -07:00
Cedric Beust
cbb02e7615 1.0.66. 2017-04-16 19:08:22 -07:00
Cedric Beust
4f9c5f383e 1.0.65. 2017-04-16 18:53:01 -07:00
Cedric Beust
822a9701a6 Fix broken TestNG dependency. 2017-04-16 18:24:26 -07:00
Cedric Beust
30e71afbc8 1.0.64. 2017-04-15 08:09:09 -07:00
Cedric Beust
85460422e0 GH-414: Authenticated repos not working.
Fixes https://github.com/cbeust/kobalt/issues/414
2017-04-15 08:09:09 -07:00
Cedric Beust
1fb984ff63 1.0.63. 2017-04-15 08:09:09 -07:00
Cedric Beust
9f93f0ca6e Merge pull request #415 from ethauvin/newest
Fix for OSX and calling outsite of residing directory
2017-04-14 23:44:44 -07:00
876420b434 Fix for OSX and calling outsite of residing directory. 2017-04-14 22:45:37 -07:00
Cedric Beust
49bdec673e Merge branch 'master' of github.com:cbeust/kobalt 2017-04-14 15:40:21 -07:00
Cedric Beust
e45e93cee8 1.0.62. 2017-04-14 12:24:27 -07:00
Cedric Beust
c4813880ac Comment. 2017-04-14 12:15:55 -07:00
Cedric Beust
f4a5d188e7 Use AssertionErrors in tests. 2017-04-14 12:15:50 -07:00
Cedric Beust
19dc26ac16 Make sure the zip entries start with kobalt-${version}. 2017-04-14 12:15:01 -07:00
Cedric Beust
2b3fc7a2c9 Fix the zip task. 2017-04-14 12:14:43 -07:00
Cedric Beust
91260d2f57 Not used. 2017-04-14 11:22:59 -07:00
Dmitry Zhuravlev
7a63f88ba5 Merge branch 'master' of https://github.com/cbeust/kobalt 2017-04-14 17:19:59 +03:00
Dmitry Zhuravlev
5d11395b7c + server should send buildFileClasspath to plugin. close #410 2017-04-14 17:18:16 +03:00
Cedric Beust
581b3de13e Refactor. 2017-04-14 07:07:47 -07:00
Cedric Beust
8bd098c458 Fix Windows tests. 2017-04-14 07:07:17 -07:00
Cedric Beust
5ddc370521 1.0.61. 2017-04-13 09:55:34 -07:00
Cedric Beust
fad6af29ee Merge branch 'master' of github.com:cbeust/kobalt 2017-04-12 17:00:07 -07:00
Cedric Beust
0e381912f7 Merge pull request #411 from dmitry-zhuravlev/master
* package all Kobalt sources in zip distribution. relates to #237
2017-04-12 16:59:22 -07:00
Cedric Beust
90df943ec3 Merge branch 'master' of github.com:cbeust/kobalt 2017-04-12 16:50:46 -07:00
Dmitry Zhuravlev
a9db9bb28a * package all Kobalt sources in zip distribution. relates to #237 2017-04-12 15:50:53 +03:00
Cedric Beust
68163731d6 Refactor. 2017-04-11 19:14:43 -07:00
Cedric Beust
3615d802b7 Merge pull request #408 from ethauvin/master
Ensured inputStream.copyTo() is automatically closed.
2017-04-11 18:46:21 -07:00
a48d091fa5 Ensured inputStream.copyTo() is automatically closed. 2017-04-11 17:10:20 -07:00
Cedric Beust
623d106e3c Forgot build file. 2017-04-11 16:28:53 -07:00
Cedric Beust
c195a7bdf7 Use commons-compress fast archive. 2017-04-11 15:58:52 -07:00
Cedric Beust
46f73ee5e7 Fix test. 2017-04-11 12:18:35 -07:00
Cedric Beust
52fe283583 Not used. 2017-04-11 11:44:29 -07:00
Cedric Beust
af5217966f Better range resolution. 2017-04-11 11:44:09 -07:00
Cedric Beust
77b7e3f5be Improve template. 2017-04-11 11:15:22 -07:00
Cedric Beust
49d058e3e1 GH-403: Honor Kotlin compiler flags in process.
Fixes https://github.com/cbeust/kobalt/issues/403
2017-04-11 10:50:24 -07:00
Cedric Beust
2e6f14007a 1.0.56. 2017-04-11 10:50:24 -07:00
Cedric Beust
367b4a9e3d Merge pull request #405 from ethauvin/master
Made sure kobaltw (dist) is executable on non-Windows platforms.
2017-04-11 05:54:25 -07:00
0f88993424 Made sure kobaltw in ~/.kobalt/wrapper/dist/ is executable on non-Windows platforms. 2017-04-10 23:23:18 -07:00
Cedric Beust
2966575073 Merge pull request #404 from ethauvin/master
Added test to check if kobaltw is executable (*nix only.)
2017-04-10 22:32:35 -07:00
54a38c22db Used OperatingSystem.current() instead of getting system property. 2017-04-10 22:31:31 -07:00
c737fc9a00 Added test to check if kobaltw is executable (*nix only.) 2017-04-10 21:10:34 -07:00
Cedric Beust
d710362af1 Merge pull request #397 from ethauvin/master
Implementation of compileOnly
2017-04-10 13:44:27 -07:00
Cedric Beust
452820e728 Log. 2017-04-09 10:32:42 -07:00
Cedric Beust
b84586261c 1.0.59. 2017-04-09 09:52:22 -07:00
Cedric Beust
a20b16da44 Extract TestNG results and show them in the final report. 2017-04-09 09:37:36 -07:00
Cedric Beust
ffd641310d Format correctly. 2017-04-09 00:40:17 -07:00
Cedric Beust
6401a9d2af Bubble up test result messages. 2017-04-08 19:27:19 -07:00
Cedric Beust
197d576440 Merge branch 'master' of github.com:cbeust/kobalt 2017-04-08 11:12:06 -07:00
Cedric Beust
f276eb3001 Merge pull request #400 from rhencke/reduceJarAssemblyTime
Reduce time spent in JAR/ZIP assembly.
2017-04-08 11:12:01 -07:00
Cedric Beust
c9e61e49a9 Any nonexistent version will cause Kobalt to use local build directories.
Relaxes the restriction for that version to be +1.
2017-04-08 11:08:17 -07:00
Robert Hencke
713faa7a3f Reduce time spent in JAR/ZIP assembly.
Locally, this reduces a run of kobaltw assemble --noIncremental
on the Kobalt codebase itself from 47 seconds to 25 seconds.

When JarInputStream.nextEntry is invoked, the stream sets its position
and length so that it can directly be used to read the underlying content
associated with the entry.  This avoids the need to call
JarFile(localFile).getInputStream(entry) and the cost associated with it.

addEntry has a slight change of semantics due to this change - it is now
the caller's responsibility to close the associated input stream.  The two
existing calls to the method were adjusted accordingly.
2017-04-08 13:11:41 -04:00
Cedric Beust
f7cb803edc Typo. 2017-04-08 09:29:27 -07:00
Cedric Beust
ebf272bf98 Upload kobalt-wrapper to bintray too. 2017-04-08 07:53:45 -07:00
Cedric Beust
821752bdb9 1.0.58. 2017-04-07 19:39:36 -07:00
Cedric Beust
5fac88b1f7 GH-391: "provided" dependencies are no longer used to compile.
Fixes https://github.com/cbeust/kobalt/issues/391
2017-04-07 19:39:21 -07:00
5f8021334a Beginning implementation of compileOnly. 2017-04-07 19:37:48 -07:00
106 changed files with 3426 additions and 681 deletions

2
.gitignore vendored
View file

@ -11,3 +11,5 @@ libs
out out
.DS_Store .DS_Store
lib/kotlin-* lib/kotlin-*
build
.history

View file

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

58
build.gradle Normal file
View file

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

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View file

@ -0,0 +1,5 @@
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 Executable file
View file

@ -0,0 +1,188 @@
#!/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 Normal file
View file

@ -0,0 +1,100 @@
@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

@ -17,31 +17,33 @@ import java.io.File
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
val bs = buildScript { val bs = buildScript {
repos("http://dl.bintray.com/cbeust/maven") repos("https://dl.bintray.com/cbeust/maven")
} }
object Versions { object Versions {
val okhttp = "3.2.0" val kotlin = "1.2.71"
val okio = "1.6.0" val okhttp = "3.9.1"
val retrofit = "2.1.0" val okio = "1.13.0"
val gson = "2.6.2" val retrofit = "2.3.0"
val maven = "3.3.9" val gson = "2.8.2"
val mavenResolver = "1.0.3" val guice = "4.2.2"
val maven = "3.5.2"
val mavenResolver = "1.1.0"
val slf4j = "1.7.3" val slf4j = "1.7.3"
val kotlin = "1.1.1"
val aether = "1.0.2.v20150114" val aether = "1.0.2.v20150114"
val testng = "6.11" val testng = "6.12"
val jcommander = "1.72"
// JUnit 5 // JUnit 5
val junit = "4.12" val junit = "4.12"
val junitPlatform = "1.0.0-M4" val junitPlatform = "1.1.0"
val junitJupiter = "5.0.0-M4" val junitJupiter = "5.1.0"
val junitVintageVersion = "$junit.0-M4"
} }
fun mavenResolver(vararg m: String) fun mavenResolver(vararg m: String)
= m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" } = m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" }
.toTypedArray() .toTypedArray()
@ -62,6 +64,7 @@ val wrapper = project {
} }
assemble { assemble {
jar { }
jar { jar {
name = projectName + ".jar" name = projectName + ".jar"
manifest { manifest {
@ -73,6 +76,13 @@ val wrapper = project {
application { application {
mainClass = "com.beust.kobalt.wrapper.Main" mainClass = "com.beust.kobalt.wrapper.Main"
} }
bintray {
publish = true
sign = true
}
pom = createPom(name, "Wrapper for Kobalt")
} }
val kobaltPluginApi = project { val kobaltPluginApi = project {
@ -82,56 +92,42 @@ val kobaltPluginApi = project {
version = readVersion() version = readVersion()
directory = "modules/kobalt-plugin-api" directory = "modules/kobalt-plugin-api"
description = "A build system in Kotlin" description = "A build system in Kotlin"
url = "http://beust.com/kobalt" url = "https://beust.com/kobalt"
pom = Model().apply { pom = createPom(name, "A build system in Kotlin")
name = project.name
description = "A build system in Kotlin"
url = "http://beust.com/kobalt"
licenses = listOf(License().apply {
name = "Apache 2.0"
url = "http://www.apache .org/licenses/LICENSE-2.0"
})
scm = Scm().apply {
url = "http://github.com/cbeust/kobalt"
connection = "https://github.com/cbeust/kobalt.git"
developerConnection = "git@github.com:cbeust/kobalt.git"
}
developers = listOf(Developer().apply {
name = "Cedric Beust"
email = "cedric@beust.com"
})
}
dependencies { dependencies {
compile( compile(
"org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}", "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}",
"com.google.inject:guice:4.0", "com.google.inject:guice:${Versions.guice}",
"com.google.inject.extensions:guice-assistedinject:4.0", "com.google.inject.extensions:guice-assistedinject:4.1.0",
"javax.inject:javax.inject:1", "javax.inject:javax.inject:1",
"com.google.guava:guava:19.0", "com.google.guava:guava:27.0.1-jre",
"org.apache.maven:maven-model:${Versions.maven}", "org.apache.maven:maven-model:${Versions.maven}",
"io.reactivex:rxjava:1.1.5", "io.reactivex:rxjava:1.3.3",
"com.squareup.okio:okio:${Versions.okio}", "com.squareup.okio:okio:${Versions.okio}",
"com.google.code.gson:gson:${Versions.gson}", "com.google.code.gson:gson:${Versions.gson}",
"com.squareup.okhttp3:okhttp:${Versions.okhttp}", "com.squareup.okhttp3:okhttp:${Versions.okhttp}",
"com.squareup.retrofit2:retrofit:${Versions.retrofit}", "com.squareup.retrofit2:retrofit:${Versions.retrofit}",
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}", "com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
"com.beust:jcommander:1.48", "com.beust:jcommander:${Versions.jcommander}",
"org.eclipse.jgit:org.eclipse.jgit:4.5.0.201609210915-r", "org.eclipse.jgit:org.eclipse.jgit:4.9.0.201710071750-r",
"org.slf4j:slf4j-simple:${Versions.slf4j}", "org.slf4j:slf4j-simple:${Versions.slf4j}",
*mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"), *mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"),
"org.apache.maven:maven-aether-provider:3.3.9", "org.apache.maven:maven-aether-provider:3.3.9",
"org.testng.testng-remote:testng-remote:1.3.0", "org.testng.testng-remote:testng-remote:1.3.2",
"org.testng:testng:${Versions.testng}", "org.testng:testng:${Versions.testng}",
"commons-io:commons-io:2.5",
"org.junit.platform:junit-platform-surefire-provider:${Versions.junitPlatform}", "org.junit.platform:junit-platform-surefire-provider:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-runner:${Versions.junitPlatform}", "org.junit.platform:junit-platform-runner:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-engine:${Versions.junitPlatform}", "org.junit.platform:junit-platform-engine:${Versions.junitPlatform}",
"org.junit.platform:junit-platform-console:${Versions.junitPlatform}", "org.junit.platform:junit-platform-console:${Versions.junitPlatform}",
"org.junit.jupiter:junit-jupiter-engine:${Versions.junitJupiter}", "org.junit.jupiter:junit-jupiter-engine:${Versions.junitJupiter}",
"org.junit.vintage:junit-vintage-engine:${Versions.junitVintageVersion}" "org.junit.vintage:junit-vintage-engine:${Versions.junitJupiter}",
"org.apache.commons:commons-compress:1.15",
"commons-io:commons-io:2.6",
// Java 9
"javax.xml.bind:jaxb-api:2.3.0"
) )
exclude(*aether("impl", "spi", "util", "api")) exclude(*aether("impl", "spi", "util", "api"))
} }
@ -146,12 +142,8 @@ val kobaltPluginApi = project {
} }
} }
// install {
// libDir = "lib-test"
// }
kotlinCompiler { kotlinCompiler {
args("-nowarn") args("nowarn")
} }
bintray { bintray {
@ -172,24 +164,30 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
// Used by the main app // Used by the main app
compile( compile(
"org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}", "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}",
"com.github.spullara.mustache.java:compiler:0.9.1", "com.github.spullara.mustache.java:compiler:0.9.5",
"javax.inject:javax.inject:1", "javax.inject:javax.inject:1",
"com.google.inject:guice:4.0", "com.google.inject:guice:${Versions.guice}",
"com.google.inject.extensions:guice-assistedinject:4.0", "com.google.inject.extensions:guice-assistedinject:${Versions.guice}",
"com.beust:jcommander:1.65", "com.beust:jcommander:${Versions.jcommander}",
"org.apache.maven:maven-model:${Versions.maven}", "org.apache.maven:maven-model:${Versions.maven}",
"com.google.code.findbugs:jsr305:3.0.1", "com.google.code.findbugs:jsr305:3.0.2",
"com.google.code.gson:gson:${Versions.gson}", "com.google.code.gson:gson:${Versions.gson}",
"com.squareup.retrofit2:retrofit:${Versions.retrofit}", "com.squareup.retrofit2:retrofit:${Versions.retrofit}",
"com.squareup.retrofit2:converter-gson:${Versions.retrofit}", "com.squareup.retrofit2:converter-gson:${Versions.retrofit}",
"com.squareup.okhttp3:okhttp-ws:${Versions.okhttp}", // "com.squareup.okhttp3:okhttp-ws:3.4.2",
"biz.aQute.bnd:bndlib:2.4.0", "biz.aQute.bnd:biz.aQute.bndlib:3.5.0",
*mavenResolver("spi"), *mavenResolver("spi"),
"com.squareup.okhttp3:logging-interceptor:3.2.0", "com.squareup.okhttp3:logging-interceptor:3.9.0",
"com.sparkjava:spark-core:2.5", "com.sparkjava:spark-core:2.6.0",
"org.codehaus.groovy:groovy:2.4.8" "org.codehaus.groovy:groovy:2.4.12",
// Java 9
"javax.xml.bind:jaxb-api:2.3.0",
"com.sun.xml.bind:jaxb-impl:2.3.0",
"com.sun.xml.bind:jaxb-core:2.3.0",
"com.sun.activation:javax.activation:1.2.0"
// "org.eclipse.jetty:jetty-server:${Versions.jetty}", // "org.eclipse.jetty:jetty-server:${Versions.jetty}",
// "org.eclipse.jetty:jetty-servlet:${Versions.jetty}", // "org.eclipse.jetty:jetty-servlet:${Versions.jetty}",
@ -205,7 +203,7 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
dependenciesTest { dependenciesTest {
compile("org.jetbrains.kotlin:kotlin-test:${Versions.kotlin}", compile("org.jetbrains.kotlin:kotlin-test:${Versions.kotlin}",
"org.testng:testng:${Versions.testng}", "org.testng:testng:${Versions.testng}",
"org.assertj:assertj-core:3.4.1", "org.assertj:assertj-core:3.8.0",
*mavenResolver("util") *mavenResolver("util")
) )
} }
@ -228,11 +226,18 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
(0 .. files.size - 1 step 3).forEach { i -> (0 .. files.size - 1 step 3).forEach { i ->
include(from(files[i]), to(files[i + 1]), files[i + 2]) include(from(files[i]), to(files[i + 1]), files[i + 2])
} }
// Package the sources
val currentDir = Paths.get(".").toAbsolutePath().normalize().toString()
zipFolders("$currentDir/$buildDirectory/libs/all-sources/$projectName-$version-sources.jar",
"$currentDir/$directory/src/main/kotlin",
"$currentDir/${kobaltPluginApi.directory}/src/main/kotlin")
include(from("$buildDirectory/libs/all-sources"), to("$dir/kobalt/wrapper"), "$projectName-$version-sources.jar")
} }
} }
kotlinCompiler { kotlinCompiler {
args("-nowarn") args("nowarn")
} }
bintray { bintray {
@ -252,6 +257,28 @@ 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 { fun readVersion() : String {
val localFile = val localFile =
listOf("src/main/resources/kobalt.properties", listOf("src/main/resources/kobalt.properties",
@ -278,3 +305,22 @@ fun taskCopyVersionForWrapper(project: Project) : TaskResult {
} }
return TaskResult() return TaskResult()
} }
fun createPom(projectName: String, projectDescription: String) = Model().apply {
name = projectName
description = projectDescription
url = "https://beust.com/kobalt"
licenses = listOf(License().apply {
name = "Apache-2.0"
url = "https://www.apache.org/licenses/LICENSE-2.0"
})
scm = Scm().apply {
url = "https://github.com/cbeust/kobalt"
connection = "https://github.com/cbeust/kobalt.git"
developerConnection = "git@github.com:cbeust/kobalt.git"
}
developers = listOf(Developer().apply {
name = "Cedric Beust"
email = "cedric@beust.com"
})
}

View file

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

8
kobaltw-test Executable file
View file

@ -0,0 +1,8 @@
#!/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

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

View file

@ -0,0 +1,279 @@
<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

@ -61,6 +61,9 @@ class Args {
@Parameter(names = arrayOf("--noIncremental"), description = "Turn off incremental builds") @Parameter(names = arrayOf("--noIncremental"), description = "Turn off incremental builds")
var noIncremental: Boolean = false var noIncremental: Boolean = false
@Parameter(names = arrayOf("--offline"), description = "Don't try to download dependencies even if there is no cached version")
var offline: Boolean = false
@Parameter(names = arrayOf("--plugins"), description = "Comma-separated list of plug-in Maven id's") @Parameter(names = arrayOf("--plugins"), description = "Comma-separated list of plug-in Maven id's")
var pluginIds: String? = null var pluginIds: String? = null
@ -101,5 +104,8 @@ class Args {
@Parameter(names = arrayOf("--update"), description = "Update to the latest version of Kobalt") @Parameter(names = arrayOf("--update"), description = "Update to the latest version of Kobalt")
var update: Boolean = false var update: Boolean = false
@Parameter(names = arrayOf("--version"), description = "Display the current version of Kobalt")
var version: Boolean = false
} }

View file

@ -74,8 +74,18 @@ data class ProxyConfig(val host: String = "", val port: Int = 0, val type: Strin
fun toAetherProxy() = Proxy(type, host, port) // TODO make support for proxy auth fun toAetherProxy() = Proxy(type, host, port) // TODO make support for proxy auth
} }
data class HostConfig(var url: String = "", var name: String = url, var username: String? = null, data class HostConfig(var url: String = "", var name: String = HostConfig.createRepoName(url),
var password: String? = null) { var username: String? = null, var password: String? = null) {
companion object {
/**
* For repos specified in the build file (repos()) that don't have an associated unique name,
* create such a name from the URL. This is a requirement from Maven Resolver, and failing to do
* this leads to very weird resolution errors.
*/
private fun createRepoName(url: String) = url.replace("/", "_").replace("\\", "_").replace(":", "_")
}
fun hasAuth() : Boolean { fun hasAuth() : Boolean {
return (! username.isNullOrBlank()) && (! password.isNullOrBlank()) return (! username.isNullOrBlank()) && (! password.isNullOrBlank())
} }
@ -106,6 +116,7 @@ fun buildFileClasspath(vararg deps: String) {
} }
fun newBuildFileClasspath(vararg deps: String) { fun newBuildFileClasspath(vararg deps: String) {
//FIXME newBuildFileClasspath called twice
deps.forEach { Kobalt.addBuildFileClasspath(it) } deps.forEach { Kobalt.addBuildFileClasspath(it) }
} }
@ -115,7 +126,7 @@ fun authRepos(vararg repos : HostConfig) {
} }
@Directive @Directive
fun authRepo(init: HostConfig.() -> Unit) = HostConfig().apply { init() } fun authRepo(init: HostConfig.() -> Unit) = HostConfig(name = "").apply { init() }
@Directive @Directive
fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g) fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g)

View file

@ -9,13 +9,13 @@ object Constants {
val BUILD_FILE_NAME = "Build.kt" val BUILD_FILE_NAME = "Build.kt"
val BUILD_FILE_DIRECTORY = "kobalt/src" val BUILD_FILE_DIRECTORY = "kobalt/src"
val BUILD_FILE_PATH = KFiles.joinDir(BUILD_FILE_DIRECTORY, BUILD_FILE_NAME) val BUILD_FILE_PATH = KFiles.joinDir(BUILD_FILE_DIRECTORY, BUILD_FILE_NAME)
val KOTLIN_COMPILER_VERSION = "1.1.1" val KOTLIN_COMPILER_VERSION = "1.2.70"
internal val DEFAULT_REPOS = listOf<HostConfig>( internal val DEFAULT_REPOS = listOf<HostConfig>(
// "https://maven-central.storage.googleapis.com/", // "https://maven-central.storage.googleapis.com/",
HostConfig("http://repo1.maven.org/maven2/", "Maven"), HostConfig("https://repo1.maven.org/maven2/", "Maven"),
HostConfig("https://jcenter.bintray.com/", "JCenter") HostConfig("https://jcenter.bintray.com/", "JCenter")
// "http://repository.jetbrains.com/all/", // <-- contains snapshots // "https://repository.jetbrains.com/all/", // <-- contains snapshots
// snapshots // snapshots
// "https://oss.sonatype.org/content/repositories/snapshots/" // "https://oss.sonatype.org/content/repositories/snapshots/"

View file

@ -3,16 +3,16 @@ package com.beust.kobalt
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.archive.Archives import com.beust.kobalt.archive.Archives
import com.beust.kobalt.archive.MetaArchive
import com.beust.kobalt.archive.Zip import com.beust.kobalt.archive.Zip
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.Scope import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.* import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.kobaltLog
import com.google.inject.Inject import com.google.inject.Inject
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.OutputStream
import java.nio.file.Paths import java.nio.file.Paths
import java.util.jar.JarOutputStream
import java.util.jar.Manifest import java.util.jar.Manifest
class JarGenerator @Inject constructor(val dependencyManager: DependencyManager) : ArchiveGenerator { class JarGenerator @Inject constructor(val dependencyManager: DependencyManager) : ArchiveGenerator {
@ -142,7 +142,7 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
val allFiles = includedFiles.flatMap { file -> val allFiles = includedFiles.flatMap { file ->
file.allFromFiles(project.directory).map { file.from(it.path) } file.allFromFiles(project.directory).map { file.from(it.path) }
} }
val manifestFiles = allFiles.filter { it.path.contains("META-INF/MANIFEST.MF") } val manifestFiles = allFiles.filter { it.path.contains(MetaArchive.MANIFEST_MF) }
return if (manifestFiles.any()) manifestFiles[0] else null return if (manifestFiles.any()) manifestFiles[0] else null
} }
@ -151,14 +151,12 @@ class JarGenerator @Inject constructor(val dependencyManager: DependencyManager)
context.logger.log(project.name, 2, "Including MANIFEST.MF file $manifestFile") context.logger.log(project.name, 2, "Including MANIFEST.MF file $manifestFile")
Manifest(FileInputStream(manifestFile)) Manifest(FileInputStream(manifestFile))
} else { } else {
Manifest() null
} }
} }
val jarFactory = { os: OutputStream -> JarOutputStream(os, manifest) }
return Archives.generateArchive(project, context, zip.name, ".jar", includedFiles, return Archives.generateArchive(project, context, zip.name, ".jar", includedFiles,
true /* expandJarFiles */, jarFactory) true /* expandJarFiles */, manifest)
} }
} }

View file

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

View file

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

View file

@ -1,3 +1,8 @@
package com.beust.kobalt package com.beust.kobalt
open public class TaskResult(val success: Boolean = true, val errorMessage: String? = null) 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
)

View file

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

View file

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

View file

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

View file

@ -5,7 +5,7 @@ import com.beust.kobalt.Variant
/** /**
* Plug-ins that can generate a BuildConfig file. * Plug-ins that can generate a BuildConfig file.
*/ */
interface IBuildConfigContributor : ISimpleAffinity<Project> { interface IBuildConfigContributor : IProjectAffinity {
fun generateBuildConfig(project: Project, context: KobaltContext, packageName: String, variant: Variant, fun generateBuildConfig(project: Project, context: KobaltContext, packageName: String, variant: Variant,
buildConfigs: List<BuildConfig>) : String buildConfigs: List<BuildConfig>) : String

View file

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

View file

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

View file

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

View file

@ -5,6 +5,7 @@ import com.beust.kobalt.HostConfig
import com.beust.kobalt.Plugins import com.beust.kobalt.Plugins
import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.google.inject.Guice import com.google.inject.Guice
import com.google.inject.Injector import com.google.inject.Injector
import com.google.inject.Module import com.google.inject.Module
@ -55,6 +56,9 @@ class Kobalt {
// Repos from the build file // Repos from the build file
result.addAll(reposFromBuildFiles) result.addAll(reposFromBuildFiles)
result.forEach {
KobaltMavenResolver.initAuthentication(it)
}
return result.toHashSet() return result.toHashSet()
} }
@ -131,6 +135,7 @@ class Kobalt {
fun cleanUp() { fun cleanUp() {
buildSourceDirs.clear() buildSourceDirs.clear()
buildFileClasspath.clear()
} }
} }
} }

View file

@ -91,7 +91,8 @@ open class Project(
@Directive @Directive
fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies { fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies {
dependencies = Dependencies(this, testDependencies, arrayListOf(), dependencies = Dependencies(this, testDependencies, arrayListOf(),
testProvidedDependencies, compileRuntimeDependencies, excludedDependencies, nativeDependencies) testProvidedDependencies, compileOnlyDependencies, compileRuntimeDependencies,
excludedDependencies, nativeDependencies)
dependencies!!.init() dependencies!!.init()
return dependencies!! return dependencies!!
} }
@ -128,7 +129,7 @@ open class Project(
return result return result
} }
class Dep(val File: File, val id: String) class Dep(val file: File, val id: String)
/** /**
* @return a list of the transitive dependencies (absolute paths to jar files) for the given dependencies. * @return a list of the transitive dependencies (absolute paths to jar files) for the given dependencies.
@ -154,6 +155,7 @@ class Dependencies(val project: Project,
val dependencies: ArrayList<IClasspathDependency>, val dependencies: ArrayList<IClasspathDependency>,
val optionalDependencies: ArrayList<IClasspathDependency>, val optionalDependencies: ArrayList<IClasspathDependency>,
val providedDependencies: ArrayList<IClasspathDependency>, val providedDependencies: ArrayList<IClasspathDependency>,
val compileOnlyDependencies: ArrayList<IClasspathDependency>,
val runtimeDependencies: ArrayList<IClasspathDependency>, val runtimeDependencies: ArrayList<IClasspathDependency>,
val excludedDependencies: ArrayList<IClasspathDependency>, val excludedDependencies: ArrayList<IClasspathDependency>,
val nativeDependencies: ArrayList<IClasspathDependency>) { val nativeDependencies: ArrayList<IClasspathDependency>) {
@ -244,6 +246,9 @@ class Dependencies(val project: Project,
addToDependencies(project, dependencies, arrayOf(dep), excludeConfig = excludeConfig) addToDependencies(project, dependencies, arrayOf(dep), excludeConfig = excludeConfig)
} }
@Directive
fun compileOnly(vararg dep: String) = addToDependencies(project, compileOnlyDependencies, dep)
@Directive @Directive
fun compileOptional(vararg dep: String) { fun compileOptional(vararg dep: String) {
addToDependencies(project, optionalDependencies, dep, optional = true) addToDependencies(project, optionalDependencies, dep, optional = true)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -70,7 +70,12 @@ class CompilerUtils @Inject constructor(val files: KFiles, val dependencyManager
copyResources(project, context, SourceSet.of(isTest)) copyResources(project, context, SourceSet.of(isTest))
val fullClasspath = dependencyManager.calculateDependencies(project, context, val fullClasspath = dependencyManager.calculateDependencies(project, context,
scopes = if (isTest) listOf(Scope.COMPILE, Scope.TEST) else listOf(Scope.COMPILE)) scopes = if (isTest) {
listOf(Scope.COMPILE, Scope.COMPILEONLY, Scope.TEST)
} else {
listOf(Scope.COMPILE, Scope.COMPILEONLY)
})
File(project.directory, buildDirectory.path).mkdirs() File(project.directory, buildDirectory.path).mkdirs()

View file

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

View file

@ -7,7 +7,8 @@ import java.lang.reflect.InvocationTargetException
import java.util.* import java.util.*
import java.util.concurrent.* import java.util.concurrent.*
open class TaskResult2<T>(success: Boolean, errorMessage: String?, val value: T) : TaskResult(success, errorMessage) { open class TaskResult2<T>(success: Boolean, testResult: TestResult? = null,
errorMessage: String? = null, val value: T) : TaskResult(success, testResult, errorMessage) {
override fun toString() = com.beust.kobalt.misc.toString("TaskResult", "value", value, "success", success) override fun toString() = com.beust.kobalt.misc.toString("TaskResult", "value", value, "success", success)
} }
@ -393,7 +394,7 @@ fun main(argv: Array<String>) {
object: IWorker<String> { object: IWorker<String> {
override fun call(): TaskResult2<String>? { override fun call(): TaskResult2<String>? {
kobaltLog(1, " Running worker $it") kobaltLog(1, " Running worker $it")
return TaskResult2(true, null, it) return TaskResult2(true, value = it)
} }
override val priority: Int get() = 0 override val priority: Int get() = 0

View file

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

View file

@ -35,7 +35,8 @@ class JUnit5Runner @Inject constructor(kFiles: KFiles) : GenericTestRunner() {
override fun affinity(project: Project, context: KobaltContext) : Int { override fun affinity(project: Project, context: KobaltContext) : Int {
val result = val result =
if (project.testDependencies.any { it.id.contains("jupiter") }) IAffinity.DEFAULT_POSITIVE_AFFINITY + 100 if (project.testDependencies.any { it.id.contains("junit5") || it.id.contains("jupiter") })
IAffinity.DEFAULT_POSITIVE_AFFINITY + 100
else 0 else 0
return result return result

View file

@ -4,6 +4,10 @@ import com.beust.kobalt.TestConfig
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.DependencyManager
import com.google.inject.Inject
import java.lang.reflect.Modifier
import java.net.URLClassLoader
open class JUnitRunner() : GenericTestRunner() { open class JUnitRunner() : GenericTestRunner() {
@ -14,5 +18,15 @@ open class JUnitRunner() : GenericTestRunner() {
override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) = findTestClasses(project, context, testConfig) testConfig: TestConfig) = findTestClasses(project, context, testConfig)
@Inject
lateinit var dependencyManager: DependencyManager
override fun filterTestClasses(project: Project, context: KobaltContext, classes: List<String>) : List<String> {
val deps = dependencyManager.testDependencies(project, context)
val cl = URLClassLoader(deps.map { it.jarFile.get().toURI().toURL() }.toTypedArray())
return classes.filter { !Modifier.isAbstract(cl.loadClass(it).modifiers) }
}
} }

View file

@ -28,7 +28,6 @@ class JvmCompiler @Inject constructor(val dependencyManager: DependencyManager)
.distinct() .distinct()
// Plugins that add flags to the compiler // Plugins that add flags to the compiler
val currentFlags = arrayListOf<String>().apply { addAll(info.compilerArgs) }
val contributorFlags : List<String> = if (project != null) flags else emptyList() val contributorFlags : List<String> = if (project != null) flags else emptyList()
val addedFlags = contributorFlags + ArrayList(info.compilerArgs) val addedFlags = contributorFlags + ArrayList(info.compilerArgs)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -272,7 +272,8 @@ class TaskManager @Inject constructor(val args: Args,
object : BasePluginTask(plugin, name, description, group, project) { object : BasePluginTask(plugin, name, description, group, project) {
override fun call(): TaskResult2<ITask> { override fun call(): TaskResult2<ITask> {
val taskResult = task(project) val taskResult = task(project)
return TaskResult2(taskResult.success, taskResult.errorMessage, this) return TaskResult2(taskResult.success, errorMessage = taskResult.errorMessage, value = this,
testResult = taskResult.testResult)
} }
}) })
dependsOn.forEach { dependsOn(it, name) } dependsOn.forEach { dependsOn(it, name) }
@ -319,9 +320,11 @@ class TaskWorker(val tasks: List<ITask>, val dryRun: Boolean, val pluginInfo: Pl
val tr = if (dryRun) TaskResult() else it.call() val tr = if (dryRun) TaskResult() else it.call()
BaseProjectRunner.runBuildListenersForTask(it.project, context, name, start = false, success = tr.success) BaseProjectRunner.runBuildListenersForTask(it.project, context, name, start = false, success = tr.success)
success = success and tr.success success = success and tr.success
if (tr.errorMessage != null) errorMessages.add(tr.errorMessage) tr.errorMessage?.let {
errorMessages.add(it)
}
} }
return TaskResult2(success, errorMessages.joinToString("\n"), tasks[0]) return TaskResult2(success, errorMessage = errorMessages.joinToString("\n"), value = tasks[0])
} }
// override val timeOut : Long = 10000 // override val timeOut : Long = 10000

View file

@ -2,6 +2,7 @@ package com.beust.kobalt.internal
import com.beust.kobalt.AsciiArt import com.beust.kobalt.AsciiArt
import com.beust.kobalt.TestConfig import com.beust.kobalt.TestConfig
import com.beust.kobalt.TestResult
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
@ -12,8 +13,15 @@ import org.testng.remote.strprotocol.JsonMessageSender
import org.testng.remote.strprotocol.MessageHelper import org.testng.remote.strprotocol.MessageHelper
import org.testng.remote.strprotocol.MessageHub import org.testng.remote.strprotocol.MessageHub
import org.testng.remote.strprotocol.TestResultMessage import org.testng.remote.strprotocol.TestResultMessage
import org.w3c.dom.Attr
import org.w3c.dom.NodeList
import org.xml.sax.InputSource
import java.io.File import java.io.File
import java.io.FileReader
import java.io.IOException import java.io.IOException
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.XPathConstants
import javax.xml.xpath.XPathFactory
class TestNgRunner : GenericTestRunner() { class TestNgRunner : GenericTestRunner() {
@ -22,7 +30,10 @@ class TestNgRunner : GenericTestRunner() {
override val annotationPackage = "org.testng" override val annotationPackage = "org.testng"
override val runnerName = "TestNG" override val runnerName = "TestNG"
fun defaultOutput(project: Project) = KFiles.joinDir(project.buildDirectory, "test-output") 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 fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) = arrayListOf<String>().apply { testConfig: TestConfig) = arrayListOf<String>().apply {
@ -34,7 +45,9 @@ class TestNgRunner : GenericTestRunner() {
if (testConfig.testArgs.none { it == "-d" }) { if (testConfig.testArgs.none { it == "-d" }) {
add("-d") add("-d")
add(defaultOutput(project)) // Don't include the project directory here since the generic runner will cd to that directory before
// running the tests
add(defaultOutputWithoutProjectDir(project))
} }
if (testConfig.testArgs.size == 0) { if (testConfig.testArgs.size == 0) {
@ -60,11 +73,50 @@ 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") val VERSION_6_10 = StringVersion("6.10")
fun _runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, fun _runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
// override fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, // override fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
configName: String): Boolean { configName: String): TestResult {
val testConfig = project.testConfigs.firstOrNull { it.name == configName } val testConfig = project.testConfigs.firstOrNull { it.name == configName }
@ -85,7 +137,7 @@ class TestNgRunner : GenericTestRunner() {
} }
return result return result
} else { } else {
return true return TestResult(true)
} }
} }
@ -102,7 +154,8 @@ class TestNgRunner : GenericTestRunner() {
} }
private fun displayPrettyColors(project: Project, context: KobaltContext, private fun displayPrettyColors(project: Project, context: KobaltContext,
classpath: List<IClasspathDependency>, testConfig: TestConfig, versions: Pair<String, String>): Boolean { classpath: List<IClasspathDependency>, testConfig: TestConfig, versions: Pair<String, String>)
: TestResult {
val port = 2345 val port = 2345
// launchRemoteServer(project, context, classpath, testConfig, versions, port) // launchRemoteServer(project, context, classpath, testConfig, versions, port)
@ -151,7 +204,7 @@ class TestNgRunner : GenericTestRunner() {
val top = it.stackTrace.substring(0, it.stackTrace.indexOf("\n")) val top = it.stackTrace.substring(0, it.stackTrace.indexOf("\n"))
kobaltLog(1, " " + it.cls + "." + it.method + "\n " + top) kobaltLog(1, " " + it.cls + "." + it.method + "\n " + top)
} }
return failed.isEmpty() && skipped.isEmpty() return TestResult(failed.isEmpty() && skipped.isEmpty())
} }
fun launchRemoteServer(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, fun launchRemoteServer(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,

View file

@ -106,6 +106,10 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors,
val result = arrayListOf<IClasspathDependency>().apply { val result = arrayListOf<IClasspathDependency>().apply {
if (scopes.contains(Scope.COMPILE)) { if (scopes.contains(Scope.COMPILE)) {
addAll(project.compileDependencies) addAll(project.compileDependencies)
addAll(project.compileProvidedDependencies)
}
if (scopes.contains(Scope.COMPILEONLY)) {
addAll(project.compileOnlyDependencies)
} }
if (scopes.contains(Scope.RUNTIME)) { if (scopes.contains(Scope.RUNTIME)) {
addAll(project.compileRuntimeDependencies) addAll(project.compileRuntimeDependencies)

View file

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

View file

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

View file

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

View file

@ -15,7 +15,7 @@ object Filters {
override fun accept(p0: DependencyNode, p1: MutableList<DependencyNode>): Boolean { override fun accept(p0: DependencyNode, p1: MutableList<DependencyNode>): Boolean {
val result = p0.dependency != null && ! p0.dependency.optional val result = p0.dependency != null && ! p0.dependency.optional
if (! result) { if (! result) {
kobaltLog(2, "Excluding from optional filter: $p0") kobaltLog(3, "Excluding from optional filter: $p0")
} }
return result return result
} }

View file

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

View file

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

View file

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

View file

@ -86,12 +86,12 @@ class GithubApi2 @Inject constructor(
.execute() .execute()
val code = response.code() val code = response.code()
if (code != Http.CREATED) { if (code != Http.CREATED) {
val error = Gson().fromJson(response.errorBody().string(), RetrofitError::class.java) val error = Gson().fromJson(response.errorBody()?.string(), RetrofitError::class.java)
throw KobaltException("Couldn't upload release, ${error.message}: " + error.errors[0].code) throw KobaltException("Couldn't upload release, ${error.message}: " + error.errors[0].code)
} else { } else {
val body = response.body() val body = response.body()
uploadAsset(accessToken, body.uploadUrl!!, Http.TypedFile("application/zip", zipFile), tagName) uploadAsset(accessToken, body?.uploadUrl!!, Http.TypedFile("application/zip", zipFile), tagName)
.toBlocking() .toBlocking()
.forEach { action -> .forEach { action ->
kobaltLog(1, "\n${zipFile.name} successfully uploaded") kobaltLog(1, "\n${zipFile.name} successfully uploaded")
@ -120,8 +120,8 @@ class GithubApi2 @Inject constructor(
Duration.between(VersionCheckTimestampFile.timestamp, Instant.now())) { Duration.between(VersionCheckTimestampFile.timestamp, Instant.now())) {
kobaltLog(2, "Skipping GitHub latest release check, too soon.") kobaltLog(2, "Skipping GitHub latest release check, too soon.")
} else { } else {
val username = localProperties.getNoThrows(PROPERTY_USERNAME, DOC_URL) val username = localProperties.getNoThrows(PROPERTY_USERNAME)
val accessToken = localProperties.getNoThrows(PROPERTY_ACCESS_TOKEN, DOC_URL) val accessToken = localProperties.getNoThrows(PROPERTY_ACCESS_TOKEN)
try { try {
val req = val req =
if (username != null && accessToken != null) { if (username != null && accessToken != null) {
@ -138,8 +138,8 @@ class GithubApi2 @Inject constructor(
val releases = ex.body() val releases = ex.body()
if (releases != null) { if (releases != null) {
releases.firstOrNull()?.let { releases.firstOrNull()?.let {
try { result = try {
result = listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() } listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() }
} catch(ex: NoSuchElementException) { } catch(ex: NoSuchElementException) {
throw KobaltException("Couldn't find the latest release") throw KobaltException("Couldn't find the latest release")
} }

View file

@ -1,14 +1,16 @@
package com.beust.kobalt.misc package com.beust.kobalt.misc
import com.beust.kobalt.* import com.beust.kobalt.From
import com.beust.kobalt.IFileSpec
import com.beust.kobalt.IncludedFile
import com.beust.kobalt.To
import com.beust.kobalt.archive.MetaArchive
import com.google.common.io.CharStreams import com.google.common.io.CharStreams
import java.io.* import java.io.File
import java.util.jar.JarEntry import java.io.FileOutputStream
import java.io.InputStreamReader
import java.util.jar.JarFile import java.util.jar.JarFile
import java.util.jar.JarInputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
class JarUtils { class JarUtils {
companion object { companion object {
@ -19,18 +21,15 @@ class JarUtils {
} }
} }
fun addFiles(directory: String, files: List<IncludedFile>, target: ZipOutputStream, fun addFiles(directory: String, files: List<IncludedFile>, metaArchive: MetaArchive,
expandJarFiles: Boolean, expandJarFiles: Boolean,
onError: (Exception) -> Unit = DEFAULT_HANDLER) { onError: (Exception) -> Unit = DEFAULT_HANDLER) {
files.forEach { files.forEach {
addSingleFile(directory, it, target, expandJarFiles, onError) addSingleFile(directory, it, metaArchive, expandJarFiles, onError)
} }
} }
private val DEFAULT_JAR_EXCLUDES = fun addSingleFile(directory: String, file: IncludedFile, metaArchive: MetaArchive,
Glob("META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA")
fun addSingleFile(directory: String, file: IncludedFile, outputStream: ZipOutputStream,
expandJarFiles: Boolean, onError: (Exception) -> Unit = DEFAULT_HANDLER) { expandJarFiles: Boolean, onError: (Exception) -> Unit = DEFAULT_HANDLER) {
val foundFiles = file.allFromFiles(directory) val foundFiles = file.allFromFiles(directory)
foundFiles.forEach { foundFile -> foundFiles.forEach { foundFile ->
@ -49,50 +48,24 @@ class JarUtils {
// Directory // Directory
val includedFile = IncludedFile(From(""), To(""), listOf(IFileSpec.GlobSpec("**"))) val includedFile = IncludedFile(From(""), To(""), listOf(IFileSpec.GlobSpec("**")))
addSingleFile(localFile.path, includedFile, outputStream, expandJarFiles) addSingleFile(localFile.path, includedFile, metaArchive, expandJarFiles)
} else { } else {
if (file.expandJarFiles && foundFile.name.endsWith(".jar") && ! file.from.contains("resources")) { try {
kobaltLog(2, " Writing contents of jar file $foundFile") if (file.expandJarFiles && foundFile.name.endsWith(".jar") && !file.from.contains("resources")) {
val stream = JarInputStream(FileInputStream(localFile)) kobaltLog(2, " Writing contents of jar file $foundFile")
var entry = stream.nextEntry metaArchive.addArchive(foundFile)
while (entry != null) { } else {
if (!entry.isDirectory && !KFiles.isExcluded(entry.name, DEFAULT_JAR_EXCLUDES)) { val toPath = File(file.to).normalize().path
val ins = JarFile(localFile).getInputStream(entry) val finalPath = if (toPath.isEmpty()) null else (toPath + "/")
addEntry(ins, JarEntry(entry), outputStream, onError) metaArchive.addFile(File(directory, fromFile.path), foundFile, finalPath)
}
entry = stream.nextEntry
} }
} else { } catch(ex: Exception) {
val entryFileName = KFiles.fixSlashes(file.to(foundFile.path)) onError(ex)
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? { fun extractTextFile(zip : ZipFile, fileName: String) : String? {
val enumEntries = zip.entries() val enumEntries = zip.entries()
while (enumEntries.hasMoreElements()) { while (enumEntries.hasMoreElements()) {

View file

@ -10,7 +10,9 @@ import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.util.*
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import java.util.regex.Pattern
class KFiles { class KFiles {
@ -20,6 +22,20 @@ class KFiles {
*/ */
val kobaltJar : List<String> val kobaltJar : List<String>
get() { get() {
val PATTERN = Pattern.compile("kobalt-([-.0-9]+)")
fun latestInstalledVersion() : StringVersion {
val versions = File(distributionsDir).listFiles().map { it.name }.map {
val matcher = PATTERN.matcher(it)
val result =
if (matcher.matches()) matcher.group(1)
else null
result
}.filterNotNull().map(::StringVersion)
Collections.sort(versions, reverseOrder())
return versions[0]
}
val envJar = System.getenv("KOBALT_JAR") val envJar = System.getenv("KOBALT_JAR")
if (envJar != null) { if (envJar != null) {
debug("Using kobalt jar $envJar") debug("Using kobalt jar $envJar")
@ -31,19 +47,21 @@ class KFiles {
if (jarFile.exists()) { if (jarFile.exists()) {
return listOf(jarFile.absolutePath) return listOf(jarFile.absolutePath)
} else { } else {
// In development mode, keep your kobalt.properties version one above kobalt-wrapper.properties: // In development mode, keep your kobalt.properties version to a nonexistent version
// kobalt.properties: kobalt.version=0.828 // kobalt.properties: kobalt.version=0.828
// kobalt-wrapper.properties: kobalt.version=0.827 // kobalt-wrapper.properties: kobalt.version=0.827
// When Kobalt can't find the newest jar file, it will instead use the classes produced by IDEA // When Kobalt can't find the newest jar file, it will instead use the classes produced by IDEA
// in the directories specified here: // in the directories specified here:
val leftSuffix = Kobalt.version.substring(0, Kobalt.version.lastIndexOf(".") + 1) val previousVersion = latestInstalledVersion().version
val previousVersion = leftSuffix +
(Kobalt.version.split(".").let { it[it.size - 1] }.toInt() - 1).toString()
val previousJar = joinDir(distributionsDir, "kobalt-" + previousVersion, val previousJar = joinDir(distributionsDir, "kobalt-" + previousVersion,
"kobalt/wrapper/kobalt-$previousVersion.jar") "kobalt/wrapper/kobalt-$previousVersion.jar")
latestInstalledVersion()
val result = listOf("", "modules/kobalt-plugin-api", "modules/wrapper").map { val result = listOf("", "modules/kobalt-plugin-api", "modules/wrapper").map {
File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "kobaltBuild", "classes"))) File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "kobaltBuild", "classes"))) //kobalt build dirs
.absolutePath .absolutePath
} + listOf("modules/kobalt", "modules/kobalt-plugin-api", "modules/wrapper").map {
File(homeDir(KFiles.joinDir("kotlin", "kobalt", it, "target", "classes"))) //maven build dirs
.absolutePath
} + listOf(previousJar) } + listOf(previousJar)
debug("Couldn't find ${jarFile.absolutePath}, using\n " + result.joinToString(" ")) debug("Couldn't find ${jarFile.absolutePath}, using\n " + result.joinToString(" "))
return result.filter { File(it).exists() } return result.filter { File(it).exists() }
@ -119,7 +137,7 @@ class KFiles {
fun joinFileAndMakeDir(vararg ts: String) = joinDir(joinAndMakeDir(ts.slice(0..ts.size - 2)), ts[ts.size - 1]) fun joinFileAndMakeDir(vararg ts: String) = joinDir(joinAndMakeDir(ts.slice(0..ts.size - 2)), ts[ts.size - 1])
fun fixSlashes(f: File) = f.normalize().path.replace('\\', '/') fun fixSlashes(f: File) = f.normalize().path.replace('\\', '/')
fun fixSlashes(s: String) = fixSlashes(File(s)) fun fixSlashes(s: String) = s.replace('\\', '/')
fun makeDir(dir: String, s: String? = null) = fun makeDir(dir: String, s: String? = null) =
(if (s != null) File(dir, s) else File(dir)).apply { mkdirs() } (if (s != null) File(dir, s) else File(dir)).apply { mkdirs() }
@ -227,22 +245,18 @@ class KFiles {
private fun isWindows() = System.getProperty("os.name").contains("Windows") private fun isWindows() = System.getProperty("os.name").contains("Windows")
fun copy(from: Path?, to: Path?, option: StandardCopyOption = StandardCopyOption.REPLACE_EXISTING) { fun copy(from: Path?, to: Path?, option: StandardCopyOption = StandardCopyOption.REPLACE_EXISTING) {
if (isWindows() && to!!.toFile().exists()) { try {
kobaltLog(2, "Windows detected, not overwriting $to") if (from != null && to != null) {
} else { if (!Files.exists(to) || Md5.toMd5(from.toFile()) != Md5.toMd5(to.toFile())) {
try { kobaltLog(3, "Copy from $from to $to")
if (from != null && to != null) { Files.copy(from, to, option)
if (!Files.exists(to) || Md5.toMd5(from.toFile()) != Md5.toMd5(to.toFile())) { } else {
kobaltLog(3, "Copy from $from to $to") kobaltLog(3, " Not copying, indentical files: $from $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}")
} }
} }

View file

@ -1,6 +1,9 @@
package com.beust.kobalt.misc package com.beust.kobalt.misc
import com.beust.kobalt.* 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.api.Kobalt
import com.beust.kobalt.maven.aether.Exceptions import com.beust.kobalt.maven.aether.Exceptions
import java.lang.Exception import java.lang.Exception
@ -48,7 +51,7 @@ fun Any.error(text: CharSequence, e: Throwable? = null) {
object KobaltLogger { object KobaltLogger {
var LOG_LEVEL: Int = 1 var LOG_LEVEL: Int = 1
val isQuiet: Boolean get() = (LOG_LEVEL == Constants.LOG_QUIET_LEVEL) val isQuiet: Boolean get() = (LOG_LEVEL == Constants.LOG_QUIET_LEVEL)
val logger: Logger get() = val logger: Logger get() =
@ -57,6 +60,14 @@ object KobaltLogger {
} else { } else {
Logger(false) Logger(false)
} }
fun setLogLevel(args: Args) {
LOG_LEVEL = when {
args.log < Constants.LOG_QUIET_LEVEL -> Constants.LOG_DEFAULT_LEVEL
args.log > Constants.LOG_MAX_LEVEL -> Constants.LOG_MAX_LEVEL
else -> args.log
}
}
} }
class Logger(val dev: Boolean) { class Logger(val dev: Boolean) {
@ -75,7 +86,8 @@ class Logger(val dev: Boolean) {
fun error(tag: String, message: CharSequence, e: Throwable? = null) { fun error(tag: String, message: CharSequence, e: Throwable? = null) {
val docUrl = if (e is KobaltException && e.docUrl != null) e.docUrl else null val docUrl = if (e is KobaltException && e.docUrl != null) e.docUrl else null
val text = if (! message.isBlank()) message val text =
if (message.isNotBlank()) message
else if (e != null && (! e.message.isNullOrBlank())) e.message else if (e != null && (! e.message.isNullOrBlank())) e.message
else { e?.toString() } else { e?.toString() }
val shortMessage = "***** E $text " + if (docUrl != null) " Documentation: $docUrl" else "" val shortMessage = "***** E $text " + if (docUrl != null) " Documentation: $docUrl" else ""
@ -88,7 +100,10 @@ class Logger(val dev: Boolean) {
} }
fun warn(tag: String, message: CharSequence, e: Throwable? = null) { fun warn(tag: String, message: CharSequence, e: Throwable? = null) {
val fullMessage = "***** WARNING " + (e?.message ?: message) val fullMessage = "***** WARNING " +
if (message.isNotBlank()) message
else if (e != null && (!e.message.isNullOrBlank())) e.message
else e?.toString()
println(AsciiArt.Companion.warnColor(getPattern("W", fullMessage, fullMessage, tag))) println(AsciiArt.Companion.warnColor(getPattern("W", fullMessage, fullMessage, tag)))
if (KobaltLogger.LOG_LEVEL > 1 && e != null) { if (KobaltLogger.LOG_LEVEL > 1 && e != null) {
Exceptions.printStackTrace(e) Exceptions.printStackTrace(e)

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,79 @@
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'
}
}
}
}
}

231
modules/kobalt/pom.xml Normal file
View file

@ -0,0 +1,231 @@
<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

@ -0,0 +1,38 @@
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'
}
}
}
}
}

28
modules/wrapper/pom.xml Normal file
View file

@ -0,0 +1,28 @@
<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

@ -47,7 +47,6 @@ public class Main {
private int installAndLaunchMain(String[] argv) throws IOException, InterruptedException { private int installAndLaunchMain(String[] argv) throws IOException, InterruptedException {
String version = getVersion(); String version = getVersion();
initWrapperFile(version);
List<String> kobaltArgv = new ArrayList<>(); List<String> kobaltArgv = new ArrayList<>();
boolean noLaunch = false; boolean noLaunch = false;
@ -78,6 +77,7 @@ public class Main {
} }
int result = 0; int result = 0;
if (! exit) { if (! exit) {
initWrapperFile(version);
Path kobaltJarFile = installDistribution(); Path kobaltJarFile = installDistribution();
if (!noLaunch) { if (!noLaunch) {
result = launchMain(kobaltJarFile, kobaltArgv); result = launchMain(kobaltJarFile, kobaltArgv);
@ -118,7 +118,7 @@ public class Main {
} }
private static String downloadUrl(String version) { private static String downloadUrl(String version) {
return "http://beust.com/kobalt/kobalt-" + version + ".zip"; return "https://beust.com/kobalt/kobalt-" + version + ".zip";
} }
private void initWrapperFile(String version) throws IOException { private void initWrapperFile(String version) throws IOException {
@ -133,7 +133,7 @@ public class Main {
} }
private String getWrapperVersion() { private String getWrapperVersion() {
return wrapperProperties.getProperty(PROPERTY_VERSION); return wrapperProperties.getProperty(PROPERTY_VERSION, "N/A");
} }
private String getWrapperDownloadUrl(String version) { private String getWrapperDownloadUrl(String version) {
@ -345,6 +345,11 @@ public class Main {
try { try {
Files.createDirectories(entryPath.getParent()); Files.createDirectories(entryPath.getParent());
Files.copy(zipFile.getInputStream(entry), entryPath, StandardCopyOption.REPLACE_EXISTING); 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) { } catch (FileSystemException ex) {
log(2, "Couldn't copy to " + entryPath); log(2, "Couldn't copy to " + entryPath);
} }

34
pom.xml Normal file
View file

@ -0,0 +1,34 @@
<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>

5
settings.gradle Normal file
View file

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

@ -38,6 +38,14 @@ class Main @Inject constructor(
companion object { companion object {
fun mainNoExit(argv: Array<String>): Int { fun mainNoExit(argv: Array<String>): Int {
val (jc, args) = parseArgs(argv) 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())) Kobalt.init(MainModule(args, KobaltSettings.readSettingsXml()))
val result = launchMain(Kobalt.INJECTOR.getInstance(Main::class.java), jc, args, argv) val result = launchMain(Kobalt.INJECTOR.getInstance(Main::class.java), jc, args, argv)
return result return result
@ -47,11 +55,7 @@ class Main @Inject constructor(
val args = Args() val args = Args()
val result = JCommander(args) val result = JCommander(args)
result.parse(*argv) result.parse(*argv)
KobaltLogger.LOG_LEVEL = if (args.log < Constants.LOG_QUIET_LEVEL) { KobaltLogger.setLogLevel(args)
Constants.LOG_DEFAULT_LEVEL
} else if (args.log > Constants.LOG_MAX_LEVEL) {
Constants.LOG_MAX_LEVEL
} else args.log
return Main.RunInfo(result, args) return Main.RunInfo(result, args)
} }

View file

@ -1,8 +1,10 @@
package com.beust.kobalt package com.beust.kobalt
import com.beust.jcommander.JCommander import com.beust.jcommander.JCommander
import com.beust.kobalt.api.ITask
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.PluginTask import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.app.ProjectFinder import com.beust.kobalt.app.ProjectFinder
import com.beust.kobalt.app.ProjectGenerator import com.beust.kobalt.app.ProjectGenerator
import com.beust.kobalt.app.Templates import com.beust.kobalt.app.Templates
@ -44,10 +46,26 @@ class Options @Inject constructor(
val p = if (args.buildFile != null) File(args.buildFile) else File(".") val p = if (args.buildFile != null) File(args.buildFile) else File(".")
// val buildFile = BuildFile(Paths.get(p.absolutePath), p.name) // val buildFile = BuildFile(Paths.get(p.absolutePath), p.name)
val buildSources = if (p.isDirectory) BuildSources(p.absoluteFile) else SingleFileBuildSources(p) val buildSources = if (p.isDirectory) BuildSources(p.absoluteFile) else SingleFileBuildSources(p)
var pluginClassLoader = javaClass.classLoader val pluginClassLoader = javaClass.classLoader
val allProjectResult = projectFinder.initForBuildFile(buildSources, args) //
val allProjects = allProjectResult.projects // 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 // Modify `args` with options found in buildScript { kobaltOptions(...) }, if any
addOptionsFromBuild(args, Kobalt.optionsFromBuild) addOptionsFromBuild(args, Kobalt.optionsFromBuild)
@ -77,9 +95,11 @@ class Options @Inject constructor(
}), }),
Option( { -> args.projectInfo }, { Option( { -> args.projectInfo }, {
// --projectInfo // --projectInfo
allProjects.forEach { runIfSuccessfulBuild(buildError) {
it.compileDependencies.filter { it.isMaven }.forEach { allProjects.forEach {
resolveDependency.run(it.id) it.compileDependencies.filter { it.isMaven }.forEach {
resolveDependency.run(it.id)
}
} }
} }
}), }),
@ -89,11 +109,15 @@ class Options @Inject constructor(
}), }),
Option( { args.tasks }, { Option( { args.tasks }, {
// --tasks // --tasks
displayTasks() runIfSuccessfulBuild(buildError) {
displayTasks(allProjects, Kobalt.context!!)
}
}), }),
Option( { args.checkVersions }, { Option( { args.checkVersions }, {
// --checkVersions // --checkVersions
checkVersions.run(allProjects) runIfSuccessfulBuild(buildError) {
checkVersions.run(allProjects)
}
}), }),
Option( { args.download }, { Option( { args.download }, {
// --download // --download
@ -121,17 +145,19 @@ class Options @Inject constructor(
if (! buildSources.exists()) { if (! buildSources.exists()) {
throw KobaltException("Could not find build file: " + buildSources) throw KobaltException("Could not find build file: " + buildSources)
} }
val runTargetResult = taskManager.runTargets(args.targets, allProjects) runIfSuccessfulBuild(buildError) {
if (result == 0) { val runTargetResult = taskManager.runTargets(args.targets, allProjects)
result = if (runTargetResult.taskResult.success) 0 else 1 if (result == 0) {
} result = if (runTargetResult.taskResult.success) 0 else 1
}
// Shutdown all plug-ins // Shutdown all plug-ins
plugins.shutdownPlugins() plugins.shutdownPlugins()
// Run the build report contributors // Run the build report contributors
pluginInfo.buildReportContributors.forEach { pluginInfo.buildReportContributors.forEach {
it.generateReport(Kobalt.context!!) it.generateReport(Kobalt.context!!)
}
} }
} }
return result return result
@ -152,19 +178,29 @@ class Options @Inject constructor(
} }
} }
private fun displayTasks() { private fun displayTasks(projects: List<Project>, context: KobaltContext) {
// //
// List of tasks, --tasks // List of tasks, --tasks
// //
val tasksByPlugins = HashMultimap.create<String, PluginTask>() val tasksByPlugins = HashMultimap.create<String, ITask>()
taskManager.annotationTasks.forEach { projects.forEach { project ->
tasksByPlugins.put(it.plugin.name, it) 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") val sb = StringBuffer("List of tasks\n")
tasksByPlugins.keySet().forEach { name -> tasksByPlugins.keySet().forEach { name ->
sb.append("\n " + AsciiArt.horizontalDoubleLine + " $name " sb.append("\n " + AsciiArt.horizontalDoubleLine + " $name "
+ AsciiArt.horizontalDoubleLine + "\n") + AsciiArt.horizontalDoubleLine + "\n")
tasksByPlugins[name].distinctBy(PluginTask::name).sortedBy(PluginTask::name).forEach { task -> tasksByPlugins[name].distinctBy(ITask::name).sortedBy(ITask::name).forEach { task ->
sb.append(" ${task.name}\t\t${task.doc}\n") sb.append(" ${task.name}\t\t${task.doc}\n")
} }
} }

View file

@ -119,7 +119,7 @@ class BuildFiles @Inject constructor(val factory: BuildFileCompiler.IFactory,
parentFile.mkdirs() parentFile.mkdirs()
val imp = arrayListOf<String>().apply { val imp = arrayListOf<String>().apply {
addAll(imports) addAll(imports)
}.distinct() }.toMutableSet().toMutableList()
Collections.sort(imp) Collections.sort(imp)
writeText(imp.joinToString("\n")) writeText(imp.joinToString("\n"))
appendText(code.joinToString("\n")) appendText(code.joinToString("\n"))

View file

@ -20,6 +20,8 @@ abstract class LanguageTemplateGenerator : ITemplate {
abstract val defaultSourceDirectories : HashSet<String> abstract val defaultSourceDirectories : HashSet<String>
abstract val defaultTestDirectories : HashSet<String> abstract val defaultTestDirectories : HashSet<String>
abstract val mainDependencies : ArrayList<Pom.Dependency>
abstract val testDependencies : ArrayList<Pom.Dependency>
abstract val directive : String abstract val directive : String
abstract val fileMatch : (String) -> Boolean abstract val fileMatch : (String) -> Boolean
abstract val fileMap: List<FileInfo> abstract val fileMap: List<FileInfo>
@ -131,20 +133,19 @@ abstract class LanguageTemplateGenerator : ITemplate {
put("directory", currentDir.absolutePath) put("directory", currentDir.absolutePath)
put("sourceDirectories", defaultSourceDirectories) put("sourceDirectories", defaultSourceDirectories)
put("sourceDirectoriesTest", defaultTestDirectories) put("sourceDirectoriesTest", defaultTestDirectories)
put("mainDependencies", mainDependencies)
put("testDependencies", testDependencies)
put("imports", "import com.beust.kobalt.plugin.$templateName.*") put("imports", "import com.beust.kobalt.plugin.$templateName.*")
put("directive", "project") put("directive", "project")
} }
var mainDeps = arrayListOf<Pom.Dependency>()
var testDeps = arrayListOf<Pom.Dependency>()
map.put("mainDependencies", mainDeps)
map.put("testDependencies", testDeps)
File("pom.xml").let { File("pom.xml").let {
if (it.absoluteFile.exists()) { if (it.absoluteFile.exists()) {
importPom(it, mainDeps, testDeps, map) importPom(it, mainDependencies, testDependencies, map)
} }
} }
val fileInputStream = javaClass.classLoader val fileInputStream = javaClass.classLoader
.getResource(ITemplateContributor.DIRECTORY_NAME + "/build.mustache").openStream() .getResource(ITemplateContributor.DIRECTORY_NAME + "/build.mustache").openStream()
val sw = StringWriter() val sw = StringWriter()

View file

@ -1,6 +1,8 @@
package com.beust.kobalt.app package com.beust.kobalt.app
import com.beust.kobalt.Args import com.beust.kobalt.Args
import com.beust.kobalt.JavaInfo
import com.beust.kobalt.Jvm
import com.beust.kobalt.app.remote.KobaltServer import com.beust.kobalt.app.remote.KobaltServer
import com.beust.kobalt.internal.IncrementalManager import com.beust.kobalt.internal.IncrementalManager
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
@ -17,6 +19,7 @@ import com.google.inject.Provider
import com.google.inject.Singleton import com.google.inject.Singleton
import com.google.inject.TypeLiteral import com.google.inject.TypeLiteral
import com.google.inject.assistedinject.FactoryModuleBuilder import com.google.inject.assistedinject.FactoryModuleBuilder
import java.io.File
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
open class MainModule(val args: Args, val settings: KobaltSettings) : AbstractModule() { open class MainModule(val args: Args, val settings: KobaltSettings) : AbstractModule() {
@ -49,15 +52,14 @@ open class MainModule(val args: Args, val settings: KobaltSettings) : AbstractMo
bind(Args::class.java).toProvider(Provider<Args> { bind(Args::class.java).toProvider(Provider<Args> {
args args
}) })
EventBus().let { eventBus -> bind(EventBus::class.java).toInstance(EventBus())
bind(EventBus::class.java).toInstance(eventBus)
}
bind(PluginInfo::class.java).toProvider(Provider<PluginInfo> { bind(PluginInfo::class.java).toProvider(Provider<PluginInfo> {
PluginInfo.readKobaltPluginXml() PluginInfo.readKobaltPluginXml()
}).`in`(Singleton::class.java) }).`in`(Singleton::class.java)
bind(KobaltSettings::class.java).toProvider(Provider<KobaltSettings> { bind(KobaltSettings::class.java).toProvider(Provider<KobaltSettings> {
settings settings
}).`in`(Singleton::class.java) }).`in`(Singleton::class.java)
bind(Jvm::class.java).toInstance(JavaInfo.create(File(com.beust.kobalt.SystemProperties.javaBase)))
// bindListener(Matchers.any(), object: TypeListener { // bindListener(Matchers.any(), object: TypeListener {
// override fun <I> hear(typeLiteral: TypeLiteral<I>?, typeEncounter: TypeEncounter<I>?) { // override fun <I> hear(typeLiteral: TypeLiteral<I>?, typeEncounter: TypeEncounter<I>?) {

View file

@ -56,7 +56,7 @@ class Profiles(val context: KobaltContext) {
val variable = if (match.first) match.second else oldMatch.second val variable = if (match.first) match.second else oldMatch.second
if (oldMatch.first) { if (oldMatch.first) {
warn("Old profile syntax detected for \"$line\"," + warn("Old profile syntax detected for \"${line.trim()}\"," +
" please update to \"val $variable by profile()\"") " please update to \"val $variable by profile()\"")
} }

View file

@ -1,11 +1,14 @@
package com.beust.kobalt.app.java package com.beust.kobalt.app.java
import com.beust.kobalt.app.LanguageTemplateGenerator import com.beust.kobalt.app.LanguageTemplateGenerator
import com.beust.kobalt.maven.Pom
/** /**
* Template for the "java" generator. * Template for the "java" generator.
*/ */
class JavaTemplateGenerator : LanguageTemplateGenerator() { class JavaTemplateGenerator : LanguageTemplateGenerator() {
override val mainDependencies = arrayListOf<Pom.Dependency>()
override val testDependencies = arrayListOf<Pom.Dependency>()
override val defaultSourceDirectories = hashSetOf("src/main/java") override val defaultSourceDirectories = hashSetOf("src/main/java")
override val defaultTestDirectories = hashSetOf("src/test/java") override val defaultTestDirectories = hashSetOf("src/test/java")
override val directive = "project" override val directive = "project"

View file

@ -1,10 +1,16 @@
package com.beust.kobalt.app.kotlin package com.beust.kobalt.app.kotlin
import com.beust.kobalt.Constants
import com.beust.kobalt.app.LanguageTemplateGenerator import com.beust.kobalt.app.LanguageTemplateGenerator
import com.beust.kobalt.maven.Pom
class KotlinTemplateGenerator : LanguageTemplateGenerator() { class KotlinTemplateGenerator : LanguageTemplateGenerator() {
override val defaultSourceDirectories = hashSetOf("src/main/kotlin") override val defaultSourceDirectories = hashSetOf("src/main/kotlin")
override val defaultTestDirectories = hashSetOf("src/test/kotlin") override val defaultTestDirectories = hashSetOf("src/test/kotlin")
override val mainDependencies = arrayListOf(
Pom.Dependency("org.jetbrains.kotlin", "kotlin-stdlib", null, Constants.KOTLIN_COMPILER_VERSION)
)
override val testDependencies = arrayListOf<Pom.Dependency>()
override val directive = "project" override val directive = "project"
override val templateName = "kotlin" override val templateName = "kotlin"
override val templateDescription = "Generate a simple Kotlin project" override val templateDescription = "Generate a simple Kotlin project"

View file

@ -35,6 +35,7 @@ class GetDependencyGraphHandler : WebSocketListener {
fun <T> sendWebsocketCommand(endpoint: RemoteEndpoint, commandName: String, payload: T, fun <T> sendWebsocketCommand(endpoint: RemoteEndpoint, commandName: String, payload: T,
errorMessage: String? = null) { errorMessage: String? = null) {
SparkServer.watchDog.rearm()
val json = Gson().toJson(WebSocketCommand(commandName, payload = Gson().toJson(payload), val json = Gson().toJson(WebSocketCommand(commandName, payload = Gson().toJson(payload),
errorMessage = errorMessage)) errorMessage = errorMessage))
endpoint.sendString(json) endpoint.sendString(json)

View file

@ -12,15 +12,7 @@ import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.warn import com.beust.kobalt.misc.warn
import com.google.gson.Gson import com.google.gson.Gson
import com.google.inject.Guice import com.google.inject.Guice
import okhttp3.OkHttpClient import okhttp3.*
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody
import okhttp3.ws.WebSocket
import okhttp3.ws.WebSocketCall
import okhttp3.ws.WebSocketListener
import okio.Buffer
import java.io.IOException
fun main(argv: Array<String>) { fun main(argv: Array<String>) {
Kobalt.INJECTOR = Guice.createInjector(MainModule(Args(), KobaltSettings.readSettingsXml())) Kobalt.INJECTOR = Guice.createInjector(MainModule(Args(), KobaltSettings.readSettingsXml()))
@ -39,26 +31,22 @@ class KobaltClient : Runnable {
.url("$url?projectRoot=$projectRoot&buildFile=$buildFile") .url("$url?projectRoot=$projectRoot&buildFile=$buildFile")
.build() .build()
var webSocket: WebSocket? = null var webSocket: WebSocket? = null
val ws = WebSocketCall.create(client, request).enqueue(object: WebSocketListener { val socketListener = object: WebSocketListener() {
override fun onOpen(ws: WebSocket, response: Response) { override fun onFailure(webSocket: WebSocket, ex: Throwable, response: Response?) {
webSocket = ws
}
override fun onPong(p0: Buffer?) {
println("WebSocket pong")
}
override fun onClose(p0: Int, p1: String?) {
println("WebSocket closed")
}
override fun onFailure(ex: IOException, response: Response?) {
Exceptions.printStackTrace(ex) Exceptions.printStackTrace(ex)
error("WebSocket failure: ${ex.message} response: $response") error("WebSocket failure: ${ex.message} response: $response")
} }
override fun onMessage(body: ResponseBody) { override fun onOpen(ws: WebSocket, response: Response) {
val json = body.string() webSocket = ws
}
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
println("Closing socket")
}
override fun onMessage(webSocket: WebSocket, text: String) {
val json = text
val wsCommand = Gson().fromJson(json, WebSocketCommand::class.java) val wsCommand = Gson().fromJson(json, WebSocketCommand::class.java)
if (wsCommand.errorMessage != null) { if (wsCommand.errorMessage != null) {
warn("Received error message from server: " + wsCommand.errorMessage) warn("Received error message from server: " + wsCommand.errorMessage)
@ -87,7 +75,10 @@ class KobaltClient : Runnable {
} }
} }
} }
}) }
val ws = client.newWebSocket(request, socketListener)
ws.close(1000, "All good")
} }
} }

View file

@ -1,6 +1,5 @@
package com.beust.kobalt.app.remote package com.beust.kobalt.app.remote
import com.beust.kobalt.api.Project
import com.beust.kobalt.homeDir import com.beust.kobalt.homeDir
import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.maven.aether.Exceptions import com.beust.kobalt.maven.aether.Exceptions
@ -74,15 +73,12 @@ class KobaltServer @Inject constructor(@Assisted val force: Boolean, @Assisted @
try { try {
if (createServerFile(port, force)) { if (createServerFile(port, force)) {
kobaltLog(1, "KobaltServer listening on port $port") kobaltLog(1, "KobaltServer listening on port $port")
// OldServer(initCallback, cleanUpCallback).run(port)
// JerseyServer(initCallback, cleanUpCallback).run(port)
SparkServer(cleanUpCallback, pluginInfo).run(port) SparkServer(cleanUpCallback, pluginInfo).run(port)
// WasabiServer(initCallback, cleanUpCallback).run(port)
} }
} catch(ex: Exception) { } catch(ex: Exception) {
Exceptions.printStackTrace(ex) Exceptions.printStackTrace(ex)
} finally { } finally {
// deleteServerFile() deleteServerFile()
} }
return port return port
} }

View file

@ -2,6 +2,7 @@ package com.beust.kobalt.app.remote
import com.beust.kobalt.Args import com.beust.kobalt.Args
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.app.BuildFileCompiler import com.beust.kobalt.app.BuildFileCompiler
import com.beust.kobalt.internal.DynamicGraph import com.beust.kobalt.internal.DynamicGraph
@ -29,7 +30,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v
val taskManager: TaskManager) { val taskManager: TaskManager) {
fun dependenciesDataFor(buildSources: BuildSources, args: Args, fun dependenciesDataFor(buildSources: BuildSources, args: Args,
findProjectResult: BuildFileCompiler.FindProjectResult, projectResult: BuildFileCompiler.FindProjectResult,
progressListener: IProgressListener? = null, progressListener: IProgressListener? = null,
useGraph : Boolean = false): GetDependenciesData { useGraph : Boolean = false): GetDependenciesData {
val projectDatas = arrayListOf<ProjectData>() val projectDatas = arrayListOf<ProjectData>()
@ -42,9 +43,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v
fun allDeps(l: List<IClasspathDependency>, name: String) = dependencyManager.transitiveClosure(l, fun allDeps(l: List<IClasspathDependency>, name: String) = dependencyManager.transitiveClosure(l,
requiredBy = name) requiredBy = name)
// val buildFile = BuildFile(Paths.get(buildFilePath), "GetDependenciesCommand") val buildFileDependencies = Kobalt.buildFileClasspath.map {toDependencyData(it, "compile")}
val buildFileCompiler = buildFileCompilerFactory.create(buildSources, pluginInfo)
val projectResult = buildFileCompiler.compileBuildFiles(args)
val pluginDependencies = projectResult.pluginUrls.map { File(it.toURI()) }.map { val pluginDependencies = projectResult.pluginUrls.map { File(it.toURI()) }.map {
DependencyData(it.name, "compile", it.absolutePath) DependencyData(it.name, "compile", it.absolutePath)
@ -176,8 +175,8 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v
}) })
} }
return GetDependenciesData(projectDatas, allTasks, pluginDependencies, findProjectResult.buildContentRoots, return GetDependenciesData(projectDatas, allTasks, pluginDependencies, buildFileDependencies,
projectResult.taskResult.errorMessage) projectResult.buildContentRoots, projectResult.taskResult.errorMessage)
} }
///// /////
@ -202,6 +201,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v
class GetDependenciesData(val projects: List<ProjectData> = emptyList(), class GetDependenciesData(val projects: List<ProjectData> = emptyList(),
val allTasks: Collection<TaskData> = emptySet(), val allTasks: Collection<TaskData> = emptySet(),
val pluginDependencies: List<DependencyData> = emptyList(), val pluginDependencies: List<DependencyData> = emptyList(),
val buildFileDependencies: List<DependencyData> = emptyList(),
val buildContentRoots: List<String> = emptyList(), val buildContentRoots: List<String> = emptyList(),
val errorMessage: String?) { val errorMessage: String?) {
companion object { companion object {

View file

@ -5,6 +5,7 @@ import com.beust.kobalt.app.Templates
import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.PluginInfo
import com.google.common.collect.ListMultimap import com.google.common.collect.ListMultimap
import com.google.gson.Gson import com.google.gson.Gson
import org.slf4j.Logger
import spark.ResponseTransformer import spark.ResponseTransformer
import spark.Route import spark.Route
import spark.Spark import spark.Spark
@ -14,6 +15,8 @@ class SparkServer(val cleanUpCallback: () -> Unit, val pluginInfo : PluginInfo)
companion object { companion object {
lateinit var cleanUpCallback: () -> Unit lateinit var cleanUpCallback: () -> Unit
val URL_QUIT = "/quit"
lateinit var watchDog: WatchDog
} }
init { init {
@ -28,19 +31,25 @@ class SparkServer(val cleanUpCallback: () -> Unit, val pluginInfo : PluginInfo)
private fun jsonRoute(path: String, route: Route) private fun jsonRoute(path: String, route: Route)
= Spark.get(path, "application/json", route, JsonTransformer()) = Spark.get(path, "application/json", route, JsonTransformer())
val log = org.slf4j.LoggerFactory.getLogger("SparkServer") val log: Logger = org.slf4j.LoggerFactory.getLogger("SparkServer")
override fun run(port: Int) { override fun run(port: Int) {
val threadPool = Executors.newFixedThreadPool(2)
watchDog = WatchDog(port, 60 * 10 /* 10 minutes */, log)
threadPool.submit {
watchDog.run()
}
log.debug("Server running") log.debug("Server running")
Spark.port(port) Spark.port(port)
Spark.webSocket("/v1/getDependencyGraph", GetDependencyGraphHandler::class.java) Spark.webSocket("/v1/getDependencyGraph", GetDependencyGraphHandler::class.java)
Spark.get("/ping") { req, res -> Spark.get("/ping") { req, res ->
watchDog.rearm()
log.debug(" Received ping") log.debug(" Received ping")
""" { "result" : "ok" } """ """ { "result" : "ok" } """
} }
Spark.get("/quit", { req, res -> Spark.get(URL_QUIT, { req, res ->
log.debug(" Received quit") log.debug(" Received quit")
Executors.newFixedThreadPool(1).let { executor -> threadPool.let { executor ->
executor.submit { executor.submit {
Thread.sleep(1000) Thread.sleep(1000)
Spark.stop() Spark.stop()

View file

@ -0,0 +1,71 @@
package com.beust.kobalt.app.remote
import com.beust.kobalt.misc.warn
import org.slf4j.Logger
import java.net.HttpURLConnection
import java.net.URL
import java.time.Duration
import java.time.LocalDateTime
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
/**
* Wakes up every `WAKE_UP_INTERVAL` and check if a certain period of time (`checkPeriod`) has elapsed
* without being rearmed. If that time has elapsed, send a QUIT command to the Kobalt server. If the WatchDog
* gets rearmed, the expiration period is reset.
*/
class WatchDog(val port: Int, val checkPeriodSeconds: Long, val log: Logger) {
private val WAKE_UP_INTERVAL: Duration = Duration.ofSeconds(60)
private val FORMAT: DateTimeFormatter = DateTimeFormatter.ofPattern("MM/d/y HH:mm:ss")
private var nextWakeUpMillis: Long = arm()
private var stop: Boolean = false
/**
* Rearm for another `checkPeriod`.
*/
fun rearm() {
nextWakeUpMillis = arm()
log.info("Watchdog rearmed for " + format(nextWakeUpMillis))
}
/**
* Start the watch dog.
*/
fun run() {
val wakeUpSeconds = WAKE_UP_INTERVAL.toMillis()
log.info("Server dying at " + format(nextWakeUpMillis) + ", next wake up in "
+ (wakeUpSeconds / 1000) + " seconds")
while (! stop) {
Thread.sleep(wakeUpSeconds)
val diffSeconds = (nextWakeUpMillis - System.currentTimeMillis()) / 1000
if (diffSeconds <= 0) {
log.info("Time to die")
stop = true
} else {
log.info("Dying in $diffSeconds seconds")
}
}
try {
val connection = (URL("http://localhost:$port" + SparkServer.URL_QUIT)
.openConnection() as HttpURLConnection).apply {
requestMethod = "GET"
}
val code = connection.responseCode
if (code == 200) {
log.info("Successfully stopped the server")
} else {
warn("Couldn't stop the server, response: " + code)
}
} catch(ex: Exception) {
warn("Couldn't stop the server: " + ex.message, ex)
}
}
private fun arm() = System.currentTimeMillis() + (checkPeriodSeconds * 1000)
private fun toLocalDate(millis: Long) = LocalDateTime.ofEpochSecond(millis / 1000, 0, OffsetDateTime.now().offset)
private fun format(millis: Long) = FORMAT.format(toLocalDate(millis))
}

View file

@ -1,11 +1,12 @@
package com.beust.kobalt.plugin.application package com.beust.kobalt.plugin.application
import com.beust.kobalt.* import com.beust.kobalt.Jvm
import com.beust.kobalt.KobaltException
import com.beust.kobalt.Plugins
import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.archive.Archives import com.beust.kobalt.archive.Archives
import com.beust.kobalt.internal.ActorUtils
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.Scope import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
@ -19,6 +20,9 @@ import com.google.inject.Singleton
import java.io.File import java.io.File
class ApplicationConfig { class ApplicationConfig {
@Directive
var taskName: String = "run"
@Directive @Directive
var mainClass: String? = null var mainClass: String? = null
@ -29,6 +33,15 @@ class ApplicationConfig {
@Directive @Directive
fun args(vararg argv: String) = argv.forEach { args.add(it) } fun args(vararg argv: String) = argv.forEach { args.add(it) }
val args = arrayListOf<String>() val args = arrayListOf<String>()
@Directive
var ignoreErrorStream: Boolean = false
@Directive
var ignoreInputStream: Boolean = true
@Directive
var ignoreExitValue: Boolean = false
} }
@Directive @Directive
@ -40,10 +53,10 @@ fun Project.application(init: ApplicationConfig.() -> Unit): ApplicationConfig {
} }
@Singleton @Singleton
class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<ApplicationConfig>, class ApplicationPlugin @Inject constructor(val configActor: ConfigsActor<ApplicationConfig>,
val executors: KobaltExecutors, val nativeManager: NativeManager, val executors: KobaltExecutors, val nativeManager: NativeManager,
val dependencyManager: DependencyManager, val taskContributor : TaskContributor) val dependencyManager: DependencyManager, val taskContributor : TaskContributor, val jvm: Jvm)
: BasePlugin(), IRunnerContributor, ITaskContributor, IConfigActor<ApplicationConfig> by configActor { : BasePlugin(), ITaskContributor, IConfigsActor<ApplicationConfig> by configActor {
companion object { companion object {
const val PLUGIN_NAME = "Application" const val PLUGIN_NAME = "Application"
@ -53,49 +66,50 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<Applica
override fun apply(project: Project, context: KobaltContext) { override fun apply(project: Project, context: KobaltContext) {
super.apply(project, context) super.apply(project, context)
taskContributor.addVariantTasks(this, project, context, "run", group = "run", dependsOn = listOf("install"),
runTask = { taskRun(project) })
}
@Task(name = "run", description = "Run the main class", group = "run", dependsOn = arrayOf("install")) configurationFor(project)?.let { configs ->
fun taskRun(project: Project): TaskResult { configs.forEach { config ->
val runContributor = ActorUtils.selectAffinityActor(project, context, taskContributor.addTask(this, project, config.taskName,
context.pluginInfo.runnerContributors) description = "Run the class " + config.mainClass,
if (runContributor != null && runContributor.affinity(project, context) > 0) { group = "run",
return runContributor.run(project, context, dependsOn = listOf("assemble"),
dependencyManager.dependencies(project, context, listOf(Scope.RUNTIME))) runTask = { run(project, context, config) })
} else { }
context.logger.log(project.name, 1,
"Couldn't find a runner for project ${project.name}. Please make sure" +
" your build file contains " +
"an application{} directive with a mainClass=... in it")
return TaskResult()
} }
} }
// fun taskRun(project: Project, config: ApplicationConfig): TaskResult {
// val runContributor = ActorUtils.selectAffinityActor(project, context,
// context.pluginInfo.runnerContributors)
// if (runContributor != null && runContributor.affinity(project, context) > 0) {
// return runContributor.run(project, context,
// dependencyManager.dependencies(project, context, listOf(Scope.RUNTIME)))
// } else {
// context.logger.log(project.name, 1,
// "Couldn't find a runner for project ${project.name}. Please make sure" +
// " your build file contains " +
// "an application{} directive with a mainClass=... in it")
// return TaskResult()
// }
// }
private fun isFatJar(packages: List<PackageConfig>, jarName: String): Boolean { private fun isFatJar(packages: List<PackageConfig>, jarName: String): Boolean {
val foundJar = packages.flatMap { it.jars }.filter { jarName.endsWith(it.name) } val foundJar = packages.flatMap { it.jars }.filter { jarName.endsWith(it.name) }
return foundJar.size == 1 && foundJar[0].fatJar return foundJar.size == 1 && foundJar[0].fatJar
} }
// IRunContributor private fun run(project: Project, context: KobaltContext, config: ApplicationConfig): TaskResult {
override fun affinity(project: Project, context: KobaltContext): Int {
return if (configurationFor(project) != null) IAffinity.DEFAULT_POSITIVE_AFFINITY else 0
}
override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>): TaskResult {
var result = TaskResult()
if (project.nativeDependencies.any()) { if (project.nativeDependencies.any()) {
nativeManager.installLibraries(project) nativeManager.installLibraries(project)
} }
configurationFor(project)?.let { config ->
val result =
if (config.mainClass != null) { if (config.mainClass != null) {
result = runJarFile(project, context, config) runJarFile(project, context, config)
} else { } else {
throw KobaltException("No \"mainClass\" specified in the application{} part of project ${project.name}") throw KobaltException("No \"mainClass\" specified in the application{} part of project ${project.name}")
} }
}
return result return result
} }
@ -111,7 +125,7 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<Applica
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val packages = project.projectProperties.get(PackagingPlugin.PACKAGES) as List<PackageConfig> val packages = project.projectProperties.get(PackagingPlugin.PACKAGES) as List<PackageConfig>
val allDeps = arrayListOf(jarName) val allDeps = arrayListOf(jarName)
val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable!! val java = jvm.javaExecutable!!
if (! isFatJar(packages, jarName)) { if (! isFatJar(packages, jarName)) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
// If the jar file is not fat, we need to add the transitive closure of all dependencies // If the jar file is not fat, we need to add the transitive closure of all dependencies
@ -133,6 +147,7 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<Applica
val exitCode = runCommand { val exitCode = runCommand {
command = "java" command = "java"
args = allArgs args = allArgs
useErrorStreamAsErrorIndicator = false
directory = File(project.directory) directory = File(project.directory)
successCallback = { output: List<String> -> successCallback = { output: List<String> ->
kobaltLog(1, output.joinToString("\n")) kobaltLog(1, output.joinToString("\n"))
@ -141,11 +156,25 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<Applica
kobaltLog(1, "ERROR") kobaltLog(1, "ERROR")
kobaltLog(1, output.joinToString("\n")) kobaltLog(1, output.joinToString("\n"))
} }
useErrorStreamAsErrorIndicator = !config.ignoreErrorStream
useInputStreamAsErrorIndicator = !config.ignoreInputStream
ignoreExitValue = config.ignoreExitValue
} }
return TaskResult(exitCode == 0) return TaskResult(exitCode == 0)
} }
//ITaskContributor //ITaskContributor
override fun tasksFor(project: Project, context: KobaltContext): List<DynamicTask> = taskContributor.dynamicTasks override fun tasksFor(project: Project, context: KobaltContext): List<DynamicTask> {
val result = arrayListOf<DynamicTask>()
configurationFor(project)?.let { configs ->
configs.forEach { config ->
result.add(DynamicTask(this, config.taskName, "Run the class " + config.mainClass, "run", project,
dependsOn = listOf("assemble"),
closure = { run(project, context, config) }))
}
}
return result
}
} }

View file

@ -1,10 +1,20 @@
package com.beust.kobalt.plugin.apt package com.beust.kobalt.plugin.apt
import com.beust.kobalt.Constants
import com.beust.kobalt.Jvm
import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.api.annotation.AnnotationDefault
import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.internal.CompilerUtils
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.Filters
import com.beust.kobalt.maven.aether.Scope
import com.beust.kobalt.maven.dependency.FileDependency
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.KobaltLogger
import com.beust.kobalt.misc.warn import com.beust.kobalt.misc.warn
import com.beust.kobalt.plugin.kotlin.KotlinPlugin
import com.google.common.collect.ArrayListMultimap import com.google.common.collect.ArrayListMultimap
import com.google.inject.Inject import com.google.inject.Inject
import java.io.File import java.io.File
@ -12,33 +22,16 @@ import java.util.*
import javax.inject.Singleton import javax.inject.Singleton
/** /**
* The AptPlugin has two components: * The AptPlugin manages both apt and kapt. Each of them has two components:
* 1) A new apt directive inside a dependency{} block (similar to compile()) that declares where * 1) A new apt directive inside a dependency{} block (similar to compile()) that declares where
* the annotation processor is found * the annotation processor is found
* 2) An apt{} configuration on Project that lets the user configure how the annotation is performed * 2) An apt{} configuration on Project that lets the user configure how the annotation is performed
* (outputDir, etc...). * (outputDir, etc...).
*/ */
@Singleton @Singleton
class AptPlugin @Inject constructor(val dependencyManager: DependencyManager) class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, val kotlinPlugin: KotlinPlugin,
: BasePlugin(), ICompilerFlagContributor, ISourceDirectoryContributor { val compilerUtils: CompilerUtils, val jvm: Jvm)
: BasePlugin(), ICompilerFlagContributor, ISourceDirectoryContributor, IClasspathContributor, ITaskContributor {
// ISourceDirectoryContributor
private fun generatedDir(project: Project, outputDir: String) : File
= File(KFiles.joinDir(project.directory, KFiles.KOBALT_BUILD_DIR, outputDir))
override fun sourceDirectoriesFor(project: Project, context: KobaltContext): List<File> {
val result = arrayListOf<File>()
aptConfigs[project.name]?.let { config ->
result.add(generatedDir(project, config.outputDir))
}
kaptConfigs[project.name]?.let { config ->
result.add(generatedDir(project, config.outputDir))
}
return result
}
companion object { companion object {
const val PLUGIN_NAME = "Apt" const val PLUGIN_NAME = "Apt"
@ -49,10 +42,14 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager)
override val name = PLUGIN_NAME override val name = PLUGIN_NAME
override fun apply(project: Project, context: KobaltContext) { override fun apply(project: Project, context: KobaltContext) {
listOf(aptConfigs[project.name]?.outputDir, aptConfigs[project.name]?.outputDir) super.apply(project, context)
val kaptConfig = kaptConfigs[project.name]
// Delete the output directories
listOf(aptConfigs[project.name]?.outputDir, kaptConfig?.outputDir)
.filterNotNull() .filterNotNull()
.distinct() .distinct()
.map { generatedDir(project, it) } .map { aptGeneratedDir(project, it) }
.forEach { .forEach {
it.normalize().absolutePath.let { path -> it.normalize().absolutePath.let { path ->
context.logger.log(project.name, 1, " Deleting " + path) context.logger.log(project.name, 1, " Deleting " + path)
@ -62,21 +59,195 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager)
} }
} }
private fun generated(project: Project, context: KobaltContext, outputDir: String) = // IClasspathContributor
KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir, override fun classpathEntriesFor(project: Project?, context: KobaltContext): Collection<IClasspathDependency> {
context.variant.toIntermediateDir()) val result = arrayListOf<IClasspathDependency>()
val kaptConfig = kaptConfigs[project?.name]
if (project != null && kaptConfig != null) {
kaptConfig.let { config ->
val c = kaptClassesDir(project, config.outputDir)
File(c).mkdirs()
result.add(FileDependency(c))
}
}
return result
}
private fun aptGeneratedDir(project: Project, outputDir: String) : File
= File(KFiles.joinDir(project.directory, KFiles.KOBALT_BUILD_DIR, outputDir))
// ISourceDirectoryContributor
override fun sourceDirectoriesFor(project: Project, context: KobaltContext): List<File> {
val result = arrayListOf<File>()
aptConfigs[project.name]?.let { config ->
result.add(aptGeneratedDir(project, config.outputDir))
}
kaptConfigs[project.name]?.let { config ->
result.add(File(kaptSourcesDir(project, config.outputDir)))
}
return result
}
private fun kaptGenerated(project: Project, outputDir: String) =
KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir)
private fun kaptSourcesDir(project: Project, outputDir: String) =
KFiles.joinDir(kaptGenerated(project, outputDir), "sources")
private fun kaptStubsDir(project: Project, outputDir: String) =
KFiles.joinDir(kaptGenerated(project, outputDir), "stubs")
private fun kaptClassesDir(project: Project, outputDir: String) =
KFiles.joinDir(kaptGenerated(project, outputDir), "classes")
// ITaskContributor
override fun tasksFor(project: Project, context: KobaltContext): List<DynamicTask> {
val kaptConfig = kaptConfigs[project.name]
val result =
if (kaptConfig != null) {
listOf(
DynamicTask(this, "runKapt", "Run kapt", AnnotationDefault.GROUP, project,
reverseDependsOn = listOf("compile"), runAfter = listOf("clean"),
closure = {p: Project -> taskRunKapt(p)}),
DynamicTask(this, "compileKapt", "Compile the sources generated by kapt",
AnnotationDefault.GROUP, project,
dependsOn = listOf("runKapt"), reverseDependsOn = listOf("compile"),
closure = {p: Project -> taskCompileKapt(p)})
)
} else {
emptyList()
}
return result
}
fun taskCompileKapt(project: Project) : TaskResult {
var success = true
kaptConfigs[project.name]?.let { config ->
val sourceDirs = listOf(
kaptStubsDir(project, config.outputDir),
kaptSourcesDir(project, config.outputDir))
val sourceFiles = KFiles.findSourceFiles(project.directory, sourceDirs, listOf("kt")).toList()
val buildDirectory = File(KFiles.joinDir(project.directory,
kaptClassesDir(project, config.outputDir)))
val flags = listOf<String>()
val cai = CompilerActionInfo(project.directory, allDependencies(project), sourceFiles, listOf(".kt"),
buildDirectory, flags, emptyList(), forceRecompile = true, compilerSeparateProcess = true)
val cr = compilerUtils.invokeCompiler(project, context, kotlinPlugin.compiler, cai)
success = cr.failedResult == null
}
return TaskResult(success)
}
val annotationDependencyId = "org.jetbrains.kotlin:kotlin-annotation-processing:" +
Constants.KOTLIN_COMPILER_VERSION
fun annotationProcessorDependency() = dependencyManager.create(annotationDependencyId)
fun aptJarDependencies(project: Project) = aptDependencies[project.name].map { dependencyManager.create(it) }
fun allDependencies(project: Project): List<IClasspathDependency> {
val allDeps = arrayListOf<IClasspathDependency>()
allDeps.add(annotationProcessorDependency())
allDeps.addAll(aptJarDependencies(project))
return allDeps
}
fun taskRunKapt(project: Project) : TaskResult {
var success = true
val flags = arrayListOf<String>()
val kaptConfig = kaptConfigs[project.name]
kaptConfig?.let { config ->
val generated = kaptGenerated(project, config.outputDir)
val generatedSources = kaptSourcesDir(project, config.outputDir).replace("//", "/")
File(generatedSources).mkdirs()
//
// Tell the Kotlin compiler to use the annotation plug-in
//
flags.add("-Xplugin")
flags.add(annotationProcessorDependency().jarFile.get().absolutePath)
// Also need tools.jar on the plug-in classpath
val toolsJar = jvm.toolsJar
if (toolsJar != null) {
flags.add("-Xplugin")
flags.add(toolsJar.absolutePath)
} else {
warn("Couldn't find tools.jar from the JDK")
}
aptJarDependencies(project).forEach {
flags.add("-Xplugin")
flags.add(it.jarFile.get().absolutePath)
}
//
// Pass options to the annotation plugin
//
flags.add("-P")
fun kaptPluginFlag(flagValue: String) = "plugin:org.jetbrains.kotlin.kapt3:$flagValue"
val kaptPluginFlags = arrayListOf<String>()
val verbose = KobaltLogger.LOG_LEVEL >= 2
listOf("sources=" + generatedSources,
"classes=" + kaptClassesDir(project, config.outputDir),
"stubs=" + kaptStubsDir(project, config.outputDir),
"verbose=$verbose",
"aptOnly=true").forEach {
kaptPluginFlags.add(kaptPluginFlag(it))
}
//
// Dependencies for the annotation plug-in and the generation
//
val allDeps = allDependencies(project)
val dependencies = dependencyManager.calculateDependencies(project, context,
Filters.EXCLUDE_OPTIONAL_FILTER,
listOf(Scope.COMPILE),
allDeps)
dependencies.forEach {
val jarFile = it.jarFile.get().absolutePath
kaptPluginFlags.add(kaptPluginFlag("apclasspath=$jarFile"))
}
flags.add(kaptPluginFlags.joinToString(","))
listOf("-language-version", "1.1", "-api-version", "1.1").forEach {
flags.add(it)
}
val sourceFiles =
KFiles.findSourceFiles(project.directory, project.sourceDirectories, listOf("kt"))
.toList() + generatedSources
val buildDirectory = File(KFiles.joinDir(project.directory, generated))
val cai = CompilerActionInfo(project.directory, allDeps, sourceFiles, listOf(".kt"),
buildDirectory, flags, emptyList(), forceRecompile = true, compilerSeparateProcess = true)
context.logger.log(project.name, 2, "kapt3 flags:")
context.logger.log(project.name, 2, " " + kaptPluginFlags.joinToString("\n "))
val cr = compilerUtils.invokeCompiler(project, context, kotlinPlugin.compiler, cai)
success = cr.failedResult == null
}
return TaskResult(success)
}
// ICompilerFlagContributor // ICompilerFlagContributor
override fun compilerFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>, override fun compilerFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>,
suffixesBeingCompiled: List<String>): List<String> { suffixesBeingCompiled: List<String>): List<String> {
if (!suffixesBeingCompiled.contains("java")) return emptyList()
val result = arrayListOf<String>() val result = arrayListOf<String>()
// Only run for Java files
if (!suffixesBeingCompiled.contains("java")) return emptyList()
fun addFlags(outputDir: String) { fun addFlags(outputDir: String) {
aptDependencies[project.name]?.let { aptDependencies[project.name]?.let {
result.add("-s") result.add("-s")
result.add(generated(project, context, outputDir)) aptGeneratedDir(project, outputDir).let { generatedSource ->
generatedSource.mkdirs()
result.add(generatedSource.path)
}
} }
} }
@ -84,10 +255,6 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager)
addFlags(config.outputDir) addFlags(config.outputDir)
} }
kaptConfigs[project.name]?.let { config ->
addFlags(config.outputDir)
}
context.logger.log(project.name, 2, "New flags from apt: " + result.joinToString(" ")) context.logger.log(project.name, 2, "New flags from apt: " + result.joinToString(" "))
return result return result
} }

View file

@ -1,7 +1,6 @@
package com.beust.kobalt.plugin.java package com.beust.kobalt.plugin.java
import com.beust.kobalt.JavaInfo import com.beust.kobalt.Jvm
import com.beust.kobalt.SystemProperties
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.internal.CompilerUtils import com.beust.kobalt.internal.CompilerUtils
@ -22,7 +21,7 @@ import javax.tools.ToolProvider
@Singleton @Singleton
class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltLog: ParallelLogger, class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltLog: ParallelLogger,
val compilerUtils: CompilerUtils) : ICompiler { val compilerUtils: CompilerUtils, val jvm: Jvm) : ICompiler {
fun compilerAction(executable: File) = object : ICompilerAction { fun compilerAction(executable: File) = object : ICompilerAction {
override fun compile(project: Project?, info: CompilerActionInfo): TaskResult { override fun compile(project: Project?, info: CompilerActionInfo): TaskResult {
val projectName = project?.name val projectName = project?.name
@ -84,7 +83,7 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltL
val pb = ProcessBuilder(executable.absolutePath, "@" + KFiles.fixSlashes(atFile)) val pb = ProcessBuilder(executable.absolutePath, "@" + KFiles.fixSlashes(atFile))
pb.inheritIO() pb.inheritIO()
logk(1, " Java compiling " + Strings.pluralizeAll(info.sourceFiles.size, "file")) logk(1, " Java compiling " + Strings.pluralizeAll(info.sourceFiles.size, "file"))
logk(2, " Java compiling file: " + KFiles.fixSlashes(atFile)) logk(2, " Java compiling using file: " + KFiles.fixSlashes(atFile))
command = allArgs.joinToString(" ") + " " + info.sourceFiles.joinToString(" ") command = allArgs.joinToString(" ") + " " + info.sourceFiles.joinToString(" ")
val process = pb.start() val process = pb.start()
@ -94,11 +93,11 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltL
} }
return if (result) { return if (result) {
TaskResult(true, "Compilation succeeded") TaskResult(true, errorMessage = "Compilation succeeded")
} else { } else {
val message = "Compilation errors, command:\n$command\n" + errorMessage val message = "Compilation errors, command:\n$command\n" + errorMessage
logk(1, message) logk(1, message)
TaskResult(false, message) TaskResult(false, errorMessage = message)
} }
} }
@ -119,7 +118,7 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltL
-> it.compilerFlagsFor(project, context, currentFlags, suffixesBeingCompiled) } -> it.compilerFlagsFor(project, context, currentFlags, suffixesBeingCompiled) }
FlagContributor(it.flagPriority, closure) FlagContributor(it.flagPriority, closure)
} }
return run(project, context, info, JavaInfo.create(File(SystemProperties.javaBase)).javacExecutable!!, return run(project, context, info, jvm.javacExecutable!!,
compilerUtils.compilerFlags(project, context, info, adapters)) compilerUtils.compilerFlags(project, context, info, adapters))
} }
@ -130,7 +129,7 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltL
-> it.docFlagsFor(project, context, currentFlags, suffixesBeingCompiled) } -> it.docFlagsFor(project, context, currentFlags, suffixesBeingCompiled) }
FlagContributor(it.flagPriority, closure) FlagContributor(it.flagPriority, closure)
} }
return run(project, context, info, JavaInfo.create(File(SystemProperties.javaBase)).javadocExecutable!!, return run(project, context, info, jvm.javadocExecutable!!,
compilerUtils.compilerFlags(project, context, info, adapters)) compilerUtils.compilerFlags(project, context, info, adapters))
} }
} }

View file

@ -44,9 +44,18 @@ class JavaPlugin @Inject constructor(val javaCompiler: JavaCompiler, override va
// IDocFlagContributor // IDocFlagContributor
override fun docFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>, override fun docFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>,
suffixesBeingCompiled: List<String>): List<String> { suffixesBeingCompiled: List<String>): List<String> {
return listOf("-d", "javadoc", "-Xdoclint:none", "-Xmaxerrs", "1", "-quiet") val config = javadocConfigurations[project.name]
return if (config == null || config.args.isEmpty()) DEFAULT_JAVADOC_ARGS
else config.args
} }
val DEFAULT_JAVADOC_ARGS = listOf("-d", "javadoc", "-Xdoclint:none", "-Xmaxerrs", "1", "-quiet")
val javadocConfigurations = hashMapOf<String, JavadocConfig>()
fun addJavadocConfiguration(project: Project, configuration: JavadocConfig)
= javadocConfigurations.put(project.name, configuration)
// ICompilerContributor // ICompilerContributor
val compiler = CompilerDescription(PLUGIN_NAME, "java", SOURCE_SUFFIXES, javaCompiler) val compiler = CompilerDescription(PLUGIN_NAME, "java", SOURCE_SUFFIXES, javaCompiler)
@ -77,4 +86,12 @@ fun Project.javaCompiler(init: JavaConfig.() -> Unit) =
JavaConfig(this).also { config -> JavaConfig(this).also { config ->
config.init() config.init()
(Kobalt.findPlugin(JavaPlugin.PLUGIN_NAME) as JavaPlugin).addConfiguration(this, config) (Kobalt.findPlugin(JavaPlugin.PLUGIN_NAME) as JavaPlugin).addConfiguration(this, config)
} }
@Directive
fun Project.javadoc(init: JavadocConfig.() -> Unit) =
JavadocConfig(this).also { config ->
config.init()
(Kobalt.findPlugin(JavaPlugin.PLUGIN_NAME) as JavaPlugin).addJavadocConfiguration(this, config)
}

View file

@ -0,0 +1,603 @@
package com.beust.kobalt.plugin.java
import com.beust.kobalt.api.Project
import com.google.inject.Singleton
import java.io.BufferedReader
import java.io.File
import java.io.InputStream
import java.io.InputStreamReader
import java.util.concurrent.TimeUnit
@Singleton
class JavadocConfig(val project: Project) {
val args = arrayListOf("-Xdoclint:none", "-Xmaxerrs", "1", "-quiet")
private fun removeArg(match: String, startsWith: Boolean = false, pair: Boolean = false) {
val it = args.iterator()
while (it.hasNext()) {
val next = it.next()
var removed = false
if (startsWith) {
if (next.startsWith(match)) {
it.remove()
removed = true
}
} else if (next == match) {
it.remove()
removed = true
}
// If it's a pair, delete the next arg too.
if (pair && removed && it.hasNext()) {
it.next()
it.remove()
}
}
}
private fun addInt(option: String, value: Int): Int {
args.add("-$option")
args.add(value.toString())
return value
}
private fun addBoolean(option: String, value: Boolean): Boolean {
args.remove("-$option")
if (value) {
args.add("-$option")
}
return value
}
private fun addString(option: String, value: String): String {
if (value.isNotEmpty()) {
args.add("-$option")
args.add("\"$value\"")
}
return value
}
private fun addStrings(option: String, vararg value: String) {
value.forEach {
addString(option, it)
}
}
private fun addPair(option: String, first: String, second: String) {
if (first.isNotEmpty() && second.isNotEmpty()) {
args.add("-$option")
args.add("\"$first\"")
args.add("\"$second\"")
}
}
private fun addFile(option: String, value: String): String {
val f = File(value)
if (f.exists()) {
args.add("-$option")
args.add("\"${f.absolutePath}\"")
}
return value
}
/**
* Set arguments manually.
*/
fun args(vararg options: String) = args.addAll(options)
//
// Jvm Options
//
/**
* @see <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html">-Xdoclint</a>
*/
var docLint: String = "none"
set(value) {
removeArg("-Xdoclint:", startsWith = true)
addString("Xdoclint:", value)
}
/**
* @see <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html">-Xmaxerrs</a>
*/
var maxErrs: Int = 1
set(value) {
removeArg("-Xmaxerrs", startsWith = true, pair = true)
addInt("Xmaxerrs", value)
}
/**
* @see <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html">-Xmaxwarns</a>
*/
var maxWarns: Int = 1
set(value) {
removeArg("-Xmaxwarns", startsWith = true, pair = true)
addInt("Xmaxwarns", value)
}
//
// Javadoc Options
//
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#BEJICGGH">-overview</a>
*/
var overview: String = ""
set(value) {
addFile("overview", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDCHFEB">-public</a>
*/
var public: Boolean = false
set(value) {
addBoolean("public", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDCIFFD">-protected</a>
*/
var protected: Boolean = false
set(value) {
addBoolean("protected", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDEDJJJ">-pakage</a>
*/
var pkg: Boolean = false
set(value) {
addBoolean("package", pkg)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDJDFJG">-private</a>
*/
var private: Boolean = false
set(value) {
addBoolean("private", private)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDCGDCA">-doclet</a>
*/
var doclet: String = ""
set(value) {
addString("doclet", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDBGIED">-docletpath</a>
*/
var docletPath: String = ""
set(value) {
addString("docletpath", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDBGDFI">-source</a>
*/
var source: String = ""
set(value) {
addString("source", source)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDEHCDG">-sourcepath</a>
*/
var sourcePath: String = ""
set(value) {
addString("sourcepath", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGAHAJ">-classpath</a>
*/
var classPath: String = ""
set(value) {
addString("classpath", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDJEDJI">-subpackages</a>
*/
var subPackages: String = ""
set(value) {
addString("subpackages", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFBDCF">-exclude</a>
*/
var exclude: String = ""
set(value) {
addString("exclude", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDHDACA">-bootClassPath</a>
*/
var bootClassPath: String = ""
set(value) {
addString("bootclasspath", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDCJGIC">-extdirs</a>
*/
var extDirs: String = ""
set(value) {
addString("extdirs", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGHFJJ">-verbose</a>
*/
var verbose: Boolean = false
set(value) {
addBoolean("verbose", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGFHAA">-quiet</a>
*/
var quiet: Boolean = true
set(value) {
addBoolean("quiet", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDHHIDI">-breakiterator</a>
*/
var breakIterator: Boolean = false
set(value) {
addBoolean("breakiterator", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDEBGCE">-locale</a>
*/
var locale: String = ""
set(value) {
addString("locale", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDEIGDC">-encoding</a>
*/
var encoding: String = ""
set(value) {
addString("encoding", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGDEEE">-Jflag</a>
*/
var jFlag: String = ""
set(value) {
addString("J-", value)
}
//
// Standard Doclet
//
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGCJEG">-use</a>
*/
var use: Boolean = false
set(value) {
addBoolean("use", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGCEFG">-version</a>
*/
var version: Boolean = false
set(value) {
addBoolean("version", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDCBHDB">-author</a>
*/
var author: Boolean = false
set(value) {
addBoolean("author", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFGBHB">-splitindex</a>
*/
var splitIndex: Boolean = false
set(value) {
addBoolean("splitindex", value)
}
/**
* Set both the [windowTitle] and [docTitle]
*/
var title: String = ""
set(value) {
windowTitle = value
docTitle = value
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDBIEEI">-windowtitle</a>
*/
var windowTitle: String = ""
set(value) {
addString("windowtitle", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDJGBIE">-doctitle</a>
*/
var docTitle: String = ""
set(value) {
addString("doctitle", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDDAEGD">-header</a>
*/
var header: String = ""
set(value) {
addString("header", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFACCA">-footer</a>
*/
var footer: String = ""
set(value) {
addString("footer", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDHHGBF">-top</a>
*/
var top: String = ""
set(value) {
addString("top", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDECAJE">-bottom</a>
*/
var bottom: String = ""
set(value) {
addString("bottom", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFBBID">-linksource</a>
*/
var linkSource: Boolean = false
set(value) {
addBoolean("linksource", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDCDFGD">-nodeprecated</a>
*/
var noDeprecated: Boolean = false
set(value) {
addBoolean("nodeprecated", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGFHJJ">-nodeprecatedlist</a>
*/
var noDeprecatedList: Boolean = false
set(value) {
addBoolean("nodeprecatedlist", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFICFB">-nosince</a>
*/
var noSince: Boolean = false
set(value) {
addBoolean("nosince", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDBGJBI">-notree</a>
*/
var noTree: Boolean = false
set(value) {
addBoolean("notree", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDHHHEI">-noindex</a>
*/
var noIndex: Boolean = false
set(value) {
addBoolean("noindex", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDHHDBI">-nohelp</a>
*/
var noHelp: Boolean = false
set(value) {
addBoolean("nohelp", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDEDCCG">-nonavbar</a>
*/
var noNavBar: Boolean = false
set(value) {
addBoolean("nonavbar", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDJICID">-helpfile</a>
*/
var helpFile: String = ""
set(value) {
addFile("helpfile", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#BEJFCAIH">-stylesheet</a>
*/
var stylesheet: String = ""
set(value) {
addFile("stylesheet", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFJAFC">-serialwarn</a>
*/
var serialWarn: Boolean = false
set(value) {
addBoolean("serialwarn", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDHDEAD">-charset</a>
*/
var charSet: String = ""
set(value) {
addString("charset", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGIHCH">-docencoding</a>
*/
var docEncoding: String = ""
set(value) {
addString("docencoding", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDBHIGE">-keywords</a>
*/
var keywords: Boolean = false
set(value) {
addBoolean("keywords", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDJFHDG">-tagletpath</a>
*/
var tagletPath: String = ""
set(value) {
addString("tagletpath", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDCBDHI">-docfilessubdirs</a>
*/
var docFilesSubDirs: Boolean = false
set(value) {
addBoolean("docfilessubdirs", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGHIAE">-excludedocfilessubdir</a>
*/
var excludeDocFilesSubDir: String = ""
set(value) {
addString("excludedocfilessubdir", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFJFBE">-noqualifiers</a>
*/
var noQualifiers: String = ""
set(value) {
addString("noqualifier", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDGBABE">-notimestamp</a>
*/
var noTimestamp: Boolean = false
set(value) {
addBoolean("notimestamp", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFCGJD">-nocomment</a>
*/
var noComment: Boolean = false
set(value) {
addBoolean("nocomment", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDIAGAG">-sourcetab</a>
*/
var sourceTab: String = ""
set(value) {
addString("sourcetab", value)
}
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDIGGII">-group</a>
*/
fun group(groupHeading: String, packagePattern: String) = addPair("group", groupHeading, packagePattern)
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDFIIJH">-linkoffline</a>
*/
fun linkOffline(extdocURL: String, packagelistLoc: String) = addPair("linkoffline", extdocURL, packagelistLoc)
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDEDJFI">-link</a>
*/
fun links(vararg links: String) = addStrings("link", *links)
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#tag">-tag</a>
*/
fun tags(vararg tags: String) = addStrings("tag", *tags)
/**
* @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#CHDHEFHH">-taglets</a>
*/
fun taglets(vararg taglets: String) = addStrings("taglet", *taglets)
}
fun main(args: Array<String>) {
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)
println(line)
line = br.readLine()
}
return result
}
val config = JavadocConfig(Project())
config.title = "This is a test."
config.verbose = true
config.quiet = false
config.links("http://docs.oracle.com/javase/8/docs/api/")
config.args.add(0, ".\\kobaltBuild\\docs\\javadoc")
config.args.add(0, "-d")
config.args.add(0, "javadoc")
config.args.add(".\\modules\\wrapper\\src\\main\\java\\com\\beust\\kobalt\\wrapper\\Config.java")
config.args.add(".\\modules\\wrapper\\src\\main\\java\\com\\beust\\kobalt\\wrapper\\Main.java")
println(config.args.joinToString(" "))
val pb = ProcessBuilder().command(config.args.toList())
pb.directory(File("."))
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()
}

View file

@ -8,10 +8,12 @@ import com.beust.kobalt.maven.dependency.FileDependency
import com.beust.kobalt.misc.* import com.beust.kobalt.misc.*
import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.ICReporter import org.jetbrains.kotlin.incremental.ICReporter
import org.jetbrains.kotlin.incremental.makeIncrementally import org.jetbrains.kotlin.incremental.makeIncrementally
@ -35,7 +37,8 @@ class KotlinCompiler @Inject constructor(
val settings: KobaltSettings, val settings: KobaltSettings,
val jvmCompiler: JvmCompiler, val jvmCompiler: JvmCompiler,
val compilerUtils: CompilerUtils, val compilerUtils: CompilerUtils,
val kobaltLog: ParallelLogger) { val kobaltLog: ParallelLogger,
val jvm: Jvm) {
val compilerAction = object: ICompilerAction { val compilerAction = object: ICompilerAction {
override fun compile(project: Project?, info: CompilerActionInfo): TaskResult { override fun compile(project: Project?, info: CompilerActionInfo): TaskResult {
@ -44,14 +47,16 @@ class KotlinCompiler @Inject constructor(
var filesToCompile = 0 var filesToCompile = 0
if (! info.outputDir.path.endsWith("ript.jar")) { if (! info.outputDir.path.endsWith("ript.jar")) {
// Don't display the message if compiling Build.kt // Don't display the message if compiling Build.kt
filesToCompile = if (info.sourceFiles.isNotEmpty()) {
info.sourceFiles.map(::File).map { filesToCompile =
if (it.isDirectory) KFiles.findRecursively(it).size else 1 info.sourceFiles.map(::File).map {
}.reduce { a, b -> if (it.isDirectory) KFiles.findRecursively(it).size else 1
a + b }.reduce { a, b ->
} a + b
kobaltLog.log(projectName ?: "", 1, }
" Kotlin $version compiling " + Strings.pluralizeAll(filesToCompile, "file")) kobaltLog.log(projectName ?: "", 1,
" Kotlin $version compiling " + Strings.pluralizeAll(filesToCompile, "file"))
}
} }
val cp = compilerFirst(info.dependencies.map { it.jarFile.get() }) val cp = compilerFirst(info.dependencies.map { it.jarFile.get() })
val infoDir = info.directory val infoDir = info.directory
@ -69,35 +74,25 @@ class KotlinCompiler @Inject constructor(
File(outputDir).parentFile.mkdirs() File(outputDir).parentFile.mkdirs()
} }
val classpath = cp.joinToString(File.pathSeparator) val classpath = cp.joinToString(File.pathSeparator)
val allArgs = arrayListOf(
"-d", outputDir,
"-classpath", classpath,
*(info.compilerArgs.toTypedArray()),
*(info.sourceFiles.toTypedArray())
)
// Get rid of annoying and useless warning
if (! info.compilerArgs.contains("-no-stdlib")) {
allArgs.add("-no-stdlib")
}
// If the Kotlin compiler version in settings.xml is different from the default, we // If the Kotlin compiler version in settings.xml is different from the default, we
// need to spawn a Kotlin compiler in a separate process. Otherwise, we can just invoke // need to spawn a Kotlin compiler in a separate process. Otherwise, we can just invoke
// the K2JVMCompiler class directly // the K2JVMCompiler class directly
val actualVersion = kotlinVersion(project) val actualVersion = kotlinVersion(project)
if (settings.kobaltCompilerSeparateProcess || actualVersion != Constants.KOTLIN_COMPILER_VERSION) { return if (settings.kobaltCompilerSeparateProcess || actualVersion != Constants.KOTLIN_COMPILER_VERSION
return invokeCompilerInSeparateProcess(classpath, info, actualVersion, project) || info.compilerSeparateProcess) {
invokeCompilerInSeparateProcess(classpath, info, actualVersion, project)
} else { } else {
return invokeCompilerDirectly(projectName ?: "kobalt-" + Random().nextInt(), outputDir, invokeCompilerDirectly(project, projectName ?: "kobalt-" + Random().nextInt(), outputDir,
info, classpath, filesToCompile) info, classpath, filesToCompile)
} }
} }
private fun invokeCompilerInSeparateProcess(classpath: String, info: CompilerActionInfo, private fun invokeCompilerInSeparateProcess(classpath: String, info: CompilerActionInfo,
compilerVersion: String, project: Project?): TaskResult { compilerVersion: String, project: Project?): TaskResult {
val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable val java = jvm.javaExecutable
val compilerClasspath = compilerDep(compilerVersion).jarFile.get().path + File.pathSeparator + val compilerClasspath = compilerDep(compilerVersion).jarFile.get().path + File.pathSeparator +
compilerEmbeddableDependencies(null, compilerVersion).map { it.jarFile.get().path } compilerEmbeddableDependencies(null, compilerVersion).map { it.jarFile.get().path }
@ -107,37 +102,60 @@ class KotlinCompiler @Inject constructor(
.filterNotNull() .filterNotNull()
.joinToString(" ") .joinToString(" ")
val xFlagsArray = xFlagsString.split(" ").toTypedArray() ?: emptyArray() val infoDir = info.directory
val outputDir =
if (infoDir != null) {
KFiles.joinDir(infoDir, info.outputDir.path)
} else {
info.outputDir.path
}
val xFlagsArray = xFlagsString.split(" ").toTypedArray()
val newArgs = listOf( val newArgs = listOf(
"-classpath", compilerClasspath, "-classpath", compilerClasspath,
K2JVMCompiler::class.java.name, K2JVMCompiler::class.java.name,
*info.compilerArgs.toTypedArray(),
"-classpath", classpath, "-classpath", classpath,
"-d", info.outputDir.absolutePath, "-d", outputDir,
*xFlagsArray, *xFlagsArray,
*info.sourceFiles.toTypedArray()) *info.sourceFiles.toTypedArray())
.filter { ! it.isEmpty() } .filter { ! it.isEmpty() }
log(2, " Invoking separate kotlinc:\n " + java!!.absolutePath + " " + newArgs.joinToString()) log(2, " Invoking separate kotlinc:\n " + java!!.absolutePath + " " + newArgs.joinToString(" "))
val result = NewRunCommand(RunCommandInfo().apply { val result = NewRunCommand(RunCommandInfo().apply {
command = java.absolutePath command = java.absolutePath
args = newArgs args = newArgs
directory = File(".") directory = File(".")
// The Kotlin compiler issues warnings on stderr :-( // // The Kotlin compiler issues warnings on stderr :-(
containsErrors = { errors: List<String> -> errors.any { it.contains("rror")} } useErrorStreamAsErrorIndicator = false
// containsErrors = {
// errors: List<String> -> errors.any { it.contains("rror")}
// }
}).invoke() }).invoke()
return TaskResult(result == 0, "Error while compiling") return TaskResult(result == 0, errorMessage = "Error while compiling")
} }
private fun invokeCompilerDirectly(projectName: String, outputDir: String?, info: CompilerActionInfo, private fun invokeCompilerDirectly(project: Project?, projectName: String, outputDir: String?,
classpathString: String, filesToCompile: Int): TaskResult { info: CompilerActionInfo, classpathString: String, filesToCompile: Int): TaskResult {
val sourceFiles = info.sourceFiles val sourceFiles = info.sourceFiles
val friends = info.friendPaths.toTypedArray() val friends = info.friendPaths.toTypedArray()
val args = K2JVMCompilerArguments().apply {
// Collect the compiler args from kotlinCompiler{} and from settings.xml and parse them
val args2 =
info.compilerArgs +
(settings.kobaltCompilerFlags?.split(" ") ?: listOf())
val args = K2JVMCompilerArguments()
val compiler = K2JVMCompiler()
parseCommandLineArguments(args2, args)
// Override important arguments with our values
args.apply {
moduleName = projectName moduleName = projectName
destination = outputDir destination = outputDir
classpath = classpathString classpath = classpathString
freeArgs = sourceFiles freeArgs = sourceFiles.toMutableList()
friendPaths = friends friendPaths = friends
} }
@ -161,12 +179,12 @@ class KotlinCompiler @Inject constructor(
"single-module" -> args.singleModule = true "single-module" -> args.singleModule = true
"load-builtins-from-dependencies" -> args.loadBuiltInsFromDependencies = true "load-builtins-from-dependencies" -> args.loadBuiltInsFromDependencies = true
"coroutines=enable" -> args.coroutinesEnable = true "coroutines=enable" -> args.coroutinesState = LanguageFeature.State.ENABLED.name
"coroutines=warn" -> args.coroutinesWarn = true "coroutines=warn" -> args.coroutinesState = LanguageFeature.State.ENABLED_WITH_WARNING.name
"coroutines=error" -> args.coroutinesError = true "coroutines=error" -> args.coroutinesState = LanguageFeature.State.ENABLED_WITH_ERROR.name
"no-inline" -> args.noInline = true "no-inline" -> args.noInline = true
"multi-platform" -> args.multiPlatform = true "multi-platform" -> args.multiPlatform = true
"no-check-impl" -> args.noCheckImpl = true // "no-check-impl" -> args.noCheckImpl = true
else -> warn("Unknown Kotlin compiler flag found in config.xml: $it") else -> warn("Unknown Kotlin compiler flag found in config.xml: $it")
} }
} }
@ -176,13 +194,27 @@ class KotlinCompiler @Inject constructor(
fun logk(level: Int, message: CharSequence) = kobaltLog.log(projectName, level, message) fun logk(level: Int, message: CharSequence) = kobaltLog.log(projectName, level, message)
logk(2, " Invoking K2JVMCompiler with arguments:" fun pluginClasspaths(args: K2JVMCompilerArguments) : String {
var result = ""
args.pluginClasspaths?.forEach {
result += " -Xplugin " + it
}
args.pluginOptions?.let {
result += " -P "
result += it.joinToString(",")
}
return result
}
logk(2, " Invoking K2JVMCompiler with arguments: kotlinc "
+ if (args.skipMetadataVersionCheck) " -Xskip-metadata-version-check" else "" + if (args.skipMetadataVersionCheck) " -Xskip-metadata-version-check" else ""
+ " -moduleName " + args.moduleName
+ " -d " + args.destination + " -d " + args.destination
+ " -friendPaths " + args.friendPaths.joinToString(";")
+ " -classpath " + args.classpath + " -classpath " + args.classpath
+ pluginClasspaths(args)
+ " " + sourceFiles.joinToString(" ")) + " " + sourceFiles.joinToString(" "))
logk(2, " Additional kotlinc arguments: "
+ " -moduleName " + args.moduleName
+ " -friendPaths " + args.friendPaths?.joinToString(";"))
val collector = object : MessageCollector { val collector = object : MessageCollector {
override fun clear() { override fun clear() {
throw UnsupportedOperationException("not implemented") throw UnsupportedOperationException("not implemented")
@ -193,7 +225,7 @@ class KotlinCompiler @Inject constructor(
} }
fun dump(location: CompilerMessageLocation?, s: String) = fun dump(location: CompilerMessageLocation?, s: String) =
if (location != null && location.lineContent != null) { if (location?.lineContent != null) {
with(location) { with(location) {
"$lineContent\n$path:$line:$column $s" "$lineContent\n$path:$line:$column $s"
} }
@ -201,12 +233,13 @@ class KotlinCompiler @Inject constructor(
s s
} }
override fun report(severity: CompilerMessageSeverity, override fun report(severity: CompilerMessageSeverity, message: String,
message: String, location: CompilerMessageLocation) { location: CompilerMessageLocation?) {
if (severity.isError) { if (severity.isError) {
"Couldn't compile file: ${dump(location, message)}".let { fullMessage -> "Couldn't compile file: ${dump(location, message)}".let { fullMessage ->
System.err.println(fullMessage) error(fullMessage)
throw KobaltException(fullMessage) val ex = KobaltException(fullMessage)
throw ex
} }
} else if (severity == CompilerMessageSeverity.WARNING && KobaltLogger.LOG_LEVEL >= 2) { } else if (severity == CompilerMessageSeverity.WARNING && KobaltLogger.LOG_LEVEL >= 2) {
warn(dump(location, message)) warn(dump(location, message))
@ -215,29 +248,27 @@ class KotlinCompiler @Inject constructor(
} }
} }
} }
//
// System.setProperty("kotlin.incremental.compilation", "true")
// // TODO: experimental should be removed as soon as it becomes standard
// System.setProperty("kotlin.incremental.compilation.experimental", "true")
System.setProperty("kotlin.incremental.compilation", "true") return if (cliArgs.noIncrementalKotlin || Kobalt.context?.internalContext?.noIncrementalKotlin ?: false) {
// TODO: experimental should be removed as soon as it becomes standard log(2, " Kotlin incremental compilation is disabled")
System.setProperty("kotlin.incremental.compilation.experimental", "true") val duration = benchmarkMillis {
compiler.exec(collector, Services.Builder().build(), args)
val result =
if (cliArgs.noIncrementalKotlin || Kobalt.context?.internalContext?.noIncrementalKotlin ?: false) {
log(2, " Kotlin incremental compilation is disabled")
val duration = benchmarkMillis {
K2JVMCompiler().exec(collector, Services.Builder().build(), args)
}
log(1, " Regular compilation time: ${duration.first} ms")
TaskResult(duration.second == ExitCode.OK)
} else {
log(1, " Kotlin incremental compilation is enabled")
val start = System.currentTimeMillis()
val duration = benchmarkMillis {
compileIncrementally(filesToCompile, sourceFiles, outputDir, info, args, collector)
}
log(1, " Incremental compilation time: ${duration.first} ms")
TaskResult()
} }
return result log(1, " Regular compilation time: ${duration.first} ms")
TaskResult(duration.second == ExitCode.OK)
} else {
log(1, " Kotlin incremental compilation is enabled")
//val start = System.currentTimeMillis()
val duration = benchmarkMillis {
compileIncrementally(filesToCompile, sourceFiles, outputDir, info, args, collector)
}
log(1, " Incremental compilation time: ${duration.first} ms")
TaskResult()
}
} }
private fun compileIncrementally(filesToCompile: Int, sourceFiles: List<String>, outputDir: String?, private fun compileIncrementally(filesToCompile: Int, sourceFiles: List<String>, outputDir: String?,
@ -351,8 +382,7 @@ class KotlinCompiler @Inject constructor(
= dependencyManager.create("org.jetbrains" + ".kotlin:kotlin-compiler-embeddable:$version") = dependencyManager.create("org.jetbrains" + ".kotlin:kotlin-compiler-embeddable:$version")
fun compilerEmbeddableDependencies(project: Project?, version: String): List<IClasspathDependency> { fun compilerEmbeddableDependencies(project: Project?, version: String): List<IClasspathDependency> {
val deps = dependencyManager.transitiveClosure(listOf(compilerDep(version)), requiredBy = project?.name ?: "") return dependencyManager.transitiveClosure(listOf(compilerDep(version)), requiredBy = project?.name ?: "")
return deps
} }
/** /**
@ -361,7 +391,8 @@ class KotlinCompiler @Inject constructor(
* JvmCompilerPlugin#createCompilerActionInfo instead * JvmCompilerPlugin#createCompilerActionInfo instead
*/ */
fun compile(project: Project?, context: KobaltContext?, compileDependencies: List<IClasspathDependency>, fun compile(project: Project?, context: KobaltContext?, compileDependencies: List<IClasspathDependency>,
otherClasspath: List<String>, sourceFiles: List<String>, outputDir: File, args: List<String>) : TaskResult { otherClasspath: List<String>, sourceFiles: List<String>, outputDir: File, args: List<String>,
compilerSeparateProcess: Boolean) : TaskResult {
val executor = executors.newExecutor("KotlinCompiler", 10) val executor = executors.newExecutor("KotlinCompiler", 10)
@ -384,13 +415,15 @@ class KotlinCompiler @Inject constructor(
if (project != null) { if (project != null) {
listOf(KFiles.joinDir(project.directory, project.buildDirectory, KFiles.CLASSES_DIR)) listOf(KFiles.joinDir(project.directory, project.buildDirectory, KFiles.CLASSES_DIR))
} else { } else {
emptyList<String>() emptyList()
} }
val info = CompilerActionInfo(project?.directory, dependencies, sourceFiles, listOf("kt"), outputDir, args, val info = CompilerActionInfo(project?.directory, dependencies, sourceFiles, listOf("kt"), outputDir, args,
friendPaths, context?.internalContext?.forceRecompile ?: false) friendPaths, context?.internalContext?.forceRecompile ?: false, compilerSeparateProcess)
return jvmCompiler.doCompile(project, context, compilerAction, info, val compilerFlags =
if (context != null) compilerUtils.sourceCompilerFlags(project, context, info) else emptyList()) if (context != null) compilerUtils.sourceCompilerFlags(project, context, info)
else emptyList()
return jvmCompiler.doCompile(project, context, compilerAction, info, compilerFlags)
} }
} }
@ -401,6 +434,7 @@ class KConfiguration @Inject constructor(val compiler: KotlinCompiler){
var output: File by Delegates.notNull() var output: File by Delegates.notNull()
val args = arrayListOf<String>() val args = arrayListOf<String>()
var noIncrementalKotlin = false var noIncrementalKotlin = false
var compilerSeparateProcess = false
fun sourceFiles(s: String) = source.add(s) fun sourceFiles(s: String) = source.add(s)
@ -415,7 +449,8 @@ class KConfiguration @Inject constructor(val compiler: KotlinCompiler){
fun compile(project: Project? = null, context: KobaltContext? = null) : TaskResult { fun compile(project: Project? = null, context: KobaltContext? = null) : TaskResult {
val saved = context?.internalContext?.noIncrementalKotlin ?: false val saved = context?.internalContext?.noIncrementalKotlin ?: false
if (context != null) context.internalContext.noIncrementalKotlin = noIncrementalKotlin if (context != null) context.internalContext.noIncrementalKotlin = noIncrementalKotlin
val result = compiler.compile(project, context, dependencies, classpath, source, output, args) val result = compiler.compile(project, context, dependencies, classpath, source, output, args,
compilerSeparateProcess)
if (context != null) context.internalContext.noIncrementalKotlin = saved if (context != null) context.internalContext.noIncrementalKotlin = saved
return result return result
} }

View file

@ -83,6 +83,7 @@ class KotlinPlugin @Inject constructor(val executors: KobaltExecutors, val depen
sourceFiles(info.sourceFiles) sourceFiles(info.sourceFiles)
compilerArgs(info.compilerArgs) compilerArgs(info.compilerArgs)
output = info.outputDir output = info.outputDir
compilerSeparateProcess = info.compilerSeparateProcess
}.compile(project, context) }.compile(project, context)
} }
@ -98,9 +99,10 @@ class KotlinPlugin @Inject constructor(val executors: KobaltExecutors, val depen
// IClasspathContributor // IClasspathContributor
override fun classpathEntriesFor(project: Project?, context: KobaltContext): List<IClasspathDependency> = override fun classpathEntriesFor(project: Project?, context: KobaltContext): List<IClasspathDependency> =
if (project == null || accept(project)) { if (project == null ||
context.pluginInfo.plugins.any { it is KotlinPlugin && it.settings.kobaltCompilerVersion == null }) {
// All Kotlin projects automatically get the Kotlin runtime added to their class path // All Kotlin projects automatically get the Kotlin runtime added to their class path
listOf(kotlinJarFiles.stdlib, kotlinJarFiles.runtime) listOf(kotlinJarFiles.stdlib)
.map { FileDependency(it.absolutePath) } .map { FileDependency(it.absolutePath) }
} else { } else {
emptyList() emptyList()

View file

@ -0,0 +1,118 @@
package com.beust.kobalt.plugin.osgi
import aQute.bnd.osgi.Analyzer
import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.*
import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.archive.Archives
import com.beust.kobalt.archive.MetaArchive
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.plugin.packaging.PackagingPlugin
import com.google.common.reflect.ClassPath
import com.google.inject.Inject
import com.google.inject.Singleton
import java.io.ByteArrayOutputStream
import java.io.File
import java.net.URLClassLoader
import java.nio.file.*
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.jar.JarFile
/**
* Generate OSGi attributes in the MANIFEST.MF if an osgi{} directive was found in the project.
*/
@Singleton
class OsgiPlugin @Inject constructor(val configActor: ConfigActor<OsgiConfig>, val taskContributor: TaskContributor,
val dependencyManager: DependencyManager)
: BasePlugin(), ITaskContributor by taskContributor, IConfigActor<OsgiConfig> by configActor {
companion object {
const val PLUGIN_NAME = "Osgi"
}
override val name: String = PLUGIN_NAME
override fun apply(project: Project, context: KobaltContext) {
super.apply(project, context)
configurationFor(project)?.let { config ->
taskContributor.addTask(this, project, "generateOsgiManifest",
description = "Generate the OSGi information in the manifest",
group = "build",
alwaysRunAfter = listOf(PackagingPlugin.TASK_ASSEMBLE),
runTask = { generateManifest(project, context) })
}
}
private fun generateManifest(project: Project, context: KobaltContext): TaskResult {
val jarName = project.projectProperties.get(Archives.JAR_NAME) as String
val jarFile = File(KFiles.libsDir(project), jarName)
val cp = ClassPath.from(URLClassLoader(arrayOf(jarFile.toURI().toURL()), null))
val packages = cp.allClasses.map { it.packageName }.distinct()
val exportPackageLine = packages.map {
it + ";version=\"" + project.version + "\""
}.joinToString(",")
val toFile = Files.createTempFile(null, ".jar")
val analyzer = Analyzer().apply {
jar = aQute.bnd.osgi.Jar(jarName)
val dependencies = project.compileDependencies + project.compileRuntimeDependencies
dependencyManager.calculateDependencies(project, context, passedDependencies = dependencies).forEach {
addClasspath(it.jarFile.get())
}
setProperty("Build-Date", LocalDate.now().format(DateTimeFormatter.ofPattern("y-MM-dd")))
setProperty(Analyzer.BUNDLE_VERSION, project.version)
setProperty(Analyzer.BUNDLE_NAME, project.group + "." + project.artifactId)
setProperty(Analyzer.BUNDLE_DESCRIPTION, project.description)
setProperty(Analyzer.IMPORT_PACKAGE, "*")
setProperty(Analyzer.EXPORT_PACKAGE, exportPackageLine)
project.pom?.let { pom ->
if (pom.licenses.any()) {
setProperty(Analyzer.BUNDLE_LICENSE, pom.licenses[0].url)
}
}
}
analyzer.calcManifest().let { manifest ->
val lines2 = ByteArrayOutputStream().use { baos ->
manifest.write(baos)
String(baos.toByteArray())
}
context.logger.log(project.name, 2, " Generated manifest:\n$lines2")
//
// Update or create META-INF/MANIFEST.MF
//
KFiles.copy(Paths.get(jarFile.toURI()), Paths.get(toFile.toUri()))
val fileSystem = FileSystems.newFileSystem(toFile, null)
fileSystem.use { fs ->
JarFile(jarFile).use { jf ->
val mf = jf.getEntry(MetaArchive.MANIFEST_MF)
if (mf == null) {
Files.createDirectories(fs.getPath("META-INF/"))
}
val jarManifest = fs.getPath(MetaArchive.MANIFEST_MF)
Files.write(jarManifest, listOf(lines2),
if (mf != null) StandardOpenOption.APPEND else StandardOpenOption.CREATE)
}
}
Files.copy(Paths.get(toFile.toUri()), Paths.get(jarFile.toURI()), StandardCopyOption.REPLACE_EXISTING)
return TaskResult()
}
}
}
class OsgiConfig
@Directive
fun Project.osgi(init: OsgiConfig.() -> Unit) {
OsgiConfig().let {
it.init()
(Kobalt.findPlugin(OsgiPlugin.PLUGIN_NAME) as OsgiPlugin).addConfiguration(this, it)
}
}

View file

@ -26,9 +26,9 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
val executors: KobaltExecutors, val jarGenerator: JarGenerator, val warGenerator: WarGenerator, val executors: KobaltExecutors, val jarGenerator: JarGenerator, val warGenerator: WarGenerator,
val zipGenerator: ZipGenerator, val taskContributor: TaskContributor, val zipGenerator: ZipGenerator, val taskContributor: TaskContributor,
val kobaltLog: ParallelLogger, val kobaltLog: ParallelLogger,
val pomFactory: PomGenerator.IFactory, val configActor: ConfigActor<InstallConfig>) val pomFactory: PomGenerator.IFactory, val configActor: ConfigsActor<InstallConfig>)
: BasePlugin(), ITaskContributor, IIncrementalAssemblyContributor, : BasePlugin(), ITaskContributor by taskContributor, IIncrementalAssemblyContributor,
IConfigActor<InstallConfig> by configActor { IConfigsActor<InstallConfig> by configActor {
companion object { companion object {
const val PLUGIN_NAME = "Packaging" const val PLUGIN_NAME = "Packaging"
@ -41,7 +41,6 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
const val PACKAGES = "packages" const val PACKAGES = "packages"
const val TASK_ASSEMBLE: String = "assemble" const val TASK_ASSEMBLE: String = "assemble"
const val TASK_INSTALL: String = "install"
} }
override val name = PLUGIN_NAME override val name = PLUGIN_NAME
@ -56,9 +55,20 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
taskContributor.addVariantTasks(this, project, context, "assemble", group = "build", taskContributor.addVariantTasks(this, project, context, "assemble", group = "build",
dependsOn = listOf("compile"), dependsOn = listOf("compile"),
runTask = { doTaskAssemble(project) }) runTask = { doTaskAssemble(project) })
taskContributor.addVariantTasks(this, project, context, "install",
dependsOn = listOf("assemble"), configurationFor(project)?.let { configs ->
runTask = { taskInstall(project) }) configs.forEach { config ->
taskContributor.addTask(this, project, config.taskName,
description = "Install to \"" + config.target + "\"",
group = "build",
dependsOn = listOf(PackagingPlugin.TASK_ASSEMBLE),
runTask = { taskInstall(project, context, config) })
taskContributor.addVariantTasks(this, project, context, config.taskName,
dependsOn = listOf("assemble"),
runTask = { taskInstall(project, context, config) })
}
}
} }
override fun assemble(project: Project, context: KobaltContext) : IncrementalTaskInfo { override fun assemble(project: Project, context: KobaltContext) : IncrementalTaskInfo {
@ -95,7 +105,7 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
val outputFile = jarGenerator.fullArchiveName(project, context, it.name) val outputFile = jarGenerator.fullArchiveName(project, context, it.name)
outputFiles.add(outputFile) outputFiles.add(outputFile)
allIncludedFiles.addAll(files) allIncludedFiles.addAll(files)
zipToFiles[it.name] = files zipToFiles[outputFile.name] = files
} }
} }
} }
@ -138,9 +148,7 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
Pair(packageConfig.zips, zipGenerator) Pair(packageConfig.zips, zipGenerator)
) )
pairs.forEach { pair -> pairs.forEach { (zips, generator) ->
val zips = pair.first
val generator = pair.second
zips.forEach { zips.forEach {
generator.generateArchive(packageConfig.project, context, it, generator.generateArchive(packageConfig.project, context, it,
findFiles(generator, it)) findFiles(generator, it))
@ -186,31 +194,7 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
packages.add(p) packages.add(p)
} }
// @Task(name = "generateOsgiManifest", alwaysRunAfter = arrayOf(TASK_ASSEMBLE)) private fun taskInstall(project: Project, context: KobaltContext, config: InstallConfig) : TaskResult {
// fun generateManifest(project: Project): TaskResult {
// val analyzer = Analyzer().apply {
// jar = aQute.bnd.osgi.Jar(project.projectProperties.get(Archives.JAR_NAME) as String)
// val dependencies = project.compileDependencies + project.compileRuntimeDependencies
// dependencyManager.calculateDependencies(project, context, passedDependencies = dependencies).forEach {
// addClasspath(it.jarFile.get())
// }
// setProperty(Analyzer.BUNDLE_VERSION, project.version)
// setProperty(Analyzer.BUNDLE_NAME, project.group)
// setProperty(Analyzer.BUNDLE_DESCRIPTION, project.description)
// setProperty(Analyzer.IMPORT_PACKAGE, "*")
// setProperty(Analyzer.EXPORT_PACKAGE, "*;-noimport:=false;version=" + project.version)
// }
//
// val manifest = analyzer.calcManifest()
// manifest.write(System.out)
// return TaskResult()
// }
@Task(name = PackagingPlugin.TASK_INSTALL, description = "Install the artifacts",
dependsOn = arrayOf(PackagingPlugin.TASK_ASSEMBLE))
fun taskInstall(project: Project) : TaskResult {
val config = configurationFor(project) ?: InstallConfig()
val buildDir = project.projectProperties.getString(LIBS_DIR) val buildDir = project.projectProperties.getString(LIBS_DIR)
val buildDirFile = File(buildDir) val buildDirFile = File(buildDir)
if (buildDirFile.exists()) { if (buildDirFile.exists()) {
@ -241,9 +225,6 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
return TaskResult() return TaskResult()
} }
//ITaskContributor
override fun tasksFor(project: Project, context: KobaltContext): List<DynamicTask> = taskContributor.dynamicTasks
} }
@Directive @Directive
@ -254,7 +235,7 @@ fun Project.install(init: InstallConfig.() -> Unit) {
} }
} }
class InstallConfig(var target : String = "libs") : IncludeFromTo() class InstallConfig(var target : String = "libs", var taskName : String = "install") : IncludeFromTo()
@Directive @Directive
fun Project.assemble(init: PackageConfig.(p: Project) -> Unit): PackageConfig = let { fun Project.assemble(init: PackageConfig.(p: Project) -> Unit): PackageConfig = let {

View file

@ -11,9 +11,7 @@ import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.google.inject.Inject import com.google.inject.Inject
import java.io.File import java.io.File
import java.io.OutputStream
import java.nio.file.Paths import java.nio.file.Paths
import java.util.jar.JarOutputStream
class WarGenerator @Inject constructor(val dependencyManager: DependencyManager, val kobaltLog: ParallelLogger) class WarGenerator @Inject constructor(val dependencyManager: DependencyManager, val kobaltLog: ParallelLogger)
: ArchiveGenerator { : ArchiveGenerator {
@ -86,9 +84,8 @@ class WarGenerator @Inject constructor(val dependencyManager: DependencyManager,
manifest.mainAttributes.putValue(attribute.first, attribute.second) manifest.mainAttributes.putValue(attribute.first, attribute.second)
} }
val jarFactory = { os: OutputStream -> JarOutputStream(os, manifest) }
return Archives.generateArchive(project, context, war.name, ".war", files, return Archives.generateArchive(project, context, war.name, ".war", files,
false /* don't expand jar files */, jarFactory) false /* don't expand jar files */, manifest)
} }
} }

View file

@ -15,6 +15,7 @@ import com.google.gson.Gson
import com.google.gson.JsonArray import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.TypeAdapter import com.google.gson.TypeAdapter
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.google.inject.assistedinject.Assisted import com.google.inject.assistedinject.Assisted
import okhttp3.* import okhttp3.*
@ -62,7 +63,7 @@ class BintrayApi @Inject constructor(val http: Http,
@Path("publish") publish: Int, @Path("publish") publish: Int,
@Body file: File): Call<BintrayResponse> @Body file: File): Call<BintrayResponse>
class UpdateVersion(val desc: String?, val vcsTag: String?) class UpdateVersion(val desc: String?, @SerializedName("vcs_tag") val vcsTag: String?)
@PATCH("/packages/{owner}/maven/{repo}/versions/{version}") @PATCH("/packages/{owner}/maven/{repo}/versions/{version}")
fun updateVersion(@Path("owner") owner: String, fun updateVersion(@Path("owner") owner: String,
@ -79,12 +80,12 @@ class BintrayApi @Inject constructor(val http: Http,
// level = HttpLoggingInterceptor.Level.BASIC // level = HttpLoggingInterceptor.Level.BASIC
// }) // })
builder.interceptors().add(Interceptor { chain -> builder.interceptors().add(Interceptor { chain ->
val original = chain.request(); val original = chain.request()
chain.proceed(original.newBuilder() chain.proceed(original.newBuilder()
.header("Authorization", Credentials.basic(username, password)) .header("Authorization", Credentials.basic(username, password))
.method(original.method(), original.body()) .method(original.method(), original.body())
.build()); .build())
}) })
val okHttpClient = builder.build() val okHttpClient = builder.build()
@ -96,25 +97,29 @@ class BintrayApi @Inject constructor(val http: Http,
.create(Api::class.java) .create(Api::class.java)
} }
fun validatePackage(project: Project) { fun validatePackage(project: Project, config: BintrayConfig) {
val execute = service.getPackage(org ?: username!!, project.name).execute() val pkgName = config.name ?: project.name
val execute = service.getPackage(org ?: username!!, pkgName).execute()
if (execute.errorBody()?.string()?.contains("'${project.name}' was not found") ?: false) { if (execute.errorBody()?.string()?.contains("'$pkgName' was not found") == true) {
warn("Package does not exist on bintray. Creating now.") warn("Package does not exist on bintray. Creating now.")
val result = service.createPackage(org ?: username!!, buildPackageInfo(project)) val result = service.createPackage(org ?: username!!, buildPackageInfo(project, config))
.execute() .execute()
if (result.errorBody() != null) { if (result.errorBody() != null) {
throw KobaltException("Error while creating package:\n" + result.errorBody().string()) throw KobaltException("Error while creating package:\n" + result.errorBody()!!.string())
} }
} }
} }
private fun buildPackageInfo(project: Project): JsonObject { private fun buildPackageInfo(project: Project, config: BintrayConfig): JsonObject {
val jsonObject = JsonObject() val jsonObject = JsonObject().apply {
jsonObject.addNonNull("name", project.name) addNonNull("name", config.name ?: project.name)
jsonObject.addNonNull("desc", project.description) addNonNull("desc",
jsonObject.addNonNull("vcs_url", project.pom?.scm?.url) if (project.description.isNotBlank()) project.description else project.pom?.description)
jsonObject.addNonNull("website_url", project.url) addNonNull("vcs_url", project.pom?.scm?.url)
addNonNull("website_url", project.url ?: project.pom?.url)
addNonNull("issue_tracker_url", config.issueTrackerUrl)
}
val licenses = JsonArray() val licenses = JsonArray()
project.pom?.licenses?.forEach { project.pom?.licenses?.forEach {
licenses.add(it.name) licenses.add(it.name)
@ -124,7 +129,7 @@ class BintrayApi @Inject constructor(val http: Http,
} }
fun uploadMaven(project: Project, files: List<File>, config: BintrayConfig): TaskResult { fun uploadMaven(project: Project, files: List<File>, config: BintrayConfig): TaskResult {
validatePackage(project) validatePackage(project, config)
return upload(project, files, config, generateMd5 = true) return upload(project, files, config, generateMd5 = true)
} }
@ -158,13 +163,13 @@ class BintrayApi @Inject constructor(val http: Http,
fun dots(total: Int, list: List<Boolean>, file: File? = null): String { fun dots(total: Int, list: List<Boolean>, file: File? = null): String {
val spaces: String = Array(total - list.size, { " " }).joinToString("") val spaces: String = Array(total - list.size, { " " }).joinToString("")
return "|" + list.map { if (it) "." else "X" }.joinToString("") + spaces + return "|" + list.joinToString("") { if (it) "." else "X" } + spaces +
(if (file != null) "| [ $file ]" else "|") (if (file != null) "| [ $file ]" else "|")
} }
val results = arrayListOf<Boolean>() val results = arrayListOf<Boolean>()
val owner = org ?: username!! val owner = org ?: username!!
val repo = project.name val repo = config.name ?: project.name
val group = project.group!!.replace('.', '/') val group = project.group!!.replace('.', '/')
val artifact = project.artifactId!! val artifact = project.artifactId!!
val version = project.version!! val version = project.version!!
@ -203,8 +208,8 @@ class BintrayApi @Inject constructor(val http: Http,
return TaskResult() return TaskResult()
} else { } else {
error(" Errors while uploading:\n" + errorMessages.map { " $it" }.joinToString("\n")) error(" Errors while uploading:\n" + errorMessages.joinToString("\n") { " $it" })
return TaskResult(false, errorMessages.joinToString("\n")) return TaskResult(false, errorMessage = errorMessages.joinToString("\n"))
} }
} else { } else {
warn("Found no artifacts to upload") warn("Found no artifacts to upload")
@ -216,7 +221,7 @@ class BintrayApi @Inject constructor(val http: Http,
fun JsonObject.addNonNull(name: String, value: String?) { fun JsonObject.addNonNull(name: String, value: String?) {
if (value != null) { if (value != null) {
addProperty(name, value); addProperty(name, value)
} }
} }
@ -231,20 +236,16 @@ class ConverterFactory : Converter.Factory() {
override fun requestBodyConverter(type: Type, parameterAnnotations: Array<out Annotation>, override fun requestBodyConverter(type: Type, parameterAnnotations: Array<out Annotation>,
methodAnnotations: Array<out Annotation>, methodAnnotations: Array<out Annotation>,
retrofit: Retrofit?): Converter<*, RequestBody>? { retrofit: Retrofit?): Converter<*, RequestBody>? {
val result = return if (type.typeName == File::class.java.name) FileBodyConverter()
if (type.typeName == File::class.java.name) FileBodyConverter() else GsonBodyConverter()
else GsonBodyConverter()
return result
} }
} }
class GsonResponseBodyConverter(private val gson: Gson, private val adapter: TypeAdapter<out Any>) : Converter<ResponseBody, Any> { class GsonResponseBodyConverter(private val gson: Gson, private val adapter: TypeAdapter<out Any>) : Converter<ResponseBody, Any> {
override fun convert(value: ResponseBody): Any { override fun convert(value: ResponseBody): Any {
val jsonReader = gson.newJsonReader(value.charStream()) val jsonReader = gson.newJsonReader(value.charStream())
try { value.use {
return adapter.read(jsonReader) return adapter.read(jsonReader)
} finally {
value.close()
} }
} }
} }

View file

@ -47,7 +47,7 @@ class PublishPlugin @Inject constructor(val files: KFiles, val factory: PomGener
private fun autoGitTag(project: Project, uploadResult: TaskResult, config: AutoGitTagConfig?) : TaskResult { private fun autoGitTag(project: Project, uploadResult: TaskResult, config: AutoGitTagConfig?) : TaskResult {
if (config != null) { if (config != null) {
with(config) { with(config) {
return git.maybeTagRelease(project, uploadResult, enabled, annotated, tag, message) return git.maybeTagRelease(project, uploadResult, enabled, annotated, push, tag, message)
} }
} else { } else {
return TaskResult() return TaskResult()
@ -117,7 +117,7 @@ class PublishPlugin @Inject constructor(val files: KFiles, val factory: PomGener
val docUrl = DocUrl.PUBLISH_PLUGIN_URL val docUrl = DocUrl.PUBLISH_PLUGIN_URL
val user = localProperties.get(PROPERTY_BINTRAY_USER, docUrl) val user = localProperties.get(PROPERTY_BINTRAY_USER, docUrl)
val password = localProperties.get(PROPERTY_BINTRAY_PASSWORD, docUrl) val password = localProperties.get(PROPERTY_BINTRAY_PASSWORD, docUrl)
val org = localProperties.getNoThrows(PROPERTY_BINTRAY_ORG, docUrl) val org = localProperties.getNoThrows(PROPERTY_BINTRAY_ORG)
val jcenter = bintrayFactory.create(user, password, org) val jcenter = bintrayFactory.create(user, password, org)
var success = false var success = false
@ -153,7 +153,7 @@ class PublishPlugin @Inject constructor(val files: KFiles, val factory: PomGener
TaskResult() TaskResult()
} }
val result = TaskResult(tmpResult.success, messages.joinToString("\n ")) val result = TaskResult(tmpResult.success, errorMessage = messages.joinToString("\n "))
return result return result
} }
@ -222,6 +222,9 @@ data class AutoGitTagConfig(val project: Project) {
@Directive @Directive
var annotated: Boolean = false var annotated: Boolean = false
@Directive
var push: Boolean = true
@Directive @Directive
var tag : String = project.version!! var tag : String = project.version!!
@ -268,9 +271,18 @@ data class BintrayConfig(val project: Project) {
files.add(Pair(filePath, url)) files.add(Pair(filePath, url))
} }
/**
* The package name on Bintray which is not always the project name.
*/
@Directive
var name: String? = null
@Directive @Directive
var description: String? = null var description: String? = null
@Directive
var issueTrackerUrl: String? = null
@Directive @Directive
var vcsTag: String? = null var vcsTag: String? = null
} }

View file

@ -15,6 +15,7 @@
<class-name>com.beust.kobalt.plugin.groovy.GroovyPlugin</class-name> <class-name>com.beust.kobalt.plugin.groovy.GroovyPlugin</class-name>
<class-name>com.beust.kobalt.internal.JvmCompilerPlugin</class-name> <class-name>com.beust.kobalt.internal.JvmCompilerPlugin</class-name>
<class-name>com.beust.kobalt.internal.BuildListeners</class-name> <class-name>com.beust.kobalt.internal.BuildListeners</class-name>
<class-name>com.beust.kobalt.plugin.osgi.OsgiPlugin</class-name>
<!-- These classes manage -init for Java and Kotlin --> <!-- These classes manage -init for Java and Kotlin -->
<class-name>com.beust.kobalt.app.Templates</class-name> <class-name>com.beust.kobalt.app.Templates</class-name>

View file

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

View file

@ -2,36 +2,37 @@ import com.beust.kobalt.*
import com.beust.kobalt.plugin.packaging.* import com.beust.kobalt.plugin.packaging.*
import com.beust.kobalt.plugin.application.* import com.beust.kobalt.plugin.application.*
{{imports}} {{imports}}
{{#repositories.length}}
val bs = buildScript { val bs = buildScript {
repos({{{repositories}}}) repos({{{repositories}}})
} }
{{/repositories.length}}
{{#properties}} {{#properties}}
val {{first}} = "{{second}}" val {{first}} = "{{second}}"
{{/properties}} {{/properties}}
val p = {{directive}} { val p = {{directive}} {
name = "{{name}}" name = "{{name}}"
group = "{{group}}" group = "{{group}}"
artifactId = name artifactId = name
version = "{{version}}" version = "{{version}}"
{{#sourceDirectories.length}}
sourceDirectories { sourceDirectories {
{{#sourceDirectories}} {{#sourceDirectories}}
path("{{toString}}") path("{{toString}}")
{{/sourceDirectories}} {{/sourceDirectories}}
} }
{{/sourceDirectories.length}}
{{#sourceDirectoriesTest.length}}
sourceDirectoriesTest { sourceDirectoriesTest {
{{#sourceDirectoriesTest}} {{#sourceDirectoriesTest}}
path("{{toString}}") path("{{toString}}")
{{/sourceDirectoriesTest}} {{/sourceDirectoriesTest}}
} }
{{/sourceDirectoriesTest.length}}
dependencies { dependencies {
// compile("com.beust:jcommander:1.48") // compile("com.beust:jcommander:1.68")
{{#mainDependencies}} {{#mainDependencies}}
compile("{{groupId}}:{{artifactId}}:{{version}}") compile("{{groupId}}:{{artifactId}}:{{version}}")
{{/mainDependencies}} {{/mainDependencies}}
@ -42,7 +43,6 @@ val p = {{directive}} {
{{#testDependencies}} {{#testDependencies}}
compile("{{groupId}}:{{artifactId}}:{{version}}") compile("{{groupId}}:{{artifactId}}:{{version}}")
{{/testDependencies}} {{/testDependencies}}
} }
assemble { assemble {
@ -53,6 +53,4 @@ val p = {{directive}} {
application { application {
mainClass = "com.example.{{mainClass}}" mainClass = "com.example.{{mainClass}}"
} }
} }

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