在混合的Mac/Windows/Linux开发团队中,使用Maven和Git。某些文件和文件夹包含:
(COLON),除Windows上以外,无处不在。具体来说,这是Apache Sling/Adobe AEM使用的jcr:content
文件夹。
使用git克隆该项目时,它会失败,因为它无法创建这些文件/文件夹。
是否可以检查这些平台上不允许的字符的所有文件吗?我想让Maven构建失败,以便开发人员知道将文件夹重命名,以便在所有平台上工作。
我已经搜索了Maven插件,但是没有发现任何可以完成这项工作的东西。如果可以作为git钩,那将是一个合适的选择,但是我在这里也看不到可行的。
为了在目录包含不必要的字符时构建失败,您可以使用Maven Enforcer插件,并编写一个可以执行此检查的自定义规则,因为没有专用规则为此。
也就是说,您还可以为此目的使用evaluateBeanshell
规则:此规则评估Beanshell代码,如果脚本返回false
,则将失败。在这种情况下,该规则使用FileUtils.getDirectoryNames
,该方法返回递归匹配的目录列表的方法包括/排除从基本目录开始的蚂蚁样式模式。在以下内容中,匹配了包含:
的src
目录下的所有目录;该列表必须是空的,才能继续进行。
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-beanshell</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<evaluateBeanshell>
<condition>org.codehaus.plexus.util.FileUtils.getDirectoryNames(new File("src"), "**/*:*", null, false).isEmpty()</condition>
</evaluateBeanshell>
</rules>
</configuration>
</execution>
</executions>
</plugin>
plexus utils已经是该插件的依赖性,因此您无需再次添加它,但是如果将来版本没有它,则可能仍然可以使用它。所有路径均相对于项目的基本目录,因此无需在文件中指定它以从。
启动搜索。还请注意,此仅在src
目录下检查文件;如果您也想检查其他目录,则可以添加更多条件。此外,它在validate
阶段运行,因此,如果要检查构建过程中生成的文件夹,您需要使用另一个阶段。
可以使用git钩阻断文件名:
https://github.com/t-b/git-pre-commit-hook-windows-filenames/blob/master/pre-commit
#!/bin/bash
#
# Copyright thomas dot braun aeht virtuell minus zuhause dot de, 2013
#
# A hook script to check that the to-be-commited files are valid
# filenames on a windows platform.
# Sources:
# - http://stackoverflow.com/a/62888
# - http://msdn.microsoft.com/en-us/library/aa365247.aspx
#
# To enable this hook, rename this file to "pre-commit", move it to ".git/hook" and make it executable.
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=
fi
enforcecompatiblefilenames=$(git config hooks.enforcecompatiblefilenames)
# Redirect output to stderr.
exec 1>&2
if test "$enforcecompatiblefilenames" != "true"
then
exit 0
fi
git diff --cached --name-only --diff-filter=A -z $against | while IFS= read -r -d '' filename; do
# Non-printable characters from ASCII range 0-31
nonprintablechars=$(echo -n "$filename" | LC_ALL=C tr -d '[ -~]' | wc -c)
# Illegal characters: < > : " / | ? *
# We don't test for / (forward slash) here as that is even on *nix not allowed in *filename*
illegalchars=$(echo -n "$filename" | LC_ALL=C grep -E '(<|>|:|"|\|||?|*)' | wc -c)
# Reserved names plus possible extension
# CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9
reservednames=$(echo -n "$filename" | LC_ALL=C grep -i -E '(CON|PRN|AUX|NUL|COM1|COM2|COM3|COM4|COM5|COM6|COM7|COM8|COM9|LPT1|LPT2|LPT3|LPT4|LPT5|LPT6|LPT7|LPT8|LPT9).[a-z]{3}' | wc -c)
# No trailing period or space
trailingperiodorspace=$(echo -n "$filename" | LC_ALL=C grep -E '(.| )$' | wc -c)
# File name is all periods
filenameallperiods=$(echo -n "$filename" | LC_ALL=C grep -E '^.+$' | wc -c)
# Check complete path length to be smaller than 260 characters
# This test can not be really accurate as we don't know if PWD on the windows filesystem itself is not very long
absolutepathtoolong=0
if test $(echo "$filename" | wc -c) -ge 260
then
absolutepathtoolong=1
fi
# debug output
if test -n "$GIT_TRACE"
then
echo "File: ${filename}"
echo nonprintablechars=$nonprintablechars
echo illegalchars=$illegalchars
echo reservednames=$reservednames
echo trailingperiodorspace=$trailingperiodorspace
echo filenameallperiods=$filenameallperiods
echo absolutepathtoolong=$absolutepathtoolong
fi
if test $nonprintablechars -ne 0
|| test $illegalchars -ne 0
|| test $reservednames -ne 0
|| test $trailingperiodorspace -ne 0
|| test $filenameallperiods -ne 0
|| test $absolutepathtoolong -ne 0
then
echo "Error: Attempt to add a file name which is incompatible to windows file systems."
echo
echo "If you know what you are doing you can disable this"
echo "check using:"
echo
echo "git config hooks.enforcecompatiblefilenames false"
echo
exit 1
fi
done
这是为每个开发人员在本地安装的缺点,因为不幸的是,并非所有Git Repo Services支持服务器端挂钩(查看您,GitHub)。
感谢您的beanshell解决方案,它确实对我有帮助。我也想显示我的答案,因为我还使用正则表达式和一些调试消息来帮助了解发生了什么。这在我的机器(TM)上起作用:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>migration-filename-convention</id>
<goals>
<goal>enforce</goal>
</goals>
<phase>validate</phase>
<configuration>
<rules>
<evaluateBeanshell>
<condition>
List filenames = org.codehaus.plexus.util.FileUtils.getFileNames(
new File("src"),
"**/*.sql",
null,
false);
for (Iterator it = filenames.iterator(); it.hasNext();) {
String file = it.next();
print("Found SQL file: " + file);
passesValidation = java.util.regex.Pattern.matches("^.+[\/\\]V[0-9]{4}([0-1][0-9])([0-3][0-9])[0-9]{6}__BDV.sql$", file);
if (passesValidation) {
print("Filename passes validation");
it.remove();
} else {
print("Did not pass validation");
};
};
filenames.isEmpty()</condition>
</evaluateBeanshell>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
这里的优势是beanshell代码更可读,并且在此过程中打印出它所找到的文件:
[INFO]
[INFO] --- maven-enforcer-plugin:1.4.1:enforce (migration-filename-convention) @ inventory-microservice ---
Found SQL file: mainresourcesdatabaseV20170803113900__BDV.sql
Filename passes validation
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
这可以用来验证SQL脚本遵循基于时间戳的文件名约定。
它也附在验证Maven生命周期上,因此mvn validate
也将调用。