From 8488b086e639b4756971b204cb28e2038215c74e Mon Sep 17 00:00:00 2001 From: Vinicius Moreira Date: Tue, 9 Nov 2021 11:47:36 -0300 Subject: [PATCH] [flatpak] fix: not displaying update components not associated with installed packages --- CHANGELOG.md | 3 + bauh/gems/flatpak/controller.py | 117 ++++++++++++++++++++------------ bauh/gems/flatpak/flatpak.py | 9 ++- bauh/gems/flatpak/model.py | 43 ++++++++---- 4 files changed, 113 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b24b96c..072aa32b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [0.9.21] 2021 ### Fixes +- Flatpak + - not displaying update components not associated with installed packages + - UI - upgrade summary: not displaying the icon type for some applications diff --git a/bauh/gems/flatpak/controller.py b/bauh/gems/flatpak/controller.py index 56bd9633..360f4395 100644 --- a/bauh/gems/flatpak/controller.py +++ b/bauh/gems/flatpak/controller.py @@ -128,48 +128,63 @@ class FlatpakManager(SoftwareManager): thread_updates = None installed = flatpak.list_installed(version) - models = [] + + update_map = None + if thread_updates: + thread_updates.join() + update_map = updates[0] + + models = {} if installed: - update_map = None - if thread_updates: - thread_updates.join() - update_map = updates[0] - for app_json in installed: model = self._map_to_model(app_json=app_json, installed=True, disk_loader=disk_loader, internet=internet_available) - model.update = None - models.append(model) + model.update = False + models[model.get_update_id(version)] = model - if update_map and (update_map['full'] or update_map['partial']): - if version >= VERSION_1_2: - update_id = '{}/{}/{}'.format(app_json['id'], app_json['branch'], app_json['installation']) + if update_map: + for update_id in update_map['full']: + model_with_update = models.get(update_id) + if model_with_update: + model_with_update.update = True + else: + # it is a new component that must be installed + update_id_split = update_id.split('/') + new_app = FlatpakApplication(id=update_id_split[0], + branch=update_id_split[1], + installation=update_id_split[2], + name=update_id_split[0].split('.')[-1].strip(), + version=update_id_split[1], + arch='x86_64' if self.context.is_system_x86_64() else 'x86', + origin=update_id_split[3] if len(update_id_split) == 4 else None) + new_app.update_component = True # mark as "update component" + new_app.installed = True # faking the "installed" status to be displayed as an update + new_app.update = True + new_app.update_ref() + models[update_id] = new_app - if update_map['full'] and update_id in update_map['full']: - model.update = True + if version >= VERSION_1_2: + for partial_update_id in update_map['partial']: + partial_data = partial_update_id.split['/'] - if update_map['partial']: - for partial in update_map['partial']: - partial_data = partial.split('/') - if app_json['id'] in partial_data[0] and\ - app_json['branch'] == partial_data[1] and\ - app_json['installation'] == partial_data[2]: - partial_model = model.gen_partial(partial.split('/')[0]) - partial_model.update = True - models.append(partial_model) - else: - model.update = '{}/{}'.format(app_json['installation'], app_json['ref']) in update_map['full'] + for model_update_id, model in models.items(): + if model.installation == partial_data[2] and model_update_id in partial_data[0] and \ + model.branch == partial_data[1]: + partial_model = model.gen_partial(partial_data[0]) + partial_model.update = True + models[partial_update_id] = partial_model + break if models: ignored = self._read_ignored_updates() if ignored: - for model in models: + for model in models.values(): if model.get_update_ignore_key() in ignored: model.updates_ignored = True - return SearchResult(models, None, len(models)) + return SearchResult([*models.values()], None, len(models)) def downgrade(self, pkg: FlatpakApplication, root_password: str, watcher: ProcessWatcher) -> bool: if not self._make_exports_dir(watcher): @@ -217,10 +232,16 @@ class FlatpakManager(SoftwareManager): ref = req.pkg.base_ref try: - res, _ = ProcessHandler(watcher).handle_simple(flatpak.update(app_ref=ref, - installation=req.pkg.installation, - related=related, - deps=deps)) + if req.pkg.update_component: + res, _ = ProcessHandler(watcher).handle_simple(flatpak.install(app_id=ref, + installation=req.pkg.installation, + origin=req.pkg.origin)) + + else: + res, _ = ProcessHandler(watcher).handle_simple(flatpak.update(app_ref=ref, + installation=req.pkg.installation, + related=related, + deps=deps)) watcher.change_substatus('') if not res: @@ -253,23 +274,33 @@ class FlatpakManager(SoftwareManager): def get_info(self, app: FlatpakApplication) -> dict: if app.installed: - version = flatpak.get_version() - id_ = app.base_id if app.partial and version < VERSION_1_5 else app.id - app_info = flatpak.get_app_info_fields(id_, app.branch, app.installation) + if app.update_component: + app_info = {'id': app.id, + 'name': app.name, + 'branch': app.branch, + 'installation': app.installation, + 'origin': app.origin, + 'arch': app.arch, + 'ref': app.ref, + 'type': self.i18n['unknown']} + else: + version = flatpak.get_version() + id_ = app.base_id if app.partial and version < VERSION_1_5 else app.id + app_info = flatpak.get_app_info_fields(id_, app.branch, app.installation) - if app.partial and version < VERSION_1_5: - app_info['id'] = app.id - app_info['ref'] = app.ref + if app.partial and version < VERSION_1_5: + app_info['id'] = app.id + app_info['ref'] = app.ref - app_info['name'] = app.name - app_info['type'] = 'runtime' if app.runtime else 'app' - app_info['description'] = strip_html(app.description) if app.description else '' + app_info['name'] = app.name + app_info['type'] = 'runtime' if app.runtime else 'app' + app_info['description'] = strip_html(app.description) if app.description else '' - if app.installation: - app_info['installation'] = app.installation + if app.installation: + app_info['installation'] = app.installation - if app_info.get('installed'): - app_info['installed'] = app_info['installed'].replace('?', ' ') + if app_info.get('installed'): + app_info['installed'] = app_info['installed'].replace('?', ' ') return app_info else: diff --git a/bauh/gems/flatpak/flatpak.py b/bauh/gems/flatpak/flatpak.py index b185ea42..37f3eb2f 100755 --- a/bauh/gems/flatpak/flatpak.py +++ b/bauh/gems/flatpak/flatpak.py @@ -15,6 +15,7 @@ from bauh.gems.flatpak import EXPORTS_PATH, VERSION_1_3, VERSION_1_2, VERSION_1_ RE_SEVERAL_SPACES = re.compile(r'\s+') RE_COMMIT = re.compile(r'(Latest commit|Commit)\s*:\s*(.+)') +OPERATION_UPDATE_SYMBOLS = {'i', 'u'} def get_app_info_fields(app_id: str, branch: str, installation: str, fields: List[str] = [], check_runtime: bool = False): @@ -208,12 +209,14 @@ def read_updates(version: Version, installation: str) -> Dict[str, set]: if len(line_split) > 2: if version >= VERSION_1_5: - update_id = '{}/{}/{}'.format(line_split[2], line_split[3], installation) + update_id = f'{line_split[2]}/{line_split[3]}/{installation}/{line_split[5]}' + elif version >= VERSION_1_2: + update_id = f'{line_split[2]}/{line_split[4]}/{installation}/{line_split[5]}' else: update_id = '{}/{}/{}'.format(line_split[2], line_split[4], installation) - if len(line_split) >= 6: - if line_split[4] != 'i': + if version >= VERSION_1_3 and len(line_split) >= 6: + if line_split[4].strip().lower() in OPERATION_UPDATE_SYMBOLS: if '(partial)' in line_split[-1]: res['partial'].add(update_id) else: diff --git a/bauh/gems/flatpak/model.py b/bauh/gems/flatpak/model.py index cf0b519e..7a6a8d9c 100644 --- a/bauh/gems/flatpak/model.py +++ b/bauh/gems/flatpak/model.py @@ -1,6 +1,8 @@ +from packaging.version import Version + from bauh.api.abstract.model import SoftwarePackage, PackageStatus from bauh.commons import resource -from bauh.gems.flatpak import ROOT_DIR +from bauh.gems.flatpak import ROOT_DIR, VERSION_1_2, VERSION_1_5 from bauh.view.util.translation import I18n @@ -23,6 +25,7 @@ class FlatpakApplication(SoftwarePackage): self.base_id = None self.base_ref = None self.updates_ignored = updates_ignored + self.update_component = False # if it is a new app/runtime that has come as an update if runtime: self.categories = ['runtime'] @@ -31,13 +34,13 @@ class FlatpakApplication(SoftwarePackage): return self.description is None and self.icon_url def has_history(self) -> bool: - return not self.partial and self.installed and self.ref + return not self.partial and not self.update_component and self.installed and self.ref def has_info(self): return bool(self.id) def can_be_downgraded(self): - return not self.partial and self.installed and self.ref + return not self.partial and not self.update_component and self.installed and self.ref def get_type(self): return 'flatpak' @@ -49,20 +52,21 @@ class FlatpakApplication(SoftwarePackage): return self.get_default_icon_path() def is_application(self): - return not self.runtime and not self.partial + return not self.runtime and not self.partial and not self.update_component def get_disk_cache_path(self): return super(FlatpakApplication, self).get_disk_cache_path() + '/installed/' + self.id def get_data_to_cache(self): - return { - 'description': self.description, - 'icon_url': self.icon_url, - 'latest_version': self.latest_version, - 'version': self.version, - 'name': self.name, - 'categories': self.categories - } + if not self.update_component: + return { + 'description': self.description, + 'icon_url': self.icon_url, + 'latest_version': self.latest_version, + 'version': self.version, + 'name': self.name, + 'categories': self.categories + } def fill_cached_data(self, data: dict): for attr in self.get_data_to_cache().keys(): @@ -70,7 +74,7 @@ class FlatpakApplication(SoftwarePackage): setattr(self, attr, data[attr]) def can_be_run(self) -> bool: - return self.installed and not self.runtime and not self.partial + return self.installed and not self.runtime and not self.partial and not self.update_component def get_publisher(self): return self.origin @@ -124,3 +128,16 @@ class FlatpakApplication(SoftwarePackage): def get_disk_icon_path(self) -> str: if not self.runtime: return super(FlatpakApplication, self).get_disk_icon_path() + + def get_update_id(self, flatpak_version: Version) -> str: + if flatpak_version >= VERSION_1_2: + return f'{self.id}/{self.branch}/{self.installation}/{self.origin}' + else: + return f'{self.installation}/{self.ref}' + + def can_be_uninstalled(self) -> bool: + return not self.update_component and super(FlatpakApplication, self).can_be_uninstalled() + + def update_ref(self): + if self.id and self.arch and self.branch: + self.ref = f'{self.id}/{self.arch}/{self.branch}'