diff --git a/README.md b/README.md
index 117787f0..00f3378a 100644
--- a/README.md
+++ b/README.md
@@ -35,9 +35,9 @@ Bearhub is currently focused on:
Large architectural changes or feature redesigns are not the immediate priority.
-Backends outside the Arch-focused scope remain in the codebase for now, but they are not the primary maintenance target of this fork.
+Debian / Apt support is intentionally removed from Bearhub. Other non-Arch backends that remain in the codebase are secondary to the Arch-focused maintenance target.
-**bauh** (baoo), formerly known as [fpakman](https://github.com/vinifmor/fpakman), is a graphical interface for managing your Linux software (packages/applications). It currently supports the following formats: AppImage, Debian and Arch Linux packages (including AUR), Flatpak, Snap and Web applications.
+**bauh** (baoo), formerly known as [fpakman](https://github.com/vinifmor/fpakman), is a graphical interface for managing your Linux software (packages/applications). In Bearhub, the maintained package formats are Arch Linux packages (including AUR), Flatpak, Snap, AppImage and Web applications.
Key features
- A management panel where you can: search, install, uninstall, upgrade, downgrade and launch your applications
@@ -54,7 +54,6 @@ Key features
## Index
1. [Installation](#installation)
- [AppImage](#inst_appimage)
- - [Ubuntu 20.04 based distros (Linux Mint, PopOS, ...)](#inst_ubuntu)
- [Arch-based distros](#inst_arch)
2. [Isolated installation](#inst_iso)
3. [Desktop entry / menu shortcut](#desk_entry)
@@ -63,7 +62,6 @@ Key features
6. [Supported types](#types)
- [AppImage](#type_appimage)
- [Arch packages/AUR](#type_arch)
- - [Debian](#type_deb)
- [Flatpak](#type_flatpak)
- [Snap](#type_snap)
- [Native Web applications](#type_web)
@@ -103,52 +101,6 @@ Key features
-#### Ubuntu 20.04 based distros (Linux Mint, PopOS, ...)
-
-##### Required dependencies
-
-`sudo apt-get install python3 python3-pip python3-yaml python3-dateutil python3-pyqt5 python3-packaging python3-requests`
-
-##### Installing bauh
-
-`sudo pip3 install bauh`
-
-
-##### Optional dependencies (they should be installed with apt-get/apt)
-
-- `aptitude`: Debian package management
-- `timeshift`: system backup
-- `aria2`: multi-threaded downloads
-- `axel`: multi-threaded downloads alternative
-- `libappindicator3-1`: tray-mode
-- `sqlite3`, `fuse`: AppImage support
-- `flatpak`: Flatpaks support
-- `snapd`: Snaps support
-- `python3-lxml`, `python3-bs4`: Web apps support
-- `python3-venv`: [isolated installation](#inst_iso)
-- `xdg-utils`: to open URLs in the browsers (`xdg-open`)
-
-##### Updating bauh
-
-Method 1
-
-`sudo pip3 install bauh --upgrade`
-
-Method 2
-
-```
-sudo pip3 uninstall bauh
-sudo pip3 install bauh
-```
-
-##### Uninstalling bauh
-
-```
-bauh --reset # removes cache and configurations files from HOME
-sudo pip3 uninstall bauh
-```
-
-
#### Arch-based distros
##### Using yay
@@ -341,24 +293,6 @@ suggestions_exp: 24 # it defines the period (in hours) in which the suggestions
```
- Cached package suggestions: `~/.cache/bauh/arch/suggestions.txt` (or `/var/cache/bauh/arch/suggestions.yml` for **root**)
-##### Debian packages
-- Basic actions supported: **search**, **install**, **uninstall**, **upgrade**
-- Custom actions supported:
- - **synchronize packages**: synchronize the available packages on the repository (`aptitude update`)
- - **index applications**: maps runnable installed packages (automatically done during initialization)
- - **software sources**: launches the application responsible for managing software sources (at the moment only `software-properties-gtk` is supported)
-- Custom package actions supported:
- - **purge**: removes the packages and all related configuration files
-- Files:
- - runnable applications index: `~/.cache/bauh/debian/apps_idx.json` (or `/var/cache/bauh/debian/apps_idx.json` for **root**)
- - cached package suggestions: `~/.cache/bauh/debian/suggestions.txt` (or `/var/cache/bauh/debian/suggestions.txt` for **root**)
- - configuration: `~/.config/bauh/debian.yml` or `/etc/bauh/debian.yml`
- - `index_apps.exp`: time period (**in minutes**) in which the installed applications cache is considered up-to-date during startup (default: `1440` -> 24 hours)
- - `sync_pkgs.time`: time period (**in minutes**) in which the packages synchronization must be done on startup (default: `1440` -> 24 hours)
- - `suggestions.exp`: it defines the period (**in hours**) in which the suggestions stored in disc will be considered up to date. Use 0 if you always want to update them.
- - `pkg_sources.app`: it defines the application for managing the software sources. A `null` value detects one of the supported applications automatically.
- - `remove.purge`: if the package configurations should be removed during the uninstallation process (purge). Default: false.
-
##### Flatpak
- Applications with ignored updates are defined at `~/.config/bauh/flatpak/updates_ignored.txt`
@@ -517,7 +451,6 @@ appimage
- The software suggestions are download from [bauh-files](https://github.com/vinifmor/bauh-files) by default
- [appimage](https://github.com/vinifmor/bauh-files/blob/master/appimage/suggestions.txt)
- [arch](https://github.com/vinifmor/bauh-files/blob/master/appimage/suggestions.txt)
- - [debian](https://github.com/vinifmor/bauh-files/blob/master/debian/suggestions_v1.txt)
- [flatpak](https://github.com/vinifmor/bauh-files/blob/master/flatpak/suggestions.txt)
- [snap](https://github.com/vinifmor/bauh-files/blob/master/snap/suggestions.txt)
- [web](https://github.com/vinifmor/bauh-files/blob/master/web/env/v2/suggestions.yml)
diff --git a/bauh/gems/debian/__init__.py b/bauh/gems/debian/__init__.py
deleted file mode 100644
index e4121fd3..00000000
--- a/bauh/gems/debian/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import os
-
-from bauh.api.paths import CACHE_DIR, CONFIG_DIR
-from bauh.commons import resource
-
-ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
-
-DEBIAN_CACHE_DIR = f'{CACHE_DIR}/debian'
-APP_INDEX_FILE = f'{DEBIAN_CACHE_DIR}/apps_idx.json'
-CONFIG_FILE = f'{CONFIG_DIR}/debian.yml'
-PACKAGE_SYNC_TIMESTAMP_FILE = f'{DEBIAN_CACHE_DIR}/sync_pkgs.ts'
-DEBIAN_ICON_PATH = resource.get_path('img/debian.svg', ROOT_DIR)
diff --git a/bauh/gems/debian/aptitude.py b/bauh/gems/debian/aptitude.py
deleted file mode 100644
index 097ea5df..00000000
--- a/bauh/gems/debian/aptitude.py
+++ /dev/null
@@ -1,430 +0,0 @@
-import re
-import time
-from contextlib import contextmanager
-from enum import Enum
-from logging import Logger
-from math import ceil
-from queue import Queue
-from threading import Thread
-from typing import Iterable, Optional, Pattern, Dict, Set, Tuple, Generator, Collection
-
-from bauh.api.abstract.handler import ProcessWatcher
-from bauh.commons import system
-from bauh.commons.html import bold
-from bauh.commons.system import SimpleProcess
-from bauh.commons.util import size_to_byte
-from bauh.gems.debian.common import strip_maintainer_email, strip_section
-from bauh.gems.debian.model import DebianPackage, DebianTransaction
-from bauh.view.util.translation import I18n
-
-
-def map_package_name(string: str):
- name_split = string.split(':')
-
- if len(name_split) > 2:
- return ':'.join(name_split[0:-1])
-
- return name_split[0]
-
-
-class AptitudeAction(Enum):
- INSTALL = 0
- UPGRADE = 1
- REMOVE = 3
-
-
-class Aptitude:
-
- def __init__(self, logger: Logger):
- self._log = logger
- self._re_show_attr: Optional[Pattern] = None
- self._env: Optional[Dict[str, str]] = None
- self._list_attrs: Optional[Set[str]] = None
- self._re_to_install: Optional[Pattern] = None
- self._re_transaction_pkg: Optional[Pattern] = None
- self._size_attrs: Optional[Tuple[str]] = None
- self._default_lang = ''
- self._ignored_fields: Optional[Set[str]] = None
- self._re_none: Optional[Pattern] = None
- self._vars_fixes: Optional[Dict[str, str]] = None
- self._preserve_env = {'DEBIAN_FRONTEND'}
-
- def show(self, pkgs: Iterable[str], attrs: Optional[Collection[str]] = None, verbose: bool = False) \
- -> Optional[Dict[str, Dict[str, object]]]:
-
- if pkgs:
- force_verbose = verbose if verbose else ('compressed size' in attrs if attrs else False)
- code, output = system.execute(f"aptitude show -q {' '.join(pkgs)}{' -v' if force_verbose else ''}",
- shell=True, custom_env=self.env)
-
- if code == 0 and output:
- info, pkg = dict(), None
- for field, val in self.re_show_attr.findall('\n' + output):
- final_field, final_val = field.strip().lower(), val.strip()
-
- if final_field == 'package':
- pkg = {}
- info[final_val] = pkg
- elif final_field not in self.ignored_fields and (not attrs or final_field in attrs):
- if final_val:
- if final_field in self.list_attrs:
- final_val = tuple((v.strip() for v in final_val.split(',') if v))
- elif final_field in self.size_attrs:
- size_split = final_val.split(' ')
-
- if len(size_split) >= 1:
- unit = size_split[1].upper() if len(size_split) >= 2 else 'B'
- final_val = size_to_byte(size_split[0], unit, self._log)
- else:
- self._log.warning(f"Unhandled value ({val}) for attribute '{field}'")
- final_val = None
-
- pkg[final_field] = final_val
-
- return info
-
- def simulate_removal(self, packages: Iterable[str], purge: bool = False) -> Optional[DebianTransaction]:
- code, output = system.execute(self.gen_remove_cmd(packages, purge, simulate=True), shell=True,
- custom_env=self.env)
-
- if code == 0 and output:
- return self.map_transaction_output(output)
-
- def map_transaction_output(self, output: str) -> DebianTransaction:
- to_install, to_upgrade, to_remove = None, None, None
- current_collection = None
-
- for line in output.split('\n'):
- if line.startswith('The following NEW packages will be installed:'):
- to_install = set()
- current_collection = to_install
- elif line.startswith('The following packages will be upgraded:'):
- to_upgrade = set()
- current_collection = to_upgrade
- elif line.startswith('The following packages will be REMOVED:'):
- to_remove = set()
- current_collection = to_remove
- elif line.startswith('Would download/install/remove packages'):
- break
- elif current_collection is not None and line.startswith(' '):
- for n, _, v, __, lv, ___, size in self.re_transaction_pkg.findall(line):
- pkg = DebianPackage(name=n, version=v, latest_version=lv if lv else v, transaction_size=0)
-
- if size:
- size_split = size.strip().split(' ')
- unit = size_split[1][0].upper() if len(size_split) >= 2 else 'B'
- pkg.transaction_size = size_to_byte(size_split[0], unit, self._log)
-
- current_collection.add(pkg)
-
- return DebianTransaction(to_install=tuple(to_install) if to_install else tuple(),
- to_remove=tuple(to_remove) if to_remove else tuple(),
- to_upgrade=tuple(to_upgrade) if to_upgrade else tuple())
-
- def simulate_upgrade(self, packages: Iterable[str]) -> DebianTransaction:
- code, output = system.execute(self.gen_transaction_cmd('upgrade', packages, simulate=True),
- shell=True, custom_env=self.env)
-
- if code == 0 and output:
- return self.map_transaction_output(output)
-
- def upgrade(self, packages: Iterable[str], root_password: Optional[str]) -> SimpleProcess:
- cmd = self.gen_transaction_cmd('upgrade', packages).split(' ')
- return SimpleProcess(cmd=cmd, shell=True, root_password=root_password, extra_env=self.vars_fixes,
- preserve_env=self._preserve_env)
-
- def update(self, root_password: Optional[str]) -> SimpleProcess:
- return SimpleProcess(('aptitude', 'update'), root_password=root_password, shell=True)
-
- def simulate_installation(self, packages: Iterable[str]) -> Optional[DebianTransaction]:
- code, output = system.execute(self.gen_transaction_cmd('install', packages, simulate=True),
- shell=True, custom_env=self.env)
-
- if code == 0 and output:
- return self.map_transaction_output(output)
-
- def install(self, packages: Iterable[str], root_password: Optional[str]) -> SimpleProcess:
- cmd = self.gen_transaction_cmd('install', packages).split(' ')
- return SimpleProcess(cmd=cmd, root_password=root_password, extra_env=self.vars_fixes,
- preserve_env=self._preserve_env)
-
- def read_installed(self) -> Generator[DebianPackage, None, None]:
- yield from self.search(query='~i')
-
- def read_updates(self) -> Generator[Tuple[str, str], None, None]:
- _, output = system.execute(f"aptitude search ~U -q -F '%p^%V' --disable-columns --no-gui",
- shell=True,
- custom_env=self.env)
-
- if output:
- for line in output.split('\n'):
- line_split = line.strip().split('^')
-
- if len(line_split) == 2 and line_split[1] != '':
- yield line_split[0], line_split[1]
-
- def search(self, query: str, fill_size: bool = False) -> Generator[DebianPackage, None, None]:
- attrs = f"%p^%v^%V^%m^%s^{'%I^' if fill_size else ''}%d"
- _, output = system.execute(f"aptitude search {query} -q -F '{attrs}' --disable-columns", shell=True)
-
- if output:
- no_attrs = 7 if fill_size else 6
-
- for line in output.split('\n'):
- line_split = line.strip().split('^', maxsplit=no_attrs - 1)
-
- if len(line_split) == no_attrs:
- latest_version = line_split[2] if not self.re_none.match(line_split[2]) else None
-
- size = None
-
- if fill_size:
- size_split = line_split[no_attrs - 2].split(' ')
- unit = size_split[1][0].upper() if len(size_split) >= 2 else 'B'
- size = size_to_byte(size_split[0], unit, self._log)
-
- if latest_version is not None:
- installed_version = line_split[1] if not self.re_none.match(line_split[1]) else None
- section = strip_section(line_split[4])
-
- yield DebianPackage(name=line_split[0],
- version=installed_version if installed_version else latest_version,
- latest_version=latest_version,
- installed=bool(installed_version),
- update=installed_version is not None and installed_version != latest_version,
- maintainer=strip_maintainer_email(line_split[3]),
- categories=(section,) if section else None,
- uncompressed_size=size,
- description=line_split[no_attrs - 1])
-
- def search_by_name(self, names: Iterable[str], fill_size: bool = False) -> Generator[DebianPackage, None, None]:
- query = f"'({'|'.join(f'?exact-name({n})' for n in names)})'"
- yield from self.search(query=query, fill_size=fill_size)
-
- def remove(self, packages: Iterable[str], root_password: Optional[str], purge: bool = False) -> SimpleProcess:
- return SimpleProcess(cmd=self.gen_remove_cmd(packages, purge).split(' '), shell=True,
- root_password=root_password, extra_env=self.vars_fixes, preserve_env=self._preserve_env)
-
- def read_installed_names(self) -> Generator[str, None, None]:
- code, output = system.execute("aptitude search ~i -q -F '%p' --disable-columns",
- shell=True,
- custom_env=self.env)
-
- if output:
- for line in output.split('\n'):
- if line:
- yield line
-
- @property
- def re_show_attr(self) -> Pattern:
- if self._re_show_attr is None:
- self._re_show_attr = re.compile(r'(\n\w+[a-zA-Z0-9\-\s]*):\s+(.+)')
-
- return self._re_show_attr
-
- @property
- def env(self) -> Dict[str, str]:
- if self._env is None:
- self._env = system.gen_env(global_interpreter=system.USE_GLOBAL_INTERPRETER)
- self._env['LC_NUMERIC'] = ''
-
- return self._env
-
- @property
- def list_attrs(self) -> Set[str]:
- if self._list_attrs is None:
- self._list_attrs = {'depends', 'provides', 'replaces', 'recommends', 'suggests', 'conflicts',
- 'state', 'predepends', 'breaks'}
-
- return self._list_attrs
-
- @property
- def re_transaction_pkg(self) -> Pattern:
- if self._re_transaction_pkg is None:
- self._re_transaction_pkg = re.compile(r'([a-zA-Z0-9\-_@~.+:]+)({\w+})?\s*\[([a-zA-Z0-9\-_@~.+:]+)'
- r'(\s+->\s+([a-zA-Z0-9\-_@~.+:]+))?](\s*<([\-+]?[0-9.,]+\s+\w+)>)?')
-
- return self._re_transaction_pkg
-
- @property
- def size_attrs(self) -> Tuple[str]:
- if self._size_attrs is None:
- self._size_attrs = {'compressed size', 'uncompressed size'}
-
- return self._size_attrs
-
- @property
- def ignored_fields(self) -> Set[str]:
- if self._ignored_fields is None:
- self._ignored_fields = {'sha1', 'sha256', 'sha512', 'checksum-filesize'}
-
- return self._ignored_fields
-
- @classmethod
- def gen_remove_cmd(cls, packages: Iterable[str], purge: bool, simulate: bool = False) -> str:
- return cls.gen_transaction_cmd(type_='purge' if purge else 'remove', packages=packages,
- simulate=simulate)
-
- @staticmethod
- def gen_transaction_cmd(type_: str, packages: Iterable[str], simulate: bool = False,
- delete_unused: bool = False) -> str:
- return f"aptitude {type_} -q -y --no-gui --full-resolver {' '.join(packages)}" \
- f" -o Aptitude::ProblemResolver::RemoveScore=9999999" \
- f" -o Aptitude::ProblemResolver::EssentialRemoveScore=9999999" \
- f" -o Aptitude::Delete-Unused={str(delete_unused).lower()}" \
- f"{' -V -s -Z' if simulate else ''}"
-
- @property
- def re_none(self) -> Pattern:
- if self._re_none is None:
- self._re_none = re.compile(r'^<\w+>$')
-
- return self._re_none
-
- @property
- def vars_fixes(self) -> Dict[str, str]:
- if self._vars_fixes is None:
- self._vars_fixes = {'LC_NUMERIC': '', 'DEBIAN_FRONTEND': 'noninteractive'}
-
- return self._vars_fixes
-
-
-class AptitudeOutputHandler(Thread):
-
- def __init__(self, i18n: I18n, targets: Iterable[str], re_download: Pattern, watcher: ProcessWatcher,
- action: AptitudeAction):
- super(AptitudeOutputHandler, self).__init__()
- self._i18n = i18n
- self._re_download = re_download
- self._watcher = watcher
- self._targets = set(targets) if targets is not None else None
- self._unpacking = 0
- self._removing = 0
- self._downloading = 0
- self._to_process = Queue()
- self._work = True
- self._action = action
-
- def stop_working(self):
- self._work = False
-
- def handle(self, string: str):
- self._to_process.put(string)
-
- @property
- def total_targets(self) -> int:
- return len(self._targets) if self._targets else 0
-
- @property
- def processed(self) -> int:
- return self._removing if self._action == AptitudeAction.REMOVE else self._unpacking
-
- def _get_progress(self, current: int) -> str:
- if self.total_targets > 0:
- if self._action == AptitudeAction.REMOVE:
- total = self._removing
- else:
- if self.total_targets == self._unpacking:
- total = self.total_targets
- else:
- total = ceil((self._unpacking + self._downloading) / 2)
-
- return f'({total / self.total_targets * 100:.2f}%) [{current}/{self.total_targets}] '
-
- return ''
-
- def run(self):
- while self._work:
- time.sleep(0.001)
-
- if self._to_process.empty():
- continue
-
- string = self._to_process.get()
-
- if self.total_targets > 0 and self.total_targets == self._unpacking:
- self._watcher.change_substatus(self._i18n['debian.output.finishing'])
- continue
-
- if string:
- if self._action != AptitudeAction.REMOVE and string.startswith('Unpacking '):
- unpacking = string.split(' ')
-
- if len(unpacking) >= 2 and unpacking[1]:
- pkg = map_package_name(unpacking[1].strip())
-
- if self._targets and pkg in self._targets:
- self._unpacking += 1
-
- msg = f"{self._get_progress(self._unpacking)}" \
- f"{self._i18n['debian.output.unpacking'].format(pkg=bold(pkg))}"
-
- self._watcher.change_substatus(msg)
-
- continue
-
- if self._action == AptitudeAction.REMOVE and string.startswith('Removing '):
- unpacking = string.split(' ')
-
- if len(unpacking) >= 2 and unpacking[1]:
- pkg = unpacking[1].strip()
-
- if self._targets and pkg in self._targets:
- self._removing += 1
-
- msg = f"{self._get_progress(self._removing)}" \
- f"{self._i18n['debian.output.removing'].format(pkg=bold(pkg))}"
-
- self._watcher.change_substatus(msg)
-
- continue
-
- download = self._re_download.findall(string)
-
- if download:
- data = download[0].split(' ')
-
- if len(data) >= 4:
- pkg = data[3].strip()
-
- if self._targets and pkg in self._targets:
- self._downloading += 1
-
- msg = f"{self._get_progress(self._downloading)}" \
- f"{self._i18n['debian.output.downloading'].format(pkg=bold(pkg))}"
-
- self._watcher.change_substatus(msg)
-
- continue
-
- _processed = self.processed
- if self._targets and _processed > 0:
- self._watcher.change_substatus(self._get_progress(_processed).strip())
- continue
-
- self._watcher.change_substatus(' ')
-
-
-class AptitudeOutputHandlerFactory:
-
- def __init__(self, i18n: I18n):
- self._i18n = i18n
- self._re_download: Optional[Pattern] = None
-
- @property
- def re_download(self) -> Pattern:
- if self._re_download is None:
- self._re_download = re.compile(r'Get:\s+\d+\s+https?://(.+)')
-
- return self._re_download
-
- @contextmanager
- def start(self, watcher: ProcessWatcher, targets: Iterable[str], action: AptitudeAction):
- handler = AptitudeOutputHandler(i18n=self._i18n, re_download=self.re_download,
- watcher=watcher, targets=targets, action=action)
- handler.start()
-
- yield handler.handle
-
- handler.stop_working()
- handler.join()
diff --git a/bauh/gems/debian/common.py b/bauh/gems/debian/common.py
deleted file mode 100644
index 910525ea..00000000
--- a/bauh/gems/debian/common.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from typing import Dict, Optional
-
-from bauh.gems.debian.model import DebianPackage
-
-
-def strip_maintainer_email(maintainer: str) -> str:
- return maintainer.split('<')[0].strip()
-
-
-def strip_section(section: str) -> Optional[str]:
- if section:
- section_split = section.split('/')
- return section_split[1] if len(section_split) > 1 else section
-
-
-def fill_show_data(pkg: DebianPackage, data: Dict[str, object]):
- if data:
- for attr, val in data.items():
- final_attr = attr.replace(' ', '_')
-
- if not val or val == '':
- final_val = None
- else:
- if attr == 'maintainer':
- final_val = strip_maintainer_email(str(val))
- elif attr == 'section':
- final_attr = 'categories'
- final_val = (strip_section(str(val)),)
- else:
- final_val = val
-
- setattr(pkg, final_attr, final_val)
diff --git a/bauh/gems/debian/config.py b/bauh/gems/debian/config.py
deleted file mode 100644
index a81ccd3d..00000000
--- a/bauh/gems/debian/config.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from bauh.commons.config import YAMLConfigManager
-from bauh.gems.debian import CONFIG_FILE
-
-
-class DebianConfigManager(YAMLConfigManager):
-
- def __init__(self):
- super(DebianConfigManager, self).__init__(config_file_path=CONFIG_FILE)
-
- def get_default_config(self) -> dict:
- return {
- 'suggestions.exp': 24, # hours
- 'index_apps.exp': 1440, # 24 hours
- 'sync_pkgs.time': 1440, # 24 hours
- 'pkg_sources.app': None,
- 'remove.purge': False
- }
diff --git a/bauh/gems/debian/controller.py b/bauh/gems/debian/controller.py
deleted file mode 100644
index 5f1182a5..00000000
--- a/bauh/gems/debian/controller.py
+++ /dev/null
@@ -1,903 +0,0 @@
-import os.path
-import shutil
-import traceback
-from operator import attrgetter
-from pathlib import Path
-from shutil import which
-from subprocess import Popen
-from threading import Thread
-from typing import List, Optional, Tuple, Set, Type, Dict, Iterable, Generator
-
-from bauh.api.abstract.context import ApplicationContext
-from bauh.api.abstract.controller import SoftwareManager, SoftwareAction, TransactionResult, UpgradeRequirements, \
- SearchResult, UpgradeRequirement, SettingsView, SettingsController
-from bauh.api.abstract.disk import DiskCacheLoader
-from bauh.api.abstract.handler import TaskManager, ProcessWatcher
-from bauh.api.abstract.model import SoftwarePackage, PackageSuggestion, PackageUpdate, PackageHistory, \
- CustomSoftwareAction
-from bauh.api.abstract.view import TextInputComponent, PanelComponent, FormComponent, MessageType, \
- SingleSelectComponent, InputOption, SelectViewType, ViewComponentAlignment
-from bauh.api.paths import CONFIG_DIR
-from bauh.commons.html import bold
-from bauh.commons.system import ProcessHandler
-from bauh.commons.util import NullLoggerFactory
-from bauh.commons.view_utils import get_human_size_str
-from bauh.gems.debian import DEBIAN_ICON_PATH
-from bauh.gems.debian.aptitude import Aptitude, AptitudeOutputHandlerFactory, AptitudeAction
-from bauh.gems.debian.common import fill_show_data
-from bauh.gems.debian.config import DebianConfigManager
-from bauh.gems.debian.gui import DebianViewBridge
-from bauh.gems.debian.index import ApplicationIndexer, ApplicationIndexError, ApplicationsMapper
-from bauh.gems.debian.model import DebianPackage, DebianApplication
-from bauh.gems.debian.suggestions import DebianSuggestionsDownloader
-from bauh.gems.debian.tasks import UpdateApplicationIndex, MapApplications, SynchronizePackages
-
-
-class DebianPackageManager(SoftwareManager, SettingsController):
-
- def __init__(self, context: ApplicationContext):
- super(DebianPackageManager, self).__init__(context)
- self._i18n = context.i18n
- self._log = context.logger
- self._types: Optional[Set[Type[SoftwarePackage]]] = None
- self._enabled = True
- self._app_indexer: Optional[ApplicationIndexer] = None
- self._apps_index: Optional[Dict[str, DebianApplication]] = None
- self._configman: Optional[DebianConfigManager] = None
- self._action_launch_sources: Optional[CustomSoftwareAction] = None
- self._default_actions: Optional[Iterable[CustomSoftwareAction]] = None
- self._view: Optional[DebianViewBridge] = None
- self._app_mapper: Optional[ApplicationsMapper] = None
- self._aptitude: Optional[Aptitude] = None
- self._output_handler: Optional[AptitudeOutputHandlerFactory] = None
- self._known_sources_apps: Optional[Tuple[str, ...]] = None
- self._install_show_attrs: Optional[Set[str]] = None
- self._file_ignored_updates: Optional[str] = None
- self._suggestions_downloader: Optional[DebianSuggestionsDownloader] = None
-
- def _update_apps_index(self, apps: Iterable[DebianApplication]):
- self._apps_index = {app.name: app for app in apps} if apps else dict()
-
- def search(self, words: str, disk_loader: Optional[DiskCacheLoader], limit: int, is_url: bool) -> SearchResult:
- config_ = dict()
- fill_config = Thread(target=self._fill_config, args=(config_,), daemon=True)
- fill_config.start()
-
- res = SearchResult.empty()
-
- if not is_url:
- for pkg in self.aptitude.search(words):
- if fill_config.is_alive():
- fill_config.join()
-
- pkg.global_purge = bool(config_.get('remove.purge', False))
- if pkg.installed:
- pkg.bind_app(self.apps_index.get(pkg.name))
- res.installed.append(pkg)
- else:
- res.new.append(pkg)
-
- return res
-
- def _fill_ignored_updates(self, output: Set[str]):
-
- try:
- with open(self.file_ignored_updates) as f:
- ignored_str = f.read()
- except FileNotFoundError:
- return
-
- if ignored_str:
- for line in ignored_str.split('\n'):
- line_clean = line.strip()
-
- if line_clean:
- output.add(line_clean)
-
- def _fill_config(self, config_: dict):
- config_.update(self.configman.get_config())
-
- def read_installed(self, disk_loader: Optional[DiskCacheLoader], pkg_types: Optional[Set[Type[SoftwarePackage]]],
- internet_available: bool, limit: int = -1, only_apps: bool = False,
- names: Optional[Iterable[str]] = None) -> SearchResult:
-
- config_ = dict()
- fill_config = Thread(target=self._fill_config, args=(config_,), daemon=True)
- fill_config.start()
-
- ignored_updates = set()
- fill_ignored_updates = Thread(target=self._fill_ignored_updates, args=(ignored_updates,), daemon=True)
- fill_ignored_updates.start()
-
- threads = (fill_config, fill_ignored_updates)
-
- res = SearchResult(installed=[], new=None, total=0)
-
- for pkg in self.aptitude.read_installed():
- for t in threads:
- if t.is_alive():
- t.join()
-
- pkg.bind_app(self.apps_index.get(pkg.name))
- pkg.global_purge = bool(config_.get('remove.purge', False))
- pkg.updates_ignored = bool(ignored_updates and pkg.name in ignored_updates)
- res.installed.append(pkg)
-
- return res
-
- def downgrade(self, pkg: SoftwarePackage, root_password: str, handler: ProcessWatcher) -> bool:
- return False
-
- def upgrade(self, requirements: UpgradeRequirements, root_password: str, watcher: ProcessWatcher) -> bool:
- handler = ProcessHandler(watcher)
-
- targets = (r.pkg.name for r in (*requirements.to_upgrade, *(requirements.to_install or ())))
-
- with self.output_handler.start(watcher=watcher, targets=targets, action=AptitudeAction.UPGRADE) as handle:
- to_upgrade = (r.pkg.name for r in requirements.to_upgrade)
- success, _ = handler.handle_simple(self.aptitude.upgrade(packages=to_upgrade,
- root_password=root_password),
- output_handler=handle)
- return success
-
- def _fill_updates(self, output: Dict[str, str]):
- for name, version in self.aptitude.read_updates():
- output[name] = version
-
- def uninstall(self, pkg: DebianPackage, root_password: str, watcher: ProcessWatcher,
- disk_loader: Optional[DiskCacheLoader], purge: bool = False) -> TransactionResult:
-
- config_ = self.configman.get_config()
- purge_ = purge or config_.get('remove.purge', False)
-
- watcher.change_substatus(self._i18n['debian.simulate_operation'])
-
- transaction = self.aptitude.simulate_removal((pkg.name,), purge=purge_)
-
- if not transaction or not transaction.to_remove:
- return TransactionResult.fail()
-
- if pkg not in transaction.to_remove:
- watcher.show_message(title=self._i18n['popup.title.error'],
- body=self._i18n['debian.remove.impossible'].format(pkg=bold(pkg.name)),
- type_=MessageType.ERROR)
- return TransactionResult.fail()
-
- watcher.change_substatus('')
-
- deps = tuple(p for p in transaction.to_remove if p.name != pkg.name)
-
- if deps:
- # updates are required to be filled in case the dependencies are currently displayed on the view
- updates = dict()
- fill_updates = Thread(target=self._fill_updates, args=(updates,), daemon=True)
- fill_updates.start()
-
- deps_data = self.aptitude.show((p.name for p in deps), attrs=('description', 'maintainer', 'section'))
-
- if deps_data:
- for p in deps:
- fill_show_data(p, deps_data.get(p.name))
-
- if not self.view.confirm_removal(source_pkg=pkg.name, dependencies=deps, watcher=watcher):
- return TransactionResult.fail()
-
- fill_updates.join()
-
- if updates:
- for p in deps:
- latest_version = updates.get(p.name)
-
- if latest_version is not None and p.version != latest_version:
- p.latest_version = latest_version
- p.update = True
-
- watcher.change_substatus(self._i18n['debian.uninstall.removing'])
-
- handler = ProcessHandler(watcher)
- to_remove = tuple(p.name for p in transaction.to_remove)
- with self.output_handler.start(watcher=watcher, targets=to_remove, action=AptitudeAction.REMOVE) as handle:
- removed, _ = handler.handle_simple(self.aptitude.remove(packages=to_remove, root_password=root_password,
- purge=purge_),
- output_handler=handle)
-
- if not removed:
- return TransactionResult.fail()
-
- watcher.change_substatus(self._i18n['debian.uninstall.validating'])
-
- current_installed_names = set(self.aptitude.read_installed_names())
-
- watcher.change_substatus('')
-
- all_removed, apps_removed, not_removed_names = [], set(), set()
-
- for p in transaction.to_remove:
- if p.name not in current_installed_names:
- instance = p if p != pkg else pkg
-
- all_removed.append(instance)
-
- if instance.app:
- apps_removed.add(instance.app)
-
- instance.installed = False
- instance.version = instance.latest_version
- instance.update = False
- instance.bind_app(None)
- else:
- not_removed_names.add(p.name)
-
- if apps_removed: # updating apps index
- watcher.print(self._i18n['debian.app_index.updating'] + ' ...')
- watcher.change_substatus(self._i18n['debian.app_index.updating'])
- indexed_apps = set(self.app_indexer.read_index())
-
- if indexed_apps:
- new_index = indexed_apps.difference(apps_removed)
- try:
- self.app_indexer.update_index(new_index, update_timestamp=False)
- self._update_apps_index(new_index)
- self._log.info(f"Debian applications removed from the index: "
- f"{', '.join((a.name for a in apps_removed))}")
- except ApplicationIndexError:
- pass
-
- watcher.change_substatus('')
-
- success = True
- if not_removed_names:
- success = pkg.name not in not_removed_names
- not_removed_str = ', '.join((bold(p) for p in sorted(not_removed_names)))
- watcher.show_message(title=self._i18n[f"popup.title.{'warning' if success else 'error'}"],
- body=self._i18n['debian.uninstall.failed_to_remove'].format(no=len(not_removed_names),
- pkgs=not_removed_str),
- type_=MessageType.WARNING if success else MessageType.ERROR)
-
- return TransactionResult(success=success, installed=None, removed=all_removed)
-
- def _map_dependents(self, packages_data: Dict[str, Dict[str, object]]) -> Optional[Dict[str, Set[str]]]:
- if packages_data:
- dependents = None
- if packages_data:
- dependents = dict()
-
- for p, data in packages_data.items():
- for attr in ('depends', 'predepends'):
- dep_exps = data.get(attr)
-
- if isinstance(dep_exps, tuple):
- for exp in dep_exps:
- dep = exp.split(' ')[0].strip()
- dep_dependents = dependents.get(dep)
- if dep_dependents is None:
- dep_dependents = set()
- dependents[dep] = dep_dependents
-
- dep_dependents.add(p)
-
- return dependents
-
- def get_upgrade_requirements(self, pkgs: List[DebianPackage], root_password: str, watcher: ProcessWatcher) \
- -> UpgradeRequirements:
-
- transaction = self.aptitude.simulate_upgrade((p.name for p in pkgs))
-
- if transaction:
- size_to_query = (f'{p.name}={p.latest_version}' for p in (*transaction.to_upgrade,
- *transaction.to_install,
- *transaction.to_remove))
-
- update_extra_attrs = ('compressed size', *(('depends', 'predepends') if transaction.to_install else ()))
- update_data = self.aptitude.show(pkgs=size_to_query, attrs=update_extra_attrs)
-
- to_install = None
- if transaction.to_install:
- dependents = self._map_dependents(update_data)
-
- to_install = []
- for p in transaction.to_install:
- p_data = update_data.get(p.name) if update_data else None
- req_size = p_data.get('compressed size') if p_data else None
-
- reason = None
- if dependents:
- p_dependents = dependents.get(p.name)
-
- if p_dependents:
- deps_str = ', '.join((bold(d) for d in p_dependents))
- reason = self._i18n['debian.transaction.dependency_of'].format(pkgs=deps_str)
-
- to_install.append(UpgradeRequirement(pkg=p, reason=reason, required_size=req_size,
- extra_size=p.transaction_size))
-
- to_install.sort(key=attrgetter('pkg.name'))
- to_install = tuple(to_install)
-
- to_remove = None
- if transaction.to_remove:
- to_remove = []
-
- for p in transaction.to_remove:
- to_remove.append(UpgradeRequirement(pkg=p, required_size=0, extra_size=p.transaction_size))
-
- to_remove.sort(key=attrgetter('pkg.name'))
- to_remove = tuple(to_remove)
-
- to_upgrade = None
-
- if transaction.to_upgrade:
- to_upgrade = []
-
- for p in transaction.to_upgrade:
- p_data = update_data.get(p.name) if update_data else None
-
- if p_data:
- req_size = p_data.get('compressed size')
- else:
- req_size = None
-
- to_upgrade.append(UpgradeRequirement(pkg=p, required_size=req_size, extra_size=p.transaction_size))
-
- to_upgrade.sort(key=attrgetter('pkg.name'))
- to_upgrade = tuple(to_upgrade)
-
- return UpgradeRequirements(to_install=to_install, to_upgrade=to_upgrade,
- to_remove=to_remove, cannot_upgrade=None)
- else:
- cannot_upgrade = [UpgradeRequirement(pkg=p, reason=self._i18n['error']) for p in pkgs]
- cannot_upgrade.sort(key=attrgetter('pkg.name'))
- return UpgradeRequirements(cannot_upgrade=cannot_upgrade, to_install=None, to_remove=None,
- to_upgrade=[])
-
- def get_managed_types(self) -> Set[Type[SoftwarePackage]]:
- if self._types is None:
- self._types = {DebianPackage}
-
- return self._types
-
- def get_info(self, pkg: DebianPackage) -> Optional[dict]:
- info = {'00.name': pkg.name, '01.version': pkg.version,
- "02.description": pkg.description}
-
- if pkg.installed and pkg.app:
- info['03.exec'] = pkg.app.exe_path
-
- extra_info = self.aptitude.show((f'{pkg.name}={pkg.version}',), verbose=True)
-
- if extra_info:
- extra_info = extra_info.get(pkg.name)
-
- if extra_info:
- ignored_fields = {'package', 'version', 'description'}
-
- for field, val in extra_info.items():
- if field not in ignored_fields and not field.startswith('description'):
- final_val = get_human_size_str(val) if field in self.aptitude.size_attrs else val
- final_field = f'04.{field}'
-
- if final_field not in self._i18n:
- self._i18n.default[final_field] = field
-
- info[final_field] = final_val # for sorting
-
- return info
-
- def get_history(self, pkg: SoftwarePackage) -> PackageHistory:
- pass
-
- def install(self, pkg: SoftwarePackage, root_password: str, disk_loader: Optional[DiskCacheLoader],
- watcher: ProcessWatcher) -> TransactionResult:
-
- watcher.change_substatus(self._i18n['debian.simulate_operation'])
- transaction = self.aptitude.simulate_installation((pkg.name, ))
-
- if transaction is None or not transaction.to_install:
- return TransactionResult.fail()
-
- if transaction.to_remove or (transaction.to_install and len(transaction.to_install) > 1):
- watcher.change_substatus(self._i18n['debian.transaction.get_data'])
-
- deps = tuple(p for p in transaction.to_install or () if p.name != pkg.name)
- removal = tuple(p for p in transaction.to_remove or ())
- all_pkgs = [*deps, *removal]
-
- pkgs_data = self.aptitude.show(pkgs=(f'{d.name}={d.version}' for d in all_pkgs),
- attrs=self.install_show_attrs)
-
- if pkgs_data:
- for p in all_pkgs:
- fill_show_data(p, pkgs_data.get(p.name))
-
- if not self.view.confirm_transaction(to_install=deps, removal=removal, watcher=watcher):
- return TransactionResult.fail()
-
- watcher.change_substatus(self._i18n['debian.installing_pkgs'])
- handler = ProcessHandler(watcher)
-
- targets = (p.name for p in transaction.to_install)
- with self.output_handler.start(watcher=watcher, targets=targets, action=AptitudeAction.INSTALL) as handle:
- installed, _ = handler.handle_simple(self.aptitude.install(packages=(pkg.name,),
- root_password=root_password),
- output_handler=handle)
-
- if installed:
- self._refresh_apps_index(watcher)
-
- watcher.change_substatus(self._i18n['debian.install.validating'])
-
- currently_installed = set(self.aptitude.read_installed_names())
-
- installed_instances = []
- if currently_installed:
- for p in transaction.to_install:
- instance = p if p != pkg else pkg
- if instance.name in currently_installed:
- instance.installed = True
- instance.bind_app(self.apps_index.get(instance.name))
- installed_instances.append(instance)
-
- removed = None
-
- if transaction.to_remove:
- removed = [p for p in transaction.to_remove if p.name not in currently_installed]
-
- not_removed = set(transaction.to_remove).difference(removed)
-
- if not_removed:
- not_removed_str = ' '.join(p.name for p in not_removed)
- self._log.warning(f"The following packages were not removed: {not_removed_str}")
-
- return TransactionResult(installed=installed_instances, removed=removed,
- success=bool(installed_instances and pkg in installed_instances))
- else:
- watcher.change_substatus('')
- return TransactionResult.fail()
-
- def _refresh_apps_index(self, watcher: ProcessWatcher):
- watcher.change_substatus(self._i18n['debian.app_index.checking'])
- self._log.info("Reading the cached Debian applications")
- indexed_apps = self.app_indexer.read_index()
- self._log.info("Mapping the Debian applications")
- current_apps = self.app_mapper.map_executable_applications()
-
- if current_apps != indexed_apps:
- watcher.print(self._i18n['debian.app_index.updating'] + '...')
- watcher.change_substatus(self._i18n['debian.app_index.updating'])
-
- try:
- self.app_indexer.update_index(current_apps)
- self._update_apps_index(current_apps)
-
- if indexed_apps is not None:
- new_apps = current_apps.difference(indexed_apps)
-
- if new_apps:
- self._log.info(f"Debian applications added to the index: "
- f"{','.join((a.name for a in new_apps))}")
-
- except ApplicationIndexError:
- pass
-
- def is_enabled(self) -> bool:
- return self._enabled
-
- def set_enabled(self, enabled: bool):
- self._enabled = enabled
-
- def can_work(self) -> Tuple[bool, Optional[str]]:
- if not which('aptitude'):
- return False, self._i18n['missing_dep'].format(dep=bold('aptitude'))
-
- return True, None
-
- def requires_root(self, action: SoftwareAction, pkg: Optional[SoftwarePackage]) -> bool:
- if action == action.PREPARE:
- deb_config = self.configman.get_config()
- return SynchronizePackages.should_synchronize(deb_config, NullLoggerFactory.logger())
-
- return action != SoftwareAction.SEARCH
-
- def prepare(self, task_manager: Optional[TaskManager], root_password: Optional[str],
- internet_available: Optional[bool]):
-
- deb_config = self.configman.get_config()
-
- if SynchronizePackages.should_synchronize(deb_config, self._log):
- sync_pkgs = SynchronizePackages(taskman=task_manager, i18n=self._i18n, logger=self._log,
- root_password=root_password, aptitude=self.aptitude)
- sync_pkgs.start()
-
- if self.suggestions_downloader.should_download(deb_config, only_positive_exp=True):
- self.suggestions_downloader.register_task(task_manager)
- self.suggestions_downloader.start()
-
- self.index_apps(root_password=root_password, watcher=None, taskman=task_manager,
- deb_config=deb_config, check_expiration=True)
-
- def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
- ignored_updates = set()
- fill_ignored_updates = Thread(target=self._fill_ignored_updates, args=(ignored_updates,), daemon=True)
- fill_ignored_updates.start()
-
- updates = list()
- for name, version in self.aptitude.read_updates():
- if fill_ignored_updates.is_alive():
- fill_ignored_updates.join()
-
- if name not in ignored_updates:
- updates.append(PackageUpdate(pkg_id=name, name=name, version=version, pkg_type='debian'))
-
- return updates
-
- def list_warnings(self, internet_available: bool) -> Optional[List[str]]:
- pass
-
- def _fill_installed_names(self, output: Set[str]):
- output.update(self.aptitude.read_installed_names())
-
- def _fill_suggestions(self, output: Dict[str, int]):
- self.suggestions_downloader.register_task(None)
- suggestions = self.suggestions_downloader.read(self.configman.read_config())
-
- if suggestions:
- output.update(suggestions)
-
- def list_suggestions(self, limit: int, filter_installed: bool) -> Optional[List[PackageSuggestion]]:
- name_priority = dict()
-
- fill_suggestions = Thread(target=self._fill_suggestions, args=(name_priority,))
- fill_suggestions.start()
-
- if filter_installed:
- installed = set()
- fill_installed = Thread(target=self._fill_installed_names, args=(installed,), daemon=True)
- fill_installed.start()
- else:
- installed, fill_installed = None, None
-
- fill_suggestions.join()
-
- if fill_installed:
- fill_installed.join()
-
- if not name_priority:
- self._log.info("No Debian package suggestions found")
- return []
-
- self._log.info(f"Found {len(name_priority)} Debian package suggestions")
-
- to_load = tuple(name_priority.keys()) if not installed else {*name_priority.keys()}.difference(installed)
-
- if not to_load:
- return []
-
- suggestions = []
-
- for pkg in self.aptitude.search_by_name(to_load):
- prio = name_priority.get(pkg.name)
-
- if prio:
- suggestions.append(PackageSuggestion(package=pkg, priority=prio))
-
- return suggestions
-
- def is_default_enabled(self) -> bool:
- return True
-
- def launch(self, pkg: SoftwarePackage):
- if isinstance(pkg, DebianPackage):
- final_cmd = pkg.app.exe_path.replace('%U', '')
- Popen(final_cmd, shell=True)
-
- def get_settings(self) -> Optional[Generator[SettingsView, None, None]]:
- config_ = self.configman.get_config()
-
- purge_opts = [InputOption(label=self._i18n['yes'].capitalize(), value=True),
- InputOption(label=self._i18n['no'].capitalize(), value=False)]
-
- purge_current = tuple(o for o in purge_opts if o.value == bool(config_['remove.purge']))[0]
- sel_purge = SingleSelectComponent(id_='remove.purge',
- label=self._i18n['debian.config.remove.purge'],
- tooltip=self._i18n['debian.config.remove.purge.tip'],
- options=purge_opts,
- default_option=purge_current,
- type_=SelectViewType.RADIO,
- max_per_line=2)
-
- sources_app = config_.get('pkg_sources.app')
-
- if isinstance(sources_app, str) and sources_app not in self.known_sources_apps:
- self._log.warning(f"'pkg_sources.app' ({sources_app}) is not supported. A 'None' value will be considered")
- sources_app = None
-
- lb_source_auto = self._i18n['debian.config.pkg_sources.app.auto']
- source_opts = [InputOption(id_='auto', value=None, label=lb_source_auto)]
-
- source_opts.extend((InputOption(id_=a, value=a, label=a) for a in self.known_sources_apps if which(a)))
-
- source_auto_tip = self._i18n['debian.config.pkg_sources.app.tip'].format(auto=f'"{lb_source_auto}"')
- input_sources = SingleSelectComponent(id_='pkg_sources.app',
- label=self._i18n['debian.config.pkg_sources.app'],
- tooltip=source_auto_tip,
- options=source_opts,
- default_option=next(o for o in source_opts if o.value == sources_app),
- alignment=ViewComponentAlignment.CENTER,
- type_=SelectViewType.COMBO)
-
- try:
- app_cache_exp = int(config_.get('index_apps.exp', 0))
- except ValueError:
- self._log.error(f"Unexpected value form Debian configuration property 'index_apps.exp': "
- f"{config_['index_apps.exp']}. Zero (0) will be considered instead.")
- app_cache_exp = 0
-
- ti_index_apps_exp = TextInputComponent(id_='index_apps.exp',
- label=self._i18n['debian.config.index_apps.exp'],
- tooltip=self._i18n['debian.config.index_apps.exp.tip'],
- value=str(app_cache_exp), only_int=True)
-
- try:
- sync_pkgs_time = int(config_.get('sync_pkgs.time', 0))
- except ValueError:
- self._log.error(f"Unexpected value form Debian configuration property 'sync_pkgs.time': {config_['sync_pkgs.time']}. "
- f"Zero (0) will be considered instead.")
- sync_pkgs_time = 0
-
- ti_sync_pkgs = TextInputComponent(id_='sync_pkgs.time',
- label=self._i18n['debian.config.sync_pkgs.time'],
- tooltip=self._i18n['debian.config.sync_pkgs.time.tip'],
- value=str(sync_pkgs_time), only_int=True)
-
- try:
- suggestions_exp = int(config_.get('suggestions.exp', 0))
- except ValueError:
- self._log.error(f"Unexpected value form Debian configuration property 'suggestions.exp': {config_['suggestions.exp']}. "
- f"Zero (0) will be considered instead.")
- suggestions_exp = 0
-
- ti_suggestions_exp = TextInputComponent(id_='suggestions.exp',
- label=self._i18n['debian.config.suggestions.exp'],
- tooltip=self._i18n['debian.config.suggestions.exp.tip'],
- value=str(suggestions_exp), only_int=True)
-
- panel = PanelComponent([FormComponent([input_sources, sel_purge, ti_sync_pkgs, ti_index_apps_exp,
- ti_suggestions_exp])])
- yield SettingsView(self, panel)
-
- def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
- config_ = self.configman.get_config()
-
- container = component.get_component_by_idx(0, FormComponent)
-
- for prop, type_ in {'remove.purge': SingleSelectComponent,
- 'pkg_sources.app': SingleSelectComponent,
- 'index_apps.exp': TextInputComponent,
- 'sync_pkgs.time': TextInputComponent,
- 'suggestions.exp': TextInputComponent}.items():
- comp = container.get_component(prop, type_)
-
- val = None
- if isinstance(comp, SingleSelectComponent):
- val = comp.get_selected()
- elif isinstance(comp, TextInputComponent):
- val = comp.get_int_value()
-
- config_[prop] = val
-
- try:
- self.configman.save_config(config_)
- return True, None
- except Exception:
- return False, [traceback.format_exc()]
-
- def gen_custom_actions(self) -> Generator[CustomSoftwareAction, None, None]:
- if self._default_actions is None:
- self._default_actions = (CustomSoftwareAction(i18n_label_key='debian.action.sync_pkgs',
- i18n_status_key='debian.task.sync_pkgs.status',
- i18n_description_key='debian.action.sync_pkgs.desc',
- icon_path=DEBIAN_ICON_PATH,
- manager_method='synchronize_packages',
- requires_root=True),
- CustomSoftwareAction(i18n_label_key='debian.action.index_apps',
- i18n_status_key='debian.task.app_index.status',
- i18n_description_key='debian.action.index_apps.desc',
- icon_path=DEBIAN_ICON_PATH,
- manager_method='index_apps',
- requires_root=False)
- )
-
- yield from self._default_actions
-
- for _ in self.get_installed_source_apps():
- yield self.action_launch_sources
- break
-
- def _write_ignored_updates(self, packages: Iterable[str]):
- Path(os.path.dirname(self.file_ignored_updates)).mkdir(parents=True, exist_ok=True)
-
- with open(self.file_ignored_updates, 'w+') as f:
- f.write('\n'.join(n for n in sorted(packages)))
-
- def ignore_update(self, pkg: DebianPackage):
- ignored_packages = set()
- self._fill_ignored_updates(ignored_packages)
-
- if pkg.name not in ignored_packages:
- pkg.updates_ignored = True
- ignored_packages.add(pkg.name)
- self._write_ignored_updates(ignored_packages)
-
- def revert_ignored_update(self, pkg: DebianPackage):
- ignored_packages = set()
- self._fill_ignored_updates(ignored_packages)
-
- if pkg.name in ignored_packages:
- pkg.updates_ignored = False
- ignored_packages.remove(pkg.name)
- self._write_ignored_updates(ignored_packages)
-
- def synchronize_packages(self, root_password: Optional[str], watcher: ProcessWatcher) -> bool:
- return SynchronizePackages(i18n=self._i18n, logger=self._log, root_password=root_password, watcher=watcher,
- aptitude=self.aptitude, taskman=TaskManager()).run()
-
- def index_apps(self, root_password: Optional[str], watcher: Optional[ProcessWatcher],
- taskman: Optional[TaskManager] = None, deb_config: Optional[dict] = None,
- check_expiration: bool = False) -> bool:
- _config = deb_config if deb_config else self.configman.get_config()
- _taskman = taskman if taskman else TaskManager()
-
- map_apps = MapApplications(taskman=_taskman, app_indexer=self.app_indexer,
- i18n=self._i18n, logger=self._log, deb_config=deb_config,
- app_mapper=self.app_mapper, check_expiration=check_expiration,
- watcher=watcher)
- map_apps.start()
-
- gen_app_index = UpdateApplicationIndex(taskman=_taskman, app_indexer=self.app_indexer,
- i18n=self._i18n, logger=self._log,
- mapping_apps=map_apps)
- gen_app_index.start()
-
- map_apps.join()
- self._update_apps_index(map_apps.apps)
- gen_app_index.join()
- return True
-
- def purge(self, pkg: DebianPackage, root_password: str, watcher: ProcessWatcher) -> bool:
- if not self.view.confirm_purge(pkg.name, watcher):
- return False
-
- res = self.uninstall(pkg=pkg, root_password=root_password, watcher=watcher, disk_loader=None, purge=True)
- return res.success
-
- def launch_sources_app(self, root_password: str, watcher: ProcessWatcher) -> bool:
- deb_config = self.configman.get_config()
-
- sources_app = deb_config.get('pkg_sources.app')
-
- if isinstance(sources_app, str) and sources_app not in self.known_sources_apps:
- watcher.show_message(title=self._i18n['popup.title.error'],
- body=self._i18n['debian.action.sources.unsupported'].format(app=bold(sources_app)))
- return False
-
- if sources_app:
- if not which(sources_app):
- watcher.show_message(title=self._i18n['popup.title.error'],
- body=self._i18n['debian.action.sources.not_installed'],
- type_=MessageType.ERROR)
- return False
-
- Popen(sources_app, shell=True)
- return True
-
- for app in self.get_installed_source_apps():
- Popen(app, shell=True)
- return True
-
- watcher.show_message(title=self._i18n['popup.title.error'],
- body=self._i18n['debian.action.sources.not_installed'],
- type_=MessageType.ERROR)
- return False
-
- @property
- def app_indexer(self) -> ApplicationIndexer:
- if self._app_indexer is None:
- self._app_indexer = ApplicationIndexer(self._log)
-
- return self._app_indexer
-
- @property
- def apps_index(self) -> Dict[str, DebianApplication]:
- if self._apps_index is None:
- self._update_apps_index(self.app_indexer.read_index())
-
- return self._apps_index
-
- @property
- def install_show_attrs(self) -> Set[str]:
- if self._install_show_attrs is None:
- self._install_show_attrs = {'description', 'maintainer', 'section', 'compressed size'}
-
- return self._install_show_attrs
-
- @property
- def configman(self) -> DebianConfigManager:
- if self._configman is None:
- self._configman = DebianConfigManager()
-
- return self._configman
-
- @property
- def view(self) -> DebianViewBridge:
- if self._view is None:
- self._view = DebianViewBridge(screen_width=self.context.screen_width,
- screen_heigth=self.context.screen_height,
- i18n=self._i18n)
-
- return self._view
-
- @property
- def app_mapper(self) -> ApplicationsMapper:
- if self._app_mapper is None:
- self._app_mapper = ApplicationsMapper(logger=self._log)
-
- return self._app_mapper
-
- @property
- def aptitude(self) -> Aptitude:
- if self._aptitude is None:
- self._aptitude = Aptitude(self._log)
-
- return self._aptitude
-
- @property
- def output_handler(self) -> AptitudeOutputHandlerFactory:
- if self._output_handler is None:
- self._output_handler = AptitudeOutputHandlerFactory(i18n=self._i18n)
-
- return self._output_handler
-
- @property
- def action_launch_sources(self) -> CustomSoftwareAction:
- if self._action_launch_sources is None:
- self._action_launch_sources = CustomSoftwareAction(i18n_label_key='debian.action.sources',
- i18n_status_key='debian.task.sources.status',
- i18n_description_key='debian.action.sources.desc',
- icon_path=DEBIAN_ICON_PATH,
- manager_method='launch_sources_app',
- requires_confirmation=False,
- requires_root=False)
-
- return self._action_launch_sources
-
- @property
- def known_sources_apps(self) -> Tuple[str, ...]:
- if self._known_sources_apps is None:
- self._known_sources_apps = ('software-properties-gtk',)
-
- return self._known_sources_apps
-
- @property
- def file_ignored_updates(self) -> str:
- if self._file_ignored_updates is None:
- self._file_ignored_updates = f'{CONFIG_DIR}/debian/updates_ignored.txt'
-
- return self._file_ignored_updates
-
- @property
- def suggestions_downloader(self) -> DebianSuggestionsDownloader:
- if not self._suggestions_downloader:
- file_url = self.context.get_suggestion_url(self.__module__)
- self._suggestions_downloader = DebianSuggestionsDownloader(i18n=self._i18n, logger=self._log,
- http_client=self.context.http_client,
- file_url=file_url)
-
- if self._suggestions_downloader.is_local_suggestions_file():
- self._log.info(f"Local Debian suggestions file mapped: {file_url}")
-
- return self._suggestions_downloader
-
- def get_installed_source_apps(self) -> Generator[str, None, None]:
- for app in self.known_sources_apps:
- if shutil.which(app):
- yield app
diff --git a/bauh/gems/debian/gui.py b/bauh/gems/debian/gui.py
deleted file mode 100644
index 8d7af964..00000000
--- a/bauh/gems/debian/gui.py
+++ /dev/null
@@ -1,142 +0,0 @@
-from operator import attrgetter
-from typing import Collection, Optional, Tuple, List
-
-from bauh.api.abstract.handler import ProcessWatcher
-from bauh.api.abstract.view import InputOption, MultipleSelectComponent, TextComponent
-from bauh.commons.html import bold
-from bauh.commons.view_utils import get_human_size_str
-from bauh.gems.debian import DEBIAN_ICON_PATH
-from bauh.gems.debian.model import DebianPackage
-from bauh.view.util.translation import I18n
-
-
-class DebianViewBridge:
-
- def __init__(self, screen_width: int, screen_heigth: int, i18n: I18n):
- self._i18n = i18n
- self._width = screen_width
- self._height = screen_heigth
-
- @staticmethod
- def _map_to_install(pkgs: Optional[Collection[DebianPackage]]) -> Optional[Tuple[List[InputOption], str, str]]:
- if pkgs:
- download_size, install_size = 0, 0
-
- views = []
- for p in pkgs:
- if p.compressed_size is not None and p.compressed_size >= 0:
- compressed = get_human_size_str(p.compressed_size)
- download_size += p.compressed_size
-
- else:
- compressed = '?'
-
- if p.transaction_size is not None:
- install_size += p.transaction_size
- uncompressed = get_human_size_str(p.transaction_size)
- else:
- uncompressed = '?'
-
- views.append(InputOption(label=f"{p.name} ({uncompressed} | {compressed})",
- value=p.name, read_only=True, icon_path=DEBIAN_ICON_PATH,
- tooltip=p.description if p.description else '?'))
-
- dsize = get_human_size_str(download_size) if download_size > 0 else '?'
- isize = get_human_size_str(install_size) if install_size > 0 else '?'
- return views, isize, dsize
-
- def _map_to_remove(self, pkgs: Optional[Collection[DebianPackage]]) -> Optional[Tuple[List[InputOption], str]]:
- if pkgs:
- freed_space = 0
-
- views = []
- for p in pkgs:
- if p.transaction_size is not None:
- size = p.transaction_size * (-1 if p.transaction_size < 0 else 1)
- freed_space += size
- uncompressed = get_human_size_str(size)
- else:
- uncompressed = '?'
-
- views.append(InputOption(label=f"{p.name} (-{uncompressed})",
- value=p.name, read_only=True, icon_path=DEBIAN_ICON_PATH,
- tooltip=p.description if p.description else '?'))
-
- return views, f'-{get_human_size_str(freed_space)}' if freed_space > 0 else '?'
-
- def confirm_transaction(self, to_install: Optional[Collection[DebianPackage]],
- removal: Optional[Collection[DebianPackage]],
- watcher: ProcessWatcher) -> bool:
-
- components = []
-
- to_remove_data = self._map_to_remove(removal)
-
- text_width, select_width = 672, 595
-
- if to_remove_data:
- to_remove_data[0].sort(key=attrgetter('label'))
- lb_rem = self._i18n['debian.transaction.to_remove'].format(no=bold(str(len(to_remove_data[0]))),
- fspace=bold(to_remove_data[1]))
-
- components.append(TextComponent(html=lb_rem, min_width=text_width))
- components.append(MultipleSelectComponent(id_='rem', options=to_remove_data[0], label=None,
- default_options={*to_remove_data[0]},
- max_width=select_width))
-
- to_install_data = self._map_to_install(to_install)
-
- if to_install_data:
- to_install_data[0].sort(key=attrgetter('label'))
- lb_deps = self._i18n['debian.transaction.to_install'].format(no=bold(str(len(to_install_data[0]))),
- dsize=bold(to_install_data[2]),
- isize=bold(to_install_data[1]))
-
- components.append(TextComponent(html=f' {lb_deps}', min_width=text_width))
- components.append(MultipleSelectComponent(id_='inst', label='', options=to_install_data[0],
- default_options={*to_install_data[0]},
- max_width=select_width))
-
- return watcher.request_confirmation(title=self._i18n['debian.transaction.title'],
- components=components,
- confirmation_label=self._i18n['popup.button.continue'],
- deny_label=self._i18n['popup.button.cancel'],
- body=None,
- min_width=text_width,
- min_height=54)
-
- def confirm_removal(self, source_pkg: str, dependencies: Collection[DebianPackage], watcher: ProcessWatcher) -> bool:
- dep_views = []
- freed_space = 0
- for p in sorted(dependencies, key=attrgetter('name')):
- if p.transaction_size is not None:
- size = p.transaction_size * (-1 if p.transaction_size < 0 else 1)
- freed_space += size
- size_str = get_human_size_str(size)
- else:
- size_str = '?'
-
- dep_views.append(InputOption(label=f"{p.name}: -{size_str}", value=p.name, read_only=True,
- icon_path=DEBIAN_ICON_PATH, tooltip=p.description))
-
- deps_container = MultipleSelectComponent(id_='deps', label='', options=dep_views, default_options={*dep_views},
- max_width=537)
-
- freed_space_str = bold('-' + get_human_size_str(freed_space))
- body_text = TextComponent(html=self._i18n['debian.remove_deps'].format(no=bold(str(len(dependencies))),
- pkg=bold(source_pkg),
- fspace=freed_space_str),
- min_width=653)
-
- return watcher.request_confirmation(title=self._i18n['debian.transaction.title'],
- components=[body_text, deps_container],
- confirmation_label=self._i18n['popup.button.continue'],
- deny_label=self._i18n['popup.button.cancel'],
- min_height=200,
- body=None)
-
- def confirm_purge(self, pkg_name: str, watcher: ProcessWatcher) -> bool:
- msg = self._i18n['debian.action.purge.confirmation'].format(pkg=bold(pkg_name))
- return watcher.request_confirmation(title=self._i18n['debian.action.purge'],
- body=msg,
- confirmation_label=self._i18n['popup.button.continue'])
diff --git a/bauh/gems/debian/index.py b/bauh/gems/debian/index.py
deleted file mode 100644
index 75e1d855..00000000
--- a/bauh/gems/debian/index.py
+++ /dev/null
@@ -1,223 +0,0 @@
-import json
-import os
-import re
-import traceback
-from concurrent.futures import ThreadPoolExecutor
-from datetime import datetime, timedelta, timezone
-from json import JSONDecodeError
-from logging import Logger
-from pathlib import Path
-from typing import Optional, Set, Generator, Iterable
-
-from bauh.commons import system
-from bauh.gems.debian import APP_INDEX_FILE
-from bauh.gems.debian.model import DebianApplication
-
-
-class ApplicationIndexError(Exception):
-
- def __init__(self, cause: Optional[str] = None):
- self.cause = cause
-
-
-class ApplicationIndexer:
-
- def __init__(self, logger: Logger, index_file_path: str = APP_INDEX_FILE):
- self._log = logger
- self._file_path = index_file_path
- self._file_timestamp_path = f'{self._file_path}.ts'
-
- def is_expired(self, deb_config: dict) -> bool:
-
- try:
- exp_minutes = int(deb_config.get('index_apps.exp', 0))
- except ValueError:
- self._log.error(f"Invalid value for Debian configuration property 'index_apps.exp': "
- f"{deb_config['index_apps.exp']}")
- return True
-
- if exp_minutes <= 0:
- self._log.warning("Debian applications index will always be updated ('index_apps.exp' <= 0 )'")
- return True
-
- if not os.path.exists(self._file_path):
- self._log.info(f"Debian applications index not found. A new one must be generated ({self._file_path})")
- return True
-
- try:
- with open(self._file_timestamp_path) as f:
- timestamp_str = f.read().strip()
- except FileNotFoundError:
- self._log.info(f"Debian applications index timestamp not found ({self._file_timestamp_path})")
- return True
-
- try:
- timestamp = datetime.fromtimestamp(float(timestamp_str), tz=timezone.utc)
- except Exception:
- self._log.error(f'Could not parse the Debian applications index timestamp: {timestamp_str} '
- f'({self._file_timestamp_path})')
- traceback.print_exc()
- return True
-
- expired = timestamp + timedelta(minutes=exp_minutes) <= datetime.now(timezone.utc)
-
- if expired:
- self._log.info("Debian applications index has expired. A new one must be generated.")
- else:
- self._log.info("Debian applications index is up-to-date")
-
- return expired
-
- def read_index(self) -> Generator[DebianApplication, None, None]:
- try:
- with open(self._file_path) as f:
- idx_str = f.read().strip()
-
- if not idx_str:
- self._log.warning(f"Debian applications index is empty ({self._file_path})")
- else:
- try:
- for name, data in json.loads(idx_str).items():
- exe_path, icon_path = data.get('exe_path'), data.get('icon_path')
-
- if not all((name, exe_path, icon_path)):
- self._log.warning(f"Invalid entry in the Debian applications index ({self._file_path}): name={name}, exe_path={exe_path}, icon_path={icon_path}")
- else:
- categories = data.get('categories')
- yield DebianApplication(name=name, exe_path=exe_path, icon_path=icon_path,
- categories=tuple(categories) if categories else None)
-
- except JSONDecodeError:
- self._log.error(f"The Debian applications index is corrupted ({self._file_path}). "
- f"Could not decode the JSON.")
-
- except FileNotFoundError:
- self._log.warning(f"Debian applications index not found ({self._file_path})")
- except OSError as e:
- self._log.error(f"Debian applications index could not be read ({self._file_path}). OSError: {e.errno}")
-
- def update_index(self, apps: Set[DebianApplication], update_timestamp: bool = True):
- idx_dir = os.path.dirname(self._file_path)
-
- try:
- Path(idx_dir).mkdir(exist_ok=True, parents=True)
- except OSError:
- self._log.error(f"Could not create directory '{idx_dir}'")
- raise ApplicationIndexError()
-
- idx = {}
- if apps:
- for app in apps:
- idx.update(app.to_index())
-
- try:
- with open(self._file_path, 'w+') as f:
- if idx:
- f.write(json.dumps(idx, sort_keys=True, indent=4))
- else:
- f.write('')
-
- except OSError:
- self._log.error(f"Could not write to the Debian applications index file: {self._file_path}")
- raise ApplicationIndexError()
-
- if update_timestamp:
- index_timestamp = datetime.now(timezone.utc).timestamp()
- try:
- with open(self._file_timestamp_path, 'w+') as f:
- f.write(str(index_timestamp))
-
- self._log.info("Debian applications index timestamp updated")
-
- except OSError:
- self._log.error(f"Could not write to the Debian applications index timestamp file: "
- f"{self._file_timestamp_path}")
- raise ApplicationIndexError()
-
-
-class ApplicationsMapper:
-
- def __init__(self, logger: Logger, workers: int = 10):
- self._log = logger
- self._re_desktop_file = re.compile(r'(.+):\s+(/usr/share/applications/.+\.desktop)')
- self._re_desktop_file_fields = re.compile(r'(Exec|TryExec|Icon|Categories|NoDisplay|Terminal)\s*=\s*(.+)')
- self._workers = workers
-
- def _read_file(self, file_path: str) -> Optional[str]:
- try:
- with open(file_path) as file:
- return file.read()
- except (FileNotFoundError, OSError) as e:
- self._log.error(f"Error when checking desktop file '{file_path}' ({file_path}):"
- f" {e.__class__.__name__}")
-
- def _add_if_application_desktop_file(self, pkg_name: str, desktop_files: Iterable[str], output: Set[DebianApplication]):
- for file_path in sorted(desktop_files):
- content = self._read_file(file_path)
-
- if content:
- data = {}
-
- gui_app = True
-
- for f, v in self._re_desktop_file_fields.findall(content):
- if f in ('NoDisplay', 'Terminal') and v.strip().lower() == 'true':
- gui_app = False
- break
-
- if f not in data:
- data[f.strip()] = v.strip()
-
- if not gui_app:
- continue
-
- exe = data.get('Exec')
-
- if not exe:
- exe = data.get('TryExec')
-
- if not exe:
- continue
-
- icon = data.get('Icon')
-
- if not icon:
- continue
-
- categories = data.get('Categories')
-
- if categories:
- categories = tuple(sorted({c.strip() for c in categories.split(';') if c}))
-
- output.add(DebianApplication(name=pkg_name, exe_path=exe, icon_path=icon, categories=categories))
- break
-
- def map_executable_applications(self) -> Optional[Set[DebianApplication]]:
- exitcode, output = system.execute('dpkg-query -S .desktop', shell=True)
-
- if exitcode == 0 and output:
-
- pkg_files = dict()
-
- for found in self._re_desktop_file.findall(output):
- pkg_name = found[0].strip()
- files = pkg_files.get(pkg_name)
-
- if files is None:
- files = set()
- pkg_files[pkg_name] = files
-
- files.add(found[1].strip())
-
- if pkg_files:
- apps_found, check_jobs = set(), []
-
- with ThreadPoolExecutor(self._workers) as pool:
- for pkg_name, files in pkg_files.items():
- check_jobs.append(pool.submit(self._add_if_application_desktop_file,
- pkg_name, files, apps_found))
-
- for job in check_jobs:
- job.done()
-
- return apps_found
diff --git a/bauh/gems/debian/model.py b/bauh/gems/debian/model.py
deleted file mode 100644
index e506a373..00000000
--- a/bauh/gems/debian/model.py
+++ /dev/null
@@ -1,172 +0,0 @@
-from typing import Optional, Tuple, Collection, Iterable, Generator
-
-from bauh.api.abstract.model import SoftwarePackage, CustomSoftwareAction
-from bauh.commons import resource
-from bauh.gems.debian import DEBIAN_ICON_PATH, ROOT_DIR
-
-
-class DebianApplication:
- """
- For packages that represent applications
- """
-
- def __init__(self, name: str, exe_path: str, icon_path: str, categories: Optional[Tuple] = None):
- self.name = name
- self.exe_path = exe_path
- self.icon_path = icon_path
- self.categories = categories
-
- def __eq__(self, other):
- if isinstance(other, DebianApplication):
- return self.__dict__ == other.__dict__
-
- return False
-
- def __hash__(self) -> int:
- hash_sum = 0
-
- for k, v in self.__dict__.items():
- hash_sum += hash(v)
-
- return hash_sum
-
- def __repr__(self):
- return f"{self.__class__.__name__} ({', '.join((f'{k}={v}' for k, v in self.__dict__.items()))})"
-
- def to_index(self) -> dict:
- return {self.name: {f: v for f, v in self.__dict__.items() if f != 'name'}}
-
-
-class DebianPackage(SoftwarePackage):
-
- __actions_purge: Optional[Tuple[CustomSoftwareAction, ...]] = None
-
- @classmethod
- def actions_purge(cls) -> Tuple[CustomSoftwareAction, ...]:
- if cls.__actions_purge is None:
- cls.__actions_purge = (CustomSoftwareAction(i18n_label_key='debian.action.purge',
- i18n_status_key='debian.action.purge.status',
- i18n_description_key='debian.action.purge.desc',
- icon_path=resource.get_path('img/clean.svg', ROOT_DIR),
- manager_method='purge',
- requires_root=True,
- requires_confirmation=False),)
-
- return cls.__actions_purge
-
- def __init__(self, name: str = None, version: Optional[str] = None, latest_version: Optional[str] = None,
- description: Optional[str] = None, maintainer: Optional[str] = None, installed: bool = False,
- update: bool = False, app: Optional[DebianApplication] = None, compressed_size: Optional[int] = None,
- uncompressed_size: Optional[int] = None, categories: Tuple[str] = None,
- updates_ignored: Optional[bool] = None, transaction_size: Optional[float] = None,
- global_purge: bool = False):
- super(DebianPackage, self).__init__(id=name, name=name, version=version, installed=installed,
- description=description, update=update,
- latest_version=latest_version if latest_version is not None else version)
- self.maintainer = maintainer
- self.compressed_size = compressed_size
- self.uncompressed_size = uncompressed_size
- self.categories = categories
- self.app = app
- self.bind_app(app)
- self.updates_ignored = updates_ignored
- self.transaction_size = transaction_size # size in bytes related to a transaction (install, upgrade, remove)
- self.global_purge = global_purge # if global purge is already enabled
-
- def bind_app(self, app: Optional[DebianApplication]):
- self.app = app
-
- if app and app.categories:
- self.categories = app.categories
-
- def has_history(self) -> bool:
- return False
-
- def has_screenshots(self) -> bool:
- return False
-
- def has_info(self) -> bool:
- return True
-
- def can_be_downgraded(self) -> bool:
- return False
-
- def get_type(self):
- return 'debian'
-
- def get_default_icon_path(self) -> str:
- return self.get_type_icon_path()
-
- def get_type_icon_path(self) -> str:
- return DEBIAN_ICON_PATH
-
- def is_application(self):
- return bool(self.app)
-
- def get_data_to_cache(self) -> dict:
- pass
-
- def fill_cached_data(self, data: dict):
- pass
-
- def can_be_run(self) -> bool:
- return bool(self.app)
-
- def get_publisher(self) -> str:
- return self.maintainer
-
- def supports_backup(self) -> bool:
- return True
-
- def get_disk_icon_path(self) -> Optional[str]:
- if self.app:
- return self.app.icon_path
-
- def get_custom_actions(self) -> Optional[Iterable[CustomSoftwareAction]]:
- if self.installed and not self.global_purge:
- return self.actions_purge()
-
- def is_update_ignored(self) -> bool:
- return bool(self.updates_ignored)
-
- def supports_ignored_updates(self) -> bool:
- return True
-
- def is_trustable(self) -> bool:
- return True
-
- def __eq__(self, other):
- if isinstance(other, DebianPackage):
- return self.name == other.name
-
- return False
-
- def __hash__(self):
- return hash(self.name)
-
- def __repr__(self) -> str:
- attrs = ', '.join((f'{p}={v}' for p, v in sorted(self.__dict__.items())))
- return f"{self.__class__.__name__} ({attrs})"
-
-
-class DebianTransaction:
-
- def __init__(self, to_install: Optional[Collection[DebianPackage]],
- to_remove: Optional[Collection[DebianPackage]],
- to_upgrade: Optional[Collection[DebianPackage]]):
-
- self.to_install = to_install
- self.to_remove = to_remove
- self.to_upgrade = to_upgrade
-
- @property
- def all_packages(self) -> Generator[DebianPackage, None, None]:
- for pkgs in (self.to_install, self.to_remove, self.to_upgrade):
- if pkgs:
- yield from pkgs
-
- def __eq__(self, other) -> bool:
- return self.__dict__ == other.__dict__ if isinstance(other, DebianTransaction) else False
-
- def __hash__(self) -> int:
- return sum((hash(v)for v in self.__dict__.values()))
diff --git a/bauh/gems/debian/resources/__init__.py b/bauh/gems/debian/resources/__init__.py
deleted file mode 100755
index e69de29b..00000000
diff --git a/bauh/gems/debian/resources/img/__init__.py b/bauh/gems/debian/resources/img/__init__.py
deleted file mode 100755
index e69de29b..00000000
diff --git a/bauh/gems/debian/resources/img/clean.svg b/bauh/gems/debian/resources/img/clean.svg
deleted file mode 100644
index fba112a9..00000000
--- a/bauh/gems/debian/resources/img/clean.svg
+++ /dev/null
@@ -1,158 +0,0 @@
-
-
diff --git a/bauh/gems/debian/resources/img/debian.svg b/bauh/gems/debian/resources/img/debian.svg
deleted file mode 100644
index c112ee02..00000000
--- a/bauh/gems/debian/resources/img/debian.svg
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/__init__.py b/bauh/gems/debian/resources/locale/__init__.py
deleted file mode 100755
index e69de29b..00000000
diff --git a/bauh/gems/debian/resources/locale/ca b/bauh/gems/debian/resources/locale/ca
deleted file mode 100644
index efbe7fc8..00000000
--- a/bauh/gems/debian/resources/locale/ca
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=Index applications
-debian.action.index_apps.desc=Identifies all installed packages associated with .desktop files and maps them as applications
-debian.action.purge=Remove completely
-debian.action.purge.confirmation=The complete removal of {pkg} will erase the software files and also the configuration ones
-debian.action.purge.desc=Removes all software and configuration files associated with the package
-debian.action.purge.status=Removing {} completely
-debian.action.sync_pkgs=Synchronize packages
-debian.action.sync_pkgs.desc=Synchronizes the available software packages on the repositories
-debian.action.sync_pkgs.status=Synchronizing packages
-debian.action.sources=Software sources
-debian.action.sources.desc=Starts the application for managing software sources
-debian.action.sources.not_installed=The application for managing software sources is not installed
-debian.action.sources.status=Launching application
-debian.action.sources.unsupported=The application {app} is not supported and will not be started
-debian.app_index.checking=Checking the apps index
-debian.app_index.updating=Updating the apps index
-debian.config.index_apps.exp=Apps cache expiration
-debian.config.index_apps.exp.tip=Time period in MINUTES in which the installed applications cache is considered up-to-date during startup
-debian.config.pkg_sources.app=Software sources
-debian.config.pkg_sources.app.tip=Application for managing the software sources. {auto} detects one of the supported applications automatically.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Complete removal
-debian.config.remove.purge.tip=If the package configurations should be removed during the uninstallation process
-debian.config.suggestions.exp=Suggestions expiration
-debian.config.suggestions.exp.tip=It defines the period (in hours) in which the suggestions stored in disc will be considered up to date. Use 0 if you always want to update them.
-debian.config.sync_pkgs.time=Packages synchronization period
-debian.config.sync_pkgs.time.tip=Time period in MINUTES in which the packages synchronization must be done on startup
-debian.info.00.name=name
-debian.info.01.version=version
-debian.info.02.description=description
-debian.info.03.exec=executable
-debian.info.04.architecture=architecture
-debian.info.04.architecture.all=all
-debian.info.04.archive=archive
-debian.info.04.automatically installed=automatically installed
-debian.info.04.automatically installed.no=no
-debian.info.04.automatically installed.yes=yes
-debian.info.04.breaks=breaks
-debian.info.04.compressed size=Download size
-debian.info.04.conflicts=conflicts
-debian.info.04.depends=dependencies
-debian.info.04.filename=file
-debian.info.04.homepage=web page
-debian.info.04.maintainer=maintainer
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=multi-architecture
-debian.info.04.multi-arch.foreign=foreign
-debian.info.04.multi-arch.same=same
-debian.info.04.replaces=replaces
-debian.info.04.predepends=pre dependencies
-debian.info.04.priority=priority
-debian.info.04.priority.important=important
-debian.info.04.priority.optional=optional
-debian.info.04.provided by=provided by
-debian.info.04.provides=provides
-debian.info.04.recommends=recommends
-debian.info.04.section=section
-debian.info.04.state=state
-debian.info.04.state.installed=installed
-debian.info.04.state.not installed=not installed
-debian.info.04.state.not installed (configuration files remain)=not installed (configuration files installed)
-debian.info.04.suggests=suggests
-debian.info.04.uncompressed size=installation size
-debian.install.validating=Validating installed packages
-debian.installing_pkgs=Installing packages
-debian.output.downloading=Downloading {pkg}
-debian.output.removing=Removing {pkg}
-debian.output.finishing=Finishing
-debian.output.unpacking=Unpacking {pkg}
-debian.remove.impossible=It is not possible to remove the package {pkg}
-debian.remove_deps=The following {no} dependent packages of {pkg} will be removed as well ({fspace})
-debian.simulate_operation=Simulating the operation
-debian.task.app_index.status=Indexing installed applications
-debian.task.map_apps.check_files=Checking {type} files
-debian.task.map_apps.read_cache=Reading apps from the index (cache)
-debian.task.map_apps.status=Mapping installed applications
-debian.task.update_apps_idx.status=Updating index
-debian.task.sync_pkgs.status=Synchronizing packages
-debian.transaction.dependency_of=Dependency of {pkgs}
-debian.transaction.get_data=Retrieving the operation's data
-debian.transaction.title=Operation details
-debian.transaction.to_install=The following additional packages ({no}) will be installed (Installation: {isize} | Download: {dsize})
-debian.transaction.to_remove=The following packages ({no}) will be removed (Freed space: {fspace})
-debian.uninstall.failed_to_remove=It was not possible to remove the following {no} packages: {pkgs}
-debian.uninstall.removing=Removing packages
-debian.uninstall.validating=Validating removed packages
-gem.debian.info=Software packages for Debian-based systems
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/de b/bauh/gems/debian/resources/locale/de
deleted file mode 100644
index 498f71cc..00000000
--- a/bauh/gems/debian/resources/locale/de
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=Anwendungen indexieren
-debian.action.index_apps.desc=Identifiziert alle installierten Pakete, die mit .desktop-Dateien verbunden sind, und ordnet sie als Anwendungen zu
-debian.action.purge=Vollständig entfernen
-debian.action.purge.confirmation=Das vollständige Entfernen von {pkg} löscht sowohl die Software- als auch die Konfigurationsdateien
-debian.action.purge.desc=Entfernt alle Software- und Konfigurationsdateien, die mit dem Paket zusammenhängen
-debian.action.purge.status=Vollständiges Entfernen von {}
-debian.action.sync_pkgs=Pakete synchronisieren
-debian.action.sync_pkgs.desc=Synchronisiert die verfügbaren Softwarepakete mit den Repositories
-debian.action.sync_pkgs.status=Synchronisierung der Pakete
-debian.action.sources=Software-Quellen
-debian.action.sources.desc=Startet die Anwendung zur Verwaltung von Softwarequellen
-debian.action.sources.not_installed=Die Anwendung zur Verwaltung von Softwarequellen ist nicht installiert
-debian.action.sources.status=Starten der Anwendung
-debian.action.sources.unsupported=Die Anwendung {app} wird nicht unterstützt und kann nicht gestartet werden
-debian.app_index.checking=Überprüfen des Apps-Index
-debian.app_index.updating=Aktualisieren des Apps-Index
-debian.config.index_apps.exp=Ablauf des Apps-Caches
-debian.config.index_apps.exp.tip=Zeitspanne in MINUTEN, in der der Cache der installierten Anwendungen beim Starten als aktuell angesehen wird
-debian.config.pkg_sources.app=Softwarequellen
-debian.config.pkg_sources.app.tip=Anwendung zur Verwaltung der Softwarequellen. {auto} erkennt eine der unterstützten Anwendungen automatisch.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Vollständige Entfernung
-debian.config.remove.purge.tip=Ob die Paketkonfigurationen während des Deinstallationsvorgangs entfernt werden sollen
-debian.config.suggestions.exp=Ablauf der Vorschläge
-debian.config.suggestions.exp.tip=Er definiert den Zeitraum (in Stunden), in dem die, auf dem Datenträger gespeicherten, Vorschläge als aktuell angesehen werden. Verwenden Sie 0, wenn Sie sie immer aktualisieren wollen.
-debian.config.sync_pkgs.time=Zeitraum für die Synchronisierung der Pakete
-debian.config.sync_pkgs.time.tip=Zeitspanne in MINUTEN, in der die Pakete beim Start synchronisiert werden müssen
-debian.info.00.name=Name
-debian.info.01.version=Version
-debian.info.02.description=Beschreibung
-debian.info.03.exec=ausführbar
-debian.info.04.architecture=Architektur
-debian.info.04.architecture.all=alle
-debian.info.04.archive=Archiv
-debian.info.04.automatically installed=automatisch installiert
-debian.info.04.automatically installed.no=nein
-debian.info.04.automatically installed.yes=ja
-debian.info.04.breaks=bricht
-debian.info.04.compressed size=Download-Größe
-debian.info.04.conflicts=Konflikte
-debian.info.04.depends=Abhängigkeiten
-debian.info.04.filename=Datei
-debian.info.04.homepage=Internetseite
-debian.info.04.maintainer=Verwalter
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=Multi-Architektur
-debian.info.04.multi-arch.foreign=fremd
-debian.info.04.multi-arch.same=gleich
-debian.info.04.replaces=ersetzt
-debian.info.04.predepends=Vorabhängigkeiten
-debian.info.04.priority=Priorität
-debian.info.04.priority.important=wichtig
-debian.info.04.priority.optional=optional
-debian.info.04.provided by=bereitgestellt von
-debian.info.04.provides=bietet
-debian.info.04.recommends=empfiehlt
-debian.info.04.section=Abschnitt
-debian.info.04.state=Status
-debian.info.04.state.installed=installiert
-debian.info.04.state.not installed=nicht installiert
-debian.info.04.state.not installed (configuration files remain)=nicht installiert (Konfigurationsdateien installiert)
-debian.info.04.suggests=empfiehlt
-debian.info.04.uncompressed size=Installationsgröße
-debian.install.validating=Überprüfung der installierten Pakete
-debian.installing_pkgs=Installieren von Paketen
-debian.output.downloading=Herunterladen von {pkg}
-debian.output.finishing=Fertigstellung
-debian.output.removing=Entfernen von {pkg}
-debian.output.unpacking=Entpacken {pkg}
-debian.remove.impossible=Es ist nicht möglich, das Paket {pkg} zu entfernen
-debian.remove_deps=Die folgenden {no} abhängigen Pakete von {pkg} werden ebenfalls entfernt ({fspace})
-debian.simulate_operation=Simulation des Vorgangs
-debian.task.app_index.status=Indexierung der installierten Anwendungen
-debian.task.map_apps.check_files=Überprüfung von {type} Dateien
-debian.task.map_apps.read_cache=Lesen von Anwendungen aus dem Index (Cache)
-debian.task.map_apps.status=Zuordnung der installierten Anwendungen
-debian.task.update_apps_idx.status=Aktualisieren des Index
-debian.task.sync_pkgs.status=Synchronisierung der Pakete
-debian.transaction.dependency_of=Abhängigkeit von {pkgs}
-debian.transaction.get_data=Abrufen der Daten des Vorgangs
-debian.transaction.title=Details zum Vorgang
-debian.transaction.to_install=Die folgenden zusätzlichen Pakete ({no}) werden installiert (Installation: {isize} | Download: {dsize})
-debian.transaction.to_remove=Die folgenden Pakete ({no}) werden entfernt (Freigegebener Speicherplatz: {fspace})
-debian.uninstall.failed_to_remove=Es war nicht möglich, die folgenden Pakete ({no}) zu entfernen: {pkgs}
-debian.uninstall.removing=Entfernen von Paketen
-debian.uninstall.validating=Validierung entfernter Pakete
-gem.debian.info=Softwarepakete für Debian-basierte Systeme
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/en b/bauh/gems/debian/resources/locale/en
deleted file mode 100644
index 401e485a..00000000
--- a/bauh/gems/debian/resources/locale/en
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=Index applications
-debian.action.index_apps.desc=Identifies all installed packages associated with .desktop files and maps them as applications
-debian.action.purge=Remove completely
-debian.action.purge.confirmation=The complete removal of {pkg} will erase the software files and also the configuration ones
-debian.action.purge.desc=Removes all software and configuration files associated with the package
-debian.action.purge.status=Removing {} completelydebian.config.pkg_sources.app.auto=
-debian.action.sync_pkgs=Synchronize packages
-debian.action.sync_pkgs.desc=Synchronizes the available software packages on the repositories
-debian.action.sync_pkgs.status=Synchronizing packages
-debian.action.sources=Software sources
-debian.action.sources.desc=Starts the application for managing software sources
-debian.action.sources.not_installed=The application for managing software sources is not installed
-debian.action.sources.status=Launching application
-debian.action.sources.unsupported=The application {app} is not supported and will not be started
-debian.app_index.checking=Checking the apps index
-debian.app_index.updating=Updating the apps index
-debian.config.index_apps.exp=Apps cache expiration
-debian.config.index_apps.exp.tip=Time period in MINUTES in which the installed applications cache is considered up-to-date during startup
-debian.config.pkg_sources.app=Software sources
-debian.config.pkg_sources.app.tip=Application for managing the software sources. {auto} detects one of the supported applications automatically.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Complete removal
-debian.config.remove.purge.tip=If the package configurations should be removed during the uninstallation process
-debian.config.suggestions.exp=Suggestions expiration
-debian.config.suggestions.exp.tip=It defines the period (in hours) in which the suggestions stored in disc will be considered up to date. Use 0 if you always want to update them.
-debian.config.sync_pkgs.time=Packages synchronization period
-debian.config.sync_pkgs.time.tip=Time period in MINUTES in which the packages synchronization must be done on startup
-debian.info.00.name=name
-debian.info.01.version=version
-debian.info.02.description=description
-debian.info.03.exec=executable
-debian.info.04.architecture=architecture
-debian.info.04.architecture.all=all
-debian.info.04.archive=archive
-debian.info.04.automatically installed=automatically installed
-debian.info.04.automatically installed.no=no
-debian.info.04.automatically installed.yes=yes
-debian.info.04.breaks=breaks
-debian.info.04.compressed size=Download size
-debian.info.04.conflicts=conflicts
-debian.info.04.depends=dependencies
-debian.info.04.filename=file
-debian.info.04.homepage=web page
-debian.info.04.maintainer=maintainer
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=multi-architecture
-debian.info.04.multi-arch.foreign=foreign
-debian.info.04.multi-arch.same=same
-debian.info.04.replaces=replaces
-debian.info.04.predepends=pre dependencies
-debian.info.04.priority=priority
-debian.info.04.priority.important=important
-debian.info.04.priority.optional=optional
-debian.info.04.provided by=provided by
-debian.info.04.provides=provides
-debian.info.04.recommends=recommends
-debian.info.04.section=section
-debian.info.04.state=state
-debian.info.04.state.installed=installed
-debian.info.04.state.not installed=not installed
-debian.info.04.state.not installed (configuration files remain)=not installed (configuration files installed)
-debian.info.04.suggests=suggests
-debian.info.04.uncompressed size=installation size
-debian.install.validating=Validating installed packages
-debian.installing_pkgs=Installing packages
-debian.output.downloading=Downloading {pkg}
-debian.output.finishing=Finishing
-debian.output.removing=Removing {pkg}
-debian.output.unpacking=Unpacking {pkg}
-debian.remove.impossible=It is not possible to remove the package {pkg}
-debian.remove_deps=The following {no} dependent packages of {pkg} will be removed as well ({fspace})
-debian.simulate_operation=Simulating the operation
-debian.task.app_index.status=Indexing installed applications
-debian.task.map_apps.check_files=Checking {type} files
-debian.task.map_apps.read_cache=Reading apps from the index (cache)
-debian.task.map_apps.status=Mapping installed applications
-debian.task.update_apps_idx.status=Updating index
-debian.task.sync_pkgs.status=Synchronizing packages
-debian.transaction.dependency_of=Dependency of {pkgs}
-debian.transaction.get_data=Retrieving the operation's data
-debian.transaction.title=Operation details
-debian.transaction.to_install=The following additional packages ({no}) will be installed (Installation: {isize} | Download: {dsize})
-debian.transaction.to_remove=The following packages ({no}) will be removed (Freed space: {fspace})
-debian.uninstall.failed_to_remove=It was not possible to remove the following {no} packages: {pkgs}
-debian.uninstall.removing=Removing packages
-debian.uninstall.validating=Validating removed packages
-gem.debian.info=Software packages for Debian-based systems
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/es b/bauh/gems/debian/resources/locale/es
deleted file mode 100644
index 0bfde98a..00000000
--- a/bauh/gems/debian/resources/locale/es
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=Indexar aplicaciones
-debian.action.index_apps.desc=Identifica todos los paquetes instalados asociados con archivos .desktop y los mapea como aplicaciones
-debian.action.purge=Eliminar completamente
-debian.action.purge.confirmation=La eliminación completa de {pkg} borrará los archivos de software y también los de configuración
-debian.action.purge.desc=Elimina los archivos de software y configuración asociados al paquete
-debian.action.purge.status=Eliminando {} completamente
-debian.action.sync_pkgs=Sincronizar paquetes
-debian.action.sync_pkgs.desc=Sincroniza los paquetes de software disponibles en los repositorios
-debian.action.sync_pkgs.status=Sincronizando paquetes
-debian.action.sources=Fuentes de software
-debian.action.sources.desc=Inicia la aplicación para administrar fuentes de software
-debian.action.sources.not_installed=La aplicación para administrar fuentes de software no está instalada
-debian.action.sources.status=Iniciando la aplicación
-debian.action.sources.unsupported=La aplicación {app} no es compatible y no se iniciará
-debian.app_index.checking=Verificando el índice de applicationes
-debian.app_index.updating=Actualizando el índice de aplicaciones
-debian.config.index_apps.exp=Caducidad de caché de aplicaciones
-debian.config.index_apps.exp.tip=Periodo de tiempo en MINUTOS en que el cache de las aplicaciones instaladas es considerado actualizado durante la inicialización
-debian.config.pkg_sources.app=Fuentes de software
-debian.config.pkg_sources.app.tip=Aplicación para administrar las fuentes de software. {auto} detecta una de las aplicaciones compatibles automáticamente.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Eliminación completa
-debian.config.remove.purge.tip=Si las configuraciones del paquete deben ser eliminadas durante el proceso de desinstalación
-debian.config.suggestions.exp=Expiración de sugerencias
-debian.config.suggestions.exp.tip=Define el período (en horas) en el que la sugerencias almacenadas en disco seran consideradas actualizadas. Use 0 si desea siempre actualizarlas.
-debian.config.sync_pkgs.time=Período de sincronización de paquetes
-debian.config.sync_pkgs.time.tip=Período de tiempo en MINUTOS en que se debe realizar la sincronización de paquetes durante la inicialización
-debian.info.00.name=nombre
-debian.info.01.version=versión
-debian.info.02.description=descripción
-debian.info.03.exec=ejecutable
-debian.info.04.architecture=arquitectura
-debian.info.04.architecture.all=todas
-debian.info.04.archive=archivamiento
-debian.info.04.automatically installed=instalado automáticamente
-debian.info.04.automatically installed.no=no
-debian.info.04.automatically installed.yes=si
-debian.info.04.breaks=roturas
-debian.info.04.compressed size=Tamaño de descarga
-debian.info.04.conflicts=conflictos
-debian.info.04.depends=dependencias
-debian.info.04.filename=archivo
-debian.info.04.homepage=página web
-debian.info.04.maintainer=mantenedor
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=multi-arquitectura
-debian.info.04.multi-arch.foreign=diferente
-debian.info.04.multi-arch.same=misma
-debian.info.04.replaces=reemplaza
-debian.info.04.predepends=pre dependencias
-debian.info.04.priority=prioridad
-debian.info.04.priority.important=importante
-debian.info.04.priority.opcional=opcional
-debian.info.04.provided by=proporcionado por
-debian.info.04.provides=proporciona
-debian.info.04.recommends=recomienda
-debian.info.04.section=sección
-debian.info.04.state=estado
-debian.info.04.state.installed=instalado
-debian.info.04.state.not installed=no instalado
-debian.info.04.state.not installed (configuration files remain)=no instalado (archivos de configuración instalados)
-debian.info.04.suggests=sugiere
-debian.info.04.uncompressed size=tamaño de instalación
-debian.install.validating=Validando paquetes instalados
-debian.installing_pkgs=Instalando paquetes
-debian.output.downloading=Descargando {pkg}
-debian.output.finishing=Finalizando
-debian.output.removing=Eliminando {pkg}
-debian.output.unpacking=Desempacando {pkg}
-debian.remove.impossible=No es posible eliminar el paquete {pkg}
-debian.remove_deps=Los siguientes {no} paquetes dependientes de {pkg} serán eliminados también ({fspace})
-debian.simulate_operation=Simulando la operación
-debian.task.app_index.status=Indexando aplicaciones instaladas
-debian.task.map_apps.check_files=Comprobando archivos {type}
-debian.task.map_apps.read_cache=Leyendo aplicaciones del índice (cache)
-debian.task.map_apps.status=Mapeando las aplicaciones instaladas
-debian.task.update_apps_idx.status=Actualizando índice
-debian.task.sync_pkgs.status=Sincronizando paquetes
-debian.transaction.dependency_of=Dependencia de {pkgs}
-debian.transaction.get_data=Recuperando datos de la operación
-debian.transaction.title=Detalles de la operación
-debian.transaction.to_install=Los siguientes paquetes adicionales ({no}) serán instalados (Instalación: {isize} | Descarga: {dsize})
-debian.transaction.to_remove=Los siguientes paquetes ({no}) serán eliminados (Espacio liberado: {fspace})
-debian.uninstall.failed_to_remove=No fue posible eliminar los siguientes {no} paquetes: {pkgs}
-debian.uninstall.removing=Removendo paquetes
-debian.uninstall.validating=Validando paquetes eliminados
-gem.debian.info=Paquetes de software para sistemas basados en Debian
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/fr b/bauh/gems/debian/resources/locale/fr
deleted file mode 100644
index bfcf4b83..00000000
--- a/bauh/gems/debian/resources/locale/fr
+++ /dev/null
@@ -1,86 +0,0 @@
-debian.action.index_apps=Index applications
-debian.action.index_apps.desc=Identifies all installed packages associated with .desktop files and maps them as applications
-debian.action.purge=Remove completely
-debian.action.purge.confirmation=The complete removal of {pkg} will erase the software files and also the configuration ones
-debian.action.purge.desc=Removes all software and configuration files associated with the package
-debian.action.purge.status=Removing {} completely
-debian.action.sync_pkgs=Synchronize packages
-debian.action.sync_pkgs.desc=Synchronizes the available software packages on the repositories
-debian.action.sync_pkgs.status=Synchronizing packages
-debian.action.sources=Software sources
-debian.action.sources.desc=Starts the application for managing software sources
-debian.action.sources.not_installed=The application for managing software sources is not installed
-debian.action.sources.status=Launching application
-debian.action.sources.unsupported=The application {app} is not supported and will not be started
-debian.app_index.checking=Checking the apps index
-debian.app_index.updating=Updating the apps index
-debian.config.index_apps.exp=Apps cache expiration
-debian.config.index_apps.exp.tip=Time period in MINUTES in which the installed applications cache is considered up-to-date during startup
-debian.config.pkg_sources.app=Software sources
-debian.config.pkg_sources.app.tip=Application for managing the software sources. {auto} detects one of the supported applications automatically.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Complete removal
-debian.config.remove.purge.tip=If the package configurations should be removed during the uninstallation process
-debian.config.suggestions.exp=Suggestions expiration
-debian.config.suggestions.exp.tip=It defines the period (in hours) in which the suggestions stored in disc will be considered up to date. Use 0 if you always want to update them.
-debian.config.sync_pkgs.time=Packages synchronization period
-debian.config.sync_pkgs.time.tip=Time period in MINUTES in which the packages synchronization must be done on startup
-debian.info.00.name=name
-debian.info.01.version=version
-debian.info.02.description=description
-debian.info.03.exec=executable
-debian.info.04.architecture=architecture
-debian.info.04.architecture.all=all
-debian.info.04.archive=archive
-debian.info.04.automatically installed=automatically installed
-debian.info.04.automatically installed.no=no
-debian.info.04.automatically installed.yes=yes
-debian.info.04.breaks=breaks
-debian.info.04.compressed size=Download size
-debian.info.04.conflicts=conflicts
-debian.info.04.depends=dependencies
-debian.info.04.filename=file
-debian.info.04.homepage=web page
-debian.info.04.maintainer=maintainer
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=multi-architecture
-debian.info.04.multi-arch.foreign=foreign
-debian.info.04.multi-arch.same=same
-debian.info.04.replaces=replaces
-debian.info.04.predepends=pre dependencies
-debian.info.04.priority=priority
-debian.info.04.priority.important=important
-debian.info.04.priority.optional=optional
-debian.info.04.provided by=provided by
-debian.info.04.provides=provides
-debian.info.04.recommends=recommends
-debian.info.04.section=section
-debian.info.04.state=state
-debian.info.04.state.installed=installed
-debian.info.04.state.not installed=not installed
-debian.info.04.state.not installed (configuration files remain)=not installed (configuration files installed)
-debian.info.04.suggests=suggests
-debian.info.04.uncompressed size=installation size
-debian.install.validating=Validating installed packages
-debian.output.downloading=Downloading {pkg}
-debian.output.finishing=Finishing
-debian.output.removing=Removing {pkg}
-debian.output.unpacking=Unpacking {pkg}
-debian.remove.impossible=It is not possible to remove the package {pkg}
-debian.remove_deps=The following {no} dependent packages of {pkg} will be removed as well ({fspace})
-debian.simulate_operation=Simulating the operation
-debian.task.app_index.status=Indexing installed applications
-debian.task.map_apps.check_files=Checking {type} files
-debian.task.map_apps.read_cache=Reading apps from the index (cache)
-debian.task.map_apps.status=Mapping installed applications
-debian.task.update_apps_idx.status=Updating index
-debian.task.sync_pkgs.status=Synchronizing packages
-debian.transaction.dependency_of=Dependency of {pkgs}
-debian.transaction.get_data=Retrieving the operation's data
-debian.transaction.title=Operation details
-debian.transaction.to_install=The following additional packages ({no}) will be installed (Installation: {isize} | Download: {dsize})
-debian.transaction.to_remove=The following packages ({no}) will be removed (Freed space: {fspace})
-debian.uninstall.failed_to_remove=It was not possible to remove the following {no} packages: {pkgs}
-debian.uninstall.removing=Removing packages
-debian.uninstall.validating=Validating removed packages
-gem.debian.info=Software packages for Debian-based systems
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/it b/bauh/gems/debian/resources/locale/it
deleted file mode 100644
index 1adcd6f7..00000000
--- a/bauh/gems/debian/resources/locale/it
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=Index applications
-debian.action.index_apps.desc=Identifies all installed packages associated with .desktop files and maps them as applications
-debian.action.purge=Remove completely
-debian.action.purge.confirmation=The complete removal of {pkg} will erase the software files and also the configuration ones
-debian.action.purge.desc=Removes all software and configuration files associated with the package
-debian.action.purge.status=Removing {} completely
-debian.action.sync_pkgs=Synchronize packages
-debian.action.sync_pkgs.desc=Synchronizes the available software packages on the repositories
-debian.action.sync_pkgs.status=Synchronizing packages
-debian.action.sources=Software sources
-debian.action.sources.desc=Starts the application for managing software sources
-debian.action.sources.not_installed=The application for managing software sources is not installed
-debian.action.sources.status=Launching application
-debian.action.sources.unsupported=The application {app} is not supported and will not be started
-debian.app_index.checking=Checking the apps index
-debian.app_index.updating=Updating the apps index
-debian.config.index_apps.exp=Apps cache expiration
-debian.config.index_apps.exp.tip=Time period in MINUTES in which the installed applications cache is considered up-to-date during startup
-debian.config.pkg_sources.app=Software sources
-debian.config.pkg_sources.app.tip=Application for managing the software sources. {auto} detects one of the supported applications automatically.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Complete removal
-debian.config.remove.purge.tip=If the package configurations should be removed during the uninstallation process
-debian.config.suggestions.exp=Suggestions expiration
-debian.config.suggestions.exp.tip=It defines the period (in hours) in which the suggestions stored in disc will be considered up to date. Use 0 if you always want to update them.
-debian.config.sync_pkgs.time=Packages synchronization period
-debian.config.sync_pkgs.time.tip=Time period in MINUTES in which the packages synchronization must be done on startup
-debian.info.00.name=name
-debian.info.01.version=version
-debian.info.02.description=description
-debian.info.03.exec=executable
-debian.info.04.architecture=architecture
-debian.info.04.architecture.all=all
-debian.info.04.archive=archive
-debian.info.04.automatically installed=automatically installed
-debian.info.04.automatically installed.no=no
-debian.info.04.automatically installed.yes=yes
-debian.info.04.breaks=breaks
-debian.info.04.compressed size=Download size
-debian.info.04.conflicts=conflicts
-debian.info.04.depends=dependencies
-debian.info.04.filename=file
-debian.info.04.homepage=web page
-debian.info.04.maintainer=maintainer
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=multi-architecture
-debian.info.04.multi-arch.foreign=foreign
-debian.info.04.multi-arch.same=same
-debian.info.04.replaces=replaces
-debian.info.04.predepends=pre dependencies
-debian.info.04.priority=priority
-debian.info.04.priority.important=important
-debian.info.04.priority.optional=optional
-debian.info.04.provided by=provided by
-debian.info.04.provides=provides
-debian.info.04.recommends=recommends
-debian.info.04.section=section
-debian.info.04.state=state
-debian.info.04.state.installed=installed
-debian.info.04.state.not installed=not installed
-debian.info.04.state.not installed (configuration files remain)=not installed (configuration files installed)
-debian.info.04.suggests=suggests
-debian.info.04.uncompressed size=installation size
-debian.install.validating=Validating installed packages
-debian.installing_pkgs=Installing packages
-debian.output.downloading=Downloading {pkg}
-debian.output.finishing=Finishing
-debian.output.removing=Removing {pkg}
-debian.output.unpacking=Unpacking {pkg}
-debian.remove.impossible=It is not possible to remove the package {pkg}
-debian.remove_deps=The following {no} dependent packages of {pkg} will be removed as well ({fspace})
-debian.simulate_operation=Simulating the operation
-debian.task.app_index.status=Indexing installed applications
-debian.task.map_apps.check_files=Checking {type} files
-debian.task.map_apps.read_cache=Reading apps from the index (cache)
-debian.task.map_apps.status=Mapping installed applications
-debian.task.update_apps_idx.status=Updating index
-debian.task.sync_pkgs.status=Synchronizing packages
-debian.transaction.dependency_of=Dependency of {pkgs}
-debian.transaction.get_data=Retrieving the operation's data
-debian.transaction.title=Operation details
-debian.transaction.to_install=The following additional packages ({no}) will be installed (Installation: {isize} | Download: {dsize})
-debian.transaction.to_remove=The following packages ({no}) will be removed (Freed space: {fspace})
-debian.uninstall.failed_to_remove=It was not possible to remove the following {no} packages: {pkgs}
-debian.uninstall.removing=Removing packages
-debian.uninstall.validating=Validating removed packages
-gem.debian.info=Software packages for Debian-based systems
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/pt b/bauh/gems/debian/resources/locale/pt
deleted file mode 100644
index cb6276a2..00000000
--- a/bauh/gems/debian/resources/locale/pt
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=Indexar aplicações
-debian.action.index_apps.desc=Identifica todos os pacotes instalados associados a arquivos .desktop e os mapeia como aplicações
-debian.action.purge=Remover completamente
-debian.action.purge.confirmation=A remoção completa de {pkg} apagará os arquivos de software e também os de configuração
-debian.action.purge.desc=Remove todos os arquivos de software e configuração associados ao pacote
-debian.action.purge.status=Removendo {} completamente
-debian.action.sync_pkgs=Sincronizar pacotes
-debian.action.sync_pkgs.desc=Sincroniza os pacotes de software disponíveis nos repositórios
-debian.action.sync_pkgs.status=Sincronizando pacotes
-debian.action.sources=Fontes de software
-debian.action.sources.desc=Inicia a aplicação detectada para gerenciamento de fontes de software
-debian.action.sources.not_installed=A aplicação para gerenciamento de fontes de software não está instalada
-debian.action.sources.status=Iniciando aplicação
-debian.action.sources.unsupported=A aplicação {app} não é suportada e não será inicializada
-debian.app_index.checking=Veriricando o índice de aplicações
-debian.app_index.updating=Atualizando o índice de aplicações
-debian.config.index_apps.exp=Validade do cache de aplicações
-debian.config.index_apps.exp.tip=Período de tempo em MINUTOS em que o cache das aplicações instaladas é considerado válido durante a inicialização
-debian.config.pkg_sources.app=Fontes de software
-debian.config.pkg_sources.app.tip=Aplicação para gerenciamento de fontes de software. {auto} detecta uma das aplicações suportadas automaticamente.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Remoção completa
-debian.config.remove.purge.tip=Se as configurações do pacote devem ser removidas durante o processo de desinstalação
-debian.config.suggestions.exp=Validade de sugestões
-debian.config.suggestions.exp.tip=Define o período (em horas) no qual as sugestões armazenadas em disco serão consideradas atualizadas. Use 0 se quiser que elas sempre sejam atualizadas.
-debian.config.sync_pkgs.time=Período de sincronização de pacotes
-debian.config.sync_pkgs.time.tip=Período de tempo em MINUTOS em que a sincronização de pacotes deve ocorrer durante a inicialização
-debian.info.00.name=nome
-debian.info.01.version=versão
-debian.info.02.description=descrição
-debian.info.03.exec=executável
-debian.info.04.architecture=arquitetura
-debian.info.04.architecture.all=todas
-debian.info.04.archive=arquivamento
-debian.info.04.automatically installed=instalado automaticamente
-debian.info.04.automatically installed.no=não
-debian.info.04.automatically installed.yes=sim
-debian.info.04.breaks=Quebra
-debian.info.04.compressed size=Tamanho de download
-debian.info.04.conflicts=Conflita
-debian.info.04.depends=dependências
-debian.info.04.filename=arquivo
-debian.info.04.homepage=página web
-debian.info.04.maintainer=mantenedor
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=multi-arquitetura
-debian.info.04.multi-arch.foreign=diferente
-debian.info.04.multi-arch.same=mesma
-debian.info.04.replaces=substitui
-debian.info.04.predepends=pré-dependências
-debian.info.04.priority=prioridade
-debian.info.04.priority.important=importante
-debian.info.04.priority.optional=opcional
-debian.info.04.provided by=provido por
-debian.info.04.provides=provê
-debian.info.04.recommends=recomenda
-debian.info.04.section=seção
-debian.info.04.state=estado
-debian.info.04.state.installed=instalado
-debian.info.04.state.not installed=não instalado
-debian.info.04.state.not installed (configuration files remain)=não instalado (arquivos de configuração instalados)
-debian.info.04.suggests=sugere
-debian.info.04.uncompressed size=tamanho de instalação
-debian.install.validating=Validando pacotes instalados
-debian.installing_pkgs=Instalando pacotes
-debian.output.downloading=Baixando {pkg}
-debian.output.finishing=Finalizando
-debian.output.removing=Removendo {pkg}
-debian.output.unpacking=Desempacotando {pkg}
-debian.remove.impossible=Não é possível remover o pacote {pkg}
-debian.remove_deps=Os seguintes {no} pacotes dependentes de {pkg} serão removidos também ({fspace})
-debian.simulate_operation=Simulando a operação
-debian.task.app_index.status=Indexando aplicações instaladas
-debian.task.map_apps.check_files=Verificando arquivos {type}
-debian.task.map_apps.read_cache=Lendo aplicações do índice (cache)
-debian.task.map_apps.status=Mapeando aplicações instaladas
-debian.task.update_apps_idx.status=Atualizando índice
-debian.task.sync_pkgs.status=Sincronizando pacotes
-debian.transaction.dependency_of=Dependência de {pkgs}
-debian.transaction.get_data=Obtendo dados da operação
-debian.transaction.title=Detalhes da operação
-debian.transaction.to_install=Os seguintes pacotes adicionais ({no}) serão instaladas (Instalação: {isize} | Download: {dsize})
-debian.transaction.to_remove=Os seguintes pacotes ({no}) serão removidos (Espaço liberado: {fspace})
-debian.uninstall.failed_to_remove=Não foi possível remover os seguintes {no} pacotes: {pkgs}
-debian.uninstall.removing=Removendo pacotes
-debian.uninstall.validating=Validando pacotes removidos
-gem.debian.info=Pacotes de software para sistemas baseados em Debian
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/ru b/bauh/gems/debian/resources/locale/ru
deleted file mode 100644
index 87417577..00000000
--- a/bauh/gems/debian/resources/locale/ru
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=Сопоставлять приложения
-debian.action.index_apps.desc=Идентифицирует все установленные пакеты, связанные с файлами .desktop, и сопоставляет их с приложениями
-debian.action.purge=Удалить полностью
-debian.action.purge.confirmation=Полное удаление {pkg} приведет к удалению программных файлов, а также файлов конфигурации
-debian.action.purge.desc=Удаление всех программных и конфигурационных файлов, связанных с пакетом
-debian.action.purge.status=Полное удаление {}
-debian.action.sync_pkgs=Синхронизация пакетов
-debian.action.sync_pkgs.desc=Синхронизация доступных программных пакетов в репозиториях
-debian.action.sync_pkgs.status=Синхронизация пакетов
-debian.action.sources=Источники ПО
-debian.action.sources.desc=Запуск приложения для управления источниками ПО
-debian.action.sources.not_installed=Приложение для управления источниками ПО не установлено
-debian.action.sources.status=Запуск приложения
-debian.action.sources.unsupported=Приложение {app} не поддерживается и не запускается
-debian.app_index.checking=Проверка индекса приложений
-debian.app_index.updating=Обновление индекса приложений
-debian.config.index_apps.exp=Истечение срока действия кэша приложений
-debian.config.index_apps.exp.tip=Период времени (в минутах) в течение которого кэш установленных приложений считается обновленным при запуске
-debian.config.pkg_sources.app=Источники ПО
-debian.config.pkg_sources.app.tip=Приложение для управления источниками ПО. {auto} автоматически определяет одно из поддерживаемых приложений.
-debian.config.pkg_sources.app.auto=Автоматически
-debian.config.remove.purge=Полное удаление
-debian.config.remove.purge.tip=Если конфигурации пакета должны быть удалены в процессе удаления
-debian.config.suggestions.exp=Срок действия предложений
-debian.config.suggestions.exp.tip=Он определяет период (в часах), в течение которого предложения, хранящиеся на диске, будут считаться актуальными. Используйте 0, если вы хотите обновлять их всегда.
-debian.config.sync_pkgs.time=Период синхронизации пакетов
-debian.config.sync_pkgs.time.tip=Период времени (в минутах) в течение которого должна быть выполнена синхронизация пакетов при запуске
-debian.info.00.name=имя
-debian.info.01.version=версия
-debian.info.02.description=описание
-debian.info.03.exec=исполняемый файл
-debian.info.04.architecture=архитектура
-debian.info.04.architecture.all=все
-debian.info.04.archive=архив
-debian.info.04.automatically installed=автоматически установленный
-debian.info.04.automatically installed.no=нет
-debian.info.04.automatically installed.yes=да
-debian.info.04.breaks=нарушает
-debian.info.04.compressed size=Размер загрузки
-debian.info.04.conflicts=конфликты
-debian.info.04.depends=зависимости
-debian.info.04.filename=файл
-debian.info.04.homepage=веб-страница
-debian.info.04.maintainer=сопровождающий
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=мультиархитектура
-debian.info.04.multi-arch.foreign=внешний
-debian.info.04.multi-arch.same=тот же
-debian.info.04.replaces=заменяет
-debian.info.04.predepends=предзависимости
-debian.info.04.priority=приоритет
-debian.info.04.priority.important=важно
-debian.info.04.priority.optional=опционально
-debian.info.04.provided by=предоставленный
-debian.info.04.provides=предоставляет
-debian.info.04.recommends=рекомендует
-debian.info.04.section=раздел
-debian.info.04.state=состояние
-debian.info.04.state.installed=установлен
-debian.info.04.state.not installed=не установлен
-debian.info.04.state.not installed (configuration files remain)=не установлен (файлы конфигурации установлены)
-debian.info.04.suggests=предлагает
-debian.info.04.uncompressed size=установочный размер
-debian.install.validating=Проверка установленных пакетов
-debian.installing_pkgs=Установка пакетов
-debian.output.downloading=Загрузка {pkg}
-debian.output.finishing=Завершение
-debian.output.removing=Удаление {pkg}
-debian.output.unpacking=Распаковка {pkg}
-debian.remove.impossible=Невозможно удалить пакет {pkg}
-debian.remove_deps=Также будут удалены следующие {no} зависимые пакеты {pkg} ({fspace})
-debian.simulate_operation=Симулирование работы
-debian.task.app_index.status=Индексирование установленных приложений
-debian.task.map_apps.check_files=Проверка {type} файлов
-debian.task.map_apps.read_cache=Чтение приложений из индекса (кэша)
-debian.task.map_apps.status=Сопоставление установленных приложений
-debian.task.update_apps_idx.status=Обновление индекса
-debian.task.sync_pkgs.status=Синхронизация пакетов
-debian.transaction.dependency_of=Зависимость от {pkgs}
-debian.transaction.get_data=Получение данных операции
-debian.transaction.title=Детали операции
-debian.transaction.to_install=Будут установлены следующие дополнительные пакеты ({no}) (Установка: {isize} | Загрузка: {dsize})
-debian.transaction.to_remove=Следующие пакеты ({no}) будут удалены (Освобожденное пространство: {fspace})
-debian.uninstall.failed_to_remove=Не удалось удалить следующие пакеты {no}: {pkgs}
-debian.uninstall.removing=Удаление пакетов
-debian.uninstall.validating=Проверка подлинности удаленных пакетов
-gem.debian.info=Пакеты ПО для систем на базе Debian
diff --git a/bauh/gems/debian/resources/locale/tr b/bauh/gems/debian/resources/locale/tr
deleted file mode 100644
index f4042c76..00000000
--- a/bauh/gems/debian/resources/locale/tr
+++ /dev/null
@@ -1,86 +0,0 @@
-debian.action.index_apps=Index applications
-debian.action.index_apps.desc=Identifies all installed packages associated with .desktop files and maps them as applications
-debian.action.purge=Remove completely
-debian.action.purge.confirmation=The complete removal of {pkg} will erase the software files and also the configuration ones
-debian.action.purge.desc=Removes all software and configuration files associated with the package
-debian.action.purge.status=Removing {} completely
-debian.action.sync_pkgs=Synchronize packages
-debian.action.sync_pkgs.desc=Synchronizes the available software packages on the repositories
-debian.action.sync_pkgs.status=Synchronizing packages
-debian.action.sources=Software sources
-debian.action.sources.desc=Starts the application for managing software sources
-debian.action.sources.not_installed=The application for managing software sources is not installed
-debian.action.sources.status=Launching application
-debian.action.sources.unsupported=The application {app} is not supported and will not be started
-debian.app_index.checking=Checking the apps index
-debian.app_index.updating=Updating the apps index
-debian.config.index_apps.exp=Apps cache expiration
-debian.config.index_apps.exp.tip=Time period in MINUTES in which the installed applications cache is considered up-to-date during startup
-debian.config.pkg_sources.app=Software sources
-debian.config.pkg_sources.app.tip=Application for managing the software sources. {auto} detects one of the supported applications automatically.
-debian.config.pkg_sources.app.auto=Auto
-debian.config.remove.purge=Complete removal
-debian.config.remove.purge.tip=If the package configurations should be removed during the uninstallation process
-debian.config.suggestions.exp=Suggestions expiration
-debian.config.suggestions.exp.tip=It defines the period (in hours) in which the suggestions stored in disc will be considered up to date. Use 0 if you always want to update them.
-debian.config.sync_pkgs.time=Packages synchronization period
-debian.config.sync_pkgs.time.tip=Time period in MINUTES in which the packages synchronization must be done on startup
-debian.info.00.name=name
-debian.info.01.version=version
-debian.info.02.description=description
-debian.info.03.exec=executable
-debian.info.04.architecture=architecture
-debian.info.04.architecture.all=all
-debian.info.04.archive=archive
-debian.info.04.automatically installed=automatically installed
-debian.info.04.automatically installed.no=no
-debian.info.04.automatically installed.yes=yes
-debian.info.04.breaks=breaks
-debian.info.04.compressed size=Download size
-debian.info.04.conflicts=conflicts
-debian.info.04.depends=dependencies
-debian.info.04.homepage=web page
-debian.info.04.maintainer=maintainer
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=multi-architecture
-debian.info.04.multi-arch.foreign=foreign
-debian.info.04.multi-arch.same=same
-debian.info.04.replaces=replaces
-debian.info.04.predepends=pre dependencies
-debian.info.04.priority=priority
-debian.info.04.priority.important=important
-debian.info.04.priority.optional=optional
-debian.info.04.provided by=provided by
-debian.info.04.provides=provides
-debian.info.04.recommends=recommends
-debian.info.04.section=section
-debian.info.04.state=state
-debian.info.04.state.installed=installed
-debian.info.04.state.not installed=not installed
-debian.info.04.state.not installed (configuration files remain)=not installed (configuration files installed)
-debian.info.04.suggests=suggests
-debian.info.04.uncompressed size=installation size
-debian.install.validating=Validating installed packages
-debian.installing_pkgs=Installing packages
-debian.output.downloading=Downloading {pkg}
-debian.output.finishing=Finishing
-debian.output.removing=Removing {pkg}
-debian.output.unpacking=Unpacking {pkg}
-debian.remove.impossible=It is not possible to remove the package {pkg}
-debian.remove_deps=The following {no} dependent packages of {pkg} will be removed as well ({fspace})
-debian.simulate_operation=Simulating the operation
-debian.task.app_index.status=Indexing installed applications
-debian.task.map_apps.check_files=Checking {type} files
-debian.task.map_apps.read_cache=Reading apps from the index (cache)
-debian.task.map_apps.status=Mapping installed applications
-debian.task.update_apps_idx.status=Updating index
-debian.task.sync_pkgs.status=Synchronizing packages
-debian.transaction.dependency_of=Dependency of {pkgs}
-debian.transaction.get_data=Retrieving the operation's data
-debian.transaction.title=Operation details
-debian.transaction.to_install=The following additional packages ({no}) will be installed (Installation: {isize} | Download: {dsize})
-debian.transaction.to_remove=The following packages ({no}) will be removed (Freed space: {fspace})
-debian.uninstall.failed_to_remove=It was not possible to remove the following {no} packages: {pkgs}
-debian.uninstall.removing=Removing packages
-debian.uninstall.validating=Validating removed packages
-gem.debian.info=Software packages for Debian-based systems
\ No newline at end of file
diff --git a/bauh/gems/debian/resources/locale/zh b/bauh/gems/debian/resources/locale/zh
deleted file mode 100644
index 95b6df4b..00000000
--- a/bauh/gems/debian/resources/locale/zh
+++ /dev/null
@@ -1,87 +0,0 @@
-debian.action.index_apps=索引应用程序
-debian.action.index_apps.desc=识别与 .desktop 文件关联的所有已安装软件包,并将它们映射为应用程序
-debian.action.purge=完全删除
-debian.action.purge.confirmation=完全删除 {pkg} 将擦除软件文件以及配置文件
-debian.action.purge.desc=删除与软件包关联的所有软件和配置文件
-debian.action.purge.status=完全删除 {}
-debian.action.sync_pkgs=同步软件包
-debian.action.sync_pkgs.desc=同步可用的软件包在仓库中
-debian.action.sync_pkgs.status=正在同步软件包
-debian.action.sources=软件源
-debian.action.sources.desc=启动管理软件源的应用程序
-debian.action.sources.not_installed=未安装管理软件源的应用程序
-debian.action.sources.status=启动应用程序
-debian.action.sources.unsupported=不支持应用程序 {app},将不会启动
-debian.app_index.checking=检查应用程序索引
-debian.app_index.updating=正在更新应用程序索引
-debian.config.index_apps.exp=应用程序缓存过期
-debian.config.index_apps.exp.tip=启动期间安装的应用程序缓存被视为最新的分钟数
-debian.config.pkg_sources.app=软件源
-debian.config.pkg_sources.app.tip=管理软件源的应用程序。 {auto} 自动检测支持的应用程序之一。
-debian.config.pkg_sources.app.auto=自动
-debian.config.remove.purge=完全删除
-debian.config.remove.purge.tip=是否应在卸载过程中删除软件包配置
-debian.config.suggestions.exp=建议过期时间
-debian.config.suggestions.exp.tip=定义建议在磁盘上存储的期间(以小时为单位)被视为最新的时间。如果始终希望更新它们,请使用 0。
-debian.config.sync_pkgs.time=软件包同步周期
-debian.config.sync_pkgs.time.tip=启动时进行软件包同步的分钟数
-debian.info.00.name=名称
-debian.info.01.version=版本
-debian.info.02.description=描述
-debian.info.03.exec=可执行文件
-debian.info.04.architecture=架构
-debian.info.04.architecture.all=全部
-debian.info.04.archive=存档
-debian.info.04.automatically installed=自动安装
-debian.info.04.automatically installed.no=否
-debian.info.04.automatically installed.yes=是
-debian.info.04.breaks=破坏
-debian.info.04.compressed size=下载大小
-debian.info.04.conflicts=冲突
-debian.info.04.depends=依赖项
-debian.info.04.filename=文件名
-debian.info.04.homepage=网页
-debian.info.04.maintainer=维护者
-debian.info.04.md5sum=MD5
-debian.info.04.multi-arch=多架构
-debian.info.04.multi-arch.foreign=外部
-debian.info.04.multi-arch.same=相同
-debian.info.04.replaces=替代
-debian.info.04.predepends=预先依赖
-debian.info.04.priority=优先级
-debian.info.04.priority.important=重要
-debian.info.04.priority.optional=可选
-debian.info.04.provided by=提供者
-debian.info.04.provides=提供
-debian.info.04.recommends=建议
-debian.info.04.section=部分
-debian.info.04.state=状态
-debian.info.04.state.installed=已安装
-debian.info.04.state.not installed=未安装
-debian.info.04.state.not installed (configuration files remain)=未安装 (配置文件已安装)
-debian.info.04.suggests=建议
-debian.info.04.uncompressed size=安装大小
-debian.install.validating=验证已安装的软件包
-debian.installing_pkgs=正在安装软件包
-debian.output.downloading=下载 {pkg}
-debian.output.finishing=完成
-debian.output.removing=删除 {pkg}
-debian.output.unpacking=解压 {pkg}
-debian.remove.impossible=无法删除软件包 {pkg}
-debian.remove_deps=以下 {no} 个与 {pkg} 有关的依赖软件包也将被删除(已释放空间:{fspace})
-debian.simulate_operation=模拟操作
-debian.task.app_index.status=正在索引已安装的应用程序
-debian.task.map_apps.check_files=检查 {type} 文件
-debian.task.map_apps.read_cache=从索引 (缓存) 读取应用程序
-debian.task.map_apps.status=映射已安装的应用程序
-debian.task.update_apps_idx.status=更新索引
-debian.task.sync_pkgs.status=正在同步软件包
-debian.transaction.dependency_of={pkgs} 的依赖项
-debian.transaction.get_data=检索操作的数据
-debian.transaction.title=操作详细信息
-debian.transaction.to_install=将安装以下额外的软件包({no})(安装:{isize} | 下载:{dsize})
-debian.transaction.to_remove=将删除以下软件包({no})(释放空间:{fspace})
-debian.uninstall.failed_to_remove=无法删除以下 {no} 个软件包:{pkgs}
-debian.uninstall.removing=正在删除软件包
-debian.uninstall.validating=正在验证已删除的软件包
-gem.debian.info=基于 Debian 的系统的软件包
diff --git a/bauh/gems/debian/suggestions.py b/bauh/gems/debian/suggestions.py
deleted file mode 100644
index 2091356d..00000000
--- a/bauh/gems/debian/suggestions.py
+++ /dev/null
@@ -1,209 +0,0 @@
-import os
-import traceback
-from datetime import datetime, timedelta, timezone
-from logging import Logger
-from pathlib import Path
-from threading import Thread
-from typing import Optional, Dict
-
-from bauh.api.abstract.handler import TaskManager
-from bauh.api.abstract.model import SuggestionPriority
-from bauh.api.http import HttpClient
-from bauh.commons.suggestions import parse
-from bauh.gems.debian import DEBIAN_ICON_PATH, DEBIAN_CACHE_DIR
-from bauh.view.util.translation import I18n
-
-
-class DebianSuggestionsDownloader(Thread):
-
- _file_suggestions: Optional[str] = None
- _file_suggestions_ts: Optional[str] = None
- _url_suggestions: Optional[str] = None
-
- @classmethod
- def file_suggestions(cls) -> str:
- if cls._file_suggestions is None:
- cls._file_suggestions = f'{DEBIAN_CACHE_DIR}/suggestions.txt'
-
- return cls._file_suggestions
-
- @classmethod
- def file_suggestions_timestamp(cls) -> str:
- if cls._file_suggestions_ts is None:
- cls._file_suggestions_ts = f'{cls.file_suggestions()}.ts'
-
- return cls._file_suggestions_ts
-
- def __init__(self, logger: Logger, http_client: HttpClient, i18n: I18n, file_url: Optional[str]):
- super(DebianSuggestionsDownloader, self).__init__()
- self._log = logger
- self.i18n = i18n
- self.http_client = http_client
- self._taskman: Optional[TaskManager] = None
-
- if file_url:
- self._file_url = file_url
- else:
- self._file_url = 'https://raw.githubusercontent.com/vinifmor/bauh-files/master/debian/suggestions_v1.txt'
-
- self.task_id = 'debian.suggs'
-
- def register_task(self, taskman: Optional[TaskManager]):
- self._taskman = taskman
- if taskman:
- self._taskman.register_task(id_=self.task_id, label=self.i18n['task.download_suggestions'],
- icon_path=DEBIAN_ICON_PATH)
-
- def is_local_suggestions_file(self) -> bool:
- return self._file_url and self._file_url.startswith('/')
-
- @property
- def taskman(self) -> TaskManager:
- if self._taskman is None:
- self._taskman = TaskManager()
-
- return self._taskman
-
- def should_download(self, debian_config: dict, only_positive_exp: bool = False) -> bool:
- if not self._file_url:
- self._log.error("No Debian suggestions file URL defined")
- return False
-
- if self.is_local_suggestions_file():
- return False
-
- try:
- exp_hours = int(debian_config['suggestions.exp'])
- except ValueError:
- self._log.error(f"The Debian configuration property 'suggestions.expiration' has a non int value set: "
- f"{debian_config['suggestions']['expiration']}")
- return not only_positive_exp
-
- if exp_hours <= 0:
- self._log.info("Suggestions cache is disabled")
- return not only_positive_exp
-
- if not os.path.exists(self.file_suggestions()):
- self._log.info(f"'{self.file_suggestions()}' not found. It must be downloaded")
- return True
-
- if not os.path.exists(self.file_suggestions()):
- self._log.info(f"'{self.file_suggestions()}' not found. The suggestions file must be downloaded.")
- return True
-
- with open(self.file_suggestions_timestamp()) as f:
- timestamp_str = f.read()
-
- try:
- suggestions_timestamp = datetime.fromtimestamp(float(timestamp_str), tz=timezone.utc)
- except Exception:
- self._log.error(f'Could not parse the Debian cached suggestions timestamp: {timestamp_str}')
- traceback.print_exc()
- return True
-
- update = suggestions_timestamp + timedelta(hours=exp_hours) <= datetime.now(timezone.utc)
- return update
-
- def _save(self, text: str, timestamp: float):
- if not self._file_url:
- self._log.error("No Debian suggestions file URL defined")
- return
-
- if self.is_local_suggestions_file():
- return False
-
- self._log.info(f"Caching suggestions to '{self.file_suggestions()}'")
-
- cache_dir = os.path.dirname(self.file_suggestions())
-
- try:
- Path(cache_dir).mkdir(parents=True, exist_ok=True)
- cache_dir_ok = True
- except OSError:
- self._log.error(f"Could not create cache directory '{cache_dir}'")
- traceback.print_exc()
- cache_dir_ok = False
-
- if cache_dir_ok:
- try:
- with open(self.file_suggestions(), 'w+') as f:
- f.write(text)
- except Exception:
- self._log.error(f"An exception happened while writing the file '{self.file_suggestions()}'")
- traceback.print_exc()
-
- try:
- with open(self.file_suggestions_timestamp(), 'w+') as f:
- f.write(str(timestamp))
- except Exception:
- self._log.error(f"An exception happened while writing the file '{self.file_suggestions_timestamp()}'")
- traceback.print_exc()
-
- def read_cached(self) -> Optional[Dict[str, SuggestionPriority]]:
- if not self._file_url:
- self._log.error("No Debian suggestions file URL defined")
- return
-
- if self.is_local_suggestions_file():
- file_path, log_ref = self._file_url, 'local'
- else:
- file_path, log_ref = self.file_suggestions(), 'cached'
-
- self._log.info(f"Reading {log_ref} suggestions file {file_path}")
-
- try:
- with open(file_path) as f:
- sugs_str = f.read()
- except FileNotFoundError:
- self._log.warning(f"The {log_ref} suggestions file does not exist ({file_path})")
- return
- except OSError:
- self._log.warning(f"Could not read from the {log_ref} suggestions file ({file_path})")
- traceback.print_exc()
- return
-
- if not sugs_str:
- self._log.warning(f"The {log_ref} suggestions file '{file_path}' is empty")
- return
-
- return parse(sugs_str, self._log, 'Debian')
-
- def download(self) -> Optional[Dict[str, SuggestionPriority]]:
- if not self._file_url:
- self._log.error("No Debian suggestions file URL defined")
- return
-
- self.taskman.update_progress(self.task_id, progress=1, substatus=None)
-
- self._log.info(f"Downloading Debian suggestions from {self._file_url}")
- res = self.http_client.get(self._file_url)
-
- suggestions = None
- if res.status_code == 200 and res.text:
- self.taskman.update_progress(self.task_id, progress=50, substatus=None)
- suggestions = parse(res.text, self._log, 'Debian')
-
- if suggestions:
- self._save(text=res.text, timestamp=datetime.now(timezone.utc).timestamp())
- else:
- self._log.warning("No Debian suggestions to cache")
- else:
- self._log.warning(f"Could not retrieve Debian suggestions. "
- f"Response (status={res.status_code}, text={res.text})")
-
- self.taskman.update_progress(self.task_id, progress=100, substatus=None)
- self.taskman.finish_task(self.task_id)
- return suggestions
-
- def read(self, debian_config: dict) -> Optional[Dict[str, int]]:
- if not self._file_url:
- self._log.error("No Debian suggestions file URL defined")
- return
-
- if self.is_local_suggestions_file() or not self.should_download(debian_config=debian_config):
- return self.read_cached()
-
- return self.download()
-
- def run(self):
- self.download()
diff --git a/bauh/gems/debian/tasks.py b/bauh/gems/debian/tasks.py
deleted file mode 100644
index edddf6b6..00000000
--- a/bauh/gems/debian/tasks.py
+++ /dev/null
@@ -1,196 +0,0 @@
-import time
-import traceback
-from datetime import datetime, timedelta, timezone
-from logging import Logger
-from threading import Thread
-from typing import Optional, Set
-
-from bauh.api.abstract.handler import TaskManager, ProcessWatcher
-from bauh.commons.html import bold
-from bauh.commons.system import ProcessHandler
-from bauh.gems.debian import DEBIAN_ICON_PATH, PACKAGE_SYNC_TIMESTAMP_FILE
-from bauh.gems.debian.aptitude import Aptitude
-from bauh.gems.debian.index import ApplicationIndexer, ApplicationsMapper
-from bauh.gems.debian.model import DebianApplication
-from bauh.view.util.translation import I18n
-
-
-class MapApplications(Thread):
-
- def __init__(self, taskman: TaskManager, app_indexer: ApplicationIndexer, i18n: I18n, logger: Logger,
- deb_config: dict, app_mapper: ApplicationsMapper, check_expiration: bool = True,
- watcher: Optional[ProcessWatcher] = None):
- super(MapApplications, self).__init__()
- self._taskman = taskman
- self._i18n = i18n
- self._log = logger
- self._id = 'debian.map_apps'
- self._indexer = app_indexer
- self._config = deb_config
- self._app_mapper = app_mapper
- self._taskman.register_task(self._id, self._i18n['debian.task.map_apps.status'], DEBIAN_ICON_PATH)
- self.apps: Optional[Set[DebianApplication]] = None
- self.cached: Optional[bool] = None
- self._check_expiration = check_expiration
- self._watcher = watcher
-
- def _change_substatus(self, msg: str):
- if self._watcher:
- self._watcher.change_substatus(msg)
-
- def run(self):
- ti = time.time()
- self._log.info("Begin: mapping Debian applications")
-
- self._taskman.update_progress(self._id, 1, None)
-
- if not self._check_expiration or self._indexer.is_expired(self._config):
- status = self._i18n['debian.task.map_apps.check_files'].format(type="'.desktop")
- self._taskman.update_progress(self._id, 1, status)
- self._change_substatus(status)
- self.apps = self._app_mapper.map_executable_applications()
- self.cached = False
- else:
- status = self._i18n['debian.task.map_apps.read_cache']
- self._taskman.update_progress(self._id, 1, status)
- self._change_substatus(status)
- self.apps = {app for app in self._indexer.read_index()}
- self.cached = True
-
- self._log.info(f"Number of Debian applications found: {len(self.apps) if self.apps else 0}")
- self._taskman.update_progress(self._id, 100, None)
- self._taskman.finish_task(self._id)
-
- tf = time.time()
- self._log.info(f"Finish: mapping Debian applications ({tf - ti:.4f} seconds)")
-
-
-class UpdateApplicationIndex(Thread):
-
- def __init__(self, taskman: TaskManager, app_indexer: ApplicationIndexer,
- i18n: I18n, logger: Logger, mapping_apps: MapApplications,
- watcher: Optional[ProcessWatcher] = None):
- super(UpdateApplicationIndex, self).__init__()
- self._taskman = taskman
- self._i18n = i18n
- self._log = logger
- self._id = 'debian.app_idx'
- self._indexer = app_indexer
- self._mapping_apps = mapping_apps
- self._taskman.register_task(self._id, self._i18n['debian.task.app_index.status'], DEBIAN_ICON_PATH)
- self._watcher = watcher
-
- def _change_substatus(self, msg: str):
- if self._watcher:
- self._watcher.change_substatus(msg)
-
- def run(self):
- ti = time.time()
- self._log.info("Begin: Debian applications indexation")
-
- self._taskman.update_progress(self._id, 1, self._i18n['task.waiting_task'].format(bold(self._i18n['debian.task.map_apps.status'])))
- self._mapping_apps.join()
-
- finish_msg = None
- if self._mapping_apps.cached:
- finish_msg = self._i18n['task.canceled']
- else:
- status = self._i18n['debian.task.update_apps_idx.status']
- self._taskman.update_progress(self._id, 50, status)
- self._change_substatus(status)
-
- try:
- self._indexer.update_index(self._mapping_apps.apps)
- except Exception:
- finish_msg = self._i18n['error']
-
- self._taskman.update_progress(self._id, 100, finish_msg)
- self._taskman.finish_task(self._id)
-
- tf = time.time()
- self._log.info(f"Finish: Debian applications indexation ({tf - ti:.4f} seconds)")
-
-
-class SynchronizePackages(Thread):
-
- def __init__(self, taskman: TaskManager, i18n: I18n, logger: Logger, root_password: Optional[str],
- aptitude: Aptitude, watcher: Optional[ProcessWatcher] = None):
- super(SynchronizePackages, self).__init__()
- self._id = 'debian.sync_pkgs'
- self._taskman = taskman
- self._i18n = i18n
- self._log = logger
- self._root_password = root_password
- self._watcher = watcher
- self._aptitude = aptitude
- self._taskman.register_task(self._id, self._i18n['debian.task.sync_pkgs.status'], DEBIAN_ICON_PATH)
-
- def _notify_output(self, output: str):
- self._taskman.update_output(self._id, output)
-
- @staticmethod
- def should_synchronize(deb_config: dict, logger: Logger) -> bool:
- try:
- period = int(deb_config.get('sync_pkgs.time', 0))
- except ValueError:
- logger.error(f"Invalid value for Debian configuration property 'sync_pkgs.time': "
- f"{deb_config['sync_pkgs.time']}")
- return True
-
- if period <= 0:
- logger.warning("Packages synchronization will always be done ('sync_pkgs.time' <= 0 )'")
- return True
-
- try:
- with open(PACKAGE_SYNC_TIMESTAMP_FILE) as f:
- timestamp_str = f.read().strip()
- except FileNotFoundError:
- logger.info(f"No packages synchronization timestamp found ({PACKAGE_SYNC_TIMESTAMP_FILE})")
- return True
-
- try:
- last_timestamp = datetime.fromtimestamp(float(timestamp_str), tz=timezone.utc)
- except Exception:
- logger.error(f'Could not parse the packages synchronization timestamp: {timestamp_str} '
- f'({PACKAGE_SYNC_TIMESTAMP_FILE})')
- traceback.print_exc()
- return True
-
- expired = last_timestamp + timedelta(minutes=period) <= datetime.now(timezone.utc)
-
- if expired:
- logger.info("Packages synchronization is outdated")
- else:
- logger.info("Packages synchronization is up-to-date")
-
- return expired
-
- def run(self) -> bool:
- ti = time.time()
- self._log.info("Begin: packages synchronization")
- self._taskman.update_progress(self._id, 1, None)
-
- handler = ProcessHandler(self._watcher)
- updated, _ = handler.handle_simple(self._aptitude.update(self._root_password),
- output_handler=self._notify_output)
- self._taskman.update_progress(self._id, 99, None)
-
- if updated:
- index_timestamp = datetime.now(timezone.utc).timestamp()
- finish_msg = None
- try:
- with open(PACKAGE_SYNC_TIMESTAMP_FILE, 'w+') as f:
- f.write(str(index_timestamp))
- except OSError:
- finish_msg = self._i18n['error']
- self._log.error(f"Could not write the packages synchronization timestamp to file "
- f"'{PACKAGE_SYNC_TIMESTAMP_FILE}'")
- else:
- finish_msg = self._i18n['error']
-
- self._taskman.update_progress(self._id, 100, finish_msg)
- self._taskman.finish_task(self._id)
-
- tf = time.time()
- self._log.info(f"Finish: packages synchronization ({tf - ti:.4f} seconds)")
- return updated
diff --git a/tests/gems/debian/__init__.py b/tests/gems/debian/__init__.py
deleted file mode 100644
index a2b38d41..00000000
--- a/tests/gems/debian/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import os
-
-DEBIAN_TESTS_DIR = os.path.dirname(os.path.abspath(__file__))
diff --git a/tests/gems/debian/resources/app_idx_full.json b/tests/gems/debian/resources/app_idx_full.json
deleted file mode 100644
index bd3d4989..00000000
--- a/tests/gems/debian/resources/app_idx_full.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "firefox": {
- "categories": [
- "GNOME",
- "GTK",
- "Network",
- "WebBrowser"
- ],
- "exe_path": "firefox %u",
- "icon_path": "firefox"
- },
-
- "synaptic": {
- "exe_path": "synaptic-pkexec",
- "icon_path": "synaptic"
- }
-}
diff --git a/tests/gems/debian/test_aptitude.py b/tests/gems/debian/test_aptitude.py
deleted file mode 100644
index 87dcb3a4..00000000
--- a/tests/gems/debian/test_aptitude.py
+++ /dev/null
@@ -1,198 +0,0 @@
-from unittest import TestCase
-from unittest.mock import Mock, patch
-
-from bauh import __app_name__
-from bauh.commons import system
-from bauh.commons.system import USE_GLOBAL_INTERPRETER
-from bauh.gems.debian.aptitude import Aptitude, map_package_name
-from bauh.gems.debian.model import DebianPackage
-
-
-class MapPackageNameTest(TestCase):
-
- def test__it_must_return_the_same_input_when_no_colon(self):
- self.assertEqual('my_package', map_package_name('my_package'))
-
- def test__it_must_return_the_only_the_word_before_the_first_colon(self):
- self.assertEqual('my_package', map_package_name('my_package:i386'))
-
- def test__it_must_return_a_name_with_colon_when_several_colons_are_present(self):
- self.assertEqual('my_package:i386', map_package_name('my_package:i386:amd64'))
-
-
-class AptitudeTest(TestCase):
-
- def setUp(self):
- self.aptitude = Aptitude(Mock())
-
- @patch(f'{__app_name__}.gems.debian.aptitude.system.execute', return_value=(0, """
-gimp-cbmplugs^^1.2.2-1build1^Distro Developers ^universe/graphics^plugins for The GIMP to import/export Commodore 64 files
-gimp-gmic^2.4.5-1.0^2.4.5-1.1^Distro Developers ^plugin^GREYC's Magic for Image Computing - GIMP Plugin
-gimp-gutenprint^5.3.3-4^5.3.3-4^Distro Developers ^plugin^print plugin for the GIMP
-gimp-help^^^^^
- """))
- def test_search__must_return_installed_and_not_installed_packages_with_updates(self, execute: Mock):
- query = 'gimp'
- res = [p for p in self.aptitude.search(query=query)]
-
- execute.assert_called_once_with(f"aptitude search {query} -q -F '%p^%v^%V^%m^%s^%d' --disable-columns", shell=True)
-
- exp = [
- DebianPackage(name='gimp-cbmplugs', version='1.2.2-1build1', latest_version='1.2.2-1build1',
- maintainer='Distro Developers',
- description='plugins for The GIMP to import/export Commodore 64 files',
- categories=('graphics',),
- installed=False, update=False),
- DebianPackage(name='gimp-gmic', version='2.4.5-1.0', latest_version='2.4.5-1.1',
- maintainer='Distro Developers',
- description="GREYC's Magic for Image Computing - GIMP Plugin",
- categories=('plugin',),
- installed=True, update=True),
- DebianPackage(name='gimp-gutenprint', version='5.3.3-4', latest_version='5.3.3-4',
- maintainer='Distro Developers',
- description="print plugin for the GIMP",
- categories=('plugin',),
- installed=True, update=False),
- ]
-
- self.assertEqual([p.__dict__ for p in exp], [p.__dict__ for p in res])
-
- @patch(f'{__app_name__}.gems.debian.aptitude.system.execute', return_value=(0, """
-Package: firefox
-Version: 97.0+distro1+una
-State: installed (95.0.1+distro1.1+una), upgrade available (97.0+distro1+una)
-Automatically installed: no
-Priority: optional
-Section: web
-Maintainer: Distro Dev
-Architecture: amd64
-Uncompressed Size: 236 M
-PreDepends: distro-system-adjustments (>= 2021.12.16)
-Breaks: firefox-dbg (< 95.0.1+distro1+una), firefox-dev (< 95.0.1+distro1+una), firefox-geckodriver (< 95.0.1+distro1+una), firefox-mozsymbols (< 95.0.1+distro1+una)
-Replaces: firefox-dbg (< 95.0.1+distro1+una), firefox-dev (< 95.0.1+distro1+una), firefox-geckodriver (< 95.0.1+distro1+una), firefox-mozsymbols (< 95.0.1+distro1+una)
-Provides: gnome-www-browser, www-browser
-Description: The Firefox web browser
- The Mozilla Firefox Web Browser.
-
-Package: gcc
-Version: 4:9.3.0-1distro2
-State: installed
-Automatically installed: no
-Priority: optional
-Section: devel
-Maintainer: Distro Developers
-Architecture: amd64
-Uncompressed Size: 51,2 k
-Depends: cpp (= 4:9.3.0-1distro2), gcc-9 (>= 9.3.0-3~)
-Recommends: libc6-dev | libc-dev
-Suggests: gcc-multilib, make, manpages-dev, autoconf, automake, libtool, flex, bison, gdb, gcc-doc
-Conflicts: gcc-doc (< 1:2.95.3), gcc-doc:i386 (< 1:2.95.3), gcc:i386
-Provides: c-compiler, gcc-x86-64-linux-gnu (= 4:9.3.0-1distro2), gcc:amd64 (= 4:9.3.0-1distro2)
-Description: GNU C compiler
- This is the GNU C compiler, a fairly portable optimizing compiler for C.
-
- This is a dependency package providing the default GNU C compiler.
-
-"""))
- def test_show__all_attributes(self, execute: Mock):
- info = self.aptitude.show(('firefox', 'gcc'))
- execute.assert_called_once_with('aptitude show -q firefox gcc', shell=True,
- custom_env={**system.gen_env(global_interpreter=system.USE_GLOBAL_INTERPRETER,
- lang=''), 'LC_NUMERIC': ''})
-
- expected = {
- 'firefox': {
- 'version': '97.0+distro1+una',
- 'state': ('installed (95.0.1+distro1.1+una)', 'upgrade available (97.0+distro1+una)'),
- 'automatically installed': 'no',
- 'priority': 'optional',
- 'section': 'web',
- 'maintainer': 'Distro Dev ',
- 'architecture': 'amd64',
- 'uncompressed size': 236000000,
- 'predepends': ('distro-system-adjustments (>= 2021.12.16)', ),
- 'breaks': ('firefox-dbg (< 95.0.1+distro1+una)', 'firefox-dev (< 95.0.1+distro1+una)',
- 'firefox-geckodriver (< 95.0.1+distro1+una)', 'firefox-mozsymbols (< 95.0.1+distro1+una)'),
- 'replaces': ('firefox-dbg (< 95.0.1+distro1+una)', 'firefox-dev (< 95.0.1+distro1+una)',
- 'firefox-geckodriver (< 95.0.1+distro1+una)', 'firefox-mozsymbols (< 95.0.1+distro1+una)'),
- 'provides': ('gnome-www-browser', 'www-browser'),
- 'description': 'The Firefox web browser'
- },
- 'gcc': {
- 'version': '4:9.3.0-1distro2',
- 'state': ('installed', ),
- 'automatically installed': 'no',
- 'priority': 'optional',
- 'section': 'devel',
- 'maintainer': 'Distro Developers ',
- 'architecture': 'amd64',
- 'uncompressed size': 51200,
- 'depends': ('cpp (= 4:9.3.0-1distro2)', 'gcc-9 (>= 9.3.0-3~)'),
- 'recommends': ('libc6-dev | libc-dev', ),
- 'suggests': ('gcc-multilib', 'make', 'manpages-dev', 'autoconf', 'automake',
- 'libtool', 'flex', 'bison', 'gdb', 'gcc-doc'),
- 'conflicts': ('gcc-doc (< 1:2.95.3)', 'gcc-doc:i386 (< 1:2.95.3)', 'gcc:i386'),
- 'provides': ('c-compiler', 'gcc-x86-64-linux-gnu (= 4:9.3.0-1distro2)', 'gcc:amd64 (= 4:9.3.0-1distro2)'),
- 'description': 'GNU C compiler'
- }
- }
-
- self.assertEqual(expected, info)
-
- @patch(f'{__app_name__}.gems.debian.aptitude.system.execute', return_value=(0, """
- gir1.2-javascriptcoregtk-4.0^2.34.1-0distro0.20.04.1^2.34.4-0distro0.20.04.1^Distro Developers ^library^JavaScript engine library from WebKitGTK - GObject introspection data
- gir1.2-nm-1.0^1.22.10-1distro2.2^1.22.10-1distro2.3^Distro Developers ^library^GObject introspection data for the libnm library
- xwayland^2:1.20.13-1distro1~20.04.2^2:1.20.13-1distro1~20.04.2^Distro X-SWAT ^X11^Xwayland X server
- """))
- def test_read_installed__with_updates_available(self, execute: Mock):
- returned = [p for p in self.aptitude.read_installed()]
- execute.assert_called_once()
-
- expected = [DebianPackage(name='gir1.2-javascriptcoregtk-4.0', version='2.34.1-0distro0.20.04.1',
- latest_version='2.34.4-0distro0.20.04.1',
- maintainer='Distro Developers', update=True, installed=True,
- categories=('library',),
- description='JavaScript engine library from WebKitGTK - GObject introspection data'),
- DebianPackage(name='gir1.2-nm-1.0', version='1.22.10-1distro2.2',
- latest_version='1.22.10-1distro2.3',
- maintainer='Distro Developers', update=True, installed=True,
- categories=('library',),
- description='GObject introspection data for the libnm library'),
- DebianPackage(name='xwayland', version='2:1.20.13-1distro1~20.04.2',
- latest_version='2:1.20.13-1distro1~20.04.2',
- maintainer='Distro X-SWAT', update=False, installed=True,
- categories=('X11',),
- description='Xwayland X server')
- ]
-
- self.assertEqual([p.__dict__ for p in expected], [p.__dict__ for p in returned])
-
- def test_map_transaction_output__it_should_map_i386_packages(self):
- output = "\nThe following NEW packages will be installed:\n" \
- " gcc-12-base:i386{a} [12.1.0-2distro~22.04] <+272 kB> glib-networking:i386{a} [2.72.0-1] <+242 kB>\n" \
- "\nThe following packages will be REMOVED:\n" \
- " celluloid{a} [0.21-linux+distro] <-1066 kB> libpcre3:i386{a} [2:8.39-13distro0.22.04.1] <-714 kB>"
-
- transaction = self.aptitude.map_transaction_output(output)
- to_install = {
- DebianPackage(name="gcc-12-base:i386",
- version="12.1.0-2distro~22.04",
- latest_version="12.1.0-2distro~22.04",
- transaction_size=272000.0
- ),
- DebianPackage(name="glib-networking:i386", version="2.72.0-1",
- latest_version="2.72.0-1", transaction_size=242000.0)
- }
- self.assertEqual(to_install, {*transaction.to_install})
-
- to_remove = {
- DebianPackage(name="celluloid",
- version="0.21-linux+distro",
- latest_version="0.21-linux+distro",
- transaction_size=-1066000.0
- ),
- DebianPackage(name="libpcre3:i386", version="2:8.39-13distro0.22.04.1",
- latest_version="2:8.39-13distro0.22.04.1", transaction_size=-714000.0)
- }
-
- self.assertEqual(to_remove, {*transaction.to_remove})
diff --git a/tests/gems/debian/test_controller.py b/tests/gems/debian/test_controller.py
deleted file mode 100644
index 23bc2a47..00000000
--- a/tests/gems/debian/test_controller.py
+++ /dev/null
@@ -1,99 +0,0 @@
-from unittest import TestCase
-from unittest.mock import MagicMock, patch, Mock
-
-from bauh import __app_name__
-from bauh.api.abstract.controller import SearchResult
-from bauh.gems.debian.controller import DebianPackageManager
-from bauh.gems.debian.model import DebianPackage, DebianApplication
-
-
-class DebianPackageManagerTest(TestCase):
-
- def setUp(self):
- self.controller = DebianPackageManager(MagicMock())
- self.controller._apps_index = {}
-
- @patch(f'{__app_name__}.gems.debian.controller.Aptitude.read_installed', return_value=iter((
- DebianPackage(name='gir1.2-javascriptcoregtk-4.0', version='2.34.1-0distro0.20.04.1',
- latest_version='2.34.1-0distro0.20.04.1',
- maintainer='Distro Developers', update=False, installed=True,
- description='JavaScript engine library from WebKitGTK - GObject introspection data'),
- DebianPackage(name='xwayland', version='2:1.20.13-1distro1~20.04.2',
- latest_version='2:1.20.13-1distro1~20.04.2',
- maintainer='Distro X-SWAT', update=False, installed=True,
- description='Xwayland X server')
- )))
- def test_read_installed__must_associated_packages_found_to_applications_if_appliable(self, read_installed: Mock):
- app = DebianApplication(name='xwayland', exe_path='xwayland', icon_path='xwayland', categories=('app',))
-
- self.controller.__apps_index = {'xwayland': app}
-
- result = self.controller.read_installed(disk_loader=None, pkg_types=None, internet_available=False)
- read_installed.assert_called_once()
-
- self.assertIsNone(result.new)
-
- expected = [DebianPackage(name='gir1.2-javascriptcoregtk-4.0', version='2.34.1-0distro0.20.04.1', latest_version='2.34.1-0distro0.20.04.1',
- maintainer='Distro Developers', update=False, installed=True,
- description='JavaScript engine library from WebKitGTK - GObject introspection data'),
- DebianPackage(name='xwayland', version='2:1.20.13-1distro1~20.04.2', latest_version='2:1.20.13-1distro1~20.04.2',
- maintainer='Distro X-SWAT', update=False, installed=True,
- description='Xwayland X server', app=app)
- ]
-
- self.assertEqual(expected, result.installed)
-
- @patch(f'{__app_name__}.gems.debian.controller.Aptitude.read_installed', return_value=iter((
- DebianPackage(name='gir1.2-javascriptcoregtk-4.0', version='2.34.1-0distro0.20.04.1',
- latest_version='2.34.1-0distro0.20.04.1',
- maintainer='Distro Developers', update=False, installed=True,
- description='JavaScript engine library from WebKitGTK - GObject introspection data'),
- DebianPackage(name='xwayland', version='2:1.20.13-1distro1~20.04.2',
- latest_version='2:1.20.13-1distro1~20.04.2',
- maintainer='Distro X-SWAT', update=False, installed=True,
- description='Xwayland X server')
- )))
- def test_read_installed__internet_not_available(self, read_installed: Mock):
- result = self.controller.read_installed(disk_loader=None, pkg_types=None, internet_available=False)
- read_installed.assert_called_once()
-
- self.assertIsNone(result.new)
-
- expected = [DebianPackage(name='gir1.2-javascriptcoregtk-4.0', version='2.34.1-0distro0.20.04.1', latest_version='2.34.1-0distro0.20.04.1',
- maintainer='Distro Developers', update=False, installed=True,
- description='JavaScript engine library from WebKitGTK - GObject introspection data'),
- DebianPackage(name='xwayland', version='2:1.20.13-1distro1~20.04.2', latest_version='2:1.20.13-1distro1~20.04.2',
- maintainer='Distro X-SWAT', update=False, installed=True,
- description='Xwayland X server')
- ]
-
- self.assertEqual(expected, result.installed)
-
- @patch(f'{__app_name__}.gems.debian.controller.Aptitude.read_installed')
- def test_search__must_return_empty_result_when_url(self, read_installed: Mock):
- words = 'i'
- res = self.controller.search(words=words, disk_loader=None, limit=-1, is_url=True)
- read_installed.assert_not_called()
- self.assertEqual(SearchResult.empty(), res)
-
- @patch(f'{__app_name__}.gems.debian.controller.Aptitude.search', return_value=iter((
- DebianPackage(name='xpto', version='1.0', latest_version='1.0', installed=True, update=False, description=''),
- DebianPackage(name='test', version='1.0', latest_version='1.0', installed=False, update=False, description=''),
- DebianPackage(name='myapp', version='1.0', latest_version='1.0', installed=True, update=False, description=''),
- )))
- def test_search__returned_packages_should_be_associated_with_apps_if_appliable(self, search: Mock):
- app = DebianApplication(name='myapp', exe_path='myapp', icon_path='myapp',
- categories=('app',))
- self.controller._apps_index = {'myapp': app}
-
- words = 'test'
- res = self.controller.search(words=words, disk_loader=None, limit=-1, is_url=False)
- search.assert_called_once_with(words)
-
- self.assertEqual([DebianPackage(name='xpto', version='1.0', latest_version='1.0', installed=True, update=False, description=''),
- DebianPackage(name='myapp', version='1.0', latest_version='1.0', installed=True, update=False,
- description='', app=app)
- ], res.installed)
-
- self.assertEqual([DebianPackage(name='test', version='1.0', latest_version='1.0', installed=False, update=False, description='')],
- res.new)
diff --git a/tests/gems/debian/test_index.py b/tests/gems/debian/test_index.py
deleted file mode 100644
index b43d55c2..00000000
--- a/tests/gems/debian/test_index.py
+++ /dev/null
@@ -1,172 +0,0 @@
-import json
-import os.path
-from unittest import TestCase
-from unittest.mock import Mock, patch, call
-
-from bauh import __app_name__
-from bauh.gems.debian.index import ApplicationsMapper, ApplicationIndexer
-from bauh.gems.debian.model import DebianApplication
-from tests.gems.debian import DEBIAN_TESTS_DIR
-
-
-def mock_read_file(fpath: str):
- if fpath.endswith('firefox.desktop'):
- return """
- [Desktop Entry]
- Version=1.0
- Name=Firefox Web Browser
- Comment=Browse the World Wide Web
- GenericName=Web Browser
- Keywords=Internet;WWW;Browser;Web;Explorer
- Exec=firefox %u
- Terminal=false
- X-MultipleArgs=false
- Type=Application
- Icon=firefox
- Categories=GNOME;GTK;Network;WebBrowser;
- """
- elif fpath.endswith('synaptic.desktop'):
- return """
- [Desktop Entry]
- Name=Synaptic Package Manager
- GenericName=Package Manager
- Comment=Install, remove and upgrade software packages
- Exec=synaptic-pkexec
- Icon=synaptic
- Terminal=false
- Type=Application
- """
- elif fpath.endswith('no-icon.desktop'):
- return """
- [Desktop Entry]
- Name=No-icon
- Exec=no-icon
- Terminal=false
- Type=Application
- Categories=PackageManager;GTK;System;Settings;
- """
- elif fpath.endswith('no-exe.desktop'):
- return """
- [Desktop Entry]
- Name=No-exe
- Terminal=false
- Type=Application
- Icon=no-exe
- Categories=PackageManager;GTK;System;Settings;
- """
- elif fpath.endswith('no-display.desktop'):
- return """
- [Desktop Entry]
- Name=No-display
- Exec=no-display
- Terminal=false
- Type=Application
- Icon=no-display
- NoDisplay=true
- Categories=PackageManager;GTK;System;Settings;
- """
- elif fpath.endswith('terminal-app.desktop'):
- return """
- [Desktop Entry]
- Name=Terminal-App
- Exec=terminal-app
- Terminal=true
- Type=Application
- Icon=terminal-app
- Categories=PackageManager;GTK;System;Settings;
- """
-
-
-class ApplicationsMapperTest(TestCase):
-
- def setUp(self):
- self.mapper = ApplicationsMapper(logger=Mock(), workers=1)
-
- @patch(f'{__app_name__}.gems.debian.index.ApplicationsMapper._read_file', side_effect=mock_read_file)
- @patch(f'{__app_name__}.gems.debian.index.system.execute', return_value=(0, """
- firefox: /usr/share/applications/firefox.desktop
- app-install-data: /usr/share/app-install/desktop/firefox-launchpad-plugin.desktop
- app-install-data: /usr/share/app-install/desktop/firefox:firefox.desktop
- xfce4-helpers: /usr/share/xfce4/helpers/firefox.desktop
- synaptic: /usr/share/applications/synaptic.desktop
- no-icon: /usr/share/applications/no-icon.desktop
- no-exe: /usr/share/applications/no-exe.desktop
- no-display: /usr/share/applications/no-display.desktop
- terminal-app: /usr/share/applications/terminal-app.desktop
- """))
- def test_map_executable_applications__return_applications_with_exec_and_icon(self, execute: Mock, read_file: Mock):
- apps = self.mapper.map_executable_applications()
- execute.assert_called_once_with('dpkg-query -S .desktop', shell=True)
- read_file.assert_has_calls([call('/usr/share/applications/firefox.desktop'),
- call('/usr/share/applications/synaptic.desktop'),
- call('/usr/share/applications/no-icon.desktop'),
- call('/usr/share/applications/no-exe.desktop')], any_order=True)
-
- self.assertEqual({
- DebianApplication(name='firefox', exe_path='firefox %u', icon_path='firefox',
- categories=('GNOME', 'GTK', 'Network', 'WebBrowser')),
- DebianApplication(name='synaptic', exe_path='synaptic-pkexec', icon_path='synaptic',
- categories=None)
- }, apps)
-
-
-class ApplicationIndexerTest(TestCase):
-
- def setUp(self):
- self.update_idx_file_path = f'{DEBIAN_TESTS_DIR}/resources/apps_idx.json'
- self.update_idx_ts_file_path = f'{self.update_idx_file_path}.ts'
- self.app_indexer = ApplicationIndexer(logger=Mock(),
- index_file_path=self.update_idx_file_path)
-
- if os.path.exists(self.update_idx_file_path):
- os.remove(self.update_idx_file_path)
-
- def tearDown(self) -> None:
- if os.path.exists(self.update_idx_file_path):
- os.remove(self.update_idx_file_path)
-
- if os.path.exists(self.update_idx_ts_file_path):
- os.remove(self.update_idx_ts_file_path)
-
- def test_update_index(self):
- apps = {
- DebianApplication(name='firefox', exe_path='firefox %u', icon_path='firefox',
- categories=('GNOME', 'GTK', 'Network', 'WebBrowser')),
- DebianApplication(name='synaptic', exe_path='synaptic-pkexec', icon_path='synaptic',
- categories=None)
- }
-
- self.app_indexer.update_index(apps)
-
- self.assertTrue(os.path.exists(self.update_idx_file_path))
-
- with open(self.update_idx_file_path) as f:
- index_content = f.read()
-
- self.assertEqual({'firefox': {'exe_path': 'firefox %u', 'icon_path': 'firefox',
- 'categories': ['GNOME', 'GTK', 'Network', 'WebBrowser']},
- 'synaptic': {'exe_path': 'synaptic-pkexec', 'icon_path': 'synaptic',
- 'categories': None}
- }, json.loads(index_content))
-
- self.assertTrue(os.path.isfile(self.update_idx_ts_file_path))
-
- with open(self.update_idx_ts_file_path) as f:
- ts_str = f.read()
-
- try:
- float(ts_str)
- except ValueError:
- self.assertFalse(False, "index timestamp must be a float number")
-
- def test_read_index(self):
- self.app_indexer._file_path = f'{DEBIAN_TESTS_DIR}/resources/app_idx_full.json'
-
- expected = {
- DebianApplication(name='firefox', exe_path='firefox %u', icon_path='firefox',
- categories=('GNOME', 'GTK', 'Network', 'WebBrowser')),
- DebianApplication(name='synaptic', exe_path='synaptic-pkexec', icon_path='synaptic',
- categories=None)
- }
-
- self.assertEqual(expected, {app for app in self.app_indexer.read_index()})