mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Add aptitude_with_progress_bar()
This commit is contained in:
parent
f6fbd69c39
commit
ac4e9cd216
2 changed files with 111 additions and 26 deletions
27
src/tools.py
27
src/tools.py
|
@ -48,6 +48,7 @@ from yunohost.utils.system import (
|
||||||
ynh_packages_version,
|
ynh_packages_version,
|
||||||
dpkg_is_broken,
|
dpkg_is_broken,
|
||||||
dpkg_lock_available,
|
dpkg_lock_available,
|
||||||
|
_apt_log_line_is_relevant,
|
||||||
)
|
)
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
from yunohost.log import is_unit_operation, OperationLogger
|
from yunohost.log import is_unit_operation, OperationLogger
|
||||||
|
@ -530,32 +531,6 @@ def tools_upgrade(operation_logger, target=None):
|
||||||
operation_logger.success()
|
operation_logger.success()
|
||||||
|
|
||||||
|
|
||||||
def _apt_log_line_is_relevant(line):
|
|
||||||
irrelevants = [
|
|
||||||
"service sudo-ldap already provided",
|
|
||||||
"Reading database ...",
|
|
||||||
"Preparing to unpack",
|
|
||||||
"Selecting previously unselected package",
|
|
||||||
"Created symlink /etc/systemd",
|
|
||||||
"Replacing config file",
|
|
||||||
"Creating config file",
|
|
||||||
"Installing new version of config file",
|
|
||||||
"Installing new config file as you requested",
|
|
||||||
", does not exist on system.",
|
|
||||||
"unable to delete old directory",
|
|
||||||
"update-alternatives:",
|
|
||||||
"Configuration file '/etc",
|
|
||||||
"==> Modified (by you or by a script) since installation.",
|
|
||||||
"==> Package distributor has shipped an updated version.",
|
|
||||||
"==> Keeping old config file as default.",
|
|
||||||
"is a disabled or a static unit",
|
|
||||||
" update-rc.d: warning: start and stop actions are no longer supported; falling back to defaults",
|
|
||||||
"insserv: warning: current stop runlevel",
|
|
||||||
"insserv: warning: current start runlevel",
|
|
||||||
]
|
|
||||||
return line.rstrip() and all(i not in line.rstrip() for i in irrelevants)
|
|
||||||
|
|
||||||
|
|
||||||
@is_unit_operation()
|
@is_unit_operation()
|
||||||
def tools_shutdown(operation_logger, force=False):
|
def tools_shutdown(operation_logger, force=False):
|
||||||
shutdown = force
|
shutdown = force
|
||||||
|
|
|
@ -211,3 +211,113 @@ def _dump_sources_list():
|
||||||
if line.startswith("#") or not line.strip():
|
if line.startswith("#") or not line.strip():
|
||||||
continue
|
continue
|
||||||
yield filename.replace("/etc/apt/", "") + ":" + line.strip()
|
yield filename.replace("/etc/apt/", "") + ":" + line.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def aptitude_with_progress_bar(cmd):
|
||||||
|
|
||||||
|
from moulinette.utils.process import call_async_output
|
||||||
|
|
||||||
|
msg_to_verb = {
|
||||||
|
"Preparing for removal": "Removing",
|
||||||
|
"Preparing to configure": "Installing",
|
||||||
|
"Removing": "Removing",
|
||||||
|
"Unpacking": "Installing",
|
||||||
|
"Configuring": "Installing",
|
||||||
|
"Installing": "Installing",
|
||||||
|
"Installed": "Installing",
|
||||||
|
"Preparing": "Installing",
|
||||||
|
"Done": "Done",
|
||||||
|
"Failed?": "Failed?",
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_progress_bar = False
|
||||||
|
if cmd.startswith("update"):
|
||||||
|
# the status-fd does stupid stuff for 'aptitude update', percentage is always zero except last iteration
|
||||||
|
disable_progress_bar = True
|
||||||
|
|
||||||
|
def log_apt_status_to_progress_bar(data):
|
||||||
|
|
||||||
|
if disable_progress_bar:
|
||||||
|
return
|
||||||
|
|
||||||
|
t, package, percent, msg = data.split(":", 3)
|
||||||
|
|
||||||
|
# We only display the stuff related to download once
|
||||||
|
if t == "dlstatus":
|
||||||
|
if log_apt_status_to_progress_bar.download_message_displayed is False:
|
||||||
|
logger.info("Downloading...")
|
||||||
|
log_apt_status_to_progress_bar.download_message_displayed = True
|
||||||
|
return
|
||||||
|
|
||||||
|
if package == "dpkg-exec":
|
||||||
|
return
|
||||||
|
if package and log_apt_status_to_progress_bar.previous_package and package == log_apt_status_to_progress_bar.previous_package:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
percent = round(float(percent), 1)
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
|
||||||
|
verb = "Processing"
|
||||||
|
for m, v in msg_to_verb.items():
|
||||||
|
if msg.startswith(m):
|
||||||
|
verb = v
|
||||||
|
|
||||||
|
log_apt_status_to_progress_bar.previous_package = package
|
||||||
|
|
||||||
|
width = 20
|
||||||
|
done = "#" * int(width * percent / 100)
|
||||||
|
remain = "." * (width - len(done))
|
||||||
|
logger.info(f"[{done}{remain}] > {percent}% {verb} {package}\r")
|
||||||
|
|
||||||
|
log_apt_status_to_progress_bar.previous_package = None
|
||||||
|
log_apt_status_to_progress_bar.download_message_displayed = False
|
||||||
|
|
||||||
|
def strip_boring_dpkg_reading_database(s):
|
||||||
|
return re.sub(r'(\(Reading database ... \d*%?|files and directories currently installed.\))', '', s)
|
||||||
|
|
||||||
|
callbacks = (
|
||||||
|
lambda l: logger.debug(strip_boring_dpkg_reading_database(l).rstrip() + "\r"),
|
||||||
|
lambda l: logger.warning(l.rstrip() + "\r"), # ... aptitude has no stderr ? :| if _apt_log_line_is_relevant(l.rstrip()) else logger.debug(l.rstrip() + "\r"),
|
||||||
|
lambda l: log_apt_status_to_progress_bar(l.rstrip()),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = (
|
||||||
|
f'LC_ALL=C DEBIAN_FRONTEND=noninteractive APT_LISTCHANGES_FRONTEND=none aptitude {cmd} --quiet=2 -o=Dpkg::Use-Pty=0 -o "APT::Status-Fd=$YNH_STDINFO"'
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.debug(f"Running: {cmd}")
|
||||||
|
|
||||||
|
ret = call_async_output(cmd, callbacks, shell=True)
|
||||||
|
|
||||||
|
if log_apt_status_to_progress_bar.previous_package is not None and ret == 0:
|
||||||
|
log_apt_status_to_progress_bar("done::100:Done")
|
||||||
|
elif ret != 0:
|
||||||
|
raise YunohostError(f"Failed to run command 'aptitude {cmd}'", raw_msg=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _apt_log_line_is_relevant(line):
|
||||||
|
irrelevants = [
|
||||||
|
"service sudo-ldap already provided",
|
||||||
|
"Reading database ...",
|
||||||
|
"Preparing to unpack",
|
||||||
|
"Selecting previously unselected package",
|
||||||
|
"Created symlink /etc/systemd",
|
||||||
|
"Replacing config file",
|
||||||
|
"Creating config file",
|
||||||
|
"Installing new version of config file",
|
||||||
|
"Installing new config file as you requested",
|
||||||
|
", does not exist on system.",
|
||||||
|
"unable to delete old directory",
|
||||||
|
"update-alternatives:",
|
||||||
|
"Configuration file '/etc",
|
||||||
|
"==> Modified (by you or by a script) since installation.",
|
||||||
|
"==> Package distributor has shipped an updated version.",
|
||||||
|
"==> Keeping old config file as default.",
|
||||||
|
"is a disabled or a static unit",
|
||||||
|
" update-rc.d: warning: start and stop actions are no longer supported; falling back to defaults",
|
||||||
|
"insserv: warning: current stop runlevel",
|
||||||
|
"insserv: warning: current start runlevel",
|
||||||
|
]
|
||||||
|
return line.rstrip() and all(i not in line.rstrip() for i in irrelevants)
|
||||||
|
|
Loading…
Add table
Reference in a new issue