diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4595c307..70db145f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- old settings properties were dropped (**db_updater.interval**, **db_updated.enabled**)
- database files (**apps.db** and **releases.db**) are now stored at **~/.cache/bauh/appimage**
- displaying a warning when the cached database files could not be found
+ - new custom action **Update database** to perform a database update anytime:
+
+
+
- Arch
- AUR
diff --git a/bauh/api/abstract/model.py b/bauh/api/abstract/model.py
index 3cb78981..8c6dad1a 100644
--- a/bauh/api/abstract/model.py
+++ b/bauh/api/abstract/model.py
@@ -10,7 +10,8 @@ class CustomSoftwareAction:
def __init__(self, i18n_label_key: str, i18n_status_key: str, icon_path: str, manager_method: str,
requires_root: bool, manager: "SoftwareManager" = None,
backup: bool = False, refresh: bool = True,
- i18n_confirm_key: str = None):
+ i18n_confirm_key: str = None,
+ requires_internet: bool = False):
"""
:param i18n_label_key: the i18n key that will be used to display the action name
:param i18n_status_key: the i18n key that will be used to display the action name being executed
@@ -21,6 +22,7 @@ class CustomSoftwareAction:
:param requires_root:
:param refresh: if the a full app refresh should be done if the action succeeds
:param i18n_confirm_key: action confirmation message
+ :param requires_internet: if the action requires internet connection to be executed
"""
self.i18n_label_key = i18n_label_key
self.i18n_status_key = i18n_status_key
@@ -31,6 +33,7 @@ class CustomSoftwareAction:
self.backup = backup
self.refresh = refresh
self.i18n_confirm_key = i18n_confirm_key
+ self.requires_internet = requires_internet
def __hash__(self):
return self.i18n_label_key.__hash__() + self.i18n_status_key.__hash__() + self.manager_method.__hash__()
diff --git a/bauh/gems/appimage/controller.py b/bauh/gems/appimage/controller.py
index bbe4241b..e42b6ffe 100644
--- a/bauh/gems/appimage/controller.py
+++ b/bauh/gems/appimage/controller.py
@@ -81,7 +81,14 @@ class AppImageManager(SoftwareManager):
manager=self,
manager_method='install_file',
icon_path=resource.get_path('img/appimage.svg', ROOT_DIR),
- requires_root=False)]
+ requires_root=False),
+ CustomSoftwareAction(i18n_label_key='appimage.custom_action.update_db',
+ i18n_status_key='appimage.custom_action.update_db.status',
+ manager=self,
+ manager_method='update_database',
+ icon_path=resource.get_path('img/appimage.svg', ROOT_DIR),
+ requires_root=False,
+ requires_internet=True)]
self.custom_app_actions = [CustomSoftwareAction(i18n_label_key='appimage.custom_action.manual_update',
i18n_status_key='appimage.custom_action.manual_update.status',
manager_method='update_file',
@@ -613,7 +620,7 @@ class AppImageManager(SoftwareManager):
symlink_check.start()
if internet_available:
- updater = DatabaseUpdater(task_man=task_manager, i18n=self.context.i18n,
+ 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()):
@@ -812,3 +819,10 @@ class AppImageManager(SoftwareManager):
self._write_ignored_updates(current_ignored)
pkg.updates_ignored = False
+
+ 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)
+
+ res = db_updater.download_databases()
+ return res
diff --git a/bauh/gems/appimage/resources/locale/ca b/bauh/gems/appimage/resources/locale/ca
index 37147d06..9f3be860 100644
--- a/bauh/gems/appimage/resources/locale/ca
+++ b/bauh/gems/appimage/resources/locale/ca
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Installing AppImage file
appimage.custom_action.manual_update=Upgrade file
appimage.custom_action.manual_update.details=Upgrade details
appimage.custom_action.manual_update.status=Upgrading
+appimage.custom_action.update_db=Update database
+appimage.custom_action.update_db.status=Updating database
appimage.downgrade.first_version={} és a la seva primera versió publicada
appimage.downgrade.impossible.body={} té només una versió publicada.
appimage.downgrade.impossible.title=No s’ha pogut revertir la versió
@@ -30,6 +32,9 @@ appimage.install.download.error=No s’ha pogut baixar el fitxer {}. El servidor
appimage.install.extract=S’està extraient el contingut de {}
appimage.install.imported.rename_error=It was not possible to move the file {} to {}
appimage.install.permission=S’està concedint el permís d’execució a {}
+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.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=No s’ha pogut suprimir el directori d’instal·lació de l’aplicació {}
diff --git a/bauh/gems/appimage/resources/locale/de b/bauh/gems/appimage/resources/locale/de
index fc365c97..c924f481 100644
--- a/bauh/gems/appimage/resources/locale/de
+++ b/bauh/gems/appimage/resources/locale/de
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Installing AppImage file
appimage.custom_action.manual_update=Upgrade file
appimage.custom_action.manual_update.details=Upgrade details
appimage.custom_action.manual_update.status=Upgrading
+appimage.custom_action.update_db=Update database
+appimage.custom_action.update_db.status=Updating database
appimage.downgrade.first_version={} ist in der ersten veröffentlichten Version
appimage.downgrade.impossible.body={} hat nur eine veröffentliche Version
appimage.downgrade.impossible.title=Downgrade nicht möglich
@@ -30,6 +32,9 @@ appimage.install.download.error=Das Herunterladen der Datei {} ist fehlgeschlage
appimage.install.extract=Entpacke Inhalt von {}
appimage.install.imported.rename_error=It was not possible to move the file {} to {}
appimage.install.permission=Ausführberechtigungen für {}
+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.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Anwendungordner {} konnte nicht entfernt werden
diff --git a/bauh/gems/appimage/resources/locale/en b/bauh/gems/appimage/resources/locale/en
index 142f777a..e66cd0b1 100644
--- a/bauh/gems/appimage/resources/locale/en
+++ b/bauh/gems/appimage/resources/locale/en
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Installing AppImage file
appimage.custom_action.manual_update=Upgrade file
appimage.custom_action.manual_update.details=Upgrade details
appimage.custom_action.manual_update.status=Upgrading
+appimage.custom_action.update_db=Update database
+appimage.custom_action.update_db.status=Updating database
appimage.downgrade.first_version={} is in its first published version
appimage.downgrade.impossible.body={} has only one published version.
appimage.downgrade.impossible.title=Impossible to downgrade
@@ -30,6 +32,9 @@ appimage.install.download.error=It was not possible to download the file {}. The
appimage.install.extract=Extracting the content from {}
appimage.install.imported.rename_error=It was not possible to move the file {} to {}
appimage.install.permission=Giving execution permission to {}
+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.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Could not remove the application installation directory {}
diff --git a/bauh/gems/appimage/resources/locale/es b/bauh/gems/appimage/resources/locale/es
index a7b88024..b1b97600 100644
--- a/bauh/gems/appimage/resources/locale/es
+++ b/bauh/gems/appimage/resources/locale/es
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Instalando archivo AppImage
appimage.custom_action.manual_update=Actualizar archivo
appimage.custom_action.manual_update.details=Detalles de actualización
appimage.custom_action.manual_update.status=Actualizando
+appimage.custom_action.update_db=Actualizar base de datos
+appimage.custom_action.update_db.status=Actualizando base de datos
appimage.downgrade.first_version={} está en su primera versión publicada
appimage.downgrade.impossible.body={} solo tiene una versión publicada.
appimage.downgrade.impossible.title=Imposible revertir la versión
@@ -30,6 +32,9 @@ appimage.install.download.error=No fue posible descargar el archivo {}. El servi
appimage.install.extract=Extrayendo el contenido de {}
appimage.install.imported.rename_error=No fue posible mover el archivo {} a {}
appimage.install.permission=Concediendo permiso de ejecución a {}
+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.symlink_check=Verificando links simbólicos
appimage.uninstall.error.remove_folder=No se pudo eliminar el directorio de instalación de la aplicación {}
diff --git a/bauh/gems/appimage/resources/locale/fr b/bauh/gems/appimage/resources/locale/fr
index 484322d9..0efe8d4a 100644
--- a/bauh/gems/appimage/resources/locale/fr
+++ b/bauh/gems/appimage/resources/locale/fr
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Installation du fichier AppImage
appimage.custom_action.manual_update=Mettre fichier à jour
appimage.custom_action.manual_update.details=Détails de mise à jour
appimage.custom_action.manual_update.status=Mise à jour
+appimage.custom_action.update_db=Update database
+appimage.custom_action.update_db.status=Updating database
appimage.downgrade.first_version={} est à sa première version publiée
appimage.downgrade.impossible.body={} a une seule version publiée.
appimage.downgrade.impossible.title=Impossible à downgrader
@@ -30,6 +32,9 @@ appimage.install.download.error=Échec du téléchargement du fichier {}. Le ser
appimage.install.extract=Extractiion du contenu de {}
appimage.install.imported.rename_error=Impossible de déplacer {} vers {}
appimage.install.permission={} est maintenant exécutable
+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.symlink_check=Verification des symlinks
appimage.uninstall.error.remove_folder=Impossible de supprimer le répertoire d'installation {}
diff --git a/bauh/gems/appimage/resources/locale/it b/bauh/gems/appimage/resources/locale/it
index 76bf6a6c..63f34052 100644
--- a/bauh/gems/appimage/resources/locale/it
+++ b/bauh/gems/appimage/resources/locale/it
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Installing AppImage file
appimage.custom_action.manual_update=Upgrade file
appimage.custom_action.manual_update.details=Upgrade details
appimage.custom_action.manual_update.status=Upgrading
+appimage.custom_action.update_db=Update database
+appimage.custom_action.update_db.status=Updating database
appimage.downgrade.first_version={} è nella sua prima versione pubblicata
appimage.downgrade.impossible.body={} ha solo una versione pubblicata.
appimage.downgrade.impossible.title=Impossibile eseguire il downgrade
@@ -30,6 +32,9 @@ appimage.install.download.error=Non è stato possibile scaricare il file {}. Il
appimage.install.extract=Estrarre il contenuto da {}
appimage.install.imported.rename_error=It was not possible to move the file {} to {}
appimage.install.permission=Gdare il permesso di esecuzione a {}
+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.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Impossibile rimuovere la directory di installazione dell'applicazione {}
diff --git a/bauh/gems/appimage/resources/locale/pt b/bauh/gems/appimage/resources/locale/pt
index 27dfbe43..6cc1060c 100644
--- a/bauh/gems/appimage/resources/locale/pt
+++ b/bauh/gems/appimage/resources/locale/pt
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Instalando arquivo AppImage
appimage.custom_action.manual_update=Atualizar arquivo
appimage.custom_action.manual_update.details=Detalhes de atualização
appimage.custom_action.manual_update.status=Atualizando
+appimage.custom_action.update_db=Atualizar banco de dados
+appimage.custom_action.update_db.status=Atualizando banco de dados
appimage.downgrade.first_version={} se encontra em sua primeira versão publicada
appimage.downgrade.impossible.body={} tem somente uma versão publicada.
appimage.downgrade.impossible.title=Impossível reverter a versão
@@ -30,6 +32,9 @@ appimage.install.download.error=Não foi possível baixar o arquivo {}. O servid
appimage.install.extract=Extraindo o conteúdo de {}
appimage.install.imported.rename_error=Não foi possível mover o arquivo {} para {}
appimage.install.permission=Concedendo permissão de execução para {}
+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.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 {}
diff --git a/bauh/gems/appimage/resources/locale/ru b/bauh/gems/appimage/resources/locale/ru
index 2a072713..06c462d8 100644
--- a/bauh/gems/appimage/resources/locale/ru
+++ b/bauh/gems/appimage/resources/locale/ru
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=Установка файла AppImag
appimage.custom_action.manual_update=Обновить файл
appimage.custom_action.manual_update.details=Детали обновления
appimage.custom_action.manual_update.status=Обновляется...
+appimage.custom_action.update_db=Update database
+appimage.custom_action.update_db.status=Updating database
appimage.downgrade.first_version={} первая опубликованная версия
appimage.downgrade.impossible.body={} Имеет только одну опубликованную версию
appimage.downgrade.impossible.title=Не удалось понизить версию
@@ -30,6 +32,9 @@ appimage.install.download.error=Не удалось загрузить файл
appimage.install.extract=Извлечь содержимое из {}
appimage.install.imported.rename_error=Не удалось переместить файл {} в {}
appimage.install.permission=Установить права на выполнение для {}
+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.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder=Не удалось удалить каталог приложения {}
diff --git a/bauh/gems/appimage/resources/locale/tr b/bauh/gems/appimage/resources/locale/tr
index 232ff11e..8f6c03e0 100644
--- a/bauh/gems/appimage/resources/locale/tr
+++ b/bauh/gems/appimage/resources/locale/tr
@@ -9,6 +9,8 @@ appimage.custom_action.install_file.status=AppImage dosyası yükleniyor
appimage.custom_action.manual_update=Yükseltme dosyası
appimage.custom_action.manual_update.details=Yükseltme ayrıntıları
appimage.custom_action.manual_update.status=Yükseltiliyor
+appimage.custom_action.update_db=Update database
+appimage.custom_action.update_db.status=Updating database
appimage.downgrade.first_version={} ilk yayınlanmış versiyonunda
appimage.downgrade.impossible.body={} yalnızca bir yayınlanmış sürümüne sahip.
appimage.downgrade.impossible.title=Sürüm düşürmek imkansız
@@ -30,6 +32,9 @@ appimage.install.download.error={} dosyası indirilemedi. Dosya sunucusu kapalı
appimage.install.extract={} 'den içerik ayıklanıyor
appimage.install.imported.rename_error={} dosyasını {} klasörüne taşımak mümkün değildi
appimage.install.permission={} için yürütme izni veriliyor
+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.symlink_check=Checking symlinks
appimage.uninstall.error.remove_folder={} uygulama kurulum dizini kaldırılamadı
diff --git a/bauh/gems/appimage/worker.py b/bauh/gems/appimage/worker.py
index 678942c7..0c209d0d 100644
--- a/bauh/gems/appimage/worker.py
+++ b/bauh/gems/appimage/worker.py
@@ -21,12 +21,13 @@ from bauh.view.util.translation import I18n
class DatabaseUpdater(Thread):
COMPRESS_FILE_PATH = '{}/db.tar.gz'.format(DATABASES_DIR)
- def __init__(self, task_man: TaskManager, i18n: I18n, http_client: HttpClient, logger: logging.Logger):
+ def __init__(self, i18n: I18n, http_client: HttpClient, logger: logging.Logger, watcher: Optional[ProcessWatcher] = None, taskman: Optional[TaskManager] = None):
super(DatabaseUpdater, self).__init__(daemon=True)
self.http_client = http_client
self.logger = logger
self.i18n = i18n
- self.task_man = task_man
+ self.taskman = taskman
+ self.watcher = watcher
self.task_id = 'appim_db'
def should_update(self, appimage_config: dict) -> bool:
@@ -75,22 +76,25 @@ class DatabaseUpdater(Thread):
return update
def register_task(self):
- if self.task_man:
- self.task_man.register_task(self.task_id, self.i18n['appimage.task.db_update'], get_icon_path())
+ 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.task_man:
- self.task_man.update_progress(self.task_id, 100, None)
- self.task_man.finish_task(self.task_id)
- self.task_man = None
+ 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.task_man:
- self.task_man.update_progress(self.task_id, progress, substatus)
+ if self.taskman:
+ self.taskman.update_progress(self.task_id, progress, substatus)
- def download_databases(self):
- self._update_task_progress(1) # TODO add 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.logger.info('Retrieving AppImage databases')
database_timestamp = datetime.utcnow().timestamp()
@@ -103,9 +107,8 @@ class DatabaseUpdater(Thread):
if not res:
self.logger.warning('Could not download the database file {}'.format(URL_COMPRESSED_DATABASES))
self._finish_task()
- return
+ return False
- self._update_task_progress(25) # TODO add substatus
Path(DATABASES_DIR).mkdir(parents=True, exist_ok=True)
with open(self.COMPRESS_FILE_PATH, 'wb+') as f:
@@ -113,7 +116,7 @@ class DatabaseUpdater(Thread):
self.logger.info("Database file saved at {}".format(self.COMPRESS_FILE_PATH))
- self._update_task_progress(50) # TODO add substatus
+ self._update_task_progress(50, self.i18n['appimage.update_database.deleting_old'])
old_db_files = glob.glob(DATABASES_DIR + '/*.db')
if old_db_files:
@@ -123,7 +126,7 @@ class DatabaseUpdater(Thread):
self.logger.info('Old database files deleted')
- self._update_task_progress(75) # TODO add substatus
+ self._update_task_progress(75, self.i18n['appimage.update_database.uncompressing'])
self.logger.info('Uncompressing {}'.format(self.COMPRESS_FILE_PATH))
try:
@@ -133,6 +136,7 @@ class DatabaseUpdater(Thread):
except:
self.logger.error('Could not extract file {}'.format(self.COMPRESS_FILE_PATH))
traceback.print_exc()
+ return False
finally:
self.logger.info('Deleting {}'.format(self.COMPRESS_FILE_PATH))
os.remove(self.COMPRESS_FILE_PATH)
@@ -147,6 +151,7 @@ class DatabaseUpdater(Thread):
self.logger.info("Database timestamp saved")
self._finish_task()
+ return True
def run(self):
self.download_databases()
diff --git a/bauh/view/core/controller.py b/bauh/view/core/controller.py
index 0fca3f37..b6cd284b 100755
--- a/bauh/view/core/controller.py
+++ b/bauh/view/core/controller.py
@@ -485,6 +485,9 @@ class GenericSoftwareManager(SoftwareManager):
return []
def execute_custom_action(self, action: CustomSoftwareAction, pkg: SoftwarePackage, root_password: str, watcher: ProcessWatcher):
+ if action.requires_internet and not self.context.is_internet_available():
+ raise NoInternetException()
+
man = action.manager if action.manager else self._get_manager_for(pkg)
if man:
diff --git a/bauh/view/qt/thread.py b/bauh/view/qt/thread.py
index 444f8106..b2c75af5 100644
--- a/bauh/view/qt/thread.py
+++ b/bauh/view/qt/thread.py
@@ -1004,6 +1004,8 @@ class CustomAction(AsyncAction):
self.i18n = i18n
def run(self):
+ 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(),
action_key=None,
@@ -1011,22 +1013,24 @@ class CustomAction(AsyncAction):
root_password=self.root_pwd,
pkg=self.pkg)
if not proceed:
- self.notify_finished({'success': False, 'pkg': self.pkg, 'action': self.custom_action})
+ self.notify_finished(res)
self.pkg = None
self.custom_action = None
self.root_pwd = None
return
try:
- success = self.manager.execute_custom_action(action=self.custom_action,
- pkg=self.pkg.model if self.pkg else None,
- root_password=self.root_pwd,
- watcher=self)
+ res['success'] = self.manager.execute_custom_action(action=self.custom_action,
+ pkg=self.pkg.model if self.pkg else None,
+ root_password=self.root_pwd,
+ watcher=self)
except (requests.exceptions.ConnectionError, NoInternetException):
- success = False
+ res['success'] = False
+ res['error'] = 'internet.required'
+ res['error_type'] = MessageType.WARNING
self.signal_output.emit(self.i18n['internet.required'])
- self.notify_finished({'success': success, 'pkg': self.pkg, 'action': self.custom_action})
+ self.notify_finished(res)
self.pkg = None
self.custom_action = None
self.root_pwd = None
diff --git a/bauh/view/qt/window.py b/bauh/view/qt/window.py
index dfda10ec..6bd7bdc1 100755
--- a/bauh/view/qt/window.py
+++ b/bauh/view/qt/window.py
@@ -1433,6 +1433,11 @@ class ManageWindow(QWidget):
self.comp_manager.restore_state(ACTION_CUSTOM_ACTION)
self._show_console_errors()
+ if res['error']:
+ dialog.show_message(title=self.i18n['warning' if res['error_type'] == MessageType.WARNING else 'error'].capitalize(),
+ body=self.i18n[res['error']],
+ type_=res['error_type'])
+
def _show_console_checkbox_if_output(self):
if self.textarea_details.toPlainText():
self.comp_manager.set_component_visible(CHECK_DETAILS, True)