diff --git a/src/main/java/org/spigotmc/builder/Builder.java b/src/main/java/org/spigotmc/builder/Builder.java index e78dca7..a4c4259 100644 --- a/src/main/java/org/spigotmc/builder/Builder.java +++ b/src/main/java/org/spigotmc/builder/Builder.java @@ -47,9 +47,11 @@ import java.text.MessageFormat; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.EnumSet; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import java.util.jar.JarFile; import java.util.zip.ZipEntry; @@ -74,6 +76,7 @@ import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.FetchResult; +import org.eclipse.jgit.transport.RefSpec; import org.spigotmc.mapper.MapUtil; public class Builder @@ -89,6 +92,7 @@ public class Builder private static boolean generateDocs; private static boolean dev; private static boolean remapped; + private static List pullRequests; private static String applyPatchesShell = "sh"; private static boolean didClone = false; // @@ -163,6 +167,7 @@ public class Builder { } ).withValuesSeparatedBy( ',' ); OptionSpec compileIfChanged = parser.accepts( "compile-if-changed", "Run BuildTools only when changes are detected in the repository" ); + OptionSpec buildPullRequest = parser.acceptsAll( Arrays.asList( "pull-request", "pr" ), "Build specific pull requests" ).withOptionalArg().withValuesConvertedBy( new PullRequest.PullRequestConverter() ); OptionSet options = parser.parse( args ); @@ -181,6 +186,8 @@ public class Builder dev = options.has( devFlag ); remapped = options.has( remappedFlag ); compile = options.valuesOf( toCompile ); + pullRequests = options.valuesOf( buildPullRequest ); + validatedPullRequestsOptions(); if ( options.has( skipCompileFlag ) ) { compile = Collections.singletonList( Compile.NONE ); @@ -375,10 +382,10 @@ public class Builder if ( !dontUpdate ) { - boolean buildDataChanged = pull( buildGit, buildInfo.getRefs().getBuildData() ); - boolean bukkitChanged = pull( bukkitGit, buildInfo.getRefs().getBukkit() ); - boolean craftBukkitChanged = pull( craftBukkitGit, buildInfo.getRefs().getCraftBukkit() ); - boolean spigotChanged = pull( spigotGit, buildInfo.getRefs().getSpigot() ); + boolean buildDataChanged = pull( buildGit, buildInfo.getRefs().getBuildData(), null ); + boolean bukkitChanged = pull( bukkitGit, buildInfo.getRefs().getBukkit(), getPullRequest( Repository.BUKKIT ) ); + boolean craftBukkitChanged = pull( craftBukkitGit, buildInfo.getRefs().getCraftBukkit(), getPullRequest( Repository.CRAFTBUKKIT ) ); + boolean spigotChanged = pull( spigotGit, buildInfo.getRefs().getSpigot(), getPullRequest( Repository.SPIGOT ) ); // Checks if any of the 4 repositories have been updated via a fetch, the --compile-if-changed flag is set and none of the repositories were cloned in this run. if ( !buildDataChanged && !bukkitChanged && !craftBukkitChanged && !spigotChanged && options.has( compileIfChanged ) && !didClone ) @@ -654,7 +661,8 @@ public class Builder craftBukkitGit.checkout().setCreateBranch( true ).setForceRefUpdate( true ).setName( "patched" ).call(); craftBukkitGit.add().addFilepattern( "src/main/java/net/" ).call(); craftBukkitGit.commit().setSign( false ).setMessage( "CraftBukkit $ " + new Date() ).call(); - craftBukkitGit.checkout().setName( buildInfo.getRefs().getCraftBukkit() ).call(); + PullRequest craftBukkitPullRequest = getPullRequest( Repository.CRAFTBUKKIT ); + craftBukkitGit.checkout().setName( ( craftBukkitPullRequest == null ) ? buildInfo.getRefs().getCraftBukkit() : "origin/pr/" + craftBukkitPullRequest.getId() ).call(); FileUtils.moveDirectory( tmpNms, nmsDir ); @@ -818,7 +826,7 @@ public class Builder } } - public static boolean pull(Git repo, String ref) throws Exception + public static boolean pull(Git repo, String ref, PullRequest pullRequest) throws Exception { System.out.println( "Pulling updates for " + repo.getRepository().getDirectory() ); @@ -830,11 +838,26 @@ public class Builder System.err.println( "*** Warning, could not find origin/master ref, but continuing anyway." ); System.err.println( "*** If further errors occur please delete " + repo.getRepository().getDirectory().getParent() + " and retry." ); } - FetchResult result = repo.fetch().call(); + + FetchResult result; + if ( pullRequest != null ) + { + result = repo.fetch().setRefSpecs( new RefSpec( "+refs/pull-requests/" + pullRequest.getId() + "/from:refs/remotes/origin/pr/" + pullRequest.getId() ) ).call(); + } else + { + result = repo.fetch().call(); + } System.out.println( "Successfully fetched updates!" ); - repo.reset().setRef( ref ).setMode( ResetCommand.ResetType.HARD ).call(); + if ( pullRequest != null ) + { + repo.checkout().setName( "origin/pr/" + pullRequest.getId() ).setForced( true ).call(); + } else + { + repo.reset().setRef( ref ).setMode( ResetCommand.ResetType.HARD ).call(); + } + if ( ref.equals( "master" ) ) { repo.reset().setRef( "origin/master" ).setMode( ResetCommand.ResetType.HARD ).call(); @@ -845,6 +868,32 @@ public class Builder return !result.getTrackingRefUpdates().isEmpty(); } + public static PullRequest getPullRequest(Repository repository) + { + for ( PullRequest request : pullRequests ) + { + if ( request.getRepository() == repository ) + { + return request; + } + } + + return null; + } + + public static void validatedPullRequestsOptions() + { + Set repositories = EnumSet.noneOf( Repository.class ); + + for ( PullRequest pullRequest : pullRequests ) + { + if ( !repositories.add( pullRequest.getRepository() ) ) + { + throw new RuntimeException( "Pull request option for repository " + pullRequest.getRepository() + " is present multiple times. Only one per repository can be specified." ); + } + } + } + private static int runMavenInstall(File workDir, String... command) throws Exception { return runMaven0( workDir, false, false, command ); diff --git a/src/main/java/org/spigotmc/builder/PullRequest.java b/src/main/java/org/spigotmc/builder/PullRequest.java new file mode 100644 index 0000000..b2b51be --- /dev/null +++ b/src/main/java/org/spigotmc/builder/PullRequest.java @@ -0,0 +1,63 @@ +package org.spigotmc.builder; + +import java.util.Locale; +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class PullRequest +{ + + private Repository repository; + private int id; + + public static class PullRequestConverter implements ValueConverter + { + + @Override + public PullRequest convert(String value) + { + String[] values = value.split( ":" ); + + if ( values.length != 2 ) + { + throw new ValueConversionException( "Expected one ':' but got " + ( value.length() - 1 ) ); + } + + Repository repository; + try + { + repository = Repository.valueOf( values[0].toUpperCase( Locale.ROOT ) ); + } catch ( Exception e ) + { + throw new ValueConversionException( "Cannot parse " + values[0] + " to a repository", e ); + } + + int id; + try + { + id = Integer.parseInt( values[1] ); + } catch ( Exception e ) + { + throw new ValueConversionException( "Cannot parse " + values[1] + " to an integer", e ); + } + + return new PullRequest( repository, id ); + } + + @Override + public Class valueType() + { + return PullRequest.class; + } + + @Override + public String valuePattern() + { + return ":"; + } + } +} diff --git a/src/main/java/org/spigotmc/builder/Repository.java b/src/main/java/org/spigotmc/builder/Repository.java new file mode 100644 index 0000000..29f0005 --- /dev/null +++ b/src/main/java/org/spigotmc/builder/Repository.java @@ -0,0 +1,8 @@ +package org.spigotmc.builder; + +public enum Repository +{ + BUKKIT, + CRAFTBUKKIT, + SPIGOT; +}