mirror of
https://gitlab.postmarketos.org/postmarketOS/pmbootstrap.git
synced 2025-07-13 11:29:46 +03:00
core: introduce global context (MR 2252)
We can't totally escape the need for some runtime state defined by args. To make the migration easier, introduce a global "Context" class and move some of the read-only global options there. Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
parent
b82c4eb167
commit
2a7c769e14
6 changed files with 56 additions and 11 deletions
|
@ -29,10 +29,11 @@ if version < (3, 9):
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
def print_log_hint(args: Any) -> None:
|
def print_log_hint() -> None:
|
||||||
|
log = config.get("log")
|
||||||
# Hints about the log file (print to stdout only)
|
# Hints about the log file (print to stdout only)
|
||||||
log_hint = "Run 'pmbootstrap log' for details."
|
log_hint = "Run 'pmbootstrap log' for details."
|
||||||
if not args or not os.path.exists(args.log):
|
if not os.path.exists(log):
|
||||||
log_hint += (" Alternatively you can use '--details-to-stdout' to get more"
|
log_hint += (" Alternatively you can use '--details-to-stdout' to get more"
|
||||||
" output, e.g. 'pmbootstrap --details-to-stdout init'.")
|
" output, e.g. 'pmbootstrap --details-to-stdout init'.")
|
||||||
print()
|
print()
|
||||||
|
@ -93,12 +94,12 @@ def main() -> int:
|
||||||
|
|
||||||
except BuildFailedError as exception:
|
except BuildFailedError as exception:
|
||||||
logging.error(f"ERROR: {exception}")
|
logging.error(f"ERROR: {exception}")
|
||||||
print_log_hint(args)
|
print_log_hint()
|
||||||
return 3
|
return 3
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Dump log to stdout when args (and therefore logging) init failed
|
# Dump log to stdout when args (and therefore logging) init failed
|
||||||
if not args:
|
if "args" not in locals():
|
||||||
import logging as pylogging
|
import logging as pylogging
|
||||||
pylogging.getLogger().setLevel(logging.DEBUG)
|
pylogging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
@ -106,7 +107,7 @@ def main() -> int:
|
||||||
logging.info("See also: <https://postmarketos.org/troubleshooting>")
|
logging.info("See also: <https://postmarketos.org/troubleshooting>")
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
|
|
||||||
print_log_hint(args)
|
print_log_hint()
|
||||||
print()
|
print()
|
||||||
print("Before you report this error, ensure that pmbootstrap is "
|
print("Before you report this error, ensure that pmbootstrap is "
|
||||||
"up to date.")
|
"up to date.")
|
||||||
|
|
|
@ -2,3 +2,16 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from pmb.core.chroot import Chroot, ChrootType
|
from pmb.core.chroot import Chroot, ChrootType
|
||||||
|
from pmb.core.context import Context
|
||||||
|
|
||||||
|
__context: Context
|
||||||
|
|
||||||
|
def get_context() -> Context:
|
||||||
|
"""Get immutable global runtime context."""
|
||||||
|
global __context
|
||||||
|
|
||||||
|
# We must defer this to first call to avoid
|
||||||
|
# circular imports.
|
||||||
|
if "__context" not in globals():
|
||||||
|
__context = Context()
|
||||||
|
return __context
|
||||||
|
|
15
pmb/core/context.py
Normal file
15
pmb/core/context.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Copyright 2024 Caleb Connolly
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
"""Global runtime context"""
|
||||||
|
|
||||||
|
class Context():
|
||||||
|
details_to_stdout: bool
|
||||||
|
quiet: bool
|
||||||
|
command_timeout: float
|
||||||
|
sudo_timer: bool
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.details_to_stdout = False
|
||||||
|
self.command_timeout = 0
|
||||||
|
self.sudo_timer = False
|
|
@ -54,7 +54,7 @@ class PmbArgs(Namespace):
|
||||||
config: Path
|
config: Path
|
||||||
config_channels: str
|
config_channels: str
|
||||||
details: bool
|
details: bool
|
||||||
details_to_stdout: str
|
details_to_stdout: bool
|
||||||
device: str
|
device: str
|
||||||
deviceinfo: Dict[str, str]
|
deviceinfo: Dict[str, str]
|
||||||
deviceinfo_parse_kernel: str
|
deviceinfo_parse_kernel: str
|
||||||
|
@ -145,7 +145,7 @@ class PmbArgs(Namespace):
|
||||||
src: str
|
src: str
|
||||||
ssh_keys: str
|
ssh_keys: str
|
||||||
strict: str
|
strict: str
|
||||||
sudo_timer: str
|
sudo_timer: bool
|
||||||
suffix: str
|
suffix: str
|
||||||
systemd: str
|
systemd: str
|
||||||
timeout: float
|
timeout: float
|
||||||
|
|
|
@ -114,9 +114,23 @@ def init(args: PmbArgs) -> PmbArgs:
|
||||||
pmb.config.merge_with_args(args)
|
pmb.config.merge_with_args(args)
|
||||||
replace_placeholders(args)
|
replace_placeholders(args)
|
||||||
|
|
||||||
|
# Configure runtime context
|
||||||
|
context = pmb.core.get_context()
|
||||||
|
context.command_timeout = args.timeout
|
||||||
|
context.details_to_stdout = args.details_to_stdout
|
||||||
|
context.sudo_timer = args.sudo_timer
|
||||||
|
context.quiet = args.quiet
|
||||||
|
|
||||||
# Initialize logs (we could raise errors below)
|
# Initialize logs (we could raise errors below)
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
|
|
||||||
|
# Remove attributes from args so they don't get used by mistake
|
||||||
|
delattr(args, "timeout")
|
||||||
|
delattr(args, "details_to_stdout")
|
||||||
|
delattr(args, "sudo_timer")
|
||||||
|
delattr(args, "log")
|
||||||
|
delattr(args, "quiet")
|
||||||
|
|
||||||
# Initialization code which may raise errors
|
# Initialization code which may raise errors
|
||||||
check_pmaports_path(args)
|
check_pmaports_path(args)
|
||||||
if args.action not in ["init", "checksum", "config", "bootimg_analyze", "log",
|
if args.action not in ["init", "checksum", "config", "bootimg_analyze", "log",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import fcntl
|
import fcntl
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.core.types import PathString, Env
|
from pmb.core.types import PathString, Env
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
|
@ -175,6 +176,7 @@ def foreground_pipe(args: PmbArgs, cmd, working_dir=None, output_to_stdout=False
|
||||||
* output: ""
|
* output: ""
|
||||||
* output: full program output string (output_return is True)
|
* output: full program output string (output_return is True)
|
||||||
"""
|
"""
|
||||||
|
context = pmb.core.get_context()
|
||||||
# Start process in background (stdout and stderr combined)
|
# Start process in background (stdout and stderr combined)
|
||||||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT, cwd=working_dir,
|
stderr=subprocess.STDOUT, cwd=working_dir,
|
||||||
|
@ -193,7 +195,7 @@ def foreground_pipe(args: PmbArgs, cmd, working_dir=None, output_to_stdout=False
|
||||||
output_buffer: list[bytes] = []
|
output_buffer: list[bytes] = []
|
||||||
sel = selectors.DefaultSelector()
|
sel = selectors.DefaultSelector()
|
||||||
sel.register(stdout, selectors.EVENT_READ)
|
sel.register(stdout, selectors.EVENT_READ)
|
||||||
timeout = args.timeout
|
timeout = context.command_timeout
|
||||||
while process.poll() is None:
|
while process.poll() is None:
|
||||||
wait_start = time.perf_counter()
|
wait_start = time.perf_counter()
|
||||||
sel.select(timeout)
|
sel.select(timeout)
|
||||||
|
@ -203,12 +205,12 @@ def foreground_pipe(args: PmbArgs, cmd, working_dir=None, output_to_stdout=False
|
||||||
# timeout was not reached.)
|
# timeout was not reached.)
|
||||||
if output_timeout:
|
if output_timeout:
|
||||||
wait_end = time.perf_counter()
|
wait_end = time.perf_counter()
|
||||||
if wait_end - wait_start >= args.timeout:
|
if wait_end - wait_start >= timeout:
|
||||||
logging.info("Process did not write any output for " +
|
logging.info("Process did not write any output for " +
|
||||||
str(args.timeout) + " seconds. Killing it.")
|
str(timeout) + " seconds. Killing it.")
|
||||||
logging.info("NOTE: The timeout can be increased with"
|
logging.info("NOTE: The timeout can be increased with"
|
||||||
" 'pmbootstrap -t'.")
|
" 'pmbootstrap -t'.")
|
||||||
kill_command(args, process.pid, sudo)
|
kill_command(process.pid, sudo)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Read all currently available output
|
# Read all currently available output
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue