Browse Source

Rename error to echo0 and debug to echo1. Add and use main's return in many cases. Remove lint. Move TRY_SHARE_MT_DIRS from deprecated.

master
poikilos 2 years ago
parent
commit
e170a2b123
  1. 1
      .gitignore
  2. 52
      Bucket_Game-base/trimpatchstats.py
  3. 27
      Bucket_Game-branches/remove_not_in.py
  4. 32
      basecompare.py
  5. 17
      buildenliven.py
  6. 61
      deploy.py
  7. 28
      filever.py
  8. 14
      forwardfilesync.py
  9. 10
      generate-mt5-share-fix.py
  10. 44
      headcompare.py
  11. 169
      install-subgametest.py
  12. 31
      install.py
  13. 144
      mtsenliven.py
  14. 11
      notes/continuify.py
  15. 103
      pyenliven/__init__.py
  16. 30
      pyenliven/compatiblizemod.py
  17. 3
      pyenliven/deprecated.py
  18. 77
      setup.py
  19. 17
      uninstall-minetestserver-git.py
  20. 8
      utilities/compatiblizemod.py
  21. 97
      utilities/enissue.py
  22. 39
      utilities/enlynx.py
  23. 29
      utilities/extra/uninstall.py
  24. 23
      utilities/generatemod.py
  25. 13
      utilities/mtcompile-program-local.py
  26. 10
      utilities/mtoldtonew.py
  27. 25
      utilities/showmissing.py

1
.gitignore

@ -18,3 +18,4 @@ linux-minetest-kit.zip
/docker/lmk-libraries.devuan-chimera/install-minetest-build-deps.sh /docker/lmk-libraries.devuan-chimera/install-minetest-build-deps.sh
/docker/libraries-devuan-chimera/install-minetest-build-deps.sh /docker/libraries-devuan-chimera/install-minetest-build-deps.sh
/docker/libraries-devuan-chimaera/install-minetest-build-deps.sh /docker/libraries-devuan-chimaera/install-minetest-build-deps.sh
/debug.txt

52
Bucket_Game-base/trimpatchstats.py

@ -1,13 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
''' '''
Remove the lines from the from the input file in Bucket_Game-base that are not in the matching list file in Bucket_Game-branches. Remove the lines from the from the input file in Bucket_Game-base that
are not in the matching list file in Bucket_Game-branches.
The resulting modified list is written to standard output. The resulting modified list is written to standard output.
The provided filename must exist in both the Bucket_Game-base directory and the parallel Bucket_Game-branches directory. The provided filename must exist in both the Bucket_Game-base directory
and the parallel Bucket_Game-branches directory.
The file must contain output such as from ls or find executing ls. Examples: The file must contain output such as from ls or find executing ls. Examples:
find -type f -name "*.ogg" -exec ls -lh {} \; find -type f -name "*.ogg" -exec ls -lh {} \\;
find -type f -exec ls -lh {} \; find -type f -exec ls -lh {} \\;
Usage: Usage:
./trimpatchstats.py <filename> ./trimpatchstats.py <filename>
@ -16,15 +18,16 @@ import sys
import os import os
import json import json
def error(msg):
sys.stderr.write("{}\n".format(msg)) def echo0(*args, **kwargs):
sys.stderr.flush() print(*args, file=sys.stderr, **kwargs)
def usage(): def usage():
error("") echo0("")
error("trimpatchstats.py") echo0("trimpatchstats.py")
error("-----------------") echo0("-----------------")
error(__doc__) echo0(__doc__)
def splitFirst(line, delimiter): def splitFirst(line, delimiter):
@ -196,6 +199,7 @@ class LSFileInfo:
def __str__(self): def __str__(self):
return json.dumps(self.to_dict()) return json.dumps(self.to_dict())
def getFileNumber(path, num): def getFileNumber(path, num):
''' '''
Get a file from a listfile that contains ls -l or ls -n output. Get a file from a listfile that contains ls -l or ls -n output.
@ -251,7 +255,7 @@ def printOnlyPatched(baseListPath):
if fid is None: if fid is None:
print("Error: \"{}\" contained no filenames." print("Error: \"{}\" contained no filenames."
"".format(patchedListPath)) "".format(patchedListPath))
exit(1) return 1
tryFilePath = os.path.join(targetDirPath, fid['name']) tryFilePath = os.path.join(targetDirPath, fid['name'])
if not os.path.isfile(tryFilePath): if not os.path.isfile(tryFilePath):
print("Error: \"{}\" doesn't exist. Run again from the" print("Error: \"{}\" doesn't exist. Run again from the"
@ -260,9 +264,9 @@ def printOnlyPatched(baseListPath):
" directory name in the \"{}\" directory and run in a" " directory name in the \"{}\" directory and run in a"
" directory parallel to that." " directory parallel to that."
"".format(tryFilePath, fid['name'], patchedPath)) "".format(tryFilePath, fid['name'], patchedPath))
exit(1) return 2
error("* analyzing \"{}\"".format(patchedListPath)) echo0("* analyzing \"{}\"".format(patchedListPath))
patchedFIs = [] patchedFIs = []
rawNames = [] rawNames = []
with open(patchedListPath, 'r') as ins: with open(patchedListPath, 'r') as ins:
@ -279,9 +283,9 @@ def printOnlyPatched(baseListPath):
fid = parse_ls(line) fid = parse_ls(line)
rawNames.append(fid['name']) rawNames.append(fid['name'])
# fill_file_dict_path(fid, targetDirPath) # fill_file_dict_path(fid, targetDirPath)
# error(fid) # echo0(fid)
error("* analyzing \"{}\"".format(baseListPath)) echo0("* analyzing \"{}\"".format(baseListPath))
allCount = 0 allCount = 0
matchCount = 0 matchCount = 0
with open(baseListPath, 'r') as ins: with open(baseListPath, 'r') as ins:
@ -300,13 +304,19 @@ def printOnlyPatched(baseListPath):
if fid['name'] in rawNames: if fid['name'] in rawNames:
print(line) print(line)
matchCount += 1 matchCount += 1
error("{} of {} in {} were also in {}" echo0("{} of {} in {} were also in {}"
"".format(matchCount, allCount, baseListPath, "".format(matchCount, allCount, baseListPath,
patchedListPath)) patchedListPath))
return 0
if __name__ == "__main__":
def main():
if len(sys.argv) < 2: if len(sys.argv) < 2:
usage() usage()
error("Error: You are missing the required list filename argument.\n") echo0("Error: You are missing the required list filename argument.\n")
exit(1) return 1
printOnlyPatched(sys.argv[1]) return printOnlyPatched(sys.argv[1])
if __name__ == "__main__":
sys.exit(main())

27
Bucket_Game-branches/remove_not_in.py

@ -11,9 +11,8 @@ else:
profile = os.environ['HOME'] profile = os.environ['HOME']
def error(msg): def echo0(*args, **kwargs):
sys.stderr.write("{}\n".format(msg)) print(*args, file=sys.stderr, **kwargs)
sys.stderr.flush()
def showNotInOriginal(patched, original, root=None, ignores=[]): def showNotInOriginal(patched, original, root=None, ignores=[]):
@ -34,7 +33,8 @@ def showNotInOriginal(patched, original, root=None, ignores=[]):
if sub in ignores: if sub in ignores:
continue continue
if os.path.isdir(patchedPath): if os.path.isdir(patchedPath):
showNotInOriginal(patchedPath, originalPath, root=root, ignores=ignores) showNotInOriginal(patchedPath, originalPath, root=root,
ignores=ignores)
continue continue
if not os.path.isfile(originalPath): if not os.path.isfile(originalPath):
relPath = patchedPath[len(root):] relPath = patchedPath[len(root):]
@ -47,17 +47,24 @@ def showNotInOriginal(patched, original, root=None, ignores=[]):
print("rm {}".format(dotPathShell)) print("rm {}".format(dotPathShell))
if __name__ == "__main__": def main():
original = os.path.join(profile, "minetest", "games", "Bucket_Game") original = os.path.join(profile, "minetest", "games", "Bucket_Game")
patched = os.path.abspath(".") patched = os.path.abspath(".")
originalMods = os.path.join(original, "mods") originalMods = os.path.join(original, "mods")
patchedMods = os.path.join(patched, "mods") patchedMods = os.path.join(patched, "mods")
if not os.path.isdir(originalMods): if not os.path.isdir(originalMods):
error("Error: \"{}\" doesn't seem to be a game since it doesn't have a \"mods\" directory.".format(original)) echo0("Error: \"{}\" doesn't seem to be a game since it doesn't"
exit(1) " have a \"mods\" directory.".format(original))
return 1
if not os.path.isdir(patchedMods): if not os.path.isdir(patchedMods):
error("Error: \"{}\" doesn't seem to be a game since it doesn't have a \"mods\" directory.".format(patched)) echo0("Error: \"{}\" doesn't seem to be a game since it doesn't"
exit(1) " have a \"mods\" directory.".format(patched))
return 2
myName = os.path.split(sys.argv[0])[1] myName = os.path.split(sys.argv[0])[1]
# error("myName:{}".format(myName)) # echo0("myName:{}".format(myName))
showNotInOriginal(patched, original, None, ignores=[myName]) showNotInOriginal(patched, original, None, ignores=[myName])
return 0
if __name__ == "__main__":
sys.exit(main())

32
basecompare.py

@ -3,8 +3,11 @@ from __future__ import print_function
import sys import sys
import os import os
from pyenliven import (
echo0,
)
from headcompare import ( from headcompare import (
error,
compareBranch, compareBranch,
defaultVirtualReposDir, defaultVirtualReposDir,
minetestPath, minetestPath,
@ -15,45 +18,48 @@ from headcompare import (
me = os.path.basename(__file__) me = os.path.basename(__file__)
def usage(): def usage():
error("Usage:") echo0("Usage:")
sys.stderr.write("Specify a branch") sys.stderr.write("Specify a branch")
parent = "Bucket_Game-base" parent = "Bucket_Game-base"
if os.path.isdir(parent): if os.path.isdir(parent):
error(" from Bucket_Game-base:") echo0(" from Bucket_Game-base:")
for sub in os.listdir(parent): for sub in os.listdir(parent):
subPath = os.path.join(parent, sub) subPath = os.path.join(parent, sub)
if sub.startswith("."): if sub.startswith("."):
continue continue
if os.path.isdir(subPath): if os.path.isdir(subPath):
error(subPath) echo0(subPath)
else: else:
error(" from Bucket_Game-base.") echo0(" from Bucket_Game-base.")
echo0("{} <branch name (see above)> [<bucket_game path>]".format(me))
echo0("")
error("{} <branch name (see above)> [<bucket_game path>]".format(me))
error("")
def main(): def main():
global defaultGamePath global defaultGamePath
defaultGamePath = None defaultGamePath = None
if len(sys.argv) < 2: if len(sys.argv) < 2:
usage() usage()
error("Error: You must provide a branch name.\n") echo0("Error: You must provide a branch name.\n")
exit(1) return 1
if len(sys.argv) > 3: if len(sys.argv) > 3:
usage() usage()
error("Error: There are too many arguments: {}.\n" echo0("Error: There are too many arguments: {}.\n"
"".format(sys.argv)) "".format(sys.argv))
exit(1) return 1
if len(sys.argv) > 2: if len(sys.argv) > 2:
defaultGamePath = sys.argv[2] defaultGamePath = sys.argv[2]
results = compareBranch(sys.argv[1], gamePath=defaultGamePath, results = compareBranch(sys.argv[1], gamePath=defaultGamePath,
compareOld=True) compareOld=True)
error("# ^ Do that to verify: they MUST match, and the first" echo0("# ^ Do that to verify: they MUST match, and the first"
" directory must be unmodified from the original" " directory must be unmodified from the original"
" release package.") " release package.")
return 0
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

17
buildenliven.py

@ -9,9 +9,10 @@ import os
import configparser import configparser
from pyenliven import ( from pyenliven import (
error, echo0,
getSGPath, getSGPath,
profile, profile,
MODS_STOPGAP_DIR,
) )
gamespec = {} gamespec = {}
@ -27,6 +28,7 @@ gamespec['remove_mods'] = [
gamespec['local_mods_paths'] = [] gamespec['local_mods_paths'] = []
gamespec['local_mods_paths'].append("mods_stopgap") gamespec['local_mods_paths'].append("mods_stopgap")
# ^ See also MODS_STOPGAP_DIR (full path) in pyenliven
gamespec['add_mods'] = [ gamespec['add_mods'] = [
# {'repo': "https://github.com/poikilos/homedecor_ua"}, # {'repo': "https://github.com/poikilos/homedecor_ua"},
@ -166,12 +168,13 @@ WARNINGS:
warnings = [] warnings = []
valid_bases = ['Bucket_Game', "bucket_game"] valid_bases = ['Bucket_Game', "bucket_game"]
def main(): def main():
for warning in warnings: for warning in warnings:
error(warning) echo0(warning)
tryGameDir = os.getcwd() tryGameDir = os.getcwd()
error('* examining "{}"'.format(tryGameDir)) echo0('* examining "{}"'.format(tryGameDir))
gameConfName = "game.conf" gameConfName = "game.conf"
gameConfPath = os.path.join(tryGameDir, gameConfName) gameConfPath = os.path.join(tryGameDir, gameConfName)
if not os.path.isfile(gameConfPath): if not os.path.isfile(gameConfPath):
@ -185,7 +188,7 @@ def main():
config.read_string('[top]\n' + ins.read()) config.read_string('[top]\n' + ins.read())
# ^ insert a section since ConfigParser requires sections. # ^ insert a section since ConfigParser requires sections.
gameName = config['top'].get("name") gameName = config['top'].get("name")
error(' * detected {} from {}' echo0(' * detected "{}" from "{}"'
''.format(gameName, gameConfName)) ''.format(gameName, gameConfName))
if gameName not in valid_bases: if gameName not in valid_bases:
raise ValueError( raise ValueError(
@ -200,8 +203,10 @@ def main():
# ^ TODO: Get this from mtanalyze? # ^ TODO: Get this from mtanalyze?
targetGames = os.path.join(targetMT, "games") targetGames = os.path.join(targetMT, "games")
target = os.path.join(targetGames, "ENLIVEN") target = os.path.join(targetGames, "ENLIVEN")
centerOfTheSunTarget = centerOfTheSunTarget = None
raise NotImplementedError("pyenliven build") raise NotImplementedError("pyenliven build")
return 0
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

61
deploy.py

@ -1,17 +1,29 @@
#!/usr/bin/env python #!/usr/bin/env python
import os import os
import sys
import shutil import shutil
from forwardfilesync import * from forwardfilesync import *
# import filever # import filever
try: from pyenliven import (
input = raw_input echo0,
except NameError: )
if sys.version_info.major >= 3:
pass pass
else:
input = raw_input
def rm_sub(bad_sub):
bad_path = path_join_all(deploy_path, bad_sub)
if os.path.isfile(bad_path):
os.remove(bad_path)
def main():
warnings = list() warnings = list()
print("") echo0("")
print("This script is NOT YET IMPLEMENTED") echo0("This script is NOT YET IMPLEMENTED")
# TODO: Scrape https://minetest.kitsunemimi.pw/builds/ (NOTE: stable is # TODO: Scrape https://minetest.kitsunemimi.pw/builds/ (NOTE: stable is
@ -19,7 +31,7 @@ print("This script is NOT YET IMPLEMENTED")
# "minetest-0.4.15-win64.7z") # "minetest-0.4.15-win64.7z")
print("This script patches minetest and minetest_game with ENLIVEN\n" + echo0("This script patches minetest and minetest_game with ENLIVEN\n" +
"(such as launcher and subgame) and creates a Windows installer.") "(such as launcher and subgame) and creates a Windows installer.")
script_dir_path = os.path.dirname(os.path.abspath(__file__)) script_dir_path = os.path.dirname(os.path.abspath(__file__))
@ -35,7 +47,7 @@ else:
if not os.path.isdir(try_path): if not os.path.isdir(try_path):
try_path = "C:\\Users\\Owner" try_path = "C:\\Users\\Owner"
print("WARNING: no HOME or USERPROFILE found, reverting to '" + echo0("WARNING: no HOME or USERPROFILE found, reverting to '" +
try_path + "'") try_path + "'")
profile_path = try_path profile_path = try_path
# TODO: Make a settings file for values in the next region. # TODO: Make a settings file for values in the next region.
@ -52,7 +64,7 @@ installer_name = "install-ENLIVEN.exe"
installer_path = os.path.join(installer_deploy_path, installer_name) installer_path = os.path.join(installer_deploy_path, installer_name)
if not os.path.isdir(installer_deploy_path): if not os.path.isdir(installer_deploy_path):
print("#WARNING: does not exist:") echo0("#WARNING: does not exist:")
print("installer_deploy_path: " + installer_deploy_path) print("installer_deploy_path: " + installer_deploy_path)
# this is a waste--it just shows 0.0.0.0 though iss file has version # this is a waste--it just shows 0.0.0.0 though iss file has version
@ -67,23 +79,23 @@ games_path = os.path.join(deploy_path, "games")
minetest_game_path = os.path.join(games_path, "minetest_game") minetest_game_path = os.path.join(games_path, "minetest_game")
minetest_game_mods_path = os.path.join(minetest_game_path, "mods") minetest_game_mods_path = os.path.join(minetest_game_path, "mods")
if not os.path.isdir(minetest_game_path): if not os.path.isdir(minetest_game_path):
print("This deploy script requires an unmodified build of minetest and\n" + echo0("This deploy script requires an unmodified build of minetest and\n" +
" minetest_game. Please place an unmodified build of minetest in\n" + " minetest_game. Please place an unmodified build of minetest in\n" +
" " + deploy_path + " so that minetest_game is at: \n\n" + " " + deploy_path + " so that minetest_game is at: \n\n" +
" " + minetest_game_path + "\n\n") " " + minetest_game_path + "\n\n")
exit(1) return 1
game_path = os.path.join(games_path, "ENLIVEN") game_path = os.path.join(games_path, "ENLIVEN")
# NOTE: remove this case, and instead: copy minetest_game, download ENLIVEN # NOTE: remove this case, and instead: copy minetest_game, download ENLIVEN
# automatically # automatically
if not os.path.isdir(game_path): if not os.path.isdir(game_path):
print("") echo0("")
print("ERROR: ENLIVEN must first be installed from web sources" + echo0("ERROR: ENLIVEN must first be installed from web sources" +
" using the provided 'install' script in the etc/change*" + " using the provided 'install' script in the etc/change*" +
" folder (run on linux then copy to a Windows machine" + " folder (run on linux then copy to a Windows machine" +
" in " + game_path) " in " + game_path)
# exit(2) # return 2
else: else:
print("game_path: " + game_path) print("game_path: " + game_path)
mods_path = os.path.join(game_path, "mods") mods_path = os.path.join(game_path, "mods")
@ -113,13 +125,6 @@ else:
shutil.copyfile(server_devel_minetest_conf_path, shutil.copyfile(server_devel_minetest_conf_path,
server_minetest_conf_path) server_minetest_conf_path)
def rm_sub(bad_sub):
bad_path = path_join_all(deploy_path, bad_sub)
if os.path.isfile(bad_path):
os.remove(bad_path)
rm_sub(["CC-BY-SA 3.0 Unported (fallback license for ENLIVEN assets)" rm_sub(["CC-BY-SA 3.0 Unported (fallback license for ENLIVEN assets)"
".txt"]) ".txt"])
rm_sub(["MIT LICENSE (fallback license for ENLIVEN code).txt"]) rm_sub(["MIT LICENSE (fallback license for ENLIVEN code).txt"])
@ -130,12 +135,16 @@ rm_sub(["MIT LICENSE (fallback license for ENLIVEN code).txt"])
# rm_sub(["games", "ENLIVEN", "LICENSE.txt"]) # rm_sub(["games", "ENLIVEN", "LICENSE.txt"])
# rm_sub(["games", "ENLIVEN", "README.txt"]) # rm_sub(["games", "ENLIVEN", "README.txt"])
print("") echo0("")
if len(warnings) > 0: if len(warnings) > 0:
print(str(len(warnings)) + " warning(s):") echo0(str(len(warnings)) + " warning(s):")
for warning in warnings: for warning in warnings:
print(warning) echo0(warning)
else: else:
print("0 warnings.") echo0("0 warnings.")
print("\n") echo0()
input("press enter to exit...") return 0
if __name__ == "__main__":
sys.exit(main())

28
filever.py

@ -1,5 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# by Jamie at <http://stackoverflow.com/questions/580924/python-windows- import sys
# based on code by Jamie at
# <http://stackoverflow.com/questions/580924/python-windows-
# file-version-attribute> # file-version-attribute>
try: try:
from win32api import GetFileVersionInfo, LOWORD, HIWORD from win32api import GetFileVersionInfo, LOWORD, HIWORD
@ -7,7 +9,7 @@ except ImportError:
print("you need to install win32api such as with the command:") print("you need to install win32api such as with the command:")
print("sudo python2 -m pip install --upgrade pip") print("sudo python2 -m pip install --upgrade pip")
print("sudo python -m pip install pypiwin32") print("sudo python -m pip install pypiwin32")
exit(1) sys.exit(1)
from win32api import GetFileVersionInfo, LOWORD, HIWORD from win32api import GetFileVersionInfo, LOWORD, HIWORD
@ -23,15 +25,25 @@ def get_version_number(filename):
return 0, 0, 0, 0 return 0, 0, 0, 0
if __name__ == '__main__': API_USAGE = '''
# API Usage:
import filever
parts = filever.get_version_number(filename)
major,minor,subminor,revision = parts
print(".".join([str (i) for i in parts]))
'''
def main():
import os import os
if "COMSPEC" in os.environ: if "COMSPEC" in os.environ:
filename = os.environ["COMSPEC"] filename = os.environ["COMSPEC"]
this_delimiter = "." this_delimiter = "."
print(str(filename) + " version:") print(str(filename) + " version:")
print(".".join([str(i) for i in get_version_number(filename)])) print(".".join([str(i) for i in get_version_number(filename)]))
print("Running filever directly doesn't do much.\n\n#Usage:\n" + print("Running filever directly doesn't do much\n\n"+API_USAGE)
"import filever\n" + return 0
"parts = filever.get_version_number(filename)\n" +
"major,minor,subminor,revision = parts\n" +
"print(\".\".join([str (i) for i in parts]))\n\n") if __name__ == '__main__':
sys.exit(main())

14
forwardfilesync.py

@ -24,6 +24,7 @@ if platform.system() == "Windows":
CMD_CP = "COPY" CMD_CP = "COPY"
CMD_MKDIR = "MD" CMD_MKDIR = "MD"
def path_join_all(names): def path_join_all(names):
result = names[0] result = names[0]
for i in range(1, len(names)): for i in range(1, len(names)):
@ -122,6 +123,7 @@ def update_tree(src, dst, level=0, do_trim=False, dot_hidden=False,
"".format(CMD_CP, sub_path, dst_sub_path)) "".format(CMD_CP, sub_path, dst_sub_path))
pass pass
USAGE = ''' USAGE = '''
Syntax: Syntax:
forwardfilesync.py <source> <destination> [options] forwardfilesync.py <source> <destination> [options]
@ -131,9 +133,11 @@ forwardfilesync.py <source> <destination> [options]
''' '''
def usage(): def usage():
print(USAGE) print(USAGE)
def main(): def main():
flags = {} flags = {}
flags["hidden"] = False flags["hidden"] = False
@ -142,7 +146,7 @@ def main():
if len(sys.argv) < 3: if len(sys.argv) < 3:
usage() usage()
print("Error: You must provide at least a source and destination.") print("Error: You must provide at least a source and destination.")
exit(1) return 1
src = sys.argv[1] src = sys.argv[1]
dst = sys.argv[2] dst = sys.argv[2]
@ -155,14 +159,14 @@ def main():
" since it doesn't start with \"--\". If it is part" " since it doesn't start with \"--\". If it is part"
" of a path with spaces, put the path in quotes." " of a path with spaces, put the path in quotes."
"".format(sys.argv[argI])) "".format(sys.argv[argI]))
exit(1) return 1
name = arg[2:] name = arg[2:]
if name not in flags: if name not in flags:
usage() usage()
print("Error: There is no option \"{}\". If it is part of a" print("Error: There is no option \"{}\". If it is part of a"
" path with spaces, put the path in quotes." " path with spaces, put the path in quotes."
"".format(sys.argv[argI])) "".format(sys.argv[argI]))
exit(1) return 1
flags[name] = True flags[name] = True
print(CMD_COMMENT + "Using options:") print(CMD_COMMENT + "Using options:")
for k, v in flags.items(): for k, v in flags.items():
@ -175,8 +179,8 @@ def main():
dot_hidden=flags["hidden"] is True, dot_hidden=flags["hidden"] is True,
) )
print(CMD_COMMENT + "Done.") print(CMD_COMMENT + "Done.")
return 0
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

10
generate-mt5-share-fix.py

@ -1,10 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import shutil import shutil
import sys
actions = {"-- Up-to-date: ": "move", "-- Installing: ": "move"} actions = {"-- Up-to-date: ": "move", "-- Installing: ": "move"}
changes = { changes = {
"/usr/local/./": "/usr/local/share/minetest/" "/usr/local/./": "/usr/local/share/minetest/"
} }
def main():
count = 0 count = 0
command_count = 0 command_count = 0
in_path = "bad_mt5_make_install_output.txt" in_path = "bad_mt5_make_install_output.txt"
@ -142,3 +146,9 @@ with open(in_path) as ins:
print('Added {} line(s) to "{}" (including {} command(s))' print('Added {} line(s) to "{}" (including {} command(s))'
''.format(count, out_path, command_count)) ''.format(count, out_path, command_count))
return 0
if __name__ == "__main__":
sys.exit(main())

44
headcompare.py

@ -4,45 +4,46 @@ import sys
import os import os
import platform import platform
from pyenliven import (
echo0,
)
me = os.path.basename(__file__) me = os.path.basename(__file__)
myDir = os.path.dirname(os.path.abspath(__file__)) myDir = os.path.dirname(os.path.abspath(__file__))
defaultVirtualReposDir = myDir defaultVirtualReposDir = myDir
def error(msg):
sys.stderr.write("{}\n".format(msg))
sys.stderr.flush()
def usage(): def usage():
error("Usage:") echo0("Usage:")
sys.stderr.write("Specify a branch") sys.stderr.write("Specify a branch")
parent = "Bucket_Game-branches" parent = "Bucket_Game-branches"
if os.path.isdir(parent): if os.path.isdir(parent):
error(" from Bucket_Game-branches:") echo0(" from Bucket_Game-branches:")
for sub in os.listdir(parent): for sub in os.listdir(parent):
subPath = os.path.join(parent, sub) subPath = os.path.join(parent, sub)
if sub.startswith("."): if sub.startswith("."):
continue continue
if os.path.isdir(subPath): if os.path.isdir(subPath):
error(subPath) echo0(subPath)
else: else:
error(" from Bucket_Game-branches.") echo0(" from Bucket_Game-branches.")
error("{} <branch name (see above)> [<bucket_game path>]".format(me)) echo0("{} <branch name (see above)> [<bucket_game path>]".format(me))
error("") echo0("")
profile = None profile = None
if platform.system() == "Windows": if platform.system() == "Windows":
profile = os.environ.get('USERPROFILE') profile = os.environ.get('USERPROFILE')
if profile is None: if profile is None:
error("Error: USERPROFILE is not set.") echo0("Error: USERPROFILE is not set.")
exit(1) sys.exit(1)
else: else:
profile = os.environ.get('HOME') profile = os.environ.get('HOME')
if profile is None: if profile is None:
error("Error: HOME is not set.") echo0("Error: HOME is not set.")
exit(1) sys.exit(1)
minetestPath = os.path.join(profile, "minetest") minetestPath = os.path.join(profile, "minetest")
gamesPath = os.path.join(minetestPath, "games") gamesPath = os.path.join(minetestPath, "games")
@ -153,7 +154,6 @@ def compareBranch(branchName, gamePath=None, bgVersion=None,
if branchPathRel.startswith(myDirSlash): if branchPathRel.startswith(myDirSlash):
branchPathRel = branchPathRel[len(myDirSlash):] branchPathRel = branchPathRel[len(myDirSlash):]
print("meld \"{}\" \"{}\"".format(gamePath, branchPath)) print("meld \"{}\" \"{}\"".format(gamePath, branchPath))
patchFilePath = branchPath+".patch" patchFilePath = branchPath+".patch"
print("diff -ru \"{}\" \"{}\" > \"{}\"" print("diff -ru \"{}\" \"{}\" > \"{}\""
@ -166,26 +166,28 @@ def compareBranch(branchName, gamePath=None, bgVersion=None,
} }
return results return results
def main(): def main():
global defaultGamePath global defaultGamePath
defaultGamePath = None defaultGamePath = None
if len(sys.argv) < 2: if len(sys.argv) < 2:
usage() usage()
error("Error: You must provide a branch name.\n") echo0("Error: You must provide a branch name.\n")
exit(1) return 1
if len(sys.argv) > 3: if len(sys.argv) > 3:
usage() usage()
error("Error: There are too many arguments: {}.\n" echo0("Error: There are too many arguments: {}.\n"
"".format(sys.argv)) "".format(sys.argv))
exit(1) return 1
if len(sys.argv) > 2: if len(sys.argv) > 2:
defaultGamePath = sys.argv[2] defaultGamePath = sys.argv[2]
results = compareBranch(sys.argv[1], gamePath=defaultGamePath) results = compareBranch(sys.argv[1], gamePath=defaultGamePath)
error("# ^ Do that to see the difference or generate a patch," echo0("# ^ Do that to see the difference or generate a patch,"
" but the first directory must be unmodified from the" " but the first directory must be unmodified from the"
" original release package.") " original release package.")
return 0
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

169
install-subgametest.py

@ -9,10 +9,12 @@ from forwardfilesync import *
force_update_mtg_enable = False # first delete subgametest then remake force_update_mtg_enable = False # first delete subgametest then remake
# endregion options # endregion options
try: '''
input = raw_input if sys.version_info.major >= 3:
except NameError:
pass pass
else:
input = raw_input
'''
gitpython_msg = """ gitpython_msg = """
You do not have gitpython installed. You do not have gitpython installed.
@ -42,22 +44,30 @@ try:
except ImportError: except ImportError:
print(gitpython_msg) print(gitpython_msg)
print("") print("")
input("press enter to close...") sys.exit(1)
exit(1)
from pyenliven import (
echo0,
)
from mtanalyze import(
TRY_SHARE_MT_DIRS,
get_var_and_check,
)
profile_path = None profile_path = None
if 'HOME' in os.environ: # if os.name=="windows": if 'HOME' in os.environ:
profile_path = os.environ['HOME'] profile_path = os.environ['HOME']
else: else: # if platform.system() == "Windows"
profile_path = os.environ['USERPROFILE'] profile_path = os.environ['USERPROFILE']
def main():
if not os.path.isdir(profile_path): if not os.path.isdir(profile_path):
print("") echo0("")
print("Failed to get existing home path--tried HOME & USERPROFILE") echo0("Failed to get existing home path--tried HOME & USERPROFILE")
print("") echo0("")
input("press enter to close") return 2
exit(2)
configs_path = os.path.join(profile_path, ".config") configs_path = os.path.join(profile_path, ".config")
if os.name == "windows": if os.name == "windows":
@ -83,36 +93,44 @@ if not os.path.isdir(GIT_REPOS_PATH):
if not os.path.isdir(GIT_BRANCHES_PATH): if not os.path.isdir(GIT_BRANCHES_PATH):
os.makedirs(GIT_BRANCHES_PATH) os.makedirs(GIT_BRANCHES_PATH)
USR_SHARE_MINETEST = "/usr/share/games/minetest" '''
if not os.path.isdir(USR_SHARE_MINETEST): USR_SHARE_MINETEST = None
if os.path.isdir("/usr/local/share/minetest"): for try_share_mt in TRY_SHARE_MT_DIRS:
# IF git version is installed: if os.path.isdir(try_share_mt):
USR_SHARE_MINETEST = "/usr/local/share/minetest" USR_SHARE_MINETEST = try_share_mt
if os.path.isdir("/usr/share/minetest"): break
USR_SHARE_MINETEST = "/usr/share/minetest" if USR_SHARE_MINETEST is None:
echo0("Minetest could not be found in any known location ({})."
if not os.path.isdir(USR_SHARE_MINETEST):
print("Minetest could not be found in any known location."
" Try installing minetest or compiling from source or" " Try installing minetest or compiling from source or"
" editing value of USR_SHARE_MINETEST in this script." " editing value of USR_SHARE_MINETEST in this script."
" The script ended early.") " The script ended early.".format(TRY_SHARE_MT_DIRS))
input("press enter to close...") return 3
exit(3) '''
USR_SHARE_MINETEST, code = get_var_and_check('shared_minetest_path', 3)
if code != 0:
return code
MT_GAMES_DIR = os.path.join(USR_SHARE_MINETEST, "games") MT_GAMES_DIR = os.path.join(USR_SHARE_MINETEST, "games")
MT_MYGAME_NAME = "subgametest" MT_MYGAME_NAME = "subgametest"
MT_MYGAME_DIR = os.path.join(MT_GAMES_DIR, MT_MYGAME_NAME) MT_MYGAME_DIR = os.path.join(MT_GAMES_DIR, MT_MYGAME_NAME)
mtg_game_name = "minetest_game" MTG_PATH = None
MTG_PATH = os.path.join(MT_GAMES_DIR, mtg_game_name) mtg_game_name = None
folder_path = MTG_PATH base_game_path = None
MTG_MODS_PATH = os.path.join(MTG_PATH, "mods") base_games = ["amhi_game", "minetest_game"]
for try_game_name in base_games:
MTG_PATH = os.path.join(MT_GAMES_DIR, try_game_name)
base_game_path = MTG_PATH
if os.path.isdir(base_game_path):
mtg_game_name = try_game_name
if mtg_game_name is None:
echo0("Could not find \"" + base_game_path + "\". Script ended early.")
echo0("Set shared_minetest_path to the path containing a")
echo0(" games folder with one of the following: {}".format(base_games))
return 4
if not os.path.isdir(folder_path): MTG_MODS_PATH = os.path.join(MTG_PATH, "mods")
print("Could not find \"" + folder_path + "\". Script ended early.")
input("press enter to close...")
exit(4)
if force_update_mtg_enable: if force_update_mtg_enable:
shutil.rmtree(MT_MYGAME_DIR) shutil.rmtree(MT_MYGAME_DIR)
@ -122,16 +140,15 @@ if force_update_mtg_enable:
try: try:
# DOES update minetest_game, but does NOT delete extra mods: # DOES update minetest_game, but does NOT delete extra mods:
update_tree(folder_path, MT_MYGAME_DIR) update_tree(base_game_path, MT_MYGAME_DIR)
print("Updated \"" + MT_MYGAME_DIR + "\"...") echo0("Updated \"" + MT_MYGAME_DIR + "\"...")
except PermissionError: except PermissionError:
print(str(sys.exc_info())) echo0(str(sys.exc_info()))
print("") echo0("")
print("You must run " + __file__ + " as a user that can write to " echo0("You must run " + __file__ + " as a user that can write to "
"\"" + MT_MYGAME_DIR + "\"") "\"" + MT_MYGAME_DIR + "\"")
print("") echo0("")
input("press enter to close...") return 5
exit(5)
try: try:
# cd $HOME # cd $HOME
@ -140,76 +157,72 @@ try:
outs.write("name = subgametest") outs.write("name = subgametest")
outs.close() outs.close()
except PermissionError: except PermissionError:
print(str(sys.exc_info())) echo0(str(sys.exc_info()))
print("") echo0("")
print("You must run " + __file__ + " as a user that can write to " echo0("You must run " + __file__ + " as a user that can write to "
"\"" + MT_MYGAME_DIR + "\"") "\"" + MT_MYGAME_DIR + "\"")
print("") echo0("")
input("press enter to close...") return 6
exit(6)
# cmd_string = "sudo mv -f game.conf \MT_MYGAME_DIR\"" # cmd_string = "sudo mv -f game.conf \MT_MYGAME_DIR\""
# shutil.move(tmp_game_conf_path, os.path.join(MT_MYGAME_DIR, "game.conf")) # shutil.move(tmp_game_conf_path, os.path.join(MT_MYGAME_DIR, "game.conf"))
if os.path.isdir(os.path.join(MT_MYGAME_DIR, "mods")): good_dir = os.path.join(MT_MYGAME_DIR, "mods")
print("Copied subgame to " + MT_MYGAME_DIR) if os.path.isdir(good_dir):
echo0("Copied subgame to " + MT_MYGAME_DIR)
else: else:
print("FAILED to copy subgame to " + MT_MYGAME_DIR) echo0('FAILED to copy subgame to "{}" ("{}" is missing)'
input("press enter to close...") ''.format(MT_MYGAME_DIR, good_dir))
exit(7) return 7
MT_MYGAME_MODS_PATH = os.path.join(MT_MYGAME_DIR, "mods") MT_MYGAME_MODS_PATH = os.path.join(MT_MYGAME_DIR, "mods")
MTMOD_DEST_NAME = "minigamer" MTMOD_DEST_NAME = "minigamer"
MTMOD_DEST_PATH = os.path.join(MT_MYGAME_MODS_PATH, MTMOD_DEST_NAME) MTMOD_DEST_PATH = os.path.join(MT_MYGAME_MODS_PATH, MTMOD_DEST_NAME)
# if force_update_mtg_mods_enable: # if force_update_mtg_mods_enable:
# for sub_name in os.listdir(folder_path): # for sub_name in os.listdir(base_game_path):
# sub_path = os.path.join(folder_path, sub_name) # sub_path = os.path.join(base_game_path, sub_name)
# dst_path = os.path.join(MT_MYGAME_DIR, sub_name) # dst_path = os.path.join(MT_MYGAME_DIR, sub_name)
# if sub_name[:1]!="." and os.path.isdir(sub_path): # if sub_name[:1]!="." and os.path.isdir(sub_path):
# if os.path.isdir(dst_path): # if os.path.isdir(dst_path):
# shutil.rmtree(dst_path) # shutil.rmtree(dst_path)
if not os.path.isdir(GIT_REPOS_PATH): if not os.path.isdir(GIT_REPOS_PATH):
print("Cannot create " + GIT_REPOS_PATH + " so cannot continue.") echo0("Cannot create " + GIT_REPOS_PATH + " so cannot continue.")
input("press enter to close...") return 8
exit(8)
# TODO: actually install something (from spreadsheet maybe) # TODO: actually install something (from spreadsheet maybe)
mtg_mods_list = list() mtg_mods_list = list()
folder_path = MTG_MODS_PATH src_mods_path = MTG_MODS_PATH
if os.path.isdir(folder_path): if os.path.isdir(src_mods_path):
for sub_name in os.listdir(folder_path): for sub_name in os.listdir(src_mods_path):
sub_path = os.path.join(folder_path, sub_name) sub_path = os.path.join(src_mods_path, sub_name)
if sub_name[:1] != "." and os.path.isdir(sub_path): if sub_name[:1] != "." and os.path.isdir(sub_path):
mtg_mods_list.append(sub_name) mtg_mods_list.append(sub_name)
mods_installed_list = list() mods_installed_list = list()
mods_added_list = list() mods_added_list = list()
folder_path = MT_MYGAME_MODS_PATH dst_mods_path = MT_MYGAME_MODS_PATH
if os.path.isdir(folder_path): if os.path.isdir(dst_mods_path):
for sub_name in os.listdir(folder_path): for sub_name in os.listdir(dst_mods_path):
sub_path = os.path.join(folder_path, sub_name) sub_path = os.path.join(dst_mods_path, sub_name)
if sub_name[:1] != "." and os.path.isdir(sub_path): if sub_name[:1] != "." and os.path.isdir(sub_path):
mods_installed_list.append(sub_name) mods_installed_list.append(sub_name)
if sub_name not in mtg_mods_list: if sub_name not in mtg_mods_list:
mods_added_list.append(sub_name) mods_added_list.append(sub_name)
else: else:
print("Missing '" + folder_path + "'") echo0("Missing '" + dst_mods_path + "'")
print("") echo0("")
print("") echo0("")
print("Installed " + str(len(mods_installed_list)) + " mod(s)" + echo0("Installed " + str(len(mods_installed_list)) + " mod(s)" +
" (" + str(len(mtg_mods_list)) + " from " + mtg_game_name + ").") " (" + str(len(mtg_mods_list)) + " from " + mtg_game_name + ").")
if len(mods_added_list) > 0: if len(mods_added_list) > 0:
print("Added:") print("Added:")
for mod_name in mods_added_list: for mod_name in mods_added_list:
print(" - " + mod_name) print(" - " + mod_name)
print("") echo0("")
input("press enter to close...")
# cd $TMP_DIR # cd $TMP_DIR
# git clone https://github.com/tenplus1/mobs_redo.git # git clone https://github.com/tenplus1/mobs_redo.git
# git clone https://github.com/tenplus1/mobs_animal.git # git clone https://github.com/tenplus1/mobs_animal.git
@ -220,3 +233,11 @@ input("press enter to close...")
# git clone https://github.com/poikilos/birthstones.git # git clone https://github.com/poikilos/birthstones.git
# Repo.clone_from(git_url, repo_dir) # Repo.clone_from(git_url, repo_dir)
return 0
if __name__ == "__main__":
code = main()
# if code != 0:
# input("press enter to close...")
sys.exit(code)

31
install.py

@ -11,9 +11,10 @@ if platform.system() == "Windows":
else: else:
profile = os.environ.get('HOME') profile = os.environ.get('HOME')
def error(msg):
sys.stderr.write("{}\n".format(msg)) def echo0(*args, **kwargs):
sys.stderr.flush() print(*args, file=sys.stderr, **kwargs)
try: try:
import mtanalyze import mtanalyze
@ -23,12 +24,20 @@ except ModuleNotFoundError as ex:
sys.path.append(tryMTA) sys.path.append(tryMTA)
import mtanalyze import mtanalyze
else: else:
error("") echo0("")
error("You must install mtanalyze in the directory alongside") echo0("You must install mtanalyze in the directory alongside")
error("EnlivenMinetest or as ~/git/mtanalize") echo0("EnlivenMinetest or as ~/git/mtanalize")
error("such as via:") echo0("such as via:")
error("git clone https://github.com/poikilos/mtanalyze ~/git/mtanalize") echo0("git clone https://github.com/poikilos/mtanalyze ~/git/mtanalize")
error("") echo0("")
# raise tryMTA # raise tryMTA
exit(1) sys.exit(1)
print("This doesn't work (not yet implemented). See build.py.")
def main():
echo0("This doesn't work (not yet implemented). See build.py.")
return 1
if __name__ == "__main__":
sys.exit(main())

144
mtsenliven.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
from __future__ import print_function from __future__ import print_function
# runs minetestserver using the paths defined by minetestinfo # runs minetestserver using the paths defined by minetestinfo
@ -7,7 +7,7 @@ from __future__ import print_function
# dr4Ke on # dr4Ke on
# https://forum.minetest.net/viewtopic.php?f=11&t=13138&start=50 # https://forum.minetest.net/viewtopic.php?f=11&t=13138&start=50
import os import os
from mtanalyze.minetestinfo import * import sys
import subprocess import subprocess
import signal import signal
try: try:
@ -20,55 +20,26 @@ try:
except ImportError: except ImportError:
from queue import Queue # Python 3 from queue import Queue # Python 3
key_exit_msg = "SIGINT should shut down server safely...\n" REPO_PATH = os.path.dirname(os.path.realpath(__file__))
game_id = "ENLIVEN" # ^ realpath follows symlinks
# screen -S MinetestServer $mts --gameid ENLIVEN --worldname ... REPOS_PATH = os.path.dirname(REPO_PATH)
print() TRY_REPO_PATH = os.path.join(REPOS_PATH, "mtanalyze")
print() if os.path.isfile(os.path.join(TRY_REPO_PATH, "mtanalyze", "__init__.py")):
print() # ^ Yes, it is 2 mtanalyze deep,
# such as "$HOME/git/mtanalyze/mtanalyze/__init__.py"
if not minetestinfo.contains("minetestserver_path"): sys.path.insert(0, TRY_REPO_PATH)
print("[ mtsenliven.py ] ERROR: minetestserver_path"
" was not found in your version of minetestinfo.py") from pyenliven import (
exit(1) echo0,
echo1,
mts = minetestinfo.get_var("minetestserver_path") )
if not minetestinfo.contains("primary_world_path"):
print("[ mtsenliven.py ] ERROR: primary_world_path"
"was selected by minetestinfo.py") # from mtanalyze.minetestinfo import *
exit(2) from mtanalyze import (
wp = minetestinfo.get_var("primary_world_path") mti,
wn = os.path.basename(wp) get_var_and_check,
print("Using minetestserver: " + mts)
print("Using primary_world_path: " + wp)
print("Using world_name: " + wn)
print()
process = None
try:
# get both stdout and stderr (see
# https://www.saltycrane.com/blog/2008/09/how-get-stdout-and-
# stderr-using-python-subprocess-module/)
process = subprocess.Popen(
[mts, '--gameid', game_id, '--worldname', wn],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=1
) )
# bufsize=1 as per jfs on <https://stackoverflow.com/questions/
# 31833897/python-read-from-subprocess-stdout-and-stderr-
# separately-while-preserving-order>
except Exception as e:
print(mts + " could not be executed. Try installing the "
" minetest-server package or compiling from git instructions"
" on minetest.net")
print(e)
exit(1)
msgprefix_flags = ["WARNING[Server]: ", "ACTION[Server]: "]
msgprefix_lists = {} # where flag is key
for flag in msgprefix_flags:
msgprefix_lists[flag] = []
# see https://www.endpoint.com/blog/2015/01/28/getting-realtime-output-
# using-python
non_unique_wraps = [] non_unique_wraps = []
non_unique_wraps.append( non_unique_wraps.append(
@ -83,6 +54,11 @@ unique_flags = [
"joins game" "joins game"
] ]
msgprefix_flags = ["WARNING[Server]: ", "ACTION[Server]: "]
msgprefix_lists = {} # where flag is key
for flag in msgprefix_flags:
msgprefix_lists[flag] = []
def print_unique_only(output, err_flag=False): def print_unique_only(output, err_flag=False):
output_strip = output.strip() output_strip = output.strip()
@ -124,7 +100,7 @@ def print_unique_only(output, err_flag=False):
if show_enable: if show_enable:
print(output_strip) print(output_strip)
if found_flag is not None: if found_flag is not None:
print(" [ mtsenliven.py ] " + msg_msg echo0(" [ mtsenliven.py ] " + msg_msg
+ " will be suppressed") + " will be suppressed")
@ -158,7 +134,7 @@ def reader(pipe, q):
finally: finally:
q.put(None) q.put(None)
except KeyboardInterrupt: except KeyboardInterrupt:
print("[ mtsenliven.py ] " + key_exit_msg) echo0("[ mtsenliven.py ] " + key_exit_msg)
pass pass
@ -167,9 +143,59 @@ def decode_safe(b):
s = b.decode() s = b.decode()
except UnicodeDecodeError: except UnicodeDecodeError:
s = b.decode('utf-8') s = b.decode('utf-8')
'''
except AttributeError as ex:
if "'str' object has no attribute" in str(ex):
return b
raise ex
'''
return s return s
def main():
key_exit_msg = "SIGINT should shut down server safely...\n"
game_id = "ENLIVEN"
# screen -S MinetestServer $mts --gameid ENLIVEN --worldname ...
echo0()
echo0()
echo0()
mts, code = get_var_and_check("minetestserver_path", code=1)
if code != 0:
return code
wp, code = get_var_and_check("primary_world_path", code=1)
if code != 0:
return code
wn = os.path.basename(wp)
echo0("Using minetestserver: " + mts)
echo0("Using primary_world_path: " + wp)
echo0("Using world_name: " + wn)
echo0()
process = None
try:
# get both stdout and stderr (see
# https://www.saltycrane.com/blog/2008/09/how-get-stdout-and-
# stderr-using-python-subprocess-module/)
process = subprocess.Popen(
[mts, '--gameid', game_id, '--worldname', wn],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=1
)
# bufsize=1 as per jfs on <https://stackoverflow.com/questions/
# 31833897/python-read-from-subprocess-stdout-and-stderr-
# separately-while-preserving-order>
except Exception as e:
echo0(mts + " could not be executed. Try installing the "
" minetest-server package or compiling from git instructions"
" on minetest.net")
echo0(e)
return 2
# see https://www.endpoint.com/blog/2015/01/28/getting-realtime-output-
# using-python
q = Queue() q = Queue()
Thread(target=reader, args=[process.stdout, q]).start() Thread(target=reader, args=[process.stdout, q]).start()
Thread(target=reader, args=[process.stderr, q]).start() Thread(target=reader, args=[process.stderr, q]).start()
@ -181,14 +207,14 @@ try:
l_s = line l_s = line
# NOTE: source is a string such as # NOTE: source is a string such as
# "<_io.BufferedReader name=5>" # "<_io.BufferedReader name=5>"
l_s = decode_safe("utf-8") l_s = decode_safe(line) # line.decode("utf-8")
process_msg("%s: %s" % (s, l_s)) process_msg("%s: %s" % (s, l_s))
except KeyboardInterrupt: except KeyboardInterrupt:
print("[ mtsenliven.py ] " + key_exit_msg) print("[ mtsenliven.py ] " + key_exit_msg)
pass pass
exit(0) return 0
'''
while True: while True:
try: try:
# can deadlock on high volume--use communicate instead # can deadlock on high volume--use communicate instead
@ -205,6 +231,12 @@ while True:
# process_msg(err_bytes) # process_msg(err_bytes)
rc = process.poll() rc = process.poll()
except KeyboardInterrupt: except KeyboardInterrupt:
print("[ mtsenliven.py ] " + key_exit_msg) echo0("[ mtsenliven.py ] " + key_exit_msg)
break break
# process.kill() # process.kill()
return 0
'''
if __name__ == "__main__":
sys.exit(main())

11
notes/continuify.py

@ -9,6 +9,7 @@ comparison purposes and link.txt files).
import sys import sys
import os import os
def continuify(inPath, outPath, continueStr=" \\", indent=" ", def continuify(inPath, outPath, continueStr=" \\", indent=" ",
sep=" "): sep=" "):
with open(outPath, 'w') as outs: with open(outPath, 'w') as outs:
@ -28,21 +29,23 @@ def continuify(inPath, outPath, continueStr=" \\", indent=" ",
if i >= 0: if i >= 0:
starter = indent starter = indent
def main(): def main():
if len(sys.argv) < 2: if len(sys.argv) < 2:
print("You must specify file(s).") print("You must specify file(s).")
exit(1) return 1
for i in range(1, len(sys.argv)): for i in range(1, len(sys.argv)):
arg = sys.argv[i] arg = sys.argv[i]
if not os.path.isfile(arg): if not os.path.isfile(arg):
print("ERROR: {} is not a file.".format(arg)) print("ERROR: {} is not a file.".format(arg))
exit(1) return 2
# parts = os.path.splitext(arg) # parts = os.path.splitext(arg)
# outPath = parts[0] + ".tmp" + parts[1] # outPath = parts[0] + ".tmp" + parts[1]
outPath = arg + ".continuified.tmp" outPath = arg + ".continuified.tmp"
continuify(arg, outPath) continuify(arg, outPath)
print("* wrote \"{}\"".format(outPath)) print("* wrote \"{}\"".format(outPath))
pass return 0
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

103
pyenliven/__init__.py

@ -0,0 +1,103 @@
#!/usr/bin/env python
'''
This module assists with building games from other games, mods, and
patches.
'''
from __future__ import print_function
import sys
import platform
import os
profile = None
if platform.system() == "Windows":
profile = os.environ.get('USERPROFILE')
else:
profile = os.environ.get('HOME')
verbosity = 0
max_verbosity = 2
def echo0(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def echo1(*args, **kwargs):
if verbosity < 1:
return False
print(*args, file=sys.stderr, **kwargs)
return True
def echo2(*args, **kwargs):
if verbosity < 2:
return False
print(*args, file=sys.stderr, **kwargs)
return True
def get_verbosity():
return verbosity
def set_verbosity(level):
if level is True:
verbosity = 1
elif level is False:
verbosity = 0
elif level in range(max_verbosity+1):
verbosity = level
raise ValueError(
"verbosity must be {} at maximum.".format(max_verbosity)
)
try:
import mtanalyze
except ModuleNotFoundError as ex:
# tryMTA = os.path.join(profile, "git", "mtanalyze")
moduleDir = os.path.dirname(os.path.realpath(__file__))
REPO_DIR = os.path.dirname(moduleDir)
modulesDir = os.path.dirname(REPO_DIR)
echo0("* looking for mtanalyze in modulesDir \"{}\""
"".format(modulesDir))
tryMTA = os.path.abspath(os.path.join(modulesDir, "mtanalyze"))
if os.path.isdir(tryMTA):
sys.path.append(tryMTA)
import mtanalyze
# ^ import mtanalyze/mtanalyze purposely since the main
# mtanalyze/ directory is a setuptools package not a module.
else:
echo0("")
echo0("You must install mtanalyze alongside")
echo0("EnlivenMinetest such that ../mtanalize/mtanalize exists")
echo0("such as via:")
echo0(" git clone https://github.com/poikilos/mtanalyze {}"
"".format(tryMTA))
echo0("")
# raise tryMTA
exit(1)
# from mtanalyze import profile_path
MY_MODULE_DIR = os.path.dirname(os.path.realpath(__file__))
# ^ realpath follows symlinks
REPO_DIR = os.path.dirname(MY_MODULE_DIR)
MODS_STOPGAP_DIR = os.path.join(REPO_DIR, "patches", "mods-stopgap")
if not os.path.isdir(MODS_STOPGAP_DIR):
echo0("Error: \"{}\" is missing.".format(MODS_STOPGAP_DIR))
exit(1)
BASE_DIR = os.path.join(REPO_DIR, "Bucket_Game-base")
if not os.path.isdir(BASE_DIR):
echo0("Error: \"{}\" is missing.".format(BASE_DIR))
exit(1)
BRANCHES_DIR = os.path.join(REPO_DIR, "Bucket_Game-branches")
if not os.path.isdir(BRANCHES_DIR):
echo0("Error: \"{}\" is missing.".format(BRANCHES_DIR))
exit(1)
# NOTE: get a git repo's origin via: git remote show origin
def getSGPath(stopgap_mod_name):
return os.path.join(MODS_STOPGAP_DIR, stopgap_mod_name)

30
pyenliven/compatiblizemod.py

@ -4,9 +4,10 @@ import sys
import os import os
import shutil import shutil
def error(msg):
sys.stderr.write("{}\n".format(msg)) def echo0(*args, **kwargs):
sys.stderr.flush() print(*args, file=sys.stderr, **kwargs)
def add_depends(mod_path): def add_depends(mod_path):
mod_dir_name = os.path.basename(mod_path) mod_dir_name = os.path.basename(mod_path)
@ -41,10 +42,10 @@ def add_depends(mod_path):
print("* created {}/modpack.txt" print("* created {}/modpack.txt"
"".format(mod_dir_name)) "".format(mod_dir_name))
else: else:
error("{}/modpack.txt already exists for compatibility." echo0("{}/modpack.txt already exists for compatibility."
"".format(mod_dir_name)) "".format(mod_dir_name))
if os.path.isfile(modpack_txt): if os.path.isfile(modpack_txt):
error("{}/{} indicates it is a modpack." echo0("{}/{} indicates it is a modpack."
"".format(mod_dir_name, found_modpack_file)) "".format(mod_dir_name, found_modpack_file))
for sub in os.listdir(mod_path): for sub in os.listdir(mod_path):
if sub.startswith('.'): if sub.startswith('.'):
@ -52,19 +53,19 @@ def add_depends(mod_path):
subPath = os.path.join(mod_path, sub) subPath = os.path.join(mod_path, sub)
add_depends(subPath) add_depends(subPath)
# It must be a modpack, so return after doing subdirectories. # It must be a modpack, so return after doing subdirectories.
return return 1
depends_path = os.path.join(mod_path, "depends.txt") depends_path = os.path.join(mod_path, "depends.txt")
description_path = os.path.join(mod_path, "description.txt") description_path = os.path.join(mod_path, "description.txt")
if os.path.isfile(depends_path): if os.path.isfile(depends_path):
error("WARNING: Writing {} will be skipped since it exists." echo0("WARNING: Writing {} will be skipped since it exists."
"".format(depends_path)) "".format(depends_path))
return return 0
mod_conf = os.path.join(mod_path, "mod.conf") mod_conf = os.path.join(mod_path, "mod.conf")
if not os.path.isfile(mod_conf): if not os.path.isfile(mod_conf):
error("WARNING: Writing {} will be skipped since {} does" echo0("WARNING: Writing {} will be skipped since {} does"
" not exist." " not exist."
"".format(depends_path, mod_conf)) "".format(depends_path, mod_conf))
return return 1
optional_depends = None optional_depends = None
depends = None depends = None
description = None description = None
@ -117,14 +118,17 @@ def add_depends(mod_path):
if os.path.isfile(description_path): if os.path.isfile(description_path):
print("* INFO: There is already a description.txt so it" print("* INFO: There is already a description.txt so it"
" will be left intact.") " will be left intact.")
return return 0
with open(description_path, 'w') as outs: with open(description_path, 'w') as outs:
outs.write("{}\n".format(description)) outs.write("{}\n".format(description))
print("* wrote {}/description.txt".format(mod_dir_name)) print("* wrote {}/description.txt".format(mod_dir_name))
return 0
def main(): def main():
parent = os.path.realpath(".") parent = os.path.realpath(".")
add_depends(parent) return add_depends(parent)
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

3
pyenliven/deprecated.py

@ -1,4 +1,4 @@
#!/usr/bin/env #!/usr/bin/env python3
class Repo: class Repo:
''' '''
WARNING: The real Repo class is in enliven.py WARNING: The real Repo class is in enliven.py
@ -6,6 +6,7 @@ class Repo:
print(__doc__) print(__doc__)
pass pass
class GiteaRepo(Repo): class GiteaRepo(Repo):
''' '''
This class is deprecated since the "options" sequential argument This class is deprecated since the "options" sequential argument

77
setup.py

@ -0,0 +1,77 @@
#!/usr/bin/env python
import setuptools
import sys
import os
# - For the example on which this was based, see
# https://github.com/poikilos/linux-preinstall/blob/main/setup.py
# which is based on
# https://github.com/poikilos/world_clock/blob/main/setup.py
# which is based on
# https://github.com/poikilos/nopackage/blob/main/setup.py
# which is based on
# https://github.com/poikilos/pypicolcd/blob/master/setup.py
# - For nose, see https://github.com/poikilos/mgep/blob/master/setup.py
# python_mr = sys.version_info.major
# versionedModule = {}
# versionedModule['urllib'] = 'urllib'
# if python_mr == 2:
# versionedModule['urllib'] = 'urllib2'
install_requires = []
if os.path.isfile("requirements.txt"):
with open("requirements.txt", "r") as ins:
for rawL in ins:
line = rawL.strip()
if len(line) < 1:
continue
install_requires.append(line)
description = '''Manage Minetest using Python.'''
long_description = description
if os.path.isfile("readme.md"):
with open("readme.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name='pyenliven',
version='0.3.0',
description=description,
long_description=long_description,
long_description_content_type="text/markdown",
classifiers=[
'Development Status :: 3 - Alpha',
'Programming Language :: Python :: 3',
('License :: OSI Approved ::'
' GNU General Public License v2 or later (GPLv2+)'),
'Operating System :: POSIX :: Linux',
'Topic :: Software Development :: Version Control',
],
keywords=('minetest repo management commit data analyzer'
' meld merge compare files diff'),
url="https://github.com/poikilos/EnlivenMinetest",
author="Jake Gustafson",
author_email='7557867+poikilos@users.noreply.github.com',
license='GPLv2.1',
# packages=setuptools.find_packages(),
packages=['pyenliven'],
# include_package_data=True, # look for MANIFEST.in
# scripts=['example'] ,
# See <https://stackoverflow.com/questions/27784271/
# how-can-i-use-setuptools-to-generate-a-console-scripts-entry-
# point-which-calls>
entry_points={
'console_scripts': [
'compatiblizemod=pyenliven.compatiblizemod:main',
],
},
install_requires=install_requires,
# versionedModule['urllib'],
# ^ "ERROR: Could not find a version that satisfies the requirement
# urllib (from nopackage) (from versions: none)
# ERROR: No matching distribution found for urllib"
test_suite='nose.collector',
tests_require=['nose', 'nose-cover3'],
zip_safe=False, # It can't run zipped due to needing data files.
)

17
uninstall-minetestserver-git.py

@ -1,6 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys
import platform import platform
def main():
CMD_REM = "#" CMD_REM = "#"
CMD_RM = "rm " CMD_RM = "rm "
CMD_RMDIR = "rmdir " CMD_RMDIR = "rmdir "
@ -22,7 +25,7 @@ if platform.system() == "Windows":
# print("ERROR: Nothing done since there is no minetest sourcecode" # print("ERROR: Nothing done since there is no minetest sourcecode"
# " folder in " + downloads_path # " folder in " + downloads_path
# + " (nor " + profile_path + ")") # + " (nor " + profile_path + ")")
# exit(1) # return 1
install_manifest_name = "install_manifest.txt" install_manifest_name = "install_manifest.txt"
# install_manifest_path = os.path.join(repo_path, install_manifest_name) # install_manifest_path = os.path.join(repo_path, install_manifest_name)
# if not os.path.isfile(install_manifest_path): # if not os.path.isfile(install_manifest_path):
@ -31,14 +34,14 @@ install_manifest_name = "install_manifest.txt"
# "'. The file would only be present if you " + # "'. The file would only be present if you " +
# "installed minetest from sourcecode" + # "installed minetest from sourcecode" +
# "(otherwise this uninstaller is not for you).") # "(otherwise this uninstaller is not for you).")
# exit(2) # return 2
if not os.path.isfile(install_manifest_name): if not os.path.isfile(install_manifest_name):
print("ERROR: nothing done since there is no " + print("ERROR: nothing done since there is no " +
install_manifest_name + " in the current " + install_manifest_name + " in the current " +
"directory. You must run: ") "directory. You must run: ")
print(" sudo python3 "+os.path.abspath(__file__)) print(" sudo python3 "+os.path.abspath(__file__))
print("from the minetest sourcecode (repo) directory.") print("from the minetest sourcecode (repo) directory.")
exit(2) return 2
directories = [] directories = []
print("Removing files...") print("Removing files...")
f_removed_count = 0 f_removed_count = 0
@ -156,6 +159,7 @@ print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
" present:" + " present:" +
str(d_skipped_count) + "; failed:" + str(d_failed_count) + ")") str(d_skipped_count) + "; failed:" + str(d_failed_count) + ")")
code = 0
if f_failed_count+d_failed_count+ed_failed_count <= 0: if f_failed_count+d_failed_count+ed_failed_count <= 0:
print("") print("")
if f_removed_count+d_removed_count <= 0: if f_removed_count+d_removed_count <= 0:
@ -177,7 +181,14 @@ else:
"If any more remain, you may have to remove them manually.") "If any more remain, you may have to remove them manually.")
print("") print("")
print("") print("")
code = 1
if not ins.closed: if not ins.closed:
print("ERROR: ins was not closed (this should never happen)--" print("ERROR: ins was not closed (this should never happen)--"
"closing manually...") "closing manually...")
ins.close() ins.close()
code = 1
return code
if __name__ == "__main__":
sys.exit(main())

8
utilities/compatiblizemod.py

@ -8,13 +8,13 @@ import re
import sys import sys
import os import os
myDir = os.path.dirname(os.path.realpath(__file__)) UTILITIES_DIR = os.path.dirname(os.path.realpath(__file__))
repoDir = os.path.dirname(myDir) REPO_DIR = os.path.dirname(UTILITIES_DIR)
# try: # try:
# from pyenliven.compatiblizemod import main # from pyenliven.compatiblizemod import main
# except ModuleNotFoundError: # except ModuleNotFoundError:
if os.path.isdir(os.path.join(repoDir, "pyenliven")): if os.path.isfile(os.path.join(REPO_DIR, "pyenliven", "__init__.py")):
sys.path.append(repoDir) sys.path.append(REPO_DIR)
from pyenliven.compatiblizemod import main from pyenliven.compatiblizemod import main

97
utilities/enissue.py

@ -93,7 +93,7 @@ except ImportError:
# see <https://stackoverflow.com/questions/5574702/how-to-print-to-stderr-in-python> # see <https://stackoverflow.com/questions/5574702/how-to-print-to-stderr-in-python>
def error(*args, **kwargs): def echo0(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs) print(*args, file=sys.stderr, **kwargs)
@ -261,7 +261,7 @@ def debug(*args, **kwargs):
if verbose: if verbose:
if len(args) > 0: if len(args) > 0:
msg = args[0] msg = args[0]
error("[debug] " + msg) echo0("[debug] " + msg)
def set_verbose(on): def set_verbose(on):
@ -353,6 +353,8 @@ match_all_labels = []
trues = ["true", "on", "yes"] trues = ["true", "on", "yes"]
falses = ["false", "off", "no"] falses = ["false", "off", "no"]
# TODO: Consider from pycodetool import to_syntax_error
# (to replace instances of {}:{}: formatted by `path, line` below).
def str_to_value(valueStr, typeName=None, lineN=-1, path="(generated)"): def str_to_value(valueStr, typeName=None, lineN=-1, path="(generated)"):
''' '''
@ -387,7 +389,7 @@ def str_to_value(valueStr, typeName=None, lineN=-1, path="(generated)"):
if typeName is not None: if typeName is not None:
if valueStr == "None": if valueStr == "None":
error("{}:{}: WARNING: The program expected a(n) '{}' but" echo0("{}:{}: WARNING: The program expected a(n) '{}' but"
" the value was 'None' and will become" " the value was 'None' and will become"
" None." " None."
"".format(conf_path, lineN, typeName)) "".format(conf_path, lineN, typeName))
@ -490,7 +492,7 @@ def modify_dict_by_conf(options, conf_path, always_lower=False,
continue continue
signI = line.find("=") signI = line.find("=")
if signI < 1: if signI < 1:
error("{}:{}: A value is expected before '='." echo0("{}:{}: A value is expected before '='."
"".format(conf_path, lineN)) "".format(conf_path, lineN))
name = line[:signI].strip() name = line[:signI].strip()
valueStr = line[signI+1:].strip() valueStr = line[signI+1:].strip()
@ -499,11 +501,11 @@ def modify_dict_by_conf(options, conf_path, always_lower=False,
value = None value = None
if always_lower: if always_lower:
if name.lower() != name: if name.lower() != name:
error("{}:{}: A lowercase name is expected." echo0("{}:{}: A lowercase name is expected."
"".format(conf_path, lineN)) "".format(conf_path, lineN))
continue continue
if (valueStr is None) and no_value_error: if (valueStr is None) and no_value_error:
error("{}:{}: A value is expected." echo0("{}:{}: A value is expected."
"".format(conf_path, lineN)) "".format(conf_path, lineN))
else: else:
typeName = None typeName = None
@ -514,11 +516,11 @@ def modify_dict_by_conf(options, conf_path, always_lower=False,
path=conf_path, lineN=lineN) path=conf_path, lineN=lineN)
options[name] = value options[name] = value
if not quiet: if not quiet:
error("[settings] {}: Set {} to {}" echo0("[settings] {}: Set {} to {}"
"".format(conf_name, name, value)) "".format(conf_name, name, value))
else: else:
if no_file_error: if no_file_error:
error("Error: \"{}\" Doesn't exist" echo0("Error: \"{}\" Doesn't exist"
"".format(conf_path, lineN)) "".format(conf_path, lineN))
@ -664,7 +666,7 @@ class Repo:
self.remote_user = "almikes@aol.com" # Wuzzy2 self.remote_user = "almikes@aol.com" # Wuzzy2
if self.api_id is not None: if self.api_id is not None:
if self.api_id != 'git_instaweb': if self.api_id != 'git_instaweb':
error("WARNING: URL has [] but self.api_id was {}" echo0("WARNING: URL has [] but self.api_id was {}"
"".format(urlParts[-2], self.api_id)) "".format(urlParts[-2], self.api_id))
self.api_id = "git_instaweb" self.api_id = "git_instaweb"
# Such as https://repo.or.cz/minetest_treasurer.git # Such as https://repo.or.cz/minetest_treasurer.git
@ -701,8 +703,8 @@ class Repo:
if self.api_id is None: if self.api_id is None:
self.api_id = "Gitea" self.api_id = "Gitea"
if "github.com" in repo_url.lower(): if "github.com" in repo_url.lower():
error("WARNING: assuming Gitea but URL has github.com.") echo0("WARNING: assuming Gitea but URL has github.com.")
error(" * assuming API is {} for {}" echo0(" * assuming API is {} for {}"
"".format(self.api_id, )) "".format(self.api_id, ))
if self.api_id is None: if self.api_id is None:
raise RuntimeError("api_id is not set") raise RuntimeError("api_id is not set")
@ -1113,7 +1115,7 @@ class Repo:
results = result results = result
err = to_error(result) err = to_error(result)
if err is not None: if err is not None:
error("WARNING: a website error was saved" echo0("WARNING: a website error was saved"
" as an issue, so it will be deleted:" " as an issue, so it will be deleted:"
" \"{}\"" " \"{}\""
"".format(c_path)) "".format(c_path))
@ -1126,7 +1128,7 @@ class Repo:
"".format(results_key)) "".format(results_key))
results = results[results_key] results = results[results_key]
else: else:
error("WARNING: expected {} in dict" echo0("WARNING: expected {} in dict"
"".format(results_key)) "".format(results_key))
if result is not None: if result is not None:
if hasattr(results, 'keys'): if hasattr(results, 'keys'):
@ -1461,9 +1463,9 @@ class Repo:
fn += ".json" fn += ".json"
c_path += ".json" c_path += ".json"
else: else:
error("url: {}".format(url)) echo0("url: {}".format(url))
error("self.labels_url: {}".format(self.labels_url)) echo0("self.labels_url: {}".format(self.labels_url))
error("self.issues_url: {}".format(self.issues_url)) echo0("self.issues_url: {}".format(self.issues_url))
raise NotImplementedError("getCachedJsonDict" raise NotImplementedError("getCachedJsonDict"
" doesn't have a cache directory" " doesn't have a cache directory"
" for {}. Try --refresh" " for {}. Try --refresh"
@ -1494,8 +1496,8 @@ class Repo:
try: try:
result = json.load(json_file) result = json.load(json_file)
except json.decoder.JSONDecodeError as ex: except json.decoder.JSONDecodeError as ex:
error("") echo0("")
error(p+"The file {} isn't valid JSON" echo0(p+"The file {} isn't valid JSON"
" and will be overwritten if loads" " and will be overwritten if loads"
"".format(c_path)) "".format(c_path))
result = None result = None
@ -1505,7 +1507,7 @@ class Repo:
err = to_error(result) err = to_error(result)
if err is not None: if err is not None:
result = None result = None
error("Error: An error was saved as an issue" echo0("Error: An error was saved as an issue"
" so it will be deleted: {}" " so it will be deleted: {}"
"".format(c_path)) "".format(c_path))
os.remove(c_path) os.remove(c_path)
@ -1691,8 +1693,8 @@ class Repo:
msg = ("WARNING: comments={} but there is no" msg = ("WARNING: comments={} but there is no"
" comments_url in:" " comments_url in:"
"".format(comments)) "".format(comments))
# error(msg) # echo0(msg)
# error(json.dumps(issue_data, indent=4, sort_keys=True)) # echo0(json.dumps(issue_data, indent=4, sort_keys=True))
for evt in data: for evt in data:
user = evt.get('user') user = evt.get('user')
@ -1784,7 +1786,7 @@ class Repo:
never_expire=never_expire, never_expire=never_expire,
) )
if err is not None: if err is not None:
error("Accessing the reactions URL failed: {}" echo0("Accessing the reactions URL failed: {}"
"".format(err.get('reason'))) "".format(err.get('reason')))
if reac_data is not None: if reac_data is not None:
for reac in reac_data: for reac in reac_data:
@ -2009,10 +2011,10 @@ class Repo:
if results is None: if results is None:
if err is not None: if err is not None:
if err.get('code') == 410: if err.get('code') == 410:
# error("The issue was deleted") # echo0("The issue was deleted")
pass pass
elif err.get('code') == 404: elif err.get('code') == 404:
# error("The issue doesn't exist") # echo0("The issue doesn't exist")
pass pass
return None, err return None, err
else: else:
@ -2111,10 +2113,10 @@ def main(custom_args=None):
else: else:
if issue_no is not None: if issue_no is not None:
usage() usage()
error("Error: Only one issue number can be" echo0("Error: Only one issue number can be"
" specified but you also specified" " specified but you also specified"
" {}.".format(arg)) " {}.".format(arg))
exit(1) return 1
issue_no = i issue_no = i
is_text = False is_text = False
except ValueError: except ValueError:
@ -2129,15 +2131,15 @@ def main(custom_args=None):
state = 'closed' state = 'closed'
elif arg == "--test": elif arg == "--test":
tests() tests()
error("All tests passed.") echo0("All tests passed.")
sys.exit(0) return 0
elif arg == "--verbose": elif arg == "--verbose":
verbose = True verbose = True
elif arg == "--debug": elif arg == "--debug":
verbose = True verbose = True
elif arg == "--help": elif arg == "--help":
usage() usage()
exit(0) return 0
elif arg in collect_logic: elif arg in collect_logic:
save_key = arg.strip("-").replace("-", "_") save_key = arg.strip("-").replace("-", "_")
elif arg in collect_options: elif arg in collect_options:
@ -2149,9 +2151,9 @@ def main(custom_args=None):
# else: the next arg will be the value. # else: the next arg will be the value.
elif arg.startswith("--"): elif arg.startswith("--"):
usage() usage()
error("Error: The argument \"{}\" is not valid" echo0("Error: The argument \"{}\" is not valid"
"".format(arg)) "".format(arg))
exit(1) return 2
elif prev_arg in SEARCH_COMMANDS: elif prev_arg in SEARCH_COMMANDS:
search_terms.append(arg) search_terms.append(arg)
isValue = True isValue = True
@ -2162,15 +2164,15 @@ def main(custom_args=None):
# print("* adding criteria: {}".format(arg)) # print("* adding criteria: {}".format(arg))
if len(search_terms) < 1: if len(search_terms) < 1:
usage() usage()
error("You can only specify \"AND\" after" echo0("You can only specify \"AND\" after"
" the \"find\" command. To literally" " the \"find\" command. To literally"
" search for the word \"AND\", place" " search for the word \"AND\", place"
" the \"find\" command before it." " the \"find\" command before it."
" Examples:") " Examples:")
for andI in modes['find']['AND_EXAMPLES']: for andI in modes['find']['AND_EXAMPLES']:
error(me echo0(me
+ modes['find']['examples'][andI]) + modes['find']['examples'][andI])
exit(1) return 3
mode = "list" mode = "list"
elif save_key is not None: elif save_key is not None:
logic[save_key] = arg logic[save_key] = arg
@ -2220,7 +2222,7 @@ def main(custom_args=None):
usage() usage()
print() print()
print() print()
sys.exit(0) return 0
elif mode not in valid_modes: elif mode not in valid_modes:
print() print()
print() print()
@ -2229,12 +2231,12 @@ def main(custom_args=None):
print(mode + " is not a valid command.") print(mode + " is not a valid command.")
print() print()
print() print()
sys.exit(0) return 0
elif mode == "list": elif mode == "list":
if issue_no is not None: if issue_no is not None:
print("Error: You must specify either an issue number" print("Error: You must specify either an issue number"
" or query criteria, not both.") " or query criteria, not both.")
sys.exit(1) return 4
print("") print("")
if caches_path is not None: if caches_path is not None:
@ -2287,12 +2289,12 @@ def main(custom_args=None):
db_type = logic.get('db-type') db_type = logic.get('db-type')
if db_type is None: if db_type is None:
db_type = "PostgresQL" db_type = "PostgresQL"
error("WARNING: No db-type was specified, so db-type was" echo0("WARNING: No db-type was specified, so db-type was"
" set to the default: {}".format(db_type)) " set to the default: {}".format(db_type))
db_u = logic.get("db-user") db_u = logic.get("db-user")
if db_u is None: if db_u is None:
db_u = Repo.os_user db_u = Repo.os_user
error("WARNING: No db-type was specified, so db-user was" echo0("WARNING: No db-type was specified, so db-user was"
" set to the default: {}".format(db_u)) " set to the default: {}".format(db_u))
pass pass
db_p = logic.get('db-password') db_p = logic.get('db-password')
@ -2301,7 +2303,7 @@ def main(custom_args=None):
if "deleted" in msg: if "deleted" in msg:
is_deleted = True is_deleted = True
if db_p is None: if db_p is None:
error("WARNING: No db-password was specified, so the db" echo0("WARNING: No db-password was specified, so the db"
" operation will be attempted without it." " operation will be attempted without it."
" Success will depend on your database type and" " Success will depend on your database type and"
" settings.") " settings.")
@ -2309,14 +2311,14 @@ def main(custom_args=None):
'repo_url': dstRepoUrl, 'repo_url': dstRepoUrl,
}) })
# print("* rewriting Gitea issue {}...".format(issue_no)) # print("* rewriting Gitea issue {}...".format(issue_no))
sys.exit(0) # Change based on return of the method. return 5 # TODO: Change based on return of the method.
if msg is not None: if msg is not None:
error(msg) echo0(msg)
if "deleted" in msg: if "deleted" in msg:
sys.exit(0) return 0
else: else:
sys.exit(1) return 6
total_count = 0 total_count = 0
print() print()
# ^ This blank line goes after "@ Cache" messages and before # ^ This blank line goes after "@ Cache" messages and before
@ -2324,11 +2326,11 @@ def main(custom_args=None):
if mode == "labels": if mode == "labels":
if repo.labels is None: if repo.labels is None:
print("There were no labels.") print("There were no labels.")
sys.exit(0) return 0
else: else:
if repo.issues is None: if repo.issues is None:
print("There were no issues.") print("There were no issues.")
sys.exit(0) return 0
match_all_labels_lower = [] match_all_labels_lower = []
p = repo.log_prefix p = repo.log_prefix
@ -2494,7 +2496,8 @@ def main(custom_args=None):
else: else:
debug("There is no summary output due to mode={}".format(mode)) debug("There is no summary output due to mode={}".format(mode))
print("") print("")
return 0
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

39
utilities/enlynx.py

@ -30,31 +30,31 @@ Examples:
''' '''
import sys
import subprocess
me = "enlynx.py" me = "enlynx.py"
browserPath = "lynx" browserPath = "lynx"
sessionPath = "/tmp/enlynx.lynx-session" sessionPath = "/tmp/enlynx.lynx-session"
import sys
import subprocess
enc = {} # URL Encoded single characters enc = {} # URL Encoded single characters
enc[':'] = '%3A' enc[':'] = '%3A'
# ^ Do this with urllib if there are many more # ^ Do this with urllib if there are many more
# see <https://stackoverflow.com/questions/5574702/how-to-print-to-stderr-in-python> verbose = True
def error(*args, **kwargs):
def echo0(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs) print(*args, file=sys.stderr, **kwargs)
verbose = True
def debug(msg): def echo1(*args, **kwargs):
if not verbose: if not verbose:
return return
sys.stderr.write("{}\n".format(msg)) print(*args, file=sys.stderr, **kwargs)
sys.stderr.flush()
def usage(): def usage():
error(__doc__) echo0(__doc__)
def toSubQueryValue(value): def toSubQueryValue(value):
@ -83,7 +83,8 @@ any_q = "?q=" + toSubQuery("is", "issue")
closed_q = "?q=" + toSubQuery("is", "issue") + '+' + toSubQuery("is", "closed") closed_q = "?q=" + toSubQuery("is", "issue") + '+' + toSubQuery("is", "closed")
if __name__ == "__main__": def main():
global browserPath
prev_arg = None prev_arg = None
findStrings = [] findStrings = []
base_q = open_q + "+" base_q = open_q + "+"
@ -115,31 +116,31 @@ if __name__ == "__main__":
elif arg == "AND": elif arg == "AND":
if len(findStrings) == 0: if len(findStrings) == 0:
usage() usage()
error("Error: You can only use AND after find" echo0("Error: You can only use AND after find"
" and after another keyword. To literally" " and after another keyword. To literally"
" search for the word \"AND\" itself," " search for the word \"AND\" itself,"
" say find before the word:\n" " say find before the word:\n"
" {} find CREEPS find AND find WEIRDOS\n" " {} find CREEPS find AND find WEIRDOS\n"
"".format(me)) "".format(me))
exit(1) return 1
prev_arg = arg prev_arg = arg
elif arg == "page": elif arg == "page":
prev_arg = arg prev_arg = arg
else: else:
encArg = toSubQueryValue(arg) encArg = toSubQueryValue(arg)
# if encArg != arg: # if encArg != arg:
# debug("* encoding label as '{}'".format(encArg)) # echo1("* encoding label as '{}'".format(encArg))
# else: # else:
debug("* adding label {}".format(encArg)) echo1("* adding label {}".format(encArg))
labels_subqueries += toSubQuery('label', encArg) + "+" labels_subqueries += toSubQuery('label', encArg) + "+"
# Ensure there aren't any dangling commands *after* the loop: # Ensure there aren't any dangling commands *after* the loop:
if prev_arg is not None: if prev_arg is not None:
usage() usage()
error("Error: You must specify a search term after {}." echo0("Error: You must specify a search term after {}."
"".format(prev_arg)) "".format(prev_arg))
exit(1) return 1
if (_closed is True) and (_open is True): if (_closed is True) and (_open is True):
base_q = any_q + '+' base_q = any_q + '+'
@ -148,8 +149,6 @@ if __name__ == "__main__":
elif _closed is True: elif _closed is True:
base_q = closed_q + '+' base_q = closed_q + '+'
for find_str in findStrings: for find_str in findStrings:
base_q += find_str + "+" base_q += find_str + "+"
# else: (dangling '+' at the end when labels_subqueries=="" is ok) # else: (dangling '+' at the end when labels_subqueries=="" is ok)
@ -159,3 +158,7 @@ if __name__ == "__main__":
print("URL: {}".format(url)) print("URL: {}".format(url))
subprocess.call([browserPath, '-session=' + sessionPath, url]) subprocess.call([browserPath, '-session=' + sessionPath, url])
return 0
if __name__ == "__main__":
sys.exit(main())

29
utilities/extra/uninstall.py

@ -1,16 +1,18 @@
#!/usr/bin/env python #!/usr/bin/env python
import os import os
import sys
import platform import platform
def doDie(msg, error_code=1): def show_error(msg, error_code=1):
print() print()
print(msg) print(msg)
print() print()
print() print()
exit(error_code) return error_code
def main():
rem_cmd = "#" rem_cmd = "#"
rm_cmd = "rm " rm_cmd = "rm "
rmdir_cmd = "rmdir " rmdir_cmd = "rmdir "
@ -28,8 +30,9 @@ if profile_path2 is not None:
+ profile_path + "' is being used.") + profile_path + "' is being used.")
else: else:
if profile_path1 is None: if profile_path1 is None:
doDie(rem_cmd + "ERROR: There is nothing to do since neither" return show_error(rem_cmd + "ERROR: There is nothing to do"
+ " HOME nor USERPROFILE is present.") " since neither"
" HOME nor USERPROFILE is present.")
mnf_name = "install_manifest.txt" mnf_name = "install_manifest.txt"
mnf_path = os.path.join(profile_path, mnf_name) mnf_path = os.path.join(profile_path, mnf_name)
@ -37,8 +40,8 @@ mnf_path = os.path.join(profile_path, mnf_name)
unsorted_list = [] unsorted_list = []
if not os.path.isfile(mnf_path): if not os.path.isfile(mnf_path):
doDie(rem_cmd + "Uninstall cannot continue since '" + mnf_path return show_error(rem_cmd + "Uninstall cannot continue since '"
+ "' is missing.") + mnf_path + "' is missing.")
with open(mnf_path) as fp: with open(mnf_path) as fp:
for cnt, line_original in enumerate(fp): for cnt, line_original in enumerate(fp):
@ -48,8 +51,8 @@ with open(mnf_path) as fp:
unsorted_list.append(line) unsorted_list.append(line)
if len(unsorted_list) < 1: if len(unsorted_list) < 1:
doDie(rem_cmd + "ERROR: There are no files in the manifest '" return show_error(rem_cmd + "ERROR: There are no files in the manifest"
+ mnf_path + "'") " '"+ mnf_path + "'")
# See https://stackoverflow.com/questions/4659524/\ # See https://stackoverflow.com/questions/4659524/\
# how-to-sort-by-length-of-string-followed-by-alphabetical-order # how-to-sort-by-length-of-string-followed-by-alphabetical-order
@ -90,8 +93,9 @@ for path in sorted_list:
if len(does_not_exist) > 0: if len(does_not_exist) > 0:
if len(does_not_exist) == len(sorted_list): if len(does_not_exist) == len(sorted_list):
doDie(" " + rem_cmd + " The program is not installed such as" return show_error(rem_cmd + 'The program is not installed such as'
+ " at '" + sorted_list[-1] + "'.") ' at "{}".'
''.format(sorted_list[-1]))
show_dot_warning = True show_dot_warning = True
print(rem_cmd + "Uninstall is complete.") print(rem_cmd + "Uninstall is complete.")
@ -115,3 +119,8 @@ if (len(not_removed_files) + len(not_removed_dirs)) > 0:
print("") print("")
print("") print("")
return 0
if __name__ == "__main__":
sys.exit(main())

