From ab084857d80e1ae1ef764c80e3d84509601c026f Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 23 Jan 2023 23:07:52 +0100 Subject: [PATCH] xbstrap: add `discard` command for nuking packages --- xbstrap/__init__.py | 49 ++++++++++++++++++++++++++++++++++++++ xbstrap/base.py | 58 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/xbstrap/__init__.py b/xbstrap/__init__.py index 253989f..fe5c404 100755 --- a/xbstrap/__init__.py +++ b/xbstrap/__init__.py @@ -996,6 +996,51 @@ def do_maintainer(args): # ---------------------------------------------------------------------------------------- +def do_discard(args): + cfg = config_for_args(args) + sel = select_pkgs(cfg, args) + plan = xbstrap.base.Plan(cfg) + handle_plan_args(cfg, plan, args) + if args.discard_src: + plan.wanted.update( + [(xbstrap.base.Action.DISCARD_SRC, cfg.get_source(pkg.source)) for pkg in sel] + ) + plan.wanted.update([(xbstrap.base.Action.DISCARD_PKG, pkg) for pkg in sel]) + if args.uninstall: + plan.wanted.update([(xbstrap.base.Action.UNINSTALL_PKG, pkg) for pkg in sel]) + plan.run_plan() + + +do_discard.parser = main_subparsers.add_parser( + "discard", + parents=[handle_plan_args.parser, select_pkgs.parser], + description="Discard a package from your tree", +) +do_discard.parser.add_argument("--discard-src", action="store_true") +do_discard.parser.add_argument("--uninstall", action="store_true") + + +# ---------------------------------------------------------------------------------------- + + +def do_uninstall(args): + cfg = config_for_args(args) + sel = select_pkgs(cfg, args) + plan = xbstrap.base.Plan(cfg) + handle_plan_args(cfg, plan, args) + plan.wanted.update([(xbstrap.base.Action.UNINSTALL_PKG, pkg) for pkg in sel]) + plan.run_plan() + + +do_uninstall.parser = main_subparsers.add_parser( + "uninstall", + parents=[handle_plan_args.parser, select_pkgs.parser], + description="Discard a package from your tree", +) + +# ---------------------------------------------------------------------------------------- + + def do_execute_manifest(args): if args.c is not None: manifest = yaml.load(args.c, Loader=xbstrap.base.global_yaml_loader) @@ -1073,6 +1118,10 @@ def main(): do_lsp(args) elif args.command == "maintainer": do_maintainer(args) + elif args.command == "discard": + do_discard(args) + elif args.command == "uninstall": + do_uninstall(args) else: assert not "Unexpected command" except ( diff --git a/xbstrap/base.py b/xbstrap/base.py index c765225..9871821 100644 --- a/xbstrap/base.py +++ b/xbstrap/base.py @@ -3041,6 +3041,40 @@ def run_tool_task(cfg, task): ) +def discard_src(cfg, src): + try: + shutil.rmtree(os.path.join(cfg.source_root, src.source_subdir)) + except FileNotFoundError: + pass + + +def discard_pkg(cfg, pkg): + try: + shutil.rmtree(os.path.join(cfg.build_root, pkg.build_subdir)) + shutil.rmtree(os.path.join(cfg.build_root, pkg.collect_subdir)) + shutil.rmtree(os.path.join(pkg.staging_dir)) + except FileNotFoundError: + pass + + +def uninstall_pkg(cfg, pkg): + if cfg.use_xbps: + output = subprocess.DEVNULL + if verbosity: + output = None + effective_arch = pkg.architecture + environ = os.environ.copy() + _util.build_environ_paths( + environ, "PATH", prepend=[os.path.join(_util.find_home(), "bin")] + ) + environ["XBPS_ARCH"] = effective_arch + args = ["xbps-remove", "-Fy", "-r", cfg.sysroot_dir, pkg.name] + _util.log_info("Running {}".format(args)) + subprocess.call(args, env=environ, stdout=output) + else: + raise GenericError("Package management configuration does not support uninstall") + + # --------------------------------------------------------------------------------------- # Build planning. # --------------------------------------------------------------------------------------- @@ -3094,6 +3128,9 @@ class Action(Enum): WANT_PKG = 22 # xbstrap-mirror functionality. MIRROR_SRC = 23 + DISCARD_SRC = 24 + DISCARD_PKG = 25 + UNINSTALL_PKG = 26 Action.strings = { @@ -3120,6 +3157,9 @@ class Action(Enum): Action.WANT_TOOL: "want-tool", Action.WANT_PKG: "want-pkg", Action.MIRROR_SRC: "mirror", + Action.DISCARD_SRC: "discard-source", + Action.DISCARD_PKG: "discard-package", + Action.UNINSTALL_PKG: "uninstall-package", } @@ -3269,6 +3309,9 @@ def _determine_state(self): Action.WANT_TOOL: lambda s, c: s.check_if_fully_installed(c), Action.WANT_PKG: lambda s, c: s.check_want_pkg(c), Action.MIRROR_SRC: lambda s, c: s.check_if_mirrord(c), + Action.DISCARD_SRC: lambda s, c: ItemState(missing=True), + Action.DISCARD_PKG: lambda s, c: ItemState(missing=True), + Action.UNINSTALL_PKG: lambda s, c: ItemState(missing=True), } self._state = visitors[self.action](self.subject, self.settings) @@ -3514,6 +3557,15 @@ def add_task_dependencies(s): add_pkg_dependencies(subject) add_task_dependencies(subject) + elif action == Action.DISCARD_SRC: + pass + + elif action == Action.DISCARD_PKG: + pass + + elif action == Action.UNINSTALL_PKG: + pass + return item def _do_materialization_visit(self, edges): @@ -3960,6 +4012,12 @@ def emit_progress(status): raise ExecutionFailureError(action, subject) elif action == Action.MIRROR_SRC: mirror_src(self._cfg, subject) + elif action == Action.DISCARD_SRC: + discard_src(self._cfg, subject) + elif action == Action.DISCARD_PKG: + discard_pkg(self._cfg, subject) + elif action == Action.UNINSTALL_PKG: + uninstall_pkg(self._cfg, subject) else: raise AssertionError("Unexpected action") item.exec_status = ExecutionStatus.SUCCESS