diff --git a/src/main/java/org/simplify4u/plugins/keysmap/ArtifactPattern.java b/src/main/java/org/simplify4u/plugins/keysmap/ArtifactPattern.java index 36e2ef80..c0416d0d 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/ArtifactPattern.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/ArtifactPattern.java @@ -38,6 +38,9 @@ class ArtifactPattern { private static final Pattern STAR_REPLACE = Pattern.compile("\\*"); private static final Pattern PACKAGING = Pattern.compile("^[a-zA-Z]+$"); + private static final String VERSION_REGEX_PREFIX = "~"; + private static final String NOT_VERSION_REGEX_PREFIX = "!~"; + /** * Original pattern from keysMap. Used to compare if object is equal to another. */ @@ -111,6 +114,18 @@ private static Function versionMatchPrepare(String versionToPre return version -> true; } + if (versionSpec.startsWith(VERSION_REGEX_PREFIX)) { + // check version against regular expression + Pattern versionRegex = Pattern.compile(versionSpec.substring(VERSION_REGEX_PREFIX.length())); + return version -> versionRegex.matcher(version).matches(); + } + + if (versionSpec.startsWith(NOT_VERSION_REGEX_PREFIX)) { + // check version against negated regular expression + Pattern versionRegex = Pattern.compile(versionSpec.substring(NOT_VERSION_REGEX_PREFIX.length())); + return version -> !versionRegex.matcher(version).matches(); + } + VersionRange versionRange = VersionRange.createFromVersionSpec(versionSpec); if (versionRange.hasRestrictions()) { // check version in range @@ -131,7 +146,9 @@ private static String versionSpecPrepare(String versionSpec) throws InvalidVersi return null; } - if (versionSpec.contains("*")) { + if (versionSpec.contains("*") + && !versionSpec.startsWith(VERSION_REGEX_PREFIX) + && !versionSpec.startsWith(NOT_VERSION_REGEX_PREFIX)) { throw new InvalidVersionSpecificationException("Invalid maven version range: " + versionSpec); } diff --git a/src/site/markdown/keysmap-format.md b/src/site/markdown/keysmap-format.md index 4b878d56..93a1b4e9 100644 --- a/src/site/markdown/keysmap-format.md +++ b/src/site/markdown/keysmap-format.md @@ -11,7 +11,7 @@ Where - `groupId` - groupId of Maven artifact, this field is required, but can be `*` for match any - `artifactId` - artifactId of Maven artifact - optional - `packaging` - packaging of Maven artifact, eg. `pom`, `jar` - optional -- `version` - version of Maven artifact, this filed support Maven version range syntax - optional +- `version` - version of Maven artifact, this field supports Maven version range syntax or regular expressions - optional - `pgpKeyFingerprint` - PGP key fingerprints in hex format which are allowed to sign artifact, multiple keys can be supplied separated by comma @@ -47,6 +47,18 @@ If line is ending with ` \ ` (backslash), break of line will be removed and next Whitespace and comments are allowed after ` \ `. +Version Regular Expressions +--------- + +When the version field begins with ` ~ ` (tilde), everything following the tilde is a case-insensitive regular +expression matched against artifact version. + +When the version field begins with ` !~ ` (not-tilde), everything following the not-tilde is a case-insensitive regular +expression with a negated match against artifact version. + +This may be used, for example, to have separate PGP signing keys for continuous integration snapshot builds, +while releases are signed by more protected PGP keys unavailable to the continuous integration platform. + Examples -------- @@ -85,6 +97,26 @@ match a specific artifact with the version and any packaging test.groupId:artifactId:1.0.0 = 0x1234567890123456789012345678901234567890 --- +match any artifact from group with any packaging and a SNAPSHOT version by regular expression + + test.groupId:*:~.*-SNAPSHOT$ = 0x1234567890123456789012345678901234567890 +--- + +match any artifact from group with any packaging and a non-SNAPSHOT version by negated regular expression + + test.groupId:*:!~.*-SNAPSHOT$ = 0x1234567890123456789012345678901234567890 +--- + +match a specific artifact with any packaging and a SNAPSHOT version by regular expression + + test.groupId:artifactId:~.*-SNAPSHOT$ = 0x1234567890123456789012345678901234567890 +--- + +match a specific artifact with specific packaging and a SNAPSHOT version by regular expression + + test.groupId:artifactId:jar:~.*-SNAPSHOT$ = 0x1234567890123456789012345678901234567890 +--- + match a specific artifact with any version and packaging and many keys test.groupId:artifactId = 0x1234567890123456789012345678901234567890, 0x1234567890123456789012345678901234567890, \ diff --git a/src/test/java/org/simplify4u/plugins/keysmap/ArtifactPatternTest.java b/src/test/java/org/simplify4u/plugins/keysmap/ArtifactPatternTest.java index 12375582..a04a8209 100644 --- a/src/test/java/org/simplify4u/plugins/keysmap/ArtifactPatternTest.java +++ b/src/test/java/org/simplify4u/plugins/keysmap/ArtifactPatternTest.java @@ -38,12 +38,29 @@ public Object[][] artifactsList() { {"test.group:test:3.0.0-M1", testArtifact().version("3.0.0-M1").build(), true}, {"test.group:test:3.0.0-M1", testArtifact().version("3.0.0-m1").build(), true}, {"test.group:test:1.1.1", testArtifact().build(), true}, + {"test.group:test:1.1.1", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:test:1.1.1-SNAPSHOT", testArtifact().version("1.1.1-SNAPSHOT").build(), true}, {"test.group:test:jar:1.1.1", testArtifact().build(), true}, {"test.group:test:pom:1.1.1", testArtifact().build(), false}, {"test.group:test:[1.1,2.0)", testArtifact().build(), true}, {"test.group:test:pom:[1.1,2.0)", testArtifact().build(), false}, + {"test.group:test:[1.1,2.0)", testArtifact().version("1.1.1-SNAPSHOT").build(), + // Expecting false once https://issues.apache.org/jira/browse/MNG-3092 is resolved + true}, {"test.group:test:[1.1,2.0)", testArtifact().version("2.0").build(), false}, {"test.group:test:1.1.1", testArtifact().version("1.1.2").build(), false}, + {"test.group:test:[1.1,1.1.1)", testArtifact().build(), false}, + {"test.group:test:[1.1,1.1.1)", testArtifact().version("1.1.1-SNAPSHOT").build(), + // Expecting false once https://issues.apache.org/jira/browse/MNG-3092 is resolved + true}, + {"test.group:test:[1.1,1.1.1-SNAPSHOT)", testArtifact().build(), false}, + {"test.group:test:[1.1,1.1.1-SNAPSHOT)", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:test:[1.1,1.1.1]", testArtifact().build(), true}, + {"test.group:test:[1.1,1.1.1]", testArtifact().version("1.1.1-SNAPSHOT").build(), + // Expecting false once https://issues.apache.org/jira/browse/MNG-3092 is resolved + true}, + {"test.group:test:[1.1,1.1.1-SNAPSHOT]", testArtifact().build(), false}, + {"test.group:test:[1.1,1.1.1-SNAPSHOT]", testArtifact().version("1.1.1-SNAPSHOT").build(), true}, {"test.group:test", testArtifact().build(), true}, {"test.group", testArtifact().build(), true}, {"test.group:*:jar", testArtifact().artifactId("test2").build(), true}, @@ -57,6 +74,35 @@ public Object[][] artifactsList() { {"test.*:test", testArtifact().build(), true}, {"test.*", testArtifact().build(), true}, {"*", testArtifact().build(), true}, + // Regular expression in version + {"test.group:test:~.*-SNAPSHOT$", testArtifact().build(), false}, + {"test.group:test:!~.*-SNAPSHOT$", testArtifact().build(), true}, + {"test.group:test:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), true}, + {"test.group:test:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:*:~.*-SNAPSHOT$", testArtifact().build(), false}, + {"test.group:*:!~.*-SNAPSHOT$", testArtifact().build(), true}, + {"test.group:*:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), true}, + {"test.group:*:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:*:jar:~.*-SNAPSHOT$", testArtifact().build(), false}, + {"test.group:*:jar:!~.*-SNAPSHOT$", testArtifact().build(), true}, + {"test.group:*:jar:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), true}, + {"test.group:*:jar:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:*:pom:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:*:pom:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:test:jar:~.*-SNAPSHOT$", testArtifact().build(), false}, + {"test.group:test:jar:!~.*-SNAPSHOT$", testArtifact().build(), true}, + {"test.group:test:jar:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), true}, + {"test.group:test:jar:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:test:pom:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:test:pom:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:other:jar:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:other:jar:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"other.group:test:jar:~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"other.group:test:jar:!~.*-SNAPSHOT$", testArtifact().version("1.1.1-SNAPSHOT").build(), false}, + {"test.group:test:jar:~.*-SNAPshot$", testArtifact().version("1.1.1-snapSHOT").build(), true}, + {"test.group:test:jar:!~.*-SNAPshot$", testArtifact().version("1.1.1-snapSHOT").build(), false}, + {"test.group:test:jar:~.*-snapSHOT$", testArtifact().version("1.1.1-SNAPshot").build(), true}, + {"test.group:test:jar:!~.*-snapSHOT$", testArtifact().version("1.1.1-SNAPshot").build(), false}, }; }