From 0ac4f13becd996731b5d3db04f177c5cd9779c38 Mon Sep 17 00:00:00 2001 From: poikilos <7557867+poikilos@users.noreply.github.com> Date: Sun, 3 Mar 2024 14:09:44 -0500 Subject: [PATCH] Fix: Correctly detect is_binary on file not dir (and rename related variables for clarity). --- pyenliven/mtpatches.py | 129 +++++++++++++++++++++++------------- utilities/check-patches-lmk | 37 +++++++++++ 2 files changed, 119 insertions(+), 47 deletions(-) create mode 100755 utilities/check-patches-lmk diff --git a/pyenliven/mtpatches.py b/pyenliven/mtpatches.py index 11ed97e..7d700b6 100755 --- a/pyenliven/mtpatches.py +++ b/pyenliven/mtpatches.py @@ -94,10 +94,12 @@ def diff_only_head(base, head, more_1char_args=None, log_level=0): Returns: list(dict): A list of differing files as info dicts, each with: - - 'rel': The path relative to head. - - 'new': True if not in base, otherwise False or not present. - - 'code': Return code (1 if file in head&base differ) - + - 'rel' (str): The path relative to head. + - 'new' (bool): True if not in base, otherwise False or not present. + - 'code' (int): Return code (1 if file in head&base differ) + - 'head_is_binary' (bool): If detected binary (implies binary + comparison was used, unless 'new' is True then not actually + compared but still detected head_is_binary). """ return _diff_only_head( base, @@ -237,6 +239,7 @@ def _diff_only_head(base, head, rel=None, more_1char_args=None, depth=0, log_level=log_level, ) else: + head_is_binary = is_binary(head_path) # echo0('base={}:"{}"'.format(whats[0], paths[0])) # echo0('head={}:"{}"'.format(whats[1], paths[1])) # file, so actually compare @@ -250,11 +253,9 @@ def _diff_only_head(base, head, rel=None, more_1char_args=None, depth=0, 'code': 1, 'rel': rel, 'new': True, + 'head_is_binary': head_is_binary, }] - - head_is_binary = is_binary(head_path) - if more_1char_args is None: if platform.system() == "Windows": if not head_is_binary: @@ -305,6 +306,7 @@ def _diff_only_head(base, head, rel=None, more_1char_args=None, depth=0, return [{ 'code': rc, 'rel': rel, + 'head_is_binary': head_is_binary, }] return diffs # folder, so return every sub's diff(s) ([] if None) @@ -449,6 +451,7 @@ def usage(): def main(): + skip_missing = False bases = ( "/opt/minebest/assemble/bucket_game", # "/opt/minebest/mtkit/minetest/src", @@ -483,17 +486,29 @@ def check_if_head_files_applied(bases, head_parents, skip_missing=False): Returns: int: 0 on success. """ - for base in bases: - if not os.path.isdir(base): - echo0('Warning: There is no base "{}".'.format(base)) + for base_root in bases: + if not os.path.isdir(base_root): + echo0('Warning: There is no base_root "{}".'.format(base_root)) continue - for head in head_parents: - echo0("\n# {}".format(head)) - for head_sub in os.listdir(head): + for head_parent in head_parents: + echo0("\n# {}".format(head_parent)) + for head_sub in os.listdir(head_parent): # Identify each head folder as an overlay to "patch" a base. - head_sub_path = os.path.join(head, head_sub) + + # *Ignore files* in each head parent! + # Files there may be diff and zip files etc.! + # Each sub *folder* is a overlay for base. + # - This method is *not* recursive, but: + # diff_only_head (recursive) is called below on each dir. + # - This method does *display* each file, for diffs + # returned by recursive diff_only_head. + + head_fuzzy_root = os.path.join(head_parent, head_sub) + # ^ head_fuzzy_root is not yet known in terms of depth + # which will be detected later if possible as patch_root + # (if contains "mods" folder, head_parent is patch_root) # region skip non-patch subs - if os.path.isfile(head_sub_path): + if os.path.isfile(head_fuzzy_root): # echo0('Warning: Only folders, skipped "{}"' # ''.format(head_sub)) continue @@ -515,12 +530,12 @@ def check_if_head_files_applied(bases, head_parents, skip_missing=False): # region identify patch structure mod_rel = get_shallowest_files_sub( - head_sub_path, + head_fuzzy_root, mask=["init.lua", "mod.conf", "depends.txt", "description.txt"], ) modpack_rel = get_shallowest_files_sub( - head_sub_path, + head_fuzzy_root, mask=["modpack.txt", "modpack.conf"], ) game_patch_root = None @@ -528,14 +543,13 @@ def check_if_head_files_applied(bases, head_parents, skip_missing=False): modpack_patch_root = None if head_sub.endswith("_game"): - game_patch_root = head_sub_path - elif os.path.isdir(os.path.join(head_sub_path, "mods")): - game_patch_root = head_sub_path - echo0('game_patch_root="{}"'.format(head_sub)) + game_patch_root = head_fuzzy_root + elif os.path.isdir(os.path.join(head_fuzzy_root, "mods")): + game_patch_root = head_fuzzy_root elif (mod_rel is not None) and (modpack_rel is None): - mod_parent = os.path.dirname(os.path.join(head_sub_path, + mod_parent = os.path.dirname(os.path.join(head_fuzzy_root, mod_rel)) - mod_parent_rel = mod_parent[len(head_sub_path)+1:] + mod_parent_rel = mod_parent[len(head_fuzzy_root)+1:] # ^ +1 no os.path.sep _, mod_parent_name = os.path.split(mod_parent) if mod_parent_rel and (mod_parent_name not in ["mods"]): @@ -546,17 +560,19 @@ def check_if_head_files_applied(bases, head_parents, skip_missing=False): if game_patch_root: pass # Already set above. + echo0('set game_patch_root="{}"'.format(head_sub)) elif modpack_patch_root: pass # Already set above. + echo0('set modpack_patch_root="{}"'.format(head_sub)) elif mod_rel is not None: if mod_rel: - mod_patch_root = os.path.join(head_sub_path, mod_rel) + mod_patch_root = os.path.join(head_fuzzy_root, mod_rel) else: # Must be "", so don't do join or will add os.path.sep - mod_patch_root = head_sub_path + mod_patch_root = head_fuzzy_root _, got_mod_name = os.path.split(mod_patch_root) - echo0('mod_patch="{}" root="{}"' - ''.format(got_mod_name, mod_patch_root)) + echo0('set mod_patch="{}"'.format(got_mod_name)) + echo0('set mod_patch_root="{}"'.format(mod_patch_root)) else: pass # echo0('Warning: mod not identified in "{}"' @@ -565,42 +581,42 @@ def check_if_head_files_applied(bases, head_parents, skip_missing=False): # endregion identify patch structure # region check whether base has it installed - patch_root = None + parallel_head = None # detected depth matches parallel_base if game_patch_root is not None: - patch_root = game_patch_root - _, game_name = os.path.split(base) - base_sub_path = base + parallel_head = game_patch_root + _, game_name = os.path.split(base_root) + parallel_base = base_root echo0("* Checking whether {} was applied to {} game" "".format(head_sub, game_name)) elif modpack_patch_root is not None: - patch_root = modpack_patch_root + parallel_head = modpack_patch_root _, modpack_name = os.path.split(modpack_patch_root) - modpack_rel = find_modpack(base, modpack_name) + modpack_rel = find_modpack(base_root, modpack_name) if modpack_rel is None: echo0("Error: {} was not found in {}" - "".format(modpack_name, base)) + "".format(modpack_name, base_root)) continue if modpack_rel: - base_sub_path = os.path.join(base, modpack_rel) + parallel_base = os.path.join(base_root, modpack_rel) else: # Must be "", so avoid join to avoid adding os.path.sep - base_sub_path = base + parallel_base = base_root echo0("* Checking whether {} was applied to" " {} modpack in {} game" "".format(head_sub, modpack_name, game_name)) elif mod_patch_root is not None: - patch_root = mod_patch_root + parallel_head = mod_patch_root _, mod_name = os.path.split(mod_patch_root) - mod_rel = find_mod(base, mod_name) + mod_rel = find_mod(base_root, mod_name) if mod_rel is None: echo0("Error: {} was not found in {}" - "".format(mod_name, base)) + "".format(mod_name, base_root)) continue if modpack_rel: - base_sub_path = os.path.join(base, modpack_rel) + parallel_base = os.path.join(base_root, modpack_rel) else: # Must be "", so avoid join to avoid adding os.path.sep - base_sub_path = base + parallel_base = base_root echo0("* Checking whether {} was applied to" " {} mod in {} game" "".format(head_sub, mod_name, game_name)) @@ -608,8 +624,11 @@ def check_if_head_files_applied(bases, head_parents, skip_missing=False): echo0('Warning: Skipping unknown patch structure: "{}"' ''.format(head_sub)) - diffs = diff_only_head(base_sub_path, patch_root, log_level=-1) + diffs = diff_only_head(parallel_base, parallel_head, + log_level=-1) for diff in diffs: + base_file = os.path.join(parallel_base, diff['rel']) + head_file = os.path.join(parallel_head, diff['rel']) missing = bool(diff.get("new")) if missing: if skip_missing: @@ -626,11 +645,27 @@ def check_if_head_files_applied(bases, head_parents, skip_missing=False): " or it will override base or head." "".format(os.path.sep) ) - echo0(" "+shlex.join([ - "meld", - os.path.join(base_sub_path, diff['rel']), - os.path.join(head_sub_path, diff['rel']), - ])+"{} # {} in base (original) vs head (patch) {}".format(color, why, Fore.RESET)) + + if not os.path.isfile(head_file): + raise NotImplementedError( + 'every head_file should be a file,' + ' but got "{}"'.format(head_file) + ) + # else isdir + # echo0("head_is_binary={}".format(head_is_binary)) + head_is_binary = is_binary(head_file) + difftool = "diffimg-gui" if head_is_binary else "meld" + + difftool = difftool + echo0( + " "+shlex.join([ + difftool, + base_file, + head_file, + ]) + + "{} # {} in base (original) vs head (patch) {}" + "".format(color, why, Fore.RESET) + ) # endregion check whether base has it installed return 0 diff --git a/utilities/check-patches-lmk b/utilities/check-patches-lmk new file mode 100755 index 0000000..0e23b34 --- /dev/null +++ b/utilities/check-patches-lmk @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# #!/usr/bin/python3 +# based on EnlivenMinetest/utilities/install-lmk +# +# The copy in hierosoft is relicensed by Poikilos (original author) +# under license of hierosoft +''' +install-lmk +----------- +Use any "minetest" folder under the current working directory +to install or upgrade. + +Developers: If /opt/minebest/mtkit is present, that will be used. + +See hierosoft.hminetestsrc documentation for more info. +''' +import re +import sys +import os + +SCRIPTS_DIR = os.path.dirname(os.path.realpath(__file__)) +REPO_DIR = os.path.dirname(SCRIPTS_DIR) + +if __name__ == "__main__": + sys.path.insert(0, REPO_DIR) + +# if os.path.isfile(os.path.join(repos_dir, "hierosoft", "init.py")): +# sys.path.insert(repos_dir) +# ^ implies both are installed (and that repos_dir is actually modules_dir), +# so leave path alone. + +from pyenliven.mtpatches import main # noqa E402 + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main())