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,
|
||||
dpkg_is_broken,
|
||||
dpkg_lock_available,
|
||||
_apt_log_line_is_relevant,
|
||||
)
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from yunohost.log import is_unit_operation, OperationLogger
|
||||
|
@ -530,32 +531,6 @@ def tools_upgrade(operation_logger, target=None):
|
|||
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()
|
||||
def tools_shutdown(operation_logger, force=False):
|
||||
shutdown = force
|
||||
|
|
|
@ -211,3 +211,113 @@ def _dump_sources_list():
|
|||
if line.startswith("#") or not line.strip():
|
||||
continue
|
||||
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