User error info and version check (#2169)

* Add user information for error

* Show output if newer version available

* Update

* Update

* flake8

---------

Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com>
This commit is contained in:
Daniel Girtler 2023-10-15 20:26:27 +11:00 committed by GitHub
parent 07b0bb1835
commit c4c5cc4224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 52 additions and 19 deletions

View File

@ -1,6 +1,8 @@
"""Arch Linux installer - guided, templates etc.""" """Arch Linux installer - guided, templates etc."""
import importlib import importlib
import os import os
import time
import traceback
from argparse import ArgumentParser, Namespace from argparse import ArgumentParser, Namespace
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, Union from typing import TYPE_CHECKING, Any, Dict, Union
@ -21,6 +23,7 @@ from . import default_profiles
from .lib.hardware import SysInfo, GfxDriver from .lib.hardware import SysInfo, GfxDriver
from .lib.installer import Installer, accessibility_tools_in_use from .lib.installer import Installer, accessibility_tools_in_use
from .lib.output import FormattedOutput, log, error, debug, warn, info from .lib.output import FormattedOutput, log, error, debug, warn, info
from .lib.pacman import Pacman
from .lib.storage import storage from .lib.storage import storage
from .lib.global_menu import GlobalMenu from .lib.global_menu import GlobalMenu
from .lib.boot import Boot from .lib.boot import Boot
@ -34,7 +37,6 @@ from .lib.general import (
run_custom_user_commands, json_stream_to_structure, secret run_custom_user_commands, json_stream_to_structure, secret
) )
if TYPE_CHECKING: if TYPE_CHECKING:
_: Any _: Any
@ -42,7 +44,6 @@ if TYPE_CHECKING:
__version__ = "2.6.3" __version__ = "2.6.3"
storage['__version__'] = __version__ storage['__version__'] = __version__
# add the custom _ as a builtin, it can now be used anywhere in the # add the custom _ as a builtin, it can now be used anywhere in the
# project to mark strings as translatable with _('translate me') # project to mark strings as translatable with _('translate me')
DeferredTranslation.install() DeferredTranslation.install()
@ -57,12 +58,10 @@ debug(f"Graphics devices detected: {SysInfo._graphics_devices().keys()}")
# For support reasons, we'll log the disk layout pre installation to match against post-installation layout # For support reasons, we'll log the disk layout pre installation to match against post-installation layout
debug(f"Disk states before installing: {disk.disk_layouts()}") debug(f"Disk states before installing: {disk.disk_layouts()}")
if os.getuid() != 0: if os.getuid() != 0:
print(_("Archinstall requires root privileges to run. See --help for more.")) print(_("Archinstall requires root privileges to run. See --help for more."))
exit(1) exit(1)
parser = ArgumentParser() parser = ArgumentParser()
@ -82,14 +81,17 @@ def define_arguments():
parser.add_argument("--dry-run", "--dry_run", action="store_true", parser.add_argument("--dry-run", "--dry_run", action="store_true",
help="Generates a configuration file and then exits instead of performing an installation") help="Generates a configuration file and then exits instead of performing an installation")
parser.add_argument("--script", default="guided", nargs="?", help="Script to run for installation", type=str) parser.add_argument("--script", default="guided", nargs="?", help="Script to run for installation", type=str)
parser.add_argument("--mount-point","--mount_point", nargs="?", type=str, help="Define an alternate mount point for installation") parser.add_argument("--mount-point", "--mount_point", nargs="?", type=str,
help="Define an alternate mount point for installation")
parser.add_argument("--debug", action="store_true", default=False, help="Adds debug info into the log") parser.add_argument("--debug", action="store_true", default=False, help="Adds debug info into the log")
parser.add_argument("--offline", action="store_true", default=False, help="Disabled online upstream services such as package search and key-ring auto update.") parser.add_argument("--offline", action="store_true", default=False,
parser.add_argument("--no-pkg-lookups", action="store_true", default=False, help="Disabled package validation specifically prior to starting installation.") help="Disabled online upstream services such as package search and key-ring auto update.")
parser.add_argument("--no-pkg-lookups", action="store_true", default=False,
help="Disabled package validation specifically prior to starting installation.")
parser.add_argument("--plugin", nargs="?", type=str) parser.add_argument("--plugin", nargs="?", type=str)
def parse_unspecified_argument_list(unknowns :list, multiple :bool = False, err :bool = False) -> dict: def parse_unspecified_argument_list(unknowns: list, multiple: bool = False, err: bool = False) -> dict:
"""We accept arguments not defined to the parser. (arguments "ad hoc"). """We accept arguments not defined to the parser. (arguments "ad hoc").
Internally argparse return to us a list of words so we have to parse its contents, manually. Internally argparse return to us a list of words so we have to parse its contents, manually.
We accept following individual syntax for each argument We accept following individual syntax for each argument
@ -105,32 +107,32 @@ def parse_unspecified_argument_list(unknowns :list, multiple :bool = False, err
argument value value ... argument value value ...
which isn't am error if multiple is specified which isn't am error if multiple is specified
""" """
tmp_list = unknowns[:] # wastes a few bytes, but avoids any collateral effect of the destructive nature of the pop method() tmp_list = unknowns[:] # wastes a few bytes, but avoids any collateral effect of the destructive nature of the pop method()
config = {} config = {}
key = None key = None
last_key = None last_key = None
while tmp_list: while tmp_list:
element = tmp_list.pop(0) # retrieve an element of the list element = tmp_list.pop(0) # retrieve an element of the list
if element.startswith('--'): # is an argument ? if element.startswith('--'): # is an argument ?
if '=' in element: # uses the arg=value syntax ? if '=' in element: # uses the arg=value syntax ?
key, value = [x.strip() for x in element[2:].split('=', 1)] key, value = [x.strip() for x in element[2:].split('=', 1)]
config[key] = value config[key] = value
last_key = key # for multiple handling last_key = key # for multiple handling
key = None # we have the kwy value pair we need key = None # we have the kwy value pair we need
else: else:
key = element[2:] key = element[2:]
config[key] = True # every argument starts its lifecycle as boolean config[key] = True # every argument starts its lifecycle as boolean
else: else:
if element == '=': if element == '=':
continue continue
if key: if key:
config[key] = element config[key] = element
last_key = key # multiple last_key = key # multiple
key = None key = None
else: else:
if multiple and last_key: if multiple and last_key:
if isinstance(config[last_key],str): if isinstance(config[last_key], str):
config[last_key] = [config[last_key],element] config[last_key] = [config[last_key], element]
else: else:
config[last_key].append(element) config[last_key].append(element)
elif err: elif err:
@ -158,6 +160,7 @@ def cleanup_empty_args(args: Union[Namespace, Dict]) -> Dict:
return clean_args return clean_args
def get_arguments() -> Dict[str, Any]: def get_arguments() -> Dict[str, Any]:
""" The handling of parameters from the command line """ The handling of parameters from the command line
Is done on following steps: Is done on following steps:
@ -275,12 +278,25 @@ def plugin(f, *args, **kwargs):
plugins[f.__name__] = f plugins[f.__name__] = f
def run_as_a_module(): def _check_new_version():
info("Checking version...")
Pacman.run("-Sy")
upgrade = Pacman.run("-Qu archinstall").decode()
if upgrade:
text = f'New version available: {upgrade}'
info(text)
time.sleep(3)
def main():
""" """
This can either be run as the compiled and installed application: python setup.py install This can either be run as the compiled and installed application: python setup.py install
OR straight as a module: python -m archinstall OR straight as a module: python -m archinstall
In any case we will be attempting to load the provided script to be run from the scripts/ folder In any case we will be attempting to load the provided script to be run from the scripts/ folder
""" """
_check_new_version()
script = arguments.get('script', None) script = arguments.get('script', None)
if script is None: if script is None:
@ -289,3 +305,20 @@ def run_as_a_module():
mod_name = f'archinstall.scripts.{script}' mod_name = f'archinstall.scripts.{script}'
# by loading the module we'll automatically run the script # by loading the module we'll automatically run the script
importlib.import_module(mod_name) importlib.import_module(mod_name)
def run_as_a_module():
try:
main()
except Exception as e:
err = ''.join(traceback.format_exception(e))
error(err)
text = (
'Archinstall experienced the above error. If you think this is a bug, please report it to\n'
'https://github.com/archlinux/archinstall and include the log file "/var/log/archinstall/install.log".\n\n'
'Hint: To extract the log from a live ISO \ncurl -F\'file=@/var/log/archinstall/install.log\' https://0x0.st\n'
)
warn(text)
exit(1)