23
utilities/generatemod.py

@ -7,13 +7,13 @@ myPath = os.path.realpath(__file__)
myDir = os.path.dirname(myPath) myDir = os.path.dirname(myPath)
def customExit(msg, code=1): def show_error(msg, code=1):
print("") print("")
print("ERROR:") print("ERROR:")
print(msg) print(msg)
print("") print("")
print("") print("")
exit(code) return code
def usage(): def usage():
@ -44,6 +44,7 @@ def usage():
print("") print("")
def main():
licSrc = "example_license.txt" licSrc = "example_license.txt"
licDestName = "LICENSE.txt" licDestName = "LICENSE.txt"
licDesc = "MIT License" licDesc = "MIT License"
@ -51,7 +52,7 @@ if not os.path.isfile(licSrc):
tryLicSrc = os.path.join(myDir, licSrc) tryLicSrc = os.path.join(myDir, licSrc)
if not os.path.isfile(tryLicSrc): if not os.path.isfile(tryLicSrc):
print("ERROR: missing " + licSrc) print("ERROR: missing " + licSrc)
exit(1) return 1
else: else:
licSrc = tryLicSrc licSrc = tryLicSrc
toMod = None toMod = None
@ -67,11 +68,12 @@ for i in range(1, len(sys.argv)):
else: else:
if (len(sys.argv[i]) >= 2) and (sys.argv[i][:2] == "--"): if (len(sys.argv[i]) >= 2) and (sys.argv[i][:2] == "--"):
usage() usage()
customExit("Invalid option: " + sys.argv[i]) return show_error("Invalid option: " + sys.argv[i],
code=2)
options.append(sys.argv[i]) options.append(sys.argv[i])
if (len(options) != 1) and (len(options) != 3): if (len(options) != 1) and (len(options) != 3):
usage() usage()
exit(1) return 3
thisName = options[0] thisName = options[0]
if os.path.isdir(thisName): if os.path.isdir(thisName):
if not enableFill: if not enableFill:
@ -79,7 +81,7 @@ if os.path.isdir(thisName):
print("ERROR: A mod named " + thisName + " cannot be ") print("ERROR: A mod named " + thisName + " cannot be ")
print("generated when the directory already exists.") print("generated when the directory already exists.")
print("") print("")
exit(1) return 4
else: else:
os.mkdir(thisName) os.mkdir(thisName)
if (len(options) == 3): if (len(options) == 3):
@ -90,8 +92,8 @@ if (len(options) == 3):
toMod = toName[:delimI] toMod = toName[:delimI]
if toMod.find(":") > -1: if toMod.find(":") > -1:
usage() usage()
customExit("Your modname contains too many colons.") return show_error("Your modname contains too many colons.",
exit(1) code=5)
else: else:
toMod = "default" toMod = "default"
@ -196,3 +198,8 @@ print(
) )
print("") print("")
print("") print("")
return 0
if __name__ == "__main__":
sys.exit(main())

13
utilities/mtcompile-program-local.py

@ -39,13 +39,13 @@ import platform
import os import os
def error(msg): def echo0(*args, **kwargs):
sys.stderr.write(msg + "\n") print(*args, file=sys.stderr, **kwargs)
def customExit(msg): def customExit(msg):
error(msg) echo0(msg)
exit(1) sys.exit(1)
def isExecutableFile(path): def isExecutableFile(path):
@ -575,7 +575,7 @@ def main():
# Confirm that script is running in the right place. # Confirm that script is running in the right place.
if not os.path.isdir('mtsrc'): if not os.path.isdir('mtsrc'):
error(""" echo0("""
Error: This script should be stored, and executed, in the directory Error: This script should be stored, and executed, in the directory
which contains the "mtsrc" directory. which contains the "mtsrc" directory.
""") """)
@ -1237,7 +1237,8 @@ again.
print("Done\n") print("Done\n")
# end main # end main
return 0
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

10
utilities/mtoldtonew.py

@ -92,20 +92,28 @@ def oldToNew(path, quotechar='"'):
print("* wrote '%s'" % newName) print("* wrote '%s'" % newName)
if __name__ == "__main__": def main():
for i in range(1, len(sys.argv)): for i in range(1, len(sys.argv)):
try_path = sys.argv[i] try_path = sys.argv[i]
if os.path.isfile(try_path): if os.path.isfile(try_path):
files.append(try_path) files.append(try_path)
else: else:
print("MISSING file: '" + try_path + "'") print("MISSING file: '" + try_path + "'")
return 1
if len(files) < 1: if len(files) < 1:
usage() usage()
print("") print("")
print("You must specify a plain-text schem such as a\n" print("You must specify a plain-text schem such as a\n"
".we file, or any file containing double-quoted node names.") ".we file, or any file containing double-quoted node names.")
return 2
for oldName in files: for oldName in files:
print("Processing %s..." % oldName) print("Processing %s..." % oldName)
oldToNew(oldName) oldToNew(oldName)
return 0
if __name__ == "__main__":
sys.exit(main())

25
utilities/showmissing.py

@ -11,16 +11,6 @@ def usage():
print("") print("")
argCount = len(sys.argv) - 1
if argCount < 2:
usage()
exit(1)
oldPath = sys.argv[1]
newPath = sys.argv[2]
def getStrings(path, delimiter='"', unique=True): def getStrings(path, delimiter='"', unique=True):
ret = [] ret = []
got = "" got = ""
@ -46,8 +36,23 @@ def getStrings(path, delimiter='"', unique=True):
return ret return ret
def main():
argCount = len(sys.argv) - 1
if argCount < 2:
usage()
return 1
oldPath = sys.argv[1]
newPath = sys.argv[2]
olds = getStrings(oldPath) olds = getStrings(oldPath)
news = getStrings(newPath) news = getStrings(newPath)
for v in olds: for v in olds:
if v not in news: if v not in news:
print(v) print(v)
return 0
if __name__ == "__main__":
sys.exit(main())

Loading…
Cancel
Save