forked from Mirror/pmbootstrap
commands: new submodule (MR 2252)
The current mechanism of invoking pmbootstrap actions can be a bit confusing, and relies heavily on args being a big namespace with lots of properties (which may or may not be valid depending on the context). To aid in slowly removing args from the codebase, introduce a new mechanism for running commands. This works by having a class for each command, where the arguments are passed in as parameters to the constructor. No doubt this won't scale very far, but it's a skeleton we can continue to build on as we migrate more commands over to not require args in order to run. Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
parent
52cf0e0fe3
commit
8526631589
6 changed files with 121 additions and 25 deletions
|
@ -76,7 +76,7 @@ def main() -> int:
|
||||||
|
|
||||||
# Run the function with the action's name (in pmb/helpers/frontend.py)
|
# Run the function with the action's name (in pmb/helpers/frontend.py)
|
||||||
if args.action:
|
if args.action:
|
||||||
getattr(frontend, args.action)(args)
|
run_command(args)
|
||||||
else:
|
else:
|
||||||
logging.info("Run pmbootstrap -h for usage information.")
|
logging.info("Run pmbootstrap -h for usage information.")
|
||||||
|
|
||||||
|
|
68
pmb/commands/__init__.py
Normal file
68
pmb/commands/__init__.py
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Copyright 2024 Caleb Connolly
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
import enum
|
||||||
|
from typing import Generator, Optional
|
||||||
|
from pathlib import Path, PosixPath, PurePosixPath
|
||||||
|
import pmb.config
|
||||||
|
from pmb.core.types import PmbArgs
|
||||||
|
from pmb.helpers import frontend
|
||||||
|
|
||||||
|
from .base import Command
|
||||||
|
from .log import Log
|
||||||
|
|
||||||
|
"""New way to model pmbootstrap subcommands that can be invoked without PmbArgs."""
|
||||||
|
|
||||||
|
# Commands that are still invoked via pmb/helpers/frontend.py
|
||||||
|
unmigrated_commands = [
|
||||||
|
"init",
|
||||||
|
"shutdown",
|
||||||
|
"index",
|
||||||
|
"work_migrate",
|
||||||
|
"repo_bootstrap",
|
||||||
|
"repo_missing",
|
||||||
|
"kconfig",
|
||||||
|
"export",
|
||||||
|
"sideload",
|
||||||
|
"netboot",
|
||||||
|
"flasher",
|
||||||
|
"initfs",
|
||||||
|
"qemu",
|
||||||
|
"pkgrel_bump",
|
||||||
|
"aportupgrade",
|
||||||
|
"newapkbuild",
|
||||||
|
"lint",
|
||||||
|
"status",
|
||||||
|
"ci",
|
||||||
|
"zap",
|
||||||
|
"stats",
|
||||||
|
"update",
|
||||||
|
"build_init",
|
||||||
|
"chroot",
|
||||||
|
"install",
|
||||||
|
"checksum",
|
||||||
|
"aportgen",
|
||||||
|
"build",
|
||||||
|
"deviceinfo_parse",
|
||||||
|
"apkbuild_parse",
|
||||||
|
"apkindex_parse",
|
||||||
|
"config",
|
||||||
|
"bootimg_analyze",
|
||||||
|
"pull",
|
||||||
|
]
|
||||||
|
|
||||||
|
def run_command(args: PmbArgs):
|
||||||
|
# Handle deprecated command format
|
||||||
|
if args.action in unmigrated_commands:
|
||||||
|
getattr(frontend, args.action)(args)
|
||||||
|
return
|
||||||
|
|
||||||
|
command: Command
|
||||||
|
# FIXME: would be nice to use match case...
|
||||||
|
if args.action == "log":
|
||||||
|
command = Log(args.clear_log, int(args.lines))
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(f"Command '{args.action}' is not implemented.")
|
||||||
|
|
||||||
|
command.run()
|
9
pmb/commands/base.py
Normal file
9
pmb/commands/base.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright 2024 Caleb Connolly
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
class Command():
|
||||||
|
"""Base class for pmbootstrap commands."""
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Run the command."""
|
||||||
|
raise NotImplementedError()
|
42
pmb/commands/log.py
Normal file
42
pmb/commands/log.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Copyright 2024 Caleb Connolly
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Generator, List, Optional
|
||||||
|
from pathlib import Path, PosixPath, PurePosixPath
|
||||||
|
from pmb import commands
|
||||||
|
from pmb.core.types import PathString
|
||||||
|
from pmb.helpers import run
|
||||||
|
from pmb.core import get_context
|
||||||
|
from pmb import config
|
||||||
|
|
||||||
|
class Log(commands.Command):
|
||||||
|
clear_log: bool
|
||||||
|
lines: int
|
||||||
|
|
||||||
|
def __init__(self, clear_log: bool, lines: int):
|
||||||
|
self.clear_log = clear_log
|
||||||
|
self.lines = lines
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
context = get_context()
|
||||||
|
log_testsuite = config.work / "log_testsuite.txt"
|
||||||
|
|
||||||
|
if self.clear_log:
|
||||||
|
run.user(["truncate", "-s", "0", context.log])
|
||||||
|
run.user(["truncate", "-s", "0", log_testsuite])
|
||||||
|
|
||||||
|
cmd: List[PathString] = ["tail", "-n", str(self.lines), "-F"]
|
||||||
|
|
||||||
|
# Follow the testsuite's log file too if it exists. It will be created when
|
||||||
|
# starting a test case that writes to it (git -C test grep log_testsuite).
|
||||||
|
if log_testsuite.exists():
|
||||||
|
cmd += [log_testsuite]
|
||||||
|
|
||||||
|
# tail writes the last lines of the files to the terminal. Put the regular
|
||||||
|
# log at the end, so that output is visible at the bottom (where the user
|
||||||
|
# looks for an error / what's currently going on).
|
||||||
|
cmd += [context.log]
|
||||||
|
|
||||||
|
run.user(cmd, output="tui")
|
||||||
|
|
|
@ -48,7 +48,7 @@ class PmbArgs(Namespace):
|
||||||
built: str
|
built: str
|
||||||
ccache_size: str
|
ccache_size: str
|
||||||
cipher: str
|
cipher: str
|
||||||
clear_log: str
|
clear_log: bool
|
||||||
cmdline: str
|
cmdline: str
|
||||||
command: str
|
command: str
|
||||||
config: Path
|
config: Path
|
||||||
|
|
|
@ -561,29 +561,6 @@ def work_migrate(args: PmbArgs):
|
||||||
pmb.helpers.logging.disable()
|
pmb.helpers.logging.disable()
|
||||||
|
|
||||||
|
|
||||||
def log(args: PmbArgs):
|
|
||||||
context = pmb.core.get_context()
|
|
||||||
log_testsuite = pmb.config.work / "log_testsuite.txt"
|
|
||||||
|
|
||||||
if args.clear_log:
|
|
||||||
pmb.helpers.run.user(["truncate", "-s", "0", context.log])
|
|
||||||
pmb.helpers.run.user(["truncate", "-s", "0", log_testsuite])
|
|
||||||
|
|
||||||
cmd: List[PathString] = ["tail", "-n", args.lines, "-F"]
|
|
||||||
|
|
||||||
# Follow the testsuite's log file too if it exists. It will be created when
|
|
||||||
# starting a test case that writes to it (git -C test grep log_testsuite).
|
|
||||||
if os.path.exists(log_testsuite):
|
|
||||||
cmd += [log_testsuite]
|
|
||||||
|
|
||||||
# tail writes the last lines of the files to the terminal. Put the regular
|
|
||||||
# log at the end, so that output is visible at the bottom (where the user
|
|
||||||
# looks for an error / what's currently going on).
|
|
||||||
cmd += [context.log]
|
|
||||||
|
|
||||||
pmb.helpers.run.user(cmd, output="tui")
|
|
||||||
|
|
||||||
|
|
||||||
def zap(args: PmbArgs):
|
def zap(args: PmbArgs):
|
||||||
pmb.chroot.zap(args, dry=args.dry, http=args.http,
|
pmb.chroot.zap(args, dry=args.dry, http=args.http,
|
||||||
distfiles=args.distfiles, pkgs_local=args.pkgs_local,
|
distfiles=args.distfiles, pkgs_local=args.pkgs_local,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue