Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
[JENKINS-43507] Mercurial would have to be difficult and need a regex
- Loading branch information
Showing
with
270 additions
and 1 deletion.
- +147 −0 src/main/java/jenkins/scm/impl/trait/RegexSCMHeadFilterTrait.java
- +1 −1 src/main/java/jenkins/scm/impl/trait/WildcardSCMHeadFilterTrait.java
- +1 −0 src/main/resources/jenkins/scm/impl/trait/Messages.properties
- +29 −0 src/main/resources/jenkins/scm/impl/trait/RegexSCMHeadFilterTrait/config.jelly
- +27 −0 src/main/resources/jenkins/scm/impl/trait/RegexSCMHeadFilterTrait/help-regex.html
- +65 −0 src/test/java/jenkins/scm/impl/trait/RegexSCMHeadFilterTraitTest.java
@@ -0,0 +1,147 @@ | ||
/* | ||
* The MIT License | ||
* | ||
* Copyright (c) 2017, CloudBees, Inc. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
package jenkins.scm.impl.trait; | ||
|
||
import edu.umd.cs.findbugs.annotations.CheckForNull; | ||
import edu.umd.cs.findbugs.annotations.NonNull; | ||
import hudson.Extension; | ||
import hudson.util.FormValidation; | ||
import java.util.regex.Pattern; | ||
import java.util.regex.PatternSyntaxException; | ||
import jenkins.scm.api.SCMHead; | ||
import jenkins.scm.api.SCMNavigator; | ||
import jenkins.scm.api.SCMSource; | ||
import jenkins.scm.api.trait.SCMHeadPrefilter; | ||
import jenkins.scm.api.trait.SCMNavigatorContext; | ||
import jenkins.scm.api.trait.SCMNavigatorRequest; | ||
import jenkins.scm.api.trait.SCMNavigatorTrait; | ||
import jenkins.scm.api.trait.SCMNavigatorTraitDescriptor; | ||
import jenkins.scm.api.trait.SCMSourceContext; | ||
import jenkins.scm.api.trait.SCMSourcePrefilter; | ||
import jenkins.scm.api.trait.SCMSourceRequest; | ||
import jenkins.scm.api.trait.SCMSourceTrait; | ||
import org.kohsuke.accmod.Restricted; | ||
import org.kohsuke.accmod.restrictions.NoExternalUse; | ||
import org.kohsuke.stapler.DataBoundConstructor; | ||
import org.kohsuke.stapler.QueryParameter; | ||
|
||
/** | ||
* Decorates a {@link SCMSource} with a {@link SCMHeadPrefilter} that excludes {@link SCMHead} instances with names that | ||
* do not match a user supplied regular expression. | ||
* | ||
* @since 2.2.0 | ||
*/ | ||
public class RegexSCMHeadFilterTrait extends SCMSourceTrait { | ||
|
||
/** | ||
* The regular expression. | ||
*/ | ||
@NonNull | ||
private final String regex; | ||
/** | ||
* The compiled {@link Pattern}. | ||
*/ | ||
@CheckForNull | ||
private transient Pattern pattern; | ||
|
||
/** | ||
* Stapler constructor. | ||
* | ||
* @param regex the regular expression. | ||
*/ | ||
@DataBoundConstructor | ||
public RegexSCMHeadFilterTrait(@NonNull String regex) { | ||
pattern = Pattern.compile(regex); | ||
this.regex = regex; | ||
} | ||
|
||
/** | ||
* Gets the regular expression. | ||
* | ||
* @return the regular expression. | ||
*/ | ||
@NonNull | ||
public String getRegex() { | ||
return regex; | ||
} | ||
|
||
/** | ||
* Gets the compiled {@link Pattern}. | ||
* | ||
* @return the compiled {@link Pattern}. | ||
*/ | ||
@NonNull | ||
private Pattern getPattern() { | ||
if (pattern == null) { | ||
// idempotent | ||
pattern = Pattern.compile(regex); | ||
} | ||
return pattern; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
protected <B extends SCMSourceContext<B, R>, R extends SCMSourceRequest> void decorateContext(B context) { | ||
context.withPrefilter(new SCMHeadPrefilter() { | ||
@Override | ||
public boolean isExcluded(@NonNull SCMSource source, @NonNull SCMHead head) { | ||
return !getPattern().matcher(head.getName()).matches(); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Our descriptor. | ||
*/ | ||
@Extension | ||
public static class DescriptorImpl extends SCMNavigatorTraitDescriptor { | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public String getDisplayName() { | ||
return Messages.RegexSCMHeadFilterTrait_DisplayName(); | ||
} | ||
|
||
/** | ||
* Form validation for the regular expression. | ||
* | ||
* @param value the regular expression. | ||
* @return the validation results. | ||
*/ | ||
@Restricted(NoExternalUse.class) // stapler | ||
public FormValidation doCheckRegex(@QueryParameter String value) { | ||
try { | ||
Pattern.compile(value); | ||
return FormValidation.ok(); | ||
} catch (PatternSyntaxException e) { | ||
return FormValidation.error(e.getMessage()); | ||
} | ||
} | ||
} | ||
} |
@@ -0,0 +1,29 @@ | ||
<!-- | ||
~ The MIT License | ||
~ | ||
~ Copyright (c) 2017, CloudBees, Inc. | ||
~ | ||
~ Permission is hereby granted, free of charge, to any person obtaining a copy | ||
~ of this software and associated documentation files (the "Software"), to deal | ||
~ in the Software without restriction, including without limitation the rights | ||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
~ copies of the Software, and to permit persons to whom the Software is | ||
~ furnished to do so, subject to the following conditions: | ||
~ | ||
~ The above copyright notice and this permission notice shall be included in | ||
~ all copies or substantial portions of the Software. | ||
~ | ||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
~ THE SOFTWARE. | ||
--> | ||
<?jelly escape-by-default='true'?> | ||
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form"> | ||
<f:entry title="${%Regular expression}" field="regex"> | ||
<f:textbox default=".*"/> | ||
</f:entry> | ||
</j:jelly> |
@@ -0,0 +1,27 @@ | ||
<!-- | ||
~ The MIT License | ||
~ | ||
~ Copyright (c) 2017, CloudBees, Inc. | ||
~ | ||
~ Permission is hereby granted, free of charge, to any person obtaining a copy | ||
~ of this software and associated documentation files (the "Software"), to deal | ||
~ in the Software without restriction, including without limitation the rights | ||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
~ copies of the Software, and to permit persons to whom the Software is | ||
~ furnished to do so, subject to the following conditions: | ||
~ | ||
~ The above copyright notice and this permission notice shall be included in | ||
~ all copies or substantial portions of the Software. | ||
~ | ||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
~ THE SOFTWARE. | ||
--> | ||
<div> | ||
A <a href="https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">Java regular expression</a> to | ||
restrict the names. Names that do not match the supplied regular expression will be ignored. | ||
</div> |
@@ -0,0 +1,65 @@ | ||
/* | ||
* The MIT License | ||
* | ||
* Copyright (c) 2017, CloudBees, Inc. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
package jenkins.scm.impl.trait; | ||
|
||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.TreeSet; | ||
import jenkins.scm.api.SCMHead; | ||
import jenkins.scm.api.SCMHeadObserver; | ||
import jenkins.scm.api.SCMRevision; | ||
import jenkins.scm.impl.mock.MockSCMController; | ||
import jenkins.scm.impl.mock.MockSCMDiscoverBranches; | ||
import jenkins.scm.impl.mock.MockSCMSource; | ||
import org.junit.ClassRule; | ||
import org.junit.Test; | ||
import org.jvnet.hudson.test.JenkinsRule; | ||
|
||
import static org.hamcrest.Matchers.containsInAnyOrder; | ||
import static org.junit.Assert.assertThat; | ||
|
||
public class RegexSCMHeadFilterTraitTest { | ||
@ClassRule | ||
public static JenkinsRule r = new JenkinsRule(); | ||
|
||
@Test | ||
public void given_sourceWithRegexRule_when_scanning_then_ruleApplied() throws Exception { | ||
MockSCMController c = MockSCMController.create(); | ||
try { | ||
c.createRepository("foo"); | ||
c.createBranch("foo", "fork"); | ||
c.createBranch("foo", "alt"); | ||
MockSCMSource src = new MockSCMSource("foo", c, "foo", new MockSCMDiscoverBranches(), new RegexSCMHeadFilterTrait("[fm].*")); | ||
Map<SCMHead, SCMRevision> result = src.fetch(null, SCMHeadObserver.collect(), null, null).result(); | ||
Set<String> names = new TreeSet<String>(); | ||
for (SCMHead h: result.keySet()) { | ||
names.add(h.getName()); | ||
} | ||
assertThat(names, containsInAnyOrder("master", "fork")); | ||
} finally { | ||
c.close(); | ||
} | ||
} | ||
} |