ForgePatch/release.py
2013-03-23 22:31:28 -04:00

320 lines
11 KiB
Python

import os, os.path, sys, glob
import shutil, fnmatch
import logging, zipfile, re
from optparse import OptionParser
forge_dir = os.path.dirname(os.path.abspath(__file__))
from forge import reset_logger, load_version, zip_folder, zip_create, inject_version, build_forge_dev
from changelog import make_changelog
zip = None
zip_name = None
zip_base = None
version_str = None
version_mc = None
def main():
global version_str
global version_mc
parser = OptionParser()
parser.add_option('-m', '--mcp-dir', action='store', dest='mcp_dir', help='MCP Path', default=None)
parser.add_option('-b', '--build', action='store', dest='build', help='Build number', default=None)
parser.add_option('-s', '--skipchangelog', action='store_true', dest='skip_changelog', help='Skip Changelog', default=False)
parser.add_option('-j', '--sign-jar', action='store', dest='sign_jar', help='Path to jar signer command', default=None)
options, _ = parser.parse_args()
build_num = 0
if not options.build is None:
try:
build_num = int(options.build)
except:
pass
mcp_dir = os.path.join(forge_dir, 'mcp')
if not options.mcp_dir is None:
mcp_dir = os.path.abspath(options.mcp_dir)
ret = 0
fml_dir = os.path.join(forge_dir, 'fml')
ret = build_forge_dev(mcp_dir, forge_dir, fml_dir, build_num)
if ret != 0:
sys.exit(ret)
temp_dir = os.path.join(forge_dir, 'temp')
src_dir = os.path.join(mcp_dir, 'src')
reobf_dir = os.path.join(mcp_dir, 'reobf')
client_dir = os.path.join(reobf_dir, 'minecraft')
fml_dir = os.path.join(temp_dir, 'fml')
print '=================================== Release Start ================================='
fml = glob.glob(os.path.join(forge_dir, 'fml', 'target', 'fml-src-*.%d-*.zip' % build_num))
if not len(fml) == 1:
if len(fml) == 0:
print 'Missing FML source zip, should be named fml-src-*.zip inside ./fml/target/ created when running setup'
else:
print 'To many FML source zips found, we should only have one. Check the Forge Git for the latest FML version supported'
sys.exit(1)
if os.path.isdir(fml_dir):
shutil.rmtree(fml_dir)
print 'Extracting: %s' % os.path.basename(fml[0])
zf = zipfile.ZipFile(fml[0])
zf.extractall(temp_dir)
zf.close()
error_level = 0
try:
sys.path.append(mcp_dir)
from runtime.reobfuscate import reobfuscate
os.chdir(mcp_dir)
reset_logger()
reobfuscate(None, False, True, True, True, False, False)
reset_logger()
os.chdir(forge_dir)
except SystemExit, e:
print 'Reobfusicate Exception: %d ' % e.code
error_level = e.code
extract_fml_obfed(fml_dir, mcp_dir, reobf_dir, client_dir)
extract_paulscode(mcp_dir, client_dir)
version = load_version(build_num)
version_forge = '%d.%d.%d.%d' % (version['major'], version['minor'], version['revision'], version['build'])
version_mc = load_mc_version(fml_dir)
branch = get_branch_name()
version_str = '%s-%s' % (version_mc, version_forge)
if not branch == "":
version_str = '%s-%s' % (version_str, branch)
out_folder = os.path.join(forge_dir, 'forge-%s' % version_str)
if os.path.isdir(out_folder):
shutil.rmtree(out_folder)
os.makedirs(out_folder)
# options.skip_changelog = True #Disable till jenkins fixes its shit
if not options.skip_changelog:
changelog_file = 'forge-%s/minecraftforge-changelog-%s.txt' % (version_str, version_str)
make_changelog("http://jenkins.minecraftforge.net/job/minecraftforge/", build_num, changelog_file, version_str)
version_file = 'forgeversion.properties'
if os.path.exists(version_file):
os.remove(version_file)
with open(version_file, 'wb') as fh:
fh.write('forge.major.number=%d\n' % version['major'])
fh.write('forge.minor.number=%d\n' % version['minor'])
fh.write('forge.revision.number=%d\n' % version['revision'])
fh.write('forge.build.number=%d\n' % version['build'])
if not options.sign_jar is None:
sign_jar(forge_dir, options.sign_jar, client_dir, 'minecraftforge-universal-%s.zip' % version_str)
else:
zip_start('minecraftforge-universal-%s.zip' % version_str)
zip_folder(client_dir, '', zip)
zip_add('MANIFEST.MF','META-INF/MANIFEST.MF')
zip_add('client/forge_logo.png')
zip_add('install/MinecraftForge-Credits.txt')
zip_add('install/MinecraftForge-License.txt')
zip_add('install/Paulscode IBXM Library License.txt')
zip_add('install/Paulscode SoundSystem CodecIBXM License.txt')
zip_add('common/forge_at.cfg')
zip_add(version_file)
if not options.skip_changelog:
zip_add(changelog_file, 'MinecraftForge-Changelog.txt')
#Add dependancy and licenses from FML
FML_FILES = [
'CREDITS-fml.txt',
'LICENSE-fml.txt',
'README-fml.txt',
'common/fml_at.cfg',
'common/fml_marker.cfg',
'common/fmlversion.properties',
'common/mcpmod.info',
'client/mcp.png'
]
for file in FML_FILES:
zip_add(os.path.join(fml_dir, file))
zip_end()
inject_version(os.path.join(forge_dir, 'common/net/minecraftforge/common/ForgeVersion.java'.replace('/', os.sep)), build_num)
zip_start('minecraftforge-src-%s.zip' % version_str, 'forge')
zip_add('client', 'client')
zip_add('common', 'common')
zip_add('patches', 'patches')
zip_add(fml_dir, 'fml')
zip_add('install', '')
zip_add('forge.py')
zip_add(version_file)
if not options.skip_changelog:
zip_add(changelog_file, 'MinecraftForge-Changelog.txt')
zip_end()
inject_version(os.path.join(forge_dir, 'common/net/minecraftforge/common/ForgeVersion.java'.replace('/', os.sep)), 0)
if os.path.exists(version_file):
os.remove(version_file)
shutil.rmtree(temp_dir)
print '=================================== Release Finished %d =================================' % error_level
sys.exit(error_level)
def zip_add(file, key=None):
if key == None:
key = os.path.basename(file)
else:
key = key.replace('/', os.sep)
if not zip_base is None:
key = os.path.join(zip_base, key)
file = os.path.join(forge_dir, file.replace('/', os.sep))
if os.path.isdir(file):
zip_folder(file, key, zip)
else:
if os.path.isfile(file):
print ' ' + key
zip.write(file, key)
def zip_start(name, base=None):
global zip, zip_name, zip_base
zip_name = name
print '================== %s Start ==================' % zip_name
zip_file = os.path.join(forge_dir, 'forge-%s' % version_str, name)
zip = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED)
zip_base = base
def zip_end():
global zip, zip_name, zip_base
zip.close()
print '================== %s Finished ==================' % zip_name
zip_name = None
zip_base = None
def load_mc_version(fml_dir):
props = os.path.join(fml_dir, 'common', 'fmlversion.properties')
if not os.path.isfile(props):
print 'Could not load fmlversion.properties, build failed'
sys.exit(1)
with open(props, 'r') as fh:
for line in fh:
line = line.strip()
if line.startswith('fmlbuild.mcversion'):
return line.split('=')[1].strip()
print 'Could not load fmlversion.properties, build failed'
sys.exit(1)
def extract_fml_obfed(fml_dir, mcp_dir, reobf_dir, client_dir):
fml_file = os.path.join(fml_dir, 'difflist.txt')
if not os.path.isfile(fml_file):
print 'Could not find Forge ModLoader\'s DiffList, looking for it at: %s' % fml_file
sys.exit(1)
with open(fml_file, 'r') as fh:
lines = fh.readlines()
client = zipfile.ZipFile(os.path.join(mcp_dir, 'temp', 'client_reobf.jar'))
print 'Extracting Reobfed Forge ModLoader classes'
for line in lines:
line = line.replace('\n', '').replace('\r', '').replace('/', os.sep)
if not os.path.isfile(os.path.join(reobf_dir, line)):
print ' %s' % line
side = line.split(os.sep)[0]
if side == 'minecraft':
client.extract(line[10:].replace(os.sep, '/'), client_dir)
client.close()
def extract_paulscode(mcp_dir, client_dir):
client = zipfile.ZipFile(os.path.join(mcp_dir, 'temp', 'client_reobf.jar'))
print 'Extracting Reobfed Paulscode for mac users -.-'
for i in client.filelist:
if i.filename.startswith('paulscode'):
if not os.path.isfile(os.path.join(client_dir, i.filename)):
print ' %s' % i.filename
client.extract(i.filename, client_dir)
client.close()
def get_branch_name():
from subprocess import Popen, PIPE, STDOUT
branch = ''
if os.getenv("GIT_BRANCH") is None:
try:
process = Popen(["git", "rev-parse", "--abbrev-ref", "HEAD"], stdout=PIPE, stderr=STDOUT, bufsize=-1)
branch, _ = process.communicate()
branch = branch.rstrip('\r\n')
except OSError:
print "Git not found"
else:
branch = os.getenv("GIT_BRANCH").rpartition('/')[2]
branch = branch.replace('master', '')
branch = branch.replace('HEAD', '')
print 'Detected Branch as \'%s\'' % branch
return branch
def sign_jar(forge_dir, command, files, dest_zip):
from subprocess import Popen, PIPE, STDOUT
global zip
zip_file = os.path.join(forge_dir, 'tmp.jar')
if os.path.isfile(zip_file):
os.remove(zip_file)
print '============== Creating tmp zip to sign ====================='
zf = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED)
zf.write(os.path.join(forge_dir, 'MANIFEST.MF'), 'META-INF/MANIFEST.MF')
zip_folder_filter(files, '', zf, 'cpw/mods/'.replace('/', os.sep))
zip_folder_filter(files, '', zf, 'net/minecraftforge/'.replace('/', os.sep))
zf.close()
print '================ End tmp zip to sign ========================'
try:
process = Popen([command, zip_file, "forge"], stdout=PIPE, stderr=STDOUT, bufsize=-1)
out, _ = process.communicate()
print out
except OSError as e:
print "Error creating signed tmp jar: %s" % e.strerror
sys.exit(1)
tmp_dir = os.path.join(forge_dir, 'tmp')
if os.path.isdir(tmp_dir):
shutil.rmtree(tmp_dir)
zf = zipfile.ZipFile(zip_file)
zf.extractall(tmp_dir)
zf.close()
os.remove(zip_file)
zip_start(dest_zip)
zip_folder(tmp_dir, '', zip)
zip_folder(files, '', zip)
if os.path.isdir(tmp_dir):
shutil.rmtree(tmp_dir)
def zip_folder_filter(path, key, zip, filter):
files = os.listdir(path)
for file in files:
file_path = os.path.join(path, file)
file_key = os.path.join(key, file)
if os.path.isdir(file_path):
zip_folder_filter(file_path, file_key, zip, filter)
else:
if file_key.startswith(filter):
print file_key
zip.write(file_path, file_key)
if __name__ == '__main__':
main()