From ed26f89aef846a2aa5a6f103621f9a25f2379268 Mon Sep 17 00:00:00 2001 From: Florian Schroegendorfer Date: Tue, 4 Jun 2024 03:39:10 +0200 Subject: [PATCH] improved mounting --- ekernel.py | 57 ++++++++++++++++++++++++++----------------- tests/test_clean.py | 6 +++-- tests/test_install.py | 16 ++++++++---- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/ekernel.py b/ekernel.py index d04c7e8..c58eafe 100644 --- a/ekernel.py +++ b/ekernel.py @@ -112,6 +112,11 @@ def cli (f): @functools.wraps(f) def handler (argv=sys.argv[1:]): try: + # dirty hack: set custom esp before mounting + try: + i = argv.index("-e") + Kernel.esp = pathlib.Path(argv[i + 1]) + except ValueError: pass r = f(argv) return 0 if r is None else r except Exception as e: @@ -119,29 +124,30 @@ def cli (f): sys.exit(1) return handler -def mount (path): +def mount (f): """Decorator ensuring a given path is mounted.""" - def wrapper (f): - @functools.wraps(f) - def mounter (*args, **kwargs): - mounted = False + @functools.wraps(f) + def mounter (*args, **kwargs): + mounted = False + esp = Kernel.esp.parents[-2] + if not esp.exists() or mount.force: try: subprocess.run( - ["mount", path], + ["mount", str(esp)], capture_output=True, check=True ) mounted = True except subprocess.CalledProcessError as e: msg = e.stderr.decode().strip() - if f"already mounted on {path}" not in msg: + if f"already mounted on {esp}" not in msg: raise RuntimeError(e.stderr.decode().splitlines()[0]) - r = f(*args, **kwargs) - if mounted: - subprocess.run(["umount", path], check=True) - return r - return mounter - return wrapper + r = f(*args, **kwargs) + if mounted: + subprocess.run(["umount", str(esp)], check=True) + return r + mount.force = False + return mounter @cli def configure (argv): @@ -341,7 +347,7 @@ def build (argv): subprocess.run(["make", "modules_install"], check=True) @cli -@mount("/boot") +@mount def install (argv): """ Install a kernel. @@ -404,7 +410,7 @@ def install (argv): help="be quiet" ) args = parser.parse_args(argv) - if args.esp: Kernel.esp = args.esp + if args.esp: Kernel.esp = args.esp # redundant kernel = Kernel(args.src) out.quiet = args.quiet @@ -435,7 +441,7 @@ def install (argv): subprocess.run(["emerge", "@module-rebuild"], check=True) @cli -@mount("/boot") +@mount def clean (argv): """ Remove unused kernel leftovers. @@ -496,7 +502,7 @@ def clean (argv): help="be quiet" ) args = parser.parse_args(argv) - if args.esp: Kernel.esp = args.esp + if args.esp: Kernel.esp = args.esp # redundant out.quiet = args.quiet if args.keep < 0: raise ValueError("invalid int value: must be greater equal zero") @@ -512,9 +518,12 @@ def clean (argv): # dry run if args.dry: - out.einfo("the following kernels will be removed:") - for k in leftovers: - print(f" {colorize('BAD', '✗')} {k.src.name}") + if leftovers: + out.einfo("the following kernels will be removed:") + for k in leftovers: + print(f" {colorize('BAD', '✗')} {k.src.name}") + else: + out.einfo("nothing to see here") return # run depclean @@ -725,14 +734,16 @@ def commit (argv): if args.msg: msg.write(f"\n\n{args.msg}") # print changes - out.einfo("changes to be committed:") + if removals or config_changed: + out.einfo("changes to be committed:") for l in removals: out.print(f" {colorize('QAWARN', '-')} {out.hilite(l)}") if config_changed: out.print(f" {colorize('INFO', '+')} {out.hilite(kernel.config)}") # print message - out.einfo("commit message:") + if msg: + out.einfo("commit message:") for l in msg.getvalue().splitlines(): out.print(f" {l}" if l else "") @@ -801,7 +812,7 @@ def update (argv): ) args = parser.parse_args(argv) args.jobs = ["-j", str(args.jobs)] if args.jobs else [] - args.esp = ["-e", str(args.esp)] if args.esp else [] + args.esp = ["-e", str(args.esp)] if args.esp else [] # redundant args.src = ["-s", str(args.src)] if args.src else [] args.keep = ["-k", str(args.keep)] if args.keep is not None else [] args.msg = ["-m", args.msg] if args.msg else [] diff --git a/tests/test_clean.py b/tests/test_clean.py index fd12899..8224c4b 100644 --- a/tests/test_clean.py +++ b/tests/test_clean.py @@ -31,6 +31,8 @@ class Tests (unittest.TestCase): k.modules.mkdir(parents=True) if not k.efi.exists(): k.efi.touch() + # force mounting + ekernel.mount.force = True # start interceptor self.interceptor = Interceptor() self.interceptor.add(subprocess.run, call=True) @@ -46,7 +48,7 @@ class Tests (unittest.TestCase): # mount /boot tracer, (args, kwargs) = next(trace_it) self.assertEqual(tracer.name, "subprocess.run") - self.assertEqual(args, (["mount", "/boot"],)) + self.assertEqual(args, (["mount", "/tmp"],)) self.assertEqual(kwargs, {"capture_output": True, "check": True}) # emerge -cq gentoo-sources tracer, (args, kwargs) = next(trace_it) @@ -64,7 +66,7 @@ class Tests (unittest.TestCase): # umount /boot tracer, (args, kwargs) = next(trace_it) self.assertEqual(tracer.name, "subprocess.run") - self.assertEqual(args, (["umount", "/boot"],)) + self.assertEqual(args, (["umount", "/tmp"],)) self.assertEqual(kwargs, {"check": True}) def test_clean (self): diff --git a/tests/test_install.py b/tests/test_install.py index 6dea38c..6199d66 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -14,6 +14,12 @@ def run (*argv): class Tests (unittest.TestCase): def setUp (self): + # setup test environment + data.setup() + self.kernel = Kernel.latest() + self.kernel.bzImage.touch() + # force mounting + ekernel.mount.force = True # start interceptor self.interceptor = Interceptor() def run (tracer, *args, **kwargs): @@ -22,10 +28,6 @@ class Tests (unittest.TestCase): data.linux.symlink_to(self.kernel.src.name) self.interceptor.add(subprocess.run, call=run) self.interceptor.start() - # setup test environment - data.setup() - self.kernel = Kernel.latest() - self.kernel.bzImage.touch() def tearDown (self): # stop interceptor @@ -36,7 +38,7 @@ class Tests (unittest.TestCase): # mount /boot tracer, (args, kwargs) = next(trace_it) self.assertEqual(tracer.name, "subprocess.run") - self.assertEqual(args, (["mount", "/boot"],)) + self.assertEqual(args, (["mount", "/tmp"],)) self.assertEqual(kwargs, {"capture_output": True, "check": True}) # eselect kernel set tracer, (args, kwargs) = next(trace_it) @@ -68,6 +70,10 @@ class Tests (unittest.TestCase): self.assertEqual(run("-q", "-e", str(esp)), 0) self.check_install() + def test_install_esp_missing (self): + with self.assertRaises(SystemExit): + run("-q", "-e", str(data.root / "boot/EFI/linux")) + def test_install_source (self): self.kernel = Kernel.current() self.assertEqual(run("-q", "-s", str(data.current)), 0)