mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 01:14:15 +02:00
[arch][snap] improvement -> caching categories file for 24 hours
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -38,12 +38,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- the index is now stored at **~/.cache/bauh/arch/aur/index.txt**.
|
||||
- info window
|
||||
- date fields format changed to numbers (e.g: Thu Dec 17 17:19:55 2020 -> 2020-12-17 17:19:55)
|
||||
- new settings property "categories_exp": it defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Default: 24 hours.
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/releases/0.9.11/cats_exp.png">
|
||||
</p>
|
||||
- Core
|
||||
- new settings property **boot.load_apps** (General -> Load apps after startup) that allows the user to choose if the installed packages/suggestions should be loaded on the management panel after the initialization process. Default: true.
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/releases/0.9.11/load_apps.png">
|
||||
</p>
|
||||
|
||||
- Snap
|
||||
- new settings property "categories_exp": it defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Default: 24 hours.
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/releases/0.9.11/cats_exp.png">
|
||||
</p>
|
||||
|
||||
- Web
|
||||
- now the environment settings are cached for 24 hours. This period can be controlled through the new settings property **environment.update_interval** (in minutes -> default: 1440 = 24 hours. Use **0** so that they are always updated).
|
||||
<p align="center">
|
||||
|
||||
@@ -128,6 +128,7 @@ installation_level: null # defines a default installation level: user or system.
|
||||
- The configuration file is located at **~/.config/bauh/snap.yml** and it allows the following customizations:
|
||||
```
|
||||
install_channel: false # it allows to select an available channel during the application installation. Default: false
|
||||
categories_exp: 24 # It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
```
|
||||
- Required dependencies:
|
||||
- Any distro: **snapd** ( it must be enabled after its installation. Details at https://snapcraft.io/docs/installing-snapd )
|
||||
@@ -209,6 +210,7 @@ aur_idx_exp: 720 # It defines the period (in minutes) for the AUR index stored
|
||||
check_dependency_breakage: true # if, during the verification of the update requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B. If A and B were selected to upgrade, and B would be upgrade to 2.0, then B would be excluded from the transaction. Default: true.
|
||||
suggest_unneeded_uninstall: false # if the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property 'suggest_optdep_uninstall'. Default: false (to prevent new users from making mistakes)
|
||||
suggest_optdep_uninstall: false # if the optional dependencies associated with uninstalled packages should be suggested for uninstallation. Only the optional dependencies that are not dependencies of other packages will be suggested. Default: false (to prevent new users from making mistakes)
|
||||
categories_exp: 24 # It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
```
|
||||
- Required dependencies:
|
||||
- **pacman**
|
||||
|
||||
@@ -1,44 +1,64 @@
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import traceback
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from threading import Thread
|
||||
from typing import Dict, List
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import requests
|
||||
|
||||
from bauh.api.abstract.controller import SoftwareManager
|
||||
from bauh.api.http import HttpClient
|
||||
from bauh.commons.internet import InternetChecker
|
||||
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, disk_cache_dir: str, categories_path: str, before=None, after=None):
|
||||
url_categories_file: str, categories_path: str, expiration: int, internet_checker: InternetChecker,
|
||||
internet_connection: Optional[bool] = True, before=None, after=None):
|
||||
"""
|
||||
:param id_:
|
||||
:param http_client:
|
||||
:param logger:
|
||||
:param manager:
|
||||
:param url_categories_file:
|
||||
:param categories_path:
|
||||
:param expiration: cached file expiration in hours
|
||||
:param internet_checker
|
||||
:param before:
|
||||
:param after:
|
||||
"""
|
||||
super(CategoriesDownloader, self).__init__(daemon=True)
|
||||
self.id_ = id_
|
||||
self.http_client = http_client
|
||||
self.logger = logger
|
||||
self.manager = manager
|
||||
self.url_categories_file = url_categories_file
|
||||
self.disk_cache_dir = disk_cache_dir
|
||||
self.categories_path = categories_path
|
||||
self.before = before
|
||||
self.after = after
|
||||
self.expiration = expiration
|
||||
self.internet_connection = internet_connection
|
||||
self.internet_checker = internet_checker
|
||||
|
||||
def _msg(self, msg: str):
|
||||
return '{}({}): {}'.format(self.__class__.__name__, self.id_, msg)
|
||||
return '{} [{}]: {}'.format(self.__class__.__name__, self.id_, msg)
|
||||
|
||||
def _read_categories_from_disk(self) -> Dict[str, List[str]]:
|
||||
if os.path.exists(self.categories_path):
|
||||
self.logger.info(self._msg("Reading cached categories from the disk"))
|
||||
self.logger.info(self._msg("Reading cached categories file {}".format(self.categories_path)))
|
||||
|
||||
with open(self.categories_path) as f:
|
||||
categories = f.read()
|
||||
|
||||
return self._map_categories(categories)
|
||||
|
||||
return {}
|
||||
else:
|
||||
self.logger.warning("No cached categories file {} found".format(self.categories_path))
|
||||
return {}
|
||||
|
||||
def _map_categories(self, categories: str) -> Dict[str, List[str]]:
|
||||
categories_map = {}
|
||||
@@ -49,16 +69,22 @@ class CategoriesDownloader(Thread):
|
||||
|
||||
return categories_map
|
||||
|
||||
def _cache_categories_to_disk(self, categories: str):
|
||||
self.logger.info(self._msg('Caching categories to the disk'))
|
||||
def _cache_categories_to_disk(self, categories_str: str, timestamp: float):
|
||||
self.logger.info(self._msg('Caching downloaded categories to disk'))
|
||||
|
||||
try:
|
||||
Path(self.disk_cache_dir).mkdir(parents=True, exist_ok=True)
|
||||
Path(os.path.dirname(self.categories_path)).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(self.categories_path, 'w+') as f:
|
||||
f.write(categories)
|
||||
f.write(categories_str)
|
||||
|
||||
self.logger.info(self._msg("Categories cached to the disk as '{}'".format(self.categories_path)))
|
||||
self.logger.info(self._msg("Categories cached to file '{}'".format(self.categories_path)))
|
||||
|
||||
categories_ts_path = map_timestamp_file(self.categories_path)
|
||||
with open(categories_ts_path, 'w+') as f:
|
||||
f.write(str(timestamp))
|
||||
|
||||
self.logger.info(self._msg("Categories timestamp ({}) cached to file '{}'".format(timestamp, categories_ts_path)))
|
||||
except:
|
||||
self.logger.error(self._msg("Could not cache categories to the disk as '{}'".format(self.categories_path)))
|
||||
traceback.print_exc()
|
||||
@@ -67,49 +93,82 @@ class CategoriesDownloader(Thread):
|
||||
self.logger.info(self._msg('Downloading category definitions from {}'.format(self.url_categories_file)))
|
||||
|
||||
try:
|
||||
timestamp = datetime.utcnow().timestamp()
|
||||
res = self.http_client.get(self.url_categories_file)
|
||||
|
||||
if res:
|
||||
try:
|
||||
categories = self._map_categories(res.text)
|
||||
self.logger.info(self._msg('Loaded categories for {} applications'.format(len(categories))))
|
||||
|
||||
if categories:
|
||||
Thread(target=self._cache_categories_to_disk, args=(res.text,), daemon=True).start()
|
||||
|
||||
return categories
|
||||
except:
|
||||
self.logger.error(self._msg("Could not parse categories definitions"))
|
||||
traceback.print_exc()
|
||||
else:
|
||||
self.logger.info(self._msg('Could not download {}'.format(self.url_categories_file)))
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
self.logger.warning(self._msg('The internet connection seems to be off.'))
|
||||
self.logger.error(self._msg('[{}] Could not download categories. The internet connection seems to be off.'.format(self.id_)))
|
||||
return {}
|
||||
|
||||
return {}
|
||||
if not res:
|
||||
self.logger.info(self._msg('Could not download {}'.format(self.url_categories_file)))
|
||||
return {}
|
||||
|
||||
try:
|
||||
categories = self._map_categories(res.text)
|
||||
self.logger.info(self._msg('Loaded categories for {} applications'.format(len(categories))))
|
||||
except:
|
||||
self.logger.error(self._msg("Could not parse categories definitions"))
|
||||
traceback.print_exc()
|
||||
return {}
|
||||
|
||||
def _set_categories(self, categories: dict):
|
||||
if categories:
|
||||
self.logger.info(self._msg("Settings {} categories to {}".format(len(categories), self.manager.__class__.__name__)))
|
||||
self.manager.categories = categories
|
||||
self._cache_categories_to_disk(categories_str=res.text, timestamp=timestamp)
|
||||
|
||||
def _download_and_set(self):
|
||||
self._set_categories(self.download_categories())
|
||||
return categories
|
||||
|
||||
def should_download(self) -> bool:
|
||||
if self.internet_connection is False or (self.internet_connection is None and not self.internet_checker.is_available()):
|
||||
self.logger.warning(self._msg("No internet connection. The categories file '{}' cannot be updated.".format(self.categories_path)))
|
||||
return False
|
||||
|
||||
if 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
|
||||
|
||||
if not os.path.exists(self.categories_path):
|
||||
self.logger.warning(self._msg("Categories file '{}' does not exist. It should be downloaded.".format(self.categories_path)))
|
||||
return True
|
||||
|
||||
categories_ts_path = map_timestamp_file(self.categories_path)
|
||||
|
||||
if not os.path.exists(categories_ts_path):
|
||||
self.logger.warning(self._msg("Categories timestamp file '{}' does not exist. The categories file should be re-downloaded.".format(categories_ts_path)))
|
||||
return True
|
||||
|
||||
with open(categories_ts_path) as f:
|
||||
timestamp_str = f.read()
|
||||
|
||||
try:
|
||||
categories_timestamp = datetime.fromtimestamp(float(timestamp_str))
|
||||
except:
|
||||
self.logger.error(self._msg("An exception occurred when trying to parse the categories file timestamp from '{}'. The categories file should be re-downloaded.".format(categories_ts_path)))
|
||||
traceback.print_exc()
|
||||
return True
|
||||
|
||||
should_download = (categories_timestamp + timedelta(hours=self.expiration) <= datetime.utcnow())
|
||||
|
||||
if should_download:
|
||||
self.logger.info(self._msg("Cached categories file '{}' has expired. A new one should be downloaded.".format(self.categories_path)))
|
||||
return True
|
||||
else:
|
||||
self.logger.info(self._msg("Cached categories file '{}' is up to date. No need to re-download it.".format(self.categories_path)))
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
ti = time.time()
|
||||
if self.before:
|
||||
self.before()
|
||||
|
||||
cached = self._read_categories_from_disk()
|
||||
should_download = self.should_download()
|
||||
|
||||
if cached:
|
||||
self._set_categories(cached)
|
||||
Thread(target=self._download_and_set, daemon=True).start()
|
||||
if not should_download:
|
||||
cached = self._read_categories_from_disk()
|
||||
self.manager.categories = cached
|
||||
else:
|
||||
self._download_and_set()
|
||||
self.download_categories()
|
||||
|
||||
if self.after:
|
||||
self.after()
|
||||
|
||||
self.logger.info(self._msg('Finished'))
|
||||
tf = time.time()
|
||||
self.logger.info(self._msg('Finished. Took {0:.2f} seconds'.format(tf - ti)))
|
||||
|
||||
@@ -30,3 +30,8 @@ def size_to_byte(size: float, unit: str) -> int:
|
||||
|
||||
def datetime_as_milis(date: datetime = datetime.utcnow()) -> int:
|
||||
return int(round(date.timestamp() * 1000))
|
||||
|
||||
|
||||
def map_timestamp_file(file_path: str) -> str:
|
||||
path_split = file_path.split('/')
|
||||
return '/'.join(path_split[0:-1]) + '/' + path_split[-1].split('.')[0] + '.ts'
|
||||
|
||||
@@ -22,7 +22,8 @@ def read_config(update_file: bool = False) -> dict:
|
||||
'check_dependency_breakage': True,
|
||||
'suggest_unneeded_uninstall': False,
|
||||
'suggest_optdep_uninstall': False,
|
||||
'aur_idx_exp': 720}
|
||||
'aur_idx_exp': 720,
|
||||
'categories_exp': 24}
|
||||
return read(CONFIG_FILE, template, update_file=update_file)
|
||||
|
||||
|
||||
|
||||
@@ -2623,7 +2623,7 @@ class ArchManager(SoftwareManager):
|
||||
return action != SoftwareAction.SEARCH
|
||||
|
||||
def _start_category_task(self, task_man: TaskManager):
|
||||
task_man.register_task('arch_aur_cats', self.i18n['task.download_categories'].format('Arch'), get_icon_path())
|
||||
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 _finish_category_task(self, task_man: TaskManager):
|
||||
@@ -2654,8 +2654,11 @@ class ArchManager(SoftwareManager):
|
||||
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, disk_cache_dir=ARCH_CACHE_PATH,
|
||||
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()
|
||||
|
||||
@@ -2878,7 +2881,14 @@ class ArchManager(SoftwareManager):
|
||||
max_width=max_width,
|
||||
file_path=local_config['aur_build_dir'],
|
||||
capitalize_label=False,
|
||||
directory=True)
|
||||
directory=True),
|
||||
TextInputComponent(id_='arch_cats_exp',
|
||||
label=self.i18n['arch.config.categories_exp'],
|
||||
tooltip=self.i18n['arch.config.categories_exp.tip'],
|
||||
max_width=max_width,
|
||||
only_int=True,
|
||||
capitalize_label=False,
|
||||
value=local_config['categories_exp'] if isinstance(local_config['categories_exp'], int) else ''),
|
||||
]
|
||||
|
||||
return PanelComponent([FormComponent(fields, spaces=False)])
|
||||
@@ -2886,25 +2896,26 @@ class ArchManager(SoftwareManager):
|
||||
def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
|
||||
config = read_config()
|
||||
|
||||
form_install = component.components[0]
|
||||
config['repositories'] = form_install.get_component('repos').get_selected()
|
||||
config['aur'] = form_install.get_component('aur').get_selected()
|
||||
config['optimize'] = form_install.get_component('opts').get_selected()
|
||||
config['sync_databases'] = form_install.get_component('sync_dbs').get_selected()
|
||||
config['sync_databases_startup'] = form_install.get_component('sync_dbs_start').get_selected()
|
||||
config['clean_cached'] = form_install.get_component('clean_cached').get_selected()
|
||||
config['refresh_mirrors_startup'] = form_install.get_component('ref_mirs').get_selected()
|
||||
config['mirrors_sort_limit'] = form_install.get_component('mirrors_sort_limit').get_int_value()
|
||||
config['repositories_mthread_download'] = form_install.get_component('mthread_download').get_selected()
|
||||
config['automatch_providers'] = form_install.get_component('autoprovs').get_selected()
|
||||
config['edit_aur_pkgbuild'] = form_install.get_component('edit_aur_pkgbuild').get_selected()
|
||||
config['aur_remove_build_dir'] = form_install.get_component('aur_remove_build_dir').get_selected()
|
||||
config['aur_build_dir'] = form_install.get_component('aur_build_dir').file_path
|
||||
config['aur_build_only_chosen'] = form_install.get_component('aur_build_only_chosen').get_selected()
|
||||
config['aur_idx_exp'] = form_install.get_component('aur_idx_exp').get_int_value()
|
||||
config['check_dependency_breakage'] = form_install.get_component('check_dependency_breakage').get_selected()
|
||||
config['suggest_optdep_uninstall'] = form_install.get_component('suggest_optdep_uninstall').get_selected()
|
||||
config['suggest_unneeded_uninstall'] = form_install.get_component('suggest_unneeded_uninstall').get_selected()
|
||||
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()
|
||||
|
||||
if not config['aur_build_dir']:
|
||||
config['aur_build_dir'] = None
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Build only chosen (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Some AUR packages have a common PKGBUILD shared with other packages and that defines build instructions for each one. This property enabled will ensure that only the chosen package will be built.
|
||||
arch.config.aur_remove_build_dir=Remove build directory (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
|
||||
arch.config.categories_exp=Categories expiration
|
||||
arch.config.categories_exp.tip=It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
arch.config.clean_cache=Elimina les versions antigues
|
||||
arch.config.clean_cache.tip=Si cal eliminar les versions antigues d'un paquet emmagatzemat al disc durant la desinstal·lació
|
||||
arch.config.check_dependency_breakage=Check dependency version breakage
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Build only chosen (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Some AUR packages have a common PKGBUILD shared with other packages and that defines build instructions for each one. This property enabled will ensure that only the chosen package will be built.
|
||||
arch.config.aur_remove_build_dir=Remove build directory (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
|
||||
arch.config.categories_exp=Categories expiration
|
||||
arch.config.categories_exp.tip=It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
arch.config.clean_cache=Remove old versions
|
||||
arch.config.clean_cache.tip=Whether old versions of a package stored on disk should be removed during uninstall
|
||||
arch.config.check_dependency_breakage=Check dependency version breakage
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Build only chosen (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Some AUR packages have a common PKGBUILD shared with other packages and that defines build instructions for each one. This property enabled will ensure that only the chosen package will be built.
|
||||
arch.config.aur_remove_build_dir=Remove build directory (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
|
||||
arch.config.categories_exp=Categories expiration
|
||||
arch.config.categories_exp.tip=It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
arch.config.clean_cache=Remove old versions
|
||||
arch.config.clean_cache.tip=Whether old versions of a package stored on disk should be removed during uninstall
|
||||
arch.config.check_dependency_breakage=Check dependency version breakage
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Compilar solo elegido (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Algunos paquetes AUR tienen un PKGBUILD común compartido con otros paquetes y que define las instrucciones de construcción para cada uno. Esta propiedad habilitada garantizará que solo se compile el paquete elegido.
|
||||
arch.config.aur_remove_build_dir=Eliminar directorio de compilación (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=Si el directorio de compilación generado para un paquete debe ser eliminado una vez finalizada la operación.
|
||||
arch.config.categories_exp=Expiración de categorías
|
||||
arch.config.categories_exp.tip=Define el tiempo de vencimiento (en HORAS) del archivo de mapeo de categorías de paquetes almacenado en el disco. Utilice 0 para que siempre se actualice durante la inicialización.
|
||||
arch.config.clean_cache=Eliminar versiones antiguas
|
||||
arch.config.clean_cache.tip=Si las versiones antiguas de un paquete almacenado en el disco deben ser eliminadas durante la desinstalación
|
||||
arch.config.check_dependency_breakage=Verificar rotura de versión de dependencia
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Compiler uniquement la sélection (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Certains paquets AUR ont un PKGBUILD commun partagé avec d'autres packages et ça définit les insctructions de compilation pour chacun d'eux. Cette propriété assure que le paquet sélectionné sera le seul compilé.
|
||||
arch.config.aur_remove_build_dir=Supprimer le répertoire de compilation (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=Si le repertoire de compilation généré doit être supprimé à la fin des opérations.
|
||||
arch.config.categories_exp=Categories expiration
|
||||
arch.config.categories_exp.tip=It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
arch.config.clean_cache=Supprimer les anciennes versions
|
||||
arch.config.clean_cache.tip=Supprimer les vielles versions d'un package stocké sur le disque pendant la désinstallation
|
||||
arch.config.check_dependency_breakage=Vérification pour éviter qu'une version de casse les dépendances
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Build only chosen (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Some AUR packages have a common PKGBUILD shared with other packages and that defines build instructions for each one. This property enabled will ensure that only the chosen package will be built.
|
||||
arch.config.aur_remove_build_dir=Remove build directory (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
|
||||
arch.config.categories_exp=Categories expiration
|
||||
arch.config.categories_exp.tip=It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
arch.config.clean_cache=Rimuovi le vecchie versioni
|
||||
arch.config.clean_cache.tip=Se le vecchie versioni di un pacchetto memorizzate sul disco devono essere rimosse durante la disinstallazione
|
||||
arch.config.check_dependency_breakage=Check dependency version breakage
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Construir somente escolhido (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Alguns pacotes do AUR têm um PKGBUILD comum a outros pacotes e que define a construção para todos. Essa propriedade ativada garantirá que somente o pacote escolhido será construído.
|
||||
arch.config.aur_remove_build_dir=Remover diretório de construção (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=Se o diretório gerado para a construção de um pacote do AUR deve ser removido após a operação ser finalizada.
|
||||
arch.config.categories_exp=Expiração de categorias
|
||||
arch.config.categories_exp.tip=Define o tempo de expiração (em HORAS) do arquivo de mapeamento de categorias de pacotes armazenado em disco. Utilize 0 para que ele seja sempre atualizado durante a inicialização.
|
||||
arch.config.clean_cache=Remover versões antigas
|
||||
arch.config.clean_cache.tip=Se versões antigas de um pacote armazenadas em disco devem ser removidas durante a desinstalação
|
||||
arch.config.check_dependency_breakage=Verificar quebra de dependência de versão
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Build only chosen (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Some AUR packages have a common PKGBUILD shared with other packages and that defines build instructions for each one. This property enabled will ensure that only the chosen package will be built.
|
||||
arch.config.aur_remove_build_dir=Remove build directory (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
|
||||
arch.config.categories_exp=Categories expiration
|
||||
arch.config.categories_exp.tip=It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
arch.config.clean_cache=Remove old versions
|
||||
arch.config.clean_cache.tip=Whether old versions of a package stored on disk should be removed during uninstall
|
||||
arch.config.check_dependency_breakage=Check dependency version breakage
|
||||
|
||||
@@ -41,6 +41,8 @@ arch.config.aur_build_only_chosen=Build only chosen (AUR)
|
||||
arch.config.aur_build_only_chosen.tip=Some AUR packages have a common PKGBUILD shared with other packages and that defines build instructions for each one. This property enabled will ensure that only the chosen package will be built.
|
||||
arch.config.aur_remove_build_dir=Remove build directory (AUR)
|
||||
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
|
||||
arch.config.categories_exp=Categories expiration
|
||||
arch.config.categories_exp.tip=It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
arch.config.clean_cache=Önbelleği temizle
|
||||
arch.config.clean_cache.tip=Disk üzerinde kurulu bir paketin eski sürümlerinin kaldırma sırasında kaldırılıp kaldırılmayacağı
|
||||
arch.config.check_dependency_breakage=Check dependency version breakage
|
||||
|
||||
@@ -3,5 +3,5 @@ from bauh.gems.snap import CONFIG_FILE
|
||||
|
||||
|
||||
def read_config(update_file: bool = False) -> dict:
|
||||
template = {'install_channel': False}
|
||||
template = {'install_channel': False, 'categories_exp': 24}
|
||||
return read(CONFIG_FILE, template, update_file=update_file)
|
||||
|
||||
@@ -11,7 +11,7 @@ from bauh.api.abstract.handler import ProcessWatcher, TaskManager
|
||||
from bauh.api.abstract.model import SoftwarePackage, PackageHistory, PackageUpdate, PackageSuggestion, \
|
||||
SuggestionPriority, CustomSoftwareAction, PackageStatus
|
||||
from bauh.api.abstract.view import SingleSelectComponent, SelectViewType, InputOption, ViewComponent, PanelComponent, \
|
||||
FormComponent
|
||||
FormComponent, TextInputComponent
|
||||
from bauh.api.exception import NoInternetException
|
||||
from bauh.commons import resource
|
||||
from bauh.commons.category import CategoriesDownloader
|
||||
@@ -19,7 +19,7 @@ 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, SNAP_CACHE_PATH, CATEGORIES_FILE_PATH, SUGGESTIONS_FILE, \
|
||||
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
|
||||
from bauh.gems.snap.model import SnapApplication
|
||||
@@ -285,7 +285,7 @@ class SnapManager(SoftwareManager):
|
||||
|
||||
def _start_category_task(self, task_man: TaskManager):
|
||||
if task_man:
|
||||
task_man.register_task('snap_cats', self.i18n['task.download_categories'].format('Snap'), get_icon_path())
|
||||
task_man.register_task('snap_cats', self.i18n['task.download_categories'], get_icon_path())
|
||||
task_man.update_progress('snap_cats', 50, None)
|
||||
|
||||
def _finish_category_task(self, task_man: TaskManager):
|
||||
@@ -294,11 +294,14 @@ class SnapManager(SoftwareManager):
|
||||
task_man.finish_task('snap_cats')
|
||||
|
||||
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
|
||||
Thread(target=read_config, args=(True,), daemon=True).start()
|
||||
snap_config = read_config()
|
||||
|
||||
CategoriesDownloader(id_='snap', manager=self, http_client=self.http_client, logger=self.logger,
|
||||
url_categories_file=URL_CATEGORIES_FILE, disk_cache_dir=SNAP_CACHE_PATH,
|
||||
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()
|
||||
|
||||
@@ -434,20 +437,31 @@ class SnapManager(SoftwareManager):
|
||||
|
||||
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
|
||||
snap_config = read_config()
|
||||
max_width = 200
|
||||
|
||||
install_channel = new_select(label=self.i18n['snap.config.install_channel'],
|
||||
opts=[(self.i18n['yes'].capitalize(), True, None),
|
||||
(self.i18n['no'].capitalize(), False, None)],
|
||||
value=bool(snap_config['install_channel']),
|
||||
id_='install_channel',
|
||||
max_width=200,
|
||||
id_='snap_install_channel',
|
||||
max_width=max_width,
|
||||
tip=self.i18n['snap.config.install_channel.tip'])
|
||||
|
||||
return PanelComponent([FormComponent([install_channel], self.i18n['installation'].capitalize())])
|
||||
categories_exp = TextInputComponent(id_='snap_cat_exp',
|
||||
value=snap_config['categories_exp'] if isinstance(snap_config['categories_exp'], int) else '',
|
||||
max_width=max_width,
|
||||
only_int=True,
|
||||
label=self.i18n['snap.config.categories_exp'],
|
||||
tooltip=self.i18n['snap.config.categories_exp.tip'])
|
||||
|
||||
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()
|
||||
config['install_channel'] = component.components[0].components[0].get_selected()
|
||||
|
||||
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()
|
||||
|
||||
try:
|
||||
save_config(config, CONFIG_FILE)
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Changing channel of
|
||||
snap.action.refresh.confirm=Actualitza {} ?
|
||||
snap.action.refresh.label=Actualitza
|
||||
snap.action.refresh.status=S’està actualitzant
|
||||
snap.config.categories_exp=Categories expiration
|
||||
snap.config.categories_exp.tip=It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
snap.config.install_channel=Display channels
|
||||
snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
|
||||
snap.info.channel=channel
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Changing channel of
|
||||
snap.action.refresh.confirm=Erneuern {} ?
|
||||
snap.action.refresh.label=Erneuern
|
||||
snap.action.refresh.status=Erneuern
|
||||
snap.config.categories_exp=Categories expiration
|
||||
snap.config.categories_exp.tip=It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
snap.config.install_channel=Display channels
|
||||
snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
|
||||
snap.info.channel=channel
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Changing channel of
|
||||
snap.action.refresh.confirm=Refresh {} ?
|
||||
snap.action.refresh.label=Refresh
|
||||
snap.action.refresh.status=Refreshing
|
||||
snap.config.categories_exp=Categories expiration
|
||||
snap.config.categories_exp.tip=It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
snap.config.install_channel=Display channels
|
||||
snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
|
||||
snap.info.channel=channel
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.label=Cambiar canal
|
||||
snap.action.refresh.confirm=Actualizar {} ?
|
||||
snap.action.refresh.label=Actualizar
|
||||
snap.action.refresh.status=Actualizando
|
||||
snap.config.categories_exp=Expiración de categorías
|
||||
snap.config.categories_exp.tip=Define el tiempo de vencimiento (en HORAS) del archivo de mapeo de categorías de Snaps almacenado en el disco. Utilice 0 para que siempre se actualice durante la inicialización.
|
||||
snap.config.install_channel=Mostrar canales
|
||||
snap.config.install_channel.tip=Permite seleccionar uno de los canales disponibles para la aplicación a instalar
|
||||
snap.info.channel=canal
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Changement de canal de
|
||||
snap.action.refresh.confirm=Actualiser {} ?
|
||||
snap.action.refresh.label=Actualiser
|
||||
snap.action.refresh.status=Actualisation
|
||||
snap.config.categories_exp=Categories expiration
|
||||
snap.config.categories_exp.tip=It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
snap.config.install_channel=Afficher les canaux
|
||||
snap.config.install_channel.tip=Permet de sélectionner un des canaux disponibles pour l'application à installer
|
||||
snap.info.channel=canal
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Changing channel of
|
||||
snap.action.refresh.confirm=Ripristina {} ?
|
||||
snap.action.refresh.label=Ripristina
|
||||
snap.action.refresh.status=Ripristinare
|
||||
snap.config.categories_exp=Categories expiration
|
||||
snap.config.categories_exp.tip=It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
snap.config.install_channel=Display channels
|
||||
snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
|
||||
snap.info.channel=channel
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Alterando canal de
|
||||
snap.action.refresh.confirm=Atualizar {} ?
|
||||
snap.action.refresh.label=Atualizar
|
||||
snap.action.refresh.status=Atualizando
|
||||
snap.config.categories_exp=Expiração de categorias
|
||||
snap.config.categories_exp.tip=Define o tempo de expiração (em HORAS) do arquivo de mapeamento de categorias Snap armazenado em disco. Utilize 0 para que ele seja sempre atualizado durante a inicialização.
|
||||
snap.config.install_channel=Exibir canais
|
||||
snap.config.install_channel.tip=Permite-se selecionar um dos canais disponíveis para o aplicativo a ser instalado
|
||||
snap.info.channel=canal
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Changing channel of
|
||||
snap.action.refresh.confirm=Обновить {} ?
|
||||
snap.action.refresh.label=Обновить
|
||||
snap.action.refresh.status=Обновляется
|
||||
snap.config.categories_exp=Categories expiration
|
||||
snap.config.categories_exp.tip=It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
snap.config.install_channel=Display channels
|
||||
snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
|
||||
snap.info.channel=channel
|
||||
|
||||
@@ -6,6 +6,8 @@ snap.action.channel.status=Changing channel of
|
||||
snap.action.refresh.confirm=Yenile {} ?
|
||||
snap.action.refresh.label=Yenile
|
||||
snap.action.refresh.status=Yenileniyor
|
||||
snap.config.categories_exp=Categories expiration
|
||||
snap.config.categories_exp.tip=It defines the expiration time (in HOURS) of the Snaps categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
|
||||
snap.config.install_channel=Display channels
|
||||
snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
|
||||
snap.info.channel=channel
|
||||
|
||||
@@ -400,6 +400,8 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
return man.requires_root(action, app)
|
||||
|
||||
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
|
||||
ti = time.time()
|
||||
self.logger.info("Initializing")
|
||||
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
|
||||
@@ -408,6 +410,9 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
man.prepare(taskman, root_password, internet_on)
|
||||
self._already_prepared.append(man)
|
||||
|
||||
tf = time.time()
|
||||
self.logger.info("Finished. Took {0:.2f} seconds".format(tf - ti))
|
||||
|
||||
def cache_available_managers(self):
|
||||
if self.managers:
|
||||
for man in self.managers:
|
||||
|
||||
@@ -391,7 +391,7 @@ status.caching_data=S’estan emmagatzemant {} dades a la memòria cau al disc
|
||||
style=estil
|
||||
success=success
|
||||
summary=resum
|
||||
task.download_categories=Download de categories [ {} ]
|
||||
task.download_categories=Download de categories
|
||||
task.waiting_task=Waiting for {}
|
||||
type=tipus
|
||||
uninstall=desinstal·la
|
||||
|
||||
@@ -391,7 +391,7 @@ status.caching_data={} Daten auf der Festplatte zwischenspeichern
|
||||
style=Stil
|
||||
success=success
|
||||
summary=Zusammenfassung
|
||||
task.download_categories=Downloading categories [ {} ]
|
||||
task.download_categories=Downloading categories
|
||||
task.waiting_task=Waiting for {}
|
||||
type=Typ
|
||||
uninstall=Deinstallation
|
||||
|
||||
@@ -392,7 +392,7 @@ status.caching_data=Caching {} data to disk
|
||||
style=style
|
||||
success=success
|
||||
summary=summary
|
||||
task.download_categories=Downloading categories [ {} ]
|
||||
task.download_categories=Downloading categories
|
||||
task.waiting_task=Waiting for {}
|
||||
type=type
|
||||
uninstall=uninstall
|
||||
|
||||
@@ -394,7 +394,7 @@ status.caching_data=Almacenando en antememoria los datos de {} para el disco
|
||||
style=estilo
|
||||
success=éxito
|
||||
summary=resumen
|
||||
task.download_categories=Descargando categorías [ {} ]
|
||||
task.download_categories=Descargando categorías
|
||||
task.waiting_task=Esperando por {}
|
||||
type=tipo
|
||||
uninstall=desinstalar
|
||||
|
||||
@@ -388,7 +388,7 @@ status.caching_data=Mise en cache des données de {} sur disque
|
||||
style=style
|
||||
success=succès
|
||||
summary=résumé
|
||||
task.download_categories=Téléchargement des catégories [ {} ]
|
||||
task.download_categories=Téléchargement des catégories
|
||||
task.waiting_task=Waiting for {}
|
||||
type=type
|
||||
uninstall=désinstaller
|
||||
|
||||
@@ -394,7 +394,7 @@ status.caching_data=Memorizza {} dati sul disco
|
||||
style=stile
|
||||
success=success
|
||||
summary=riepilogo
|
||||
task.download_categories=Download delle categorie [ {} ]
|
||||
task.download_categories=Download delle categorie
|
||||
task.waiting_task=Waiting for {}
|
||||
type=tipe
|
||||
uninstall=Disinstalla
|
||||
|
||||
@@ -392,7 +392,7 @@ status.caching_data=Cacheando dados de {} para o disco
|
||||
style=estilo
|
||||
success=sucesso
|
||||
summary=resumo
|
||||
task.download_categories=Baixando categorias [ {} ]
|
||||
task.download_categories=Baixando categorias
|
||||
task.waiting_task=Aguardando {}
|
||||
type=tipo
|
||||
uninstall=desinstalar
|
||||
|
||||
@@ -391,7 +391,7 @@ status.caching_data=Кэширование данных {} на диск
|
||||
style=Стиль
|
||||
success=success
|
||||
summary=Суммарно
|
||||
task.download_categories=Downloading categories [ {} ]
|
||||
task.download_categories=Downloading categories
|
||||
task.waiting_task=Waiting for {}
|
||||
type=Тип
|
||||
uninstall=Деинсталляция
|
||||
|
||||
@@ -391,7 +391,7 @@ status.caching_data={} verilerini diske önbellekle
|
||||
style=Görünüm biçimi
|
||||
success=başarılı
|
||||
summary=özet
|
||||
task.download_categories=Kategoriler indiriliyor [ {} ]
|
||||
task.download_categories=Kategoriler indiriliyor
|
||||
task.waiting_task=Waiting for {}
|
||||
type=tür
|
||||
uninstall=kaldır
|
||||
|
||||
Reference in New Issue
Block a user