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. 43
      buildenliven.py
  6. 177
      deploy.py
  7. 28
      filever.py
  8. 16
      forwardfilesync.py
  9. 34
      generate-mt5-share-fix.py
  10. 44
      headcompare.py
  11. 291
      install-subgametest.py
  12. 31
      install.py
  13. 160
      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. 151
      uninstall-minetestserver-git.py
  20. 8
      utilities/compatiblizemod.py
  21. 97
      utilities/enissue.py
  22. 41
      utilities/enlynx.py
  23. 109
      utilities/extra/uninstall.py
  24. 125
      utilities/generatemod.py
  25. 13
      utilities/mtcompile-program-local.py
  26. 10
      utilities/mtoldtonew.py
  27. 31
      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())

43
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,25 +28,26 @@ 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"},
{'name': "animal_materials_legacy"}, {'name': "animal_materials_legacy"},
{'repo':"https://github.com/minetest-mods/ccompass.git"}, {'repo': "https://github.com/minetest-mods/ccompass.git"},
{'repo':"https://github.com/octacian/chat3.git"}, {'repo': "https://github.com/octacian/chat3.git"},
{'repo':"https://github.com/poikilos/compassgps.git"}, {'repo': "https://github.com/poikilos/compassgps.git"},
{'name': "elk_legacy"}, {'name': "elk_legacy"},
{'repo':"https://github.com/MinetestForFun/fishing.git"}, {'repo': "https://github.com/MinetestForFun/fishing.git"},
{'name': "glooptest_missing"}, {'name': "glooptest_missing"},
{'repo':"https://github.com/minetest-mods/item_drop.git"}, {'repo': "https://github.com/minetest-mods/item_drop.git"},
{'repo':"https://github.com/poikilos/metatools.git"}, {'repo': "https://github.com/poikilos/metatools.git"},
{'name': "nftools_legacy"}, {'name': "nftools_legacy"},
{'name': "glooptest_missing"}, {'name': "glooptest_missing"},
{'repo':"https://github.com/poikilos/slimenodes.git"}, {'repo': "https://github.com/poikilos/slimenodes.git"},
{'repo':"https://github.com/BenjieFiftysix/sponge.git"}, {'repo': "https://github.com/BenjieFiftysix/sponge.git"},
{'repo':"https://github.com/poikilos/throwing.git"}, # Can utilize toolranks, toolranks_extras, wielded_light {'repo': "https://github.com/poikilos/throwing.git"}, # Can utilize toolranks, toolranks_extras, wielded_light
{'repo':"https://github.com/poikilos/throwing_arrows.git"}, # Can utilize mesecons, mesecons_button {'repo': "https://github.com/poikilos/throwing_arrows.git"}, # Can utilize mesecons, mesecons_button
{'repo':"https://github.com/mt-mods/biome_lib.git"}, {'repo': "https://github.com/mt-mods/biome_lib.git"},
{ {
'repo': "https://github.com/Poikilos/vines.git", 'repo': "https://github.com/Poikilos/vines.git",
'branch': "Bucket_Game", # git clone <url> --branch <branch> 'branch': "Bucket_Game", # git clone <url> --branch <branch>
@ -164,14 +166,15 @@ 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())

177
deploy.py

@ -1,141 +1,150 @@
#!/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
warnings = list()
print("") def rm_sub(bad_sub):
print("This script is NOT YET IMPLEMENTED") bad_path = path_join_all(deploy_path, bad_sub)
if os.path.isfile(bad_path):
os.remove(bad_path)
def main():
warnings = list()
echo0("")
echo0("This script is NOT YET IMPLEMENTED")
# TODO: Scrape https://minetest.kitsunemimi.pw/builds/ (NOTE: stable is
# always "https://minetest.kitsunemimi.pw/builds/win64/"
# "minetest-0.4.15-win64.7z")
# TODO: Scrape https://minetest.kitsunemimi.pw/builds/ (NOTE: stable is
# always "https://minetest.kitsunemimi.pw/builds/win64/"
# "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__))
enliven_project_path = os.path.dirname(script_dir_path) enliven_project_path = os.path.dirname(script_dir_path)
profile_path = None profile_path = None
if "HOME" in os.environ: if "HOME" in os.environ:
profile_path = os.environ["HOME"] profile_path = os.environ["HOME"]
elif "USERPROFILE" in os.environ: elif "USERPROFILE" in os.environ:
profile_path = os.environ["USERPROFILE"] profile_path = os.environ["USERPROFILE"]
else: else:
try_path = "C:\\Users\\jgustafson" try_path = "C:\\Users\\jgustafson"
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.
# region user settings # region user settings
deploy_path = "C:\\Games\\ENLIVEN-deploy" deploy_path = "C:\\Games\\ENLIVEN-deploy"
try_path = "C:\\Games\\Minetest" try_path = "C:\\Games\\Minetest"
if (not os.path.isdir(deploy_path)) and os.path.isdir(try_path): if (not os.path.isdir(deploy_path)) and os.path.isdir(try_path):
deploy_path = try_path deploy_path = try_path
installer_deploy_path = path_join_all([profile_path, "ownCloud", "www", installer_deploy_path = path_join_all([profile_path, "ownCloud", "www",
"expertmultimedia", "downloads"]) "expertmultimedia", "downloads"])
installer_name = "install-ENLIVEN.exe" installer_name = "install-ENLIVEN.exe"
# endregion user settings # endregion user settings
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
# if os.path.isfile(installer_path): # if os.path.isfile(installer_path):
# numbers=filever.get_version_number(installer_path) # numbers=filever.get_version_number(installer_path)
# major,minor,subminor,revision = numbers # major,minor,subminor,revision = numbers
# print(".".join([str (i) for i in numbers])) # print(".".join([str (i) for i in numbers]))
if not os.path.isdir(deploy_path): if not os.path.isdir(deploy_path):
os.makedirs(deploy_path) os.makedirs(deploy_path)
games_path = os.path.join(deploy_path, "games") 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")
if not os.path.isdir(mods_path): if not os.path.isdir(mods_path):
os.makedirs(mods_path) os.makedirs(mods_path)
mtg_list_path = os.path.join(game_path, "minetest_game-mod-list.txt") mtg_list_path = os.path.join(game_path, "minetest_game-mod-list.txt")
mtg_list_out = open(mtg_list_path, 'w') mtg_list_out = open(mtg_list_path, 'w')
folder_path = minetest_game_mods_path folder_path = minetest_game_mods_path
if os.path.isdir(folder_path): if os.path.isdir(folder_path):
for sub_name in os.listdir(folder_path): for sub_name in os.listdir(folder_path):
sub_path = os.path.join(folder_path, sub_name) sub_path = os.path.join(folder_path, sub_name)
if sub_name[:1] != "." and os.path.isdir(sub_path): if sub_name[:1] != "." and os.path.isdir(sub_path):
mtg_list_out.write(sub_name + "\n") mtg_list_out.write(sub_name + "\n")
mtg_list_out.close() mtg_list_out.close()
# TODO: uncomment this: update_tree(minetest_game_path, game_path) # TODO: uncomment this: update_tree(minetest_game_path, game_path)
server_devel_minetest_conf_path = os.path.join( server_devel_minetest_conf_path = os.path.join(
game_path, game_path,
"minetest.conf.ENLIVEN-server" "minetest.conf.ENLIVEN-server"
) )
server_minetest_conf_path = os.path.join(game_path, "minetest.conf") server_minetest_conf_path = os.path.join(game_path, "minetest.conf")
if not os.path.isfile(server_devel_minetest_conf_path): if not os.path.isfile(server_devel_minetest_conf_path):
warnings.append(server_devel_minetest_conf_path + " was not found") warnings.append(server_devel_minetest_conf_path + " was not found")
else: else:
shutil.copyfile(server_devel_minetest_conf_path, shutil.copyfile(server_devel_minetest_conf_path,
server_minetest_conf_path) server_minetest_conf_path)
rm_sub(["CC-BY-SA 3.0 Unported (fallback license for ENLIVEN assets)"
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)"
".txt"]) ".txt"])
rm_sub(["MIT LICENSE (fallback license for ENLIVEN code).txt"]) rm_sub(["MIT LICENSE (fallback license for ENLIVEN code).txt"])
# NOTE: At this point, the following LICENSE and README files are # NOTE: At this point, the following LICENSE and README files are
# minetest_game's and the following are intentionally looking in # minetest_game's and the following are intentionally looking in
# C:\games\ENLIVEN\games\ENLIVEN: # C:\games\ENLIVEN\games\ENLIVEN:
# 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())

16
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,17 +159,17 @@ 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():
print(CMD_COMMENT + "{}: {}".format(k, v)) print(CMD_COMMENT + "{}: {}".format(k, v))
update_tree( update_tree(
@ -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())

34
generate-mt5-share-fix.py

@ -1,21 +1,25 @@
#!/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/"
} }
count = 0
command_count = 0
in_path = "bad_mt5_make_install_output.txt" def main():
outs_path = os.path.dirname(os.path.realpath(__file__)) count = 0
out_path = os.path.join(outs_path, "install-fix-minetest5-share.sh") command_count = 0
file_commands = [] in_path = "bad_mt5_make_install_output.txt"
rmd_cmds = [] outs_path = os.path.dirname(os.path.realpath(__file__))
mkdir_commands = [] out_path = os.path.join(outs_path, "install-fix-minetest5-share.sh")
made_dirs = [] file_commands = []
mtg_mod_dirs = ["games//minetest_game/mods", "games/minetest_game/mods"] rmd_cmds = []
with open(in_path) as ins: mkdir_commands = []
made_dirs = []
mtg_mod_dirs = ["games//minetest_game/mods", "games/minetest_game/mods"]
with open(in_path) as ins:
with open(out_path, 'w') as outs: with open(out_path, 'w') as outs:
outs.write("#!/bin/sh\n") outs.write("#!/bin/sh\n")
count += 1 count += 1
@ -140,5 +144,11 @@ with open(in_path) as ins:
count += 1 count += 1
command_count += 1 command_count += 1
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())

291
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,181 +44,200 @@ 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']
if not os.path.isdir(profile_path): def main():
print("") if not os.path.isdir(profile_path):
print("Failed to get existing home path--tried HOME & USERPROFILE") echo0("")
print("") echo0("Failed to get existing home path--tried HOME & USERPROFILE")
input("press enter to close") echo0("")
exit(2) return 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":
base_path = os.path.join(profile_path, "AppData") base_path = os.path.join(profile_path, "AppData")
configs_path = os.path.join(base_path, "Local") configs_path = os.path.join(base_path, "Local")
CONFIG_PATH = os.path.join(configs_path, "EnlivenMinetest") CONFIG_PATH = os.path.join(configs_path, "EnlivenMinetest")
if not os.path.isdir(CONFIG_PATH): if not os.path.isdir(CONFIG_PATH):
os.makedirs(CONFIG_PATH) os.makedirs(CONFIG_PATH)
# NOTE: not using /var/cache # NOTE: not using /var/cache
caches_path = os.path.join(CONFIG_PATH, "cache") caches_path = os.path.join(CONFIG_PATH, "cache")
RELEASES_PATH = os.path.join(caches_path, "releases") RELEASES_PATH = os.path.join(caches_path, "releases")
GIT_REPOS_PATH = os.path.join(caches_path, "git") GIT_REPOS_PATH = os.path.join(caches_path, "git")
GIT_BRANCHES_PATH = os.path.join(caches_path, "git-branches") GIT_BRANCHES_PATH = os.path.join(caches_path, "git-branches")
if not os.path.isdir(RELEASES_PATH): if not os.path.isdir(RELEASES_PATH):
os.makedirs(RELEASES_PATH) os.makedirs(RELEASES_PATH)
if not os.path.isdir(GIT_REPOS_PATH): if not os.path.isdir(GIT_REPOS_PATH):
os.makedirs(GIT_REPOS_PATH) os.makedirs(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:
MT_GAMES_DIR = os.path.join(USR_SHARE_MINETEST, "games") return code
MT_MYGAME_NAME = "subgametest"
MT_MYGAME_DIR = os.path.join(MT_GAMES_DIR, MT_MYGAME_NAME) MT_GAMES_DIR = os.path.join(USR_SHARE_MINETEST, "games")
MT_MYGAME_NAME = "subgametest"
mtg_game_name = "minetest_game" MT_MYGAME_DIR = os.path.join(MT_GAMES_DIR, MT_MYGAME_NAME)
MTG_PATH = os.path.join(MT_GAMES_DIR, mtg_game_name)
folder_path = MTG_PATH MTG_PATH = None
MTG_MODS_PATH = os.path.join(MTG_PATH, "mods") mtg_game_name = None
base_game_path = None
if not os.path.isdir(folder_path): base_games = ["amhi_game", "minetest_game"]
print("Could not find \"" + folder_path + "\". Script ended early.") for try_game_name in base_games:
input("press enter to close...") MTG_PATH = os.path.join(MT_GAMES_DIR, try_game_name)
exit(4) base_game_path = MTG_PATH
if os.path.isdir(base_game_path):
if force_update_mtg_enable: 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
MTG_MODS_PATH = os.path.join(MTG_PATH, "mods")
if force_update_mtg_enable:
shutil.rmtree(MT_MYGAME_DIR) shutil.rmtree(MT_MYGAME_DIR)
# yes | cp -rf $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR" # yes | cp -rf $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR"
# sudo rsync -a $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR" # sudo rsync -a $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR"
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
# tmp_game_conf_path = os.path.join(profile_path, "game.conf") # tmp_game_conf_path = os.path.join(profile_path, "game.conf")
outs = open(os.path.join(MT_MYGAME_DIR, "game.conf"), 'w') outs = open(os.path.join(MT_MYGAME_DIR, "game.conf"), 'w')
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"))
good_dir = os.path.join(MT_MYGAME_DIR, "mods")
if os.path.isdir(os.path.join(MT_MYGAME_DIR, "mods")): if os.path.isdir(good_dir):
print("Copied subgame to " + MT_MYGAME_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(base_game_path):
# for sub_name in os.listdir(folder_path): # sub_path = os.path.join(base_game_path, sub_name)
# sub_path = os.path.join(folder_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):
echo0("Cannot create " + GIT_REPOS_PATH + " so cannot continue.")
if not os.path.isdir(GIT_REPOS_PATH): return 8
print("Cannot create " + GIT_REPOS_PATH + " so cannot continue.")
input("press enter to close...") # TODO: actually install something (from spreadsheet maybe)
exit(8)
mtg_mods_list = list()
# TODO: actually install something (from spreadsheet maybe) src_mods_path = MTG_MODS_PATH
if os.path.isdir(src_mods_path):
mtg_mods_list = list() for sub_name in os.listdir(src_mods_path):
folder_path = MTG_MODS_PATH sub_path = os.path.join(src_mods_path, sub_name)
if os.path.isdir(folder_path):
for sub_name in os.listdir(folder_path):
sub_path = os.path.join(folder_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 # git clone https://github.com/tenplus1/mobs_monster.git
# git clone https://github.com/tenplus1/mobs_monster.git # git clone https://github.com/tenplus1/mobs_npc.git
# git clone https://github.com/tenplus1/mobs_npc.git # but not:
# but not: # git clone https://github.com/poikilos/minetest-minigamer.git
# git clone https://github.com/poikilos/minetest-minigamer.git # 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())

160
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,13 +143,63 @@ 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
q = Queue() def main():
Thread(target=reader, args=[process.stdout, q]).start() key_exit_msg = "SIGINT should shut down server safely...\n"
Thread(target=reader, args=[process.stderr, q]).start() game_id = "ENLIVEN"
try: # 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()
Thread(target=reader, args=[process.stdout, q]).start()
Thread(target=reader, args=[process.stderr, q]).start()
try:
for _ in range(2): for _ in range(2):
for source, line in iter(q.get, None): for source, line in iter(q.get, None):
# print "%s: %s" % (source, line), # print "%s: %s" % (source, line),
@ -181,15 +207,15 @@ 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
# as per https://docs.python.org/2/library/subprocess.html # as per https://docs.python.org/2/library/subprocess.html
@ -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.
)

151
uninstall-minetestserver-git.py

@ -1,51 +1,54 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys
import platform import platform
CMD_REM = "#"
CMD_RM = "rm " def main():
CMD_RMDIR = "rmdir " CMD_REM = "#"
if platform.system() == "Windows": CMD_RM = "rm "
CMD_RMDIR = "rmdir "
if platform.system() == "Windows":
CMD_REM = "REM " CMD_REM = "REM "
CMD_RM = "del " CMD_RM = "del "
CMD_RMDIR = "rd " CMD_RMDIR = "rd "
# profile_path = None # profile_path = None
# if 'HOME' in os.environ: # if 'HOME' in os.environ:
# profile_path = os.environ['HOME'] # profile_path = os.environ['HOME']
# elif 'USERPROFILE' in os.environ: # elif 'USERPROFILE' in os.environ:
# profile_path = os.environ['USERPROFILE'] # profile_path = os.environ['USERPROFILE']
# downloads_path = os.path.join(profile_path, "Downloads") # downloads_path = os.path.join(profile_path, "Downloads")
# repo_path = os.path.join(downloads_path, "minetest") # repo_path = os.path.join(downloads_path, "minetest")
# if not os.path.isdir(repo_path): # if not os.path.isdir(repo_path):
# repo_path = os.path.join(profile_path, "minetest") # repo_path = os.path.join(profile_path, "minetest")
# if not os.path.isdir(repo_path): # if not os.path.isdir(repo_path):
# 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):
# print("ERROR: nothing done since there is no " + # print("ERROR: nothing done since there is no " +
# install_manifest_name + " in '" + repo_path + # install_manifest_name + " in '" + repo_path +
# "'. 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
f_skipped_count = 0 f_skipped_count = 0
f_failed_count = 0 f_failed_count = 0
retry_lines = [] retry_lines = []
with open(install_manifest_name, 'r') as ins: with open(install_manifest_name, 'r') as ins:
original_line = True original_line = True
while original_line: while original_line:
original_line = ins.readline() original_line = ins.readline()
@ -68,42 +71,42 @@ with open(install_manifest_name, 'r') as ins:
else: else:
f_skipped_count += 1 f_skipped_count += 1
print("Removed " + str(f_removed_count) + " file(s) (skipped not" print("Removed " + str(f_removed_count) + " file(s) (skipped not"
" present:" + str(f_skipped_count) + "; failed:" " present:" + str(f_skipped_count) + "; failed:"
+ str(f_failed_count) + ")") + str(f_failed_count) + ")")
# NOTE: the next line makes ASCENDING (by len) list of TUPLES (name,len) # NOTE: the next line makes ASCENDING (by len) list of TUPLES (name,len)
sorted_directories = [ sorted_directories = [
(x, len(x)) for x in sorted(directories, key=len) (x, len(x)) for x in sorted(directories, key=len)
] ]
print("Removing folders...") print("Removing folders...")
# NOTE: they are sorted ASCENDING so start at end: # NOTE: they are sorted ASCENDING so start at end:
d_removed_count = 0 d_removed_count = 0
d_skipped_count = 0 d_skipped_count = 0
d_failed_count = 0 d_failed_count = 0
# still leaves: # still leaves:
# /usr/local/share/minetest/games/minetest_game/mods # /usr/local/share/minetest/games/minetest_game/mods
# /usr/local/share/minetest/textures/base/pack/: # /usr/local/share/minetest/textures/base/pack/:
# down_arrow.png left_arrow.png right_arrow.png up_arrow.png # down_arrow.png left_arrow.png right_arrow.png up_arrow.png
# /usr/local/share/minetest/games/minimal/mods # /usr/local/share/minetest/games/minimal/mods
# so: # so:
try_files = ["depends.txt", "down_arrow.png", "left_arrow.png", try_files = ["depends.txt", "down_arrow.png", "left_arrow.png",
"right_arrow.png", "up_arrow.png"] "right_arrow.png", "up_arrow.png"]
try_dirs = ["mods"] try_dirs = ["mods"]
extra_dirs = [] extra_dirs = []
ed_failed_count = 0 ed_failed_count = 0
ed_removed_count = 0 ed_removed_count = 0
extra_files = [] extra_files = []
e_failed_count = 0 e_failed_count = 0
e_removed_count = 0 e_removed_count = 0
for i in reversed(range(len(sorted_directories))): for i in reversed(range(len(sorted_directories))):
d_path = sorted_directories[i][0] d_path = sorted_directories[i][0]
# for d in reversed(sorted_directories): # for d in reversed(sorted_directories):
# d_path = d[0] # d_path = d[0]
# print("checking "+str(d_path)) # print("checking "+str(d_path))
if os.path.isdir(d_path): if os.path.isdir(d_path):
try: try:
for try_name in try_files: for try_name in try_files:
@ -143,20 +146,21 @@ for i in reversed(range(len(sorted_directories))):
d_removed_count += 1 d_removed_count += 1
else: else:
d_skipped_count += 1 d_skipped_count += 1
print("Removed " + str(d_removed_count) + " folder(s) (skipped not" print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
" present:" + str(d_skipped_count) + "; failed:" " present:" + str(d_skipped_count) + "; failed:"
+ str(d_failed_count) + ")") + str(d_failed_count) + ")")
if e_failed_count > 0: if e_failed_count > 0:
print("(failed to remove " + e_failed_count + " known extra file(s)" print("(failed to remove " + e_failed_count + " known extra file(s)"
" (will be shown under FAILURES below)") " (will be shown under FAILURES below)")
if ed_failed_count > 0: if ed_failed_count > 0:
print("(failed to remove " + ed_failed_count + " known extra" print("(failed to remove " + ed_failed_count + " known extra"
" folder(s) (will be shown under FAILURES below)") " folder(s) (will be shown under FAILURES below)")
print("Removed " + str(d_removed_count) + " folder(s) (skipped not" 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) + ")")
if f_failed_count+d_failed_count+ed_failed_count <= 0: code = 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:
print("Nothing to do (minetest+minetestserver has 0 known files" print("Nothing to do (minetest+minetestserver has 0 known files"
@ -165,7 +169,7 @@ if f_failed_count+d_failed_count+ed_failed_count <= 0:
else: else:
print("OK [finished uninstalling all installed files]") print("OK [finished uninstalling all installed files]")
print("") print("")
else: else:
print("") print("")
print("") print("")
print(CMD_REM+"FAILURES:") print(CMD_REM+"FAILURES:")
@ -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("")
if not ins.closed: code = 1
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())

41
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 + "+"
@ -101,7 +102,7 @@ if __name__ == "__main__":
elif prev_arg == "--browser": elif prev_arg == "--browser":
browserPath = arg browserPath = arg
elif prev_arg == "page": elif prev_arg == "page":
page_param="&page=2" page_param = "&page=2"
prev_arg = None prev_arg = None
else: else:
if arg == "--closed": if arg == "--closed":
@ -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())

