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 2022-07-30 13:38:49 -04:00
parent ee1986ee4e
commit e170a2b123
27 changed files with 1522 additions and 1159 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ linux-minetest-kit.zip
/docker/lmk-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
/debug.txt

View File

@ -1,13 +1,15 @@
#!/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 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:
find -type f -name "*.ogg" -exec ls -lh {} \;
find -type f -exec ls -lh {} \;
find -type f -name "*.ogg" -exec ls -lh {} \\;
find -type f -exec ls -lh {} \\;
Usage:
./trimpatchstats.py <filename>
@ -16,15 +18,16 @@ import sys
import os
import json
def error(msg):
sys.stderr.write("{}\n".format(msg))
sys.stderr.flush()
def echo0(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def usage():
error("")
error("trimpatchstats.py")
error("-----------------")
error(__doc__)
echo0("")
echo0("trimpatchstats.py")
echo0("-----------------")
echo0(__doc__)
def splitFirst(line, delimiter):
@ -196,6 +199,7 @@ class LSFileInfo:
def __str__(self):
return json.dumps(self.to_dict())
def getFileNumber(path, num):
'''
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:
print("Error: \"{}\" contained no filenames."
"".format(patchedListPath))
exit(1)
return 1
tryFilePath = os.path.join(targetDirPath, fid['name'])
if not os.path.isfile(tryFilePath):
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 parallel to that."
"".format(tryFilePath, fid['name'], patchedPath))
exit(1)
return 2
error("* analyzing \"{}\"".format(patchedListPath))
echo0("* analyzing \"{}\"".format(patchedListPath))
patchedFIs = []
rawNames = []
with open(patchedListPath, 'r') as ins:
@ -279,9 +283,9 @@ def printOnlyPatched(baseListPath):
fid = parse_ls(line)
rawNames.append(fid['name'])
# fill_file_dict_path(fid, targetDirPath)
# error(fid)
# echo0(fid)
error("* analyzing \"{}\"".format(baseListPath))
echo0("* analyzing \"{}\"".format(baseListPath))
allCount = 0
matchCount = 0
with open(baseListPath, 'r') as ins:
@ -300,13 +304,19 @@ def printOnlyPatched(baseListPath):
if fid['name'] in rawNames:
print(line)
matchCount += 1
error("{} of {} in {} were also in {}"
echo0("{} of {} in {} were also in {}"
"".format(matchCount, allCount, baseListPath,
patchedListPath))
return 0
if __name__ == "__main__":
def main():
if len(sys.argv) < 2:
usage()
error("Error: You are missing the required list filename argument.\n")
exit(1)
printOnlyPatched(sys.argv[1])
echo0("Error: You are missing the required list filename argument.\n")
return 1
return printOnlyPatched(sys.argv[1])
if __name__ == "__main__":
sys.exit(main())

View File

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

View File

@ -3,8 +3,11 @@ from __future__ import print_function
import sys
import os
from pyenliven import (
echo0,
)
from headcompare import (
error,
compareBranch,
defaultVirtualReposDir,
minetestPath,
@ -15,45 +18,48 @@ from headcompare import (
me = os.path.basename(__file__)
def usage():
error("Usage:")
echo0("Usage:")
sys.stderr.write("Specify a branch")
parent = "Bucket_Game-base"
if os.path.isdir(parent):
error(" from Bucket_Game-base:")
echo0(" from Bucket_Game-base:")
for sub in os.listdir(parent):
subPath = os.path.join(parent, sub)
if sub.startswith("."):
continue
if os.path.isdir(subPath):
error(subPath)
echo0(subPath)
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():
global defaultGamePath
defaultGamePath = None
if len(sys.argv) < 2:
usage()
error("Error: You must provide a branch name.\n")
exit(1)
echo0("Error: You must provide a branch name.\n")
return 1
if len(sys.argv) > 3:
usage()
error("Error: There are too many arguments: {}.\n"
echo0("Error: There are too many arguments: {}.\n"
"".format(sys.argv))
exit(1)
return 1
if len(sys.argv) > 2:
defaultGamePath = sys.argv[2]
results = compareBranch(sys.argv[1], gamePath=defaultGamePath,
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"
" release package.")
return 0
if __name__ == "__main__":
main()
sys.exit(main())

View File

@ -9,46 +9,48 @@ import os
import configparser
from pyenliven import (
error,
echo0,
getSGPath,
profile,
MODS_STOPGAP_DIR,
)
gamespec = {}
gamespec['remove_mods'] = [
"coderblocks", # includes lmb blocks; no recipes
"facade", # no recipes
"placecraft", # interferes with eating
"more_chests", # See https://github.com/poikilos/EnlivenMinetest/issues/446
"emeralds", # See https://github.com/poikilos/EnlivenMinetest/issues/497
"facade", # no recipes
"placecraft", # interferes with eating
"more_chests", # See https://github.com/poikilos/EnlivenMinetest/issues/446
"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)
# TODO: more are at https://github.com/poikilos/EnlivenMinetest/issues/310
]
gamespec['local_mods_paths'] = []
gamespec['local_mods_paths'].append("mods_stopgap")
# ^ See also MODS_STOPGAP_DIR (full path) in pyenliven
gamespec['add_mods'] = [
# {'repo':"https://github.com/poikilos/homedecor_ua"},
# {'repo': "https://github.com/poikilos/homedecor_ua"},
{'name': "animal_materials_legacy"},
{'repo':"https://github.com/minetest-mods/ccompass.git"},
{'repo':"https://github.com/octacian/chat3.git"},
{'repo':"https://github.com/poikilos/compassgps.git"},
{'repo': "https://github.com/minetest-mods/ccompass.git"},
{'repo': "https://github.com/octacian/chat3.git"},
{'repo': "https://github.com/poikilos/compassgps.git"},
{'name': "elk_legacy"},
{'repo':"https://github.com/MinetestForFun/fishing.git"},
{'repo': "https://github.com/MinetestForFun/fishing.git"},
{'name': "glooptest_missing"},
{'repo':"https://github.com/minetest-mods/item_drop.git"},
{'repo':"https://github.com/poikilos/metatools.git"},
{'repo': "https://github.com/minetest-mods/item_drop.git"},
{'repo': "https://github.com/poikilos/metatools.git"},
{'name': "nftools_legacy"},
{'name': "glooptest_missing"},
{'repo':"https://github.com/poikilos/slimenodes.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_arrows.git"}, # Can utilize mesecons, mesecons_button
{'repo':"https://github.com/mt-mods/biome_lib.git"},
{'repo': "https://github.com/poikilos/slimenodes.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_arrows.git"}, # Can utilize mesecons, mesecons_button
{'repo': "https://github.com/mt-mods/biome_lib.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"},
]
@ -164,14 +166,15 @@ WARNINGS:
'''
"""
warnings = []
valid_bases = ['Bucket_Game', "bucket_ game"]
valid_bases = ['Bucket_Game', "bucket_game"]
def main():
for warning in warnings:
error(warning)
echo0(warning)
tryGameDir = os.getcwd()
error('* examining "{}"'.format(tryGameDir))
echo0('* examining "{}"'.format(tryGameDir))
gameConfName = "game.conf"
gameConfPath = os.path.join(tryGameDir, gameConfName)
if not os.path.isfile(gameConfPath):
@ -185,7 +188,7 @@ def main():
config.read_string('[top]\n' + ins.read())
# ^ insert a section since ConfigParser requires sections.
gameName = config['top'].get("name")
error(' * detected {} from {}'
echo0(' * detected "{}" from "{}"'
''.format(gameName, gameConfName))
if gameName not in valid_bases:
raise ValueError(
@ -200,8 +203,10 @@ def main():
# ^ TODO: Get this from mtanalyze?
targetGames = os.path.join(targetMT, "games")
target = os.path.join(targetGames, "ENLIVEN")
centerOfTheSunTarget =
centerOfTheSunTarget = None
raise NotImplementedError("pyenliven build")
return 0
if __name__ == "__main__":
main()
sys.exit(main())

257
deploy.py
View File

@ -1,117 +1,16 @@
#!/usr/bin/env python
import os
import sys
import shutil
from forwardfilesync import *
# import filever
try:
input = raw_input
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"
from pyenliven import (
echo0,
)
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")
if sys.version_info.major >= 3:
pass
else:
shutil.copyfile(server_devel_minetest_conf_path,
server_minetest_conf_path)
input = raw_input
def rm_sub(bad_sub):
@ -120,22 +19,132 @@ def rm_sub(bad_sub):
os.remove(bad_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"])
def main():
warnings = list()
# 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("")
echo0("This script is NOT YET IMPLEMENTED")
print("")
if len(warnings) > 0:
print(str(len(warnings)) + " warning(s):")
for warning in warnings:
print(warning)
else:
print("0 warnings.")
print("\n")
input("press enter to exit...")
# TODO: Scrape https://minetest.kitsunemimi.pw/builds/ (NOTE: stable is
# always "https://minetest.kitsunemimi.pw/builds/win64/"
# "minetest-0.4.15-win64.7z")
echo0("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"
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())

View File

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

View File

@ -24,6 +24,7 @@ if platform.system() == "Windows":
CMD_CP = "COPY"
CMD_MKDIR = "MD"
def path_join_all(names):
result = names[0]
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
and subdirectories recursively that are not present on src.
Keyword arguments:
dot_hidden -- Operate on files and directories even if they are
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
recursively.
Keyword arguments:
do_trim -- Delete files and directories from dst that are not on
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))
pass
USAGE = '''
Syntax:
forwardfilesync.py <source> <destination> [options]
@ -131,18 +133,20 @@ forwardfilesync.py <source> <destination> [options]
'''
def usage():
print(USAGE)
def main():
flags = {}
flags["hidden"] = False
flags["delete"] = False
if len(sys.argv) < 3:
usage()
print("Error: You must provide at least a source and destination.")
exit(1)
return 1
src = sys.argv[1]
dst = sys.argv[2]
@ -155,17 +159,17 @@ def main():
" since it doesn't start with \"--\". If it is part"
" of a path with spaces, put the path in quotes."
"".format(sys.argv[argI]))
exit(1)
return 1
name = arg[2:]
if name not in flags:
usage()
print("Error: There is no option \"{}\". If it is part of a"
" path with spaces, put the path in quotes."
"".format(sys.argv[argI]))
exit(1)
return 1
flags[name] = True
print(CMD_COMMENT + "Using options:")
for k,v in flags.items():
for k, v in flags.items():
print(CMD_COMMENT + "{}: {}".format(k, v))
update_tree(
@ -175,8 +179,8 @@ def main():
dot_hidden=flags["hidden"] is True,
)
print(CMD_COMMENT + "Done.")
return 0
if __name__ == "__main__":
main()
sys.exit(main())

View File

@ -1,144 +1,154 @@
#!/usr/bin/env python3
import os
import shutil
import sys
actions = {"-- Up-to-date: ": "move", "-- Installing: ": "move"}
changes = {
"/usr/local/./": "/usr/local/share/minetest/"
}
count = 0
command_count = 0
in_path = "bad_mt5_make_install_output.txt"
outs_path = os.path.dirname(os.path.realpath(__file__))
out_path = os.path.join(outs_path, "install-fix-minetest5-share.sh")
file_commands = []
rmd_cmds = []
mkdir_commands = []
made_dirs = []
mtg_mod_dirs = ["games//minetest_game/mods", "games/minetest_game/mods"]
with open(in_path) as ins:
with open(out_path, 'w') as outs:
outs.write("#!/bin/sh\n")
count += 1
for line_orig in ins:
line = line_orig.strip()
action = None
old_path = None
for k, try_action in actions.items():
if line.startswith(k):
action = try_action
old_path = line[len(k):].strip()
break
if action == "move":
found = None
for old, new in changes.items():
if old_path.startswith(old):
found = old
new_path = new + old_path[len(old):]
if not os.path.exists(old_path):
if not os.path.exists(new_path):
# raise ValueError(
# "The program is not installed"
# " (missing '{}')".format(old_path)
# )
outs.write(
'# WARNING: expected "{}" (there is'
' no destination "{}" either)'
''.format(old_path, new_path)
)
else:
outs.write(
'# 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)
# 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/
# ./games//minetest_game/mods':
# Directory not empty
# rmdir: failed to remove '/usr/local/
# ./games//minetest_game':
# Directory not empty
# due to /usr/local/./games//
# minetest_game/mods/game_commands:
orphan_mods = ["game_commands"]
removed_orphan_mods = []
for mod_rel in orphan_mods:
for mtg_rel in mtg_mod_dirs:
f_rel = found + mtg_rel
# such as ("/usr/local/./"
# + "games//minetest_game/mods")
if old_path.startswith(f_rel):
# if mod_rel not in
# removed_orphan_mods:
try_path = (found + mtg_rel
+ "/" + mod_rel)
if os.path.isdir(try_path):
cmd = (
'rmdir "{}"'.format(
try_path
)
)
# queue for last stage:
if cmd not in rmd_cmds:
rmd_cmds.append(cmd)
# removed_orphan_mods.
# append(mod_rel)
break
cmd = 'rmdir "{}"'.format(old_path)
rmd_cmds.append(cmd) # AFTER everything
def main():
count = 0
command_count = 0
in_path = "bad_mt5_make_install_output.txt"
outs_path = os.path.dirname(os.path.realpath(__file__))
out_path = os.path.join(outs_path, "install-fix-minetest5-share.sh")
file_commands = []
rmd_cmds = []
mkdir_commands = []
made_dirs = []
mtg_mod_dirs = ["games//minetest_game/mods", "games/minetest_game/mods"]
with open(in_path) as ins:
with open(out_path, 'w') as outs:
outs.write("#!/bin/sh\n")
count += 1
for line_orig in ins:
line = line_orig.strip()
action = None
old_path = None
for k, try_action in actions.items():
if line.startswith(k):
action = try_action
old_path = line[len(k):].strip()
break
if found is None:
outs.write("# WARNING: The destination path is"
" unknown: ")
outs.write('# mv "{}" "{}"'.format(old_path,
old_path))
else:
outs.write("# " + line + "\n")
count += 1
for cmd in sorted(mkdir_commands, key=len):
outs.write(cmd + "\n")
count += 1
command_count += 1
for cmd in file_commands:
outs.write(cmd + "\n")
count += 1
command_count += 1
for cmd in sorted(rmd_cmds, key=len, reverse=True):
outs.write(cmd + "\n")
count += 1
command_count += 1
if action == "move":
found = None
for old, new in changes.items():
if old_path.startswith(old):
found = old
new_path = new + old_path[len(old):]
if not os.path.exists(old_path):
if not os.path.exists(new_path):
# raise ValueError(
# "The program is not installed"
# " (missing '{}')".format(old_path)
# )
outs.write(
'# WARNING: expected "{}" (there is'
' no destination "{}" either)'
''.format(old_path, new_path)
)
else:
outs.write(
'# 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)
# 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:
print('Added {} line(s) to "{}" (including {} command(s))'
''.format(count, out_path, command_count))
# rmdir: failed to remove '/usr/local/
# ./games//minetest_game/mods':
# Directory not empty
# rmdir: failed to remove '/usr/local/
# ./games//minetest_game':
# Directory not empty
# due to /usr/local/./games//
# minetest_game/mods/game_commands:
orphan_mods = ["game_commands"]
removed_orphan_mods = []
for mod_rel in orphan_mods:
for mtg_rel in mtg_mod_dirs:
f_rel = found + mtg_rel
# such as ("/usr/local/./"
# + "games//minetest_game/mods")
if old_path.startswith(f_rel):
# if mod_rel not in
# removed_orphan_mods:
try_path = (found + mtg_rel
+ "/" + mod_rel)
if os.path.isdir(try_path):
cmd = (
'rmdir "{}"'.format(
try_path
)
)
# queue for last stage:
if cmd not in rmd_cmds:
rmd_cmds.append(cmd)
# removed_orphan_mods.
# append(mod_rel)
break
cmd = 'rmdir "{}"'.format(old_path)
rmd_cmds.append(cmd) # AFTER everything
break
if found is None:
outs.write("# WARNING: The destination path is"
" unknown: ")
outs.write('# mv "{}" "{}"'.format(old_path,
old_path))
else:
outs.write("# " + line + "\n")
count += 1
for cmd in sorted(mkdir_commands, key=len):
outs.write(cmd + "\n")
count += 1
command_count += 1
for cmd in file_commands:
outs.write(cmd + "\n")
count += 1
command_count += 1
for cmd in sorted(rmd_cmds, key=len, reverse=True):
outs.write(cmd + "\n")
count += 1
command_count += 1
print('Added {} line(s) to "{}" (including {} command(s))'
''.format(count, out_path, command_count))
return 0
if __name__ == "__main__":
sys.exit(main())

View File

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

View File

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

View File

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

200
mtsenliven.py Normal file → Executable file
View File

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

View File

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

103
pyenliven/__init__.py Normal file
View File

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

View File

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

View File

@ -1,4 +1,4 @@
#!/usr/bin/env
#!/usr/bin/env python3
class Repo:
'''
WARNING: The real Repo class is in enliven.py
@ -6,6 +6,7 @@ class Repo:
print(__doc__)
pass
class GiteaRepo(Repo):
'''
This class is deprecated since the "options" sequential argument
@ -28,7 +29,7 @@ class GiteaRepo(Repo):
# hide_events=['renamed', 'assigned'],
caches_path=None,
# api_comments_url_fmt="{instance_url}/repos/{ru}/{rn}/issues/comments",
):
):
print(GiteaRepo.__doc__)
if repo_url.endswith(".git"):
repo_url = repo_url[:-4]

77
setup.py Normal file
View File

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

View File

@ -1,183 +1,194 @@
#!/usr/bin/env python3
import os
import sys
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
# if 'HOME' in os.environ:
# profile_path = os.environ['HOME']
# elif 'USERPROFILE' in os.environ:
# profile_path = os.environ['USERPROFILE']
# downloads_path = os.path.join(profile_path, "Downloads")
# repo_path = os.path.join(downloads_path, "minetest")
# if not os.path.isdir(repo_path):
# repo_path = os.path.join(profile_path, "minetest")
# if not os.path.isdir(repo_path):
# print("ERROR: Nothing done since there is no minetest sourcecode"
# " folder in " + downloads_path
# + " (nor " + profile_path + ")")
# exit(1)
install_manifest_name = "install_manifest.txt"
# install_manifest_path = os.path.join(repo_path, install_manifest_name)
# if not os.path.isfile(install_manifest_path):
# print("ERROR: nothing done since there is no " +
# install_manifest_name + " in '" + repo_path +
# "'. The file would only be present if you " +
# "installed minetest from sourcecode" +
# "(otherwise this uninstaller is not for you).")
# exit(2)
if not os.path.isfile(install_manifest_name):
print("ERROR: nothing done since there is no " +
install_manifest_name + " in the current " +
"directory. You must run: ")
print(" sudo python3 "+os.path.abspath(__file__))
print("from the minetest sourcecode (repo) directory.")
exit(2)
directories = []
print("Removing files...")
f_removed_count = 0
f_skipped_count = 0
f_failed_count = 0
retry_lines = []
with open(install_manifest_name, 'r') as ins:
original_line = True
while original_line:
original_line = ins.readline()
if original_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):
os.remove(line)
def main():
CMD_REM = "#"
CMD_RM = "rm "
CMD_RMDIR = "rmdir "
if platform.system() == "Windows":
CMD_REM = "REM "
CMD_RM = "del "
CMD_RMDIR = "rd "
# profile_path = None
# if 'HOME' in os.environ:
# profile_path = os.environ['HOME']
# elif 'USERPROFILE' in os.environ:
# profile_path = os.environ['USERPROFILE']
# downloads_path = os.path.join(profile_path, "Downloads")
# repo_path = os.path.join(downloads_path, "minetest")
# if not os.path.isdir(repo_path):
# repo_path = os.path.join(profile_path, "minetest")
# if not os.path.isdir(repo_path):
# print("ERROR: Nothing done since there is no minetest sourcecode"
# " folder in " + downloads_path
# + " (nor " + profile_path + ")")
# return 1
install_manifest_name = "install_manifest.txt"
# install_manifest_path = os.path.join(repo_path, install_manifest_name)
# if not os.path.isfile(install_manifest_path):
# print("ERROR: nothing done since there is no " +
# install_manifest_name + " in '" + repo_path +
# "'. The file would only be present if you " +
# "installed minetest from sourcecode" +
# "(otherwise this uninstaller is not for you).")
# return 2
if not os.path.isfile(install_manifest_name):
print("ERROR: nothing done since there is no " +
install_manifest_name + " in the current " +
"directory. You must run: ")
print(" sudo python3 "+os.path.abspath(__file__))
print("from the minetest sourcecode (repo) directory.")
return 2
directories = []
print("Removing files...")
f_removed_count = 0
f_skipped_count = 0
f_failed_count = 0
retry_lines = []
with open(install_manifest_name, 'r') as ins:
original_line = True
while original_line:
original_line = ins.readline()
if original_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):
f_failed_count += 1
retry_lines.append(CMD_RM+'"'+line+'"')
os.remove(line)
if os.path.isfile(line):
f_failed_count += 1
retry_lines.append(CMD_RM+'"'+line+'"')
else:
f_removed_count += 1
else:
f_removed_count += 1
else:
f_skipped_count += 1
f_skipped_count += 1
print("Removed " + str(f_removed_count) + " file(s) (skipped not"
" present:" + str(f_skipped_count) + "; failed:"
+ str(f_failed_count) + ")")
print("Removed " + str(f_removed_count) + " file(s) (skipped not"
" present:" + str(f_skipped_count) + "; failed:"
+ str(f_failed_count) + ")")
# NOTE: the next line makes ASCENDING (by len) list of TUPLES (name,len)
sorted_directories = [
(x, len(x)) for x in sorted(directories, key=len)
]
# NOTE: the next line makes ASCENDING (by len) list of TUPLES (name,len)
sorted_directories = [
(x, len(x)) for x in sorted(directories, key=len)
]
print("Removing folders...")
# NOTE: they are sorted ASCENDING so start at end:
d_removed_count = 0
d_skipped_count = 0
d_failed_count = 0
print("Removing folders...")
# NOTE: they are sorted ASCENDING so start at end:
d_removed_count = 0
d_skipped_count = 0
d_failed_count = 0
# still leaves:
# /usr/local/share/minetest/games/minetest_game/mods
# /usr/local/share/minetest/textures/base/pack/:
# down_arrow.png left_arrow.png right_arrow.png up_arrow.png
# /usr/local/share/minetest/games/minimal/mods
# so:
try_files = ["depends.txt", "down_arrow.png", "left_arrow.png",
"right_arrow.png", "up_arrow.png"]
try_dirs = ["mods"]
# still leaves:
# /usr/local/share/minetest/games/minetest_game/mods
# /usr/local/share/minetest/textures/base/pack/:
# down_arrow.png left_arrow.png right_arrow.png up_arrow.png
# /usr/local/share/minetest/games/minimal/mods
# so:
try_files = ["depends.txt", "down_arrow.png", "left_arrow.png",
"right_arrow.png", "up_arrow.png"]
try_dirs = ["mods"]
extra_dirs = []
ed_failed_count = 0
ed_removed_count = 0
extra_files = []
e_failed_count = 0
e_removed_count = 0
for i in reversed(range(len(sorted_directories))):
d_path = sorted_directories[i][0]
# for d in reversed(sorted_directories):
# d_path = d[0]
# 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))
extra_dirs = []
ed_failed_count = 0
ed_removed_count = 0
extra_files = []
e_failed_count = 0
e_removed_count = 0
for i in reversed(range(len(sorted_directories))):
d_path = sorted_directories[i][0]
# for d in reversed(sorted_directories):
# d_path = d[0]
# print("checking "+str(d_path))
if os.path.isdir(d_path):
d_failed_count += 1
retry_lines.append(CMD_RMDIR+'"'+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):
d_failed_count += 1
retry_lines.append(CMD_RMDIR+'"'+d_path+'"')
else:
d_removed_count += 1
else:
d_removed_count += 1
else:
d_skipped_count += 1
print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
" present:" + str(d_skipped_count) + "; failed:"
+ str(d_failed_count) + ")")
if e_failed_count > 0:
print("(failed to remove " + e_failed_count + " known extra file(s)"
" (will be shown under FAILURES below)")
if ed_failed_count > 0:
print("(failed to remove " + ed_failed_count + " known extra"
" folder(s) (will be shown under FAILURES below)")
print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
" present:" +
str(d_skipped_count) + "; failed:" + str(d_failed_count) + ")")
d_skipped_count += 1
print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
" present:" + str(d_skipped_count) + "; failed:"
+ str(d_failed_count) + ")")
if e_failed_count > 0:
print("(failed to remove " + e_failed_count + " known extra file(s)"
" (will be shown under FAILURES below)")
if ed_failed_count > 0:
print("(failed to remove " + ed_failed_count + " known extra"
" folder(s) (will be shown under FAILURES below)")
print("Removed " + str(d_removed_count) + " folder(s) (skipped not"
" present:" +
str(d_skipped_count) + "; failed:" + str(d_failed_count) + ")")
if f_failed_count+d_failed_count+ed_failed_count <= 0:
print("")
if f_removed_count+d_removed_count <= 0:
print("Nothing to do (minetest+minetestserver has 0 known files"
" on system--you apparently already uninstalled the local"
" version that was installed using 'sudo make install')")
code = 0
if f_failed_count+d_failed_count+ed_failed_count <= 0:
print("")
if f_removed_count+d_removed_count <= 0:
print("Nothing to do (minetest+minetestserver has 0 known files"
" 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:
print("OK [finished uninstalling all installed files]")
print("")
else:
print("")
print("")
print(CMD_REM+"FAILURES:")
for rl in retry_lines:
print(rl)
print("")
print("In case of any failures are counted above, "
"try running this script with administrative privileges."
"If any more remain, you may have to remove them manually.")
print("")
print("")
if not ins.closed:
print("ERROR: ins was not closed (this should never happen)--"
"closing manually...")
ins.close()
print("")
print("")
print(CMD_REM+"FAILURES:")
for rl in retry_lines:
print(rl)
print("")
print("In case of any failures are counted above, "
"try running this script with administrative privileges."
"If any more remain, you may have to remove them manually.")
print("")
print("")
code = 1
if not ins.closed:
print("ERROR: ins was not closed (this should never happen)--"
"closing manually...")
ins.close()
code = 1
return code
if __name__ == "__main__":
sys.exit(main())

View File

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

View File

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

View File

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

View File

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

View File

@ -7,13 +7,13 @@ myPath = os.path.realpath(__file__)
myDir = os.path.dirname(myPath)
def customExit(msg, code=1):
def show_error(msg, code=1):
print("")
print("ERROR:")
print(msg)
print("")
print("")
exit(code)
return code
def usage():
@ -44,155 +44,162 @@ def usage():
print("")
licSrc = "example_license.txt"
licDestName = "LICENSE.txt"
licDesc = "MIT License"
if not os.path.isfile(licSrc):
tryLicSrc = os.path.join(myDir, licSrc)
if not os.path.isfile(tryLicSrc):
print("ERROR: missing " + licSrc)
exit(1)
else:
licSrc = tryLicSrc
toMod = None
fromName = None
toName = None
extraArgCount = 0
enableFill = False
options = []
for i in range(1, len(sys.argv)):
if sys.argv[i] == "--fill":
extraArgCount += 1
enableFill = True
else:
if (len(sys.argv[i]) >= 2) and (sys.argv[i][:2] == "--"):
usage()
customExit("Invalid option: " + sys.argv[i])
options.append(sys.argv[i])
if (len(options) != 1) and (len(options) != 3):
usage()
exit(1)
thisName = options[0]
if os.path.isdir(thisName):
if not enableFill:
print("")
print("ERROR: A mod named " + thisName + " cannot be ")
print("generated when the directory already exists.")
print("")
exit(1)
else:
os.mkdir(thisName)
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:
toMod = "default"
mobAPI = None
if toMod is not None:
if not os.path.isfile(os.path.join(thisName, "depends.txt")):
dependsOut = open(os.path.join(thisName, "depends.txt"), 'w')
dependsOut.write(toMod+"\n")
dependsOut.close()
if toMod.find("mob") > -1:
mobAPI = toMod
if not os.path.isfile(os.path.join(thisName, "description.txt")):
descOut = open(os.path.join(thisName, "description.txt"), 'w')
descOut.write("\n")
descOut.close()
if not os.path.isfile(os.path.join(thisName, "mod.conf")):
confOut = open(os.path.join(thisName, "mod.conf"), 'w')
confOut.write("name = "+thisName+"\n")
confOut.close()
if not os.path.isfile(os.path.join(thisName, "readme.md")):
readmeOut = open(os.path.join(thisName, "readme.md"), 'w')
readmeLine1 = thisName + " Minetest Mod"
readmeOut.write(readmeLine1+"\n")
readmeOut.write("="*len(readmeLine1)+"\n")
readmeOut.write("See description.txt\n")
readmeOut.write("\n")
readmeOut.write("## License\n")
readmeOut.write("See " + licDestName + "\n")
readmeOut.close()
licDest = os.path.join(thisName, licDestName)
if not os.path.isfile(licDest):
shutil.copyfile(licSrc, licDest)
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 = "-- "
def main():
licSrc = "example_license.txt"
licDestName = "LICENSE.txt"
licDesc = "MIT License"
if not os.path.isfile(licSrc):
tryLicSrc = os.path.join(myDir, licSrc)
if not os.path.isfile(tryLicSrc):
print("ERROR: missing " + licSrc)
return 1
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:
step0 = "Add your code init.lua."
if luaOut is not None:
luaOut.write("\n")
luaOut.close()
licSrc = tryLicSrc
toMod = None
fromName = None
toName = None
extraArgCount = 0
enableFill = False
options = []
for i in range(1, len(sys.argv)):
if sys.argv[i] == "--fill":
extraArgCount += 1
enableFill = True
else:
if (len(sys.argv[i]) >= 2) and (sys.argv[i][:2] == "--"):
usage()
return show_error("Invalid option: " + sys.argv[i],
code=2)
options.append(sys.argv[i])
if (len(options) != 1) and (len(options) != 3):
usage()
return 3
thisName = options[0]
if os.path.isdir(thisName):
if not enableFill:
print("")
print("ERROR: A mod named " + thisName + " cannot be ")
print("generated when the directory already exists.")
print("")
return 4
else:
os.mkdir(thisName)
if (len(options) == 3):
fromName = options[1]
toName = options[2]
delimI = toName.rfind(":")
if delimI > -1:
toMod = toName[:delimI]
if toMod.find(":") > -1:
usage()
return show_error("Your modname contains too many colons.",
code=5)
else:
toMod = "default"
print("")
print("")
print(step0)
print("The new mod is the " + thisName + " folder. Remember to:")
ender = "."
if (toMod is not None) and (len(toMod) > 0):
ender = ""
print("1. Edit depends.txt if your mod requires some mod" + ender)
if (toMod is not None) and (len(toMod) > 0):
print(" other than '" + toMod + "'.")
print("")
print("2. Edit description.txt to contain a brief description of")
print(" your mod (less than 100 characters).")
print("")
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(" " + licSrc)
print(" should be the " + licDesc + ".")
print(
''' The MIT License is good for Minetest mods so they can be used
most widely such as on app stores where replacing the program as per
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("")
mobAPI = None
if toMod is not None:
if not os.path.isfile(os.path.join(thisName, "depends.txt")):
dependsOut = open(os.path.join(thisName, "depends.txt"), 'w')
dependsOut.write(toMod+"\n")
dependsOut.close()
if toMod.find("mob") > -1:
mobAPI = toMod
if not os.path.isfile(os.path.join(thisName, "description.txt")):
descOut = open(os.path.join(thisName, "description.txt"), 'w')
descOut.write("\n")
descOut.close()
if not os.path.isfile(os.path.join(thisName, "mod.conf")):
confOut = open(os.path.join(thisName, "mod.conf"), 'w')
confOut.write("name = "+thisName+"\n")
confOut.close()
if not os.path.isfile(os.path.join(thisName, "readme.md")):
readmeOut = open(os.path.join(thisName, "readme.md"), 'w')
readmeLine1 = thisName + " Minetest Mod"
readmeOut.write(readmeLine1+"\n")
readmeOut.write("="*len(readmeLine1)+"\n")
readmeOut.write("See description.txt\n")
readmeOut.write("\n")
readmeOut.write("## License\n")
readmeOut.write("See " + licDestName + "\n")
readmeOut.close()
licDest = os.path.join(thisName, licDestName)
if not os.path.isfile(licDest):
shutil.copyfile(licSrc, licDest)
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:
step0 = "Add your code init.lua."
if luaOut is not None:
luaOut.write("\n")
luaOut.close()
print("")
print("")
print(step0)
print("The new mod is the " + thisName + " folder. Remember to:")
ender = "."
if (toMod is not None) and (len(toMod) > 0):
ender = ""
print("1. Edit depends.txt if your mod requires some mod" + ender)
if (toMod is not None) and (len(toMod) > 0):
print(" other than '" + toMod + "'.")
print("")
print("2. Edit description.txt to contain a brief description of")
print(" your mod (less than 100 characters).")
print("")
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(" " + licSrc)
print(" should be the " + licDesc + ".")
print(
''' The MIT License is good for Minetest mods so they can be used
most widely such as on app stores where replacing the program as per
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("")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

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

View File

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

View File

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