之前我发布了一个关于如何从命令行更改Maven项目版本的问题,这导致我遇到了一个新问题。
以前我能够获得版本号,因为版本存储为一个属性,很容易从命令行(bash)进行grep和解析。现在pom.xml <version>元素用于此,它不再是唯一的,因为所有依赖项(也许其他一些依赖项也使用它)。我认为,如果没有用于解析XML的外部工具或一些非常能感知上下文的sed命令,就无法用bash脚本获得当前版本号。
在我看来,最干净的解决方案是Maven发布这个版本信息。我想写一个自定义的maven插件检索不同的属性,但我想我应该先问这里。
那么,是否有任何简单的方法来获取${project的值。版本}到命令行?
解决方案
我必须手动cd到该目录,但这可以很容易地做到。在我的bash脚本我有:
version=`cd $project_loc && mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | sed -n -e '/^\[.*\]/ !{ /^[0-9]/ { p; q } }'`
这就得到了我可以改进的当前版本。Grepping可能更简单,但我认为我想尽可能健壮,所以我对以数字开头的第一行感到满意,并尝试将其作为版本号处理。
# Advances the last number of the given version string by one.
function advance_version () {
local v=$1
# Get the last number. First remove any suffixes (such as '-SNAPSHOT').
local cleaned=`echo $v | sed -e 's/[^0-9][^0-9]*$//'`
local last_num=`echo $cleaned | sed -e 's/[0-9]*\.//g'`
local next_num=$(($last_num+1))
# Finally replace the last number in version string with the new one.
echo $v | sed -e "s/[0-9][0-9]*\([^0-9]*\)$/$next_num/"
}
我通过调用:
new_version=$(advance_version $version)
如果您不介意将版本写入临时文件,那么还有另一种解决方案(不含grep/sed)适合我。(编辑:请参阅rjrjr的回答,这是一个更简单的解决方案,没有任何临时文件的麻烦)
我使用Exec Maven插件和echo二进制文件。与Maven Help Plugin相反,Exec Plugin允许输出重定向到文件,可以用来绕过grep/sed,甚至可以解析奇怪的东西,比如多行版本字符串(版本标记中带有CDATA块),至少在一定程度上是这样。
#!/usr/bin/env sh
MVN_VERSION=""
VERSION_FILE=$( mktemp mvn_project_version_XXXXX )
trap "rm -f -- \"$VERSION_FILE\"" INT EXIT
mvn -Dexec.executable="echo" \
-Dexec.args='${project.version}' \
-Dexec.outputFile="$VERSION_FILE" \
--non-recursive \
--batch-mode \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 ||
{ echo "Maven invocation failed!" 1>&2; exit 1; }
# if you just care about the first line of the version, which will be
# sufficent for pretty much every use case I can imagine, you can use
# the read builtin
[ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE"
# Otherwise, you could use cat.
# Note that this still has issues when there are leading whitespaces
# in the multiline version string
#MVN_VERSION=$( cat "$VERSION_FILE" )
printf "Maven project version: %s\n" "$MVN_VERSION"
如果您不介意将版本写入临时文件,那么还有另一种解决方案(不含grep/sed)适合我。(编辑:请参阅rjrjr的回答,这是一个更简单的解决方案,没有任何临时文件的麻烦)
我使用Exec Maven插件和echo二进制文件。与Maven Help Plugin相反,Exec Plugin允许输出重定向到文件,可以用来绕过grep/sed,甚至可以解析奇怪的东西,比如多行版本字符串(版本标记中带有CDATA块),至少在一定程度上是这样。
#!/usr/bin/env sh
MVN_VERSION=""
VERSION_FILE=$( mktemp mvn_project_version_XXXXX )
trap "rm -f -- \"$VERSION_FILE\"" INT EXIT
mvn -Dexec.executable="echo" \
-Dexec.args='${project.version}' \
-Dexec.outputFile="$VERSION_FILE" \
--non-recursive \
--batch-mode \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 ||
{ echo "Maven invocation failed!" 1>&2; exit 1; }
# if you just care about the first line of the version, which will be
# sufficent for pretty much every use case I can imagine, you can use
# the read builtin
[ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE"
# Otherwise, you could use cat.
# Note that this still has issues when there are leading whitespaces
# in the multiline version string
#MVN_VERSION=$( cat "$VERSION_FILE" )
printf "Maven project version: %s\n" "$MVN_VERSION"
在做了一些研究之后,我发现了以下几点:
Maven一直被指责,因为与DevOps工具的集成并不容易,因为它没有遵循一些关于CLI工具的良好实践,例如:
http://www.faqs.org/docs/artu/ch01s06.html (not available anymore)
"The Unix Way"
(ii) Expect the output of every program to become the input of another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input.
What does it actually mean?
Your output should be:
"grepable": (One "record" per line)
"cutable": (Delimited "fields")
exit codes: 0 for success, nonzero for failure.
messaging (stderr) vs. output (stdout)
(参考:Dave Copeland于2012年1月18日用ruby制作很棒的命令行应用程序https://youtu.be/1ILEw6Qca3U?t=372)
Honesty I think Dave Copeland was right when he said that maven does't play fairly with others. So I decided to give a look to maven's source code as well as to maven-help-plugin's source code as well. It seems that they have fixed a little bit the maven's -q switch (I was using version 3.5.3 at that time), so now if you pass it, you won't get all the annoying non-sense logging stuff that prevents maven from being used within automated scripts. So you should be able to use something like this:
mvn help:evaluate -Dexpression=project.version -q
问题是这个命令不会输出任何东西,因为默认情况下,帮助插件通过记录器输出,而记录器已被-q开关静音。(当时插件的最新可用版本是2018年6月3日发布的3.1.0)
Karl Heinz Marbaise (https://github.com/khmarbaise)通过添加一个可选参数来修复它,允许你以以下方式调用它:
mvn help:evaluate -Dexpression=project。version -q -DforceStdout
提交描述可在以下网站获得:(https://github.com/apache/maven-help-plugin/commit/316656983d780c04031bbadd97d4ab245c84d014)
同样,您应该始终验证命令的退出码,并在unix上将所有stderr重定向到/dev/null。