Initial Commit

For more information please see http://www.spigotmc.org/
This commit is contained in:
md_5 2014-11-26 16:56:48 +11:00
commit 032e8ca0a3
5 changed files with 610 additions and 0 deletions

35
.gitignore vendored Normal file
View file

@ -0,0 +1,35 @@
# Eclipse stuff
.classpath
.project
.settings/
# netbeans
nbproject/
nbactions.xml
# we use maven!
build.xml
# maven
target/
dependency-reduced-pom.xml
# vim
.*.sw[a-p]
# various other potential build files
build/
bin/
dist/
manifest.mf
# Mac filesystem dust
.DS_Store/
# intellij
*.iml
*.ipr
*.iws
.idea/
out

26
LICENSE Normal file
View file

@ -0,0 +1,26 @@
Copyright (c) 2014, SpigotMC. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

31
nb-configuration.xml Normal file
View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

107
pom.xml Normal file
View file

@ -0,0 +1,107 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.spigotmc</groupId>
<artifactId>builder</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>BuildTools</name>
<description></description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.custardsource.dybdob</groupId>
<artifactId>java-diff-utils-copy</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
<version>4.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>3.3.2.201404171909-r</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.14.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
<build>
<finalName>${project.name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>org.spigotmc.builder.Builder</Main-Class>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/*.java</exclude>
<exclude>**/*.SF</exclude>
<exclude>**/*.DSA</exclude>
</excludes>
</filter>
</filters>
<minimizeJar>true</minimizeJar>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -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;
}
}