Skip to content

Commit

Permalink
xbstrap: add discard command for nuking packages
Browse files Browse the repository at this point in the history
  • Loading branch information
no92 committed Aug 9, 2022
1 parent 31b0368 commit 04e5cf3
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 12 deletions.
27 changes: 27 additions & 0 deletions xbstrap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,31 @@ def resolve_host_paths(x):
# ----------------------------------------------------------------------------------------


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)
plan.wanted.update([(xbstrap.base.Action.DISCARD_PKG, pkg) for pkg in sel])
if args.src:
plan.wanted.update(
[(xbstrap.base.Action.DISCARD_SRC, cfg.get_source(pkg.source)) for pkg in sel]
)
plan.run_plan()


do_discard.parser = main_subparsers.add_parser(
"discard",
parents=[handle_plan_args.parser, select_pkgs.parser],
formatter_class=argparse.RawDescriptionHelpFormatter,
description="Discard a package from your tree",
)
do_discard.parser.add_argument("--src", action="store_true", help="also remove sources")
do_discard.parser.set_defaults(src=False)

# ----------------------------------------------------------------------------------------


def do_execute_manifest(args):
if args.c is not None:
manifest = yaml.load(args.c, Loader=xbstrap.base.global_yaml_loader)
Expand Down Expand Up @@ -990,6 +1015,8 @@ def main():
do_run_task(args)
elif args.command == "lsp":
do_lsp(args)
elif args.command == "discard":
do_discard(args)
else:
assert not "Unexpected command"
except (
Expand Down
91 changes: 79 additions & 12 deletions xbstrap/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import tempfile
import urllib.request
import zipfile
from contextlib import suppress
from enum import Enum

import colorama
Expand Down Expand Up @@ -951,8 +952,11 @@ def check_if_mirrord(self, settings):

return ItemState()

def mark_as_fetched(self):
touch(os.path.join(self.source_dir, "fetched.xbstrap"))
def mark_as_fetched(self, mark=True):
if mark:
touch(os.path.join(self.source_dir, "fetched.xbstrap"))
else:
os.unlink(os.path.join(self.source_dir, "fetched.xbstrap"))

def check_if_checkedout(self, settings):
path = os.path.join(self.source_dir, "checkedout.xbstrap")
Expand All @@ -962,8 +966,11 @@ def check_if_checkedout(self, settings):
return ItemState(missing=True)
return ItemState(timestamp=stat.st_mtime)

def mark_as_checkedout(self):
touch(os.path.join(self.source_dir, "checkedout.xbstrap"))
def mark_as_checkedout(self, mark=True):
if mark:
touch(os.path.join(self.source_dir, "checkedout.xbstrap"))
else:
os.unlink(os.path.join(self.source_dir, "checkedout.xbstrap"))

def check_if_patched(self, settings):
path = os.path.join(self.source_dir, "patched.xbstrap")
Expand All @@ -973,8 +980,11 @@ def check_if_patched(self, settings):
return ItemState(missing=True)
return ItemState(timestamp=stat.st_mtime)

def mark_as_patched(self):
touch(os.path.join(self.source_dir, "patched.xbstrap"))
def mark_as_patched(self, mark=True):
if mark:
touch(os.path.join(self.source_dir, "patched.xbstrap"))
else:
os.unlink(os.path.join(self.source_dir, "patched.xbstrap"))

def check_if_regenerated(self, settings):
path = os.path.join(self.source_dir, "regenerated.xbstrap")
Expand All @@ -984,8 +994,11 @@ def check_if_regenerated(self, settings):
return ItemState(missing=True)
return ItemState(timestamp=stat.st_mtime)

def mark_as_regenerated(self):
touch(os.path.join(self.source_dir, "regenerated.xbstrap"))
def mark_as_regenerated(self, mark=True):
if mark:
touch(os.path.join(self.source_dir, "regenerated.xbstrap"))
else:
os.unlink(os.path.join(self.source_dir, "regenerated.xbstrap"))


class HostStage(RequirementsMixin):
Expand Down Expand Up @@ -1060,7 +1073,7 @@ def check_if_installed(self, settings):
return ItemState(missing=True)
return ItemState(timestamp=stat.st_mtime)

def mark_as_installed(self):
def mark_as_installed(self, mark=True):
stage_spec = ""
if not self._inherited:
stage_spec = "@" + self.stage_name
Expand All @@ -1069,7 +1082,10 @@ def mark_as_installed(self):
path = os.path.join(
self._pkg.prefix_dir, "etc", "xbstrap", self._pkg.name + stage_spec + ".installed"
)
touch(path)
if mark:
touch(path)
else:
os.unlink(path)


class HostPackage(RequirementsMixin):
Expand Down Expand Up @@ -1448,11 +1464,14 @@ def check_if_installed(self, settings):
return ItemState(missing=True)
return ItemState()

def mark_as_installed(self):
def mark_as_installed(self, mark=True):
_util.try_mkdir(os.path.join(self._cfg.sysroot_dir, "etc"))
_util.try_mkdir(os.path.join(self._cfg.sysroot_dir, "etc", "xbstrap"))
path = os.path.join(self._cfg.sysroot_dir, "etc", "xbstrap", self.name + ".installed")
touch(path)
if mark:
touch(path)
else:
os.unlink(path)


class PackageRunTask(RequirementsMixin):
Expand Down Expand Up @@ -2612,6 +2631,38 @@ def run_tool_task(cfg, task):
)


def discard_src(cfg, src):
with suppress(Exception):
src.mark_as_fetched(mark=False)
src.mark_as_checkedout(mark=False)
src.mark_as_patched(mark=False)
src.mark_as_regenerated(mark=False)
with suppress(Exception):
shutil.rmtree(os.path.join(cfg.source_root, src.source_subdir))
with suppress(Exception):
os.remove(src.source_archive_file)


def discard_pkg(cfg, pkg):
with suppress(Exception):
pkg.mark_as_configured(mark=False)
pkg.mark_as_installed(mark=False)
with suppress(Exception):
shutil.rmtree(os.path.join(cfg.build_root, pkg.build_subdir))
shutil.rmtree(os.path.join(cfg.build_root, pkg.collect_subdir))

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)


# ---------------------------------------------------------------------------------------
# Build planning.
# ---------------------------------------------------------------------------------------
Expand Down Expand Up @@ -2664,6 +2715,8 @@ class Action(Enum):
WANT_PKG = 21
# xbstrap-mirror functionality.
MIRROR_SRC = 22
DISCARD_SRC = 23
DISCARD_PKG = 24


Action.strings = {
Expand All @@ -2689,6 +2742,8 @@ 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",
}


Expand Down Expand Up @@ -2768,6 +2823,8 @@ def _determine_state(self):
Action.WANT_TOOL: lambda s, c: s.check_if_fully_installed(c),
Action.WANT_PKG: lambda s, c: s.check_staging(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),
}
self._state = visitors[self.action](self.subject, self.settings)

Expand Down Expand Up @@ -2967,6 +3024,12 @@ 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

return item

def _do_materialization_visit(self, edges):
Expand Down Expand Up @@ -3310,6 +3373,10 @@ 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)
else:
raise AssertionError("Unexpected action")
item.exec_status = ExecutionStatus.SUCCESS
Expand Down

0 comments on commit 04e5cf3

Please sign in to comment.