diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb0e02f6..1caf713a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -59,7 +59,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
+ - displaying the "Indexing suggestions" task during the initialization process
+
+- all types now display an initialization task "Checking configuration file" responsible to create/update the respective configuration file
- minor translation improvements
diff --git a/bauh/app.py b/bauh/app.py
index abc33929..172b0e5a 100755
--- a/bauh/app.py
+++ b/bauh/app.py
@@ -7,7 +7,7 @@ import urllib3
from PyQt5.QtCore import QCoreApplication, Qt
from bauh import __app_name__, app_args
-from bauh.view.core import config
+from bauh.view.core.config import CoreConfigManager
from bauh.view.util import logs
@@ -25,7 +25,7 @@ def main(tray: bool = False):
if args.offline:
logger.warning("offline mode activated")
- app_config = config.read_config(update_file=True)
+ app_config = CoreConfigManager().get_config()
if bool(app_config['ui']['auto_scale']):
os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1'
diff --git a/bauh/cli/app.py b/bauh/cli/app.py
index af4a4c4e..232e809a 100644
--- a/bauh/cli/app.py
+++ b/bauh/cli/app.py
@@ -9,7 +9,8 @@ from bauh.cli import __app_name__, cli_args
from bauh.cli.controller import CLIManager
from bauh.commons.internet import InternetChecker
from bauh.context import generate_i18n, DEFAULT_I18N_KEY
-from bauh.view.core import config, gems
+from bauh.view.core import gems
+from bauh.view.core.config import CoreConfigManager
from bauh.view.core.controller import GenericSoftwareManager
from bauh.view.core.downloader import AdaptableFileDownloader
from bauh.view.util import logs, util, resource
@@ -26,7 +27,7 @@ def main():
args = cli_args.read()
logger = logs.new_logger(__app_name__, False)
- app_config = config.read_config(update_file=True)
+ app_config = CoreConfigManager().get_config()
http_client = HttpClient(logger)
i18n = generate_i18n(app_config, resource.get_path('locale'))
diff --git a/bauh/commons/boot.py b/bauh/commons/boot.py
new file mode 100644
index 00000000..c9874ada
--- /dev/null
+++ b/bauh/commons/boot.py
@@ -0,0 +1,57 @@
+import time
+from logging import Logger
+from threading import Thread
+from typing import Optional
+
+from bauh.api.abstract.handler import TaskManager
+from bauh.commons.config import ConfigManager
+from bauh.view.util.translation import I18n
+
+
+class CreateConfigFile(Thread):
+ """
+ Generic initialization task to create a configuration file
+ """
+
+ def __init__(self, configman: ConfigManager, taskman: TaskManager, task_icon_path: str, i18n: I18n, logger: Logger, config_instance: Optional[dict] = None):
+ super(CreateConfigFile, self).__init__(daemon=True)
+ self.configman = configman
+ self.taskman = taskman
+ self.logger = logger
+ self.config = config_instance
+ self.task_icon_path = task_icon_path
+ self.task_id = configman.__class__.__name__
+ self.i18n = i18n
+ self.task_name = self.i18n['task.checking_config']
+ self.taskman.register_task(self.task_id, self.task_name, self.task_icon_path)
+
+ def _log(self, msg: str):
+ self.logger.info('{}: {}'.format(self.configman.__class__.__name__, msg))
+
+ def run(self):
+ ti = time.time()
+ self.taskman.update_progress(self.task_id, 1, None)
+
+ self._log("Reading cached configuration file")
+ default_config = self.configman.get_default_config()
+
+ cached_config = self.configman.read_config()
+
+ self.taskman.update_progress(self.task_id, 50, None)
+
+ if cached_config:
+ self._log("Merging configuration file")
+ self.configman.merge_config(default_config, cached_config)
+ else:
+ self._log("No cached configuration file found")
+
+ self.config = default_config
+ self.taskman.update_progress(self.task_id, 75, self.i18n['task.checking_config.saving'])
+
+ self._log("Writing configuration file")
+ self.configman.save_config(default_config)
+
+ self.taskman.update_progress(self.task_id, 100, None)
+ self.taskman.finish_task(self.task_id)
+ tf = time.time()
+ self._log("Finished. Took {0:.2f} seconds".format(tf - ti))
diff --git a/bauh/commons/category.py b/bauh/commons/category.py
index 19ef9976..12b589d8 100644
--- a/bauh/commons/category.py
+++ b/bauh/commons/category.py
@@ -18,8 +18,8 @@ from bauh.commons.util import map_timestamp_file
class CategoriesDownloader(Thread):
def __init__(self, id_: str, http_client: HttpClient, logger: logging.Logger, manager: SoftwareManager,
- url_categories_file: str, categories_path: str, expiration: int, internet_checker: InternetChecker,
- internet_connection: Optional[bool] = True, before=None, after=None):
+ url_categories_file: str, categories_path: str, internet_checker: InternetChecker,
+ expiration: Optional[int] = None, internet_connection: Optional[bool] = True, before=None, after=None):
"""
:param id_:
:param http_client:
@@ -121,7 +121,7 @@ class CategoriesDownloader(Thread):
self.logger.warning(self._msg("No internet connection. The categories file '{}' cannot be updated.".format(self.categories_path)))
return False
- if self.expiration <= 0:
+ if self.expiration is None or self.expiration <= 0:
self.logger.warning(self._msg("No expiration set for the categories file '{}'. It should be downloaded".format(self.categories_path)))
return True
diff --git a/bauh/commons/config.py b/bauh/commons/config.py
index cf6fbba6..dcb42638 100644
--- a/bauh/commons/config.py
+++ b/bauh/commons/config.py
@@ -1,6 +1,9 @@
import os
+import traceback
+from abc import abstractmethod, ABC
from pathlib import Path
from threading import Thread
+from typing import Optional
import yaml
@@ -31,3 +34,69 @@ def read_config(file_path: str, template: dict, update_file: bool = False, updat
def save_config(config: dict, file_path: str):
with open(file_path, 'w+') as f:
f.write(yaml.dump(config))
+
+
+class ConfigManager(ABC):
+
+ @abstractmethod
+ def read_config(self) -> Optional[dict]:
+ pass
+
+ @abstractmethod
+ def get_default_config(self) -> dict:
+ pass
+
+ @abstractmethod
+ def is_config_cached(self) -> bool:
+ pass
+
+ def get_config(self) -> dict:
+ default_config = self.get_default_config()
+
+ if default_config:
+ cached_config = self.read_config()
+
+ if cached_config:
+ self.merge_config(default_config, cached_config)
+
+ return default_config
+
+ @staticmethod
+ def merge_config(base_config: dict, current_config: dict):
+ util.deep_update(base_config, current_config)
+
+ @abstractmethod
+ def save_config(self, config_obj: dict):
+ pass
+
+
+class YAMLConfigManager(ConfigManager, ABC):
+
+ def __init__(self, config_file_path: str):
+ self.file_path = config_file_path
+
+ def is_config_cached(self) -> bool:
+ return os.path.exists(self.file_path)
+
+ def read_config(self) -> Optional[dict]:
+ if self.is_config_cached():
+ with open(self.file_path) as f:
+ local_config = yaml.safe_load(f.read())
+
+ if local_config is not None:
+ return local_config
+
+ def save_config(self, config_obj: dict):
+ if config_obj:
+ config_dir = os.path.dirname(self.file_path)
+ try:
+ Path(config_dir).mkdir(parents=True, exist_ok=True)
+ except OSError:
+ traceback.print_exc()
+ return
+
+ try:
+ with open(self.file_path, 'w+') as f:
+ f.write(yaml.dump(config_obj))
+ except:
+ traceback.print_exc()
diff --git a/bauh/gems/appimage/config.py b/bauh/gems/appimage/config.py
index 6c80328e..2ced2afb 100644
--- a/bauh/gems/appimage/config.py
+++ b/bauh/gems/appimage/config.py
@@ -1,11 +1,15 @@
-from bauh.commons.config import read_config as read
+from bauh.commons.config import YAMLConfigManager
from bauh.gems.appimage import CONFIG_FILE
-def read_config(update_file: bool = False) -> dict:
- default = {
- 'database': {
- 'expiration': 60
+class AppImageConfigManager(YAMLConfigManager):
+
+ def __init__(self):
+ super(AppImageConfigManager, self).__init__(config_file_path=CONFIG_FILE)
+
+ def get_default_config(self) -> dict:
+ return {
+ 'database': {
+ 'expiration': 60
+ }
}
- }
- return read(CONFIG_FILE, default, update_file=update_file)
diff --git a/bauh/gems/appimage/controller.py b/bauh/gems/appimage/controller.py
index e42b6ffe..821c6a5b 100644
--- a/bauh/gems/appimage/controller.py
+++ b/bauh/gems/appimage/controller.py
@@ -24,13 +24,13 @@ from bauh.api.abstract.model import SoftwarePackage, PackageHistory, PackageUpda
from bauh.api.abstract.view import MessageType, ViewComponent, FormComponent, InputOption, SingleSelectComponent, \
SelectViewType, TextInputComponent, PanelComponent, FileChooserComponent, ViewObserver
from bauh.commons import resource
-from bauh.commons.config import save_config
+from bauh.commons.boot import CreateConfigFile
from bauh.commons.html import bold
from bauh.commons.system import SystemProcess, new_subprocess, ProcessHandler, run_cmd, SimpleProcess
-from bauh.gems.appimage import query, INSTALLATION_PATH, LOCAL_PATH, SUGGESTIONS_FILE, CONFIG_FILE, ROOT_DIR, \
+from bauh.gems.appimage import query, INSTALLATION_PATH, LOCAL_PATH, SUGGESTIONS_FILE, ROOT_DIR, \
CONFIG_DIR, UPDATES_IGNORED_FILE, util, get_default_manual_installation_file_dir, DATABASE_APPS_FILE, \
- DATABASE_RELEASES_FILE, DESKTOP_ENTRIES_PATH, DATABASES_DIR
-from bauh.gems.appimage.config import read_config
+ DATABASE_RELEASES_FILE, DESKTOP_ENTRIES_PATH, DATABASES_DIR, get_icon_path
+from bauh.gems.appimage.config import AppImageConfigManager
from bauh.gems.appimage.model import AppImage
from bauh.gems.appimage.util import replace_desktop_entry_exec_command
from bauh.gems.appimage.worker import DatabaseUpdater, SymlinksVerifier
@@ -76,6 +76,7 @@ class AppImageManager(SoftwareManager):
self.http_client = context.http_client
self.logger = context.logger
self.file_downloader = context.file_downloader
+ self.configman = AppImageConfigManager()
self.custom_actions = [CustomSoftwareAction(i18n_label_key='appimage.custom_action.install_file',
i18n_status_key='appimage.custom_action.install_file.status',
manager=self,
@@ -616,16 +617,17 @@ class AppImageManager(SoftwareManager):
return False
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
+ create_config = CreateConfigFile(taskman=task_manager, configman=self.configman, i18n=self.i18n,
+ task_icon_path=get_icon_path(), logger=self.logger)
+ create_config.start()
+
symlink_check = SymlinksVerifier(taskman=task_manager, i18n=self.i18n, logger=self.logger)
symlink_check.start()
if internet_available:
- updater = DatabaseUpdater(taskman=task_manager, i18n=self.context.i18n,
- http_client=self.context.http_client, logger=self.context.logger)
-
- if updater.should_update(read_config()):
- updater.register_task()
- updater.start()
+ DatabaseUpdater(taskman=task_manager, i18n=self.context.i18n,
+ create_config=create_config, http_client=self.context.http_client,
+ logger=self.context.logger).start()
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
res = self.read_installed(disk_loader=None, internet_available=internet_available)
@@ -729,12 +731,12 @@ class AppImageManager(SoftwareManager):
traceback.print_exc()
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
- config = read_config()
+ appimage_config = self.configman.get_config()
max_width = floor(screen_width * 0.15)
opts = [
TextInputComponent(label=self.i18n['appimage.config.database.expiration'],
- value=int(config['database']['expiration']) if isinstance(config['database']['expiration'], int) else '',
+ value=int(appimage_config['database']['expiration']) if isinstance(appimage_config['database']['expiration'], int) else '',
tooltip=self.i18n['appimage.config.database.expiration.tip'],
only_int=True,
max_width=max_width,
@@ -744,13 +746,13 @@ class AppImageManager(SoftwareManager):
return PanelComponent([FormComponent(opts, self.i18n['appimage.config.database'])])
def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
- config = read_config()
+ appimage_config = self.configman.get_config()
panel = component.components[0]
- config['database']['expiration'] = panel.get_component('appim_db_exp').get_int_value()
+ appimage_config['database']['expiration'] = panel.get_component('appim_db_exp').get_int_value()
try:
- save_config(config, CONFIG_FILE)
+ self.configman.save_config(appimage_config)
return True, None
except:
return False, [traceback.format_exc()]
@@ -822,7 +824,7 @@ class AppImageManager(SoftwareManager):
def update_database(self, root_password: str, watcher: ProcessWatcher) -> bool:
db_updater = DatabaseUpdater(i18n=self.i18n, http_client=self.context.http_client,
- logger=self.context.logger, watcher=watcher)
+ logger=self.context.logger, watcher=watcher, taskman=TaskManager())
res = db_updater.download_databases()
return res
diff --git a/bauh/gems/appimage/resources/locale/ca b/bauh/gems/appimage/resources/locale/ca
index 9f3be860..34b228f7 100644
--- a/bauh/gems/appimage/resources/locale/ca
+++ b/bauh/gems/appimage/resources/locale/ca
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removing old files
appimage.update_database.downloading=Downloading database files
appimage.update_database.uncompressing=Uncompressing files
appimage.task.db_update=Actualització de bases de dades
+appimage.task.db_update.checking=Checking for updates
appimage.task.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=No s’ha pogut suprimir el directori d’instal·lació de l’aplicació {}
appimage.warning.missing_db_files={appimage} database files were not found. Some actions will not work properly.
diff --git a/bauh/gems/appimage/resources/locale/de b/bauh/gems/appimage/resources/locale/de
index c924f481..2cccb9bf 100644
--- a/bauh/gems/appimage/resources/locale/de
+++ b/bauh/gems/appimage/resources/locale/de
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removing old files
appimage.update_database.downloading=Downloading database files
appimage.update_database.uncompressing=Uncompressing files
appimage.task.db_update=Updating databases
+appimage.task.db_update.checking=Checking for updates
appimage.task.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Anwendungordner {} konnte nicht entfernt werden
appimage.warning.missing_db_files={appimage} database files were not found. Some actions will not work properly.
diff --git a/bauh/gems/appimage/resources/locale/en b/bauh/gems/appimage/resources/locale/en
index e66cd0b1..04217331 100644
--- a/bauh/gems/appimage/resources/locale/en
+++ b/bauh/gems/appimage/resources/locale/en
@@ -1,6 +1,6 @@
appimage.config.database=Database
appimage.config.database.expiration=Expiration
-appimage.config.database.expiration.tip=appimage.config.database.expiration.tip=It defines the period (in minutes) in which the database will be considered up to date. Use 0 if you always want to update it.
+appimage.config.database.expiration.tip=It defines the period (in minutes) in which the database will be considered up to date. Use 0 if you always want to update it.
appimage.custom_action.install_file=Install AppImage file
appimage.custom_action.install_file.details=Installation details
appimage.custom_action.install_file.invalid_file=You must define a valid AppImage file
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removing old files
appimage.update_database.downloading=Downloading database files
appimage.update_database.uncompressing=Uncompressing files
appimage.task.db_update=Updating databases
+appimage.task.db_update.checking=Checking for updates
appimage.task.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Could not remove the application installation directory {}
appimage.warning.missing_db_files={appimage} database files were not found. Some actions will not work properly.
diff --git a/bauh/gems/appimage/resources/locale/es b/bauh/gems/appimage/resources/locale/es
index b1b97600..047ca4fd 100644
--- a/bauh/gems/appimage/resources/locale/es
+++ b/bauh/gems/appimage/resources/locale/es
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Eliminando archivos antiguos
appimage.update_database.downloading=Descargando archivos de la base de datos
appimage.update_database.uncompressing=Descomprindo archivos
appimage.task.db_update=Actualizando base de datos
+appimage.task.db_update.checking=Buscando actualizaciones
appimage.task.symlink_check=Verificando links simbólicos
appimage.uninstall.error.remove_folder=No se pudo eliminar el directorio de instalación de la aplicación {}
appimage.warning.missing_db_files=No se encontraron archivos de la base de datos {appimage}. Algunas acciones no funcionarán correctamente.
diff --git a/bauh/gems/appimage/resources/locale/fr b/bauh/gems/appimage/resources/locale/fr
index 0efe8d4a..0730d376 100644
--- a/bauh/gems/appimage/resources/locale/fr
+++ b/bauh/gems/appimage/resources/locale/fr
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removing old files
appimage.update_database.downloading=Downloading database files
appimage.update_database.uncompressing=Uncompressing files
appimage.task.db_update=Mise à jour des bases de données
+appimage.task.db_update.checking=Checking for updates
appimage.task.symlink_check=Verification des symlinks
appimage.uninstall.error.remove_folder=Impossible de supprimer le répertoire d'installation {}
appimage.warning.missing_db_files={appimage} database files were not found. Some actions will not work properly.
diff --git a/bauh/gems/appimage/resources/locale/it b/bauh/gems/appimage/resources/locale/it
index 63f34052..72b78692 100644
--- a/bauh/gems/appimage/resources/locale/it
+++ b/bauh/gems/appimage/resources/locale/it
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removing old files
appimage.update_database.downloading=Downloading database files
appimage.update_database.uncompressing=Uncompressing files
appimage.task.db_update=Aggiornamento dei database
+appimage.task.db_update.checking=Checking for updates
appimage.task.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Impossibile rimuovere la directory di installazione dell'applicazione {}
appimage.warning.missing_db_files={appimage} database files were not found. Some actions will not work properly.
diff --git a/bauh/gems/appimage/resources/locale/pt b/bauh/gems/appimage/resources/locale/pt
index 6cc1060c..f4357e77 100644
--- a/bauh/gems/appimage/resources/locale/pt
+++ b/bauh/gems/appimage/resources/locale/pt
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removendo arquicos antigos
appimage.update_database.downloading=Baixando arquivos do banco de dados
appimage.update_database.uncompressing=Descomprimindo arquivos
appimage.task.db_update=Atualizando base de dados
+appimage.task.db_update.checking=Checando atualizações
appimage.task.symlink_check=Verificando links simbólicos
appimage.uninstall.error.remove_folder=Não foi possível remover o diretóri ode instalação do aplicativo {}
appimage.warning.missing_db_files=Arquivos do banco de dados {appimage} não foram encontrados. Algumas ações não funcionarão corretamente.
diff --git a/bauh/gems/appimage/resources/locale/ru b/bauh/gems/appimage/resources/locale/ru
index 06c462d8..adeb3fd1 100644
--- a/bauh/gems/appimage/resources/locale/ru
+++ b/bauh/gems/appimage/resources/locale/ru
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removing old files
appimage.update_database.downloading=Downloading database files
appimage.update_database.uncompressing=Uncompressing files
appimage.task.db_update=Обновление базы данных
+appimage.task.db_update.checking=Checking for updates
appimage.task.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Не удалось удалить каталог приложения {}
appimage.warning.missing_db_files={appimage} database files were not found. Some actions will not work properly.
diff --git a/bauh/gems/appimage/resources/locale/tr b/bauh/gems/appimage/resources/locale/tr
index 8f6c03e0..3173b2f4 100644
--- a/bauh/gems/appimage/resources/locale/tr
+++ b/bauh/gems/appimage/resources/locale/tr
@@ -36,6 +36,7 @@ appimage.update_database.deleting_old=Removing old files
appimage.update_database.downloading=Downloading database files
appimage.update_database.uncompressing=Uncompressing files
appimage.task.db_update=Veritabanları güncelleniyor
+appimage.task.db_update.checking=Checking for updates
appimage.task.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder={} uygulama kurulum dizini kaldırılamadı
appimage.warning.missing_db_files={appimage} database files were not found. Some actions will not work properly.
diff --git a/bauh/gems/appimage/worker.py b/bauh/gems/appimage/worker.py
index 0c209d0d..4ebb3920 100644
--- a/bauh/gems/appimage/worker.py
+++ b/bauh/gems/appimage/worker.py
@@ -12,6 +12,8 @@ from typing import Optional
from bauh.api.abstract.handler import TaskManager, ProcessWatcher
from bauh.api.http import HttpClient
+from bauh.commons.boot import CreateConfigFile
+from bauh.commons.html import bold
from bauh.gems.appimage import get_icon_path, INSTALLATION_PATH, SYMLINKS_DIR, util, DATABASES_TS_FILE, \
DATABASES_DIR, DATABASE_APPS_FILE, DATABASE_RELEASES_FILE, URL_COMPRESSED_DATABASES
from bauh.gems.appimage.model import AppImage
@@ -21,7 +23,8 @@ from bauh.view.util.translation import I18n
class DatabaseUpdater(Thread):
COMPRESS_FILE_PATH = '{}/db.tar.gz'.format(DATABASES_DIR)
- def __init__(self, i18n: I18n, http_client: HttpClient, logger: logging.Logger, watcher: Optional[ProcessWatcher] = None, taskman: Optional[TaskManager] = None):
+ def __init__(self, i18n: I18n, http_client: HttpClient, logger: logging.Logger, taskman: TaskManager,
+ watcher: Optional[ProcessWatcher] = None, appimage_config: Optional[dict] = None, create_config: Optional[CreateConfigFile] = None):
super(DatabaseUpdater, self).__init__(daemon=True)
self.http_client = http_client
self.logger = logger
@@ -29,6 +32,9 @@ class DatabaseUpdater(Thread):
self.taskman = taskman
self.watcher = watcher
self.task_id = 'appim_db'
+ self.config = appimage_config
+ self.create_config = create_config
+ self.taskman.register_task(self.task_id, self.i18n['appimage.task.db_update'], get_icon_path())
def should_update(self, appimage_config: dict) -> bool:
ti = time.time()
@@ -75,26 +81,14 @@ class DatabaseUpdater(Thread):
self.logger.info('Finished. Took {0:.2f} seconds'.format(time.time() - ti))
return update
- def register_task(self):
- if self.taskman:
- self.taskman.register_task(self.task_id, self.i18n['appimage.task.db_update'], get_icon_path())
-
- def _finish_task(self):
- if self.taskman:
- self.taskman.update_progress(self.task_id, 100, None)
- self.taskman.finish_task(self.task_id)
- self.taskman = None
- self.logger.info("Finished")
-
def _update_task_progress(self, progress: float, substatus: Optional[str] = None):
- if self.taskman:
- self.taskman.update_progress(self.task_id, progress, substatus)
+ self.taskman.update_progress(self.task_id, progress, substatus)
if self.watcher:
self.watcher.change_substatus(substatus)
def download_databases(self) -> bool:
- self._update_task_progress(1, self.i18n['appimage.update_database.downloading'])
+ self._update_task_progress(10, self.i18n['appimage.update_database.downloading'])
self.logger.info('Retrieving AppImage databases')
database_timestamp = datetime.utcnow().timestamp()
@@ -106,7 +100,6 @@ class DatabaseUpdater(Thread):
if not res:
self.logger.warning('Could not download the database file {}'.format(URL_COMPRESSED_DATABASES))
- self._finish_task()
return False
Path(DATABASES_DIR).mkdir(parents=True, exist_ok=True)
@@ -150,11 +143,25 @@ class DatabaseUpdater(Thread):
self.logger.info("Database timestamp saved")
- self._finish_task()
return True
def run(self):
- self.download_databases()
+ ti = time.time()
+
+ if self.create_config:
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(bold(self.create_config.task_name)))
+ self.create_config.join()
+ self.config = self.create_config.config
+
+ self.taskman.update_progress(self.task_id, 1, self.i18n['appimage.task.db_update.checking'])
+
+ if self.should_update(self.config):
+ self.download_databases()
+
+ self.taskman.update_progress(self.task_id, 100, None)
+ self.taskman.finish_task(self.task_id)
+ tf = time.time()
+ self.logger.info("Finished. Took {0:.2f} seconds".format(tf - ti))
class SymlinksVerifier(Thread):
@@ -165,6 +172,7 @@ class SymlinksVerifier(Thread):
self.i18n = i18n
self.logger = logger
self.task_id = 'appim_symlink_check'
+ self.taskman.register_task(self.task_id, self.i18n['appimage.task.symlink_check'], get_icon_path())
@staticmethod
def create_symlink(app: AppImage, file_path: str, logger: logging.Logger, watcher: ProcessWatcher = None):
@@ -222,8 +230,6 @@ class SymlinksVerifier(Thread):
watcher.print('[error] {}'.format(msg))
def run(self):
- self.taskman.register_task(self.task_id, self.i18n['appimage.task.symlink_check'], get_icon_path())
-
if os.path.exists(INSTALLATION_PATH):
installed_files = glob.glob('{}/*/*.json'.format(INSTALLATION_PATH))
diff --git a/bauh/gems/arch/config.py b/bauh/gems/arch/config.py
index f4bea0cd..ecd4f9f7 100644
--- a/bauh/gems/arch/config.py
+++ b/bauh/gems/arch/config.py
@@ -1,11 +1,26 @@
from pathlib import Path
-from bauh.commons.config import read_config as read
+from bauh.commons.config import YAMLConfigManager
from bauh.gems.arch import CONFIG_FILE, BUILD_DIR
-def read_config(update_file: bool = False) -> dict:
- template = {'optimize': True,
+def get_build_dir(arch_config: dict) -> str:
+ build_dir = arch_config.get('aur_build_dir')
+
+ if not build_dir:
+ build_dir = BUILD_DIR
+
+ Path(build_dir).mkdir(parents=True, exist_ok=True)
+ return build_dir
+
+
+class ArchConfigManager(YAMLConfigManager):
+
+ def __init__(self):
+ super(ArchConfigManager, self).__init__(config_file_path=CONFIG_FILE)
+
+ def get_default_config(self) -> dict:
+ return {'optimize': True,
"sync_databases": True,
"clean_cached": True,
'aur': True,
@@ -24,14 +39,3 @@ def read_config(update_file: bool = False) -> dict:
'suggest_optdep_uninstall': False,
'aur_idx_exp': 720,
'categories_exp': 24}
- return read(CONFIG_FILE, template, update_file=update_file)
-
-
-def get_build_dir(arch_config: dict) -> str:
- build_dir = arch_config.get('aur_build_dir')
-
- if not build_dir:
- build_dir = BUILD_DIR
-
- Path(build_dir).mkdir(parents=True, exist_ok=True)
- return build_dir
diff --git a/bauh/gems/arch/controller.py b/bauh/gems/arch/controller.py
index a27d8c76..e8ec10a2 100644
--- a/bauh/gems/arch/controller.py
+++ b/bauh/gems/arch/controller.py
@@ -27,18 +27,18 @@ from bauh.api.abstract.view import MessageType, FormComponent, InputOption, Sing
FileChooserComponent, TextComponent
from bauh.api.constants import TEMP_DIR
from bauh.commons import user, system
+from bauh.commons.boot import CreateConfigFile
from bauh.commons.category import CategoriesDownloader
-from bauh.commons.config import save_config
from bauh.commons.html import bold
from bauh.commons.system import SystemProcess, ProcessHandler, new_subprocess, run_cmd, SimpleProcess
from bauh.commons.util import datetime_as_milis
from bauh.commons.view_utils import new_select
from bauh.gems.arch import aur, pacman, makepkg, message, confirmation, disk, git, \
gpg, URL_CATEGORIES_FILE, CATEGORIES_FILE_PATH, CUSTOM_MAKEPKG_FILE, SUGGESTIONS_FILE, \
- CONFIG_FILE, get_icon_path, database, mirrors, sorting, cpu_manager, ARCH_CACHE_PATH, UPDATES_IGNORED_FILE, \
+ get_icon_path, database, mirrors, sorting, cpu_manager, UPDATES_IGNORED_FILE, \
CONFIG_DIR, EDITABLE_PKGBUILDS_FILE, URL_GPG_SERVERS, BUILD_DIR
from bauh.gems.arch.aur import AURClient
-from bauh.gems.arch.config import read_config, get_build_dir
+from bauh.gems.arch.config import get_build_dir, ArchConfigManager
from bauh.gems.arch.dependencies import DependenciesAnalyser
from bauh.gems.arch.download import MultithreadedDownloadService, ArchDownloadException
from bauh.gems.arch.exceptions import PackageNotFoundException, PackageInHoldException
@@ -47,8 +47,8 @@ from bauh.gems.arch.model import ArchPackage
from bauh.gems.arch.output import TransactionStatusHandler
from bauh.gems.arch.pacman import RE_DEP_OPERATORS
from bauh.gems.arch.updates import UpdatesSummarizer
-from bauh.gems.arch.worker import AURIndexUpdater, ArchDiskCacheUpdater, ArchCompilationOptimizer, SyncDatabases, \
- RefreshMirrors
+from bauh.gems.arch.worker import AURIndexUpdater, ArchDiskCacheUpdater, ArchCompilationOptimizer, RefreshMirrors, \
+ SyncDatabases
URL_GIT = 'https://aur.archlinux.org/{}.git'
URL_SRC_INFO = 'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h='
@@ -191,11 +191,11 @@ class TransactionContext:
class ArchManager(SoftwareManager):
- def __init__(self, context: ApplicationContext, disk_cache_updater: ArchDiskCacheUpdater = None):
+ def __init__(self, context: ApplicationContext, disk_cache_updater: Optional[ArchDiskCacheUpdater] = None):
super(ArchManager, self).__init__(context=context)
self.aur_cache = context.cache_factory.new()
# context.disk_loader_factory.map(ArchPackage, self.aur_cache) TODO
-
+ self.configman = ArchConfigManager()
self.aur_mapper = AURDataMapper(http_client=context.http_client, i18n=context.i18n, logger=context.logger)
self.i18n = context.i18n
self.aur_client = AURClient(http_client=context.http_client, logger=context.logger, x86_64=context.is_system_x86_64())
@@ -309,7 +309,7 @@ class ArchManager(SoftwareManager):
type_=MessageType.ERROR)
return False
- sort_limit = read_config()['mirrors_sort_limit']
+ sort_limit = self.configman.get_config()['mirrors_sort_limit']
if sort_limit is not None and isinstance(sort_limit, int) and sort_limit >= 0:
watcher.change_substatus(self.i18n['arch.custom_action.refresh_mirrors.status.sorting'])
@@ -419,7 +419,7 @@ class ArchManager(SoftwareManager):
if is_url:
return SearchResult([], [], 0)
- arch_config = read_config()
+ arch_config = self.configman.get_config()
aur_supported = aur.is_supported(arch_config)
if not any([arch_config['repositories'], aur_supported]):
@@ -563,7 +563,7 @@ class ArchManager(SoftwareManager):
def read_installed(self, disk_loader: Optional[DiskCacheLoader], limit: int = -1, only_apps: bool = False, pkg_types: Set[Type[SoftwarePackage]] = None, internet_available: bool = None, names: Iterable[str] = None, wait_disk_cache: bool = True) -> SearchResult:
self.aur_client.clean_caches()
- arch_config = read_config()
+ arch_config = self.configman.get_config()
aur_supported = aur.is_supported(arch_config)
@@ -781,7 +781,7 @@ class ArchManager(SoftwareManager):
if self._is_database_locked(handler, root_password):
return False
- arch_config = read_config()
+ arch_config = self.configman.get_config()
aur_supported = pkg.repository == 'aur' or aur.is_supported(arch_config)
context = TransactionContext(name=pkg.name, base=pkg.get_base_name(), skip_opt_deps=True,
change_progress=True, dependency=False, repository=pkg.repository, pkg=pkg,
@@ -1105,7 +1105,7 @@ class ArchManager(SoftwareManager):
if aur_pkgs and not self._check_action_allowed(aur_pkgs[0], watcher):
return False
- arch_config = read_config()
+ arch_config = self.configman.get_config()
aur_supported = bool(aur_pkgs) or aur.is_supported(arch_config)
self._sync_databases(arch_config=arch_config, aur_supported=aur_supported,
@@ -1392,7 +1392,7 @@ class ArchManager(SoftwareManager):
return TransactionResult.fail()
removed = {}
- arch_config = read_config()
+ arch_config = self.configman.get_config()
success = self._uninstall(TransactionContext(change_progress=True,
arch_config=arch_config,
watcher=watcher,
@@ -1520,7 +1520,7 @@ class ArchManager(SoftwareManager):
else:
self.logger.warning("Package '{}' has no commit associated with it. Current history status may not be correct.".format(pkg.name))
- arch_config = read_config()
+ arch_config = self.configman.get_config()
temp_dir = '{}/build_{}'.format(get_build_dir(arch_config), int(time.time()))
try:
@@ -1938,7 +1938,7 @@ class ArchManager(SoftwareManager):
watcher.change_substatus(self.i18n['arch.task.aur.index.status'])
idx_updater = AURIndexUpdater(context=self.context, taskman=TaskManager()) # null task manager
- idx_updater.run()
+ idx_updater.update_index()
else:
self.logger.warning("Could not update the AUR index: no internet connection detected")
@@ -2488,7 +2488,7 @@ class ArchManager(SoftwareManager):
def _optimize_makepkg(self, arch_config: dict, watcher: Optional[ProcessWatcher]):
if arch_config['optimize'] and not os.path.exists(CUSTOM_MAKEPKG_FILE):
watcher.change_substatus(self.i18n['arch.makepkg.optimizing'])
- ArchCompilationOptimizer(arch_config=arch_config, i18n=self.i18n, logger=self.context.logger).optimize()
+ ArchCompilationOptimizer(i18n=self.i18n, logger=self.context.logger, taskman=TaskManager()).optimize()
def install(self, pkg: ArchPackage, root_password: str, disk_loader: Optional[DiskCacheLoader], watcher: ProcessWatcher, context: TransactionContext = None) -> TransactionResult:
self.aur_client.clean_caches()
@@ -2504,7 +2504,7 @@ class ArchManager(SoftwareManager):
if context:
install_context = context
else:
- install_context = TransactionContext.gen_context_from(pkg=pkg, handler=handler, arch_config=read_config(),
+ install_context = TransactionContext.gen_context_from(pkg=pkg, handler=handler, arch_config=self.configman.get_config(),
root_password=root_password)
install_context.skip_opt_deps = False
install_context.disk_loader = disk_loader
@@ -2612,68 +2612,68 @@ class ArchManager(SoftwareManager):
def requires_root(self, action: SoftwareAction, pkg: ArchPackage) -> bool:
if action == SoftwareAction.PREPARE:
- arch_config = read_config()
+ arch_config = self.configman.get_config()
+ aur_supported = (pkg and pkg.repository == 'aur') or aur.is_supported(arch_config)
- if arch_config['refresh_mirrors_startup'] and mirrors.should_sync(self.logger):
+ if RefreshMirrors.should_synchronize(arch_config, aur_supported, self.logger):
return True
- aur_supported = (pkg and pkg.repository == 'aur') or aur.is_supported(arch_config)
- return arch_config['sync_databases_startup'] and database.should_sync(arch_config, aur_supported, None, self.logger)
+ return SyncDatabases.should_sync(mirrors_refreshed=False, arch_config=arch_config,
+ aur_supported=aur_supported, logger=self.logger)
return action != SoftwareAction.SEARCH
- def _start_category_task(self, task_man: TaskManager):
- task_man.register_task('arch_aur_cats', self.i18n['task.download_categories'], get_icon_path())
- task_man.update_progress('arch_aur_cats', 50, None)
+ def _start_category_task(self, taskman: TaskManager, create_config: CreateConfigFile, downloader: CategoriesDownloader):
+ taskman.update_progress('arch_aur_cats', 0, self.i18n['task.waiting_task'].format(bold(create_config.task_name)))
+ create_config.join()
+ arch_config = create_config.config
- def _finish_category_task(self, task_man: TaskManager):
- task_man.update_progress('arch_aur_cats', 100, None)
- task_man.finish_task('arch_aur_cats')
+ downloader.expiration = arch_config['categories_exp'] if isinstance(arch_config['categories_exp'], int) else None
+ taskman.update_progress('arch_aur_cats', 50, None)
+
+ def _finish_category_task(self, taskman: TaskManager):
+ taskman.update_progress('arch_aur_cats', 100, None)
+ taskman.finish_task('arch_aur_cats')
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
- arch_config = read_config(update_file=True)
+ create_config = CreateConfigFile(taskman=task_manager, configman=self.configman, i18n=self.i18n,
+ task_icon_path=get_icon_path(), logger=self.logger)
+ create_config.start()
- if internet_available and AURIndexUpdater.should_update(arch_config):
- self.index_aur = AURIndexUpdater(context=self.context, taskman=task_manager) # must all execute to properly determine the installed packages (even that AUR is disabled)
+ if internet_available:
+ self.index_aur = AURIndexUpdater(context=self.context, taskman=task_manager, create_config=create_config) # must always execute to properly determine the installed packages (even that AUR is disabled)
self.index_aur.start()
- aur_supported = aur.is_supported(arch_config)
-
- if aur_supported:
- ArchCompilationOptimizer(arch_config, self.i18n, self.context.logger, task_manager).start()
-
- if aur_supported or arch_config['repositories']:
- self.disk_cache_updater = ArchDiskCacheUpdater(task_man=task_manager,
- arch_config=arch_config,
- i18n=self.i18n,
- logger=self.context.logger,
- controller=self,
- internet_available=internet_available,
- aur_indexer=self.index_aur,
- aur_supported=aur_supported)
- self.disk_cache_updater.start()
-
- CategoriesDownloader(id_='Arch', http_client=self.context.http_client, logger=self.context.logger,
- manager=self, url_categories_file=URL_CATEGORIES_FILE,
- categories_path=CATEGORIES_FILE_PATH,
- expiration=arch_config['categories_exp'] if isinstance(arch_config['categories_exp'], int) else '',
- internet_connection=internet_available,
- internet_checker=self.context.internet_checker,
- before=lambda: self._start_category_task(task_manager),
- after=lambda: self._finish_category_task(task_manager)).start()
-
- refresh_mirrors = None
- if internet_available and arch_config['repositories'] and arch_config['refresh_mirrors_startup'] \
- and pacman.is_mirrors_available() and mirrors.should_sync(self.logger):
-
- refresh_mirrors = RefreshMirrors(taskman=task_manager, i18n=self.i18n,
- root_password=root_password, logger=self.logger,
- sort_limit=arch_config['mirrors_sort_limit'])
+ refresh_mirrors = RefreshMirrors(taskman=task_manager, i18n=self.i18n, root_password=root_password,
+ logger=self.logger, create_config=create_config)
refresh_mirrors.start()
- if internet_available and (refresh_mirrors or (arch_config['sync_databases_startup'] and database.should_sync(arch_config, aur_supported, None, self.logger))):
SyncDatabases(taskman=task_manager, root_password=root_password, i18n=self.i18n,
- logger=self.logger, refresh_mirrors=refresh_mirrors).start()
+ logger=self.logger, refresh_mirrors=refresh_mirrors, create_config=create_config).start()
+
+ ArchCompilationOptimizer(i18n=self.i18n, logger=self.context.logger,
+ taskman=task_manager, create_config=create_config).start()
+
+ self.disk_cache_updater = ArchDiskCacheUpdater(taskman=task_manager,
+ i18n=self.i18n,
+ logger=self.context.logger,
+ controller=self,
+ internet_available=internet_available,
+ aur_indexer=self.index_aur,
+ create_config=create_config)
+ self.disk_cache_updater.start()
+
+ task_manager.register_task('arch_aur_cats', self.i18n['task.download_categories'], get_icon_path())
+ cat_download = CategoriesDownloader(id_='Arch', http_client=self.context.http_client,
+ logger=self.context.logger,
+ manager=self, url_categories_file=URL_CATEGORIES_FILE,
+ categories_path=CATEGORIES_FILE_PATH,
+ internet_connection=internet_available,
+ internet_checker=self.context.internet_checker,
+ after=lambda: self._finish_category_task(task_manager))
+ cat_download.before = lambda: self._start_category_task(taskman=task_manager, create_config=create_config,
+ downloader=cat_download)
+ cat_download.start()
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
installed = self.read_installed(disk_loader=None, internet_available=internet_available).installed
@@ -2763,90 +2763,92 @@ class ArchManager(SoftwareManager):
capitalize_label=capitalize_label)
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
- local_config = read_config()
+ arch_config = self.configman.get_config()
max_width = floor(screen_width * 0.25)
db_sync_start = self._gen_bool_selector(id_='sync_dbs_start',
label_key='arch.config.sync_dbs',
tooltip_key='arch.config.sync_dbs_start.tip',
- value=bool(local_config['sync_databases_startup']),
+ value=bool(arch_config['sync_databases_startup']),
max_width=max_width)
- db_sync_start.label += ' ( {} )'.format(self.i18n['initialization'].capitalize())
+ db_sync_start.label += ' ({})'.format(self.i18n['initialization'].capitalize())
fields = [
self._gen_bool_selector(id_='repos',
label_key='arch.config.repos',
tooltip_key='arch.config.repos.tip',
- value=bool(local_config['repositories']),
+ value=bool(arch_config['repositories']),
max_width=max_width),
self._gen_bool_selector(id_='aur',
label_key='arch.config.aur',
tooltip_key='arch.config.aur.tip',
- value=local_config['aur'],
+ value=arch_config['aur'],
max_width=max_width,
capitalize_label=False),
self._gen_bool_selector(id_='opts',
label_key='arch.config.optimize',
tooltip_key='arch.config.optimize.tip',
- value=bool(local_config['optimize']),
+ value=bool(arch_config['optimize']),
+ label_params=['(AUR)'],
+ capitalize_label=False,
max_width=max_width),
self._gen_bool_selector(id_='autoprovs',
label_key='arch.config.automatch_providers',
tooltip_key='arch.config.automatch_providers.tip',
- value=bool(local_config['automatch_providers']),
+ value=bool(arch_config['automatch_providers']),
max_width=max_width),
self._gen_bool_selector(id_='check_dependency_breakage',
label_key='arch.config.check_dependency_breakage',
tooltip_key='arch.config.check_dependency_breakage.tip',
- value=bool(local_config['check_dependency_breakage']),
+ value=bool(arch_config['check_dependency_breakage']),
max_width=max_width),
self._gen_bool_selector(id_='mthread_download',
label_key='arch.config.pacman_mthread_download',
tooltip_key='arch.config.pacman_mthread_download.tip',
- value=local_config['repositories_mthread_download'],
+ value=arch_config['repositories_mthread_download'],
max_width=max_width,
capitalize_label=True),
self._gen_bool_selector(id_='sync_dbs',
label_key='arch.config.sync_dbs',
tooltip_key='arch.config.sync_dbs.tip',
- value=bool(local_config['sync_databases']),
+ value=bool(arch_config['sync_databases']),
max_width=max_width),
db_sync_start,
self._gen_bool_selector(id_='clean_cached',
label_key='arch.config.clean_cache',
tooltip_key='arch.config.clean_cache.tip',
- value=bool(local_config['clean_cached']),
+ value=bool(arch_config['clean_cached']),
max_width=max_width),
self._gen_bool_selector(id_='suggest_unneeded_uninstall',
label_key='arch.config.suggest_unneeded_uninstall',
tooltip_params=['"{}"'.format(self.i18n['arch.config.suggest_optdep_uninstall'])],
tooltip_key='arch.config.suggest_unneeded_uninstall.tip',
- value=bool(local_config['suggest_unneeded_uninstall']),
+ value=bool(arch_config['suggest_unneeded_uninstall']),
max_width=max_width),
self._gen_bool_selector(id_='suggest_optdep_uninstall',
label_key='arch.config.suggest_optdep_uninstall',
tooltip_key='arch.config.suggest_optdep_uninstall.tip',
- value=bool(local_config['suggest_optdep_uninstall']),
+ value=bool(arch_config['suggest_optdep_uninstall']),
max_width=max_width),
self._gen_bool_selector(id_='ref_mirs',
label_key='arch.config.refresh_mirrors',
tooltip_key='arch.config.refresh_mirrors.tip',
- value=bool(local_config['refresh_mirrors_startup']),
+ value=bool(arch_config['refresh_mirrors_startup']),
max_width=max_width),
TextInputComponent(id_='mirrors_sort_limit',
label=self.i18n['arch.config.mirrors_sort_limit'],
tooltip=self.i18n['arch.config.mirrors_sort_limit.tip'],
only_int=True,
max_width=max_width,
- value=local_config['mirrors_sort_limit'] if isinstance(local_config['mirrors_sort_limit'], int) else ''),
+ value=arch_config['mirrors_sort_limit'] if isinstance(arch_config['mirrors_sort_limit'], int) else ''),
TextInputComponent(id_='aur_idx_exp',
label=self.i18n['arch.config.aur_idx_exp'] + ' (AUR)',
tooltip=self.i18n['arch.config.aur_idx_exp.tip'],
max_width=max_width,
only_int=True,
capitalize_label=False,
- value=local_config['aur_idx_exp'] if isinstance(local_config['aur_idx_exp'], int) else ''),
+ value=arch_config['aur_idx_exp'] if isinstance(arch_config['aur_idx_exp'], int) else ''),
new_select(id_='aur_build_only_chosen',
label=self.i18n['arch.config.aur_build_only_chosen'],
tip=self.i18n['arch.config.aur_build_only_chosen.tip'],
@@ -2854,7 +2856,7 @@ class ArchManager(SoftwareManager):
(self.i18n['no'].capitalize(), False, None),
(self.i18n['ask'].capitalize(), None, None),
],
- value=local_config['aur_build_only_chosen'],
+ value=arch_config['aur_build_only_chosen'],
max_width=max_width,
type_=SelectViewType.RADIO,
capitalize_label=False),
@@ -2865,21 +2867,21 @@ class ArchManager(SoftwareManager):
(self.i18n['no'].capitalize(), False, None),
(self.i18n['ask'].capitalize(), None, None),
],
- value=local_config['edit_aur_pkgbuild'],
+ value=arch_config['edit_aur_pkgbuild'],
max_width=max_width,
type_=SelectViewType.RADIO,
capitalize_label=False),
self._gen_bool_selector(id_='aur_remove_build_dir',
label_key='arch.config.aur_remove_build_dir',
tooltip_key='arch.config.aur_remove_build_dir.tip',
- value=bool(local_config['aur_remove_build_dir']),
+ value=bool(arch_config['aur_remove_build_dir']),
max_width=max_width,
capitalize_label=False),
FileChooserComponent(id_='aur_build_dir',
label=self.i18n['arch.config.aur_build_dir'],
tooltip=self.i18n['arch.config.aur_build_dir.tip'].format(BUILD_DIR),
max_width=max_width,
- file_path=local_config['aur_build_dir'],
+ file_path=arch_config['aur_build_dir'],
capitalize_label=False,
directory=True),
TextInputComponent(id_='arch_cats_exp',
@@ -2888,47 +2890,47 @@ class ArchManager(SoftwareManager):
max_width=max_width,
only_int=True,
capitalize_label=False,
- value=local_config['categories_exp'] if isinstance(local_config['categories_exp'], int) else ''),
+ value=arch_config['categories_exp'] if isinstance(arch_config['categories_exp'], int) else ''),
]
return PanelComponent([FormComponent(fields, spaces=False)])
def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
- config = read_config()
+ arch_config = self.configman.get_config()
panel = component.components[0]
- config['repositories'] = panel.get_component('repos').get_selected()
- config['aur'] = panel.get_component('aur').get_selected()
- config['optimize'] = panel.get_component('opts').get_selected()
- config['sync_databases'] = panel.get_component('sync_dbs').get_selected()
- config['sync_databases_startup'] = panel.get_component('sync_dbs_start').get_selected()
- config['clean_cached'] = panel.get_component('clean_cached').get_selected()
- config['refresh_mirrors_startup'] = panel.get_component('ref_mirs').get_selected()
- config['mirrors_sort_limit'] = panel.get_component('mirrors_sort_limit').get_int_value()
- config['repositories_mthread_download'] = panel.get_component('mthread_download').get_selected()
- config['automatch_providers'] = panel.get_component('autoprovs').get_selected()
- config['edit_aur_pkgbuild'] = panel.get_component('edit_aur_pkgbuild').get_selected()
- config['aur_remove_build_dir'] = panel.get_component('aur_remove_build_dir').get_selected()
- config['aur_build_dir'] = panel.get_component('aur_build_dir').file_path
- config['aur_build_only_chosen'] = panel.get_component('aur_build_only_chosen').get_selected()
- config['aur_idx_exp'] = panel.get_component('aur_idx_exp').get_int_value()
- config['check_dependency_breakage'] = panel.get_component('check_dependency_breakage').get_selected()
- config['suggest_optdep_uninstall'] = panel.get_component('suggest_optdep_uninstall').get_selected()
- config['suggest_unneeded_uninstall'] = panel.get_component('suggest_unneeded_uninstall').get_selected()
- config['categories_exp'] = panel.get_component('arch_cats_exp').get_int_value()
+ arch_config['repositories'] = panel.get_component('repos').get_selected()
+ arch_config['aur'] = panel.get_component('aur').get_selected()
+ arch_config['optimize'] = panel.get_component('opts').get_selected()
+ arch_config['sync_databases'] = panel.get_component('sync_dbs').get_selected()
+ arch_config['sync_databases_startup'] = panel.get_component('sync_dbs_start').get_selected()
+ arch_config['clean_cached'] = panel.get_component('clean_cached').get_selected()
+ arch_config['refresh_mirrors_startup'] = panel.get_component('ref_mirs').get_selected()
+ arch_config['mirrors_sort_limit'] = panel.get_component('mirrors_sort_limit').get_int_value()
+ arch_config['repositories_mthread_download'] = panel.get_component('mthread_download').get_selected()
+ arch_config['automatch_providers'] = panel.get_component('autoprovs').get_selected()
+ arch_config['edit_aur_pkgbuild'] = panel.get_component('edit_aur_pkgbuild').get_selected()
+ arch_config['aur_remove_build_dir'] = panel.get_component('aur_remove_build_dir').get_selected()
+ arch_config['aur_build_dir'] = panel.get_component('aur_build_dir').file_path
+ arch_config['aur_build_only_chosen'] = panel.get_component('aur_build_only_chosen').get_selected()
+ arch_config['aur_idx_exp'] = panel.get_component('aur_idx_exp').get_int_value()
+ arch_config['check_dependency_breakage'] = panel.get_component('check_dependency_breakage').get_selected()
+ arch_config['suggest_optdep_uninstall'] = panel.get_component('suggest_optdep_uninstall').get_selected()
+ arch_config['suggest_unneeded_uninstall'] = panel.get_component('suggest_unneeded_uninstall').get_selected()
+ arch_config['categories_exp'] = panel.get_component('arch_cats_exp').get_int_value()
- if not config['aur_build_dir']:
- config['aur_build_dir'] = None
+ if not arch_config['aur_build_dir']:
+ arch_config['aur_build_dir'] = None
try:
- save_config(config, CONFIG_FILE)
+ self.configman.save_config(arch_config)
return True, None
except:
return False, [traceback.format_exc()]
def get_upgrade_requirements(self, pkgs: List[ArchPackage], root_password: str, watcher: ProcessWatcher) -> UpgradeRequirements:
self.aur_client.clean_caches()
- arch_config = read_config()
+ arch_config = self.configman.get_config()
aur_supported = aur.is_supported(arch_config)
@@ -2949,7 +2951,7 @@ class ArchManager(SoftwareManager):
def get_custom_actions(self) -> List[CustomSoftwareAction]:
actions = []
- arch_config = read_config()
+ arch_config = self.configman.get_config()
if pacman.is_mirrors_available():
actions.append(self.custom_actions['ref_mirrors'])
diff --git a/bauh/gems/arch/pacman.py b/bauh/gems/arch/pacman.py
index b929f266..13cadd25 100644
--- a/bauh/gems/arch/pacman.py
+++ b/bauh/gems/arch/pacman.py
@@ -497,7 +497,8 @@ def get_current_mirror_countries() -> List[str]:
def is_mirrors_available() -> bool:
- return bool(run_cmd('which pacman-mirrors', print_error=False))
+ code, _ = system.execute(cmd='which pacman-mirrors', output=False)
+ return code == 0
def map_update_sizes(pkgs: List[str]) -> Dict[str, int]: # bytes:
diff --git a/bauh/gems/arch/resources/locale/ca b/bauh/gems/arch/resources/locale/ca
index c7fb64e3..4860325d 100644
--- a/bauh/gems/arch/resources/locale/ca
+++ b/bauh/gems/arch/resources/locale/ca
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Index expiration
arch.config.aur_idx_exp.tip=It defines the period (in minutes) for the AUR index stored in disc to be considered valid during the initialization process. Use 0 so that it is always updated.
arch.config.mirrors_sort_limit=Mirrors sort limit
arch.config.mirrors_sort_limit.tip=Defines the maximum number of mirrors that will be used for speed sorting. Use 0 for no limit or leave it blank to disable sorting.
-arch.config.optimize=optimize
+arch.config.optimize=Optimize {}
arch.config.optimize.tip=La configuració optimitzada s'utilitzarà per fer més ràpida la instal·lació, actualització i reversió dels paquets, en cas contrari s'utilitzarà la configuració del sistema.
arch.config.pacman_mthread_download=Multithreaded download (repositories)
arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed.
arch.config.refresh_mirrors=Refresh mirrors on startup
-arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
+arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Running pre-transaction hooks
arch.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Synchronizing package databases
arch.sync_databases.substatus.error=It was not possible to synchronize the package database
+arch.sync_databases.substatus.synchronized=Synchronized
arch.task.aur.index.status=Generating local AUR index
+arch.task.aur.index.substatus.checking=Checking for updates
arch.task.aur.index.substatus.download=Downloading the AUR index
arch.task.aur.index.substatus.error.download=Connection error while downloading the index
arch.task.aur.index.substatus.error.no_data=Error: empty index
arch.task.aur.index.substatus.gen_index=Generating index
+arch.task.checking_settings=Checking settings
+arch.task.disabled=Disabled
arch.task.disk_cache=Indexing packages data
arch.task.disk_cache.checking=Checking index
arch.task.disk_cache.indexed=Indexed
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexing
arch.task.disk_cache.reading_files=Reading files
arch.task.disk_cache.waiting_aur_index=Waiting {}
arch.task.mirrors=Refreshing mirrors
+arch.task.mirrors.cached=Refreshed
arch.task.optimizing=Optimizing {}
-arch.task.sync_databases.waiting=Waiting for {}
arch.task.sync_sb.status=Actualitzen {}
arch.uninstall.clean_cached.error=No s'ha pogut eliminar {} versions antigues que es troba al disc
arch.uninstall.clean_cached.substatus=Eliminació de versions antigues del disc
diff --git a/bauh/gems/arch/resources/locale/de b/bauh/gems/arch/resources/locale/de
index e0804d17..6c0168c5 100644
--- a/bauh/gems/arch/resources/locale/de
+++ b/bauh/gems/arch/resources/locale/de
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Index expiration
arch.config.aur_idx_exp.tip=It defines the period (in minutes) for the AUR index stored in disc to be considered valid during the initialization process. Use 0 so that it is always updated.
arch.config.mirrors_sort_limit=Mirrors sort limit
arch.config.mirrors_sort_limit.tip=Defines the maximum number of mirrors that will be used for speed sorting. Use 0 for no limit or leave it blank to disable sorting.
-arch.config.optimize=optimize
+arch.config.optimize=Optimize {}
arch.config.optimize.tip=Optimized settings will be used in order to make the packages installation, upgrading and downgrading faster, otherwise the system settings will be used
arch.config.pacman_mthread_download=Multithreaded download (repositories)
arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed.
arch.config.refresh_mirrors=Refresh mirrors on startup
-arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
+arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Running pre-transaction hooks
arch.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Synchronizing package databases
arch.sync_databases.substatus.error=It was not possible to synchronize the package database
+arch.sync_databases.substatus.synchronized=Synchronized
arch.task.aur.index.status=Generating local AUR index
+arch.task.aur.index.substatus.checking=Checking for updates
arch.task.aur.index.substatus.download=Downloading the AUR index
arch.task.aur.index.substatus.error.download=Connection error while downloading the index
arch.task.aur.index.substatus.error.no_data=Error: empty index
arch.task.aur.index.substatus.gen_index=Generating index
+arch.task.checking_settings=Checking settings
+arch.task.disabled=Disabled
arch.task.disk_cache=Indexing packages data
arch.task.disk_cache.checking=Checking index
arch.task.disk_cache.indexed=Indexed
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexing
arch.task.disk_cache.reading_files=Reading files
arch.task.disk_cache.waiting_aur_index=Waiting {}
arch.task.mirrors=Refreshing mirrors
+arch.task.mirrors.cached=Refreshed
arch.task.optimizing=Optimizing {}
-arch.task.sync_databases.waiting=Waiting for {}
arch.task.sync_sb.status=Updating {}
arch.uninstall.clean_cached.error=It was not possible to remove old {} versions found on disk
arch.uninstall.clean_cached.substatus=Removing old versions from disk
diff --git a/bauh/gems/arch/resources/locale/en b/bauh/gems/arch/resources/locale/en
index 5de9022e..ef81ee91 100644
--- a/bauh/gems/arch/resources/locale/en
+++ b/bauh/gems/arch/resources/locale/en
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Index expiration
arch.config.aur_idx_exp.tip=It defines the period (in minutes) for the AUR index stored in disc to be considered valid during the initialization process. Use 0 so that it is always updated.
arch.config.mirrors_sort_limit=Mirrors sort limit
arch.config.mirrors_sort_limit.tip=Defines the maximum number of mirrors that will be used for speed sorting. Use 0 for no limit or leave it blank to disable sorting.
-arch.config.optimize=optimize
+arch.config.optimize=Optimize {}
arch.config.optimize.tip=Optimized settings will be used in order to make the packages installation, upgrading and downgrading faster, otherwise the system settings will be used
arch.config.pacman_mthread_download=Multi-threaded download (repositories)
arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed.
arch.config.refresh_mirrors=Refresh mirrors on startup
-arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
+arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Running pre-transaction hooks
arch.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Synchronizing package databases
arch.sync_databases.substatus.error=It was not possible to synchronize the package database
+arch.sync_databases.substatus.synchronized=Synchronized
arch.task.aur.index.status=Generating local AUR index
+arch.task.aur.index.substatus.checking=Checking for updates
arch.task.aur.index.substatus.download=Downloading the AUR index
arch.task.aur.index.substatus.error.download=Connection error while downloading the index
arch.task.aur.index.substatus.error.no_data=Error: empty index
arch.task.aur.index.substatus.gen_index=Generating index
+arch.task.checking_settings=Checking settings
+arch.task.disabled=Disabled
arch.task.disk_cache=Indexing packages data
arch.task.disk_cache.checking=Checking index
arch.task.disk_cache.indexed=Indexed
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexing
arch.task.disk_cache.reading_files=Reading files
arch.task.disk_cache.waiting_aur_index=Waiting {}
arch.task.mirrors=Refreshing mirrors
+arch.task.mirrors.cached=Refreshed
arch.task.optimizing=Optimizing {}
-arch.task.sync_databases.waiting=Waiting for {}
arch.task.sync_sb.status=Updating {}
arch.uninstall.clean_cached.error=It was not possible to remove old {} versions found on disk
arch.uninstall.clean_cached.substatus=Removing old versions from disk
diff --git a/bauh/gems/arch/resources/locale/es b/bauh/gems/arch/resources/locale/es
index 8d79a7dc..2d500d3e 100644
--- a/bauh/gems/arch/resources/locale/es
+++ b/bauh/gems/arch/resources/locale/es
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Expiración del índice
arch.config.aur_idx_exp.tip=Define el período (en minutos) para que el índice AUR almacenado en el disco se considere válido durante el proceso de inicialización. Utilice 0 para que esté siempre actualizado.
arch.config.mirrors_sort_limit=Límite de ordenación de espejos
arch.config.mirrors_sort_limit.tip=Define el número máximo de espejos que se utilizarán para la ordenación por velocidad. Use 0 para no limitar o déjelo en blanco para deshabilitar la clasificación.
-arch.config.optimize=optimizar
+arch.config.optimize=Optimizar {}
arch.config.optimize.tip=Se usará la configuración optimizada para que la instalación, actualización y reversión de los paquetes sean más rápidas, de lo contrario se usará la configuración del sistema
arch.config.pacman_mthread_download=Descarga segmentada (repositorios)
arch.config.pacman_mthread_download.tip=Si los paquetes de los repositorios deben descargarse con una herramienta que usa segmentación/threads (puede ser más rápido). pacman-mirrors necesita estar instalado.
arch.config.refresh_mirrors=Actualizar espejos al iniciar
-arch.config.refresh_mirrors.tip=Actualiza los espejos de paquetes una vez al día al iniciar ( o después de reiniciar el dispositivo )
+arch.config.refresh_mirrors.tip=Actualiza los espejos de paquetes una vez al día al iniciar
arch.config.repos=Paquetes de repositorios
arch.config.repos.tip=Permite gestionar paquetes de los repositorios configurados
arch.config.suggest_optdep_uninstall=Desinstalar dependencias opcionales
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Ejecutando ganchos pre-transacción
arch.sync.dep_breakage.reason={} necesita de {}
arch.sync_databases.substatus=Sincronizando bases de paquetes
arch.sync_databases.substatus.error=No fue posible sincronizar la base de paquetes
+arch.sync_databases.substatus.synchronized=Sincronizado
arch.task.aur.index.status=Generando índice local del AUR
+arch.task.aur.index.substatus.checking=Buscando actualizaciones
arch.task.aur.index.substatus.download=Descargando el índice
arch.task.aur.index.substatus.error.download=Error de conexión al descargar el índice
arch.task.aur.index.substatus.error.no_data=Error: índice vacío
arch.task.aur.index.substatus.gen_index=Generando índice
+arch.task.checking_settings=Verificando configuraciones
+arch.task.disabled=Deshabilitado
arch.task.disk_cache=Indexando datos de paquetes
arch.task.disk_cache.checking=Comprobando índice
arch.task.disk_cache.indexed=Indexados
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexando
arch.task.disk_cache.reading_files=Lendo archivos
arch.task.disk_cache.waiting_aur_index=Esperando {}
arch.task.mirrors=Actualizando espejos
+arch.task.mirrors.cached=Actualizados
arch.task.optimizing=Optimizando {}
-arch.task.sync_databases.waiting=Esperando por {}
arch.task.sync_sb.status=Actualizando {}
arch.uninstall.clean_cached.error=No fue posible eliminar versiones antiguas de {} encontradas en disco
arch.uninstall.clean_cached.substatus=Eliminando versiones antiguas del disco
diff --git a/bauh/gems/arch/resources/locale/fr b/bauh/gems/arch/resources/locale/fr
index c9a3c609..80e8581b 100644
--- a/bauh/gems/arch/resources/locale/fr
+++ b/bauh/gems/arch/resources/locale/fr
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Index expiration
arch.config.aur_idx_exp.tip=It defines the period (in minutes) for the AUR index stored in disc to be considered valid during the initialization process. Use 0 so that it is always updated.
arch.config.mirrors_sort_limit=Limite de tri des miroirs
arch.config.mirrors_sort_limit.tip=Définit le nombre maximal de miroirs utilisés pour trier vite. 0 pour aucune limite ou vide pour désactiver le tri.
-arch.config.optimize=optimizer
+arch.config.optimize=Optimizer {}
arch.config.optimize.tip=Utiliser des paramètres optimisés pour rendre l'installation, mise à jour et downgrade des paquets plus rapide. À défaut, les paramètres systèmes seront utilisés.
arch.config.pacman_mthread_download=Téléchargement parallèle (repos)
arch.config.pacman_mthread_download.tip=Si il faut utiliser un outil qui télécharge les paquets du répos en parallèle (plus rapide). pacman-mirrors doit être installé.
arch.config.refresh_mirrors=Actualiser les miroirs au démarrage
-arch.config.refresh_mirrors.tip=Actualiser les miroirs du paquet une fois par jour au démarrage ( ou après redémarrage système )
+arch.config.refresh_mirrors.tip=Actualiser les miroirs du paquet une fois par jour au démarrage
arch.config.repos=Repos des paquets
arch.config.repos.tip=Permet de gerer les paquets du repo
arch.config.suggest_optdep_uninstall=Désinstaller les dépendances optionnelles
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Éxécution des pre-transaction hooks
arch.sync.dep_breakage.reason={} requiert {}
arch.sync_databases.substatus=Synchronisation des bases de données du paquet
arch.sync_databases.substatus.error=Impossible de synchroniser les bases de données du paquet
+arch.sync_databases.substatus.synchronized=Synchronized
arch.task.aur.index.status=Generating local AUR index
+arch.task.aur.index.substatus.checking=Checking for updates
arch.task.aur.index.substatus.download=Downloading the AUR index
arch.task.aur.index.substatus.error.download=Connection error while downloading the index
arch.task.aur.index.substatus.error.no_data=Error: empty index
arch.task.aur.index.substatus.gen_index=Generating index
+arch.task.checking_settings=Checking settings
+arch.task.disabled=Disabled
arch.task.disk_cache=Indexation des données des paquets
arch.task.disk_cache.checking=Verification de l'index
arch.task.disk_cache.indexed=Indexé
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexation
arch.task.disk_cache.reading_files=Lecture des fichiers
arch.task.disk_cache.waiting_aur_index=Waiting {}
arch.task.mirrors=Mise à jour des miroirs
+arch.task.mirrors.cached=Refreshed
arch.task.optimizing=Optimisation {}
-arch.task.sync_databases.waiting=Attente de {}
arch.task.sync_sb.status=Mise à jour {}
arch.uninstall.clean_cached.error=Impossible de supprimer les anciennes version de {} trouvées sur le disque
arch.uninstall.clean_cached.substatus=Suppression des anciennes versions
diff --git a/bauh/gems/arch/resources/locale/it b/bauh/gems/arch/resources/locale/it
index 020f5c48..43567720 100644
--- a/bauh/gems/arch/resources/locale/it
+++ b/bauh/gems/arch/resources/locale/it
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Index expiration
arch.config.aur_idx_exp.tip=It defines the period (in minutes) for the AUR index stored in disc to be considered valid during the initialization process. Use 0 so that it is always updated.
arch.config.mirrors_sort_limit=Mirrors sort limit
arch.config.mirrors_sort_limit.tip=Defines the maximum number of mirrors that will be used for speed sorting. Use 0 for no limit or leave it blank to disable sorting.
-arch.config.optimize=optimize
+arch.config.optimize=Optimize {}
arch.config.optimize.tip=Verranno utilizzate le impostazioni ottimizzate per velocizzare l'installazione, l'aggiornamento e l'inversione dei pacchetti, altrimenti verranno utilizzate le impostazioni di sistema
arch.config.pacman_mthread_download=Multithreaded download (repositories)
arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed.
arch.config.refresh_mirrors=Refresh mirrors on startup
-arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
+arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Running pre-transaction hooks
arch.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Synchronizing package databases
arch.sync_databases.substatus.error=It was not possible to synchronize the package database
+arch.sync_databases.substatus.synchronized=Synchronized
arch.task.aur.index.status=Generating local AUR index
+arch.task.aur.index.substatus.checking=Checking for updates
arch.task.aur.index.substatus.download=Downloading the AUR index
arch.task.aur.index.substatus.error.download=Connection error while downloading the index
arch.task.aur.index.substatus.error.no_data=Error: empty index
arch.task.aur.index.substatus.gen_index=Generating index
+arch.task.checking_settings=Checking settings
+arch.task.disabled=Disabled
arch.task.disk_cache=Indexing packages data
arch.task.disk_cache.checking=Checking index
arch.task.disk_cache.indexed=Indexed
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexing
arch.task.disk_cache.reading_files=Reading files
arch.task.disk_cache.waiting_aur_index=Waiting {}
arch.task.mirrors=Aggiornando i mirror
+arch.task.mirrors.cached=Refreshed
arch.task.optimizing=Ottimizzando {}
-arch.task.sync_databases.waiting=Waiting for {}
arch.task.sync_sb.status=Aggiornando {}
arch.uninstall.clean_cached.error=Non è stato possibile rimuovere le vecchie {} versioni trovate sul disco
arch.uninstall.clean_cached.substatus=Rimozione di versioni precedenti dal disco
diff --git a/bauh/gems/arch/resources/locale/pt b/bauh/gems/arch/resources/locale/pt
index 2d586fe2..e127c31b 100644
--- a/bauh/gems/arch/resources/locale/pt
+++ b/bauh/gems/arch/resources/locale/pt
@@ -53,7 +53,7 @@ arch.config.aur_idx_exp=Expiração do índice
arch.config.aur_idx_exp.tip=Define o período (em minutos) em que o índice do AUR armazenado em disco é considerado válido durante a inicialização. Utilize 0 para que ele sempre seja atualizado.
arch.config.mirrors_sort_limit=Limite de ordenação de espelhos
arch.config.mirrors_sort_limit.tip=Define o número máximo de espelhos que serão utilizados para a ordenação por velocidade. Utilize 0 para não limitar ou deixe em branco para desabilitar a ordenação.
-arch.config.optimize=Otimizar
+arch.config.optimize=Otimizar {}
arch.config.pacman_mthread_download=Download segmentado (repositórios)
arch.config.pacman_mthread_download.tip=Se os pacotes dos repositórios devem baixados através de uma ferramenta que trabalha com segmentação/threads (pode ser mais rápido). pacman-mirrors precisa estar instalado.
arch.config.refresh_mirrors=Atualizar espelhos ao iniciar
@@ -209,11 +209,15 @@ arch.substatus.pre_hooks=Executando ganchos pré-transação
arch.sync.dep_breakage.reason={} precisa de {}
arch.sync_databases.substatus=Sincronizando bases de pacotes
arch.sync_databases.substatus.error=Não foi possível sincronizar as bases de pacotes
+arch.sync_databases.substatus.synchronized=Sincronizado
arch.task.aur.index.status=Gerando índice local do AUR
+arch.task.aur.index.substatus.checking=Checando atualizações
arch.task.aur.index.substatus.download=Baixando o índice
arch.task.aur.index.substatus.error.download=Erro de conexão ao baixar o índice
arch.task.aur.index.substatus.error.no_data=Error: índice vazio
arch.task.aur.index.substatus.gen_index=Gerando índice
+arch.task.checking_settings=Verificando configurações
+arch.task.disabled=Desabilitado
arch.task.disk_cache=Indexando dados de pacotes
arch.task.disk_cache.checking=Verificando índice
arch.task.disk_cache.indexed=Indexados
@@ -221,8 +225,8 @@ arch.task.disk_cache.indexing=Indexando
arch.task.disk_cache.reading_files=Lendo arquivos
arch.task.disk_cache.waiting_aur_index=Aguardando {}
arch.task.mirrors=Atualizando espelhos
+arch.task.mirrors.cached=Atualizados
arch.task.optimizing=Otimizando {}
-arch.task.sync_databases.waiting=Aguardando por {}
arch.task.sync_sb.status=Atualizando {}
arch.uninstall.clean_cached.error=Não foi possível remover versões antigas de {} encontradas em disco
arch.uninstall.clean_cached.substatus=Removendo versões antigas do disco
diff --git a/bauh/gems/arch/resources/locale/ru b/bauh/gems/arch/resources/locale/ru
index 50279fb3..9a5a58f9 100644
--- a/bauh/gems/arch/resources/locale/ru
+++ b/bauh/gems/arch/resources/locale/ru
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Index expiration
arch.config.aur_idx_exp.tip=It defines the period (in minutes) for the AUR index stored in disc to be considered valid during the initialization process. Use 0 so that it is always updated.
arch.config.mirrors_sort_limit=Ограничение сортировки зеркал
arch.config.mirrors_sort_limit.tip=Определяет максимальное количество зеркал, которые будут использоваться для сортировки по скорости. Используйте 0 для No limit или оставьте его пустым, чтобы отключить сортировку.
-arch.config.optimize=Оптимизация
+arch.config.optimize=Оптимизация {}
arch.config.optimize.tip=Оптимизированные настройки будут использоваться для ускорения установки пакетов, в противном случае будут использоваться системные настройки
arch.config.pacman_mthread_download=Multithreaded download (repositories)
arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed.
arch.config.refresh_mirrors=Обновить зеркала при запуске
-arch.config.refresh_mirrors.tip=Обновляйте зеркала пакета один раз в день при запуске (или после перезагрузки устройства)
+arch.config.refresh_mirrors.tip=Обновляйте зеркала пакета один раз в день при запуске
arch.config.repos=Пакеты репозиториев
arch.config.repos.tip=Он позволяет управлять пакетами из набора репозиториев
arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Running pre-transaction hooks
arch.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Синхронизация баз данных пакетов
arch.sync_databases.substatus.error=Синхронизировать базу данных пакета не удалось
+arch.sync_databases.substatus.synchronized=Synchronized
arch.task.aur.index.status=Generating local AUR index
+arch.task.aur.index.substatus.checking=Checking for updates
arch.task.aur.index.substatus.download=Downloading the AUR index
arch.task.aur.index.substatus.error.download=Connection error while downloading the index
arch.task.aur.index.substatus.error.no_data=Error: empty index
arch.task.aur.index.substatus.gen_index=Generating index
+arch.task.checking_settings=Checking settings
+arch.task.disabled=Disabled
arch.task.disk_cache=Indexing packages data
arch.task.disk_cache.checking=Checking index
arch.task.disk_cache.indexed=Indexed
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexing
arch.task.disk_cache.reading_files=Reading files
arch.task.disk_cache.waiting_aur_index=Waiting {}
arch.task.mirrors=Обновление зеркал
+arch.task.mirrors.cached=Refreshed
arch.task.optimizing=Optimizing {}
-arch.task.sync_databases.waiting=Waiting for {}
arch.task.sync_sb.status=Updating {}
arch.uninstall.clean_cached.error=It was not possible to remove old {} versions found on disk
arch.uninstall.clean_cached.substatus=Removing old versions from disk
diff --git a/bauh/gems/arch/resources/locale/tr b/bauh/gems/arch/resources/locale/tr
index 865603af..13d3b726 100644
--- a/bauh/gems/arch/resources/locale/tr
+++ b/bauh/gems/arch/resources/locale/tr
@@ -53,12 +53,12 @@ arch.config.aur_idx_exp=Index expiration
arch.config.aur_idx_exp.tip=It defines the period (in minutes) for the AUR index stored in disc to be considered valid during the initialization process. Use 0 so that it is always updated.
arch.config.mirrors_sort_limit=Yansı sıralama sınırı
arch.config.mirrors_sort_limit.tip=Hız sıralama için kullanılacak maksimum yansı sayısını tanımlar. Sınırsız olması için 0 kullanın veya sıralamayı devre dışı bırakmak için boş bırakın.
-arch.config.optimize=optimize
+arch.config.optimize=Optimize {}
arch.config.optimize.tip=Paketlerin kurulumunu, yükseltilmesini ve indirilmesini hızlandırmak için optimize edilmiş ayarlar kullanılacak, aksi takdirde sistem ayarları kullanılacak
arch.config.pacman_mthread_download=Multithreaded download (repositories)
arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed.
arch.config.refresh_mirrors=Başlangıçta yansıları yenile
-arch.config.refresh_mirrors.tip=Paket yansılarını başlangıçta günde bir kez (veya cihaz yeniden başlatıldıktan sonra) yenileyin
+arch.config.refresh_mirrors.tip=Paket yansılarını başlangıçta günde bir kez yenileyin
arch.config.repos=Depo paketleri
arch.config.repos.tip=Paketleri depolardan yönetmeye izin verir
arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
@@ -210,11 +210,15 @@ arch.substatus.pre_hooks=Running pre-transaction hooks
arch.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Paket veritabanı eşitleniyor
arch.sync_databases.substatus.error=Paket veritabanı eşitlenemedi
+arch.sync_databases.substatus.synchronized=Synchronized
arch.task.aur.index.status=Generating local AUR index
+arch.task.aur.index.substatus.checking=Checking for updates
arch.task.aur.index.substatus.download=Downloading the AUR index
arch.task.aur.index.substatus.error.download=Connection error while downloading the index
arch.task.aur.index.substatus.error.no_data=Error: empty index
arch.task.aur.index.substatus.gen_index=Generating index
+arch.task.checking_settings=Checking settings
+arch.task.disabled=Disabled
arch.task.disk_cache=Indexing packages data
arch.task.disk_cache.checking=Checking index
arch.task.disk_cache.indexed=Indexed
@@ -222,8 +226,8 @@ arch.task.disk_cache.indexing=Indexing
arch.task.disk_cache.reading_files=Reading files
arch.task.disk_cache.waiting_aur_index=Waiting {}
arch.task.mirrors=Yansılar yenileniyor
+arch.task.mirrors.cached=Refreshed
arch.task.optimizing=Uygun hale getiriliyor {}
-arch.task.sync_databases.waiting=Waiting for {}
arch.task.sync_sb.status={} güncelleniyor
arch.uninstall.clean_cached.error=Diskte bulunan eski {} sürümleri kaldırılamadı
arch.uninstall.clean_cached.substatus=Eski sürümler diskten kaldırılıyor
diff --git a/bauh/gems/arch/worker.py b/bauh/gems/arch/worker.py
index 63f4ecdc..3fbcd82f 100644
--- a/bauh/gems/arch/worker.py
+++ b/bauh/gems/arch/worker.py
@@ -13,11 +13,12 @@ import requests
from bauh.api.abstract.context import ApplicationContext
from bauh.api.abstract.handler import TaskManager
+from bauh.commons import system
+from bauh.commons.boot import CreateConfigFile
from bauh.commons.html import bold
-from bauh.commons.system import run_cmd, new_root_subprocess, ProcessHandler
-from bauh.commons.util import datetime_as_milis
+from bauh.commons.system import new_root_subprocess, ProcessHandler
from bauh.gems.arch import pacman, disk, CUSTOM_MAKEPKG_FILE, CONFIG_DIR, AUR_INDEX_FILE, get_icon_path, database, \
- mirrors, ARCH_CACHE_PATH, BUILD_DIR, AUR_INDEX_TS_FILE
+ mirrors, ARCH_CACHE_PATH, AUR_INDEX_TS_FILE, aur
from bauh.gems.arch.aur import URL_INDEX
from bauh.view.util.translation import I18n
@@ -31,18 +32,20 @@ RE_CLEAR_REPLACE = re.compile(r'[\-_.]')
class AURIndexUpdater(Thread):
- def __init__(self, context: ApplicationContext, taskman: TaskManager):
+ def __init__(self, context: ApplicationContext, taskman: TaskManager, create_config: Optional[CreateConfigFile] = None, arch_config: Optional[dict] = None):
super(AURIndexUpdater, self).__init__(daemon=True)
self.http_client = context.http_client
self.i18n = context.i18n
self.logger = context.logger
self.taskman = taskman
self.task_id = 'index_aur'
+ self.create_config = create_config
+ self.config = arch_config
+ self.taskman.register_task(self.task_id, self.i18n['arch.task.aur.index.status'], get_icon_path())
- @staticmethod
- def should_update(arch_config: dict) -> bool:
+ def should_update(self) -> bool:
try:
- exp_minutes = int(arch_config['aur_idx_exp'])
+ exp_minutes = int(self.config['aur_idx_exp'])
except:
traceback.print_exc()
return True
@@ -66,11 +69,9 @@ class AURIndexUpdater(Thread):
traceback.print_exc()
return True
- def run(self):
- ti = time.time()
+ def update_index(self):
self.logger.info('Indexing AUR packages')
- self.taskman.register_task(self.task_id, self.i18n['arch.task.aur.index.status'], get_icon_path())
- self.taskman.update_progress(self.task_id, 1, self.i18n['arch.task.aur.index.substatus.download'])
+ self.taskman.update_progress(self.task_id, 5, self.i18n['arch.task.aur.index.substatus.download'])
try:
index_ts = datetime.utcnow().timestamp()
res = self.http_client.get(URL_INDEX)
@@ -115,6 +116,22 @@ class AURIndexUpdater(Thread):
self.logger.warning('No internet connection: could not pre-index packages')
self.taskman.update_progress(self.task_id, 100, self.i18n['arch.task.aur.index.substatus.error.download'])
+ def run(self):
+ ti = time.time()
+
+ if self.create_config:
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(self.create_config.task_name))
+ self.create_config.join()
+ self.config = self.create_config.config
+
+ self.taskman.update_progress(self.task_id, 1, self.i18n['arch.task.aur.index.substatus.checking'])
+
+ if self.should_update():
+ self.update_index()
+ else:
+ self.logger.info("AUR index is up to date. Aborting...")
+ self.taskman.update_progress(self.task_id, 100, None)
+
tf = time.time()
self.taskman.finish_task(self.task_id)
self.logger.info("Finished. Took {0:.2f} seconds".format(tf - ti))
@@ -122,48 +139,56 @@ class AURIndexUpdater(Thread):
class ArchDiskCacheUpdater(Thread):
- def __init__(self, task_man: TaskManager, arch_config: dict, i18n: I18n, logger: logging.Logger, controller: "ArchManager", internet_available: bool,
- aur_supported: bool, aur_indexer: Thread):
+ def __init__(self, taskman: TaskManager, i18n: I18n, logger: logging.Logger,
+ controller: "ArchManager", internet_available: bool, aur_indexer: Thread,
+ create_config: CreateConfigFile):
super(ArchDiskCacheUpdater, self).__init__(daemon=True)
self.logger = logger
- self.task_man = task_man
+ self.taskman = taskman
self.task_id = 'arch_cache_up'
self.i18n = i18n
self.indexed = 0
self.indexed_template = self.i18n['arch.task.disk_cache.indexed'] + ': {}/ {}'
self.to_index = 0
self.progress = 0 # progress is defined by the number of packages prepared and indexed
- self.repositories = arch_config['repositories']
- self.aur = aur_supported
self.controller = controller
self.internet_available = internet_available
self.installed_hash_path = '{}/installed.sha1'.format(ARCH_CACHE_PATH)
self.installed_cache_dir = '{}/installed'.format(ARCH_CACHE_PATH)
self.aur_indexer = aur_indexer
+ self.create_config = create_config
+ self.taskman.register_task(self.task_id, self.i18n['arch.task.disk_cache'], get_icon_path())
def update_indexed(self, pkgname: str):
self.indexed += 1
sub = self.indexed_template.format(self.indexed, self.to_index)
progress = self.progress + (self.indexed / self.to_index) * 50
- self.task_man.update_progress(self.task_id, progress, sub)
+ self.taskman.update_progress(self.task_id, progress, sub)
def _update_progress(self, progress: float, msg: str):
self.progress = progress
- self.task_man.update_progress(self.task_id, self.progress, msg)
+ self.taskman.update_progress(self.task_id, self.progress, msg)
def _notify_reading_files(self):
self._update_progress(50, self.i18n['arch.task.disk_cache.indexing'])
def run(self):
- if not any([self.aur, self.repositories]):
+ ti = time.time()
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(self.create_config.task_name))
+ self.create_config.join()
+
+ config = self.create_config.config
+ aur_supported, repositories = aur.is_supported(config), config['repositories']
+
+ self.taskman.update_progress(self.task_id, 1, None)
+ if not any([aur_supported, repositories]):
+ self.taskman.update_progress(self.task_id, 100, self.i18n['arch.task.disabled'])
+ self.taskman.finish_task(self.task_id)
return
- ti = time.time()
- self.task_man.register_task(self.task_id, self.i18n['arch.task.disk_cache'], get_icon_path())
-
self.logger.info("Checking already cached package data")
-
self._update_progress(1, self.i18n['arch.task.disk_cache.checking'])
+
cache_dirs = [fpath for fpath in glob.glob('{}/*'.format(self.installed_cache_dir)) if os.path.isdir(fpath)]
not_cached_names = None
@@ -177,8 +202,8 @@ class ArchDiskCacheUpdater(Thread):
self._update_progress(20, self.i18n['arch.task.disk_cache.checking'])
if not not_cached_names:
- self.task_man.update_progress(self.task_id, 100, '')
- self.task_man.finish_task(self.task_id)
+ self.taskman.update_progress(self.task_id, 100, '')
+ self.taskman.finish_task(self.task_id)
tf = time.time()
time_msg = '{0:.2f} seconds'.format(tf - ti)
self.logger.info('Finished: no package data to cache ({})'.format(time_msg))
@@ -186,8 +211,8 @@ class ArchDiskCacheUpdater(Thread):
self.logger.info('Pre-caching installed Arch packages data to disk')
- if self.aur and self.aur_indexer:
- self.task_man.update_progress(self.task_id, 20, self.i18n['arch.task.disk_cache.waiting_aur_index'].format(bold(self.i18n['arch.task.aur.index.status'])))
+ if aur_supported and self.aur_indexer:
+ self.taskman.update_progress(self.task_id, 20, self.i18n['arch.task.disk_cache.waiting_aur_index'].format(bold(self.i18n['arch.task.aur.index.status'])))
self.aur_indexer.join()
self._update_progress(21, self.i18n['arch.task.disk_cache.checking'])
@@ -199,7 +224,7 @@ class ArchDiskCacheUpdater(Thread):
saved = 0
- pkgs = {p.name: p for p in installed if ((self.aur and p.repository == 'aur') or (self.repositories and p.repository != 'aur')) and not os.path.exists(p.get_disk_cache_path())}
+ pkgs = {p.name: p for p in installed if ((aur_supported and p.repository == 'aur') or (repositories and p.repository != 'aur')) and not os.path.exists(p.get_disk_cache_path())}
self.to_index = len(pkgs)
# overwrite == True because the verification already happened
@@ -207,8 +232,8 @@ class ArchDiskCacheUpdater(Thread):
saved += disk.write_several(pkgs=pkgs,
after_desktop_files=self._notify_reading_files,
after_written=self.update_indexed, overwrite=True)
- self.task_man.update_progress(self.task_id, 100, None)
- self.task_man.finish_task(self.task_id)
+ self.taskman.update_progress(self.task_id, 100, None)
+ self.taskman.finish_task(self.task_id)
tf = time.time()
time_msg = '{0:.2f} seconds'.format(tf - ti)
@@ -217,7 +242,7 @@ class ArchDiskCacheUpdater(Thread):
class ArchCompilationOptimizer(Thread):
- def __init__(self, arch_config: dict, i18n: I18n, logger: logging.Logger, taskman: Optional[TaskManager] = None):
+ def __init__(self, i18n: I18n, logger: logging.Logger, taskman: TaskManager, create_config: Optional[CreateConfigFile] = None):
super(ArchCompilationOptimizer, self).__init__(daemon=True)
self.logger = logger
self.i18n = i18n
@@ -227,17 +252,12 @@ class ArchCompilationOptimizer(Thread):
self.re_ccache = re.compile(r'!?ccache')
self.taskman = taskman
self.task_id = 'arch_make_optm'
- self.optimizations = bool(arch_config['optimize'])
+ self.create_config = create_config
+ self.taskman.register_task(self.task_id, self.i18n['arch.task.optimizing'].format(bold('makepkg.conf')), get_icon_path())
def _is_ccache_installed(self) -> bool:
- return bool(run_cmd('which ccache', print_error=False))
-
- def _update_progress(self, progress: float, substatus: str = None):
- if self.taskman:
- self.taskman.update_progress(self.task_id, progress, substatus)
-
- if progress == 100:
- self.taskman.finish_task(self.task_id)
+ code, _ = system.execute(cmd='which ccache', output=False)
+ return code == 0
def optimize(self):
ti = time.time()
@@ -271,7 +291,7 @@ class ArchCompilationOptimizer(Thread):
else:
optimizations.append('MAKEFLAGS="-j$(nproc)"')
- self._update_progress(20)
+ self.taskman.update_progress(self.task_id, 20, None)
compress_xz = self.re_compress_xz.findall(custom_makepkg or global_makepkg)
@@ -286,7 +306,7 @@ class ArchCompilationOptimizer(Thread):
else:
optimizations.append('COMPRESSXZ=(xz -c -z - --threads=0)')
- self._update_progress(40)
+ self.taskman.update_progress(self.task_id, 40, None)
compress_zst = self.re_compress_zst.findall(custom_makepkg or global_makepkg)
@@ -301,7 +321,7 @@ class ArchCompilationOptimizer(Thread):
else:
optimizations.append('COMPRESSZST=(zstd -c -z -q - --threads=0)')
- self._update_progress(60)
+ self.taskman.update_progress(self.task_id, 60, None)
build_envs = self.re_build_env.findall(custom_makepkg or global_makepkg)
@@ -331,7 +351,7 @@ class ArchCompilationOptimizer(Thread):
self.logger.info('Adding a BUILDENV declaration')
optimizations.append('BUILDENV=(ccache)')
- self._update_progress(80)
+ self.taskman.update_progress(self.task_id, 80, None)
if custom_makepkg and optimizations:
generated_by = '# \n'
@@ -348,43 +368,91 @@ class ArchCompilationOptimizer(Thread):
self.logger.info("Removing old optimized 'makepkg.conf' at '{}'".format(CUSTOM_MAKEPKG_FILE))
os.remove(CUSTOM_MAKEPKG_FILE)
+ self.taskman.update_progress(self.task_id, 100, None)
tf = time.time()
- self._update_progress(100)
- self.logger.info("Optimizations took {0:.2f} seconds".format(tf - ti))
- self.logger.info('Finished')
+ self.logger.info('Finished. {0:.2f} seconds'.format(tf - ti))
def run(self):
- if not self.optimizations:
- self.logger.info("Arch packages compilation optimizations are disabled")
+ ti = time.time()
+ if self.create_config:
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(bold(self.create_config.task_name)))
+ self.create_config.join()
- if os.path.exists(CUSTOM_MAKEPKG_FILE):
- self.logger.info("Removing custom 'makepkg.conf' -> '{}'".format(CUSTOM_MAKEPKG_FILE))
- os.remove(CUSTOM_MAKEPKG_FILE)
+ self.taskman.update_progress(self.task_id, 1, None)
- self.logger.info('Finished')
- else:
- if self.taskman:
- self.taskman.register_task(self.task_id, self.i18n['arch.task.optimizing'].format(bold('makepkg.conf')), get_icon_path())
+ if self.create_config.config['optimize'] and aur.is_supported(self.create_config.config):
+ try:
+ self.optimize()
+ except:
+ self.logger.error("Unexpected exception")
+ traceback.print_exc()
+ self.taskman.update_progress(self.task_id, 100, None)
+ else:
+ self.logger.info("AUR packages compilation optimizations are disabled")
- self.optimize()
+ if os.path.exists(CUSTOM_MAKEPKG_FILE):
+ try:
+ self.logger.info("Removing custom 'makepkg.conf' -> '{}'".format(CUSTOM_MAKEPKG_FILE))
+ os.remove(CUSTOM_MAKEPKG_FILE)
+ except:
+ self.logger.error("Unexpected exception")
+ traceback.print_exc()
+
+ self.taskman.update_progress(self.task_id, 100, self.i18n['arch.task.disabled'])
+
+ tf = time.time()
+ self.taskman.finish_task(self.task_id)
+ self.logger.info('Finished. Took {0:.2f} seconds'.format(tf - ti))
class RefreshMirrors(Thread):
- def __init__(self, taskman: TaskManager, root_password: str, i18n: I18n, sort_limit: int, logger: logging.Logger):
+ def __init__(self, taskman: TaskManager, root_password: str, i18n: I18n, logger: logging.Logger,
+ create_config: CreateConfigFile):
super(RefreshMirrors, self).__init__(daemon=True)
self.taskman = taskman
self.i18n = i18n
self.logger = logger
self.root_password = root_password
self.task_id = "arch_mirrors"
- self.sort_limit = sort_limit
+ self.create_config = create_config
+ self.refreshed = False
+ self.task_name = self.i18n['arch.task.mirrors']
+ self.taskman.register_task(self.task_id, self.task_name, get_icon_path())
def _notify_output(self, output: str):
self.taskman.update_output(self.task_id, output)
+ @staticmethod
+ def is_enabled(arch_config: dict, aur_supported: bool) -> bool:
+ return (arch_config['repositories'] or aur_supported) \
+ and arch_config['refresh_mirrors_startup'] and pacman.is_mirrors_available()
+
+ @classmethod
+ def should_synchronize(cls, arch_config: dict, aur_supported: bool, logger: logging.Logger) -> bool:
+ return cls.is_enabled(arch_config, aur_supported) and mirrors.should_sync(logger)
+
def run(self):
- self.taskman.register_task(self.task_id, self.i18n['arch.task.mirrors'], get_icon_path())
+ ti = time.time()
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(bold(self.create_config.task_name)))
+ self.create_config.join()
+
+ arch_config = self.create_config.config
+ aur_supported = aur.is_supported(arch_config)
+
+ self.taskman.update_progress(self.task_id, 1, self.i18n['arch.task.checking_settings'])
+
+ if not self.is_enabled(arch_config, aur_supported):
+ self.taskman.update_progress(self.task_id, 100, self.i18n['arch.task.disabled'])
+ self.taskman.finish_task(self.task_id)
+ return
+
+ if not mirrors.should_sync(self.logger):
+ self.taskman.update_progress(self.task_id, 100, self.i18n['arch.task.mirrors.cached'])
+ self.taskman.finish_task(self.task_id)
+ return
+
+ sort_limit = arch_config['mirrors_sort_limit']
self.logger.info("Refreshing mirrors")
handler = ProcessHandler()
@@ -394,15 +462,16 @@ class RefreshMirrors(Thread):
if success:
- if self.sort_limit is not None and self.sort_limit >= 0:
+ if sort_limit is not None and sort_limit >= 0:
self.taskman.update_progress(self.task_id, 50, self.i18n['arch.custom_action.refresh_mirrors.status.updating'])
try:
- handler.handle_simple(pacman.sort_fastest_mirrors(self.root_password, self.sort_limit), output_handler=self._notify_output)
+ handler.handle_simple(pacman.sort_fastest_mirrors(self.root_password, sort_limit), output_handler=self._notify_output)
except:
self.logger.error("Could not sort mirrors by speed")
traceback.print_exc()
mirrors.register_sync(self.logger)
+ self.refreshed = True
else:
self.logger.error("It was not possible to refresh mirrors")
except:
@@ -411,12 +480,14 @@ class RefreshMirrors(Thread):
self.taskman.update_progress(self.task_id, 100, None)
self.taskman.finish_task(self.task_id)
- self.logger.info("Finished")
+ tf = time.time()
+ self.logger.info("Finished. Took {0:.2f} seconds".format(tf - ti))
class SyncDatabases(Thread):
- def __init__(self, taskman: TaskManager, root_password: str, i18n: I18n, logger: logging.Logger, refresh_mirrors: RefreshMirrors = None):
+ def __init__(self, taskman: TaskManager, root_password: str, i18n: I18n, logger: logging.Logger,
+ refresh_mirrors: RefreshMirrors, create_config: CreateConfigFile):
super(SyncDatabases, self).__init__(daemon=True)
self.task_man = taskman
self.i18n = i18n
@@ -425,15 +496,46 @@ class SyncDatabases(Thread):
self.root_password = root_password
self.refresh_mirrors = refresh_mirrors
self.logger = logger
+ self.create_config = create_config
+ self.task_name = self.i18n['arch.sync_databases.substatus']
+ self.taskman.register_task(self.task_id, self.task_name, get_icon_path())
+ self.synchronized = False
+
+ @staticmethod
+ def is_enabled(arch_config: dict, aur_supported: bool) -> bool:
+ return arch_config['sync_databases_startup'] and (aur_supported or arch_config['repositories'])
+
+ @classmethod
+ def should_sync(cls, mirrors_refreshed: bool, arch_config: dict, aur_supported: bool, logger: logging.Logger):
+ return mirrors_refreshed or (cls.is_enabled(arch_config, aur_supported) and database.should_sync(arch_config, aur_supported, None, logger))
def run(self) -> None:
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(bold(self.create_config.task_name)))
+ self.create_config.join()
+
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(bold(self.refresh_mirrors.task_name)))
+ self.refresh_mirrors.join()
+
+ self.taskman.update_progress(self.task_id, 1, self.i18n['arch.task.checking_settings'])
+
+ arch_config = self.create_config.config
+ aur_supported = aur.is_supported(arch_config)
+ if not self.is_enabled(arch_config, aur_supported):
+ self.taskman.update_progress(self.task_id, 100, self.i18n['arch.task.disabled'])
+ self.taskman.finish_task(self.task_id)
+ return
+
+ shoud_sync = self.refresh_mirrors.refreshed or (database.should_sync(arch_config, aur_supported, None, self.logger))
+
+ if not shoud_sync:
+ self.taskman.update_progress(self.task_id, 100, self.i18n['arch.sync_databases.substatus.synchronized'])
+ self.taskman.finish_task(self.task_id)
+ self.synchronized = True
+ return
+
self.logger.info("Synchronizing databases")
self.taskman.register_task(self.task_id, self.i18n['arch.sync_databases.substatus'], get_icon_path())
- if self.refresh_mirrors and self.refresh_mirrors.is_alive():
- self.taskman.update_progress(self.task_id, 0, self.i18n['arch.task.sync_databases.waiting'].format('"{}"'.format(self.i18n['arch.task.mirrors'])))
- self.refresh_mirrors.join()
-
progress = 10
dbs = pacman.get_databases()
self.taskman.update_progress(self.task_id, progress, None)
@@ -472,6 +574,7 @@ class SyncDatabases(Thread):
if p.returncode == 0:
database.register_sync(self.logger)
+ self.synchronized = True
else:
self.logger.error("Could not synchronize database")
diff --git a/bauh/gems/flatpak/__init__.py b/bauh/gems/flatpak/__init__.py
index 69e08aae..e6a7328b 100644
--- a/bauh/gems/flatpak/__init__.py
+++ b/bauh/gems/flatpak/__init__.py
@@ -2,6 +2,7 @@ import os
from pathlib import Path
from bauh.api.constants import CONFIG_PATH
+from bauh.commons import resource
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
SUGGESTIONS_FILE = 'https://raw.githubusercontent.com/vinifmor/bauh-files/master/flatpak/suggestions.txt'
@@ -9,3 +10,7 @@ CONFIG_FILE = '{}/flatpak.yml'.format(CONFIG_PATH)
CONFIG_DIR = '{}/flatpak'.format(CONFIG_PATH)
UPDATES_IGNORED_FILE = '{}/updates_ignored.txt'.format(CONFIG_DIR)
EXPORTS_PATH = '{}/.local/share/flatpak/exports/share'.format(str(Path.home()))
+
+
+def get_icon_path() -> str:
+ return resource.get_path('img/flatpak.svg', ROOT_DIR)
diff --git a/bauh/gems/flatpak/config.py b/bauh/gems/flatpak/config.py
index c6c9dcff..fbc2046a 100644
--- a/bauh/gems/flatpak/config.py
+++ b/bauh/gems/flatpak/config.py
@@ -1,7 +1,11 @@
-from bauh.commons.config import read_config as read
+from bauh.commons.config import YAMLConfigManager
from bauh.gems.flatpak import CONFIG_FILE
-def read_config(update_file: bool = False) -> dict:
- template = {'installation_level': None}
- return read(CONFIG_FILE, template, update_file=update_file)
+class FlatpakConfigManager(YAMLConfigManager):
+
+ def __init__(self):
+ super(FlatpakConfigManager, self).__init__(config_file_path=CONFIG_FILE)
+
+ def get_default_config(self) -> dict:
+ return {'installation_level': None}
diff --git a/bauh/gems/flatpak/controller.py b/bauh/gems/flatpak/controller.py
index de5e7d6a..16465450 100644
--- a/bauh/gems/flatpak/controller.py
+++ b/bauh/gems/flatpak/controller.py
@@ -16,11 +16,12 @@ from bauh.api.abstract.model import PackageHistory, PackageUpdate, SoftwarePacka
from bauh.api.abstract.view import MessageType, FormComponent, SingleSelectComponent, InputOption, SelectViewType, \
ViewComponent, PanelComponent
from bauh.commons import user
-from bauh.commons.config import save_config
+from bauh.commons.boot import CreateConfigFile
from bauh.commons.html import strip_html, bold
from bauh.commons.system import ProcessHandler
-from bauh.gems.flatpak import flatpak, SUGGESTIONS_FILE, CONFIG_FILE, UPDATES_IGNORED_FILE, CONFIG_DIR, EXPORTS_PATH
-from bauh.gems.flatpak.config import read_config
+from bauh.gems.flatpak import flatpak, SUGGESTIONS_FILE, CONFIG_FILE, UPDATES_IGNORED_FILE, CONFIG_DIR, EXPORTS_PATH, \
+ get_icon_path
+from bauh.gems.flatpak.config import FlatpakConfigManager
from bauh.gems.flatpak.constants import FLATHUB_API_URL
from bauh.gems.flatpak.model import FlatpakApplication
from bauh.gems.flatpak.worker import FlatpakAsyncDataLoader, FlatpakUpdateLoader
@@ -41,6 +42,7 @@ class FlatpakManager(SoftwareManager):
self.http_client = context.http_client
self.suggestions_cache = context.cache_factory.new()
self.logger = context.logger
+ self.configman = FlatpakConfigManager()
def get_managed_types(self) -> Set["type"]:
return {FlatpakApplication}
@@ -337,9 +339,9 @@ class FlatpakManager(SoftwareManager):
return True
def install(self, pkg: FlatpakApplication, root_password: str, disk_loader: DiskCacheLoader, watcher: ProcessWatcher) -> TransactionResult:
- config = read_config()
+ flatpak_config = self.configman.get_config()
- install_level = config['installation_level']
+ install_level = flatpak_config['installation_level']
if install_level is not None:
self.logger.info("Default Flaptak installation level defined: {}".format(install_level))
@@ -453,7 +455,8 @@ class FlatpakManager(SoftwareManager):
return action == SoftwareAction.DOWNGRADE and pkg.installation == 'system'
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
- Thread(target=read_config, args=(True,), daemon=True).start()
+ CreateConfigFile(taskman=task_manager, configman=self.configman, i18n=self.i18n,
+ task_icon_path=get_icon_path(), logger=self.logger).start()
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
updates = []
@@ -555,7 +558,7 @@ class FlatpakManager(SoftwareManager):
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
fields = []
- config = read_config()
+ flatpak_config = self.configman.get_config()
install_opts = [InputOption(label=self.i18n['flatpak.config.install_level.system'].capitalize(),
value='system',
@@ -568,7 +571,7 @@ class FlatpakManager(SoftwareManager):
tooltip=self.i18n['flatpak.config.install_level.ask.tip'].format(app=self.context.app_name))]
fields.append(SingleSelectComponent(label=self.i18n['flatpak.config.install_level'],
options=install_opts,
- default_option=[o for o in install_opts if o.value == config['installation_level']][0],
+ default_option=[o for o in install_opts if o.value == flatpak_config['installation_level']][0],
max_per_line=len(install_opts),
max_width=floor(screen_width * 0.22),
type_=SelectViewType.RADIO))
@@ -576,11 +579,11 @@ class FlatpakManager(SoftwareManager):
return PanelComponent([FormComponent(fields, self.i18n['installation'].capitalize())])
def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
- config = read_config()
- config['installation_level'] = component.components[0].components[0].get_selected()
+ flatpak_config = self.configman.get_config()
+ flatpak_config['installation_level'] = component.components[0].components[0].get_selected()
try:
- save_config(config, CONFIG_FILE)
+ self.configman.save_config(flatpak_config)
return True, None
except:
return False, [traceback.format_exc()]
diff --git a/bauh/gems/snap/config.py b/bauh/gems/snap/config.py
index 1dc7c398..5a44d04d 100644
--- a/bauh/gems/snap/config.py
+++ b/bauh/gems/snap/config.py
@@ -1,7 +1,11 @@
-from bauh.commons.config import read_config as read
+from bauh.commons.config import YAMLConfigManager
from bauh.gems.snap import CONFIG_FILE
-def read_config(update_file: bool = False) -> dict:
- template = {'install_channel': False, 'categories_exp': 24}
- return read(CONFIG_FILE, template, update_file=update_file)
+class SnapConfigManager(YAMLConfigManager):
+
+ def __init__(self):
+ super(SnapConfigManager, self).__init__(config_file_path=CONFIG_FILE)
+
+ def get_default_config(self) -> dict:
+ return {'install_channel': False, 'categories_exp': 24}
diff --git a/bauh/gems/snap/controller.py b/bauh/gems/snap/controller.py
index 241a4e64..db8dcb53 100644
--- a/bauh/gems/snap/controller.py
+++ b/bauh/gems/snap/controller.py
@@ -14,14 +14,14 @@ from bauh.api.abstract.view import SingleSelectComponent, SelectViewType, InputO
FormComponent, TextInputComponent
from bauh.api.exception import NoInternetException
from bauh.commons import resource
+from bauh.commons.boot import CreateConfigFile
from bauh.commons.category import CategoriesDownloader
-from bauh.commons.config import save_config
from bauh.commons.html import bold
from bauh.commons.system import SystemProcess, ProcessHandler, new_root_subprocess, get_human_size_str
from bauh.commons.view_utils import new_select
from bauh.gems.snap import snap, URL_CATEGORIES_FILE, CATEGORIES_FILE_PATH, SUGGESTIONS_FILE, \
- get_icon_path, snapd, CONFIG_FILE, ROOT_DIR
-from bauh.gems.snap.config import read_config
+ get_icon_path, snapd, ROOT_DIR
+from bauh.gems.snap.config import SnapConfigManager
from bauh.gems.snap.model import SnapApplication
from bauh.gems.snap.snapd import SnapdClient
@@ -42,6 +42,7 @@ class SnapManager(SoftwareManager):
self.categories = {}
self.suggestions_cache = context.cache_factory.new()
self.info_path = None
+ self.configman = SnapConfigManager()
self.custom_actions = [
CustomSoftwareAction(i18n_status_key='snap.action.refresh.status',
i18n_label_key='snap.action.refresh.label',
@@ -187,7 +188,7 @@ class SnapManager(SoftwareManager):
installed_names = {s['name'] for s in SnapdClient(self.logger).list_all_snaps()}
client = SnapdClient(self.logger)
- snap_config = read_config()
+ snap_config = self.configman.get_config()
try:
channel = self._request_channel_installation(pkg=pkg, snap_config=snap_config, snapd_client=client, watcher=watcher)
@@ -283,27 +284,35 @@ class SnapManager(SoftwareManager):
except:
return False
- def _start_category_task(self, task_man: TaskManager):
- if task_man:
- task_man.register_task('snap_cats', self.i18n['task.download_categories'], get_icon_path())
- task_man.update_progress('snap_cats', 50, None)
+ def _start_category_task(self, taskman: TaskManager, create_config: CreateConfigFile, downloader: CategoriesDownloader):
+ if taskman:
+ taskman.update_progress('snap_cats', 0, self.i18n['task.waiting_task'].format(bold(create_config.task_name)))
+ create_config.join()
- def _finish_category_task(self, task_man: TaskManager):
- if task_man:
- task_man.update_progress('snap_cats', 100, None)
- task_man.finish_task('snap_cats')
+ categories_exp = create_config.config['categories_exp']
+ downloader.expiration = categories_exp if isinstance(categories_exp, int) else None
+ taskman.update_progress('snap_cats', 1, None)
+
+ def _finish_category_task(self, taskman: TaskManager):
+ if taskman:
+ taskman.update_progress('snap_cats', 100, None)
+ taskman.finish_task('snap_cats')
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
- snap_config = read_config()
+ create_config = CreateConfigFile(taskman=task_manager, configman=self.configman, i18n=self.i18n,
+ task_icon_path=get_icon_path(), logger=self.logger)
+ create_config.start()
- CategoriesDownloader(id_='snap', manager=self, http_client=self.http_client, logger=self.logger,
- url_categories_file=URL_CATEGORIES_FILE,
- categories_path=CATEGORIES_FILE_PATH,
- expiration=snap_config['categories_exp'] if isinstance(snap_config['categories_exp'], int) else 0,
- internet_connection=internet_available,
- internet_checker=self.context.internet_checker,
- before=lambda: self._start_category_task(task_manager),
- after=lambda: self._finish_category_task(task_manager)).start()
+ task_manager.register_task('snap_cats', self.i18n['task.download_categories'], get_icon_path())
+ category_downloader = CategoriesDownloader(id_='snap', manager=self, http_client=self.http_client,
+ logger=self.logger,
+ url_categories_file=URL_CATEGORIES_FILE,
+ categories_path=CATEGORIES_FILE_PATH,
+ internet_connection=internet_available,
+ internet_checker=self.context.internet_checker,
+ after=lambda: self._finish_category_task(task_manager))
+ category_downloader.before = lambda: self._start_category_task(task_manager, create_config, category_downloader)
+ category_downloader.start()
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
pass
@@ -436,7 +445,7 @@ class SnapManager(SoftwareManager):
return pkg.screenshots if pkg.has_screenshots() else []
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
- snap_config = read_config()
+ snap_config = self.configman.get_config()
max_width = 200
install_channel = new_select(label=self.i18n['snap.config.install_channel'],
@@ -457,14 +466,14 @@ class SnapManager(SoftwareManager):
return PanelComponent([FormComponent([install_channel, categories_exp], self.i18n['installation'].capitalize())])
def save_settings(self, component: ViewComponent) -> Tuple[bool, Optional[List[str]]]:
- config = read_config()
+ snap_config = self.configman.get_config()
panel = component.components[0]
- config['install_channel'] = panel.get_component('snap_install_channel').get_selected()
- config['categories_exp'] = panel.get_component('snap_cat_exp').get_int_value()
+ snap_config['install_channel'] = panel.get_component('snap_install_channel').get_selected()
+ snap_config['categories_exp'] = panel.get_component('snap_cat_exp').get_int_value()
try:
- save_config(config, CONFIG_FILE)
+ self.configman.save_config(snap_config)
return True, None
except:
return False, [traceback.format_exc()]
diff --git a/bauh/gems/web/config.py b/bauh/gems/web/config.py
index dde44cd6..82ace5d1 100644
--- a/bauh/gems/web/config.py
+++ b/bauh/gems/web/config.py
@@ -1,16 +1,17 @@
-from bauh.commons.config import read_config as read
+from bauh.commons.config import YAMLConfigManager
from bauh.gems.web import CONFIG_FILE
-def read_config(update_file: bool = False) -> dict:
- default_config = {
- 'environment': {
- 'system': False,
- 'electron': {'version': None},
- 'cache_exp': 1440
+class WebConfigManager(YAMLConfigManager):
+
+ def __init__(self):
+ super(WebConfigManager, self).__init__(config_file_path=CONFIG_FILE)
+
+ def get_default_config(self) -> dict:
+ return {
+ 'environment': {
+ 'system': False,
+ 'electron': {'version': None},
+ 'cache_exp': 1440
+ }
}
- }
-
- return read(CONFIG_FILE, default_config, update_file)
-
-
diff --git a/bauh/gems/web/controller.py b/bauh/gems/web/controller.py
index 484d2051..db2ff42a 100644
--- a/bauh/gems/web/controller.py
+++ b/bauh/gems/web/controller.py
@@ -28,15 +28,17 @@ from bauh.api.abstract.view import MessageType, MultipleSelectComponent, InputOp
SelectViewType, TextInputComponent, FormComponent, FileChooserComponent, ViewComponent, PanelComponent
from bauh.api.constants import DESKTOP_ENTRIES_DIR
from bauh.commons import resource
-from bauh.commons.config import save_config
+from bauh.commons.boot import CreateConfigFile
from bauh.commons.html import bold
from bauh.commons.system import ProcessHandler, get_dir_size, get_human_size_str, SimpleProcess
from bauh.gems.web import INSTALLED_PATH, nativefier, DESKTOP_ENTRY_PATH_PATTERN, URL_FIX_PATTERN, ENV_PATH, UA_CHROME, \
- SEARCH_INDEX_FILE, SUGGESTIONS_CACHE_FILE, ROOT_DIR, CONFIG_FILE, TEMP_PATH, FIXES_PATH, ELECTRON_PATH
-from bauh.gems.web.config import read_config
+ SEARCH_INDEX_FILE, SUGGESTIONS_CACHE_FILE, ROOT_DIR, TEMP_PATH, FIXES_PATH, ELECTRON_PATH, \
+ get_icon_path
+from bauh.gems.web.config import WebConfigManager
from bauh.gems.web.environment import EnvironmentUpdater, EnvironmentComponent
from bauh.gems.web.model import WebApplication
-from bauh.gems.web.worker import SuggestionsDownloader, SearchIndexGenerator
+from bauh.gems.web.worker import SuggestionsManager, UpdateEnvironmentSettings, \
+ SuggestionsLoader, SearchIndexGenerator
try:
from bs4 import BeautifulSoup, SoupStrainer
@@ -58,7 +60,7 @@ RE_SYMBOLS_SPLIT = re.compile(r'[\-|_\s:.]')
class WebApplicationManager(SoftwareManager):
- def __init__(self, context: ApplicationContext, suggestions_downloader: Thread = None):
+ def __init__(self, context: ApplicationContext, suggestions_loader: Optional[SuggestionsLoader] = None):
super(WebApplicationManager, self).__init__(context=context)
self.http_client = context.http_client
self.env_updater = EnvironmentUpdater(logger=context.logger, http_client=context.http_client,
@@ -67,8 +69,9 @@ class WebApplicationManager(SoftwareManager):
self.i18n = context.i18n
self.logger = context.logger
self.env_thread = None
- self.suggestions_downloader = suggestions_downloader
+ self.suggestions_loader = suggestions_loader
self.suggestions = {}
+ self.configman = WebConfigManager()
self.custom_actions = [CustomSoftwareAction(i18n_label_key='web.custom_action.clean_env',
i18n_status_key='web.custom_action.clean_env.status',
manager=self,
@@ -254,8 +257,8 @@ class WebApplicationManager(SoftwareManager):
index = self._read_search_index()
- if not index and self.suggestions_downloader and self.suggestions_downloader.is_alive():
- self.suggestions_downloader.join()
+ if not index and self.suggestions_loader and self.suggestions_loader.is_alive():
+ self.suggestions_loader.join()
index = self._read_search_index()
if index:
@@ -634,7 +637,7 @@ class WebApplicationManager(SoftwareManager):
watcher.change_substatus(self.i18n['web.env.checking'])
handler = ProcessHandler(watcher)
- web_config = read_config()
+ web_config = self.configman.get_config()
env_settings = self.env_updater.read_settings(web_config=web_config)
if web_config['environment']['system'] and not nativefier.is_available():
@@ -796,7 +799,7 @@ class WebApplicationManager(SoftwareManager):
def can_work(self) -> bool:
if BS4_AVAILABLE and LXML_AVAILABLE:
- config = read_config(update_file=True)
+ config = self.configman.get_config()
use_system_env = config['environment']['system']
if not use_system_env:
@@ -809,28 +812,37 @@ class WebApplicationManager(SoftwareManager):
def requires_root(self, action: SoftwareAction, pkg: SoftwarePackage) -> bool:
return False
- def _download_suggestions(self, downloader: SuggestionsDownloader):
- self.suggestions = downloader.download()
-
- if self.suggestions:
- index_gen = SearchIndexGenerator(logger=self.logger)
- Thread(target=index_gen.generate_index, args=(self.suggestions,), daemon=True).start()
+ def _assign_suggestions(self, suggestions: dict):
+ self.suggestions = suggestions
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
+ create_config = CreateConfigFile(taskman=task_manager, configman=self.configman, i18n=self.i18n,
+ task_icon_path=get_icon_path(), logger=self.logger)
+ create_config.start()
+
if internet_available:
- downloader = SuggestionsDownloader(logger=self.logger, http_client=self.http_client,
- i18n=self.i18n, taskman=task_manager)
- downloader.register_task()
+ UpdateEnvironmentSettings(env_updater=EnvironmentUpdater(logger=self.context.logger,
+ i18n=self.i18n,
+ http_client=self.http_client,
+ file_downloader=self.context.file_downloader,
+ taskman=task_manager),
+ taskman=task_manager,
+ create_config=create_config,
+ i18n=self.i18n).start()
- self.suggestions_downloader = Thread(target=self._download_suggestions, args=(downloader,), daemon=True)
- self.suggestions_downloader.start()
+ self.suggestions_loader = SuggestionsLoader(manager=SuggestionsManager(logger=self.logger,
+ http_client=self.http_client,
+ i18n=self.i18n),
+ logger=self.logger,
+ i18n=self.i18n,
+ taskman=task_manager,
+ suggestions_callback=self._assign_suggestions)
+ self.suggestions_loader.start()
- web_config = read_config()
-
- if self.env_updater.should_download_settings(web_config):
- self.env_updater.register_task_read_settings(taskman=task_manager)
- self.env_thread = Thread(target=self.env_updater.read_settings, args=(web_config, False, task_manager), daemon=True)
- self.env_thread.start()
+ SearchIndexGenerator(taskman=task_manager,
+ suggestions_loader=self.suggestions_loader,
+ i18n=self.i18n,
+ logger=self.logger).start()
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
pass
@@ -893,7 +905,7 @@ class WebApplicationManager(SoftwareManager):
return PackageSuggestion(priority=SuggestionPriority(suggestion['priority']), package=app)
def _fill_config_async(self, output: dict):
- output.update(read_config())
+ output.update(self.configman.get_config())
def list_suggestions(self, limit: int, filter_installed: bool) -> List[PackageSuggestion]:
web_config = {}
@@ -903,14 +915,14 @@ class WebApplicationManager(SoftwareManager):
if self.suggestions:
suggestions = self.suggestions
- elif self.suggestions_downloader:
- self.suggestions_downloader.join(5)
+ elif self.suggestions_loader:
+ self.suggestions_loader.join(5)
suggestions = self.suggestions
else:
- suggestions = SuggestionsDownloader(logger=self.logger, http_client=self.http_client, i18n=self.i18n).download()
+ suggestions = SuggestionsManager(logger=self.logger, http_client=self.http_client, i18n=self.i18n).download()
# cleaning memory
- self.suggestions_downloader = None
+ self.suggestions_loader = None
self.suggestions = None
if suggestions:
@@ -981,7 +993,7 @@ class WebApplicationManager(SoftwareManager):
traceback.print_exc()
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
- web_config = read_config()
+ web_config = self.configman.get_config()
max_width = floor(screen_width * 0.15)
input_electron = TextInputComponent(label=self.i18n['web.settings.electron.version.label'],
@@ -1018,7 +1030,7 @@ class WebApplicationManager(SoftwareManager):
return PanelComponent([form_env])
def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
- web_config = read_config()
+ web_config = self.configman.get_config()
form_env = component.components[0]
@@ -1036,7 +1048,7 @@ class WebApplicationManager(SoftwareManager):
web_config['environment']['cache_exp'] = form_env.get_component('web_cache_exp').get_int_value()
try:
- save_config(web_config, CONFIG_FILE)
+ self.configman.save_config(web_config)
return True, None
except:
return False, [traceback.format_exc()]
diff --git a/bauh/gems/web/environment.py b/bauh/gems/web/environment.py
index e8d077fa..fd0303c1 100644
--- a/bauh/gems/web/environment.py
+++ b/bauh/gems/web/environment.py
@@ -41,12 +41,13 @@ class EnvironmentComponent:
class EnvironmentUpdater:
- def __init__(self, logger: logging.Logger, http_client: HttpClient, file_downloader: FileDownloader, i18n: I18n):
+ def __init__(self, logger: logging.Logger, http_client: HttpClient, file_downloader: FileDownloader, i18n: I18n, taskman: Optional[TaskManager] = None):
self.logger = logger
self.file_downloader = file_downloader
self.i18n = i18n
self.http_client = http_client
self.task_read_settings_id = 'web_read_settings'
+ self.taskman = taskman
def _download_and_install(self, version: str, version_url: str, watcher: ProcessWatcher) -> bool:
self.logger.info("Downloading NodeJS {}: {}".format(version, version_url))
@@ -267,10 +268,10 @@ class EnvironmentUpdater:
return res
- def _finish_task_download_settings(self, task_man: TaskManager):
- if task_man:
- task_man.update_progress(self.task_read_settings_id, 100, None)
- task_man.finish_task(self.task_read_settings_id)
+ def _finish_task_download_settings(self):
+ if self.taskman:
+ self.taskman.update_progress(self.task_read_settings_id, 100, None)
+ self.taskman.finish_task(self.task_read_settings_id)
def should_download_settings(self, web_config: dict) -> bool:
try:
@@ -302,7 +303,14 @@ class EnvironmentUpdater:
self.logger.error("Could not parse environment settings file timestamp: {}".format(env_ts_str))
return True
- return env_timestamp + timedelta(minutes=settings_exp) <= datetime.utcnow()
+ expired = env_timestamp + timedelta(minutes=settings_exp) <= datetime.utcnow()
+
+ if expired:
+ self.logger.info("Environment settings file has expired. It should be re-downloaded")
+ return True
+ else:
+ self.logger.info("Cached environment settings file is up to date")
+ return False
def read_cached_settings(self, web_config: dict) -> Optional[dict]:
if not self.should_download_settings(web_config):
@@ -314,32 +322,33 @@ class EnvironmentUpdater:
except yaml.YAMLError:
self.logger.error('Could not parse the cache environment settings file: {}'.format(cached_settings_str))
- def register_task_read_settings(self, taskman: TaskManager):
- taskman.register_task(self.task_read_settings_id, self.i18n['web.task.download_settings'], get_icon_path())
+ def read_settings(self, web_config: dict, cache: bool = True) -> Optional[dict]:
+ if self.taskman:
+ self.taskman.register_task(self.task_read_settings_id, self.i18n['web.task.download_settings'], get_icon_path())
+ self.taskman.update_progress(self.task_read_settings_id, 1, None)
- def read_settings(self, web_config: dict, cache: bool = True, taskman: Optional[TaskManager] = None) -> Optional[dict]:
cached_settings = self.read_cached_settings(web_config) if cache else None
if cached_settings:
return cached_settings
try:
- if taskman:
- taskman.update_progress(self.task_read_settings_id, 10, None)
+ if self.taskman:
+ self.taskman.update_progress(self.task_read_settings_id, 10, None)
self.logger.info("Downloading environment settings")
res = self.http_client.get(URL_ENVIRONMENT_SETTINGS)
if not res:
self.logger.warning('Could not retrieve the environments settings from the cloud')
- self._finish_task_download_settings(taskman)
+ self._finish_task_download_settings()
return
try:
settings = yaml.safe_load(res.content)
except yaml.YAMLError:
self.logger.error('Could not parse environment settings: {}'.format(res.text))
- self._finish_task_download_settings(taskman)
+ self._finish_task_download_settings()
return
self.logger.info("Caching environment settings to disk")
@@ -350,7 +359,7 @@ class EnvironmentUpdater:
except OSError:
self.logger.error("Could not create Web cache directory: {}".format(cache_dir))
self.logger.info('Finished')
- self._finish_task_download_settings(taskman)
+ self._finish_task_download_settings()
return
cache_timestamp = datetime.utcnow().timestamp()
@@ -360,12 +369,12 @@ class EnvironmentUpdater:
with open(ENVIRONMENT_SETTINGS_TS_FILE, 'w+') as f:
f.write(str(cache_timestamp))
- self._finish_task_download_settings(taskman)
+ self._finish_task_download_settings()
self.logger.info("Finished")
return settings
except requests.exceptions.ConnectionError:
- self._finish_task_download_settings(taskman)
+ self._finish_task_download_settings()
return
def _check_and_fill_electron(self, pkg: WebApplication, env: dict, local_config: dict, x86_x64: bool, widevine: bool, output: List[EnvironmentComponent]):
diff --git a/bauh/gems/web/resources/locale/ca b/bauh/gems/web/resources/locale/ca
index eb8fc2f2..0365d8be 100644
--- a/bauh/gems/web/resources/locale/ca
+++ b/bauh/gems/web/resources/locale/ca
@@ -73,7 +73,9 @@ web.settings.nativefier.system.tooltip=The Nativefier version installed on your
web.settings.nativefier.system=system
web.settings.nativefier.tip=Defines which Nativefier version should be used to generate the Web applications
web.task.download_settings=Updating environment settings
-web.task.suggestions=Downloading applications suggestions list
+web.task.search_index=Indexing suggestions
+web.task.suggestions=Downloading suggestions
+web.task.suggestions.saving=Saving to disk
web.uninstall.error.install_dir.not_found=The installation directory {} was not found
web.uninstall.error.remove_dir=It was not possible to remove {}
web.waiting.env_updater=Updating environment
\ No newline at end of file
diff --git a/bauh/gems/web/resources/locale/en b/bauh/gems/web/resources/locale/en
index eb8fc2f2..0365d8be 100644
--- a/bauh/gems/web/resources/locale/en
+++ b/bauh/gems/web/resources/locale/en
@@ -73,7 +73,9 @@ web.settings.nativefier.system.tooltip=The Nativefier version installed on your
web.settings.nativefier.system=system
web.settings.nativefier.tip=Defines which Nativefier version should be used to generate the Web applications
web.task.download_settings=Updating environment settings
-web.task.suggestions=Downloading applications suggestions list
+web.task.search_index=Indexing suggestions
+web.task.suggestions=Downloading suggestions
+web.task.suggestions.saving=Saving to disk
web.uninstall.error.install_dir.not_found=The installation directory {} was not found
web.uninstall.error.remove_dir=It was not possible to remove {}
web.waiting.env_updater=Updating environment
\ No newline at end of file
diff --git a/bauh/gems/web/resources/locale/es b/bauh/gems/web/resources/locale/es
index ee60e4b1..03e99768 100644
--- a/bauh/gems/web/resources/locale/es
+++ b/bauh/gems/web/resources/locale/es
@@ -73,7 +73,9 @@ web.settings.nativefier.system.tooltip=Se utilizará la versión de Nativefier i
web.settings.nativefier.system=sistema
web.settings.nativefier.tip=Define qué versión de Nativefier debe usarse para generar las aplicaciones Web
web.task.download_settings=Actualizando configuraciones de ambiente
-web.task.suggestions=Descargando la lista de sugerencias de aplicaciones
+web.task.search_index=Indexando sugerencias
+web.task.suggestions=Descargando sugerencias
+web.task.suggestions.saving=Guardando en disco
web.uninstall.error.install_dir.not_found=No se encontró el directorio de instalación {}
web.uninstall.error.remove_dir=No fue posible eliminar {}
web.waiting.env_updater=Actualizando el ambiente
\ No newline at end of file
diff --git a/bauh/gems/web/resources/locale/fr b/bauh/gems/web/resources/locale/fr
index f9b225a0..5e0ea4d3 100644
--- a/bauh/gems/web/resources/locale/fr
+++ b/bauh/gems/web/resources/locale/fr
@@ -73,7 +73,9 @@ web.settings.nativefier.system.tooltip=La version de Nativefier installée sur v
web.settings.nativefier.system=système
web.settings.nativefier.tip=Definit quelle version de Nativefier doit être utilisée pour géner les applications Web
web.task.download_settings=Mise à jour des paramètres d'environnement
-web.task.suggestions=Téléchargement de la liste de suggestions d'applications
+web.task.search_index=Indexing suggestions
+web.task.suggestions=Téléchargement de suggestions
+web.task.suggestions.saving=Saving to disk
web.uninstall.error.install_dir.not_found=Impossible de trouver le dossier d'installation {}
web.uninstall.error.remove_dir=Impossible d'enlever {}
web.waiting.env_updater=Mise à jour de l'environnement
diff --git a/bauh/gems/web/resources/locale/it b/bauh/gems/web/resources/locale/it
index eb8fc2f2..0365d8be 100644
--- a/bauh/gems/web/resources/locale/it
+++ b/bauh/gems/web/resources/locale/it
@@ -73,7 +73,9 @@ web.settings.nativefier.system.tooltip=The Nativefier version installed on your
web.settings.nativefier.system=system
web.settings.nativefier.tip=Defines which Nativefier version should be used to generate the Web applications
web.task.download_settings=Updating environment settings
-web.task.suggestions=Downloading applications suggestions list
+web.task.search_index=Indexing suggestions
+web.task.suggestions=Downloading suggestions
+web.task.suggestions.saving=Saving to disk
web.uninstall.error.install_dir.not_found=The installation directory {} was not found
web.uninstall.error.remove_dir=It was not possible to remove {}
web.waiting.env_updater=Updating environment
\ No newline at end of file
diff --git a/bauh/gems/web/resources/locale/pt b/bauh/gems/web/resources/locale/pt
index 5c5c5ae6..3310e350 100644
--- a/bauh/gems/web/resources/locale/pt
+++ b/bauh/gems/web/resources/locale/pt
@@ -72,7 +72,9 @@ web.settings.nativefier.system.tooltip=A versão do Nativefier instalada no seu
web.settings.nativefier.system=sistema
web.settings.nativefier.tip=Define qual versão do Nativefier será utilizada para gerar os aplicativos Web
web.task.download_settings=Atualizando configurações de ambiente
-web.task.suggestions=Baixando lista de sugestões de aplicativos
+web.task.search_index=Indexando sugestões
+web.task.suggestions=Baixando sugestões
+web.task.suggestions.saving=Salvando em disco
web.uninstall.error.install_dir.not_found=O diretório de instalação {} não foi encontrado
web.uninstall.error.remove=Não foi possível remover {}
web.waiting.env_updater=Atualizando ambiente
diff --git a/bauh/gems/web/resources/locale/ru b/bauh/gems/web/resources/locale/ru
index 94fcd970..d14ec477 100644
--- a/bauh/gems/web/resources/locale/ru
+++ b/bauh/gems/web/resources/locale/ru
@@ -73,7 +73,9 @@ web.settings.nativefier.system=Из системы
web.settings.nativefier.system.tooltip=Будет использоваться версия Nativefier установленная в Вашей системе
web.settings.nativefier.tip=Определяет, какие Nativefier версии должны быдут использованы для установки веб-приложений
web.task.download_settings=Updating environment settings
-web.task.suggestions=Downloading applications suggestions list
+web.task.search_index=Indexing suggestions
+web.task.suggestions=Downloading suggestions
+web.task.suggestions.saving=Saving to disk
web.uninstall.error.install_dir.not_found=Каталог установки {} не найден
web.uninstall.error.remove_dir=Не удалось удалить {}
web.waiting.env_updater=Обнавляется Веб-среда
\ No newline at end of file
diff --git a/bauh/gems/web/resources/locale/tr b/bauh/gems/web/resources/locale/tr
index 60e3eafb..62a4d4ad 100644
--- a/bauh/gems/web/resources/locale/tr
+++ b/bauh/gems/web/resources/locale/tr
@@ -73,7 +73,9 @@ web.settings.nativefier.system.tooltip=Sisteminizde yüklü olan Nativefier sür
web.settings.nativefier.system=sistem
web.settings.nativefier.tip=Web uygulamalarını oluşturmak için hangi Nativefier sürümünün kullanılması gerektiğini tanımlar
web.task.download_settings=Ortam ayarları güncelleniyor
-web.task.suggestions=Uygulama öneri listesi indiriliyor
+web.task.search_index=Indexing suggestions
+web.task.suggestions=Downloading suggestions
+web.task.suggestions.saving=Saving to disk
web.uninstall.error.install_dir.not_found={} kurulum dizini bulunamadı
web.uninstall.error.remove_dir={} kaldırmak mümkün olmadı
web.waiting.env_updater=Ortam güncelleniyor
diff --git a/bauh/gems/web/suggestions.py b/bauh/gems/web/suggestions.py
new file mode 100644
index 00000000..ecd0bf7f
--- /dev/null
+++ b/bauh/gems/web/suggestions.py
@@ -0,0 +1,59 @@
+import os
+import traceback
+from logging import Logger
+from pathlib import Path
+
+import requests
+import yaml
+
+from bauh.api.http import HttpClient
+from bauh.gems.web import URL_SUGGESTIONS, SUGGESTIONS_CACHE_FILE
+from bauh.view.util.translation import I18n
+
+
+class SuggestionsManager:
+
+ def __init__(self, http_client: HttpClient, logger: Logger, i18n: I18n):
+ self.http_client = http_client
+ self.logger = logger
+ self.i18n = i18n
+
+ def download(self) -> dict:
+ self.logger.info("Reading suggestions from {}".format(URL_SUGGESTIONS))
+ try:
+ suggestions = self.http_client.get_yaml(URL_SUGGESTIONS, session=False)
+
+ if suggestions:
+ self.logger.info("{} suggestions successfully read".format(len(suggestions)))
+ else:
+ self.logger.warning("Could not read suggestions from {}".format(URL_SUGGESTIONS))
+
+ except (requests.exceptions.ConnectionError, requests.exceptions.ConnectTimeout):
+ self.logger.warning("Internet seems to be off: it was not possible to retrieve the suggestions")
+ suggestions = {}
+
+ self.logger.info("Finished")
+ return suggestions
+
+ def save_to_disk(self, suggestions: dict):
+ if not suggestions:
+ return
+
+ self.logger.info('Caching {} suggestions to the disk'.format(len(suggestions)))
+ suggestions_file_dir = os.path.dirname(SUGGESTIONS_CACHE_FILE)
+ try:
+ Path(suggestions_file_dir).mkdir(parents=True, exist_ok=True)
+ except OSError:
+ self.logger.error("Could not generate the directory {}".format(suggestions_file_dir))
+ traceback.print_exc()
+ return
+
+ try:
+ with open(SUGGESTIONS_CACHE_FILE, 'w+') as f:
+ f.write(yaml.safe_dump(suggestions))
+
+ self.logger.info("{} suggestions successfully cached to file '{}'".format(len(suggestions), SUGGESTIONS_CACHE_FILE))
+ except:
+ self.logger.error("Could write to {}".format(SUGGESTIONS_CACHE_FILE))
+ traceback.print_exc()
+ return
diff --git a/bauh/gems/web/worker.py b/bauh/gems/web/worker.py
index 3d3628fd..a96c9cea 100644
--- a/bauh/gems/web/worker.py
+++ b/bauh/gems/web/worker.py
@@ -1,87 +1,85 @@
import logging
+import time
import traceback
-from pathlib import Path
+from threading import Thread
+from typing import Optional
-import requests
import yaml
from bauh.api.abstract.handler import TaskManager
-from bauh.api.http import HttpClient
-from bauh.gems.web import URL_SUGGESTIONS, TEMP_PATH, SEARCH_INDEX_FILE, SUGGESTIONS_CACHE_FILE, get_icon_path
+from bauh.commons.boot import CreateConfigFile
+from bauh.commons.html import bold
+from bauh.gems.web import SEARCH_INDEX_FILE, get_icon_path
+from bauh.gems.web.environment import EnvironmentUpdater
+from bauh.gems.web.suggestions import SuggestionsManager
from bauh.view.util.translation import I18n
-class SuggestionsDownloader:
+class SuggestionsLoader(Thread):
- def __init__(self, http_client: HttpClient, logger: logging.Logger, i18n: I18n, taskman: TaskManager = None):
- super(SuggestionsDownloader, self).__init__()
- self.http_client = http_client
- self.logger = logger
+ def __init__(self, taskman: TaskManager, manager: SuggestionsManager,
+ i18n: I18n, logger: logging.Logger, suggestions_callback, suggestions: Optional[dict] = None):
+ super(SuggestionsLoader, self).__init__(daemon=True)
self.taskman = taskman
- self.i18n = i18n
self.task_id = 'web_sugs'
- self._task_registered = False
- self._task_finished = False
+ self.manager = manager
+ self.suggestions_callback = suggestions_callback
+ self.i18n = i18n
+ self.logger = logger
+ self.suggestions = suggestions
+ self.task_name = self.i18n['web.task.suggestions']
+ self.taskman.register_task(self.task_id, self.task_name, get_icon_path())
- def _finish_task(self):
- if self.taskman:
+ def run(self):
+ ti = time.time()
+ self.taskman.update_progress(self.task_id, 10, None)
+ try:
+ self.suggestions = self.manager.download()
+
+ if self.suggestions_callback:
+ self.suggestions_callback(self.suggestions)
+
+ if self.suggestions:
+ self.taskman.update_progress(self.task_id, 50, self.i18n['web.task.suggestions.saving'])
+ self.manager.save_to_disk(self.suggestions)
+
+ except:
+ self.logger.error("Unexpected exception")
+ traceback.print_exc()
+ finally:
self.taskman.update_progress(self.task_id, 100, None)
self.taskman.finish_task(self.task_id)
- self._task_finished = True
- self.logger.info("Finished")
-
- def register_task(self):
- if self.taskman and not self._task_registered and not self._task_finished:
- self.taskman.register_task(self.task_id, self.i18n['web.task.suggestions'], get_icon_path())
- self._task_registered = True
-
- def download(self) -> dict:
- if self.taskman:
- self.taskman.update_progress(self.task_id, 10, None)
-
- self.logger.info("Reading suggestions from {}".format(URL_SUGGESTIONS))
- try:
- suggestions = self.http_client.get_yaml(URL_SUGGESTIONS, session=False)
-
- if suggestions:
- self.logger.info("{} suggestions successfully read".format(len(suggestions)))
- else:
- self.logger.warning("Could not read suggestions from {}".format(URL_SUGGESTIONS))
-
- except (requests.exceptions.ConnectionError, requests.exceptions.ConnectTimeout):
- self.logger.warning("Internet seems to be off: it was not possible to retrieve the suggestions")
- self._finish_task()
- return {}
-
- self._finish_task()
- return suggestions
+ tf = time.time()
+ self.logger.info("Finished. Took {0:.2f} seconds".format(tf - ti))
-class SearchIndexGenerator:
+class SearchIndexGenerator(Thread):
- def __init__(self, logger: logging.Logger):
+ def __init__(self, taskman: TaskManager, suggestions_loader: SuggestionsLoader, i18n: I18n, logger: logging.Logger):
+ super(SearchIndexGenerator, self).__init__(daemon=True)
+ self.taskman = taskman
+ self.i18n = i18n
self.logger = logger
+ self.suggestions_loader = suggestions_loader
+ self.task_id = 'web_idx_gen'
+ self.taskman.register_task(self.task_id, self.i18n['web.task.search_index'], get_icon_path())
+
+ def run(self):
+ ti = time.time()
+ self.taskman.update_progress(self.task_id, 0, self.i18n['task.waiting_task'].format(bold(self.suggestions_loader.task_name)))
+ self.suggestions_loader.join()
+
+ if self.suggestions_loader.suggestions:
+ self.generate_index(self.suggestions_loader.suggestions)
+ else:
+ self.taskman.update_progress(self.task_id, 100, None)
+ self.taskman.finish_task(self.task_id)
+
+ tf = time.time()
+ self.logger.info("Finished. Took {0:.2f} seconds".format(tf - ti))
def generate_index(self, suggestions: dict):
- self.logger.info('Caching {} suggestions to the disk'.format(len(suggestions)))
-
- try:
- Path(TEMP_PATH).mkdir(parents=True, exist_ok=True)
- except:
- self.logger.error("Could not generate the directory {}".format(TEMP_PATH))
- traceback.print_exc()
- return
-
- try:
- with open(SUGGESTIONS_CACHE_FILE, 'w+') as f:
- f.write(yaml.safe_dump(suggestions))
-
- self.logger.info('{} successfully cached to the disk as {}'.format(len(suggestions), SUGGESTIONS_CACHE_FILE))
- except:
- self.logger.error("Could write to {}".format(SUGGESTIONS_CACHE_FILE))
- traceback.print_exc()
- return
-
+ self.taskman.update_progress(self.task_id, 1, None)
self.logger.info('Indexing suggestions')
index = {}
@@ -102,6 +100,7 @@ class SearchIndexGenerator:
mapped.add(key)
if index:
+ self.taskman.update_progress(self.task_id, 50, self.i18n['web.task.suggestions.saving'])
self.logger.info('Preparing search index for writing')
for key in index.keys():
@@ -115,3 +114,29 @@ class SearchIndexGenerator:
except:
self.logger.error("Could not write the seach index to {}".format(SEARCH_INDEX_FILE))
traceback.print_exc()
+
+ self.taskman.update_progress(self.task_id, 100, None)
+ self.taskman.finish_task(self.task_id)
+
+
+class UpdateEnvironmentSettings(Thread):
+
+ def __init__(self, env_updater: EnvironmentUpdater, taskman: TaskManager, i18n: I18n, create_config: CreateConfigFile):
+ super(UpdateEnvironmentSettings, self).__init__(daemon=True)
+ self.env_updater = env_updater
+ self.taskman = taskman
+ self.create_config = create_config
+ self.task_id = env_updater.task_read_settings_id
+ self.i18n = i18n
+
+ def run(self):
+ self.taskman.register_task(self.task_id, self.i18n['web.task.download_settings'], get_icon_path())
+ self.taskman.update_progress(self.task_id, 1, self.i18n['task.waiting_task'].format(bold(self.create_config.task_name)))
+ self.create_config.join()
+
+ web_config = self.create_config.config
+ if self.env_updater.should_download_settings(web_config):
+ self.env_updater.read_settings(web_config=web_config, cache=False)
+ else:
+ self.taskman.update_progress(self.task_id, 100, None)
+ self.taskman.finish_task(self.task_id)
diff --git a/bauh/view/core/config.py b/bauh/view/core/config.py
index ce6fe43f..9737bc5c 100644
--- a/bauh/view/core/config.py
+++ b/bauh/view/core/config.py
@@ -1,80 +1,73 @@
from pathlib import Path
-import yaml
-
from bauh import __app_name__
-from bauh.commons.config import read_config as read
+from bauh.commons.config import YAMLConfigManager
-CONFIG_PATH = '{}/.config/{}'.format(Path.home(), __app_name__)
-FILE_PATH = '{}/config.yml'.format(CONFIG_PATH)
+FILE_PATH = '{}/.config/{}/config.yml'.format(str(Path.home()), __app_name__)
-def read_config(update_file: bool = False) -> dict:
- default = {
- 'gems': None,
- 'memory_cache': {
- 'data_expiration': 60 * 60,
- 'icon_expiration': 60 * 5
- },
- 'locale': None,
- 'updates': {
- 'check_interval': 30,
- 'ask_for_reboot': True
- },
- 'system': {
- 'notifications': True,
- 'single_dependency_checking': False
- },
- 'suggestions': {
- 'enabled': True,
- 'by_type': 10
- },
- 'ui': {
- 'table': {
- 'max_displayed': 50
+class CoreConfigManager(YAMLConfigManager):
+
+ def __init__(self):
+ super(CoreConfigManager, self).__init__(config_file_path=FILE_PATH)
+
+ def get_default_config(self) -> dict:
+ return {
+ 'gems': None,
+ 'memory_cache': {
+ 'data_expiration': 60 * 60,
+ 'icon_expiration': 60 * 5
},
- 'tray': {
- 'default_icon': None,
- 'updates_icon': None
+ 'locale': None,
+ 'updates': {
+ 'check_interval': 30,
+ 'ask_for_reboot': True
},
- 'qt_style': 'fusion',
- 'hdpi': True,
- "auto_scale": False,
- "scale_factor": 1.0,
- 'theme': 'light',
- 'system_theme': False
+ 'system': {
+ 'notifications': True,
+ 'single_dependency_checking': False
+ },
+ 'suggestions': {
+ 'enabled': True,
+ 'by_type': 10
+ },
+ 'ui': {
+ 'table': {
+ 'max_displayed': 50
+ },
+ 'tray': {
+ 'default_icon': None,
+ 'updates_icon': None
+ },
+ 'qt_style': 'fusion',
+ 'hdpi': True,
+ "auto_scale": False,
+ "scale_factor": 1.0,
+ 'theme': 'light',
+ 'system_theme': False
- },
- 'download': {
- 'multithreaded': True,
- 'multithreaded_client': None,
- 'icons': True
- },
- 'store_root_password': True,
- 'disk': {
- 'trim': {
- 'after_upgrade': False
+ },
+ 'download': {
+ 'multithreaded': True,
+ 'multithreaded_client': None,
+ 'icons': True
+ },
+ 'store_root_password': True,
+ 'disk': {
+ 'trim': {
+ 'after_upgrade': False
+ }
+ },
+ 'backup': {
+ 'enabled': True,
+ 'install': None,
+ 'uninstall': None,
+ 'downgrade': None,
+ 'upgrade': None,
+ 'mode': 'incremental',
+ 'type': 'rsync'
+ },
+ 'boot': {
+ 'load_apps': True
}
- },
- 'backup': {
- 'enabled': True,
- 'install': None,
- 'uninstall': None,
- 'downgrade': None,
- 'upgrade': None,
- 'mode': 'incremental',
- 'type': 'rsync'
- },
- 'boot': {
- 'load_apps': True
}
-
- }
- return read(FILE_PATH, default, update_file=update_file, update_async=True)
-
-
-def save(config: dict):
- Path(CONFIG_PATH).mkdir(parents=True, exist_ok=True)
-
- with open(FILE_PATH, 'w+') as f:
- f.write(yaml.safe_dump(config))
diff --git a/bauh/view/core/controller.py b/bauh/view/core/controller.py
index 21f5eb70..baca76d9 100755
--- a/bauh/view/core/controller.py
+++ b/bauh/view/core/controller.py
@@ -14,12 +14,14 @@ from bauh.api.abstract.model import SoftwarePackage, PackageUpdate, PackageHisto
CustomSoftwareAction
from bauh.api.abstract.view import ViewComponent, TabGroupComponent, MessageType
from bauh.api.exception import NoInternetException
+from bauh.commons.boot import CreateConfigFile
from bauh.commons.html import bold
from bauh.commons.system import run_cmd
-from bauh.view.core.config import read_config
+from bauh.view.core.config import CoreConfigManager
from bauh.view.core.settings import GenericSettingsManager
from bauh.view.core.update import check_for_update
from bauh.view.util import resource
+from bauh.view.util.resource import get_path
from bauh.view.util.util import clean_app_files, restart_app
RE_IS_URL = re.compile(r'^https?://.+')
@@ -52,6 +54,7 @@ class GenericSoftwareManager(SoftwareManager):
self.config = config
self.settings_manager = settings_manager
self.http_client = context.http_client
+ self.configman = CoreConfigManager()
self.extra_actions = [CustomSoftwareAction(i18n_label_key='action.reset',
i18n_status_key='action.reset.status',
manager_method='reset',
@@ -402,14 +405,25 @@ class GenericSoftwareManager(SoftwareManager):
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
ti = time.time()
self.logger.info("Initializing")
+ taskman = task_manager if task_manager else TaskManager() # empty task manager to prevent null pointers
+
+ create_config = CreateConfigFile(taskman=taskman, configman=self.configman, i18n=self.i18n,
+ task_icon_path=get_path('img/logo.svg'), logger=self.logger)
+ create_config.start()
+
if self.managers:
internet_on = self.context.is_internet_available()
- taskman = task_manager if task_manager else TaskManager() # empty task manager to prevent null pointers
+ prepare_tasks = []
for man in self.managers:
if man not in self._already_prepared and self._can_work(man):
- man.prepare(taskman, root_password, internet_on)
+ t = Thread(target=man.prepare, args=(taskman, root_password, internet_on), daemon=True)
+ t.start()
+ prepare_tasks.append(t)
self._already_prepared.append(man)
+ for t in prepare_tasks:
+ t.join()
+
tf = time.time()
self.logger.info("Finished. Took {0:.2f} seconds".format(tf - ti))
@@ -525,7 +539,8 @@ class GenericSoftwareManager(SoftwareManager):
working_managers=self.working_managers,
logger=self.logger,
i18n=self.i18n,
- file_downloader=self.context.file_downloader)
+ file_downloader=self.context.file_downloader,
+ configman=self.configman)
else:
self.settings_manager.managers = self.managers
self.settings_manager.working_managers = self.working_managers
@@ -618,7 +633,7 @@ class GenericSoftwareManager(SoftwareManager):
if man_actions:
actions.extend(man_actions)
- app_config = read_config()
+ app_config = self.configman.get_config()
for action, available in self.dynamic_extra_actions.items():
if available(app_config):
diff --git a/bauh/view/core/settings.py b/bauh/view/core/settings.py
index 99a196fd..253da8d0 100644
--- a/bauh/view/core/settings.py
+++ b/bauh/view/core/settings.py
@@ -13,8 +13,8 @@ from bauh.api.abstract.view import ViewComponent, TabComponent, InputOption, Tex
PanelComponent, FormComponent, TabGroupComponent, SingleSelectComponent, SelectViewType, TextInputComponent, \
FileChooserComponent, RangeInputComponent
from bauh.commons.view_utils import new_select
-from bauh.view.core import config, timeshift
-from bauh.view.core.config import read_config
+from bauh.view.core import timeshift
+from bauh.view.core.config import CoreConfigManager
from bauh.view.core.downloader import AdaptableFileDownloader
from bauh.view.util import translation
from bauh.view.util.translation import I18n
@@ -23,12 +23,13 @@ from bauh.view.util.translation import I18n
class GenericSettingsManager:
def __init__(self, managers: List[SoftwareManager], working_managers: List[SoftwareManager],
- logger: logging.Logger, i18n: I18n, file_downloader: FileDownloader):
+ logger: logging.Logger, i18n: I18n, file_downloader: FileDownloader, configman: CoreConfigManager):
self.i18n = i18n
self.managers = managers
self.working_managers = working_managers
self.logger = logger
self.file_downloader = file_downloader
+ self.configman = configman
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
tabs = list()
@@ -54,7 +55,7 @@ class GenericSettingsManager:
if man.is_enabled() and man in self.working_managers:
def_gem_opts.add(opt)
- core_config = read_config()
+ core_config = self.configman.get_config()
if gem_opts:
type_help = TextComponent(html=self.i18n['core.config.types.tip'])
@@ -340,7 +341,7 @@ class GenericSettingsManager:
ui: PanelComponent,
tray: PanelComponent,
gems_panel: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
- core_config = config.read_config()
+ core_config = self.configman.get_config()
# general
general_form = general.components[0]
@@ -443,7 +444,7 @@ class GenericSettingsManager:
core_config['gems'] = None if core_config['gems'] is None and len(checked_gems) == len(self.managers) else checked_gems
try:
- config.save(core_config)
+ self.configman.save_config(core_config)
return True, None
except:
return False, [traceback.format_exc()]
diff --git a/bauh/view/qt/prepare.py b/bauh/view/qt/prepare.py
index 9df7d1fa..65a7f930 100644
--- a/bauh/view/qt/prepare.py
+++ b/bauh/view/qt/prepare.py
@@ -1,6 +1,8 @@
import datetime
import operator
+import time
from functools import reduce
+from threading import Lock
from typing import Tuple, Optional
from PyQt5.QtCore import QSize, Qt, QThread, pyqtSignal, QCoreApplication
@@ -34,7 +36,10 @@ class Prepare(QThread, TaskManager):
self.context = context
self.waiting_password = False
self.password_response = None
- self._registered = 0
+ self._tasks_added = set()
+ self._tasks_finished = set()
+ self._add_lock = Lock()
+ self._finish_lock = Lock()
def ask_password(self) -> Tuple[bool, Optional[str]]:
self.waiting_password = True
@@ -58,20 +63,42 @@ class Prepare(QThread, TaskManager):
QCoreApplication.exit(1)
self.manager.prepare(self, root_pwd, None)
- self.signal_started.emit(self._registered)
+ self._add_lock.acquire()
+ self.signal_started.emit(len(self._tasks_added))
+ self._add_lock.release()
def update_progress(self, task_id: str, progress: float, substatus: str):
- self.signal_update.emit(task_id, progress, substatus)
+ if task_id in self._tasks_added:
+ self.signal_update.emit(task_id, progress, substatus)
def update_output(self, task_id: str, output: str):
- self.signal_output.emit(task_id, output)
+ if task_id in self._tasks_added:
+ self.signal_output.emit(task_id, output)
def register_task(self, id_: str, label: str, icon_path: str):
- self._registered += 1
- self.signal_register.emit(id_, label, icon_path)
+ self._add_lock.acquire()
+
+ if id_ not in self._tasks_added:
+ self._tasks_added.add(id_)
+ self.signal_register.emit(id_, label, icon_path)
+
+ self._add_lock.release()
def finish_task(self, task_id: str):
- self.signal_finished.emit(task_id)
+ self._add_lock.acquire()
+ task_registered = task_id in self._tasks_added
+ self._add_lock.release()
+
+ if not task_registered:
+ return
+
+ self._finish_lock.acquire()
+
+ if task_id not in self._tasks_finished:
+ self._tasks_finished.add(task_id)
+ self.signal_finished.emit(task_id)
+
+ self._finish_lock.release()
class CheckFinished(QThread):
@@ -84,7 +111,7 @@ class CheckFinished(QThread):
def run(self):
while True:
- if self.total == self.finished:
+ if self.finished == self.total:
break
self.msleep(5)
@@ -134,6 +161,7 @@ class PreparePanel(QWidget, TaskManager):
self.output = {}
self.added_tasks = 0
self.ftasks = 0
+ self.started_at = None
self.self_close = False
self.prepare_thread = Prepare(self.context, manager, self.i18n)
@@ -263,6 +291,7 @@ class PreparePanel(QWidget, TaskManager):
centralize(self)
def start(self, tasks: int):
+ self.started_at = time.time()
self.check_thread.total = tasks
self.check_thread.start()
self.skip_thread.start()
@@ -387,9 +416,8 @@ class PreparePanel(QWidget, TaskManager):
def finish_task(self, task_id: str):
task = self.tasks[task_id]
- task['lb_sub'].setText('')
- for key in ('lb_prog', 'lb_status'):
+ for key in ('lb_prog', 'lb_status', 'lb_sub'):
label = task[key]
label.setProperty('status', 'done')
label.style().unpolish(label)
@@ -402,10 +430,9 @@ class PreparePanel(QWidget, TaskManager):
self.ftasks += 1
self.signal_status.emit(self.ftasks)
- if self.table.rowCount() == self.ftasks:
- self.label_top.setText(self.i18n['ready'].capitalize())
-
def finish(self):
+ now = time.time()
+ self.context.logger.info("{0} tasks finished in {1:.9f} seconds".format(self.ftasks, (now - self.started_at)))
if self.isVisible():
self.manage_window.show()
diff --git a/bauh/view/qt/root.py b/bauh/view/qt/root.py
index 7c260da0..fd541d32 100644
--- a/bauh/view/qt/root.py
+++ b/bauh/view/qt/root.py
@@ -9,7 +9,7 @@ from PyQt5.QtWidgets import QLineEdit, QApplication, QDialog, QPushButton, QVBox
from bauh.api.abstract.context import ApplicationContext
from bauh.commons.system import new_subprocess
-from bauh.view.core.config import read_config
+from bauh.view.core.config import CoreConfigManager
from bauh.view.qt.components import QtComponentsManager, new_spacer
from bauh.view.util import util
from bauh.view.util.translation import I18n
@@ -131,7 +131,7 @@ class RootDialog(QDialog):
def ask_password(context: ApplicationContext, i18n: I18n, app_config: Optional[dict] = None,
comp_manager: Optional[QtComponentsManager] = None, tries: int = 3) -> Tuple[bool, Optional[str]]:
- current_config = read_config() if not app_config else app_config
+ current_config = CoreConfigManager().get_config() if not app_config else app_config
store_password = bool(current_config['store_root_password'])
diff --git a/bauh/view/qt/thread.py b/bauh/view/qt/thread.py
index b2c75af5..e386138b 100644
--- a/bauh/view/qt/thread.py
+++ b/bauh/view/qt/thread.py
@@ -23,8 +23,8 @@ from bauh.api.exception import NoInternetException
from bauh.commons import user
from bauh.commons.html import bold
from bauh.commons.system import get_human_size_str, ProcessHandler, SimpleProcess
-from bauh.view.core import timeshift, config
-from bauh.view.core.config import read_config
+from bauh.view.core import timeshift
+from bauh.view.core.config import CoreConfigManager
from bauh.view.qt import commons
from bauh.view.qt.view_model import PackageView, PackageViewStatus
from bauh.view.util.translation import I18n
@@ -466,7 +466,7 @@ class UpgradeSelected(AsyncAction):
self.change_substatus('')
- app_config = read_config()
+ app_config = CoreConfigManager().get_config()
# backup dialog ( if enabled, supported and accepted )
should_backup = bkp_supported
@@ -572,7 +572,7 @@ class UninstallPackage(AsyncAction):
pkg=self.pkg,
i18n=self.i18n,
root_password=self.root_pwd,
- app_config=read_config())
+ app_config=CoreConfigManager().get_config())
if not proceed:
self.notify_finished({'success': False, 'removed': None, 'pkg': self.pkg})
self.pkg = None
@@ -615,7 +615,7 @@ class DowngradePackage(AsyncAction):
pkg=self.pkg,
i18n=self.i18n,
root_password=self.root_pwd,
- app_config=read_config())
+ app_config=CoreConfigManager().get_config())
if not proceed:
self.notify_finished({'app': self.pkg, 'success': success})
@@ -707,7 +707,7 @@ class InstallPackage(AsyncAction):
pkg=self.pkg,
i18n=self.i18n,
root_password=self.root_pwd,
- app_config=read_config())
+ app_config=CoreConfigManager().get_config())
if not proceed:
self.signal_finished.emit(res)
@@ -1007,7 +1007,7 @@ class CustomAction(AsyncAction):
res = {'success': False, 'pkg': self.pkg, 'action': self.custom_action, 'error': None, 'error_type': MessageType.ERROR}
if self.custom_action.backup:
- proceed, _ = self.request_backup(app_config=read_config(),
+ proceed, _ = self.request_backup(app_config=CoreConfigManager.get_config(),
action_key=None,
i18n=self.i18n,
root_password=self.root_pwd,
@@ -1081,10 +1081,11 @@ class SaveTheme(QThread):
def run(self):
if self.theme_key:
- core_config = read_config()
+ configman = CoreConfigManager()
+ core_config = configman.get_config()
core_config['ui']['theme'] = self.theme_key
try:
- config.save(core_config)
+ configman.save_config(core_config)
except:
traceback.print_exc()
diff --git a/bauh/view/qt/window.py b/bauh/view/qt/window.py
index bbad74e2..d40d5a89 100755
--- a/bauh/view/qt/window.py
+++ b/bauh/view/qt/window.py
@@ -22,7 +22,7 @@ from bauh.commons import user
from bauh.commons.html import bold
from bauh.context import set_theme
from bauh.stylesheet import read_all_themes_metadata, ThemeMetadata
-from bauh.view.core.config import read_config
+from bauh.view.core.config import CoreConfigManager
from bauh.view.core.tray_client import notify_tray
from bauh.view.qt import dialog, commons, qt_utils
from bauh.view.qt.about import AboutDialog
@@ -1586,7 +1586,7 @@ class ManageWindow(QWidget):
menu_row.exec_()
def _map_theme_actions(self, menu: QMenu) -> List[QCustomMenuAction]:
- core_config = read_config()
+ core_config = CoreConfigManager().get_config()
current_theme_key, current_action = core_config['ui']['theme'], None
diff --git a/bauh/view/resources/locale/ca b/bauh/view/resources/locale/ca
index 31ae55ba..95c5812c 100644
--- a/bauh/view/resources/locale/ca
+++ b/bauh/view/resources/locale/ca
@@ -391,6 +391,8 @@ status.caching_data=S’estan emmagatzemant {} dades a la memòria cau al disc
style=estil
success=success
summary=resum
+task.checking_config=Checking configuration file
+task.checking_config.saving=Creating file
task.download_categories=Download de categories
task.waiting_task=Waiting for {}
type=tipus
diff --git a/bauh/view/resources/locale/de b/bauh/view/resources/locale/de
index 440d4e17..8b555c43 100644
--- a/bauh/view/resources/locale/de
+++ b/bauh/view/resources/locale/de
@@ -391,6 +391,8 @@ status.caching_data={} Daten auf der Festplatte zwischenspeichern
style=Stil
success=success
summary=Zusammenfassung
+task.checking_config=Checking configuration file
+task.checking_config.saving=Creating file
task.download_categories=Downloading categories
task.waiting_task=Waiting for {}
type=Typ
diff --git a/bauh/view/resources/locale/en b/bauh/view/resources/locale/en
index e6593837..acd65ae9 100644
--- a/bauh/view/resources/locale/en
+++ b/bauh/view/resources/locale/en
@@ -392,6 +392,8 @@ status.caching_data=Caching {} data to disk
style=style
success=success
summary=summary
+task.checking_config=Checking configuration file
+task.checking_config.saving=Creating file
task.download_categories=Downloading categories
task.waiting_task=Waiting for {}
type=type
diff --git a/bauh/view/resources/locale/es b/bauh/view/resources/locale/es
index 4928aa86..72d12dd0 100644
--- a/bauh/view/resources/locale/es
+++ b/bauh/view/resources/locale/es
@@ -394,6 +394,8 @@ status.caching_data=Almacenando en antememoria los datos de {} para el disco
style=estilo
success=éxito
summary=resumen
+task.checking_config=Verificando archivo de configuración
+task.checking_config.saving=Creando archivo
task.download_categories=Descargando categorías
task.waiting_task=Esperando por {}
type=tipo
diff --git a/bauh/view/resources/locale/fr b/bauh/view/resources/locale/fr
index 6ec77d62..30e3bd23 100644
--- a/bauh/view/resources/locale/fr
+++ b/bauh/view/resources/locale/fr
@@ -388,6 +388,8 @@ status.caching_data=Mise en cache des données de {} sur disque
style=style
success=succès
summary=résumé
+task.checking_config=Checking configuration file
+task.checking_config.saving=Creating file
task.download_categories=Téléchargement des catégories
task.waiting_task=Waiting for {}
type=type
diff --git a/bauh/view/resources/locale/it b/bauh/view/resources/locale/it
index f5ad626e..2e9e5d6c 100644
--- a/bauh/view/resources/locale/it
+++ b/bauh/view/resources/locale/it
@@ -394,6 +394,8 @@ status.caching_data=Memorizza {} dati sul disco
style=stile
success=success
summary=riepilogo
+task.checking_config=Checking configuration file
+task.checking_config.saving=Creating file
task.download_categories=Download delle categorie
task.waiting_task=Waiting for {}
type=tipe
diff --git a/bauh/view/resources/locale/pt b/bauh/view/resources/locale/pt
index 82b80356..58e7b48f 100644
--- a/bauh/view/resources/locale/pt
+++ b/bauh/view/resources/locale/pt
@@ -392,6 +392,8 @@ status.caching_data=Cacheando dados de {} para o disco
style=estilo
success=sucesso
summary=resumo
+task.checking_config=Verificando arquivo de configuração
+task.checking_config.saving=Criando arquivo
task.download_categories=Baixando categorias
task.waiting_task=Aguardando {}
type=tipo
diff --git a/bauh/view/resources/locale/ru b/bauh/view/resources/locale/ru
index 93c97421..3777c7ac 100644
--- a/bauh/view/resources/locale/ru
+++ b/bauh/view/resources/locale/ru
@@ -391,6 +391,8 @@ status.caching_data=Кэширование данных {} на диск
style=Стиль
success=success
summary=Суммарно
+task.checking_config=Checking configuration file
+task.checking_config.saving=Creating file
task.download_categories=Downloading categories
task.waiting_task=Waiting for {}
type=Тип
diff --git a/bauh/view/resources/locale/tr b/bauh/view/resources/locale/tr
index cf27b801..84db32dc 100644
--- a/bauh/view/resources/locale/tr
+++ b/bauh/view/resources/locale/tr
@@ -391,6 +391,8 @@ status.caching_data={} verilerini diske önbellekle
style=Görünüm biçimi
success=başarılı
summary=özet
+task.checking_config=Checking configuration file
+task.checking_config.saving=Creating file
task.download_categories=Kategoriler indiriliyor
task.waiting_task=Waiting for {}
type=tür
diff --git a/bauh/view/resources/style/darcula/darcula.qss b/bauh/view/resources/style/darcula/darcula.qss
index 84e96707..c662c20f 100644
--- a/bauh/view/resources/style/darcula/darcula.qss
+++ b/bauh/view/resources/style/darcula/darcula.qss
@@ -238,7 +238,7 @@ PreparePanel QTableWidget#tasks {
background-color: @inner_widget.background.color;
}
-PreparePanel QLabel#task_status[status = "done"], QLabel#task_progress[status = "done"] {
+PreparePanel QLabel#task_status[status = "done"], PreparePanel QLabel#task_progress[status = "done"], PreparePanel QLabel#task_substatus[status = "done"] {
color: @task.done.color;
}
diff --git a/bauh/view/resources/style/default/default.qss b/bauh/view/resources/style/default/default.qss
index 2ca2a7b6..e00e2cfd 100644
--- a/bauh/view/resources/style/default/default.qss
+++ b/bauh/view/resources/style/default/default.qss
@@ -219,7 +219,7 @@ PreparePanel QPushButton#bt_hide_details {
background: none;
}
-PreparePanel QLabel#task_status[status = "done"], QLabel#task_progress[status = "done"] {
+PreparePanel QLabel#task_status[status = "done"], PreparePanel QLabel#task_progress[status = "done"], PreparePanel QLabel#task_substatus[status = "done"] {
text-decoration: line-through;
}
diff --git a/bauh/view/resources/style/light/light.qss b/bauh/view/resources/style/light/light.qss
index d1e28538..b0db2bac 100644
--- a/bauh/view/resources/style/light/light.qss
+++ b/bauh/view/resources/style/light/light.qss
@@ -145,11 +145,11 @@ PreparePanel QTableWidget#tasks {
background-color: @task.background.color;
}
-PreparePanel QLabel#task_status[status = "running"], QLabel#task_progress[status = "running"] {
+PreparePanel QLabel#task_status[status = "running"], PreparePanel QLabel#task_progress[status = "running"] {
font-weight: 525;
}
-PreparePanel QLabel#task_status[status = "done"], QLabel#task_progress[status = "done"] {
+PreparePanel QLabel#task_status[status = "done"], PreparePanel QLabel#task_progress[status = "done"], PreparePanel QLabel#task_substatus[status = "done"] {
color: @task.done.color;
}
diff --git a/bauh/view/resources/style/sublime/sublime.qss b/bauh/view/resources/style/sublime/sublime.qss
index c67ab5f6..019bdb56 100644
--- a/bauh/view/resources/style/sublime/sublime.qss
+++ b/bauh/view/resources/style/sublime/sublime.qss
@@ -195,7 +195,7 @@ PreparePanel QLabel#task_status[status = "running"], QLabel#task_progress[status
color: @task.running.color;
}
-PreparePanel QLabel#task_status[status = "done"], QLabel#task_progress[status = "done"] {
+PreparePanel QLabel#task_status[status = "done"], PreparePanel QLabel#task_progress[status = "done"], PreparePanel QLabel#task_substatus[status = "done"]{
color: @task.done.color;
}