diff --git a/.gitattributes b/.gitattributes index 4c277ec..c2a2ac8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,9 +4,13 @@ pk_generated_parent.pom linguist-generated=true dependencies.md linguist-generated=true doc/changes/changelog.md linguist-generated=true -.github/workflows/broken_links_checker.yml linguist-generated=true -.github/workflows/ci-build-next-java.yml linguist-generated=true -.github/workflows/ci-build.yml linguist-generated=true -.github/workflows/dependencies_check.yml linguist-generated=true -.github/workflows/release_droid_prepare_original_checksum.yml linguist-generated=true -.github/workflows/release_droid_print_quick_checksum.yml linguist-generated=true + +.github/workflows/broken_links_checker.yml linguist-generated=true +.github/workflows/ci-build-next-java.yml linguist-generated=true +.github/workflows/ci-build.yml linguist-generated=true +.github/workflows/dependencies_check.yml linguist-generated=true +.github/workflows/release_droid_prepare_original_checksum.yml linguist-generated=true +.github/workflows/release_droid_print_quick_checksum.yml linguist-generated=true + +.settings/org.eclipse.jdt.core.prefs linguist-generated=true +.settings/org.eclipse.jdt.ui.prefs linguist-generated=true diff --git a/.github/workflows/broken_links_checker.yml b/.github/workflows/broken_links_checker.yml index c4ff3be..f2079ec 100644 --- a/.github/workflows/broken_links_checker.yml +++ b/.github/workflows/broken_links_checker.yml @@ -22,6 +22,8 @@ jobs: echo '{"aliveStatusCodes": [429, 200], "ignorePatterns": [' \ '{"pattern": "^https?://(www|dev).mysql.com/"},' \ '{"pattern": "^https?://(www.)?opensource.org"}' \ + '{"pattern": "^https?://(www.)?eclipse.org"}' \ + '{"pattern": "^https?://projects.eclipse.org"}' \ ']}' > ./target/broken_links_checker.json - uses: gaurav-nelson/github-action-markdown-link-check@v1 with: diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index e520870..6e90d53 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -9,20 +9,32 @@ on: jobs: build: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + docker_db_version: ["7.1.22", "8.22.0"] + env: + DEFAULT_DB_VERSION: "7.1.22" concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.docker_db_version }} cancel-in-progress: true steps: + - name: Free Disk Space + run: | + sudo rm -rf /usr/local/lib/android + sudo rm -rf /usr/share/dotnet - name: Checkout the repository uses: actions/checkout@v3 with: fetch-depth: 0 - - name: Set up JDK 11 + - name: Set up JDK 11 & 17 uses: actions/setup-java@v3 with: - distribution: 'temurin' - java-version: 11 - cache: 'maven' + distribution: "temurin" + java-version: | + 17 + 11 + cache: "maven" - name: Cache SonarCloud packages uses: actions/cache@v3 with: @@ -33,7 +45,7 @@ jobs: run: echo 'testcontainers.reuse.enable=true' > "$HOME/.testcontainers.properties" - name: Run tests and build with Maven run: | - mvn --batch-mode clean verify \ + JAVA_HOME=$JAVA_HOME_11_X64 mvn --batch-mode clean verify \ -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ -DtrimStackTrace=false - name: Publish Test Report @@ -42,14 +54,14 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} - name: Sonar analysis - if: ${{ env.SONAR_TOKEN != null }} + if: ${{ env.SONAR_TOKEN != null && env.DEFAULT_DB_VERSION == matrix.docker_db_version }} run: | - mvn --batch-mode org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ + JAVA_HOME=$JAVA_HOME_17_X64 mvn --batch-mode org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ -DtrimStackTrace=false \ -Dsonar.organization=exasol \ -Dsonar.host.url=https://sonarcloud.io \ - -Dsonar.login=$SONAR_TOKEN + -Dsonar.token=$SONAR_TOKEN env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/release_droid_prepare_original_checksum.yml b/.github/workflows/release_droid_prepare_original_checksum.yml index 4a980f8..0e2d3e7 100644 --- a/.github/workflows/release_droid_prepare_original_checksum.yml +++ b/.github/workflows/release_droid_prepare_original_checksum.yml @@ -7,6 +7,10 @@ jobs: build: runs-on: ubuntu-latest steps: + - name: Free Disk Space + run: | + sudo rm -rf /usr/local/lib/android + sudo rm -rf /usr/share/dotnet - name: Checkout the repository uses: actions/checkout@v3 with: @@ -14,9 +18,9 @@ jobs: - name: Set up JDK 11 uses: actions/setup-java@v3 with: - distribution: 'temurin' + distribution: "temurin" java-version: 11 - cache: 'maven' + cache: "maven" - name: Enable testcontainer reuse run: echo 'testcontainers.reuse.enable=true' > "$HOME/.testcontainers.properties" - name: Run tests and build with Maven @@ -28,4 +32,4 @@ jobs: with: name: original_checksum retention-days: 5 - path: original_checksum \ No newline at end of file + path: original_checksum diff --git a/.gitignore b/.gitignore index c482a5c..82ae8a3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ dependency-reduced-pom.xml .classpath .settings/org.eclipse.jdt.apt.core.prefs .settings/org.eclipse.core.resources.prefs +.settings/org.eclipse.m2e.core.prefs pom.xml.versionsBackup ~* *.orig diff --git a/.project-keeper.yml b/.project-keeper.yml index e447ffd..05493ae 100644 --- a/.project-keeper.yml +++ b/.project-keeper.yml @@ -6,3 +6,4 @@ sources: - jar_artifact excludes: - "E-PK-CORE-18: Outdated content: '.github/workflows/release_droid_upload_github_release_assets.yml'" + - "E-PK-CORE-18: Outdated content: '.github/workflows/ci-build.yml'" diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 8b5a9aa..bb40c3f 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -111,7 +111,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.processAnnotations=disabled org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=11 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false diff --git a/.vscode/settings.json b/.vscode/settings.json index 21c0cc1..23a8bc9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +1,21 @@ { - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.organizeImports": true, - "source.generate.finalModifiers": true, - "source.fixAll": true - }, - "java.codeGeneration.useBlocks": true, - "java.saveActions.organizeImports": true, - "java.sources.organizeImports.starThreshold": 3, - "java.sources.organizeImports.staticStarThreshold": 3, - "java.test.config": { - "vmArgs": [ - "-Djava.util.logging.config.file=src/test/resources/logging.properties" - ] - }, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": true, + "source.generate.finalModifiers": true, + "source.fixAll": true + }, + "java.codeGeneration.useBlocks": true, + "java.saveActions.organizeImports": true, + "java.sources.organizeImports.starThreshold": 3, + "java.sources.organizeImports.staticStarThreshold": 3, + "java.test.config": { + "vmArgs": [ + "-Djava.util.logging.config.file=src/test/resources/logging.properties" + ] + }, + "sonarlint.connectedMode.project": { + "connectionId": "exasol", + "projectKey": "com.exasol:bucketfs-client" + } } diff --git a/dependencies.md b/dependencies.md index 2ad8a19..359d2ff 100644 --- a/dependencies.md +++ b/dependencies.md @@ -14,13 +14,13 @@ | Dependency | License | | ----------------------------------------------- | --------------------------------- | -| [JUnit Jupiter Engine][7] | [Eclipse Public License v2.0][8] | +| [JUnit Jupiter (Aggregator)][7] | [Eclipse Public License v2.0][8] | | [JUnit Jupiter Params][7] | [Eclipse Public License v2.0][8] | | [Hamcrest][9] | [BSD License 3][10] | | [mockito-junit-jupiter][11] | [The MIT License][12] | | [Test containers for Exasol on Docker][13] | [MIT License][14] | | [Testcontainers :: JUnit Jupiter Extension][15] | [MIT][16] | -| [EqualsVerifier | release normal jar][17] | [Apache License, Version 2.0][18] | +| [EqualsVerifier \| release normal jar][17] | [Apache License, Version 2.0][18] | | [JUnit5 System Extensions][19] | [Eclipse Public License v2.0][20] | | [junit-pioneer][21] | [Eclipse Public License v2.0][8] | | [SLF4J JDK14 Binding][22] | [MIT License][23] | @@ -32,20 +32,20 @@ | [SonarQube Scanner for Maven][24] | [GNU LGPL 3][25] | | [OpenFastTrace Maven Plugin][26] | [GNU General Public License v3.0][27] | | [Project keeper maven plugin][28] | [The MIT License][29] | -| [Apache Maven Compiler Plugin][30] | [Apache License, Version 2.0][18] | +| [Apache Maven Compiler Plugin][30] | [Apache-2.0][18] | | [Apache Maven Enforcer Plugin][31] | [Apache-2.0][18] | | [Maven Flatten Plugin][32] | [Apache Software Licenese][18] | | [org.sonatype.ossindex.maven:ossindex-maven-plugin][33] | [ASL2][5] | -| [Maven Surefire Plugin][34] | [Apache License, Version 2.0][18] | +| [Maven Surefire Plugin][34] | [Apache-2.0][18] | | [Versions Maven Plugin][35] | [Apache License, Version 2.0][18] | -| [Apache Maven Assembly Plugin][36] | [Apache License, Version 2.0][18] | -| [Apache Maven JAR Plugin][37] | [Apache License, Version 2.0][18] | -| [Artifact reference checker and unifier][38] | [MIT License][39] | -| [Maven Failsafe Plugin][40] | [Apache License, Version 2.0][18] | -| [JaCoCo :: Maven Plugin][41] | [Eclipse Public License 2.0][42] | -| [error-code-crawler-maven-plugin][43] | [MIT License][44] | -| [Reproducible Build Maven Plugin][45] | [Apache 2.0][5] | -| [duplicate-finder-maven-plugin Maven Mojo][46] | [Apache License 2.0][47] | +| [duplicate-finder-maven-plugin Maven Mojo][36] | [Apache License 2.0][37] | +| [Apache Maven Assembly Plugin][38] | [Apache-2.0][18] | +| [Apache Maven JAR Plugin][39] | [Apache License, Version 2.0][18] | +| [Artifact reference checker and unifier][40] | [MIT License][41] | +| [Maven Failsafe Plugin][42] | [Apache-2.0][18] | +| [JaCoCo :: Maven Plugin][43] | [Eclipse Public License 2.0][44] | +| [error-code-crawler-maven-plugin][45] | [MIT License][46] | +| [Reproducible Build Maven Plugin][47] | [Apache 2.0][5] | | [Maven Clean Plugin][48] | [The Apache Software License, Version 2.0][5] | | [Maven Resources Plugin][49] | [The Apache Software License, Version 2.0][5] | | [Maven Install Plugin][50] | [The Apache Software License, Version 2.0][5] | @@ -67,7 +67,7 @@ [12]: https://github.com/mockito/mockito/blob/main/LICENSE [13]: https://github.com/exasol/exasol-testcontainers/ [14]: https://github.com/exasol/exasol-testcontainers/blob/main/LICENSE -[15]: https://testcontainers.org +[15]: https://java.testcontainers.org [16]: http://opensource.org/licenses/MIT [17]: https://www.jqno.nl/equalsverifier [18]: https://www.apache.org/licenses/LICENSE-2.0.txt @@ -88,18 +88,18 @@ [33]: https://sonatype.github.io/ossindex-maven/maven-plugin/ [34]: https://maven.apache.org/surefire/maven-surefire-plugin/ [35]: https://www.mojohaus.org/versions/versions-maven-plugin/ -[36]: https://maven.apache.org/plugins/maven-assembly-plugin/ -[37]: https://maven.apache.org/plugins/maven-jar-plugin/ -[38]: https://github.com/exasol/artifact-reference-checker-maven-plugin/ -[39]: https://github.com/exasol/artifact-reference-checker-maven-plugin/blob/main/LICENSE -[40]: https://maven.apache.org/surefire/maven-failsafe-plugin/ -[41]: https://www.jacoco.org/jacoco/trunk/doc/maven.html -[42]: https://www.eclipse.org/legal/epl-2.0/ -[43]: https://github.com/exasol/error-code-crawler-maven-plugin/ -[44]: https://github.com/exasol/error-code-crawler-maven-plugin/blob/main/LICENSE -[45]: http://zlika.github.io/reproducible-build-maven-plugin -[46]: https://github.com/basepom/duplicate-finder-maven-plugin -[47]: http://www.apache.org/licenses/LICENSE-2.0.html +[36]: https://github.com/basepom/duplicate-finder-maven-plugin +[37]: http://www.apache.org/licenses/LICENSE-2.0.html +[38]: https://maven.apache.org/plugins/maven-assembly-plugin/ +[39]: https://maven.apache.org/plugins/maven-jar-plugin/ +[40]: https://github.com/exasol/artifact-reference-checker-maven-plugin/ +[41]: https://github.com/exasol/artifact-reference-checker-maven-plugin/blob/main/LICENSE +[42]: https://maven.apache.org/surefire/maven-failsafe-plugin/ +[43]: https://www.jacoco.org/jacoco/trunk/doc/maven.html +[44]: https://www.eclipse.org/legal/epl-2.0/ +[45]: https://github.com/exasol/error-code-crawler-maven-plugin/ +[46]: https://github.com/exasol/error-code-crawler-maven-plugin/blob/main/LICENSE +[47]: http://zlika.github.io/reproducible-build-maven-plugin [48]: http://maven.apache.org/plugins/maven-clean-plugin/ [49]: http://maven.apache.org/plugins/maven-resources-plugin/ [50]: http://maven.apache.org/plugins/maven-install-plugin/ diff --git a/doc/changes/changes_1.1.3.md b/doc/changes/changes_1.1.3.md index e6982e9..dd2276b 100644 --- a/doc/changes/changes_1.1.3.md +++ b/doc/changes/changes_1.1.3.md @@ -1,9 +1,15 @@ -# Bucketfs Client 1.1.3, released 2023-??-?? +# Bucketfs Client 1.1.3, released 2023-09-04 -Code name: +Code name: Fix Uploading Local File ## Summary +This release fixes uploading a local file without specifying a directory. This failed with error `Cannot invoke "java.nio.file.Path.relativize(java.nio.file.Path)" because "this.sourceRoot" is null` before. + +## Bugfixes + +* #30: Fixed uploading when no directory is specified + ## Refactoring * #19: Removed class ListingProvider @@ -13,15 +19,31 @@ Code name: ### Compile Dependency Updates * Updated `com.exasol:bucketfs-java:3.0.0` to `3.1.0` -* Updated `info.picocli:picocli:4.7.1` to `4.7.2` +* Updated `info.picocli:picocli:4.7.1` to `4.7.5` ### Test Dependency Updates +* Updated `com.exasol:exasol-testcontainers:6.5.1` to `6.6.1` +* Updated `nl.jqno.equalsverifier:equalsverifier:3.14.1` to `3.15.1` +* Updated `org.junit-pioneer:junit-pioneer:2.0.0` to `2.0.1` +* Removed `org.junit.jupiter:junit-jupiter-engine:5.9.2` +* Updated `org.junit.jupiter:junit-jupiter-params:5.9.2` to `5.10.0` +* Added `org.junit.jupiter:junit-jupiter:5.10.0` +* Updated `org.mockito:mockito-junit-jupiter:5.2.0` to `5.5.0` * Added `org.slf4j:slf4j-jdk14:2.0.7` -* Updated `org.testcontainers:junit-jupiter:1.17.6` to `1.18.0` +* Updated `org.testcontainers:junit-jupiter:1.17.6` to `1.19.0` ### Plugin Dependency Updates -* Updated `com.exasol:project-keeper-maven-plugin:2.9.4` to `2.9.6` +* Updated `com.exasol:error-code-crawler-maven-plugin:1.2.2` to `1.3.0` +* Updated `com.exasol:project-keeper-maven-plugin:2.9.4` to `2.9.11` +* Updated `org.apache.maven.plugins:maven-assembly-plugin:3.5.0` to `3.6.0` +* Updated `org.apache.maven.plugins:maven-compiler-plugin:3.10.1` to `3.11.0` +* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.2.1` to `3.4.0` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.0.0-M8` to `3.1.2` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M8` to `3.1.2` * Added `org.basepom.maven:duplicate-finder-maven-plugin:1.5.1` +* Updated `org.codehaus.mojo:flatten-maven-plugin:1.3.0` to `1.5.0` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.14.2` to `2.16.0` * Updated `org.itsallcode:openfasttrace-maven-plugin:1.5.0` to `1.6.1` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.8` to `0.8.10` diff --git a/pk_generated_parent.pom b/pk_generated_parent.pom index bbc8e62..74d823c 100644 --- a/pk_generated_parent.pom +++ b/pk_generated_parent.pom @@ -42,7 +42,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.11.0 ${java.version} ${java.version} @@ -51,7 +51,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.2.1 + 3.4.0 enforce-maven @@ -71,7 +71,7 @@ org.codehaus.mojo flatten-maven-plugin - 1.3.0 + 1.5.0 true oss @@ -110,7 +110,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M8 + 3.1.2 @@ -121,7 +121,7 @@ org.codehaus.mojo versions-maven-plugin - 2.14.2 + 2.16.0 display-updates @@ -136,10 +136,35 @@ file:///${project.basedir}/versionsMavenPluginRules.xml + + org.basepom.maven + duplicate-finder-maven-plugin + 2.0.1 + + + default + verify + + check + + + + + true + true + true + true + true + true + false + true + false + + org.apache.maven.plugins maven-assembly-plugin - 3.5.0 + 3.6.0 src/assembly/all-dependencies.xml @@ -189,7 +214,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0-M8 + 3.1.2 @@ -210,7 +235,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.10 prepare-agent @@ -251,7 +276,7 @@ com.exasol error-code-crawler-maven-plugin - 1.2.2 + 1.3.0 verify diff --git a/pom.xml b/pom.xml index 9c83585..c44407e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,8 +6,8 @@ Command line client for BucketFS https://github.com/exasol/bucketfs-client/ - 5.9.2 - 4.7.2 + 5.10.0 + 4.7.5 @@ -47,7 +47,7 @@ org.junit.jupiter - junit-jupiter-engine + junit-jupiter ${junit.version} test @@ -66,25 +66,25 @@ org.mockito mockito-junit-jupiter - 5.2.0 + 5.5.0 test com.exasol exasol-testcontainers - 6.5.1 + 6.6.1 test org.testcontainers junit-jupiter - 1.18.0 + 1.19.0 test nl.jqno.equalsverifier equalsverifier - 3.14.1 + 3.15.1 test @@ -96,7 +96,7 @@ org.junit-pioneer junit-pioneer - 2.0.0 + 2.0.1 test @@ -134,7 +134,7 @@ com.exasol project-keeper-maven-plugin - 2.9.6 + 2.9.11 diff --git a/some_file b/some_file index e69de29..7fa5ada 100644 --- a/some_file +++ b/some_file @@ -0,0 +1,2 @@ +This file is used for integration tests +to verify uploads from the current working directory. diff --git a/src/main/java/com/exasol/bucketfs/client/CopyCommand.java b/src/main/java/com/exasol/bucketfs/client/CopyCommand.java index d3e8d37..e94a87c 100644 --- a/src/main/java/com/exasol/bucketfs/client/CopyCommand.java +++ b/src/main/java/com/exasol/bucketfs/client/CopyCommand.java @@ -65,7 +65,8 @@ private void upload() { if (!Files.exists(sourcePath)) { throw Uploader.createExceptionForFileNotFound(sourcePath); } - Files.walkFileTree(sourcePath, Uploader.from(sourcePath.getParent(), bucket, url)); + final Path sourceParent = sourcePath.getParent() == null ? Path.of(".") : sourcePath.getParent(); + Files.walkFileTree(sourcePath, Uploader.from(sourceParent, bucket, url)); } catch (final IOException exception) { throw new BucketFsClientException(ExaError.messageBuilder("E-BFSC-9") // .message("Failed to upload {{file}}", sourcePath) diff --git a/src/main/java/com/exasol/bucketfs/url/PathCompleter.java b/src/main/java/com/exasol/bucketfs/url/PathCompleter.java index ab46d5f..f8f6642 100644 --- a/src/main/java/com/exasol/bucketfs/url/PathCompleter.java +++ b/src/main/java/com/exasol/bucketfs/url/PathCompleter.java @@ -4,6 +4,7 @@ import java.nio.file.Files; import java.nio.file.Path; +import java.util.Objects; public class PathCompleter { @@ -12,8 +13,8 @@ public class PathCompleter { private final boolean isDirectory; public PathCompleter(final Path sourceRoot, final String pathInBucket) { - this.sourceRoot = sourceRoot; - this.pathInBucket = pathInBucket; + this.sourceRoot = Objects.requireNonNull(sourceRoot, "sourceRoot"); + this.pathInBucket = Objects.requireNonNull(pathInBucket, "pathInBucket"); this.isDirectory = BucketFsLocation.isDirectorySyntax(pathInBucket); } diff --git a/src/test/java/com/exasol/bucketfs/ProcessExecutor.java b/src/test/java/com/exasol/bucketfs/ProcessExecutor.java index 874a0a7..a6fdbe2 100644 --- a/src/test/java/com/exasol/bucketfs/ProcessExecutor.java +++ b/src/test/java/com/exasol/bucketfs/ProcessExecutor.java @@ -19,7 +19,7 @@ public class ProcessExecutor { /** Name of the JAR file */ - public static String JAR_NAME = "bfsc-1.1.3.jar"; + public static final String JAR_NAME = "bfsc-1.1.3.jar"; /** * Create a {@link ProcessExecutor} for the jar built by for the current projects. The Jar file must be built before @@ -44,6 +44,7 @@ private static Path getJarFile() { private final String[] initialArgs; private Process process; private final Duration timeout = Duration.ofSeconds(5); + private Path workingDir = null; /** * Create a new instance of {@link ProcessExecutor}. @@ -54,6 +55,19 @@ public ProcessExecutor(final String... initialArgs) { this.initialArgs = initialArgs; } + /** + * Set the working directory for the new process. + *

+ * Default value {@code null} is the current working directory. + * + * @param workingDir the working directory for the new process + * @return this instance for method chaining + */ + public ProcessExecutor workingDirectory(final Path workingDir) { + this.workingDir = workingDir; + return this; + } + /** * Execute sub process defined by this {@link ProcessExecutor}. * @@ -65,7 +79,8 @@ public ProcessExecutor(final String... initialArgs) { public ProcessExecutor run(final String... args) throws IOException, InterruptedException { final List commandLine = new ArrayList<>(asList(this.initialArgs)); commandLine.addAll(asList(args)); - this.process = new ProcessBuilder(commandLine).redirectErrorStream(false).start(); + final File directory = workingDir == null ? null : workingDir.toAbsolutePath().toFile(); + this.process = new ProcessBuilder(commandLine).redirectErrorStream(false).directory(directory).start(); return this; } diff --git a/src/test/java/com/exasol/bucketfs/client/BucketFsClientExecutableJarIT.java b/src/test/java/com/exasol/bucketfs/client/BucketFsClientExecutableJarIT.java index 20751e7..89f08b7 100644 --- a/src/test/java/com/exasol/bucketfs/client/BucketFsClientExecutableJarIT.java +++ b/src/test/java/com/exasol/bucketfs/client/BucketFsClientExecutableJarIT.java @@ -4,8 +4,7 @@ import static com.exasol.bucketfs.BucketConstants.DEFAULT_BUCKETFS; import static com.exasol.bucketfs.Lines.lines; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.assertAll; import java.io.IOException; @@ -30,6 +29,9 @@ class BucketFsClientExecutableJarIT { private static ExasolContainer> EXASOL = new ExasolContainer<>()// .withRequiredServices(ExasolService.BUCKETFS).withReuse(true); + @TempDir + Path tempDir; + @Test void executableFailsWithoutArguments() throws Exception { final ProcessExecutor executor = ProcessExecutor.currentJar().run(); @@ -76,6 +78,22 @@ void copyFileFailsForNonExistingFile() throws Exception { equalTo(lines("E-BFSC-2: Unable to upload. No such file or directory: 'non-existing-file'.", ""))); } + @Test + void copyFileWithoutDirectory() throws Exception { + final Path tempFile = tempDir.resolve("test-file.txt"); + final String fileContent = "test file content"; + Files.writeString(tempFile, fileContent); + + final String fileName = tempFile.getFileName().toString(); + final String destination = getDefaultBucketUriToFile(fileName); + final String password = EXASOL.getClusterConfiguration().getDefaultBucketWritePassword(); + final ProcessExecutor executor = ProcessExecutor.currentJar().workingDirectory(tempDir) // + .run("cp", "--profile", "xxx", fileName, destination) // + .feedStdIn(password); + assertResult(executor, ExitCode.OK, equalTo("Password for writing to BucketFS: "), emptyString()); + assertThat(EXASOL.getDefaultBucket().downloadFileAsString(fileName), equalTo(fileContent)); + } + @Test void testVersion() throws Exception { final ProcessExecutor executor = ProcessExecutor.currentJar().run("--version"); @@ -95,8 +113,8 @@ private void assertResult(final ProcessExecutor executor, final int expectedExit final Matcher expectedStdOut, final Matcher expectedStdErr) throws InterruptedException, IOException { executor.assertProcessFinishes(); - assertAll(() -> assertThat(executor.getExitCode(), equalTo(expectedExitCode)), // - () -> assertThat(executor.getStdOut(), expectedStdOut), // - () -> assertThat(executor.getStdErr(), expectedStdErr)); + assertAll(() -> assertThat("exit code", executor.getExitCode(), equalTo(expectedExitCode)), // + () -> assertThat("std out", executor.getStdOut(), expectedStdOut), // + () -> assertThat("std err", executor.getStdErr(), expectedStdErr)); } } diff --git a/src/test/java/com/exasol/bucketfs/client/UploadCommandIT.java b/src/test/java/com/exasol/bucketfs/client/UploadCommandIT.java index 8feb5e4..8820275 100644 --- a/src/test/java/com/exasol/bucketfs/client/UploadCommandIT.java +++ b/src/test/java/com/exasol/bucketfs/client/UploadCommandIT.java @@ -22,6 +22,8 @@ import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junitpioneer.jupiter.ClearSystemProperty; import com.exasol.bucketfs.BucketAccessException; @@ -111,7 +113,7 @@ void testUploadWithReadPasswordRequired(@SysOut final Capturable stream) throws } @Test - void testSuccessUploadWithPassswordFromProfile() throws Exception { + void testSuccessUploadWithPasswordFromProfile() throws Exception { final Path configFile = this.tempDir.resolve(".bucketfs-client-config"); Files.writeString(configFile, lines("[other-profile]", "password.write=" + writePassword())); final BFSC client = createClient("cp", "--profile", "other-profile").withConfigFile(configFile); @@ -138,6 +140,14 @@ void testSuccessUploadToDirectory() throws Exception { verifyUpload(client, local, remote + FILENAME); } + @ParameterizedTest + @CsvSource({ "some_file", "./some_file" }) + void testSuccessUploadFile(final String localPath) throws Exception { + final String remote = "uploaded_file"; + final BFSC client = BFSC.create("cp", localPath, bfsUri(remote)).feedStdIn(writePassword()); + verifyUpload(client, Path.of("some_file"), remote); + } + private void verifyUpload(final BFSC client, final Path localFile, final String remotePath) throws BucketAccessException, IOException, InterruptedException { assertExitWithStatus(OK, () -> client.run()); diff --git a/src/test/java/com/exasol/bucketfs/url/BucketFsUrlTest.java b/src/test/java/com/exasol/bucketfs/url/BucketFsUrlTest.java index 678a5b3..b1854f3 100644 --- a/src/test/java/com/exasol/bucketfs/url/BucketFsUrlTest.java +++ b/src/test/java/com/exasol/bucketfs/url/BucketFsUrlTest.java @@ -89,7 +89,7 @@ void testGetDefaultPortWithTls() throws Exception { } @Test - void testGetProtocolWithouTls() throws Exception { + void testGetProtocolWithoutTls() throws Exception { assertThat(randomBucketFsUrl(false).getProtocol(), equalTo("bfs")); }