Work on dist script
This commit is contained in:
142
scripts/dist.py
142
scripts/dist.py
@@ -4,18 +4,26 @@ Script for generating distributables based on platform skeletons.
|
||||
|
||||
User supplies path for pyfa code base, root skeleton directory, and where the
|
||||
builds go. The builds are automatically named depending on the pyfa config
|
||||
values of `version` and `tag`. If it's a Stable release, the naming convention is:
|
||||
values of `version` and `tag`. If it's a Stable release, the naming
|
||||
convention is:
|
||||
|
||||
pyfa-pyfaversion-expansion-expversion-platform
|
||||
If it is not Stable (tag=git), we determine if the pyfa code base includes the
|
||||
git repo to use as an ID. If not, uses randomly generated 6-character ID. The
|
||||
unstable naming convention:
|
||||
|
||||
If it is not Stable (tag=git), we determine if the pyfa code base includes
|
||||
the git repo to use as an ID. If not, uses randomly generated 6-character ID.
|
||||
The unstable naming convention:
|
||||
|
||||
pyfa-YYYMMDD-id-platform
|
||||
|
||||
dist.py can also build the Windows installer provided that it has a path to Inno
|
||||
Setup (and, for generating on non-Windows platforms, that WINE is installed).
|
||||
To build the EXE file, `win` must be included in the platforms to be built.
|
||||
dist.py can also build the Windows installer provided that it has a path to
|
||||
Inno Setup (and, for generating on non-Windows platforms, that WINE is
|
||||
installed). To build the EXE file, `win` must be included in the platforms to
|
||||
be built.
|
||||
"""
|
||||
|
||||
#@todo: ensure build directory can be written to
|
||||
# todo: default build and dist directories
|
||||
|
||||
from optparse import OptionParser
|
||||
import os.path
|
||||
import shutil
|
||||
@@ -25,6 +33,7 @@ import datetime
|
||||
import random
|
||||
import string
|
||||
import zipfile
|
||||
import errno
|
||||
from subprocess import call
|
||||
|
||||
class FileStub():
|
||||
@@ -34,6 +43,15 @@ class FileStub():
|
||||
def flush(self, *args):
|
||||
pass
|
||||
|
||||
def copyanything(src, dst):
|
||||
try:
|
||||
shutil.copytree(src, dst, ignore=loginfo)
|
||||
except: # python >2.5
|
||||
try:
|
||||
shutil.copy(src, dst)
|
||||
except:
|
||||
raise
|
||||
|
||||
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
|
||||
return ''.join(random.choice(chars) for x in range(size))
|
||||
|
||||
@@ -42,7 +60,7 @@ def zipdir(path, zip):
|
||||
for file in files:
|
||||
zip.write(os.path.join(root, file))
|
||||
|
||||
skels = ['win', 'mac', 'src']
|
||||
skels = ['win', 'mac', 'src', 'win-wx3']
|
||||
iscc = "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" # inno script location via wine
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -52,7 +70,6 @@ if __name__ == "__main__":
|
||||
parser.add_option("-b", "--base", dest="base", help="Location of cleaned read-only base directory")
|
||||
parser.add_option("-d", "--destination", dest="destination", help="Where to copy our distributable")
|
||||
parser.add_option("-p", "--platforms", dest="platforms", help="Comma-separated list of platforms to build", default="win,src,mac")
|
||||
parser.add_option("-t", "--static", dest="static", help="Directory containing static files")
|
||||
parser.add_option("-q", "--quiet", dest="silent", action="store_true")
|
||||
parser.add_option("-w", "--winexe", dest="winexe", action="store_true", help="Build the Windows installer file (needs Inno Setup). Must include 'win' in platform options")
|
||||
parser.add_option("-z", "--zip", dest="zip", action="store_true", help="zip archive instead of tar")
|
||||
@@ -69,80 +86,109 @@ if __name__ == "__main__":
|
||||
|
||||
options.platforms = options.platforms.split(",")
|
||||
|
||||
sys.path.append(options.base)
|
||||
import config as pyfaconfig
|
||||
#sys.path.append(options.base)
|
||||
#import config as pyfaconfig
|
||||
|
||||
for skel in skels:
|
||||
if skel not in options.platforms:
|
||||
continue
|
||||
|
||||
print "\n======== %s ========"%skel
|
||||
infoDict = {}
|
||||
|
||||
info = {}
|
||||
config = {}
|
||||
skeleton = os.path.expanduser(os.path.join(options.skeleton, skel))
|
||||
info = execfile(os.path.join(skeleton, "info.py"), infoDict)
|
||||
dirName = infoDict["arcname"]
|
||||
|
||||
execfile(os.path.join(options.base, "config.py"), config)
|
||||
execfile(os.path.join(skeleton, "info.py"), info)
|
||||
|
||||
destination = os.path.expanduser(options.destination)
|
||||
if not os.path.isdir(destination) or not os.access(destination, os.W_OK | os.X_OK):
|
||||
print "Destination directory does not exist or is not writable: {}".format(destination)
|
||||
sys.exit()
|
||||
|
||||
dirName = info["arcname"]
|
||||
|
||||
nowdt = datetime.datetime.now()
|
||||
now = "%04d%02d%02d" % (nowdt.year, nowdt.month, nowdt.day)
|
||||
|
||||
git = False
|
||||
if pyfaconfig.tag.lower() == "git":
|
||||
if config['tag'].lower() == "git":
|
||||
try: # if there is a git repo associated with base, use master commit
|
||||
with open(os.path.join(options.base,".git","refs","heads","master"), 'r') as f:
|
||||
with open(os.path.join(options.base, ".git", "refs", "heads", "master"), 'r') as f:
|
||||
id = f.readline()[0:6]
|
||||
git = True
|
||||
except: # else, use custom ID
|
||||
id = id_generator()
|
||||
fileName = "pyfa-%s-%s-%s" % (now, id, infoDict["os"])
|
||||
fileName = "pyfa-{}-{}-{}".format(now, id, info["os"])
|
||||
else:
|
||||
fileName = "pyfa-%s-%s-%s-%s" % (pyfaconfig.version, pyfaconfig.expansionName.lower(), pyfaconfig.expansionVersion, infoDict["os"])
|
||||
fileName = "pyfa-{}-{}-{}-{}".format(
|
||||
config['version'],
|
||||
config['expansionName'].lower(),
|
||||
config['expansionVersion'],
|
||||
info["os"]
|
||||
)
|
||||
|
||||
archiveName = "%s.%s"%(fileName, "zip" if options.zip else "tar.bz2")
|
||||
archiveName = "{}.{}".format(fileName, "zip" if options.zip else "tar.bz2")
|
||||
dst = os.path.join(os.getcwd(), dirName) # tmp directory where files are copied
|
||||
tmpFile = os.path.join(os.getcwd(), archiveName)
|
||||
config = os.path.join(skeleton, "config.py")
|
||||
destination = os.path.expanduser(options.destination)
|
||||
|
||||
i = 0
|
||||
gitData = (".git", ".gitignore", ".gitmodules")
|
||||
ignoreData = (".git", ".gitignore", ".gitmodules", "dist_assets", "saveddata", "build", "dist", "scripts", ".idea")
|
||||
def loginfo(path, names):
|
||||
# Print out a "progress" and return directories / files to ignore
|
||||
global i
|
||||
i += 1
|
||||
if i % 10 == 0:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
return gitData
|
||||
return ignoreData
|
||||
|
||||
try:
|
||||
print "Copying skeleton to ", dst
|
||||
i = 0
|
||||
shutil.copytree(skeleton, dst, ignore=loginfo)
|
||||
print
|
||||
base = os.path.join(dst, infoDict["base"])
|
||||
print "Copying base to ", base
|
||||
if "win-wx3" not in skel:
|
||||
# simply copying base into working build
|
||||
base = os.path.join(dst, info["base"])
|
||||
print "Copying base to ", base
|
||||
|
||||
i = 0
|
||||
for stuff in os.listdir(os.path.expanduser(options.base)):
|
||||
currSource = os.path.join(os.path.expanduser(options.base), stuff)
|
||||
currDest = os.path.join(base, stuff)
|
||||
if stuff in gitData:
|
||||
continue
|
||||
elif os.path.isdir(currSource):
|
||||
shutil.copytree(currSource, currDest, ignore=loginfo)
|
||||
else:
|
||||
shutil.copy2(currSource, currDest)
|
||||
i = 0
|
||||
for stuff in os.listdir(os.path.expanduser(options.base)):
|
||||
currSource = os.path.join(os.path.expanduser(options.base), stuff)
|
||||
currDest = os.path.join(base, stuff)
|
||||
if stuff in ignoreData:
|
||||
continue
|
||||
elif os.path.isdir(currSource):
|
||||
shutil.copytree(currSource, currDest, ignore=loginfo)
|
||||
else:
|
||||
shutil.copy2(currSource, currDest)
|
||||
|
||||
print
|
||||
print
|
||||
print "Copying done, making archive: ", tmpFile
|
||||
else:
|
||||
# this should work, but it's barely been tested
|
||||
base = os.path.join(dst, info["base"])
|
||||
source = os.path.expanduser(options.base)
|
||||
sys.path.append(source)
|
||||
import setup
|
||||
|
||||
if os.path.exists(config):
|
||||
print "Adding skeleton config file"
|
||||
shutil.copy2(config, base)
|
||||
libraryFile = os.path.join(base, "library.zip")
|
||||
|
||||
with zipfile.ZipFile(libraryFile, 'a') as library:
|
||||
# change cwd to source so that the zip append will work correctly
|
||||
oldcwd = os.getcwd()
|
||||
os.chdir(source)
|
||||
for dir in setup.packages:
|
||||
zipdir(dir, library)
|
||||
library.write('pyfa.py', 'pyfa__main__.py')
|
||||
library.write('config.py')
|
||||
|
||||
if options.static is not None and os.path.exists(os.path.expanduser(options.static)):
|
||||
print "Copying static data to ", os.path.join(base, "staticdata")
|
||||
static = os.path.expanduser(options.static)
|
||||
shutil.copytree(static, os.path.join(base, "staticdata"), ignore=loginfo)
|
||||
for dir in setup.include_files:
|
||||
copyanything(dir, os.path.join(base, dir))
|
||||
|
||||
print "Copying done, making archive: ", tmpFile
|
||||
os.chdir(oldcwd)
|
||||
|
||||
if options.zip:
|
||||
archive = zipfile.ZipFile(tmpFile, 'w', compression=zipfile.ZIP_DEFLATED)
|
||||
@@ -150,7 +196,7 @@ if __name__ == "__main__":
|
||||
archive.close()
|
||||
else:
|
||||
archive = tarfile.open(tmpFile, "w:bz2")
|
||||
archive.add(dst, arcname=infoDict["arcname"])
|
||||
archive.add(dst, arcname=info["arcname"])
|
||||
archive.close()
|
||||
|
||||
print "Moving archive to ", destination
|
||||
@@ -159,20 +205,20 @@ if __name__ == "__main__":
|
||||
if "win" in skel and options.winexe:
|
||||
print "Compiling EXE"
|
||||
|
||||
if pyfaconfig.tag.lower() == "git":
|
||||
if config['tag'].lower() == "git":
|
||||
if git: # if git repo info available, use git commit
|
||||
expansion = "git-%s"%(id)
|
||||
else: # if there is no git repo, use timestamp
|
||||
expansion = now
|
||||
else: # if code is Stable, use expansion name
|
||||
expansion = "%s %s"%(pyfaconfig.expansionName, pyfaconfig.expansionVersion),
|
||||
expansion = "%s %s"%(config['expansionName'], config['expansionVersion']),
|
||||
|
||||
calllist = ["wine"] if 'win' not in sys.platform else []
|
||||
|
||||
call(calllist + [
|
||||
iscc,
|
||||
os.path.join(os.path.dirname(__file__), "pyfa-setup.iss"),
|
||||
"/dMyAppVersion=%s"%(pyfaconfig.version),
|
||||
"/dMyAppVersion=%s"%(config['version']),
|
||||
"/dMyAppExpansion=%s"%(expansion),
|
||||
"/dMyAppDir=%s"%dst,
|
||||
"/dMyOutputDir=%s"%destination,
|
||||
|
||||
Reference in New Issue
Block a user