Advertisement
ijontichy

packagepk3.py

Dec 27th, 2011
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.68 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import sys, os, shutil, zipfile, tempfile
  4. from subprocess import Popen, PIPE
  5.  
  6. import which
  7. from pathwalker import pathwalker
  8. from decpreproc import *
  9.  
  10. LINEPROCS   = [defineproc.DefineProc, includeproc.IncludeDirProc, ]#includeproc.IncludeProc]
  11.  
  12. NUMBERS     = "0123456789"
  13.  
  14. MAKE_ACT    = "make"
  15. TEST_ACT    = "test"
  16. PACKAGE_ACT = "package"
  17. HELP_ACT    = "help"
  18.  
  19. USAGE = "usage: {} [{}] <args>".format(os.path.basename(sys.argv[0]), "|".join([MAKE_ACT, TEST_ACT, PACKAGE_ACT, HELP_ACT]))
  20.  
  21. USAGE_FULL = """
  22. - make: Builds a PK3 from the files in the pk3/ directory, with the name being
  23.  that of the current directory.
  24.  
  25. - test [port=skulltag] <args>: Runs 'make', and then runs 'port' with the PK3,
  26.  along with any arguments you choose.
  27.  
  28. - package [version]: Runs 'make', with 'version' at the end of the name, copies
  29.  it to a ZIP with the same name, and copies the PK3 to "$HOME/.zdoom" if the
  30.  directory exists.
  31.  
  32. - help: Prints this.
  33.  
  34. Examples:
  35.  # PWD is /home/derp/derpPK3
  36.  packagepk3.py make  # derpPK3.pk3
  37.  packagepk3.py test skulltag -file nuts
  38.  packagepk3.py package 1_5  # derpPK3_1_5.pk3, derpPK3_1_5.zip,
  39.                             # /home/derp/.zdoom/derpPK3_1_5.pk3
  40.  # PWD is /home/derp/derpWAD
  41.  packagepk3.py package 1_5  # derpWAD1_5.pk3, derpWAD1_5.zip,
  42.                             # /home/derp/.zdoom/derpWAD1_5.pk3
  43. """
  44.  
  45. DECORATE_EXTS   = ("dec",)
  46. ACS_EXTS        = ("c", "acs")
  47. ACS_OBJ_EXTS    = ("o",)
  48.  
  49. ACC_ERROR   = "**** ERROR ****"
  50.  
  51. DEFAULT_ARGS = ["-warp 01"]
  52.  
  53. def warn(reason):
  54.     print("warning:", reason, file=sys.stderr)
  55.  
  56.  
  57. def errorExit(code = 1, reason = None):
  58.     if reason:
  59.         print("ERROR:", reason, file=sys.stderr)
  60.  
  61.     sys.exit(code)
  62.  
  63. def usageExit(code = 1, reason = None):
  64.     if reason:
  65.         print("error:", reason, file=sys.stderr)
  66.  
  67.     usage()
  68.     sys.exit(code)
  69.  
  70. def usage():
  71.     print(USAGE)
  72.  
  73. def usageFull():
  74.     usage()
  75.     print(USAGE_FULL)
  76.  
  77. NO_ARGS, NO_PK3, NO_ACC, NO_VERSION, ACC_FAIL, NO_BINARY = range(4, 10)
  78.  
  79. PK3NAME = os.path.basename(os.path.realpath("."))
  80.  
  81. WAD_DIR = os.environ["HOME"] + "/.zdoom"
  82.  
  83. if not os.path.isdir(WAD_DIR):
  84.     warn("{} does not exist - no pk3 auto-installation will be done".format(WAD_DIR))
  85.     WAD_DIR = None
  86.  
  87. zdoomExe = "zdoom" + (".exe" if sys.platform[:3] == "win" else "")
  88. skulltagExe = "skulltag" + (".exe" if sys.platform[:3] == "win" else "")
  89.  
  90. if which.is_exe(zdoomExe):
  91.     ZDOOM = os.path.realpath(zdoomExe)
  92. else:
  93.     ZDOOM = which.which(zdoomExe)
  94.  
  95.     if ZDOOM is None:
  96.         warn("no zdoom in PATH or PWD")
  97.  
  98. if which.is_exe(skulltagExe):
  99.     SKULLTAG = os.path.realpath(skulltagExe)
  100. else:
  101.     SKULLTAG = which.which(skulltagExe)
  102.  
  103.     if SKULLTAG is None:
  104.         warn("no skulltag in PATH or PWD")
  105.  
  106.  
  107. if which.is_exe("acc"):
  108.     ACC = os.path.realpath("acc")
  109. else:
  110.     ACC = which.which("acc")
  111.  
  112.     if ACC is None:
  113.         ACC_DIR = None
  114.         errorExit(NO_ACC, "no acc in PATH or PWD")
  115.     else:
  116.         ACC_DIR = ACC.rpartition("/")[0]
  117.  
  118.  
  119.  
  120. def playPK3(pk3, binary=SKULLTAG, *args):
  121.  
  122.     if binary is None:
  123.         errorExit(1, "no binary")
  124.  
  125.     pk3 = os.path.realpath(pk3)
  126.  
  127.     if not os.path.isfile(pk3):
  128.         errorExit(NO_BINARY, "somehow, {} doesn't exist")
  129.  
  130.     if not args:
  131.         args = DEFAULT_ARGS
  132.     elif isinstance(args, str):
  133.         args = [i for i in args.split(" ") if i]
  134.     else:
  135.         args = list(args)
  136.  
  137.     pk3Game = Popen([binary, "-file {}".format(pk3)] + args)
  138.     pk3Game.wait()
  139.  
  140.     return 0
  141.  
  142.  
  143. def compileACS(file):
  144.     file2 = file
  145.     file = os.path.realpath(file)
  146.  
  147.     if not os.path.isfile(file):
  148.         errorExit(ACC_FAIL, "must provide name of actual file")
  149.  
  150.     newFile = file.rpartition(".")[:2] + ("o",)
  151.     newFile = "".join(newFile)
  152.  
  153.     newFile2 = file2.rpartition(".")[:2] + ("o",)
  154.     newFile2 = "".join(newFile2)
  155.  
  156.     accProc = Popen([ACC, "-i", ACC_DIR, file, newFile], stdout=PIPE, stderr=PIPE)
  157.  
  158.     accOut, accErr = (i.decode().split("\n") for i in accProc.communicate())
  159.  
  160.     if ACC_ERROR in accErr:
  161.         reasonLines = accErr[accErr.index(ACC_ERROR)+1:]
  162.         reason = "\n".join(reasonLines)
  163.  
  164.         raise RuntimeError(reason)
  165.  
  166.     return newFile2
  167.  
  168.  
  169. def makePK3(aArgs):
  170.     if not os.path.isdir("pk3"):
  171.         errorExit(NO_PK3, "no pk3/ directory")
  172.  
  173.     pk3Walk = pathwalker.PathWalker('pk3')
  174.  
  175.     oldDir = os.getcwd()
  176.     os.chdir("pk3")
  177.  
  178.     pk3Name     = "{}.pk3".format(PK3NAME)
  179.     pk3Name2    = "../{}.pk3".format(PK3NAME)
  180.     pk3Zip      = zipfile.ZipFile(pk3Name2, "w")
  181.     pk3Files    = pk3Walk.walk(abs=1, fFilter=lambda x: not x.endswith("*.o")).flattenFiles(rel=1)
  182.     pk3Total    = len(pk3Files)
  183.     nLen        = 0
  184.  
  185.     print("making... ", end="")
  186.  
  187.     try:
  188.         for i, file in enumerate(pk3Files):
  189.             j = i + 1
  190.  
  191.             oLen = nLen
  192.             perc = "{}%".format(int( ( (j / pk3Total) * 100) ) )
  193.             nLen = len(perc)
  194.  
  195.             print(("\b"*oLen) + perc, end="")
  196.  
  197.             sys.stdout.flush()
  198.            
  199.             fPath, fName = os.path.realpath(file).rsplit("/", 1)
  200.             fExt = file.rsplit(".", 1)[1]
  201.  
  202.             zipFName = file.lstrip("./")
  203.  
  204.             if fExt in DECORATE_EXTS:  # DECORATE
  205.                 prevDir = os.getcwd()
  206.  
  207.                 os.chdir(fPath)
  208.  
  209.                 dTmpName = tempfile.mkstemp(prefix="dec")[1]
  210.                 dTmp     = open(dTmpName, "w")
  211.                
  212.                 dTmp.write(fileproc.processFile(fName, LINEPROCS))
  213.                 dTmp.close()
  214.                
  215.                 os.chdir(prevDir)
  216.  
  217.                 pk3Zip.write(dTmpName, zipFName)
  218.            
  219.             elif fExt in ACS_OBJ_EXTS:  # ACS .o - will be handled later
  220.                 pass
  221.  
  222.             elif fExt in ACS_EXTS:  # ACS
  223.                 objFile = compileACS(file)
  224.                 pk3Zip.write(objFile, objFile.lstrip("./"))
  225.                 pk3Zip.write(file, zipFName)
  226.            
  227.             else:
  228.                 pk3Zip.write(file, zipFName)
  229.  
  230.     except KeyboardInterrupt:
  231.         print( ("\b" * (nLen + 2)) + "aborted.")
  232.         os.remove(pk3Name2)
  233.         sys.exit(127)
  234.  
  235.     except RuntimeError as exc:
  236.         print()
  237.         errorExit(1, "\n" + exc.args[0])
  238.  
  239.     pk3Zip.close()
  240.     os.chdir(oldDir)
  241.     print( ("\b" * nLen) + "done.")
  242.  
  243.     return pk3Name
  244.  
  245. def testPK3(aArgs):
  246.     pk3 = makePK3([])
  247.     playPK3(pk3, *aArgs)
  248.  
  249.  
  250. def packagePK3(aArgs):
  251.  
  252.     if len(aArgs) < 1:
  253.         usageExit(NO_VERSION, "no version supplied")
  254.  
  255.     pk3 = makePK3([])
  256.  
  257.     print("renaming... ", end="")
  258.     sys.stdout.flush()
  259.  
  260.     pk3Name = os.path.basename(pk3)
  261.     pk3Base = pk3Name.rsplit(".", 1)[0]
  262.  
  263.     zipBase = [pk3Base, aArgs[0]]
  264.  
  265.     if pk3Base[-1] in NUMBERS:
  266.         zipBase = "_".join(zipBase)
  267.     else:
  268.         zipBase = "".join(zipBase)
  269.  
  270.     zipName  = "{}.zip".format(zipBase)
  271.     pk3Name2 = "{}.pk3".format(zipBase)
  272.  
  273.     shutil.move(pk3, pk3Name2)
  274.     print("done.")
  275.  
  276.     print("packaging... ", end="")
  277.     sys.stdout.flush()
  278.  
  279.  
  280.     pk3Zip = zipfile.ZipFile(zipName, "w")
  281.  
  282.     for file in (pk3Name2, "README", "README.txt", "CHANGELOG", "CHANGELOG.txt"):
  283.         if os.path.isfile(file):
  284.             pk3Zip.write(file, file)
  285.  
  286.     pk3Zip.close()
  287.  
  288.     print(zipName)
  289.  
  290.     if WAD_DIR is not None:
  291.         pk3Name3 = WAD_DIR + "/" + pk3Name2
  292.  
  293.         print("copying {} to {}... ".format(pk3Name2, pk3Name3), end="")
  294.         sys.stdout.flush()
  295.  
  296.         shutil.copy(pk3Name2, pk3Name3)
  297.         print("done.")
  298.  
  299. def printHelp(aArgs):
  300.     usageFull()
  301.  
  302.  
  303. choices = {MAKE_ACT: makePK3, TEST_ACT: testPK3, PACKAGE_ACT: packagePK3,
  304.             HELP_ACT: printHelp}
  305.  
  306. #######
  307. ##
  308. #   MAIN CODE
  309. ##
  310. ###
  311.  
  312. def main(*args, **kwargs):
  313.  
  314.     if len(args) < 2:
  315.         usageExit(NO_ARGS, "not enough arguments")
  316.  
  317.     action = args[1].lower()
  318.     aArgs  = args[2:]
  319.  
  320.     if action in choices:
  321.         choices[action](aArgs)
  322.     else:
  323.         usageExit(127, "not a valid command")
  324.  
  325. if __name__ == "__main__":
  326.     main(*sys.argv)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement