Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- import sys, os, shutil, zipfile, tempfile
- import os.path
- from subprocess import Popen, PIPE
- import which
- import ansicodes
- from pathwalker import pathwalker
- from decpreproc import *
- WAD_DIR = os.environ["HOME"] + "/.pwads"
- LINEPROCS = [defineproc.DefineProc(), includeproc.IncludeDirProc()]
- NUMBERS = "0123456789"
- OKSTR = ansicodes.mapColors("[ ok ]", "--22--")
- OKLEN = len(ansicodes.stripCodes(OKSTR) )
- MAKE_ACT = "make"
- TEST_ACT = "test"
- PACKAGE_ACT = "package"
- HELP_ACT = "help"
- USAGE = "usage: {} [{}] <args>".format(os.path.basename(sys.argv[0]), "|".join([MAKE_ACT, TEST_ACT, PACKAGE_ACT, HELP_ACT]))
- USAGE_FULL = """
- - make: Builds a PK3 from the files in the pk3/ directory, with the name being
- that of the current directory.
- - test [port=zandronum] <args>: Runs 'make', and then runs 'port' with the PK3,
- along with any arguments you choose.
- - package [version]: Runs 'make', with 'version' at the end of the name, copies
- it to a ZIP with the same name, and copies the PK3 to "{0}" if the
- directory exists.
- - help: Prints this.
- Examples:
- # PWD is /home/derp/derpPK3
- packagepk3.py make # derpPK3.pk3
- packagepk3.py test zandronum -file nuts
- packagepk3.py package 1_5 # derpPK3_1_5.pk3, derpPK3_1_5.zip,
- # /home/derp/.zdoom/derpPK3_1_5.pk3
- # PWD is /home/derp/derpWAD
- packagepk3.py package 1_5 # derpWAD1_5.pk3, derpWAD1_5.zip,
- # /home/derp/.zdoom/derpWAD1_5.pk3
- """.format(WAD_DIR)
- DECORATE_EXTS = ("dec",)
- ACS_EXTS = ("c", "acs")
- ACS_OBJ_EXTS = ("o",)
- BACKUP_EXTS = ("bak", "bkp", "swp")
- ACC_ERROR = "**** ERROR ****"
- DEFAULT_ARGS = ["-iwad doom2", "-warp 01"]
- def warn(reason):
- print("warning:", reason, file=sys.stderr)
- def errorExit(code = 1, reason = None):
- if reason:
- print("ERROR:", reason, file=sys.stderr)
- sys.exit(code)
- def usageExit(code = 1, reason = None):
- if reason:
- print("error:", reason, file=sys.stderr)
- usage()
- sys.exit(code)
- def usage():
- print(USAGE)
- def usageFull():
- usage()
- print(USAGE_FULL)
- NO_ARGS, NO_PK3, NO_ACC, NO_VERSION, ACC_FAIL, NO_BINARY, PREPROC_FAIL = range(4, 11)
- PK3NAME = os.path.basename(os.path.realpath("."))
- if not os.path.isdir(WAD_DIR):
- warn("{} does not exist - no pk3 auto-installation will be done".format(WAD_DIR))
- WAD_DIR = None
- validProgs = ["gzdoom", "zdoom", "zandronum"]
- progPaths = []
- zdoomExe = "zdoom" + (".exe" if sys.platform[:3] == "win" else "")
- zandronumExe = "zandronum" + (".exe" if sys.platform[:3] == "win" else "")
- progSuffix = ".exe" if sys.platform[:3] == "win" else ""
- for prog in validProgs:
- progExe = prog + progSuffix
- progPath = which.which(progExe) or ""
- progPaths.append(progPath)
- ZDOOM = progPaths[0] or progPaths[1]
- ZANDRONUM = progPaths[2]
- if not ZDOOM: warn("no zdoom in PATH or PWD")
- if not ZANDRONUM: warn("no zandronum in PATH or PWD")
- if which.is_exe("acc"):
- ACC = os.path.realpath("acc")
- else:
- ACC = which.which("acc")
- if ACC is None:
- ACC_DIR = None
- errorExit(NO_ACC, "no acc in PATH or PWD")
- else:
- ACC_DIR = ACC.rpartition("/")[0]
- def playPK3(pk3, binary=ZANDRONUM, *args):
- args = list(args)
- if binary is None:
- errorExit(1, "no binary")
- if binary[0] in "+-":
- args[:0] = [binary]
- binary = ZANDRONUM
- pk3 = os.path.realpath(pk3)
- if not os.path.isfile(pk3):
- errorExit(NO_BINARY, "somehow, {} doesn't exist".format(pk3))
- binPath = which.which(binary)
- if not binPath:
- errorExit(NO_BINARY, "no such binary {}".format(binary))
- if not args:
- args = DEFAULT_ARGS
- elif isinstance(args, str):
- args = [i for i in args.split()] or []
- else:
- args = list(args)
- pk3Game = Popen([binPath] + args + ["-file {}".format(pk3)])
- try:
- pk3Game.wait()
- except KeyboardInterrupt:
- pk3Game.send_signal(2) # SIGINT
- sys.exit(2)
- return 0
- def compileACS(file):
- file2 = file
- file = os.path.realpath(file)
- if not os.path.isfile(file):
- errorExit(ACC_FAIL, "must provide name of actual file")
- newFile = file.rpartition(".")[:2] + ("o",)
- newFile = "".join(newFile)
- newFile2 = file2.rpartition(".")[:2] + ("o",)
- newFile2 = "".join(newFile2)
- cmdline = [ACC, "-i", ACC_DIR, file, newFile]
- accProc = Popen(cmdline, stdout=PIPE, stderr=PIPE)
- accOut, accErr = (i.decode().split("\n") for i in accProc.communicate())
- if ACC_ERROR in accErr:
- reasonLines = accErr[accErr.index(ACC_ERROR)+1:]
- reason = "\n".join(reasonLines)
- raise RuntimeError(reason)
- return newFile2
- def statPrint(statStr):
- statParts = statStr.split("\x1F")
- statParts[0] = ansicodes.mapColors(statParts[0], "A6666A")
- statParts[1:1] = [" "]
- statColor = ansicodes.mapColors(statParts, "---")
- print(statColor, end="")
- def makePK3(aArgs):
- if not os.path.isdir("pk3"):
- errorExit(NO_PK3, "no pk3/ directory")
- parseDecorate = "parse" in (i.lower() for i in aArgs)
- pk3Walk = pathwalker.PathWalker('pk3')
- oldDir = os.getcwd()
- os.chdir("pk3")
- pk3Name = "{}.pk3".format(PK3NAME)
- pk3Name2 = os.path.realpath("../{}.pk3".format(PK3NAME) )
- pk3Zip = zipfile.ZipFile(pk3Name2, "w", zipfile.ZIP_DEFLATED)
- pk3Files = pk3Walk.walk(abs=1, fFilter=lambda x: not x.endswith("*.o")).flattenFiles(rel=1)
- pk3Total = len(pk3Files)
- toBuild = []
- nLen = 0
- padLength = max(len(i) for i in pk3Files)
- try:
- conWidth = int(os.environ.get("COLUMNS"))
- except (TypeError, ValueError):
- conWidth = 80
- builtFiles = []
- try:
- if os.path.isfile("pk3/buildFiles"):
- toBuild = open("pk3/buildFiles", "r").readlines()
- for i, file in enumerate(pk3Files):
- j = i + 1
- oLen = nLen
- perc = "{}%".format(int( ( (j / pk3Total) * 100) ) )
- nLen = len(perc)
- statStr = "[{:>4}]\x1F".format(perc)
- fPath, fName = os.path.realpath(file).rsplit("/", 1)
- try:
- fNameClean, fExt = fName.rsplit(".", 1)
- except ValueError:
- fNameClean, fExt = fName, ""
- zipFName = file.lstrip("./")
- if not os.path.isfile(file):
- statStr += "{} doesn't exist...".format(fName)
- statPrint(statStr)
- elif fExt in BACKUP_EXTS:
- statStr += "ignore {}...".format(fName)
- statPrint(statStr)
- elif fExt in DECORATE_EXTS and parseDecorate: # DECORATE
- statStr += "preprocessing {}...".format(fName)
- statPrint(statStr)
- prevDir = os.getcwd()
- os.chdir(fPath)
- dTmpName = tempfile.mkstemp(prefix="dec")[1]
- dTmp = open(dTmpName, "w")
- try:
- dTmp.write(fileproc.processFile(fName, LINEPROCS))
- except lineproc.LineProcError as exc:
- reason = exc.args[0]
- print("\n\n !!! ERROR !!!", file=sys.stderr)
- print(" In file {}:".format(fPath), file=sys.stderr)
- print(" {}".format(reason), file=sys.stderr)
- sys.exit(PREPROC_FAIL)
- finally:
- dTmp.close()
- os.chdir(prevDir)
- pk3Zip.write(dTmpName, zipFName)
- elif fExt in ACS_OBJ_EXTS:
- for acsExt in ACS_EXTS:
- if file in builtFiles:
- statStr += "already added {}...".format(fName)
- statPrint(statStr)
- break
- possibleSource = fPath + os.sep + fNameClean + "." + acsExt
- if os.path.exists(possibleSource):
- statStr += "ignore {}...".format(fName)
- statPrint(statStr)
- break
- else:
- statStr += "adding {}...".format(fName)
- statPrint(statStr)
- pk3Zip.write(file, zipFName)
- elif (fExt in ACS_EXTS and (not toBuild)) or (fName in toBuild): # ACS
- statStr += "building {}...".format(fName)
- statPrint(statStr)
- objFile = compileACS(file)
- pk3Zip.write(objFile, objFile.lstrip("./"))
- pk3Zip.write(file, zipFName)
- builtFiles.append(objFile)
- else:
- statStr += "adding {}...".format(fName)
- statPrint(statStr)
- pk3Zip.write(file, zipFName)
- statClean = ansicodes.stripCodes(statStr)
- print(" " * (conWidth - len(statClean) - OKLEN) + OKSTR)
- except KeyboardInterrupt:
- print()
- os.remove(pk3Name2)
- sys.exit(130)
- except RuntimeError as exc:
- print()
- errorExit(1, "\n" + exc.args[0])
- pk3Zip.close()
- os.chdir(oldDir)
- return pk3Name
- def testPK3(aArgs):
- aArgs = list(aArgs)
- try:
- parseIndex = [i.lower() for i in aArgs].index("parse")
- aArgs.pop(parseIndex)
- pk3 = makePK3(["parse"])
- except ValueError:
- pk3 = makePK3([])
- playPK3(pk3, *aArgs)
- def packagePK3(aArgs):
- if len(aArgs) < 1:
- usageExit(NO_VERSION, "no version supplied")
- try:
- parseIndex = [i.lower() for i in aArgs].index("parse")
- aArgs.pop(parseIndex)
- pk3 = makePK3(["parse"])
- except ValueError:
- pk3 = makePK3([])
- print("renaming... ", end="")
- sys.stdout.flush()
- pk3Name = os.path.basename(pk3)
- pk3Base = pk3Name.rsplit(".", 1)[0]
- zipBase = [pk3Base, aArgs[0]]
- if pk3Base[-1] in NUMBERS:
- zipBase = "_".join(zipBase)
- else:
- zipBase = "".join(zipBase)
- zipName = "{}.zip".format(zipBase)
- pk3Name2 = "{}.pk3".format(zipBase)
- shutil.move(pk3, pk3Name2)
- print("done.")
- print("packaging... ", end="")
- sys.stdout.flush()
- pk3Zip = zipfile.ZipFile(zipName, "w")
- for file in (pk3Name2, "README", "README.txt", "CHANGELOG", "CHANGELOG.txt"):
- if os.path.isfile(file):
- pk3Zip.write(file, file)
- pk3Zip.close()
- print(zipName)
- if WAD_DIR is not None:
- pk3Name3 = WAD_DIR + "/" + pk3Name2
- print("copying {} to {}... ".format(pk3Name2, pk3Name3), end="")
- sys.stdout.flush()
- shutil.copy(pk3Name2, pk3Name3)
- print("done.")
- def printHelp(aArgs):
- usageFull()
- choices = {MAKE_ACT: makePK3, TEST_ACT: testPK3, PACKAGE_ACT: packagePK3,
- HELP_ACT: printHelp}
- #######
- ##
- # MAIN CODE
- ##
- ###
- def main(*args, **kwargs):
- args = list(args)
- try:
- if len(args) < 2:
- args.extend(input("wat do? ").split())
- except KeyboardInterrupt:
- print()
- sys.exit(2)
- action = args[1].lower()
- aArgs = args[2:]
- if action in choices:
- choices[action](aArgs)
- else:
- usageExit(127, "not a valid command")
- if __name__ == "__main__":
- main(*sys.argv)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement