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. 53
      buildenliven.py
  6. 261
      deploy.py
  7. 28
      filever.py
  8. 22
      forwardfilesync.py
  9. 262
      generate-mt5-share-fix.py
  10. 48
      headcompare.py
  11. 367
      install-subgametest.py
  12. 31
      install.py
  13. 208
      mtsenliven.py
  14. 13
      notes/continuify.py
  15. 103
      pyenliven/__init__.py
  16. 30
      pyenliven/compatiblizemod.py
  17. 5
      pyenliven/deprecated.py
  18. 77
      setup.py
  19. 347
      uninstall-minetestserver-git.py
  20. 8
      utilities/compatiblizemod.py
  21. 97
      utilities/enissue.py
  22. 41
      utilities/enlynx.py
  23. 221
      utilities/extra/uninstall.py
  24. 309
      utilities/generatemod.py
  25. 13
      utilities/mtcompile-program-local.py
  26. 10
      utilities/mtoldtonew.py
  27. 35
      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())

53
buildenliven.py

@ -9,46 +9,48 @@ import os
import configparser import configparser
from pyenliven import ( from pyenliven import (
error, echo0,
getSGPath, getSGPath,
profile, profile,
MODS_STOPGAP_DIR,
) )
gamespec = {} gamespec = {}
gamespec['remove_mods'] = [ gamespec['remove_mods'] = [
"coderblocks", # includes lmb blocks; no recipes "coderblocks", # includes lmb blocks; no recipes
"facade", # no recipes "facade", # no recipes
"placecraft", # interferes with eating "placecraft", # interferes with eating
"more_chests", # See https://github.com/poikilos/EnlivenMinetest/issues/446 "more_chests", # See https://github.com/poikilos/EnlivenMinetest/issues/446
"emeralds", # See https://github.com/poikilos/EnlivenMinetest/issues/497 "emeralds", # See https://github.com/poikilos/EnlivenMinetest/issues/497
"give_initial_stuff", # or make it configurable (It only uses a give_initial_stuff boolean, no configurable item list) "give_initial_stuff", # or make it configurable (It only uses a give_initial_stuff boolean, no configurable item list)
# TODO: more are at https://github.com/poikilos/EnlivenMinetest/issues/310 # TODO: more are at https://github.com/poikilos/EnlivenMinetest/issues/310
] ]
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>
}, },
{"https://github.com/MinetestForFun/unified_inventory"}, {"https://github.com/MinetestForFun/unified_inventory"},
] ]
@ -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())

261
deploy.py

@ -1,117 +1,16 @@
#!/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:
pass
warnings = list()
print("")
print("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")
print("This script patches minetest and minetest_game with ENLIVEN\n" +
"(such as launcher and subgame) and creates a Windows installer.")
script_dir_path = os.path.dirname(os.path.abspath(__file__))
enliven_project_path = os.path.dirname(script_dir_path)
profile_path = None
if "HOME" in os.environ:
profile_path = os.environ["HOME"]
elif "USERPROFILE" in os.environ:
profile_path = os.environ["USERPROFILE"]
else:
try_path = "C:\\Users\\jgustafson"
if not os.path.isdir(try_path):
try_path = "C:\\Users\\Owner"
print("WARNING: no HOME or USERPROFILE found, reverting to '" +
try_path + "'")
profile_path = try_path
# TODO: Make a settings file for values in the next region.
# region user settings
deploy_path = "C:\\Games\\ENLIVEN-deploy"
try_path = "C:\\Games\\Minetest"
if (not os.path.isdir(deploy_path)) and os.path.isdir(try_path):
deploy_path = try_path
installer_deploy_path = path_join_all([profile_path, "ownCloud", "www",
"expertmultimedia", "downloads"])
installer_name = "install-ENLIVEN.exe"
# endregion user settings
installer_path = os.path.join(installer_deploy_path, installer_name)
if not os.path.isdir(installer_deploy_path):
print("#WARNING: does not exist:")
print("installer_deploy_path: " + installer_deploy_path)
# this is a waste--it just shows 0.0.0.0 though iss file has version
# if os.path.isfile(installer_path):
# numbers=filever.get_version_number(installer_path)
# major,minor,subminor,revision = numbers
# print(".".join([str (i) for i in numbers]))
if not os.path.isdir(deploy_path):
os.makedirs(deploy_path)
games_path = os.path.join(deploy_path, "games")
minetest_game_path = os.path.join(games_path, "minetest_game")
minetest_game_mods_path = os.path.join(minetest_game_path, "mods")
if not os.path.isdir(minetest_game_path):
print("This deploy script requires an unmodified build of minetest and\n" +
" minetest_game. Please place an unmodified build of minetest in\n" +
" " + deploy_path + " so that minetest_game is at: \n\n" +
" " + minetest_game_path + "\n\n")
exit(1)
game_path = os.path.join(games_path, "ENLIVEN")
# NOTE: remove this case, and instead: copy minetest_game, download ENLIVEN
# automatically
if not os.path.isdir(game_path):
print("")
print("ERROR: ENLIVEN must first be installed from web sources" +
" using the provided 'install' script in the etc/change*" +
" folder (run on linux then copy to a Windows machine" +
" in " + game_path)
# exit(2)
else:
print("game_path: " + game_path)
mods_path = os.path.join(game_path, "mods")
if not os.path.isdir(mods_path):
os.makedirs(mods_path)
mtg_list_path = os.path.join(game_path, "minetest_game-mod-list.txt")
mtg_list_out = open(mtg_list_path, 'w')
folder_path = minetest_game_mods_path
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):
mtg_list_out.write(sub_name + "\n")
mtg_list_out.close()
# TODO: uncomment this: update_tree(minetest_game_path, game_path)
server_devel_minetest_conf_path = os.path.join(
game_path,
"minetest.conf.ENLIVEN-server"
) )
server_minetest_conf_path = os.path.join(game_path, "minetest.conf") if sys.version_info.major >= 3:
pass
if not os.path.isfile(server_devel_minetest_conf_path):
warnings.append(server_devel_minetest_conf_path + " was not found")
else: else:
shutil.copyfile(server_devel_minetest_conf_path, input = raw_input
server_minetest_conf_path)
def rm_sub(bad_sub): def rm_sub(bad_sub):
@ -120,22 +19,132 @@ def rm_sub(bad_sub):
os.remove(bad_path) os.remove(bad_path)
rm_sub(["CC-BY-SA 3.0 Unported (fallback license for ENLIVEN assets)" def main():
".txt"]) warnings = list()
rm_sub(["MIT LICENSE (fallback license for ENLIVEN code).txt"])
echo0("")
# NOTE: At this point, the following LICENSE and README files are echo0("This script is NOT YET IMPLEMENTED")
# minetest_game's and the following are intentionally looking in
# C:\games\ENLIVEN\games\ENLIVEN:
# rm_sub(["games", "ENLIVEN", "LICENSE.txt"]) # TODO: Scrape https://minetest.kitsunemimi.pw/builds/ (NOTE: stable is
# rm_sub(["games", "ENLIVEN", "README.txt"]) # always "https://minetest.kitsunemimi.pw/builds/win64/"
# "minetest-0.4.15-win64.7z")
print("")
if len(warnings) > 0:
print(str(len(warnings)) + " warning(s):") echo0("This script patches minetest and minetest_game with ENLIVEN\n" +
for warning in warnings: "(such as launcher and subgame) and creates a Windows installer.")
print(warning)
else: script_dir_path = os.path.dirname(os.path.abspath(__file__))
print("0 warnings.") enliven_project_path = os.path.dirname(script_dir_path)
print("\n")
input("press enter to exit...") profile_path = None
if "HOME" in os.environ:
profile_path = os.environ["HOME"]
elif "USERPROFILE" in os.environ:
profile_path = os.environ["USERPROFILE"]
else:
try_path = "C:\\Users\\jgustafson"
if not os.path.isdir(try_path):
try_path = "C:\\Users\\Owner"
echo0("WARNING: no HOME or USERPROFILE found, reverting to '" +
try_path + "'")
profile_path = try_path
# TODO: Make a settings file for values in the next region.
# region user settings
deploy_path = "C:\\Games\\ENLIVEN-deploy"
try_path = "C:\\Games\\Minetest"
if (not os.path.isdir(deploy_path)) and os.path.isdir(try_path):
deploy_path = try_path
installer_deploy_path = path_join_all([profile_path, "ownCloud", "www",
"expertmultimedia", "downloads"])
installer_name = "install-ENLIVEN.exe"
# endregion user settings
installer_path = os.path.join(installer_deploy_path, installer_name)
if not os.path.isdir(installer_deploy_path):
echo0("#WARNING: does not exist:")
print("installer_deploy_path: " + installer_deploy_path)
# this is a waste--it just shows 0.0.0.0 though iss file has version
# if os.path.isfile(installer_path):
# numbers=filever.get_version_number(installer_path)
# major,minor,subminor,revision = numbers
# print(".".join([str (i) for i in numbers]))
if not os.path.isdir(deploy_path):
os.makedirs(deploy_path)
games_path = os.path.join(deploy_path, "games")
minetest_game_path = os.path.join(games_path, "minetest_game")
minetest_game_mods_path = os.path.join(minetest_game_path, "mods")
if not os.path.isdir(minetest_game_path):
echo0("This deploy script requires an unmodified build of minetest and\n" +
" minetest_game. Please place an unmodified build of minetest in\n" +
" " + deploy_path + " so that minetest_game is at: \n\n" +
" " + minetest_game_path + "\n\n")
return 1
game_path = os.path.join(games_path, "ENLIVEN")
# NOTE: remove this case, and instead: copy minetest_game, download ENLIVEN
# automatically
if not os.path.isdir(game_path):
echo0("")
echo0("ERROR: ENLIVEN must first be installed from web sources" +
" using the provided 'install' script in the etc/change*" +
" folder (run on linux then copy to a Windows machine" +
" in " + game_path)
# return 2
else:
print("game_path: " + game_path)
mods_path = os.path.join(game_path, "mods")
if not os.path.isdir(mods_path):
os.makedirs(mods_path)
mtg_list_path = os.path.join(game_path, "minetest_game-mod-list.txt")
mtg_list_out = open(mtg_list_path, 'w')
folder_path = minetest_game_mods_path
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):
mtg_list_out.write(sub_name + "\n")
mtg_list_out.close()
# TODO: uncomment this: update_tree(minetest_game_path, game_path)
server_devel_minetest_conf_path = os.path.join(
game_path,
"minetest.conf.ENLIVEN-server"
)
server_minetest_conf_path = os.path.join(game_path, "minetest.conf")
if not os.path.isfile(server_devel_minetest_conf_path):
warnings.append(server_devel_minetest_conf_path + " was not found")
else:
shutil.copyfile(server_devel_minetest_conf_path,
server_minetest_conf_path)
rm_sub(["CC-BY-SA 3.0 Unported (fallback license for ENLIVEN assets)"
".txt"])
rm_sub(["MIT LICENSE (fallback license for ENLIVEN code).txt"])
# NOTE: At this point, the following LICENSE and README files are
# minetest_game's and the following are intentionally looking in
# C:\games\ENLIVEN\games\ENLIVEN:
# rm_sub(["games", "ENLIVEN", "LICENSE.txt"])
# rm_sub(["games", "ENLIVEN", "README.txt"])
echo0("")
if len(warnings) > 0:
echo0(str(len(warnings)) + " warning(s):")
for warning in warnings:
echo0(warning)
else:
echo0("0 warnings.")
echo0()
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())

22
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)):
@ -35,7 +36,7 @@ def trim_branch(src, dst, dot_hidden=True, verbose=True):
''' '''
Explore dst non-recursively and delete files Explore dst non-recursively and delete files
and subdirectories recursively that are not present on src. and subdirectories recursively that are not present on src.
Keyword arguments: Keyword arguments:
dot_hidden -- Operate on files and directories even if they are dot_hidden -- Operate on files and directories even if they are
hidden by starting with '.'. hidden by starting with '.'.
@ -60,7 +61,7 @@ def update_tree(src, dst, level=0, do_trim=False, dot_hidden=False,
''' '''
Creates dst if not present, then copies everything from src to dst Creates dst if not present, then copies everything from src to dst
recursively. recursively.
Keyword arguments: Keyword arguments:
do_trim -- Delete files and directories from dst that are not on do_trim -- Delete files and directories from dst that are not on
src. src.
@ -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,18 +133,20 @@ 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
flags["delete"] = False flags["delete"] = False
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())

262
generate-mt5-share-fix.py

@ -1,144 +1,154 @@
#!/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 = []
with open(out_path, 'w') as outs: made_dirs = []
outs.write("#!/bin/sh\n") mtg_mod_dirs = ["games//minetest_game/mods", "games/minetest_game/mods"]
count += 1 with open(in_path) as ins:
for line_orig in ins: with open(out_path, 'w') as outs:
line = line_orig.strip() outs.write("#!/bin/sh\n")
action = None count += 1
old_path = None for line_orig in ins:
for k, try_action in actions.items(): line = line_orig.strip()
if line.startswith(k): action = None
action = try_action old_path = None
old_path = line[len(k):].strip() for k, try_action in actions.items():
break if line.startswith(k):
if action == "move": action = try_action
found = None old_path = line[len(k):].strip()
for old, new in changes.items(): break
if old_path.startswith(old): if action == "move":
found = old found = None
new_path = new + old_path[len(old):] for old, new in changes.items():
if not os.path.exists(old_path): if old_path.startswith(old):
if not os.path.exists(new_path): found = old
# raise ValueError( new_path = new + old_path[len(old):]
# "The program is not installed" if not os.path.exists(old_path):
# " (missing '{}')".format(old_path) if not os.path.exists(new_path):
# ) # raise ValueError(
outs.write( # "The program is not installed"
'# WARNING: expected "{}" (there is' # " (missing '{}')".format(old_path)
' no destination "{}" either)' # )
''.format(old_path, new_path) outs.write(
) '# WARNING: expected "{}" (there is'
else: ' no destination "{}" either)'
outs.write( ''.format(old_path, new_path)
'# Already moved (no source "{}"'
' for destination "{}")'
''.format(old_path, new_path)
)
else:
if os.path.isfile(old_path):
parent = os.path.split(new_path)[0]
if parent not in made_dirs:
made_dirs.append(parent)
cmd = 'mkdir -p "{}"'.format(
parent.replace("//", "/")
) )
mkdir_commands.append(cmd) else:
# AFTER all directories BEFORE all files outs.write(
options = "" '# Already moved (no source "{}"'
if os.path.isfile(new_path): ' for destination "{}")'
options = "-f" ''.format(old_path, new_path)
if len(options) > 0:
options = " " + options.strip()
cmd = (
'mv' + options
+ ' "{}" "{}"'.format(
old_path.replace("//", "/"),
new_path.replace("//", "/")
) )
)
# outs.write(cmd + "\n")
# AFTER all directories
file_commands.append(cmd)
else: else:
# old_path == old_path.replace("//","/") if os.path.isfile(old_path):
# Manually fix: parent = os.path.split(new_path)[0]
if parent not in made_dirs:
made_dirs.append(parent)
cmd = 'mkdir -p "{}"'.format(
parent.replace("//", "/")
)
mkdir_commands.append(cmd)
# AFTER all directories BEFORE all files
options = ""
if os.path.isfile(new_path):
options = "-f"
if len(options) > 0:
options = " " + options.strip()
cmd = (
'mv' + options
+ ' "{}" "{}"'.format(
old_path.replace("//", "/"),
new_path.replace("//", "/")
)
)
# outs.write(cmd + "\n")
# AFTER all directories
file_commands.append(cmd)
else:
# old_path == old_path.replace("//","/")
# Manually fix:
# rmdir: failed to remove '/usr/local/ # rmdir: failed to remove '/usr/local/
# ./games//minetest_game/mods': # ./games//minetest_game/mods':
# Directory not empty # Directory not empty
# rmdir: failed to remove '/usr/local/ # rmdir: failed to remove '/usr/local/
# ./games//minetest_game': # ./games//minetest_game':
# Directory not empty # Directory not empty
# due to /usr/local/./games// # due to /usr/local/./games//
# minetest_game/mods/game_commands: # minetest_game/mods/game_commands:
orphan_mods = ["game_commands"] orphan_mods = ["game_commands"]
removed_orphan_mods = [] removed_orphan_mods = []
for mod_rel in orphan_mods: for mod_rel in orphan_mods:
for mtg_rel in mtg_mod_dirs: for mtg_rel in mtg_mod_dirs:
f_rel = found + mtg_rel f_rel = found + mtg_rel
# such as ("/usr/local/./" # such as ("/usr/local/./"
# + "games//minetest_game/mods") # + "games//minetest_game/mods")
if old_path.startswith(f_rel): if old_path.startswith(f_rel):
# if mod_rel not in # if mod_rel not in
# removed_orphan_mods: # removed_orphan_mods:
try_path = (found + mtg_rel try_path = (found + mtg_rel
+ "/" + mod_rel) + "/" + mod_rel)
if os.path.isdir(try_path): if os.path.isdir(try_path):
cmd = ( cmd = (
'rmdir "{}"'.format( 'rmdir "{}"'.format(
try_path try_path
)
) )
) # queue for last stage:
# queue for last stage: if cmd not in rmd_cmds:
if cmd not in rmd_cmds: rmd_cmds.append(cmd)
rmd_cmds.append(cmd) # removed_orphan_mods.
# removed_orphan_mods. # append(mod_rel)
# append(mod_rel) break
break
cmd = 'rmdir "{}"'.format(old_path) cmd = 'rmdir "{}"'.format(old_path)
rmd_cmds.append(cmd) # AFTER everything rmd_cmds.append(cmd) # AFTER everything
break break
if found is None: if found is None:
outs.write("# WARNING: The destination path is" outs.write("# WARNING: The destination path is"
" unknown: ") " unknown: ")
outs.write('# mv "{}" "{}"'.format(old_path, outs.write('# mv "{}" "{}"'.format(old_path,
old_path)) old_path))
else: else:
outs.write("# " + line + "\n") outs.write("# " + line + "\n")
count += 1
for cmd in sorted(mkdir_commands, key=len):
outs.write(cmd + "\n")
count += 1 count += 1
for cmd in sorted(mkdir_commands, key=len): command_count += 1
outs.write(cmd + "\n") for cmd in file_commands:
count += 1 outs.write(cmd + "\n")
command_count += 1 count += 1
for cmd in file_commands: command_count += 1
outs.write(cmd + "\n") for cmd in sorted(rmd_cmds, key=len, reverse=True):
count += 1 outs.write(cmd + "\n")
command_count += 1 count += 1
for cmd in sorted(rmd_cmds, key=len, reverse=True): command_count += 1
outs.write(cmd + "\n")
count += 1 print('Added {} line(s) to "{}" (including {} command(s))'
command_count += 1 ''.format(count, out_path, command_count))
return 0
print('Added {} line(s) to "{}" (including {} command(s))' if __name__ == "__main__":
''.format(count, out_path, command_count)) sys.exit(main())

48
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())

367
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
shutil.rmtree(MT_MYGAME_DIR)
if mtg_game_name is None:
# yes | cp -rf $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR" echo0("Could not find \"" + base_game_path + "\". Script ended early.")
# sudo rsync -a $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR" echo0("Set shared_minetest_path to the path containing a")
echo0(" games folder with one of the following: {}".format(base_games))
try: return 4
# DOES update minetest_game, but does NOT delete extra mods:
update_tree(folder_path, MT_MYGAME_DIR) MTG_MODS_PATH = os.path.join(MTG_PATH, "mods")
print("Updated \"" + MT_MYGAME_DIR + "\"...")
except PermissionError: if force_update_mtg_enable:
print(str(sys.exc_info())) shutil.rmtree(MT_MYGAME_DIR)
print("")
print("You must run " + __file__ + " as a user that can write to " # yes | cp -rf $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR"
"\"" + MT_MYGAME_DIR + "\"") # sudo rsync -a $MT_GAMES_DIR/minetest_game/* MT_MYGAME_DIR"
print("")
input("press enter to close...") try:
exit(5) # DOES update minetest_game, but does NOT delete extra mods:
update_tree(base_game_path, MT_MYGAME_DIR)
try: echo0("Updated \"" + MT_MYGAME_DIR + "\"...")
# cd $HOME except PermissionError:
# tmp_game_conf_path = os.path.join(profile_path, "game.conf") echo0(str(sys.exc_info()))
outs = open(os.path.join(MT_MYGAME_DIR, "game.conf"), 'w') echo0("")
outs.write("name = subgametest") echo0("You must run " + __file__ + " as a user that can write to "
outs.close() "\"" + MT_MYGAME_DIR + "\"")
except PermissionError: echo0("")
print(str(sys.exc_info())) return 5
print("")
print("You must run " + __file__ + " as a user that can write to " try:
"\"" + MT_MYGAME_DIR + "\"") # cd $HOME
print("") # tmp_game_conf_path = os.path.join(profile_path, "game.conf")
input("press enter to close...") outs = open(os.path.join(MT_MYGAME_DIR, "game.conf"), 'w')
exit(6) outs.write("name = subgametest")
# cmd_string = "sudo mv -f game.conf \MT_MYGAME_DIR\"" outs.close()
# shutil.move(tmp_game_conf_path, os.path.join(MT_MYGAME_DIR, "game.conf")) except PermissionError:
echo0(str(sys.exc_info()))
if os.path.isdir(os.path.join(MT_MYGAME_DIR, "mods")): echo0("")
print("Copied subgame to " + MT_MYGAME_DIR) echo0("You must run " + __file__ + " as a user that can write to "
else: "\"" + MT_MYGAME_DIR + "\"")
print("FAILED to copy subgame to " + MT_MYGAME_DIR) echo0("")
input("press enter to close...") return 6
exit(7) # cmd_string = "sudo mv -f game.conf \MT_MYGAME_DIR\""
# shutil.move(tmp_game_conf_path, os.path.join(MT_MYGAME_DIR, "game.conf"))
MT_MYGAME_MODS_PATH = os.path.join(MT_MYGAME_DIR, "mods") good_dir = os.path.join(MT_MYGAME_DIR, "mods")
MTMOD_DEST_NAME = "minigamer" if os.path.isdir(good_dir):
MTMOD_DEST_PATH = os.path.join(MT_MYGAME_MODS_PATH, MTMOD_DEST_NAME) echo0("Copied subgame to " + MT_MYGAME_DIR)
else:
# if force_update_mtg_mods_enable: echo0('FAILED to copy subgame to "{}" ("{}" is missing)'
# for sub_name in os.listdir(folder_path): ''.format(MT_MYGAME_DIR, good_dir))
# sub_path = os.path.join(folder_path, sub_name) return 7
# dst_path = os.path.join(MT_MYGAME_DIR, sub_name)
# if sub_name[:1]!="." and os.path.isdir(sub_path): MT_MYGAME_MODS_PATH = os.path.join(MT_MYGAME_DIR, "mods")
# if os.path.isdir(dst_path): MTMOD_DEST_NAME = "minigamer"
# shutil.rmtree(dst_path) MTMOD_DEST_PATH = os.path.join(MT_MYGAME_MODS_PATH, MTMOD_DEST_NAME)
# if force_update_mtg_mods_enable:
if not os.path.isdir(GIT_REPOS_PATH): # for sub_name in os.listdir(base_game_path):
print("Cannot create " + GIT_REPOS_PATH + " so cannot continue.") # sub_path = os.path.join(base_game_path, sub_name)
input("press enter to close...") # dst_path = os.path.join(MT_MYGAME_DIR, sub_name)
exit(8) # if sub_name[:1]!="." and os.path.isdir(sub_path):
# if os.path.isdir(dst_path):
# TODO: actually install something (from spreadsheet maybe) # shutil.rmtree(dst_path)
mtg_mods_list = list() if not os.path.isdir(GIT_REPOS_PATH):
folder_path = MTG_MODS_PATH echo0("Cannot create " + GIT_REPOS_PATH + " so cannot continue.")
if os.path.isdir(folder_path): return 8
for sub_name in os.listdir(folder_path):
sub_path = os.path.join(folder_path, sub_name) # TODO: actually install something (from spreadsheet maybe)
if sub_name[:1] != "." and os.path.isdir(sub_path):
mtg_mods_list.append(sub_name) mtg_mods_list = list()
src_mods_path = MTG_MODS_PATH
mods_installed_list = list() if os.path.isdir(src_mods_path):
mods_added_list = list() for sub_name in os.listdir(src_mods_path):
sub_path = os.path.join(src_mods_path, sub_name)
folder_path = MT_MYGAME_MODS_PATH if sub_name[:1] != "." and os.path.isdir(sub_path):
if os.path.isdir(folder_path): mtg_mods_list.append(sub_name)
for sub_name in os.listdir(folder_path):
sub_path = os.path.join(folder_path, sub_name) mods_installed_list = list()
if sub_name[:1] != "." and os.path.isdir(sub_path): mods_added_list = list()
mods_installed_list.append(sub_name)
if sub_name not in mtg_mods_list: dst_mods_path = MT_MYGAME_MODS_PATH
mods_added_list.append(sub_name) if os.path.isdir(dst_mods_path):
else: for sub_name in os.listdir(dst_mods_path):
print("Missing '" + folder_path + "'") sub_path = os.path.join(dst_mods_path, sub_name)
if sub_name[:1] != "." and os.path.isdir(sub_path):
print("") mods_installed_list.append(sub_name)
print("") if sub_name not in mtg_mods_list:
print("Installed " + str(len(mods_installed_list)) + " mod(s)" + mods_added_list.append(sub_name)
" (" + str(len(mtg_mods_list)) + " from " + mtg_game_name + ").") else:
if len(mods_added_list) > 0: echo0("Missing '" + dst_mods_path + "'")
print("Added:")
for mod_name in mods_added_list: echo0("")
print(" - " + mod_name) echo0("")
print("") echo0("Installed " + str(len(mods_installed_list)) + " mod(s)" +
input("press enter to close...") " (" + str(len(mtg_mods_list)) + " from " + mtg_game_name + ").")
# cd $TMP_DIR if len(mods_added_list) > 0:
# git clone https://github.com/tenplus1/mobs_redo.git print("Added:")
# git clone https://github.com/tenplus1/mobs_animal.git for mod_name in mods_added_list:
# git clone https://github.com/tenplus1/mobs_monster.git print(" - " + mod_name)
# git clone https://github.com/tenplus1/mobs_npc.git echo0("")
# but not: # cd $TMP_DIR
# git clone https://github.com/poikilos/minetest-minigamer.git # git clone https://github.com/tenplus1/mobs_redo.git
# git clone https://github.com/poikilos/birthstones.git # git clone https://github.com/tenplus1/mobs_animal.git
# git clone https://github.com/tenplus1/mobs_monster.git
# Repo.clone_from(git_url, repo_dir) # git clone https://github.com/tenplus1/mobs_npc.git
# but not:
# git clone https://github.com/poikilos/minetest-minigamer.git
# git clone https://github.com/poikilos/birthstones.git
# 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())

208
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,44 +143,100 @@ 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 ...
for _ in range(2): echo0()
for source, line in iter(q.get, None): echo0()
# print "%s: %s" % (source, line), echo0()
s = source
l_s = line mts, code = get_var_and_check("minetestserver_path", code=1)
# NOTE: source is a string such as if code != 0:
# "<_io.BufferedReader name=5>" return code
l_s = decode_safe("utf-8")
process_msg("%s: %s" % (s, l_s)) wp, code = get_var_and_check("primary_world_path", code=1)
except KeyboardInterrupt: if code != 0:
print("[ mtsenliven.py ] " + key_exit_msg) return code
pass
wn = os.path.basename(wp)
exit(0) echo0("Using minetestserver: " + mts)
echo0("Using primary_world_path: " + wp)
while True: echo0("Using world_name: " + wn)
echo0()
process = None
try: try:
# can deadlock on high volume--use communicate instead # get both stdout and stderr (see
# as per https://docs.python.org/2/library/subprocess.html # https://www.saltycrane.com/blog/2008/09/how-get-stdout-and-
out_bytes = process.stdout.readline() # stderr-using-python-subprocess-module/)
# err_bytes = process.stderr.readline() process = subprocess.Popen(
# (err_bytes == '') and \ [mts, '--gameid', game_id, '--worldname', wn],
if (out_bytes == '') and \ stdout=subprocess.PIPE,
(process.poll() is not None): stderr=subprocess.PIPE,
break bufsize=1
if out_bytes: )
process_msg(out_bytes) # bufsize=1 as per jfs on <https://stackoverflow.com/questions/
# if err_bytes: # 31833897/python-read-from-subprocess-stdout-and-stderr-
# process_msg(err_bytes) # separately-while-preserving-order>
rc = process.poll() 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 source, line in iter(q.get, None):
# print "%s: %s" % (source, line),
s = source
l_s = line
# NOTE: source is a string such as
# "<_io.BufferedReader name=5>"
l_s = decode_safe(line) # line.decode("utf-8")
process_msg("%s: %s" % (s, l_s))
except KeyboardInterrupt: except KeyboardInterrupt:
print("[ mtsenliven.py ] " + key_exit_msg) print("[ mtsenliven.py ] " + key_exit_msg)
break pass
# process.kill()
return 0
'''
while True:
try:
# can deadlock on high volume--use communicate instead
# as per https://docs.python.org/2/library/subprocess.html
out_bytes = process.stdout.readline()
# err_bytes = process.stderr.readline()
# (err_bytes == '') and \
if (out_bytes == '') and \
(process.poll() is not None):
break
if out_bytes:
process_msg(out_bytes)
# if err_bytes:
# process_msg(err_bytes)
rc = process.poll()
except KeyboardInterrupt:
echo0("[ mtsenliven.py ] " + key_exit_msg)
break
# process.kill()
return 0
'''
if __name__ == "__main__":
sys.exit(main())

13
notes/continuify.py

@ -9,8 +9,9 @@ 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:
with open(inPath) as ins: with open(inPath) as ins:
rawLine = True rawLine = True
@ -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())

5
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
@ -28,7 +29,7 @@ class GiteaRepo(Repo):
# hide_events=['renamed', 'assigned'], # hide_events=['renamed', 'assigned'],
caches_path=None, caches_path=None,
# api_comments_url_fmt="{instance_url}/repos/{ru}/{rn}/issues/comments", # api_comments_url_fmt="{instance_url}/repos/{ru}/{rn}/issues/comments",
): ):
print(GiteaRepo.__doc__) print(GiteaRepo.__doc__)
if repo_url.endswith(".git"): if repo_url.endswith(".git"):
repo_url = repo_url[:-4] repo_url = repo_url[:-4]

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.
)

347
uninstall-minetestserver-git.py

@ -1,183 +1,194 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys
import platform import platform
CMD_REM = "#"
CMD_RM = "rm "
CMD_RMDIR = "rmdir "
if platform.system() == "Windows":
CMD_REM = "REM "
CMD_RM = "del "
CMD_RMDIR = "rd "
# profile_path = None def main():
# if 'HOME' in os.environ: CMD_REM = "#"
# profile_path = os.environ['HOME'] CMD_RM = "rm "
# elif 'USERPROFILE' in os.environ: CMD_RMDIR = "rmdir "
# profile_path = os.environ['USERPROFILE'] if platform.system() == "Windows":
# downloads_path = os.path.join(profile_path, "Downloads") CMD_REM = "REM "
# repo_path = os.path.join(downloads_path, "minetest") CMD_RM = "del "
# if not os.path.isdir(repo_path): CMD_RMDIR = "rd "
# repo_path = os.path.join(profile_path, "minetest")
# if not os.path.isdir(repo_path): # profile_path = None
# print("ERROR: Nothing done since there is no minetest sourcecode" # if 'HOME' in os.environ:
# " folder in " + downloads_path # profile_path = os.environ['HOME']
# + " (nor " + profile_path + ")") # elif 'USERPROFILE' in os.environ:
# exit(1) # profile_path = os.environ['USERPROFILE']
install_manifest_name = "install_manifest.txt" # downloads_path = os.path.join(profile_path, "Downloads")
# install_manifest_path = os.path.join(repo_path, install_manifest_name) # repo_path = os.path.join(downloads_path, "minetest")
# if not os.path.isfile(install_manifest_path): # if not os.path.isdir(repo_path):
# print("ERROR: nothing done since there is no " + # repo_path = os.path.join(profile_path, "minetest")
# install_manifest_name + " in '" + repo_path + # if not os.path.isdir(repo_path):
# "'. The file would only be present if you " + # print("ERROR: Nothing done since there is no minetest sourcecode"
# "installed minetest from sourcecode" + # " folder in " + downloads_path
# "(otherwise this uninstaller is not for you).") # + " (nor " + profile_path + ")")
# exit(2) # return 1
if not os.path.isfile(install_manifest_name): install_manifest_name = "install_manifest.txt"
print("ERROR: nothing done since there is no " + # install_manifest_path = os.path.join(repo_path, install_manifest_name)
install_manifest_name + " in the current " + # if not os.path.isfile(install_manifest_path):
"directory. You must run: ") # print("ERROR: nothing done since there is no " +
print(" sudo python3 "+os.path.abspath(__file__)) # install_manifest_name + " in '" + repo_path +
print("from the minetest sourcecode (repo) directory.") # "'. The file would only be present if you " +
exit(2) # "installed minetest from sourcecode" +
directories = [] # "(otherwise this uninstaller is not for you).")
print("Removing files...") # return 2
f_removed_count = 0 if not os.path.isfile(install_manifest_name):
f_skipped_count = 0 print("ERROR: nothing done since there is no " +
f_failed_count = 0 install_manifest_name + " in the current " +
retry_lines = [] "directory. You must run: ")
with open(install_manifest_name, 'r') as ins: print(" sudo python3 "+os.path.abspath(__file__))
original_line = True print("from the minetest sourcecode (repo) directory.")
while original_line: return 2
original_line = ins.readline() directories = []
if original_line: print("Removing files...")
line = original_line.rstrip() # remove trailing newline f_removed_count = 0
if len(line) > 0: f_skipped_count = 0
d_path = os.path.dirname(line) f_failed_count = 0
if d_path not in directories: retry_lines = []
if "minetest" in d_path: with open(install_manifest_name, 'r') as ins:
directories.append(d_path) original_line = True
# else must be a system directory like while original_line:
# /usr/local/share/applications original_line = ins.readline()
if os.path.isfile(line): if original_line:
os.remove(line) line = original_line.rstrip() # remove trailing newline
if len(line) > 0:
d_path = os.path.dirname(line)
if d_path not in directories:
if "minetest" in d_path:
directories.append(d_path)
# else must be a system directory like
# /usr/local/share/applications
if os.path.isfile(line): if os.path.isfile(line):
f_failed_count += 1 os.remove(line)
retry_lines.append(CMD_RM+'"'+line+'"') if os.path.isfile(line):
f_failed_count += 1
retry_lines.append(CMD_RM+'"'+line+'"')
else:
f_removed_count += 1
else: else:
f_removed_count += 1 f_skipped_count += 1
else:
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):
try:
for try_name in try_files:
try_path = os.path.join(d_path, try_name)
if os.path.isfile(try_path):
extra_files.append(try_path)
print('Removing known extra file: "' + try_path
+ '"')
try:
os.remove(try_path)
e_removed_count += 1
except Exception as e:
e_failed_count += 1
retry_lines.append(CMD_RM + '"' + try_path
+ '"')
print(str(e))
for try_name in try_dirs:
try_path = os.path.join(d_path, try_name)
if os.path.isdir(try_path):
extra_dirs.append(try_path)
print('Removing known extra folder: "' + try_path
+ '"')
try:
os.rmdir(try_path)
ed_removed_count += 1
except Exception as e:
ed_failed_count += 1
retry_lines.append(CMD_RMDIR+'"'+try_path+'"')
print(str(e))
os.rmdir(d_path)
except Exception as e:
print(str(e))
if os.path.isdir(d_path): if os.path.isdir(d_path):
d_failed_count += 1 try:
retry_lines.append(CMD_RMDIR+'"'+d_path+'"') for try_name in try_files:
try_path = os.path.join(d_path, try_name)
if os.path.isfile(try_path):
extra_files.append(try_path)
print('Removing known extra file: "' + try_path
+ '"')
try:
os.remove(try_path)
e_removed_count += 1
except Exception as e:
e_failed_count += 1
retry_lines.append(CMD_RM + '"' + try_path
+ '"')
print(str(e))
for try_name in try_dirs:
try_path = os.path.join(d_path, try_name)
if os.path.isdir(try_path):
extra_dirs.append(try_path)
print('Removing known extra folder: "' + try_path
+ '"')
try:
os.rmdir(try_path)
ed_removed_count += 1
except Exception as e:
ed_failed_count += 1
retry_lines.append(CMD_RMDIR+'"'+try_path+'"')
print(str(e))
os.rmdir(d_path)
except Exception as e:
print(str(e))
if os.path.isdir(d_path):
d_failed_count += 1
retry_lines.append(CMD_RMDIR+'"'+d_path+'"')
else:
d_removed_count += 1
else: else:
d_removed_count += 1 d_skipped_count += 1
else: print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
d_skipped_count += 1 " present:" + str(d_skipped_count) + "; failed:"
print("Removed " + str(d_removed_count) + " folder(s) (skipped not" + str(d_failed_count) + ")")
" present:" + str(d_skipped_count) + "; failed:" if e_failed_count > 0:
+ str(d_failed_count) + ")") print("(failed to remove " + e_failed_count + " known extra file(s)"
if e_failed_count > 0: " (will be shown under FAILURES below)")
print("(failed to remove " + e_failed_count + " known extra file(s)" if ed_failed_count > 0:
" (will be shown under FAILURES below)") print("(failed to remove " + ed_failed_count + " known extra"
if ed_failed_count > 0: " folder(s) (will be shown under FAILURES below)")
print("(failed to remove " + ed_failed_count + " known extra" print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
" folder(s) (will be shown under FAILURES below)") " present:" +
print("Removed " + str(d_removed_count) + " folder(s) (skipped not" str(d_skipped_count) + "; failed:" + str(d_failed_count) + ")")
" present:" +
str(d_skipped_count) + "; failed:" + str(d_failed_count) + ")")
if f_failed_count+d_failed_count+ed_failed_count <= 0: code = 0
print("") if f_failed_count+d_failed_count+ed_failed_count <= 0:
if f_removed_count+d_removed_count <= 0: print("")
print("Nothing to do (minetest+minetestserver has 0 known files" if f_removed_count+d_removed_count <= 0:
" on system--you apparently already uninstalled the local" print("Nothing to do (minetest+minetestserver has 0 known files"
" version that was installed using 'sudo make install')") " on system--you apparently already uninstalled the local"
" version that was installed using 'sudo make install')")
else:
print("OK [finished uninstalling all installed files]")
print("")
else: else:
print("OK [finished uninstalling all installed files]") print("")
print("") print("")
else: print(CMD_REM+"FAILURES:")
print("") for rl in retry_lines:
print("") print(rl)
print(CMD_REM+"FAILURES:") print("")
for rl in retry_lines: print("In case of any failures are counted above, "
print(rl) "try running this script with administrative privileges."
print("") "If any more remain, you may have to remove them manually.")
print("In case of any failures are counted above, " print("")
"try running this script with administrative privileges." print("")
"If any more remain, you may have to remove them manually.") code = 1
print("") if not ins.closed:
print("") print("ERROR: ins was not closed (this should never happen)--"
if not ins.closed: "closing manually...")
print("ERROR: ins was not closed (this should never happen)--" ins.close()
"closing manually...") code = 1
ins.close() 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())

221
utilities/extra/uninstall.py

@ -1,117 +1,126 @@
#!/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 "
rm_cmd = "DEL " if platform.system() == "Windows":
rmdir_cmd = "RD " rm_cmd = "DEL "
rem_cmd = "REM " rmdir_cmd = "RD "
profile_path1 = os.environ.get('HOME') rem_cmd = "REM "
profile_path = profile_path1 profile_path1 = os.environ.get('HOME')
profile_path2 = os.environ.get('USERPROFILE') profile_path = profile_path1
if profile_path2 is not None: profile_path2 = os.environ.get('USERPROFILE')
profile_path = profile_path2 if profile_path2 is not None:
if profile_path1 is not None: profile_path = profile_path2
print(rem_cmd + "WARNING: HOME is present, but USERPROFILE '" if profile_path1 is not None:
+ profile_path + "' is being used.") print(rem_cmd + "WARNING: HOME is present, but USERPROFILE '"
else: + profile_path + "' is being used.")
if profile_path1 is None: else:
doDie(rem_cmd + "ERROR: There is nothing to do since neither" if profile_path1 is None:
+ " HOME nor USERPROFILE is present.") return show_error(rem_cmd + "ERROR: There is nothing to do"
" since neither"
mnf_name = "install_manifest.txt" " HOME nor USERPROFILE is present.")
mnf_path = os.path.join(profile_path, mnf_name)
mnf_name = "install_manifest.txt"
unsorted_list = [] mnf_path = os.path.join(profile_path, mnf_name)
if not os.path.isfile(mnf_path): unsorted_list = []
doDie(rem_cmd + "Uninstall cannot continue since '" + mnf_path
+ "' is missing.") if not os.path.isfile(mnf_path):
return show_error(rem_cmd + "Uninstall cannot continue since '"
with open(mnf_path) as fp: + mnf_path + "' is missing.")
for cnt, line_original in enumerate(fp):
# print("Line {}: {}".format(cnt, line)) with open(mnf_path) as fp:
line = line_original.strip() for cnt, line_original in enumerate(fp):
if len(line) > 0: # print("Line {}: {}".format(cnt, line))
unsorted_list.append(line) line = line_original.strip()
if len(line) > 0:
if len(unsorted_list) < 1: unsorted_list.append(line)
doDie(rem_cmd + "ERROR: There are no files in the manifest '"
+ mnf_path + "'") if len(unsorted_list) < 1:
return show_error(rem_cmd + "ERROR: There are no files in the manifest"
# See https://stackoverflow.com/questions/4659524/\ " '"+ mnf_path + "'")
# how-to-sort-by-length-of-string-followed-by-alphabetical-order
sorted_list = sorted(unsorted_list, key=len, reverse=True) # See https://stackoverflow.com/questions/4659524/\
# reverse: descending # how-to-sort-by-length-of-string-followed-by-alphabetical-order
# or (also reverse): sorted_list = sorted(unsorted_list, key=len, reverse=True)
# the_list.sort(key=lambda item: (-len(item), item)) # reverse: descending
# or (also reverse):
print(rem_cmd + "Uninstalling...") # the_list.sort(key=lambda item: (-len(item), item))
not_removed_files = []
not_removed_dirs = [] print(rem_cmd + "Uninstalling...")
does_not_exist = [] not_removed_files = []
file_count = 0 not_removed_dirs = []
dir_count = 0 does_not_exist = []
for path in sorted_list: file_count = 0
if os.path.isfile(path): dir_count = 0
if path[0:1] == ".": for path in sorted_list:
if os.path.isfile(path):
if path[0:1] == ".":
print(rm_cmd + "\"" + path + "\"")
not_removed_files.append(path)
continue
try:
os.remove(path)
file_count += 1
except PermissionError:
not_removed_files.append(path)
elif os.path.isdir(path):
if path[0:1] == ".":
print(rmdir_cmd + "\"" + path + "\"")
not_removed_dirs.append(path)
continue
try:
os.rmdir(path)
dir_count += 1
except PermissionError:
not_removed_dirs.append(path)
else:
does_not_exist.append(path)
if len(does_not_exist) > 0:
if len(does_not_exist) == len(sorted_list):
return show_error(rem_cmd + 'The program is not installed such as'
' at "{}".'
''.format(sorted_list[-1]))
show_dot_warning = True
print(rem_cmd + "Uninstall is complete.")
print(rem_cmd + "- files: " + str(file_count))
print(rem_cmd + "- directories: " + str(dir_count))
print(rem_cmd + "- missing: " + len(does_not_exist))
if (len(not_removed_files) + len(not_removed_dirs)) > 0:
for path in not_removed_files:
if path[0:1] == ".":
if show_dot_warning:
print(rem_cmd + "Paths starting with '.' are not yet"
" implemented.")
show_dot_warning = False
print(rm_cmd + "\"" + path + "\"") print(rm_cmd + "\"" + path + "\"")
not_removed_files.append(path) for path in not_removed_dirs:
continue
try:
os.remove(path)
file_count += 1
except PermissionError:
not_removed_files.append(path)
elif os.path.isdir(path):
if path[0:1] == ".":
print(rmdir_cmd + "\"" + path + "\"") print(rmdir_cmd + "\"" + path + "\"")
not_removed_dirs.append(path) print(rem_cmd + "Deleting items above FAILED:")
continue print(" " + rem_cmd + "- files: " + str(not_removed_file_count))
try: print(" " + rem_cmd + "- directories: "
os.rmdir(path) + str(not_removed_dir_count))
dir_count += 1
except PermissionError: print("")
not_removed_dirs.append(path) print("")
else: return 0
does_not_exist.append(path)
if len(does_not_exist) > 0: if __name__ == "__main__":
if len(does_not_exist) == len(sorted_list): sys.exit(main())
doDie(" " + rem_cmd + " The program is not installed such as"
+ " at '" + sorted_list[-1] + "'.")
show_dot_warning = True
print(rem_cmd + "Uninstall is complete.")
print(rem_cmd + "- files: " + str(file_count))
print(rem_cmd + "- directories: " + str(dir_count))
print(rem_cmd + "- missing: " + len(does_not_exist))
if (len(not_removed_files) + len(not_removed_dirs)) > 0:
for path in not_removed_files:
if path[0:1] == ".":
if show_dot_warning:
print(rem_cmd + "Paths starting with '.' are not yet"
" implemented.")
show_dot_warning = False
print(rm_cmd + "\"" + path + "\"")
for path in not_removed_dirs:
print(rmdir_cmd + "\"" + path + "\"")
print(rem_cmd + "Deleting items above FAILED:")
print(" " + rem_cmd + "- files: " + str(not_removed_file_count))
print(" " + rem_cmd + "- directories: "
+ str(not_removed_dir_count))
print("")
print("")

309
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,155 +44,162 @@ 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"
tryLicSrc = os.path.join(myDir, licSrc) if not os.path.isfile(licSrc):
if not os.path.isfile(tryLicSrc): tryLicSrc = os.path.join(myDir, licSrc)
print("ERROR: missing " + licSrc) if not os.path.isfile(tryLicSrc):
exit(1) print("ERROR: missing " + licSrc)
else: return 1
licSrc = tryLicSrc else:
toMod = None licSrc = tryLicSrc
fromName = None toMod = None
toName = None fromName = None
extraArgCount = 0 toName = None
enableFill = False extraArgCount = 0
options = [] enableFill = False
for i in range(1, len(sys.argv)): options = []
if sys.argv[i] == "--fill": for i in range(1, len(sys.argv)):
extraArgCount += 1 if sys.argv[i] == "--fill":
enableFill = True extraArgCount += 1
else: enableFill = True
if (len(sys.argv[i]) >= 2) and (sys.argv[i][:2] == "--"): else:
usage() if (len(sys.argv[i]) >= 2) and (sys.argv[i][:2] == "--"):
customExit("Invalid option: " + sys.argv[i]) usage()
options.append(sys.argv[i]) return show_error("Invalid option: " + sys.argv[i],
if (len(options) != 1) and (len(options) != 3): code=2)
usage() options.append(sys.argv[i])
exit(1) if (len(options) != 1) and (len(options) != 3):
thisName = options[0] usage()
if os.path.isdir(thisName): return 3
if not enableFill: thisName = options[0]
print("") if os.path.isdir(thisName):
print("ERROR: A mod named " + thisName + " cannot be ") if not enableFill:
print("generated when the directory already exists.") print("")
print("") print("ERROR: A mod named " + thisName + " cannot be ")
exit(1) print("generated when the directory already exists.")
else: print("")
os.mkdir(thisName) return 4
if (len(options) == 3):
fromName = options[1]
toName = options[2]
delimI = toName.rfind(":")
if delimI > -1:
toMod = toName[:delimI]
if toMod.find(":") > -1:
usage()
customExit("Your modname contains too many colons.")
exit(1)
else: else:
toMod = "default" os.mkdir(thisName)
if (len(options) == 3):
mobAPI = None fromName = options[1]
if toMod is not None: toName = options[2]
if not os.path.isfile(os.path.join(thisName, "depends.txt")): delimI = toName.rfind(":")
dependsOut = open(os.path.join(thisName, "depends.txt"), 'w') if delimI > -1:
dependsOut.write(toMod+"\n") toMod = toName[:delimI]
dependsOut.close() if toMod.find(":") > -1:
if toMod.find("mob") > -1: usage()
mobAPI = toMod return show_error("Your modname contains too many colons.",
code=5)
if not os.path.isfile(os.path.join(thisName, "description.txt")): else:
descOut = open(os.path.join(thisName, "description.txt"), 'w') toMod = "default"
descOut.write("\n")
descOut.close() mobAPI = None
if toMod is not None:
if not os.path.isfile(os.path.join(thisName, "mod.conf")): if not os.path.isfile(os.path.join(thisName, "depends.txt")):
confOut = open(os.path.join(thisName, "mod.conf"), 'w') dependsOut = open(os.path.join(thisName, "depends.txt"), 'w')
confOut.write("name = "+thisName+"\n") dependsOut.write(toMod+"\n")
confOut.close() dependsOut.close()
if toMod.find("mob") > -1:
if not os.path.isfile(os.path.join(thisName, "readme.md")): mobAPI = toMod
readmeOut = open(os.path.join(thisName, "readme.md"), 'w')
readmeLine1 = thisName + " Minetest Mod" if not os.path.isfile(os.path.join(thisName, "description.txt")):
readmeOut.write(readmeLine1+"\n") descOut = open(os.path.join(thisName, "description.txt"), 'w')
readmeOut.write("="*len(readmeLine1)+"\n") descOut.write("\n")
readmeOut.write("See description.txt\n") descOut.close()
readmeOut.write("\n")
readmeOut.write("## License\n") if not os.path.isfile(os.path.join(thisName, "mod.conf")):
readmeOut.write("See " + licDestName + "\n") confOut = open(os.path.join(thisName, "mod.conf"), 'w')
readmeOut.close() confOut.write("name = "+thisName+"\n")
confOut.close()
licDest = os.path.join(thisName, licDestName)
if not os.path.isfile(licDest): if not os.path.isfile(os.path.join(thisName, "readme.md")):
shutil.copyfile(licSrc, licDest) readmeOut = open(os.path.join(thisName, "readme.md"), 'w')
luaOut = None readmeLine1 = thisName + " Minetest Mod"
if not os.path.isfile(os.path.join(thisName, "init.lua")): readmeOut.write(readmeLine1+"\n")
luaOut = open(os.path.join(thisName, "init.lua"), 'w') readmeOut.write("="*len(readmeLine1)+"\n")
# luaOut.write("#!/usr/bin/env lua\n") readmeOut.write("See description.txt\n")
luaOut.write("-- " + sys.argv[0] + " (EnlivenMinetest) generated\n") readmeOut.write("\n")
luaOut.write("-- the original version of this file.\n") readmeOut.write("## License\n")
fromMod = None # not required readmeOut.write("See " + licDestName + "\n")
step0 = "" readmeOut.close()
if (len(options) == 3): licDest = os.path.join(thisName, licDestName)
delimI = fromName.find(":") if not os.path.isfile(licDest):
if delimI > -1: shutil.copyfile(licSrc, licDest)
fromMod = fromName[:delimI] luaOut = None
if not os.path.isfile(os.path.join(thisName, "init.lua")):
luaOut = open(os.path.join(thisName, "init.lua"), 'w')
# luaOut.write("#!/usr/bin/env lua\n")
luaOut.write("-- " + sys.argv[0] + " (EnlivenMinetest) generated\n")
luaOut.write("-- the original version of this file.\n")
fromMod = None # not required
step0 = ""
if (len(options) == 3):
delimI = fromName.find(":")
if delimI > -1:
fromMod = fromName[:delimI]
else:
fromMod = ""
apiLinePrefix = ""
mobLinePrefix = ""
if luaOut is not None:
if mobAPI is not None:
apiLinePrefix = "-- "
else:
mobLinePrefix = "-- "
luaOut.write("-- If your mobs API doesn't contain the\n")
luaOut.write("-- word 'mobs', your alias method is not\n")
luaOut.write("-- known. In that case, you may have to\n")
luaOut.write("-- change minetest.register_alias to your\n")
luaOut.write("-- mob API's (if your alias is for a mob).\n")
luaOut.write(mobLinePrefix + mobAPI + ':alias_mob("'
+ fromName + '", "' + toName + '")' + "\n")
luaOut.write(apiLinePrefix + 'minetest.register_alias("'
+ fromName + '", "' + toName + '")' + "\n")
else: else:
fromMod = "" step0 = "Add your code init.lua."
apiLinePrefix = ""
mobLinePrefix = ""
if luaOut is not None: if luaOut is not None:
if mobAPI is not None: luaOut.write("\n")
apiLinePrefix = "-- " luaOut.close()
else:
mobLinePrefix = "-- " print("")
luaOut.write("-- If your mobs API doesn't contain the\n") print("")
luaOut.write("-- word 'mobs', your alias method is not\n") print(step0)
luaOut.write("-- known. In that case, you may have to\n") print("The new mod is the " + thisName + " folder. Remember to:")
luaOut.write("-- change minetest.register_alias to your\n") ender = "."
luaOut.write("-- mob API's (if your alias is for a mob).\n") if (toMod is not None) and (len(toMod) > 0):
luaOut.write(mobLinePrefix + mobAPI + ':alias_mob("' ender = ""
+ fromName + '", "' + toName + '")' + "\n") print("1. Edit depends.txt if your mod requires some mod" + ender)
luaOut.write(apiLinePrefix + 'minetest.register_alias("' if (toMod is not None) and (len(toMod) > 0):
+ fromName + '", "' + toName + '")' + "\n") print(" other than '" + toMod + "'.")
else: print("")
step0 = "Add your code init.lua." print("2. Edit description.txt to contain a brief description of")
if luaOut is not None: print(" your mod (less than 100 characters).")
luaOut.write("\n") print("")
luaOut.close() 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("") print(" " + licSrc)
print("") print(" should be the " + licDesc + ".")
print(step0) print(
print("The new mod is the " + thisName + " folder. Remember to:") ''' The MIT License is good for Minetest mods so they can be used
ender = "." most widely such as on app stores where replacing the program as per
if (toMod is not None) and (len(toMod) > 0): the GPL v3 is not compliant with mobile OS security--the license of
ender = "" most Minetest releases is the MIT License). Some joke licenses exist
print("1. Edit depends.txt if your mod requires some mod" + ender) but DO NOT protect your work in cases where they explicitly allow
if (toMod is not None) and (len(toMod) > 0): others to copy your work and claim it as their own especially if they
print(" other than '" + toMod + "'.") modify it in any way. They would just be doing what you said they
print("") could do!
print("2. Edit description.txt to contain a brief description of") '''
print(" your mod (less than 100 characters).") )
print("") print("")
print("3. Edit LICENSE.txt and add the year and the name of all ") print("")
print(" authors, and change the license if desired (The included") return 0
print(" " + licSrc)
print(" should be the " + licDesc + ".")
print( if __name__ == "__main__":
''' The MIT License is good for Minetest mods so they can be used sys.exit(main())
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
most Minetest releases is the MIT License). Some joke licenses exist
but DO NOT protect your work in cases where they explicitly allow
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
could do!
'''
)
print("")
print("")

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())

35
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 v not in news: if argCount < 2:
print(v) 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:
print(v)
return 0
if __name__ == "__main__":
sys.exit(main())

Loading…
Cancel
Save