Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
merge pr/71 and resolve conflict
  • Loading branch information
nishio-dens committed Jan 31, 2016
2 parents 85dc025 + 96ab7a7 commit 6a9340e
Show file tree
Hide file tree
Showing 12 changed files with 771 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .gitignore
@@ -1,4 +1,4 @@
.idea
bitbucket-pullrequest-builder.iml
target
target/
work
11 changes: 11 additions & 0 deletions .travis.yml
@@ -0,0 +1,11 @@
language: java

jdk:
- openjdk7
- oraclejdk7

script:
mvn install -U

after_failure:
- cat target/surefire-reports/*.txt
23 changes: 17 additions & 6 deletions pom.xml
Expand Up @@ -3,15 +3,15 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.509.4</version><!-- which version of Jenkins is this plugin built against? -->
<version>1.509.4</version><!-- which version of Jenkins is this plugin built against? -->
</parent>

<artifactId>bitbucket-pullrequest-builder</artifactId>
<name>Bitbucket Pullrequest Builder Plugin</name>
<version>1.4.9-SNAPSHOT</version>
<version>1.4.13</version>
<description>This Jenkins plugin builds pull requests from Bitbucket.org and will report the test results.</description>
<packaging>hpi</packaging>
<url>https://wiki.jenkins-ci.org/display/JENKINS/Bitbucket+pullrequest+builder+plugin</url>
<url>https://wiki.jenkins-ci.org/display/JENKINS/Bitbucket+pullrequest+builder+plugin</url>

<scm>
<connection>scm:git:ssh://git@github.com/jenkinsci/bitbucket-pullrequest-builder-plugin.git</connection>
Expand All @@ -25,10 +25,10 @@
<name>nishio_dens</name>
<email>nishio@densan-labs.net</email>
</developer>
</developers>

</developers>
<!-- get every artifact through repo.jenkins-ci.org, which proxies all the artifacts that we need -->
<repositories>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
Expand Down Expand Up @@ -61,6 +61,17 @@
<artifactId>git</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0-rc3</version>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.4</version>
<scope>test</scope>
</dependency>
</dependencies>

<pluginRepositories>
Expand Down
@@ -0,0 +1,184 @@
package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder;

import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Matcher;
import jenkins.plugins.git.AbstractGitSCMSource;
import jenkins.scm.api.SCMSource;

/**
* Mutable wrapper
*/
class Mutable<T> {
private T value;
public Mutable() { this.value = null; }
public Mutable(T value) { this.value = value; }
T get() { return this.value; }
void set(T value) { this.value = value; }
}

abstract class Filter {
protected static final Logger logger = Logger.getLogger(BitbucketBuildTrigger.class.getName());

public static final String RX_FILTER_FLAG = "r";
public static final String RX_FILTER_FLAG_SINGLE = RX_FILTER_FLAG + ":";

public static final String SRC_RX = "s:(" + RX_FILTER_FLAG_SINGLE + ")?";
public static final String DST_RX = "d:(" + RX_FILTER_FLAG_SINGLE + ")?";
public static final String BRANCH_FILTER_RX_PART = "([^\\s$]*)";

abstract public boolean apply(String filter, BitbucketCause cause);
abstract public boolean check(String filter);

static final Pattern RX_SRC_DST_PARTS = Pattern.compile("(s:)|(d:)");
public static boolean HasSourceOrDestPartsPredicate(String filter) { return RX_SRC_DST_PARTS.matcher(filter).find(); }
}

class EmptyFilter extends Filter {
@Override
public boolean apply(String filter, BitbucketCause cause) { return true; }
@Override
public boolean check(String filter) { return true; }
}

class AnyFlag extends Filter {
@Override
public boolean apply(String filter, BitbucketCause cause) { return true; }
@Override
public boolean check(String filter) { return filter.isEmpty() || filter.contains("*") || filter.toLowerCase().contains("any"); }
}

class OnlySourceFlag extends Filter {
@Override
public boolean apply(String filter, BitbucketCause cause) {
String selectedRx = filter.startsWith(RX_FILTER_FLAG_SINGLE) ? filter.substring(RX_FILTER_FLAG_SINGLE.length()) : Pattern.quote(filter);
logger.log(Level.INFO, "OnlySourceFlag using filter: {0}", selectedRx);
Matcher matcher = Pattern.compile(selectedRx, Pattern.CASE_INSENSITIVE).matcher(cause.getSourceBranch());
return filter.startsWith(RX_FILTER_FLAG_SINGLE) ? matcher.find() : matcher.matches();
}
@Override
public boolean check(String filter) {
return false;
}
}

class OnlyDestFlag extends Filter {
@Override
public boolean apply(String filter, BitbucketCause cause) {
String selectedRx = filter.startsWith(RX_FILTER_FLAG_SINGLE) ? filter.substring(RX_FILTER_FLAG_SINGLE.length()) : Pattern.quote(filter);
logger.log(Level.INFO, "OnlyDestFlag using filter: {0}", selectedRx);
Matcher matcher = Pattern.compile(selectedRx, Pattern.CASE_INSENSITIVE).matcher(cause.getTargetBranch());
return filter.startsWith(RX_FILTER_FLAG_SINGLE) ? matcher.find() : matcher.matches();
}
@Override
public boolean check(String filter) {
return !HasSourceOrDestPartsPredicate(filter);
}
}

class SourceDestFlag extends Filter {
static final Pattern SRC_MATCHER_RX = Pattern.compile(SRC_RX + BRANCH_FILTER_RX_PART, Pattern.CASE_INSENSITIVE | Pattern.CANON_EQ);
static final Pattern DST_MATCHER_RX = Pattern.compile(DST_RX + BRANCH_FILTER_RX_PART, Pattern.CASE_INSENSITIVE | Pattern.CANON_EQ);

boolean applyByRx(Pattern rx, Filter usedFilter, String filter, BitbucketCause cause) {
Matcher srcMatch = rx.matcher(filter);
boolean apply = rx.matcher(filter).matches();
while (srcMatch.find()) {
String computedFilter = ((srcMatch.group(1) == null ? "" : srcMatch.group(1)) + srcMatch.group(2)).trim();
logger.log(Level.INFO, "Apply computed filter: {0}", computedFilter);
apply = apply || (computedFilter.isEmpty() ? true : usedFilter.apply(computedFilter, cause));
}
return apply;
}

@Override
public boolean apply(String filter, BitbucketCause cause) {
return this.applyByRx(SRC_MATCHER_RX, new OnlySourceFlag(), filter, cause) &&
this.applyByRx(DST_MATCHER_RX, new OnlyDestFlag(), filter, cause);
}
@Override
public boolean check(String filter) {
return HasSourceOrDestPartsPredicate(filter);
}
}

/**
* Created by maxvodo
*/
public class BitbucketBuildFilter {
private static final Logger logger = Logger.getLogger(BitbucketBuildTrigger.class.getName());

private final String filter;
private Filter currFilter = null;
private static final List<Filter> AvailableFilters;

static {
ArrayList<Filter> filters = new ArrayList<Filter>();
filters.add(new AnyFlag());
filters.add(new OnlyDestFlag());
filters.add(new SourceDestFlag());
filters.add(new EmptyFilter());
AvailableFilters = filters;
}

public BitbucketBuildFilter(String f) {
this.filter = (f != null ? f : "").trim();
this.buildFilter(this.filter);
}

private void buildFilter(String filter) {
logger.log(Level.INFO, "Build filter by phrase: {0}", filter);
for(Filter f : AvailableFilters) {
if (f.check(filter)) {
this.currFilter = f;
logger.log(Level.INFO, "Using filter: {0}", f.getClass().getSimpleName());
break;
}
}
}

public boolean approved(BitbucketCause cause) {
logger.log(Level.INFO, "Approve cause: {0}", cause.toString());
return this.currFilter.apply(this.filter, cause);
}

public static BitbucketBuildFilter InstanceByString(String filter) {
logger.log(Level.INFO, "Filter instance by filter string");
return new BitbucketBuildFilter(filter);
}

static public String FilterFromGitSCMSource(AbstractGitSCMSource gitscm, String defaultFilter) {
if (gitscm == null) {
logger.log(Level.INFO, "Git SCMSource unavailable. Using default value: {0}", defaultFilter);
return defaultFilter;
}

String filter = defaultFilter;
final String includes = gitscm.getIncludes();
if (includes != null && !includes.isEmpty()) {
for(String part : includes.split("\\s+")) {
filter += String.format("%s ", part.replaceAll("\\*\\/", "d:"));
}
}

logger.log(Level.INFO, "Git includes transformation to filter result: {1} -> {0}; default: {2}", new Object[]{ filter, includes, defaultFilter });
return filter.trim();
}

public static BitbucketBuildFilter InstanceBySCM(Collection<SCMSource> scmSources, String defaultFilter) {
logger.log(Level.INFO, "Filter instance by using SCMSources list with {0} items", scmSources.size());
AbstractGitSCMSource gitscm = null;
for(SCMSource scm : scmSources) {
logger.log(Level.INFO, "Check {0} SCMSource ", scm.getClass());
if (scm instanceof AbstractGitSCMSource) {
gitscm = (AbstractGitSCMSource)scm;
break;
}
}
return new BitbucketBuildFilter(FilterFromGitSCMSource(gitscm, defaultFilter));
}
}
Expand Up @@ -28,16 +28,18 @@ public class BitbucketBuildTrigger extends Trigger<AbstractProject<?, ?>> {
private final String password;
private final String repositoryOwner;
private final String repositoryName;
private final String branchesFilter;
private final boolean branchesFilterBySCMIncludes;
private final String ciKey;
private final String ciName;
private final String ciSkipPhrases;
private final boolean checkDestinationCommit;
private final boolean approveIfSuccess;

transient private BitbucketPullRequestsBuilder bitbucketPullRequestsBuilder;

@Extension
public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor();
public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor();

@DataBoundConstructor
public BitbucketBuildTrigger(
Expand All @@ -47,6 +49,8 @@ public BitbucketBuildTrigger(
String password,
String repositoryOwner,
String repositoryName,
String branchesFilter,
boolean branchesFilterBySCMIncludes,
String ciKey,
String ciName,
String ciSkipPhrases,
Expand All @@ -60,6 +64,8 @@ public BitbucketBuildTrigger(
this.password = password;
this.repositoryOwner = repositoryOwner;
this.repositoryName = repositoryName;
this.branchesFilter = branchesFilter;
this.branchesFilterBySCMIncludes = branchesFilterBySCMIncludes;
this.ciKey = ciKey;
this.ciName = ciName;
this.ciSkipPhrases = ciSkipPhrases;
Expand Down Expand Up @@ -91,6 +97,14 @@ public String getRepositoryName() {
return repositoryName;
}

public String getBranchesFilter() {
return branchesFilter;
}

public boolean getBranchesFilterBySCMIncludes() {
return branchesFilterBySCMIncludes;
}

public String getCiKey() {
return ciKey;
}
Expand All @@ -102,7 +116,7 @@ public String getCiName() {
public String getCiSkipPhrases() {
return ciSkipPhrases;
}

public boolean getCheckDestinationCommit() {
return checkDestinationCommit;
}
Expand Down
Expand Up @@ -2,9 +2,11 @@

import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.Pullrequest;
import hudson.model.AbstractProject;
import java.security.MessageDigest;

import java.util.Collection;
import java.util.logging.Logger;
import org.apache.commons.codec.binary.Hex;

/**
* Created by nishio
Expand Down Expand Up @@ -50,6 +52,16 @@ public void setTrigger(BitbucketBuildTrigger trigger) {

public AbstractProject<?, ?> getProject() {
return this.project;
}

public String getProjectId() {
try {
final MessageDigest MD5 = MessageDigest.getInstance("MD5");
return new String(Hex.encodeHex(MD5.digest(this.project.getFullName().getBytes("UTF-8"))));
} catch (Exception exc) {
logger.severe(exc.toString());
}
return this.project.getFullName();
}

public BitbucketBuildTrigger getTrigger() {
Expand Down

0 comments on commit 6a9340e

Please sign in to comment.