How does quoting and escaping work for parameters passed to Maven plugins?
For example I want to pass multiple filenames as arguments to an application run by the Maven Exec plugin:
mvnDebug exec:java -Dexec.mainClass="Main" -Dexec.args="/path/to/file1 /path/to/file2"
But what if the paths have spaces?
I've tried using \":
-Dexec.args="\"/path/to/a file\" /path/to/file2"
and "":
-Dexec.args="""/path/to/a file"" /path/to/file2"
neither works :-(. Neither does moving the first quote before -D.
The source code for the Maven Exec plugin doesn't help me either, it receives a String[] from somewhere, but where?
Note that I must get this to work from the command line, without changes to the POM file.
You could try single quotes (') but I doubt that will work, either.
The problem is that you can have several argument elements inside the POM (hence the array in the plugin's source) but you have only a single property from the command line.
Options:
Patch the plugin and/or open a feature request to support several arguments (maybe exec.args.0, exec.args.1, exec.args.2, ...)
Create a module which depends on this project/module and where you can change the POM
Use an Ant or BASH script. I often use this approach to collect useful commands which aren't easily supported by Maven. mvn dependency:build-classpath -Dmdep.outputFile=... will give you the classpath in this case.
Related
So this problem is vexing me and I decided to ask a question because no answer out there was able to help, the problem is happening SPECIFICALLY to project.build.directory.
I have a Jenkins pipeline, and I need to build this string to deploy my artifact
#${project.build.directory}\${project.artifactId}_${project.version}.car
I am using the following to get some information from the pom.xml
script {
pom = readMavenPom file: 'pom.xml'
deployVersion = pom.properties.'deploy.version'}
So doing both
${deployVersion} and ${pom.version}
works perfectly, so there's no reason for ${pom.build.directory} not to work, but it doesn't. Nevertheless I decided to work around it and expose that property via the pom's properties, since I know the property works inside the pom, so I did, in my pom
<properties>
<build.dir>${project.build.directory}</build.dir>
</properties>
And that don't work either, after assigning pom.properties.'build.dir' to buildDir I get ${project.build.directory} as a literal
#${buildDir}\${pom.artifactId}_${pom.version}.car
I have no idea why this is happening or how to fix. Any ideas?
EDIT: The below was answered in the comments, either escape with another slash (\\) or use a forward slash (didn't test this one though)
Even more weird, the \ disapears and it don't convert pom.artifactId (which will convert properly if I call it without the build directory)
This is my build.gradle:
group 'whatever'
version '1.0.0-SNAPSHOT'
...
dependencies {
compile 'whatever:2.2.1-SNAPSHOT'
}
I want to automate releasing process, which includes the need to set both versions to particular values, e.g. 1.1.0 or 2.2.0 using command line only. Any kind of autoincrement is not an option.
With Maven, I'd do this using maven-versions-plugin:
mvn versions:set -DnewVersion=${WHATEVER_NEW_VERSION}
How can I do the same with Gradle? I only found this unanswered question. There must be some simple way to do that?
I ended up extracting version numbers to gradle.properties and updating them as part of the automated build script using sed:
sed -i -e \"/someVersionNumber=/ s/=.*/=${SOME_NEW_VERSION_NUMBER}/\" gradle.properties
It's what I want. Although for me, coming from the Maven background, this doesn't seem natural. I may research another alternative later.
Though not related to publishing, one way to pass command-line properties is as follows:
gradle -PWHATEVER_NEW_VERSION=2.0.0
Consider the following build.gradle snippet:
def newVersion = project."WHATEVER_NEW_VERSION"
println newVersion
See ~/utils/gradle/version.gradle in this project for another approach. It uses separate environment variables for major, minor, and incremental versions and then builds the string automatically. Because it resides in the gradle directory, it can simply be imported into build.gradle, which hides some boilerplate.
I successfully used Axion Release Plugin a couple of times and was very satisfied. Functionality-wise it comes the closest to what Maven's
Along the lines of this answer (which works for me, BTW) and the javadocs, I tried
gradle.startParameter.consoleOutput = org.gradle.api.logging.configuration.ConsoleOutput.Rich
in my ~/.gradle/init.gradle. However, I still need --console=rich to get color output. Why?
Tested with Gradle 2.14.1 and 3.2.1.
Terminal is cygwin urxvt with TERM variable set to rxvt-unicode-256color.
Since Gradle 4.3 you can use org.gradle.console property in gradle.properties:
org.gradle.console=rich
A new console verbose mode will print outcomes of all tasks (like UP-TO-DATE) like Gradle 3.5 and earlier did. You can set this via --console=verbose or by a new Gradle property org.gradle.console=(plain rich verbose).
I am not sure if you can force the rich console from a gradle script, as the detection happens likely before the script is interpreted.
NativeServices class provides the integration with the console. If you look at the source code, there are two messages possibly printed in log:
Native-platform terminal integration is not available. Continuing with fallback.
Unable to load from native-platform backed ConsoleDetector. Continuing with fallback.
The latter might give you more information why. Try running the gradle script with --debug. You will likely find out that you are missing a native library that is either not available in cygwin or it is, but is not on library path.
I believe it works when you specify the rich console from the command line, because gradle forces the colours even though the console doesn't indicate it supports them.
Does it work if you don't use the cygwin console in Windows native command line or maybe GitBash?
There is a workaround how you can make this work. You can create an alias in cygwin that will always add the --console=rich.
If you are using gradle wrapper, you can edit the gradlew script and add the command line parameter. To make it automated, you can change the wrapper task to alter your script in the doLast part.
Create a file called gradle.properties inside your ~/.gradle/ folder.
Inside gradle.properties, add the line org.gradle.console=rich.
Each builds will run under --console=rich automatically because the new gradle.properties will be merged with the gradle.properties of your project.
If your project's gradle.properties contains the same tag as the local file, your project's will be used overriding the local file's
If you are on Linux/Mac set
alias gradle='gradle --console rich'
in your ~/.bashrc.
In Gradle Wrapper, add the following line:
org.gradle.console=rich
to ./gradle.properties in the root folder, where the gradlew script is located.
As a test developer using cuke4duke with maven2, I want to be able to optionally select tests by tags on the cmd line. It seems that since maven doesn't have conditionals, the 'optionally' part requires a hack.
The cucumber arg might be e.g. "--tags #firstTag". One way to implement this is to have in pom.xml
<cucumberArgs>
...
<cucumberArg>${tagargs}</cucumberArg>
</cucumberArgs>
Then the cmd line has
mvn integration-test -Dtagargs="--tags #firstTag"
This works fine when I want to define tags, but when I don't include that -D argument (i.e. not selecting by tags), I get
[INFO] No such file or directory - null (Errno::ENOENT)
A workaround is to define ${tagargs} in properties as a duplicate of a cucumber arg I already use:
<properties>
<tagargs>--strict</tagargs>
</properties>
So, worst case is I get "--strict --strict". Is such a hack the best maven is capable of?
I've managed to work around this problem using an ignored negative tag. Note I'm using cuke4duke 0.4.4.
Define a default value for your property that runs all scenarios that are NOT tagged with "ignore" (call it whatever you like).
<properties>
<tagargs>--tags=~#ignore</tagargs>
</properties>
Maven will use this property when you do not pass in a specific value on the command line. Therefore all of your scenarios will match and execute.
I am having a similar problem as Ant produces jsfl with backslashes instead of slashes except that I'm running under Maven.
I'd like to generate cross-platform paths relative to Maven's built-in property ${basedir}. The problem is that under Windows, ${basedir} resolves to a path containing Windows-style slashes. Is there an easy way for me to get ${basedir} into a form that always uses Unix-style slashes even under Windows?
Answering my own question:
Use ${file.separator} instead of slash and watch out for bug MEXEC-81 which was fixed in 2010 by git commit 6e8be6881fe50714a00509f8f106e21d50d606a6 (svn: 12372) which was where quotes and backslashes were misinterpreted.
In the case of adding a dir to the library path, you are better off creating a new artifact with its own pom, installing it in your local repo and adding it as a dependency in the project.
Maven and Native Libraries: JDIC and java.library.path UPDATED goes into more detail about getting a native dependency into the library path.
Using native dependencies inside Maven Is another approach.