diff options
Diffstat (limited to 'debputy/disabled-plugins/lua.py')
-rw-r--r-- | debputy/disabled-plugins/lua.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/debputy/disabled-plugins/lua.py b/debputy/disabled-plugins/lua.py new file mode 100644 index 0000000..7d49c6e --- /dev/null +++ b/debputy/disabled-plugins/lua.py @@ -0,0 +1,77 @@ +import itertools +from typing import Any, Optional, Tuple, IO, Iterable + +from debputy.plugin.api import DebputyPluginInitializer, VirtualPath + +_BUF_SIZE = 8096 + + +def initialize(api: DebputyPluginInitializer) -> None: + register_processing_steps_via_non_public_api(api) + + +def register_processing_steps_via_non_public_api(api: Any) -> None: + api.package_processor( + "deduplicate-lua-files", + deduplicate_lua_files, + ) + + +def find_lowest_lua5_version_dir(fs_root: VirtualPath) -> Optional[Tuple[int, VirtualPath]]: + for lua5_minor_version in range(1, 9): + lua_dir = fs_root.lookup(f"/usr/share/lua/5.{lua5_minor_version}/") + if not lua_dir: + continue + return lua5_minor_version, lua_dir + return None + + +def _compute_rel_path(reference_point: VirtualPath, target_file: VirtualPath) -> str: + assert target_file.path.startswith(reference_point.path + "/") + return target_file.path[len(reference_point.path) + 1:] + + +def _chunk(fd: IO[bytes]) -> Iterable[bytes]: + c = fd.read(_BUF_SIZE) + while c: + yield c + c = fd.read(_BUF_SIZE) + + +def _same_content(a: VirtualPath, b: VirtualPath) -> bool: + if a.size != b.size: + return False + # It might be tempting to use `cmp {a.fs_path} {b.fs_path}`, but this method makes it easier to test + # as the test will not have to create physical files. + # + # We could also replace this with a checksum check, then we could store them in a table and deduplicate + # between multiple versions (not just against the lowest version). Decided against it because this is + # are more faithful translation of the original code. + with a.open(byte_io=True, buffering=_BUF_SIZE) as afd, b.open(byte_io=True, buffering=_BUF_SIZE) as bfd: + for a_chunk, b_chunk in itertools.zip_longest(afd, bfd, fillvalue=None): + if a_chunk is None or b_chunk is None or a_chunk != b_chunk: + return False + return True + + +def deduplicate_lua_files(fs_root: VirtualPath, _unused1: Any, _unused2: Any) -> None: + res_tuple = find_lowest_lua5_version_dir(fs_root) + if res_tuple is None: + return + lua5_minor_version, lua5_reference_dir = res_tuple + all_lua5_ref_files = [ + lua_file + for lua_file in lua5_reference_dir.all_paths() + if lua_file.is_file and lua_file.name.endswith(".lua") + ] + for lua_file in all_lua5_ref_files: + rel_path = _compute_rel_path(lua5_reference_dir, lua_file) + for newer_lua_minor_version in range(lua5_minor_version + 1, 9): + alt_lua_file = fs_root.lookup(f"/usr/share/lua/5.{newer_lua_minor_version}/{rel_path}") + if alt_lua_file is None or not alt_lua_file.is_file or not _same_content(lua_file, alt_lua_file): + continue + parent_dir = alt_lua_file.parent_dir + assert parent_dir is not None + alt_lua_file.unlink() + # We do not have to normalize the link; debputy will handle that later. + parent_dir.add_symlink(alt_lua_file.name, lua_file.absolute) |