Commits

md_5 authored 032e8ca0a3a
Initial Commit

For more information please see http://www.spigotmc.org/
No tags
No parent commit
master

src/main/java/org/spigotmc/builder/Builder.java

Added
1 +package org.spigotmc.builder;
2 +
3 +import com.google.common.base.Charsets;
4 +import com.google.common.base.Predicate;
5 +import com.google.common.base.Throwables;
6 +import com.google.common.collect.Iterables;
7 +import com.google.common.hash.Hasher;
8 +import com.google.common.hash.Hashing;
9 +import com.google.common.io.ByteStreams;
10 +import com.google.common.io.Files;
11 +import com.google.common.io.Resources;
12 +import difflib.DiffUtils;
13 +import difflib.Patch;
14 +import java.io.BufferedReader;
15 +import java.io.BufferedWriter;
16 +import java.io.File;
17 +import java.io.FileOutputStream;
18 +import java.io.FileWriter;
19 +import java.io.IOException;
20 +import java.io.InputStream;
21 +import java.io.InputStreamReader;
22 +import java.io.OutputStream;
23 +import java.io.PrintStream;
24 +import java.net.URL;
25 +import java.util.Date;
26 +import java.util.Enumeration;
27 +import java.util.List;
28 +import java.util.zip.ZipEntry;
29 +import java.util.zip.ZipFile;
30 +import lombok.RequiredArgsConstructor;
31 +import org.apache.commons.io.FileUtils;
32 +import org.eclipse.jgit.api.Git;
33 +import org.eclipse.jgit.api.ResetCommand;
34 +import org.eclipse.jgit.api.errors.GitAPIException;
35 +import org.eclipse.jgit.revwalk.RevCommit;
36 +
37 +public class Builder
38 +{
39 +
40 + public static final boolean IS_WINDOWS = System.getProperty( "os.name" ).startsWith( "Windows" );
41 + public static final boolean IS_MAC = System.getProperty( "os.name" ).startsWith( "Mac" );
42 + public static final File CWD = new File( "." );
43 + public static final String MC_VERSION = "1.8";
44 +
45 + public static void main(String[] args) throws Exception
46 + {
47 + if ( IS_MAC )
48 + {
49 + System.out.println( "Sorry, but Macintosh is not currently a supported platform for compilation at this time." );
50 + System.out.println( "Please run this script on a Windows or Linux PC and then copy the jars to this computer." );
51 + return;
52 + }
53 +
54 + try
55 + {
56 + runProcess( "bash -c exit", CWD );
57 + } catch ( Exception ex )
58 + {
59 + System.out.println( "You must run this jar through bash (msysgit)" );
60 + return;
61 + }
62 +
63 + try
64 + {
65 + runProcess( "git config --global user.name", CWD );
66 + } catch ( Exception ex )
67 + {
68 + System.out.println( "Git name not set, setting it to default value." );
69 + runProcess( "git config --global user.name BuildTools", CWD );
70 + }
71 + try
72 + {
73 + runProcess( "git config --global user.email", CWD );
74 + } catch ( Exception ex )
75 + {
76 + System.out.println( "Git email not set, setting it to default value." );
77 + runProcess( "git config --global user.email unconfigured@null.spigotmc.org", CWD );
78 + }
79 +
80 + File workDir = new File( "work" );
81 + workDir.mkdir();
82 +
83 + File bukkit = new File( "Bukkit" );
84 + if ( !bukkit.exists() )
85 + {
86 + clone( "https://hub.spigotmc.org/stash/scm/spigot/bukkit.git", bukkit );
87 + }
88 +
89 + File craftBukkit = new File( "CraftBukkit" );
90 + if ( !craftBukkit.exists() )
91 + {
92 + clone( "https://hub.spigotmc.org/stash/scm/spigot/craftbukkit.git", craftBukkit );
93 + }
94 +
95 + File spigot = new File( "Spigot" );
96 + if ( !spigot.exists() )
97 + {
98 + clone( "https://hub.spigotmc.org/stash/scm/spigot/spigot.git", spigot );
99 + }
100 +
101 + File buildData = new File( "BuildData" );
102 + if ( !buildData.exists() )
103 + {
104 + clone( "https://hub.spigotmc.org/stash/scm/spigot/builddata.git", buildData );
105 + }
106 +
107 + File maven = new File( "apache-maven-3.2.3" );
108 + if ( !maven.exists() )
109 + {
110 + System.out.println( "Maven does not exist, downloading. Please wait." );
111 +
112 + File mvnTemp = new File( "mvn.zip" );
113 + mvnTemp.deleteOnExit();
114 +
115 + download( "http://static.spigotmc.org/maven/apache-maven-3.2.3-bin.zip", mvnTemp );
116 + unzip( mvnTemp, new File( "." ) );
117 + }
118 +
119 + String mvnCmd = maven.getAbsolutePath() + "/bin/mvn";
120 + if ( IS_WINDOWS )
121 + {
122 + mvnCmd += ".bat";
123 + } else
124 + {
125 + mvnCmd = "/bin/sh " + mvnCmd;
126 + }
127 +
128 + Git bukkitGit = Git.open( bukkit );
129 + Git craftBukkitGit = Git.open( craftBukkit );
130 + Git spigotGit = Git.open( spigot );
131 + Git buildGit = Git.open( buildData );
132 +
133 + pull( bukkitGit );
134 + pull( craftBukkitGit );
135 + pull( spigotGit );
136 + pull( buildGit );
137 +
138 + File vanillaJar = new File( workDir, "minecraft_server." + MC_VERSION + ".jar" );
139 + if ( !vanillaJar.exists() )
140 + {
141 + download( String.format( "https://s3.amazonaws.com/Minecraft.Download/versions/%1$s/minecraft_server.%1$s.jar", MC_VERSION ), vanillaJar );
142 + }
143 +
144 + Iterable<RevCommit> mappings = buildGit.log()
145 + .addPath( "mappings/bukkit-1.8.at" )
146 + .addPath( "mappings/bukkit-1.8-cl.csrg" )
147 + .addPath( "mappings/bukkit-1.8-members.csrg" )
148 + .addPath( "mappings/package.srg" )
149 + .setMaxCount( 1 ).call();
150 +
151 + Hasher mappingsHash = Hashing.md5().newHasher();
152 + for ( RevCommit rev : mappings )
153 + {
154 + mappingsHash.putString( rev.getName(), Charsets.UTF_8 );
155 + }
156 + String mappingsVersion = mappingsHash.hash().toString().substring( 24 ); // Last 8 chars
157 +
158 + File finalMappedJar = new File( workDir, "mapped." + mappingsVersion + ".jar" );
159 + if ( !finalMappedJar.exists() )
160 + {
161 + System.out.println( "Final mapped jar: " + finalMappedJar + " does not exist, creating!" );
162 +
163 + File clMappedJar = new File( finalMappedJar + "-cl" );
164 + File mMappedJar = new File( finalMappedJar + "-m" );
165 +
166 + runProcess( "java -jar BuildData/bin/SpecialSource.jar -i " + vanillaJar + " -m BuildData/mappings/bukkit-1.8-cl.csrg -o " + clMappedJar, CWD );
167 + runProcess( "java -jar BuildData/bin/SpecialSource-2.jar map -i " + clMappedJar + " -m " + "BuildData/mappings/bukkit-1.8-members.csrg -o " + mMappedJar, CWD );
168 + runProcess( "java -jar BuildData/bin/SpecialSource.jar -i " + mMappedJar + " --access-transformer BuildData/mappings/bukkit-1.8.at "
169 + + "-m BuildData/mappings/package.srg -o " + finalMappedJar, CWD );
170 + }
171 +
172 + runProcess( mvnCmd + " install:install-file -Dfile=" + finalMappedJar + " -Dpackaging=jar -DgroupId=org.spigotmc -DartifactId=minecraft-server -Dversion=1.8-SNAPSHOT", CWD );
173 +
174 + File decompileDir = new File( workDir, "decompile-" + mappingsVersion );
175 + if ( !decompileDir.exists() )
176 + {
177 + decompileDir.mkdir();
178 +
179 + File clazzDir = new File( decompileDir, "classes" );
180 + unzip( finalMappedJar, clazzDir, new Predicate<String>()
181 + {
182 +
183 + @Override
184 + public boolean apply(String input)
185 + {
186 + return input.startsWith( "net/minecraft/server" );
187 + }
188 + } );
189 +
190 + runProcess( "java -jar BuildData/bin/fernflower.jar -dgs=1 -hdc=0 -rbr=0 -asc=1 " + clazzDir + " " + decompileDir, CWD );
191 +
192 + String jacobePath = "BuildData/bin/jacobe";
193 + if ( IS_WINDOWS )
194 + {
195 + jacobePath += ".exe";
196 + }
197 + runProcess( jacobePath + " -cfg=BuildData/bin/jacobe.cfg -nobackup -overwrite -outext=java " + decompileDir + "/net/minecraft/server", CWD );
198 + }
199 +
200 + System.out.println( "Applying CraftBukkit Patches" );
201 + File nmsDir = new File( craftBukkit, "src/main/java/net" );
202 + if ( nmsDir.exists() )
203 + {
204 + System.out.println( "Backing up NMS dir" );
205 + FileUtils.moveDirectory( nmsDir, new File( workDir, "nms.old." + System.currentTimeMillis() ) );
206 + }
207 + File patchDir = new File( craftBukkit, "nms-patches" );
208 + for ( File file : patchDir.listFiles() )
209 + {
210 + String targetFile = "net/minecraft/server/" + file.getName().replaceAll( ".patch", ".java" );
211 +
212 + File clean = new File( decompileDir, targetFile );
213 + File t = new File( nmsDir.getParentFile(), targetFile );
214 + t.getParentFile().mkdirs();
215 +
216 + System.out.println( "Patching with " + file.getName() );
217 +
218 + Patch parsedPatch = DiffUtils.parseUnifiedDiff( Files.readLines( file, Charsets.UTF_8 ) );
219 + List<?> modifiedLines = DiffUtils.patch( Files.readLines( clean, Charsets.UTF_8 ), parsedPatch );
220 +
221 + BufferedWriter bw = new BufferedWriter( new FileWriter( t ) );
222 + for ( String line : (List<String>) modifiedLines )
223 + {
224 + bw.write( line );
225 + bw.newLine();
226 + }
227 + bw.close();
228 + }
229 + File tmpNms = new File( craftBukkit, "tmp-nms" );
230 + FileUtils.copyDirectory( nmsDir, tmpNms );
231 +
232 + craftBukkitGit.branchDelete().setBranchNames( "patched" ).setForce( true ).call();
233 + craftBukkitGit.checkout().setCreateBranch( true ).setForce( true ).setName( "patched" ).call();
234 + craftBukkitGit.add().addFilepattern( "src/main/java/net/" ).call();
235 + craftBukkitGit.commit().setMessage( "CraftBukkit $ " + new Date() ).call();
236 + craftBukkitGit.checkout().setName( "master" ).call();
237 +
238 + FileUtils.moveDirectory( tmpNms, nmsDir );
239 +
240 + File spigotApi = new File( spigot, "Bukkit" );
241 + if ( !spigotApi.exists() )
242 + {
243 + clone( "file://" + bukkit.getAbsolutePath(), spigotApi );
244 + }
245 + File spigotServer = new File( spigot, "CraftBukkit" );
246 + if ( !spigotServer.exists() )
247 + {
248 + clone( "file://" + craftBukkit.getAbsolutePath(), spigotServer );
249 + }
250 +
251 + // Git spigotApiGit = Git.open( spigotApi );
252 + // Git spigotServerGit = Git.open( spigotServer );
253 + System.out.println( "Compiling Bukkit" );
254 + runProcess( mvnCmd + " clean install", bukkit );
255 +
256 + System.out.println( "Compiling CraftBukkit" );
257 + runProcess( mvnCmd + " clean install", craftBukkit );
258 +
259 + try
260 + {
261 + runProcess( "bash applyPatches.sh", spigot );
262 + System.out.println( "*** Spigot patches applied!" );
263 + System.out.println( "Compiling Spigot & Spigot-API" );
264 + runProcess( mvnCmd + " clean install", spigot );
265 + } catch ( Exception ex )
266 + {
267 + System.err.println( "Error compiling Spigot, are you running this jar via msysgit?" );
268 + ex.printStackTrace();
269 + }
270 + }
271 +
272 + public static void pull(Git repo) throws Exception
273 + {
274 + System.out.println( "Pulling updates for " + repo.getRepository().getDirectory() );
275 +
276 + repo.reset().setRef( "origin/master" ).setMode( ResetCommand.ResetType.HARD ).call();
277 + boolean result = repo.pull().call().isSuccessful();
278 +
279 + if ( !result )
280 + {
281 + throw new RuntimeException( "Could not pull updates!" );
282 + }
283 +
284 + System.out.println( "Successfully pulled updates!" );
285 + }
286 +
287 + public static int runProcess(String command, File workDir) throws Exception
288 + {
289 + final Process ps = new ProcessBuilder( command.split( " " ) ).directory( workDir ).start();
290 +
291 + new Thread( new StreamRedirector( ps.getInputStream(), System.out ) ).start();
292 + new Thread( new StreamRedirector( ps.getErrorStream(), System.err ) ).start();
293 +
294 + int status = ps.waitFor();
295 +
296 + if ( status != 0 )
297 + {
298 + throw new RuntimeException( "Error running command, return status !=0: " + command );
299 + }
300 +
301 + return status;
302 + }
303 +
304 + @RequiredArgsConstructor
305 + private static class StreamRedirector implements Runnable
306 + {
307 +
308 + private final InputStream in;
309 + private final PrintStream out;
310 +
311 + @Override
312 + public void run()
313 + {
314 + BufferedReader br = new BufferedReader( new InputStreamReader( in ) );
315 + try
316 + {
317 + String line;
318 + while ( ( line = br.readLine() ) != null )
319 + {
320 + out.println( line );
321 + }
322 + } catch ( IOException ex )
323 + {
324 + throw Throwables.propagate( ex );
325 + }
326 + }
327 + }
328 +
329 + public static void unzip(File zipFile, File targetFolder) throws IOException
330 + {
331 + unzip( zipFile, targetFolder, null );
332 + }
333 +
334 + public static void unzip(File zipFile, File targetFolder, Predicate<String> filter) throws IOException
335 + {
336 + targetFolder.mkdir();
337 + ZipFile zip = new ZipFile( zipFile );
338 +
339 + for ( Enumeration<? extends ZipEntry> entries = zip.entries(); entries.hasMoreElements(); )
340 + {
341 + ZipEntry entry = entries.nextElement();
342 +
343 + if ( filter != null )
344 + {
345 + if ( !filter.apply( entry.getName() ) )
346 + {
347 + continue;
348 + }
349 + }
350 +
351 + File outFile = new File( targetFolder, entry.getName() );
352 +
353 + if ( entry.isDirectory() )
354 + {
355 + outFile.mkdirs();
356 + continue;
357 + }
358 + if ( outFile.getParentFile() != null )
359 + {
360 + outFile.getParentFile().mkdirs();
361 + }
362 +
363 + InputStream is = zip.getInputStream( entry );
364 + OutputStream os = new FileOutputStream( outFile );
365 + try
366 + {
367 + ByteStreams.copy( is, os );
368 + } finally
369 + {
370 + is.close();
371 + os.close();
372 + }
373 +
374 + System.out.println( "Extracted: " + outFile );
375 + }
376 + }
377 +
378 + public static void clone(String url, File target) throws GitAPIException
379 + {
380 + System.out.println( "Starting clone of " + url + " to " + target );
381 +
382 + Git result = Git.cloneRepository().setURI( url ).setDirectory( target ).call();
383 +
384 + try
385 + {
386 + System.out.println( "Cloned git repository " + url + " to " + url + ". Current HEAD: " + commitHash( result ) );
387 +
388 + } finally
389 + {
390 + result.close();
391 + }
392 + }
393 +
394 + public static String commitHash(Git repo) throws GitAPIException
395 + {
396 + return Iterables.getOnlyElement( repo.log().setMaxCount( 1 ).call() ).getName();
397 + }
398 +
399 + public static File download(String url, File target) throws IOException
400 + {
401 + System.out.println( "Starting download of " + url );
402 +
403 + byte[] bytes = Resources.toByteArray( new URL( url ) );
404 +
405 + System.out.println( "Downloaded file: " + target + " with md5: " + Hashing.md5().hashBytes( bytes ).toString() );
406 +
407 + Files.write( bytes, target );
408 +
409 + return target;
410 + }
411 +}

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut