Compare commits
56 commits
Author | SHA1 | Date | |
---|---|---|---|
1979f58cb9 | |||
3efcb61eab | |||
b9a694f99a | |||
62b1eeb595 | |||
07e2daff34 | |||
8ba37725ce | |||
f80f6a8e02 | |||
d974896245 | |||
33650647aa | |||
8644298bd9 | |||
451f4a2cdb | |||
211983dab0 | |||
4c8609a765 | |||
f7d5aed088 | |||
1c69c7f2dd | |||
5fdbb91f92 | |||
e3eaeeeeb5 | |||
65de4c3500 | |||
dec06028d4 | |||
e8f4716abb | |||
7c81ee086d | |||
ba1a164cab | |||
05ec79e055 | |||
6b47dfb139 | |||
bb518c02c7 | |||
4dc3b6fb5e | |||
9548ddea23 | |||
f563cffd3f | |||
0a45d5747f | |||
68f3b81a74 | |||
8f4bb51dd2 | |||
df9aee7ca3 | |||
051f744831 | |||
6e8d3c2cd6 | |||
35287d7d6d | |||
e601ffab91 | |||
77d7463b0c | |||
906969525e | |||
d5882eca84 | |||
2a2c81994a | |||
e7d3060649 | |||
8b80ca1bc0 | |||
b1c8c49fbc | |||
9e8479ab30 | |||
013c6a0de6 | |||
1702e10817 | |||
1f85d040e2 | |||
0be91a7ab3 | |||
d1a5f617ed | |||
f061f41123 | |||
cabaef9d2f | |||
eda0df169c | |||
e4412eb1d6 | |||
db12be1c4c | |||
70d266d52e | |||
f73526bc20 |
20 changed files with 593 additions and 261 deletions
21
.github/workflows/bld.yml
vendored
21
.github/workflows/bld.yml
vendored
|
@ -4,29 +4,28 @@ on: [ push, pull_request, workflow_dispatch ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-bld-project:
|
build-bld-project:
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
java-version: [ 17, 20 ]
|
java-version: [ 17, 21, 24 ]
|
||||||
|
kotlin-version: [ 1.9.25, 2.0.21, 2.1.20 ]
|
||||||
|
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source repository
|
- name: Checkout source repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up JDK ${{ matrix.java-version }}
|
- name: Set up JDK ${{ matrix.java-version }}
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: "zulu"
|
||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
|
|
||||||
- name: Grant execute permission for bld
|
- name: Download dependencies
|
||||||
run: chmod +x bld
|
|
||||||
|
|
||||||
- name: Download the dependencies
|
|
||||||
run: ./bld download
|
run: ./bld download
|
||||||
|
|
||||||
- name: Run tests with bld
|
- name: Run tests
|
||||||
run: ./bld compile test
|
run: ./bld compile test
|
57
.github/workflows/pages.yml
vendored
Normal file
57
.github/workflows/pages.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
name: javadocs-pages
|
||||||
|
|
||||||
|
on:
|
||||||
|
# Runs on pushes targeting the default branch
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
# Allow one concurrent deployment
|
||||||
|
concurrency:
|
||||||
|
group: "pages"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Single deploy job since we're just deploying
|
||||||
|
deploy:
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: "zulu"
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Build Javadocs
|
||||||
|
run: ./bld download clean javadoc
|
||||||
|
|
||||||
|
- name: Setup Pages
|
||||||
|
uses: actions/configure-pages@v3
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
# Upload generated Javadocs repository
|
||||||
|
path: "build/javadoc/"
|
||||||
|
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
6
.idea/bld.xml
generated
Normal file
6
.idea/bld.xml
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="BldConfiguration">
|
||||||
|
<events />
|
||||||
|
</component>
|
||||||
|
</project>
|
2
.idea/copyright/Apache_License.xml
generated
2
.idea/copyright/Apache_License.xml
generated
|
@ -1,6 +1,6 @@
|
||||||
<component name="CopyrightManager">
|
<component name="CopyrightManager">
|
||||||
<copyright>
|
<copyright>
|
||||||
<option name="notice" value="Copyright &#36;today.year 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 https://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." />
|
<option name="notice" value="Copyright 2023-&#36;today.year 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 https://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." />
|
||||||
<option name="myName" value="Apache License" />
|
<option name="myName" value="Apache License" />
|
||||||
</copyright>
|
</copyright>
|
||||||
</component>
|
</component>
|
13
.idea/icon.svg
generated
Normal file
13
.idea/icon.svg
generated
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 179 108" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<g transform="matrix(1,0,0,1,-210.511,-96.3382)">
|
||||||
|
<g transform="matrix(1,0,0,1,-23.3386,-649.816)">
|
||||||
|
<g transform="matrix(0.221288,0,0,0.24,73.9536,390.254)">
|
||||||
|
<path d="M722.568,1482.92L722.568,1921.1L808.968,1921.1L808.968,1888.7C822.168,1907.9 846.168,1930.1 893.568,1930.1C933.168,1930.1 961.968,1917.5 985.368,1893.5C1012.97,1865.9 1027.37,1827.5 1027.37,1786.1C1027.37,1741.7 1011.17,1705.1 985.368,1680.5C961.968,1658.3 928.968,1644.5 892.368,1644.5C862.968,1644.5 830.568,1654.1 808.968,1683.5L808.968,1482.92L722.568,1482.92ZM871.368,1718.9C888.768,1718.9 903.768,1723.7 917.568,1736.9C930.168,1748.9 938.568,1766.3 938.568,1787.9C938.568,1807.7 930.168,1825.1 917.568,1837.1C904.368,1849.7 887.568,1855.7 872.568,1855.7C856.368,1855.7 837.168,1849.1 823.368,1835.9C813.168,1826.3 803.568,1810.1 803.568,1787.9C803.568,1765.1 812.568,1749.5 822.768,1738.7C836.568,1724.3 852.768,1718.9 871.368,1718.9Z" style="fill:rgb(35,146,255);fill-rule:nonzero;"/>
|
||||||
|
<rect x="1083.77" y="1482.92" width="86.4" height="438.182" style="fill:rgb(250,144,82);fill-rule:nonzero;"/>
|
||||||
|
<path d="M1531.37,1482.92L1444.97,1482.92L1444.97,1683.5C1423.37,1654.1 1390.97,1644.5 1361.57,1644.5C1324.97,1644.5 1291.97,1658.3 1268.57,1680.5C1242.77,1705.1 1226.57,1741.7 1226.57,1786.1C1226.57,1827.5 1240.97,1865.9 1268.57,1893.5C1291.97,1917.5 1320.77,1930.1 1360.37,1930.1C1407.77,1930.1 1431.77,1907.9 1444.97,1888.7L1444.97,1921.1L1531.37,1921.1L1531.37,1482.92ZM1382.57,1718.9C1401.17,1718.9 1417.37,1724.3 1431.17,1738.7C1441.37,1749.5 1450.37,1765.1 1450.37,1787.9C1450.37,1810.1 1440.77,1826.3 1430.57,1835.9C1416.77,1849.1 1397.57,1855.7 1381.37,1855.7C1366.37,1855.7 1349.57,1849.7 1336.37,1837.1C1323.77,1825.1 1315.37,1807.7 1315.37,1787.9C1315.37,1766.3 1323.77,1748.9 1336.37,1736.9C1350.17,1723.7 1365.17,1718.9 1382.57,1718.9Z" style="fill:rgb(35,146,255);fill-rule:nonzero;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
204
.idea/intellij-javadocs-4.0.1.xml
generated
Normal file
204
.idea/intellij-javadocs-4.0.1.xml
generated
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaDocConfiguration">
|
||||||
|
<GENERAL>
|
||||||
|
<MODE>UPDATE</MODE>
|
||||||
|
<OVERRIDDEN_METHODS>false</OVERRIDDEN_METHODS>
|
||||||
|
<SPLITTED_CLASS_NAME>true</SPLITTED_CLASS_NAME>
|
||||||
|
<LEVELS>
|
||||||
|
<LEVEL>FIELD</LEVEL>
|
||||||
|
<LEVEL>METHOD</LEVEL>
|
||||||
|
<LEVEL>TYPE</LEVEL>
|
||||||
|
</LEVELS>
|
||||||
|
<VISIBILITIES>
|
||||||
|
<VISIBILITY>PUBLIC</VISIBILITY>
|
||||||
|
<VISIBILITY>PROTECTED</VISIBILITY>
|
||||||
|
<VISIBILITY>DEFAULT</VISIBILITY>
|
||||||
|
</VISIBILITIES>
|
||||||
|
</GENERAL>
|
||||||
|
<TEMPLATES>
|
||||||
|
<CLASSES>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>^.*(public|protected|private)*.+interface\s+\w+.*</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The interface ${name}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>^.*(public|protected|private)*.+enum\s+\w+.*</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The enum ${name}.\n
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>^.*(public|protected|private)*.+class\s+\w+.*</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The type ${name}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The type ${name}.\n
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
</CLASSES>
|
||||||
|
<CONSTRUCTORS>
|
||||||
|
<CONSTRUCTOR>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* Instantiates a new ${name}.\n
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</CONSTRUCTOR>
|
||||||
|
</CONSTRUCTORS>
|
||||||
|
<METHODS>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>^.*(public|protected|private)*\s*.*(\w(\s*<.+>)*)+\s+get\w+\s*\(.*\).+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* Gets ${partName}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if isNotVoid>
|
||||||
|
*\n
|
||||||
|
* @return the ${partName}\n
|
||||||
|
</#if>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>^.*(public|protected|private)*\s*.*(void|\w(\s*<.+>)*)+\s+set\w+\s*\(.*\).+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* Sets ${partName}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if isNotVoid>
|
||||||
|
*\n
|
||||||
|
* @return the ${partName}\n
|
||||||
|
</#if>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The entry point of application.\n
|
||||||
|
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
* @param ${element.parameterList.parameters[0].name} the input arguments\n
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* ${name}<#if isNotVoid> ${return}</#if>.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if isNotVoid>
|
||||||
|
*\n
|
||||||
|
* @return the ${return}\n
|
||||||
|
</#if>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
</METHODS>
|
||||||
|
<FIELDS>
|
||||||
|
<FIELD>
|
||||||
|
<KEY>^.*(public|protected|private)*.+static.*(\w\s\w)+.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The constant ${element.getName()}.\n
|
||||||
|
*/</VALUE>
|
||||||
|
</FIELD>
|
||||||
|
<FIELD>
|
||||||
|
<KEY>^.*(public|protected|private)*.*(\w\s\w)+.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
<#if element.parent.isInterface()>
|
||||||
|
* The constant ${element.getName()}.\n
|
||||||
|
<#else>
|
||||||
|
* The ${name}.\n
|
||||||
|
</#if> */</VALUE>
|
||||||
|
</FIELD>
|
||||||
|
<FIELD>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
<#if element.parent.isEnum()>
|
||||||
|
*${name} ${typeName}.\n
|
||||||
|
<#else>
|
||||||
|
* The ${name}.\n
|
||||||
|
</#if>*/</VALUE>
|
||||||
|
</FIELD>
|
||||||
|
</FIELDS>
|
||||||
|
</TEMPLATES>
|
||||||
|
</component>
|
||||||
|
</project>
|
5
.idea/libraries/bld.xml
generated
5
.idea/libraries/bld.xml
generated
|
@ -2,11 +2,12 @@
|
||||||
<library name="bld">
|
<library name="bld">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/bld" />
|
<root url="file://$PROJECT_DIR$/lib/bld" />
|
||||||
<root url="jar://$USER_HOME$/.bld/dist/bld-1.7.5.jar!/" />
|
<root url="jar://$USER_HOME$/.bld/dist/bld-2.2.1.jar!/" />
|
||||||
</CLASSES>
|
</CLASSES>
|
||||||
<JAVADOC />
|
<JAVADOC />
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="jar://$USER_HOME$/.bld/dist/bld-1.7.5-sources.jar!/" />
|
<root url="file://$PROJECT_DIR$/lib/bld" />
|
||||||
|
<root url="jar://$USER_HOME$/.bld/dist/bld-2.2.1-sources.jar!/" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<excluded>
|
<excluded>
|
||||||
<root url="jar://$PROJECT_DIR$/lib/bld/bld-wrapper.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/bld/bld-wrapper.jar!/" />
|
||||||
|
|
4
.idea/libraries/compile.xml
generated
4
.idea/libraries/compile.xml
generated
|
@ -7,7 +7,7 @@
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/compile" />
|
<root url="file://$PROJECT_DIR$/lib/compile" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="true" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="true" type="SOURCES" />
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
4
.idea/libraries/runtime.xml
generated
4
.idea/libraries/runtime.xml
generated
|
@ -8,7 +8,7 @@
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/runtime" />
|
<root url="file://$PROJECT_DIR$/lib/runtime" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="true" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="true" type="SOURCES" />
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
4
.idea/libraries/test.xml
generated
4
.idea/libraries/test.xml
generated
|
@ -8,7 +8,7 @@
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/test" />
|
<root url="file://$PROJECT_DIR$/lib/test" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="true" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="true" type="SOURCES" />
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
9
.vscode/launch.json
vendored
9
.vscode/launch.json
vendored
|
@ -5,7 +5,14 @@
|
||||||
"type": "java",
|
"type": "java",
|
||||||
"name": "Run Tests",
|
"name": "Run Tests",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mainClass": "rife.bld.extension.ExecOperationTest"
|
"mainClass": "org.junit.platform.console.ConsoleLauncher",
|
||||||
|
"args": [
|
||||||
|
"--details=verbose",
|
||||||
|
"--scan-classpath",
|
||||||
|
"--disable-banner",
|
||||||
|
"--disable-ansi-colors",
|
||||||
|
"--exclude-engine=junit-platform-suite",
|
||||||
|
"--exclude-engine=junit-vintage"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
|
@ -3,13 +3,13 @@
|
||||||
"src/main/java",
|
"src/main/java",
|
||||||
"src/main/resources",
|
"src/main/resources",
|
||||||
"src/test/java",
|
"src/test/java",
|
||||||
"src/bld/java"
|
"src/test/resources",
|
||||||
|
"src/bld/java",
|
||||||
|
"src/bld/resources"
|
||||||
],
|
],
|
||||||
"java.configuration.updateBuildConfiguration": "automatic",
|
"java.configuration.updateBuildConfiguration": "automatic",
|
||||||
"java.project.referencedLibraries": [
|
"java.project.referencedLibraries": [
|
||||||
"${HOME}/.bld/dist/bld-1.7.5.jar",
|
"${HOME}/.bld/dist/bld-2.2.1.jar",
|
||||||
"lib/compile/*.jar",
|
"lib/**/*.jar"
|
||||||
"lib/runtime/*.jar",
|
|
||||||
"lib/test/*.jar"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
41
README.md
41
README.md
|
@ -2,12 +2,20 @@
|
||||||
|
|
||||||
[](https://opensource.org/licenses/Apache-2.0)
|
[](https://opensource.org/licenses/Apache-2.0)
|
||||||
[](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
|
[](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
|
||||||
[](https://rife2.com/bld)
|
[](https://rife2.com/bld)
|
||||||
[](https://repo.rife2.com/#/releases/com/uwyn/rife2/bld-exec)
|
[](https://repo.rife2.com/#/releases/com/uwyn/rife2/bld-exec)
|
||||||
[](https://repo.rife2.com/#/snapshots/com/uwyn/rife2/bld-exec)
|
[](https://repo.rife2.com/#/snapshots/com/uwyn/rife2/bld-exec)
|
||||||
[](https://github.com/rife2/bld-exec/actions/workflows/bld.yml)
|
[](https://github.com/rife2/bld-exec/actions/workflows/bld.yml)
|
||||||
|
|
||||||
To install, please refer to the [extensions documentation](https://github.com/rife2/bld/wiki/Extensions).
|
To install the latest version, add the following to the `lib/bld/bld-wrapper.properties` file:
|
||||||
|
|
||||||
|
```properties
|
||||||
|
bld.extension-exec=com.uwyn.rife2:bld-exec
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information, please refer to the [extensions](https://github.com/rife2/bld/wiki/Extensions) documentation.
|
||||||
|
|
||||||
|
## Execute a Command
|
||||||
|
|
||||||
To execute a command at the command line, add the following to your build file:
|
To execute a command at the command line, add the following to your build file:
|
||||||
|
|
||||||
|
@ -21,16 +29,15 @@ public void startServer() throws Exception {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Failure Modes
|
## Exit Value
|
||||||
|
|
||||||
Use the `fail` function to specify whether data returned to the standard streams and/or an abnormal exit value
|
Use the `failOnExit` function to specify whether a command non-zero exit value (status) constitutes a failure.
|
||||||
constitute a failure.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@BuildCommand
|
@BuildCommand
|
||||||
public void startServer() throws Exception {
|
public void startServer() throws Exception {
|
||||||
final List<String> cmds;
|
final List<String> cmds;
|
||||||
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
if (System.getProperty("os.name").toLowerCase().contains("win")) {
|
||||||
cmds = List.of("cmd", "/c", "stop.bat");
|
cmds = List.of("cmd", "/c", "stop.bat");
|
||||||
} else {
|
} else {
|
||||||
cmds = List.of("./stop.sh");
|
cmds = List.of("./stop.sh");
|
||||||
|
@ -38,28 +45,14 @@ public void startServer() throws Exception {
|
||||||
new ExecOperation()
|
new ExecOperation()
|
||||||
.fromProject(this)
|
.fromProject(this)
|
||||||
.command(cmds)
|
.command(cmds)
|
||||||
.fail(ExecFail.STDERR)
|
.failOneExit(false)
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The following predefined values are available:
|
## Work Directory
|
||||||
|
|
||||||
| Name | Failure When |
|
You can also specify the work directory:
|
||||||
|:------------------|:-----------------------------------------------------------------|
|
|
||||||
| `ExecFail.EXIT` | Exit value > 0 |
|
|
||||||
| `ExecFail.NORMAL` | Exit value > 0 or any data to the standard error stream (stderr) |
|
|
||||||
| `ExecFail.OUTPUT` | Any data to the standard output stream (stdout) or stderr. |
|
|
||||||
| `ExecFail.STDERR` | Any data to stderr. |
|
|
||||||
| `ExecFail.STDOUT` | Any data to stdout. |
|
|
||||||
| `ExecFail.ALL` | Any of the conditions above. |
|
|
||||||
| `ExecFail.NONE` | Never fails. |
|
|
||||||
|
|
||||||
`ExecFail.NORMAL` is the default value.
|
|
||||||
|
|
||||||
## Working Directory
|
|
||||||
|
|
||||||
You can also specify the working directory:
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@BuildCommand
|
@BuildCommand
|
||||||
|
@ -71,3 +64,5 @@ public void startServer() throws Exception {
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Please check the [ExecOperation documentation](https://rife2.github.io/bld-exec/rife/bld/extension/ExecOperation.html#method-summary) for all available configuration options.
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
<!-- BEST PRACTICES -->
|
<!-- BEST PRACTICES -->
|
||||||
<rule ref="category/java/bestpractices.xml">
|
<rule ref="category/java/bestpractices.xml">
|
||||||
<exclude name="AvoidPrintStackTrace"/>
|
<exclude name="AvoidPrintStackTrace"/>
|
||||||
<exclude name="JUnit4TestShouldUseTestAnnotation"/>
|
|
||||||
<exclude name="JUnitTestContainsTooManyAsserts"/>
|
|
||||||
<exclude name="GuardLogStatement"/>
|
<exclude name="GuardLogStatement"/>
|
||||||
|
<exclude name="UnitTestContainsTooManyAsserts"/>
|
||||||
|
<exclude name="UnitTestShouldUseTestAnnotation"/>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<rule ref="category/java/bestpractices.xml/MissingOverride">
|
<rule ref="category/java/bestpractices.xml/MissingOverride">
|
||||||
|
@ -19,12 +19,13 @@
|
||||||
</properties>
|
</properties>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
<!-- CODE STYLE -->
|
<!-- CODE STYLE -->
|
||||||
<rule ref="category/java/codestyle.xml">
|
<rule ref="category/java/codestyle.xml">
|
||||||
<exclude name="AtLeastOneConstructor"/>
|
<exclude name="AtLeastOneConstructor"/>
|
||||||
<exclude name="ClassNamingConventions"/>
|
<exclude name="ClassNamingConventions"/>
|
||||||
<exclude name="ConfusingTernary"/>
|
|
||||||
<exclude name="CommentDefaultAccessModifier"/>
|
<exclude name="CommentDefaultAccessModifier"/>
|
||||||
|
<exclude name="ConfusingTernary"/>
|
||||||
<exclude name="FieldNamingConventions"/>
|
<exclude name="FieldNamingConventions"/>
|
||||||
<exclude name="LocalVariableCouldBeFinal"/>
|
<exclude name="LocalVariableCouldBeFinal"/>
|
||||||
<exclude name="LongVariable"/>
|
<exclude name="LongVariable"/>
|
||||||
|
@ -34,8 +35,9 @@
|
||||||
<exclude name="ShortClassName"/>
|
<exclude name="ShortClassName"/>
|
||||||
<exclude name="ShortMethodName"/>
|
<exclude name="ShortMethodName"/>
|
||||||
<exclude name="ShortVariable"/>
|
<exclude name="ShortVariable"/>
|
||||||
<exclude name="UselessParentheses"/>
|
<exclude name="UseExplicitTypes"/>
|
||||||
<exclude name="UseUnderscoresInNumericLiterals"/>
|
<exclude name="UseUnderscoresInNumericLiterals"/>
|
||||||
|
<exclude name="UselessParentheses"/>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<rule ref="category/java/codestyle.xml/UnnecessaryImport">
|
<rule ref="category/java/codestyle.xml/UnnecessaryImport">
|
||||||
|
@ -51,8 +53,6 @@
|
||||||
<exclude name="AvoidUncheckedExceptionsInSignatures"/>
|
<exclude name="AvoidUncheckedExceptionsInSignatures"/>
|
||||||
<exclude name="CognitiveComplexity"/>
|
<exclude name="CognitiveComplexity"/>
|
||||||
<exclude name="CyclomaticComplexity"/>
|
<exclude name="CyclomaticComplexity"/>
|
||||||
<exclude name="ExcessiveClassLength"/>
|
|
||||||
<exclude name="ExcessiveMethodLength"/>
|
|
||||||
<exclude name="ExcessiveParameterList"/>
|
<exclude name="ExcessiveParameterList"/>
|
||||||
<exclude name="ExcessivePublicCount"/>
|
<exclude name="ExcessivePublicCount"/>
|
||||||
<exclude name="GodClass"/>
|
<exclude name="GodClass"/>
|
||||||
|
|
Binary file not shown.
|
@ -1,8 +1,7 @@
|
||||||
bld.downloadExtensionJavadoc=false
|
bld.downloadExtensionJavadoc=false
|
||||||
bld.downloadExtensionSources=true
|
bld.downloadExtensionSources=true
|
||||||
bld.extension-pmd=com.uwyn.rife2:bld-pmd:0.9.3
|
|
||||||
bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.1
|
|
||||||
bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES
|
|
||||||
bld.downloadLocation=
|
bld.downloadLocation=
|
||||||
|
bld.extension-pmd=com.uwyn.rife2:bld-pmd:1.2.2
|
||||||
|
bld.repositories=MAVEN_CENTRAL,MAVEN_LOCAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES
|
||||||
bld.sourceDirectories=
|
bld.sourceDirectories=
|
||||||
bld.version=1.7.5
|
bld.version=2.2.1
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023 the original author or authors.
|
* Copyright 2023-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,11 +22,9 @@ import rife.bld.publish.PublishDeveloper;
|
||||||
import rife.bld.publish.PublishLicense;
|
import rife.bld.publish.PublishLicense;
|
||||||
import rife.bld.publish.PublishScm;
|
import rife.bld.publish.PublishScm;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static rife.bld.dependencies.Repository.MAVEN_CENTRAL;
|
import static rife.bld.dependencies.Repository.*;
|
||||||
import static rife.bld.dependencies.Repository.RIFE2_RELEASES;
|
|
||||||
import static rife.bld.dependencies.Scope.compile;
|
import static rife.bld.dependencies.Scope.compile;
|
||||||
import static rife.bld.dependencies.Scope.test;
|
import static rife.bld.dependencies.Scope.test;
|
||||||
import static rife.bld.operations.JavadocOptions.DocLinkOption.NO_MISSING;
|
import static rife.bld.operations.JavadocOptions.DocLinkOption.NO_MISSING;
|
||||||
|
@ -35,41 +33,52 @@ public class ExecOperationBuild extends Project {
|
||||||
public ExecOperationBuild() {
|
public ExecOperationBuild() {
|
||||||
pkg = "rife.bld.extension";
|
pkg = "rife.bld.extension";
|
||||||
name = "ExecOperation";
|
name = "ExecOperation";
|
||||||
version = version(0, 9, 0);
|
version = version(1, 0, 5);
|
||||||
|
|
||||||
javaRelease = 17;
|
javaRelease = 17;
|
||||||
|
|
||||||
downloadSources = true;
|
downloadSources = true;
|
||||||
autoDownloadPurge = true;
|
autoDownloadPurge = true;
|
||||||
repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES);
|
|
||||||
|
repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES, RIFE2_SNAPSHOTS);
|
||||||
|
|
||||||
scope(compile)
|
scope(compile)
|
||||||
.include(dependency("com.uwyn.rife2", "bld", version(1, 7, 5)));
|
.include(dependency("com.uwyn.rife2", "bld", version(2, 2, 1)));
|
||||||
scope(test)
|
scope(test)
|
||||||
.include(dependency("org.jsoup", "jsoup", version(1, 16, 2)))
|
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1)))
|
||||||
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 0)))
|
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1)))
|
||||||
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 10, 0)))
|
.include(dependency("org.assertj", "assertj-core", version(3, 27, 3)));
|
||||||
.include(dependency("org.assertj", "assertj-core", version(3, 24, 2)));
|
|
||||||
|
|
||||||
javadocOperation()
|
javadocOperation()
|
||||||
.javadocOptions()
|
.javadocOptions()
|
||||||
|
.author()
|
||||||
.docLint(NO_MISSING)
|
.docLint(NO_MISSING)
|
||||||
.link("https://rife2.github.io/bld/")
|
.link("https://rife2.github.io/bld/")
|
||||||
.link("https://rife2.github.io/rife2/");
|
.link("https://rife2.github.io/rife2/");
|
||||||
|
|
||||||
publishOperation()
|
publishOperation()
|
||||||
.repository(version.isSnapshot() ? repository("rife2-snapshot") : repository("rife2"))
|
.repository(version.isSnapshot() ? repository("rife2-snapshot") : repository("rife2"))
|
||||||
|
.repository(repository("github"))
|
||||||
.info()
|
.info()
|
||||||
.groupId("com.uwyn.rife2")
|
.groupId("com.uwyn.rife2")
|
||||||
.artifactId("bld-exec")
|
.artifactId("bld-exec")
|
||||||
.description("Command Line Execution Extension for bld")
|
.description("Command Line Execution Extension for bld")
|
||||||
.url("https://github.com/rife2/bld-exec")
|
.url("https://github.com/rife2/bld-exec")
|
||||||
.developer(new PublishDeveloper().id("ethauvin").name("Erik C. Thauvin").email("erik@thauvin.net")
|
.developer(new PublishDeveloper()
|
||||||
.url("https://erik.thauvin.net/"))
|
.id("ethauvin")
|
||||||
.license(new PublishLicense().name("The Apache License, Version 2.0")
|
.name("Erik C. Thauvin")
|
||||||
.url("http://www.apache.org/licenses/LICENSE-2.0.txt"))
|
.email("erik@thauvin.net")
|
||||||
.scm(new PublishScm().connection("scm:git:https://github.com/rife2/bld-exec.git")
|
.url("https://erik.thauvin.net/")
|
||||||
|
)
|
||||||
|
.license(new PublishLicense()
|
||||||
|
.name("The Apache License, Version 2.0")
|
||||||
|
.url("https://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||||
|
)
|
||||||
|
.scm(new PublishScm()
|
||||||
|
.connection("scm:git:https://github.com/rife2/bld-exec.git")
|
||||||
.developerConnection("scm:git:git@github.com:rife2/bld-exec.git")
|
.developerConnection("scm:git:git@github.com:rife2/bld-exec.git")
|
||||||
.url("https://github.com/rife2/bld-exec"))
|
.url("https://github.com/rife2/bld-exec")
|
||||||
|
)
|
||||||
.signKey(property("sign.key"))
|
.signKey(property("sign.key"))
|
||||||
.signPassphrase(property("sign.passphrase"));
|
.signPassphrase(property("sign.passphrase"));
|
||||||
}
|
}
|
||||||
|
@ -78,15 +87,8 @@ public class ExecOperationBuild extends Project {
|
||||||
new ExecOperationBuild().start(args);
|
new ExecOperationBuild().start(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BuildCommand(summary = "Generates JaCoCo Reports")
|
|
||||||
public void jacoco() throws IOException {
|
|
||||||
new JacocoReportOperation()
|
|
||||||
.fromProject(this)
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BuildCommand(summary = "Runs PMD analysis")
|
@BuildCommand(summary = "Runs PMD analysis")
|
||||||
public void pmd() {
|
public void pmd() throws Exception {
|
||||||
new PmdOperation()
|
new PmdOperation()
|
||||||
.fromProject(this)
|
.fromProject(this)
|
||||||
.failOnViolation(true)
|
.failOnViolation(true)
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2023 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
|
|
||||||
*
|
|
||||||
* https://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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package rife.bld.extension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The failure modes enumeration.
|
|
||||||
*
|
|
||||||
* @author <a href="https://erik.thauvin.net/">Erik C. Thauvin</a>
|
|
||||||
* @since 1.0
|
|
||||||
*/
|
|
||||||
public enum ExecFail {
|
|
||||||
ALL, EXIT, NONE, NORMAL, OUTPUT, STDERR, STDOUT
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023 the original author or authors.
|
* Copyright 2023-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,11 +18,14 @@ package rife.bld.extension;
|
||||||
|
|
||||||
import rife.bld.BaseProject;
|
import rife.bld.BaseProject;
|
||||||
import rife.bld.operations.AbstractOperation;
|
import rife.bld.operations.AbstractOperation;
|
||||||
|
import rife.bld.operations.exceptions.ExitStatusException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.nio.file.Path;
|
||||||
import java.io.InputStream;
|
import java.util.ArrayList;
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -35,30 +38,44 @@ import java.util.logging.Logger;
|
||||||
*/
|
*/
|
||||||
public class ExecOperation extends AbstractOperation<ExecOperation> {
|
public class ExecOperation extends AbstractOperation<ExecOperation> {
|
||||||
private static final Logger LOGGER = Logger.getLogger(ExecOperation.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(ExecOperation.class.getName());
|
||||||
private final List<String> args_ = new ArrayList<>();
|
private final Collection<String> args_ = new ArrayList<>();
|
||||||
private final Set<ExecFail> fail_ = new HashSet<>();
|
private boolean failOnExit_ = true;
|
||||||
private BaseProject project_;
|
private BaseProject project_;
|
||||||
private String workDir_;
|
private int timeout_ = 30;
|
||||||
|
private File workDir_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the command and arguments to be executed.
|
* Configures the command and arguments to be executed.
|
||||||
* <p>
|
* <p>
|
||||||
* For example:
|
* For example:
|
||||||
* <p><ul>
|
* <ul>
|
||||||
* <li>{@code command("cmd", "/c", "stop.bat")}</li>
|
* <li>{@code command("cmd", "/c", "stop.bat")}</li>
|
||||||
* <li>{@code command("./stop.sh"}</li>
|
* <li>{@code command("./stop.sh"}</li>
|
||||||
* </ul></p>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* @param arg one or more arguments
|
||||||
|
* @return this operation instance
|
||||||
* @see #command(Collection)
|
* @see #command(Collection)
|
||||||
*/
|
*/
|
||||||
public ExecOperation command(String... arg) {
|
public ExecOperation command(String... arg) {
|
||||||
args_.addAll(List.of(arg));
|
return command(List.of(arg));
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the command and arguments to be executed.
|
||||||
|
*
|
||||||
|
* @return the command and arguments
|
||||||
|
*/
|
||||||
|
public Collection<String> command() {
|
||||||
|
return args_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the command and arguments to be executed.
|
* Configures the command and arguments to be executed.
|
||||||
*
|
*
|
||||||
|
* @param args the list of arguments
|
||||||
|
* @return this operation instance
|
||||||
* @see #command(String...)
|
* @see #command(String...)
|
||||||
*/
|
*/
|
||||||
public ExecOperation command(Collection<String> args) {
|
public ExecOperation command(Collection<String> args) {
|
||||||
|
@ -72,98 +89,143 @@ public class ExecOperation extends AbstractOperation<ExecOperation> {
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws Exception {
|
public void execute() throws Exception {
|
||||||
if (project_ == null) {
|
if (project_ == null) {
|
||||||
|
if (LOGGER.isLoggable(Level.SEVERE) && !silent()) {
|
||||||
LOGGER.severe("A project must be specified.");
|
LOGGER.severe("A project must be specified.");
|
||||||
}
|
}
|
||||||
var errorMessage = new StringBuilder(27);
|
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||||
|
|
||||||
final File workDir;
|
|
||||||
if (workDir_ == null || workDir_.isBlank()) {
|
|
||||||
workDir = new File(project_.workDirectory().getAbsolutePath());
|
|
||||||
} else {
|
} else {
|
||||||
workDir = new File(workDir_);
|
final File workDir = Objects.requireNonNullElseGet(workDir_,
|
||||||
|
() -> new File(project_.workDirectory().getAbsolutePath()));
|
||||||
|
|
||||||
|
if (LOGGER.isLoggable(Level.INFO)) {
|
||||||
|
LOGGER.info("Working directory: " + workDir.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workDir.isDirectory()) {
|
if (workDir.isDirectory()) {
|
||||||
var pb = new ProcessBuilder();
|
var pb = new ProcessBuilder();
|
||||||
pb.command(args_);
|
pb.inheritIO();
|
||||||
|
pb.command(args_.stream().toList());
|
||||||
pb.directory(workDir);
|
pb.directory(workDir);
|
||||||
|
|
||||||
if (LOGGER.isLoggable(Level.INFO)) {
|
if (LOGGER.isLoggable(Level.INFO) && !silent()) {
|
||||||
LOGGER.info(String.join(" ", args_));
|
LOGGER.info(String.join(" ", args_));
|
||||||
}
|
}
|
||||||
|
|
||||||
var proc = pb.start();
|
var proc = pb.start();
|
||||||
var err = proc.waitFor(30, TimeUnit.SECONDS);
|
var err = proc.waitFor(timeout_, TimeUnit.SECONDS);
|
||||||
var stdout = readStream(proc.getInputStream());
|
|
||||||
var stderr = readStream(proc.getErrorStream());
|
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
errorMessage.append("TIMEOUT");
|
proc.destroy();
|
||||||
} else if (!fail_.contains(ExecFail.NONE)) {
|
if (LOGGER.isLoggable(Level.SEVERE) && !silent()) {
|
||||||
var all = fail_.contains(ExecFail.ALL);
|
LOGGER.severe("The command timed out.");
|
||||||
var output = fail_.contains(ExecFail.OUTPUT);
|
|
||||||
if ((all || fail_.contains(ExecFail.EXIT) || fail_.contains(ExecFail.NORMAL)) && proc.exitValue() > 0) {
|
|
||||||
errorMessage.append("EXIT ").append(proc.exitValue());
|
|
||||||
if (!stderr.isEmpty()) {
|
|
||||||
errorMessage.append(", STDERR -> ").append(stderr.get(0));
|
|
||||||
} else if (!stdout.isEmpty()) {
|
|
||||||
errorMessage.append(", STDOUT -> ").append(stdout.get(0));
|
|
||||||
}
|
}
|
||||||
} else if ((all || output || fail_.contains(ExecFail.STDERR) || fail_.contains(ExecFail.NORMAL))
|
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||||
&& !stderr.isEmpty()) {
|
} else if (proc.exitValue() != 0 && failOnExit_) {
|
||||||
errorMessage.append("STDERR -> ").append(stderr.get(0));
|
if (LOGGER.isLoggable(Level.SEVERE) && !silent()) {
|
||||||
} else if ((all || output || fail_.contains(ExecFail.STDOUT)) && !stdout.isEmpty()) {
|
LOGGER.severe("The command exit value/status is: " + proc.exitValue());
|
||||||
errorMessage.append("STDOUT -> ").append(stdout.get(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LOGGER.isLoggable(Level.INFO) && errorMessage.isEmpty() && !stdout.isEmpty()) {
|
|
||||||
for (var l : stdout) {
|
|
||||||
LOGGER.info(l);
|
|
||||||
}
|
}
|
||||||
|
ExitStatusException.throwOnFailure(proc.exitValue());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorMessage.append("Invalid working directory: ").append(workDir.getCanonicalPath());
|
if (LOGGER.isLoggable(Level.SEVERE) && !silent()) {
|
||||||
|
LOGGER.severe("Invalid working directory: " + workDir);
|
||||||
|
}
|
||||||
|
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!errorMessage.isEmpty()) {
|
|
||||||
throw new IOException(errorMessage.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the failure mode.
|
* Configures whether the operation should fail if the command exit value/status is not 0.
|
||||||
|
* <p>
|
||||||
|
* Default is {@code TRUE}
|
||||||
*
|
*
|
||||||
* @see ExecFail
|
* @param failOnExit The fail on exit toggle
|
||||||
|
* @return this operation instance.
|
||||||
*/
|
*/
|
||||||
public ExecOperation fail(ExecFail... fail) {
|
public ExecOperation failOnExit(boolean failOnExit) {
|
||||||
fail_.addAll(Set.of(fail));
|
failOnExit_ = failOnExit;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures an Exec operation from a {@link BaseProject}.
|
* Configures an Exec operation from a {@link BaseProject}.
|
||||||
|
*
|
||||||
|
* @param project the project
|
||||||
|
* @return this operation instance
|
||||||
*/
|
*/
|
||||||
public ExecOperation fromProject(BaseProject project) {
|
public ExecOperation fromProject(BaseProject project) {
|
||||||
project_ = project;
|
project_ = project;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> readStream(InputStream stream) {
|
/**
|
||||||
var lines = new ArrayList<String>();
|
* Returns whether the operation should fail if the command exit value/status is not 0.
|
||||||
try (var scanner = new Scanner(stream)) {
|
*
|
||||||
while (scanner.hasNextLine()) {
|
* @return {@code true} or {@code false}
|
||||||
lines.add(scanner.nextLine());
|
*/
|
||||||
|
public boolean isFailOnExit() {
|
||||||
|
return failOnExit_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the command timeout.
|
||||||
|
*
|
||||||
|
* @param timeout The timeout in seconds
|
||||||
|
* @return this operation instance
|
||||||
|
*/
|
||||||
|
public ExecOperation timeout(int timeout) {
|
||||||
|
timeout_ = timeout;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
return lines;
|
|
||||||
|
/**
|
||||||
|
* Returns the command timeout.
|
||||||
|
*
|
||||||
|
* @return the timeout
|
||||||
|
*/
|
||||||
|
public int timeout() {
|
||||||
|
return timeout_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the working directory.
|
* Configures the working directory.
|
||||||
|
*
|
||||||
|
* @param dir the directory
|
||||||
|
* @return this operation instance
|
||||||
*/
|
*/
|
||||||
public ExecOperation workDir(String dir) {
|
public ExecOperation workDir(File dir) {
|
||||||
workDir_ = dir;
|
workDir_ = dir;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the working directory.
|
||||||
|
*
|
||||||
|
* @param dir the directory
|
||||||
|
* @return this operation instance
|
||||||
|
*/
|
||||||
|
public ExecOperation workDir(Path dir) {
|
||||||
|
return workDir(dir.toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the working directory.
|
||||||
|
*
|
||||||
|
* @param dir the directory path
|
||||||
|
* @return this operation instance
|
||||||
|
*/
|
||||||
|
public ExecOperation workDir(String dir) {
|
||||||
|
return workDir(new File(dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the working directory.
|
||||||
|
*
|
||||||
|
* @return the directory
|
||||||
|
*/
|
||||||
|
public File workDir() {
|
||||||
|
return workDir_;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023 the original author or authors.
|
* Copyright 2023-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,54 +17,30 @@
|
||||||
package rife.bld.extension;
|
package rife.bld.extension;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||||
|
import org.junit.jupiter.api.condition.OS;
|
||||||
import rife.bld.BaseProject;
|
import rife.bld.BaseProject;
|
||||||
import rife.bld.Project;
|
import rife.bld.Project;
|
||||||
import rife.bld.WebProject;
|
import rife.bld.WebProject;
|
||||||
|
import rife.bld.operations.exceptions.ExitStatusException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||||
|
|
||||||
|
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
|
||||||
class ExecOperationTest {
|
class ExecOperationTest {
|
||||||
private static final String FOO = "foo";
|
private static final String FOO = "foo";
|
||||||
private static final String HELLO = "Hello";
|
private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.US).contains("win");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testAll() {
|
void testCommand() {
|
||||||
assertThatCode(() ->
|
var op = new ExecOperation().fromProject(new WebProject())
|
||||||
new ExecOperation()
|
.command(FOO, "bar");
|
||||||
.fromProject(new Project())
|
assertThat(op.command()).containsExactly(FOO, "bar");
|
||||||
.command("date")
|
|
||||||
.fail(ExecFail.ALL)
|
|
||||||
.execute()
|
|
||||||
).isInstanceOf(IOException.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testCat() throws Exception {
|
|
||||||
var tmpFile = new File("hello.tmp");
|
|
||||||
tmpFile.deleteOnExit();
|
|
||||||
new ExecOperation()
|
|
||||||
.fromProject(new Project())
|
|
||||||
.command("touch", tmpFile.getName())
|
|
||||||
.fail(ExecFail.NORMAL)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
assertThat(tmpFile).exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testCommandList() {
|
|
||||||
assertThatCode(() ->
|
|
||||||
new ExecOperation()
|
|
||||||
.fromProject(new BaseProject())
|
|
||||||
.command(List.of("logger", "-s", HELLO))
|
|
||||||
.fail(ExecFail.STDERR)
|
|
||||||
.execute()).message().startsWith("STDERR -> ").endsWith(HELLO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -77,64 +53,102 @@ class ExecOperationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testExit() {
|
void testExitValue() {
|
||||||
|
List<String> cat;
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
cat = List.of("cmd", "/c", "type", FOO);
|
||||||
|
} else {
|
||||||
|
cat = List.of("cat", FOO);
|
||||||
|
}
|
||||||
assertThatCode(() ->
|
assertThatCode(() ->
|
||||||
new ExecOperation()
|
new ExecOperation()
|
||||||
.fromProject(new BaseProject())
|
.fromProject(new BaseProject())
|
||||||
.command("tail", FOO)
|
.command(cat)
|
||||||
.fail(ExecFail.EXIT)
|
.execute()).isInstanceOf(ExitStatusException.class);
|
||||||
.execute()).message().startsWith("EXIT ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testNone() {
|
void testFailOnExit() {
|
||||||
assertThatCode(() ->
|
List<String> cat;
|
||||||
new ExecOperation()
|
if (IS_WINDOWS) {
|
||||||
.fromProject(new WebProject())
|
cat = List.of("cmd", "/c", "type", FOO);
|
||||||
.command("cat", FOO)
|
} else {
|
||||||
.fail(ExecFail.NONE)
|
cat = List.of("cat", FOO);
|
||||||
.execute()).doesNotThrowAnyException();
|
|
||||||
}
|
}
|
||||||
|
var op = new ExecOperation()
|
||||||
@Test
|
|
||||||
void testOutput() {
|
|
||||||
assertThatCode(() ->
|
|
||||||
new ExecOperation()
|
|
||||||
.fromProject(new WebProject())
|
|
||||||
.command("echo")
|
|
||||||
.fail(ExecFail.OUTPUT)
|
|
||||||
.execute()
|
|
||||||
).message().isEqualTo("STDOUT -> ");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testStdErr() {
|
|
||||||
assertThatCode(() ->
|
|
||||||
new ExecOperation()
|
|
||||||
.fromProject(new BaseProject())
|
.fromProject(new BaseProject())
|
||||||
.command("logger", "-s", HELLO)
|
.command(cat)
|
||||||
.fail(ExecFail.STDERR)
|
.failOnExit(false);
|
||||||
.execute()).message().startsWith("STDERR -> ").endsWith(HELLO);
|
assertThat(op.isFailOnExit()).isFalse();
|
||||||
|
assertThatCode(op::execute).doesNotThrowAnyException();
|
||||||
|
|
||||||
|
op.failOnExit(true);
|
||||||
|
assertThat(op.isFailOnExit()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testStdOut() {
|
void testTimeout() {
|
||||||
assertThatCode(() ->
|
List<String> sleep;
|
||||||
new ExecOperation()
|
if (IS_WINDOWS) {
|
||||||
|
sleep = List.of("cmd", "/c", "timeout", "/t", "10");
|
||||||
|
} else {
|
||||||
|
sleep = List.of("sleep", "10");
|
||||||
|
}
|
||||||
|
var op = new ExecOperation()
|
||||||
.fromProject(new BaseProject())
|
.fromProject(new BaseProject())
|
||||||
.command("echo", HELLO)
|
.timeout(5)
|
||||||
.fail(ExecFail.STDOUT)
|
.command(sleep);
|
||||||
.execute()).message().isEqualTo("STDOUT -> Hello");
|
assertThat(op.timeout()).isEqualTo(5);
|
||||||
|
assertThatCode(op::execute).isInstanceOf(ExitStatusException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnabledOnOs({OS.LINUX, OS.MAC})
|
||||||
|
void testTouch() throws Exception {
|
||||||
|
var tmpFile = new File("hello.tmp");
|
||||||
|
tmpFile.deleteOnExit();
|
||||||
|
new ExecOperation()
|
||||||
|
.fromProject(new Project())
|
||||||
|
.timeout(10)
|
||||||
|
.command("touch", tmpFile.getName())
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
assertThat(tmpFile).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWorkDir() {
|
void testWorkDir() {
|
||||||
|
List<String> echo;
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
echo = List.of("cmd", "/c", "echo", FOO);
|
||||||
|
} else {
|
||||||
|
echo = List.of("echo", FOO);
|
||||||
|
}
|
||||||
|
var workDir = new File(System.getProperty("java.io.tmpdir"));
|
||||||
|
var op = new ExecOperation()
|
||||||
|
.fromProject(new BaseProject())
|
||||||
|
.command(echo)
|
||||||
|
.workDir(workDir);
|
||||||
|
assertThat(op.workDir()).as("as file").isEqualTo(workDir);
|
||||||
|
assertThatCode(op::execute).doesNotThrowAnyException();
|
||||||
|
|
||||||
|
var build = "build";
|
||||||
|
op = op.workDir(build);
|
||||||
|
assertThat(op.workDir()).as("as string").isEqualTo(new File(build));
|
||||||
|
assertThatCode(op::execute).doesNotThrowAnyException();
|
||||||
|
|
||||||
|
op = op.workDir(workDir.toPath());
|
||||||
|
assertThat(op.workDir()).as("as path").isEqualTo(workDir);
|
||||||
|
assertThatCode(op::execute).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testWorkDirInvalid() {
|
||||||
assertThatCode(() ->
|
assertThatCode(() ->
|
||||||
new ExecOperation()
|
new ExecOperation()
|
||||||
.fromProject(new BaseProject())
|
.fromProject(new BaseProject())
|
||||||
.command("echo")
|
.command("echo")
|
||||||
.workDir(FOO)
|
.workDir(FOO)
|
||||||
.fail(ExecFail.NORMAL)
|
.execute()).isInstanceOf(ExitStatusException.class);
|
||||||
.execute()).message().startsWith("Invalid working directory: ").endsWith(FOO);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue