summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authormd_5 <git@md-5.net>2014-11-26 16:56:48 +1100
committermd_5 <git@md-5.net>2014-11-28 17:10:15 +1100
commit032e8ca0a3a2fd6059308ca43083df986467b99e (patch)
tree29a154dcfab98c5390ef6502c604509b884ea2d8 /src
downloadbuildtools-032e8ca0a3a2fd6059308ca43083df986467b99e.tar
buildtools-032e8ca0a3a2fd6059308ca43083df986467b99e.tar.gz
buildtools-032e8ca0a3a2fd6059308ca43083df986467b99e.tar.lz
buildtools-032e8ca0a3a2fd6059308ca43083df986467b99e.tar.xz
buildtools-032e8ca0a3a2fd6059308ca43083df986467b99e.zip
Initial Commit
For more information please see http://www.spigotmc.org/
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/spigotmc/builder/Builder.java411
1 files changed, 411 insertions, 0 deletions
diff --git a/src/main/java/org/spigotmc/builder/Builder.java b/src/main/java/org/spigotmc/builder/Builder.java
new file mode 100644
index 0000000..c8248b4
--- /dev/null
+++ b/src/main/java/org/spigotmc/builder/Builder.java
@@ -0,0 +1,411 @@
+package org.spigotmc.builder;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Predicate;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Iterables;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Files;
+import com.google.common.io.Resources;
+import difflib.DiffUtils;
+import difflib.Patch;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URL;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.io.FileUtils;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.ResetCommand;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+public class Builder
+{
+
+ public static final boolean IS_WINDOWS = System.getProperty( "os.name" ).startsWith( "Windows" );
+ public static final boolean IS_MAC = System.getProperty( "os.name" ).startsWith( "Mac" );
+ public static final File CWD = new File( "." );
+ public static final String MC_VERSION = "1.8";
+
+ public static void main(String[] args) throws Exception
+ {
+ if ( IS_MAC )
+ {
+ System.out.println( "Sorry, but Macintosh is not currently a supported platform for compilation at this time." );
+ System.out.println( "Please run this script on a Windows or Linux PC and then copy the jars to this computer." );
+ return;
+ }
+
+ try
+ {
+ runProcess( "bash -c exit", CWD );
+ } catch ( Exception ex )
+ {
+ System.out.println( "You must run this jar through bash (msysgit)" );
+ return;
+ }
+
+ try
+ {
+ runProcess( "git config --global user.name", CWD );
+ } catch ( Exception ex )
+ {
+ System.out.println( "Git name not set, setting it to default value." );
+ runProcess( "git config --global user.name BuildTools", CWD );
+ }
+ try
+ {
+ runProcess( "git config --global user.email", CWD );
+ } catch ( Exception ex )
+ {
+ System.out.println( "Git email not set, setting it to default value." );
+ runProcess( "git config --global user.email unconfigured@null.spigotmc.org", CWD );
+ }
+
+ File workDir = new File( "work" );
+ workDir.mkdir();
+
+ File bukkit = new File( "Bukkit" );
+ if ( !bukkit.exists() )
+ {
+ clone( "https://hub.spigotmc.org/stash/scm/spigot/bukkit.git", bukkit );
+ }
+
+ File craftBukkit = new File( "CraftBukkit" );
+ if ( !craftBukkit.exists() )
+ {
+ clone( "https://hub.spigotmc.org/stash/scm/spigot/craftbukkit.git", craftBukkit );
+ }
+
+ File spigot = new File( "Spigot" );
+ if ( !spigot.exists() )
+ {
+ clone( "https://hub.spigotmc.org/stash/scm/spigot/spigot.git", spigot );
+ }
+
+ File buildData = new File( "BuildData" );
+ if ( !buildData.exists() )
+ {
+ clone( "https://hub.spigotmc.org/stash/scm/spigot/builddata.git", buildData );
+ }
+
+ File maven = new File( "apache-maven-3.2.3" );
+ if ( !maven.exists() )
+ {
+ System.out.println( "Maven does not exist, downloading. Please wait." );
+
+ File mvnTemp = new File( "mvn.zip" );
+ mvnTemp.deleteOnExit();
+
+ download( "http://static.spigotmc.org/maven/apache-maven-3.2.3-bin.zip", mvnTemp );
+ unzip( mvnTemp, new File( "." ) );
+ }
+
+ String mvnCmd = maven.getAbsolutePath() + "/bin/mvn";
+ if ( IS_WINDOWS )
+ {
+ mvnCmd += ".bat";
+ } else
+ {
+ mvnCmd = "/bin/sh " + mvnCmd;
+ }
+
+ Git bukkitGit = Git.open( bukkit );
+ Git craftBukkitGit = Git.open( craftBukkit );
+ Git spigotGit = Git.open( spigot );
+ Git buildGit = Git.open( buildData );
+
+ pull( bukkitGit );
+ pull( craftBukkitGit );
+ pull( spigotGit );
+ pull( buildGit );
+
+ File vanillaJar = new File( workDir, "minecraft_server." + MC_VERSION + ".jar" );
+ if ( !vanillaJar.exists() )
+ {
+ download( String.format( "https://s3.amazonaws.com/Minecraft.Download/versions/%1$s/minecraft_server.%1$s.jar", MC_VERSION ), vanillaJar );
+ }
+
+ Iterable<RevCommit> mappings = buildGit.log()
+ .addPath( "mappings/bukkit-1.8.at" )
+ .addPath( "mappings/bukkit-1.8-cl.csrg" )
+ .addPath( "mappings/bukkit-1.8-members.csrg" )
+ .addPath( "mappings/package.srg" )
+ .setMaxCount( 1 ).call();
+
+ Hasher mappingsHash = Hashing.md5().newHasher();
+ for ( RevCommit rev : mappings )
+ {
+ mappingsHash.putString( rev.getName(), Charsets.UTF_8 );
+ }
+ String mappingsVersion = mappingsHash.hash().toString().substring( 24 ); // Last 8 chars
+
+ File finalMappedJar = new File( workDir, "mapped." + mappingsVersion + ".jar" );
+ if ( !finalMappedJar.exists() )
+ {
+ System.out.println( "Final mapped jar: " + finalMappedJar + " does not exist, creating!" );
+
+ File clMappedJar = new File( finalMappedJar + "-cl" );
+ File mMappedJar = new File( finalMappedJar + "-m" );
+
+ runProcess( "java -jar BuildData/bin/SpecialSource.jar -i " + vanillaJar + " -m BuildData/mappings/bukkit-1.8-cl.csrg -o " + clMappedJar, CWD );
+ runProcess( "java -jar BuildData/bin/SpecialSource-2.jar map -i " + clMappedJar + " -m " + "BuildData/mappings/bukkit-1.8-members.csrg -o " + mMappedJar, CWD );
+ runProcess( "java -jar BuildData/bin/SpecialSource.jar -i " + mMappedJar + " --access-transformer BuildData/mappings/bukkit-1.8.at "
+ + "-m BuildData/mappings/package.srg -o " + finalMappedJar, CWD );
+ }
+
+ runProcess( mvnCmd + " install:install-file -Dfile=" + finalMappedJar + " -Dpackaging=jar -DgroupId=org.spigotmc -DartifactId=minecraft-server -Dversion=1.8-SNAPSHOT", CWD );
+
+ File decompileDir = new File( workDir, "decompile-" + mappingsVersion );
+ if ( !decompileDir.exists() )
+ {
+ decompileDir.mkdir();
+
+ File clazzDir = new File( decompileDir, "classes" );
+ unzip( finalMappedJar, clazzDir, new Predicate<String>()
+ {
+
+ @Override
+ public boolean apply(String input)
+ {
+ return input.startsWith( "net/minecraft/server" );
+ }
+ } );
+
+ runProcess( "java -jar BuildData/bin/fernflower.jar -dgs=1 -hdc=0 -rbr=0 -asc=1 " + clazzDir + " " + decompileDir, CWD );
+
+ String jacobePath = "BuildData/bin/jacobe";
+ if ( IS_WINDOWS )
+ {
+ jacobePath += ".exe";
+ }
+ runProcess( jacobePath + " -cfg=BuildData/bin/jacobe.cfg -nobackup -overwrite -outext=java " + decompileDir + "/net/minecraft/server", CWD );
+ }
+
+ System.out.println( "Applying CraftBukkit Patches" );
+ File nmsDir = new File( craftBukkit, "src/main/java/net" );
+ if ( nmsDir.exists() )
+ {
+ System.out.println( "Backing up NMS dir" );
+ FileUtils.moveDirectory( nmsDir, new File( workDir, "nms.old." + System.currentTimeMillis() ) );
+ }
+ File patchDir = new File( craftBukkit, "nms-patches" );
+ for ( File file : patchDir.listFiles() )
+ {
+ String targetFile = "net/minecraft/server/" + file.getName().replaceAll( ".patch", ".java" );
+
+ File clean = new File( decompileDir, targetFile );
+ File t = new File( nmsDir.getParentFile(), targetFile );
+ t.getParentFile().mkdirs();
+
+ System.out.println( "Patching with " + file.getName() );
+
+ Patch parsedPatch = DiffUtils.parseUnifiedDiff( Files.readLines( file, Charsets.UTF_8 ) );
+ List<?> modifiedLines = DiffUtils.patch( Files.readLines( clean, Charsets.UTF_8 ), parsedPatch );
+
+ BufferedWriter bw = new BufferedWriter( new FileWriter( t ) );
+ for ( String line : (List<String>) modifiedLines )
+ {
+ bw.write( line );
+ bw.newLine();
+ }
+ bw.close();
+ }
+ File tmpNms = new File( craftBukkit, "tmp-nms" );
+ FileUtils.copyDirectory( nmsDir, tmpNms );
+
+ craftBukkitGit.branchDelete().setBranchNames( "patched" ).setForce( true ).call();
+ craftBukkitGit.checkout().setCreateBranch( true ).setForce( true ).setName( "patched" ).call();
+ craftBukkitGit.add().addFilepattern( "src/main/java/net/" ).call();
+ craftBukkitGit.commit().setMessage( "CraftBukkit $ " + new Date() ).call();
+ craftBukkitGit.checkout().setName( "master" ).call();
+
+ FileUtils.moveDirectory( tmpNms, nmsDir );
+
+ File spigotApi = new File( spigot, "Bukkit" );
+ if ( !spigotApi.exists() )
+ {
+ clone( "file://" + bukkit.getAbsolutePath(), spigotApi );
+ }
+ File spigotServer = new File( spigot, "CraftBukkit" );
+ if ( !spigotServer.exists() )
+ {
+ clone( "file://" + craftBukkit.getAbsolutePath(), spigotServer );
+ }
+
+ // Git spigotApiGit = Git.open( spigotApi );
+ // Git spigotServerGit = Git.open( spigotServer );
+ System.out.println( "Compiling Bukkit" );
+ runProcess( mvnCmd + " clean install", bukkit );
+
+ System.out.println( "Compiling CraftBukkit" );
+ runProcess( mvnCmd + " clean install", craftBukkit );
+
+ try
+ {
+ runProcess( "bash applyPatches.sh", spigot );
+ System.out.println( "*** Spigot patches applied!" );
+ System.out.println( "Compiling Spigot & Spigot-API" );
+ runProcess( mvnCmd + " clean install", spigot );
+ } catch ( Exception ex )
+ {
+ System.err.println( "Error compiling Spigot, are you running this jar via msysgit?" );
+ ex.printStackTrace();
+ }
+ }
+
+ public static void pull(Git repo) throws Exception
+ {
+ System.out.println( "Pulling updates for " + repo.getRepository().getDirectory() );
+
+ repo.reset().setRef( "origin/master" ).setMode( ResetCommand.ResetType.HARD ).call();
+ boolean result = repo.pull().call().isSuccessful();
+
+ if ( !result )
+ {
+ throw new RuntimeException( "Could not pull updates!" );
+ }
+
+ System.out.println( "Successfully pulled updates!" );
+ }
+
+ public static int runProcess(String command, File workDir) throws Exception
+ {
+ final Process ps = new ProcessBuilder( command.split( " " ) ).directory( workDir ).start();
+
+ new Thread( new StreamRedirector( ps.getInputStream(), System.out ) ).start();
+ new Thread( new StreamRedirector( ps.getErrorStream(), System.err ) ).start();
+
+ int status = ps.waitFor();
+
+ if ( status != 0 )
+ {
+ throw new RuntimeException( "Error running command, return status !=0: " + command );
+ }
+
+ return status;
+ }
+
+ @RequiredArgsConstructor
+ private static class StreamRedirector implements Runnable
+ {
+
+ private final InputStream in;
+ private final PrintStream out;
+
+ @Override
+ public void run()
+ {
+ BufferedReader br = new BufferedReader( new InputStreamReader( in ) );
+ try
+ {
+ String line;
+ while ( ( line = br.readLine() ) != null )
+ {
+ out.println( line );
+ }
+ } catch ( IOException ex )
+ {
+ throw Throwables.propagate( ex );
+ }
+ }
+ }
+
+ public static void unzip(File zipFile, File targetFolder) throws IOException
+ {
+ unzip( zipFile, targetFolder, null );
+ }
+
+ public static void unzip(File zipFile, File targetFolder, Predicate<String> filter) throws IOException
+ {
+ targetFolder.mkdir();
+ ZipFile zip = new ZipFile( zipFile );
+
+ for ( Enumeration<? extends ZipEntry> entries = zip.entries(); entries.hasMoreElements(); )
+ {
+ ZipEntry entry = entries.nextElement();
+
+ if ( filter != null )
+ {
+ if ( !filter.apply( entry.getName() ) )
+ {
+ continue;
+ }
+ }
+
+ File outFile = new File( targetFolder, entry.getName() );
+
+ if ( entry.isDirectory() )
+ {
+ outFile.mkdirs();
+ continue;
+ }
+ if ( outFile.getParentFile() != null )
+ {
+ outFile.getParentFile().mkdirs();
+ }
+
+ InputStream is = zip.getInputStream( entry );
+ OutputStream os = new FileOutputStream( outFile );
+ try
+ {
+ ByteStreams.copy( is, os );
+ } finally
+ {
+ is.close();
+ os.close();
+ }
+
+ System.out.println( "Extracted: " + outFile );
+ }
+ }
+
+ public static void clone(String url, File target) throws GitAPIException
+ {
+ System.out.println( "Starting clone of " + url + " to " + target );
+
+ Git result = Git.cloneRepository().setURI( url ).setDirectory( target ).call();
+
+ try
+ {
+ System.out.println( "Cloned git repository " + url + " to " + url + ". Current HEAD: " + commitHash( result ) );
+
+ } finally
+ {
+ result.close();
+ }
+ }
+
+ public static String commitHash(Git repo) throws GitAPIException
+ {
+ return Iterables.getOnlyElement( repo.log().setMaxCount( 1 ).call() ).getName();
+ }
+
+ public static File download(String url, File target) throws IOException
+ {
+ System.out.println( "Starting download of " + url );
+
+ byte[] bytes = Resources.toByteArray( new URL( url ) );
+
+ System.out.println( "Downloaded file: " + target + " with md5: " + Hashing.md5().hashBytes( bytes ).toString() );
+
+ Files.write( bytes, target );
+
+ return target;
+ }
+}