109
utilities/extra/uninstall.py

@ -1,70 +1,73 @@
#!/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
rem_cmd = "#" def main():
rm_cmd = "rm " rem_cmd = "#"
rmdir_cmd = "rmdir " rm_cmd = "rm "
if platform.system() == "Windows": rmdir_cmd = "rmdir "
if platform.system() == "Windows":
rm_cmd = "DEL " rm_cmd = "DEL "
rmdir_cmd = "RD " rmdir_cmd = "RD "
rem_cmd = "REM " rem_cmd = "REM "
profile_path1 = os.environ.get('HOME') profile_path1 = os.environ.get('HOME')
profile_path = profile_path1 profile_path = profile_path1
profile_path2 = os.environ.get('USERPROFILE') profile_path2 = os.environ.get('USERPROFILE')
if profile_path2 is not None: if profile_path2 is not None:
profile_path = profile_path2 profile_path = profile_path2
if profile_path1 is not None: if profile_path1 is not None:
print(rem_cmd + "WARNING: HOME is present, but USERPROFILE '" print(rem_cmd + "WARNING: HOME is present, but USERPROFILE '"
+ 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)
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):
# print("Line {}: {}".format(cnt, line)) # print("Line {}: {}".format(cnt, line))
line = line_original.strip() line = line_original.strip()
if len(line) > 0: if len(line) > 0:
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
sorted_list = sorted(unsorted_list, key=len, reverse=True) sorted_list = sorted(unsorted_list, key=len, reverse=True)
# reverse: descending # reverse: descending
# or (also reverse): # or (also reverse):
# the_list.sort(key=lambda item: (-len(item), item)) # the_list.sort(key=lambda item: (-len(item), item))
print(rem_cmd + "Uninstalling...") print(rem_cmd + "Uninstalling...")
not_removed_files = [] not_removed_files = []
not_removed_dirs = [] not_removed_dirs = []
does_not_exist = [] does_not_exist = []
file_count = 0 file_count = 0
dir_count = 0 dir_count = 0
for path in sorted_list: for path in sorted_list:
if os.path.isfile(path): if os.path.isfile(path):
if path[0:1] == ".": if path[0:1] == ".":
print(rm_cmd + "\"" + path + "\"") print(rm_cmd + "\"" + path + "\"")
@ -88,17 +91,18 @@ for path in sorted_list:
else: else:
does_not_exist.append(path) does_not_exist.append(path)
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
print(rem_cmd + "Uninstall is complete.") show_dot_warning = True
print(rem_cmd + "- files: " + str(file_count)) print(rem_cmd + "Uninstall is complete.")
print(rem_cmd + "- directories: " + str(dir_count)) print(rem_cmd + "- files: " + str(file_count))
print(rem_cmd + "- missing: " + len(does_not_exist)) print(rem_cmd + "- directories: " + str(dir_count))
if (len(not_removed_files) + len(not_removed_dirs)) > 0: print(rem_cmd + "- missing: " + len(does_not_exist))
if (len(not_removed_files) + len(not_removed_dirs)) > 0:
for path in not_removed_files: for path in not_removed_files:
if path[0:1] == ".": if path[0:1] == ".":
if show_dot_warning: if show_dot_warning:
@ -113,5 +117,10 @@ if (len(not_removed_files) + len(not_removed_dirs)) > 0:
print(" " + rem_cmd + "- directories: " print(" " + rem_cmd + "- directories: "
+ str(not_removed_dir_count)) + str(not_removed_dir_count))
print("") print("")
print("") print("")
return 0
if __name__ == "__main__":
sys.exit(main())

125
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,45 +44,47 @@ def usage():
print("") print("")
licSrc = "example_license.txt" def main():
licDestName = "LICENSE.txt" licSrc = "example_license.txt"
licDesc = "MIT License" licDestName = "LICENSE.txt"
if not os.path.isfile(licSrc): licDesc = "MIT License"
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
fromName = None fromName = None
toName = None toName = None
extraArgCount = 0 extraArgCount = 0
enableFill = False enableFill = False
options = [] options = []
for i in range(1, len(sys.argv)): for i in range(1, len(sys.argv)):
if sys.argv[i] == "--fill": if sys.argv[i] == "--fill":
extraArgCount += 1 extraArgCount += 1
enableFill = True enableFill = True
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:
print("") print("")
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):
fromName = options[1] fromName = options[1]
toName = options[2] toName = options[2]
delimI = toName.rfind(":") delimI = toName.rfind(":")
@ -90,13 +92,13 @@ 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"
mobAPI = None mobAPI = None
if toMod is not None: if toMod is not None:
if not os.path.isfile(os.path.join(thisName, "depends.txt")): if not os.path.isfile(os.path.join(thisName, "depends.txt")):
dependsOut = open(os.path.join(thisName, "depends.txt"), 'w') dependsOut = open(os.path.join(thisName, "depends.txt"), 'w')
dependsOut.write(toMod+"\n") dependsOut.write(toMod+"\n")
@ -104,17 +106,17 @@ if toMod is not None:
if toMod.find("mob") > -1: if toMod.find("mob") > -1:
mobAPI = toMod mobAPI = toMod
if not os.path.isfile(os.path.join(thisName, "description.txt")): if not os.path.isfile(os.path.join(thisName, "description.txt")):
descOut = open(os.path.join(thisName, "description.txt"), 'w') descOut = open(os.path.join(thisName, "description.txt"), 'w')
descOut.write("\n") descOut.write("\n")
descOut.close() descOut.close()
if not os.path.isfile(os.path.join(thisName, "mod.conf")): if not os.path.isfile(os.path.join(thisName, "mod.conf")):
confOut = open(os.path.join(thisName, "mod.conf"), 'w') confOut = open(os.path.join(thisName, "mod.conf"), 'w')
confOut.write("name = "+thisName+"\n") confOut.write("name = "+thisName+"\n")
confOut.close() confOut.close()
if not os.path.isfile(os.path.join(thisName, "readme.md")): if not os.path.isfile(os.path.join(thisName, "readme.md")):
readmeOut = open(os.path.join(thisName, "readme.md"), 'w') readmeOut = open(os.path.join(thisName, "readme.md"), 'w')
readmeLine1 = thisName + " Minetest Mod" readmeLine1 = thisName + " Minetest Mod"
readmeOut.write(readmeLine1+"\n") readmeOut.write(readmeLine1+"\n")
@ -125,19 +127,19 @@ if not os.path.isfile(os.path.join(thisName, "readme.md")):
readmeOut.write("See " + licDestName + "\n") readmeOut.write("See " + licDestName + "\n")
readmeOut.close() readmeOut.close()
licDest = os.path.join(thisName, licDestName) licDest = os.path.join(thisName, licDestName)
if not os.path.isfile(licDest): if not os.path.isfile(licDest):
shutil.copyfile(licSrc, licDest) shutil.copyfile(licSrc, licDest)
luaOut = None luaOut = None
if not os.path.isfile(os.path.join(thisName, "init.lua")): if not os.path.isfile(os.path.join(thisName, "init.lua")):
luaOut = open(os.path.join(thisName, "init.lua"), 'w') luaOut = open(os.path.join(thisName, "init.lua"), 'w')
# luaOut.write("#!/usr/bin/env lua\n") # luaOut.write("#!/usr/bin/env lua\n")
luaOut.write("-- " + sys.argv[0] + " (EnlivenMinetest) generated\n") luaOut.write("-- " + sys.argv[0] + " (EnlivenMinetest) generated\n")
luaOut.write("-- the original version of this file.\n") luaOut.write("-- the original version of this file.\n")
fromMod = None # not required fromMod = None # not required
step0 = "" step0 = ""
if (len(options) == 3): if (len(options) == 3):
delimI = fromName.find(":") delimI = fromName.find(":")
if delimI > -1: if delimI > -1:
fromMod = fromName[:delimI] fromMod = fromName[:delimI]
@ -159,31 +161,31 @@ if (len(options) == 3):
+ fromName + '", "' + toName + '")' + "\n") + fromName + '", "' + toName + '")' + "\n")
luaOut.write(apiLinePrefix + 'minetest.register_alias("' luaOut.write(apiLinePrefix + 'minetest.register_alias("'
+ fromName + '", "' + toName + '")' + "\n") + fromName + '", "' + toName + '")' + "\n")
else: else:
step0 = "Add your code init.lua." step0 = "Add your code init.lua."
if luaOut is not None: if luaOut is not None:
luaOut.write("\n") luaOut.write("\n")
luaOut.close() luaOut.close()
print("") print("")
print("") print("")
print(step0) print(step0)
print("The new mod is the " + thisName + " folder. Remember to:") print("The new mod is the " + thisName + " folder. Remember to:")
ender = "." ender = "."
if (toMod is not None) and (len(toMod) > 0): if (toMod is not None) and (len(toMod) > 0):
ender = "" ender = ""
print("1. Edit depends.txt if your mod requires some mod" + ender) print("1. Edit depends.txt if your mod requires some mod" + ender)
if (toMod is not None) and (len(toMod) > 0): if (toMod is not None) and (len(toMod) > 0):
print(" other than '" + toMod + "'.") print(" other than '" + toMod + "'.")
print("") print("")
print("2. Edit description.txt to contain a brief description of") print("2. Edit description.txt to contain a brief description of")
print(" your mod (less than 100 characters).") print(" your mod (less than 100 characters).")
print("") print("")
print("3. Edit LICENSE.txt and add the year and the name of all ") print("3. Edit LICENSE.txt and add the year and the name of all ")
print(" authors, and change the license if desired (The included") print(" authors, and change the license if desired (The included")
print(" " + licSrc) print(" " + licSrc)
print(" should be the " + licDesc + ".") print(" should be the " + licDesc + ".")
print( print(
''' The MIT License is good for Minetest mods so they can be used ''' The MIT License is good for Minetest mods so they can be used
most widely such as on app stores where replacing the program as per most widely such as on app stores where replacing the program as per
the GPL v3 is not compliant with mobile OS security--the license of the GPL v3 is not compliant with mobile OS security--the license of
@ -192,7 +194,12 @@ print(
others to copy your work and claim it as their own especially if they others to copy your work and claim it as their own especially if they
modify it in any way. They would just be doing what you said they modify it in any way. They would just be doing what you said they
could do! could do!
''' '''
) )
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())

31
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
olds = getStrings(oldPath) def main():
news = getStrings(newPath) argCount = len(sys.argv) - 1
for v in olds:
if argCount < 2:
usage()
return 1
oldPath = sys.argv[1]
newPath = sys.argv[2]
olds = getStrings(oldPath)
news = getStrings(newPath)
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