From 0c455ca4bee8cda34f857bb0e83b51393b078443 Mon Sep 17 00:00:00 2001 From: "AO Industries, Inc" Date: Fri, 3 Dec 2021 18:59:59 -0600 Subject: [PATCH] Added regular expression matching for artifact version 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. --- .../plugins/keysmap/ArtifactPattern.java | 19 +++++++- src/site/markdown/keysmap-format.md | 34 +++++++++++++- .../plugins/keysmap/ArtifactPatternTest.java | 46 +++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) 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}, }; }