如何检查Maven项目中的文件名是否包含某些字符(然后构建失败)?

时间:2017-02-20 10:19:50

标签: git maven aem

在混合的Mac / Windows / Linux开发团队中,使用Maven和Git。某些文件和文件夹包含:(冒号),除Windows上外,它在任何地方都有效。具体来说,这是Apache Sling / Adob​​e AEM使用的jcr:content文件夹。

使用Git克隆项目时,它会失败,因为它无法创建这些文件/文件夹。

是否可以检查这些平台上不允许的字符的所有文件?我想失败Maven构建,以便开发人员知道重命名该文件夹,以便它可以在所有平台上运行。

我搜索了Maven插件,但没有找到任何可能做这项工作的人。如果它可以作为Git钩子,那将是一个合适的选择,但我在这里也看不到任何可行的东西。

3 个答案:

答案 0 :(得分:3)

为了在目录包含不需要的字符时使构建失败,您可以使用执行此检查的Maven Enforcer Pluginwrite a custom rule,因为没有专门的规则。

也就是说,您也可以使用evaluateBeanshell规则来实现此目的:如果脚本返回false,此规则将评估Beanshell代码并使构建失败。在这种情况下,规则使用FileUtils.getDirectoryNames,该方法返回以递归方式匹配的目录列表包括/排除从基本目录开始的Ant样式模式。在下文中,匹配名称中包含冒号src的{​​{1}}目录下的所有目录;该列表必须为空才能继续构建。

:

Plexus Utils is already a dependency of the plugin,因此您无需再次添加它,但如果以后的版本没有它,最好仍然这样做。所有路径都相对于项目的基本目录,因此无需在文件中指定它以开始搜索。

另请注意,这仅检查<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> 目录下的文件;如果您还想检查其他目录,可以添加更多条件。此外,它运行在src阶段,因此如果要检查在构建期间生成的文件夹,您将需要使用另一个阶段。

答案 1 :(得分:0)

可以使用Git Hooks来阻止文件名:

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服务都支持服务器端挂钩(看着你,GitHub)。

答案 2 :(得分:0)

感谢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: main\resources\database\V20170803113900__BDV.sql
Filename passes validation
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

这可用于验证SQL脚本是否遵循基于时间戳的文件名约定。

它也附加到验证Maven生命周期,因此mvn validate也会调用它。