This commit is contained in:
Vinícius Moreira
2019-12-09 14:13:27 -03:00
committed by GitHub
33 changed files with 544 additions and 106 deletions

View File

@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [0.7.4] 2019-12-09
### Improvements
- AUR
- retrieving and displaying all transitive required dependencies ( it can be disabled via the new environment variable **BAUH_ARCH_CHECK_SUBDEPS=0** )
- displaying **makedepends** and **checkdepends** in the info window
- Some AUR labels have been changed to not confuse the user
- **--clean** param renamed to **--reset**
- Minor UI improvements
### Fixes
- AUR
- not finding some dependencies declared as files instead of the package names (e.g: dolphin-emu-git )
- replaces the term **mirror** by **repository**
## [0.7.3] 2019-11-29 ## [0.7.3] 2019-11-29
### Improvements ### Improvements
- Not breaking the application when a i18n (translation) key was not found - Not breaking the application when a i18n (translation) key was not found

View File

@@ -88,7 +88,10 @@ Icon=/home/$USER/bauh_env/lib/python3.7/site-packages/bauh/view/resources/img/lo
In order to autostart the application, use your Desktop Environment settings to register it as a startup application / script (**bauh --tray=1**). In order to autostart the application, use your Desktop Environment settings to register it as a startup application / script (**bauh --tray=1**).
### Uninstallation ### Uninstallation
Before uninstalling bauh via your package manager, consider executing `bauh --clean` to remove configuration and cache files stored in your **HOME** folder. Before uninstalling bauh via your package manager, consider executing `bauh --reset` to remove configuration and cache files stored in your **HOME** folder.
### Theme issues
If bauh is not starting properly after changing its style, execute `bauh --reset` to reset its configuration or just delete the **style** key from the file **~/.config/bauh/config.json**.
### Gems ( package technology support ) ### Gems ( package technology support )
#### Flatpak ( flatpak ) #### Flatpak ( flatpak )
@@ -123,10 +126,10 @@ will be pre-downloaded faster ( it does **NOT** modify your **pacman** settings
b) same as previous, but related to **COMPRESSXZ** definition ( if '--threads=0' is not defined ) b) same as previous, but related to **COMPRESSXZ** definition ( if '--threads=0' is not defined )
Obs: this feature can be disabled through the environment variable **BAUH_ARCH_OPTIMIZE=0** Obs: this feature can be disabled through the environment variable **BAUH_ARCH_OPTIMIZE=0**
( For more information about these optimizations, have a look at [Makepkg](https://wiki.archlinux.org/index.php/Makepkg) ( For more information about these optimizations, have a look at [Makepkg](https://wiki.archlinux.org/index.php/Makepkg) )
- Arch package memory-indexer running every 20 minutes. This memory index is used when AUR Api cannot handle the amount of results found for a given search. It can be disabled via the environment variable **BAUH_ARCH_AUR_INDEX_UPDATER=0**. - Arch package memory-indexer running every 20 minutes. This memory index is used when AUR Api cannot handle the amount of results found for a given search. It can be disabled via the environment variable **BAUH_ARCH_AUR_INDEX_UPDATER=0**.
- If some of your installed packages are not categorized, send an e-mail to **bauh4linux@gmail.com** informing their names and categories in the following format: ```name=category1[,category2,category3,...]``` - If some of your installed packages are not categorized, send an e-mail to **bauh4linux@gmail.com** informing their names and categories in the following format: ```name=category1[,category2,category3,...]```
- Transitive dependencies checking can be disabled through the environment variable **BAUH_ARCH_CHECK_SUBDEPS=0**. The dependency checking process will be faster, but the application will ask for a confirmation every time a not installed dependency is detected.
### General settings ### General settings
You can change some application settings via environment variables or arguments (type ```bauh --help``` to get more information). You can change some application settings via environment variables or arguments (type ```bauh --help``` to get more information).

View File

@@ -1,4 +1,4 @@
__version__ = '0.7.3' __version__ = '0.7.4'
__app_name__ = 'bauh' __app_name__ = 'bauh'
import os import os

View File

@@ -29,7 +29,7 @@ def main():
logger = logs.new_logger(__app_name__, bool(args.logs)) logger = logs.new_logger(__app_name__, bool(args.logs))
app_args.validate(args, logger) app_args.validate(args, logger)
if args.clean: if args.reset:
util.clean_app_files() util.clean_app_files()
exit(0) exit(0)

View File

@@ -36,7 +36,7 @@ def read() -> Namespace:
parser.add_argument('--logs', action="store", default=int(os.getenv('BAUH_LOGS', 0)), choices=[0, 1], type=int, help='If the application logs should be displayed. Default: %(default)s') parser.add_argument('--logs', action="store", default=int(os.getenv('BAUH_LOGS', 0)), choices=[0, 1], type=int, help='If the application logs should be displayed. Default: %(default)s')
parser.add_argument('--show-panel', action="store_true", help='Shows the management panel after the app icon is attached to the tray.') parser.add_argument('--show-panel', action="store_true", help='Shows the management panel after the app icon is attached to the tray.')
parser.add_argument('-dmt', '--download-mthread', action="store", default=os.getenv('BAUH_DOWNLOAD_MULTITHREAD', 1), choices=[0, 1], type=int, help='If installation files should be downloaded using multi-threads (only possible if aria2c is installed). Not all gems support this feature. Check README.md. Default: %(default)s') parser.add_argument('-dmt', '--download-mthread', action="store", default=os.getenv('BAUH_DOWNLOAD_MULTITHREAD', 1), choices=[0, 1], type=int, help='If installation files should be downloaded using multi-threads (only possible if aria2c is installed). Not all gems support this feature. Check README.md. Default: %(default)s')
parser.add_argument('--clean', action="store_true", help='Removes all configuration and cache files') parser.add_argument('--reset', action="store_true", help='Removes all configuration and cache files')
return parser.parse_args() return parser.parse_args()

View File

@@ -4,6 +4,9 @@ from typing import Set, List
from bauh.api.http import HttpClient from bauh.api.http import HttpClient
import urllib.parse import urllib.parse
from bauh.gems.arch import pacman
from bauh.gems.arch.exceptions import PackageNotFoundException
URL_INFO = 'https://aur.archlinux.org/rpc/?v=5&type=info&' URL_INFO = 'https://aur.archlinux.org/rpc/?v=5&type=info&'
URL_SRC_INFO = 'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h=' URL_SRC_INFO = 'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h='
URL_SEARCH = 'https://aur.archlinux.org/rpc/?v=5&type=search&arg=' URL_SEARCH = 'https://aur.archlinux.org/rpc/?v=5&type=search&arg='
@@ -46,5 +49,18 @@ class AURClient:
return info return info
def get_all_dependencies(self, name: str) -> Set[str]:
deps = set()
info = self.get_src_info(name)
if not info:
raise PackageNotFoundException(name)
for attr in ('makedepends', 'depends', 'checkdepends'):
if info.get(attr):
deps.update([pacman.RE_DEP_OPERATORS.split(dep)[0] for dep in info[attr]])
return deps
def _map_names_as_queries(self, names) -> str: def _map_names_as_queries(self, names) -> str:
return '&'.join(['arg[{}]={}'.format(i, urllib.parse.quote(n)) for i, n in enumerate(names)]) return '&'.join(['arg[{}]={}'.format(i, urllib.parse.quote(n)) for i, n in enumerate(names)])

View File

@@ -1,4 +1,4 @@
from typing import Set from typing import Set, List, Tuple
from bauh.api.abstract.handler import ProcessWatcher from bauh.api.abstract.handler import ProcessWatcher
from bauh.api.abstract.view import MultipleSelectComponent, InputOption from bauh.api.abstract.view import MultipleSelectComponent, InputOption
@@ -16,7 +16,7 @@ def request_optional_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatch
opts = [] opts = []
for p, d in pkg_mirrors.items(): for p, d in pkg_mirrors.items():
op = InputOption('{}{} ( {}: {} )'.format(p, ': ' + d['desc'] if d['desc'] else '', i18n['mirror'], d['mirror'].upper()), p) op = InputOption('{}{} ( {}: {} )'.format(p, ': ' + d['desc'] if d['desc'] else '', i18n['repository'], d['mirror'].upper()), p)
op.icon_path = _get_mirror_icon(d['mirror']) op.icon_path = _get_mirror_icon(d['mirror'])
opts.append(op) opts.append(op)
@@ -25,25 +25,29 @@ def request_optional_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatch
default_options=None) default_options=None)
install = watcher.request_confirmation(title=i18n['arch.install.optdeps.request.title'], install = watcher.request_confirmation(title=i18n['arch.install.optdeps.request.title'],
body='<p>{}</p>'.format(i18n['arch.install.optdeps.request.body'].format(bold(pkgname)) + ':'), body='<p>{}.</p><p>{}:</p>'.format(i18n['arch.install.optdeps.request.body'].format(bold(pkgname)), i18n['arch.install.optdeps.request.help']),
components=[view_opts], components=[view_opts],
confirmation_label=i18n['install'], confirmation_label=i18n['install'].capitalize(),
deny_label=i18n['cancel']) deny_label=i18n['do_not.install'].capitalize())
if install: if install:
return {o.value for o in view_opts.values} return {o.value for o in view_opts.values}
def request_install_missing_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatcher, i18n: I18n) -> bool: def request_install_missing_deps(pkgname: str, deps: List[Tuple[str, str]], watcher: ProcessWatcher, i18n: I18n) -> bool:
msg = '<p>{}</p>'.format(i18n['arch.missing_deps.body'].format(bold(pkgname)) + ':') msg = '<p>{}</p>'.format(i18n['arch.missing_deps.body'].format(name=bold(pkgname) if pkgname else '', deps=bold(str(len(deps)))))
opts = [] opts = []
for p, m in pkg_mirrors.items():
op = InputOption('{} ( {}: {} )'.format(p, i18n['mirror'], m.upper()), p) sorted_deps = [*deps]
sorted_deps.sort(key=lambda e: e[0])
for dep in sorted_deps:
op = InputOption('{} ( {}: {} )'.format(dep[0], i18n['repository'], dep[1].upper()), dep[0])
op.read_only = True op.read_only = True
op.icon_path = _get_mirror_icon(m) op.icon_path = _get_mirror_icon(dep[1])
opts.append(op) opts.append(op)
comp = MultipleSelectComponent(label='', options=opts, default_options=set(opts)) comp = MultipleSelectComponent(label='', options=opts, default_options=set(opts))
return watcher.request_confirmation(i18n['arch.missing_deps.title'], msg, [comp], confirmation_label=i18n['continue'].capitalize()) return watcher.request_confirmation(i18n['arch.missing_deps.title'], msg, [comp], confirmation_label=i18n['continue'].capitalize(), deny_label=i18n['cancel'].capitalize())

View File

@@ -6,7 +6,7 @@ import subprocess
import time import time
from pathlib import Path from pathlib import Path
from threading import Thread from threading import Thread
from typing import List, Set, Type from typing import List, Set, Type, Tuple, Dict
import requests import requests
@@ -22,6 +22,7 @@ from bauh.commons.system import SystemProcess, ProcessHandler, new_subprocess, r
from bauh.gems.arch import BUILD_DIR, aur, pacman, makepkg, pkgbuild, message, confirmation, disk, git, suggestions, \ from bauh.gems.arch import BUILD_DIR, aur, pacman, makepkg, pkgbuild, message, confirmation, disk, git, suggestions, \
gpg, URL_CATEGORIES_FILE, CATEGORIES_CACHE_DIR, CATEGORIES_FILE_PATH gpg, URL_CATEGORIES_FILE, CATEGORIES_CACHE_DIR, CATEGORIES_FILE_PATH
from bauh.gems.arch.aur import AURClient from bauh.gems.arch.aur import AURClient
from bauh.gems.arch.depedencies import DependenciesAnalyser
from bauh.gems.arch.mapper import ArchDataMapper from bauh.gems.arch.mapper import ArchDataMapper
from bauh.gems.arch.model import ArchPackage from bauh.gems.arch.model import ArchPackage
from bauh.gems.arch.worker import AURIndexUpdater, ArchDiskCacheUpdater, ArchCompilationOptimizer from bauh.gems.arch.worker import AURIndexUpdater, ArchDiskCacheUpdater, ArchCompilationOptimizer
@@ -62,6 +63,7 @@ class ArchManager(SoftwareManager):
self.categories_mapper = CategoriesDownloader('AUR', context.http_client, context.logger, self, self.context.disk_cache, self.categories_mapper = CategoriesDownloader('AUR', context.http_client, context.logger, self, self.context.disk_cache,
URL_CATEGORIES_FILE, CATEGORIES_CACHE_DIR, CATEGORIES_FILE_PATH) URL_CATEGORIES_FILE, CATEGORIES_CACHE_DIR, CATEGORIES_FILE_PATH)
self.categories = {} self.categories = {}
self.deps_analyser = DependenciesAnalyser(self.aur_client)
def _upgrade_search_result(self, apidata: dict, installed_pkgs: dict, downgrade_enabled: bool, res: SearchResult, disk_loader: DiskCacheLoader): def _upgrade_search_result(self, apidata: dict, installed_pkgs: dict, downgrade_enabled: bool, res: SearchResult, disk_loader: DiskCacheLoader):
app = self.mapper.map_api_data(apidata, installed_pkgs['not_signed'], self.categories) app = self.mapper.map_api_data(apidata, installed_pkgs['not_signed'], self.categories)
@@ -219,7 +221,7 @@ class ArchManager(SoftwareManager):
break break
watcher.change_substatus(self.i18n['arch.downgrade.install_older']) watcher.change_substatus(self.i18n['arch.downgrade.install_older'])
return self._make_pkg(pkg.name, pkg.maintainer, root_password, handler, app_build_dir, clone_path, dependency=False, skip_optdeps=True) return self._build(pkg.name, pkg.maintainer, root_password, handler, app_build_dir, clone_path, dependency=False, skip_optdeps=True)
else: else:
watcher.show_message(title=self.i18n['arch.downgrade.error'], watcher.show_message(title=self.i18n['arch.downgrade.error'],
body=self.i18n['arch.downgrade.impossible'].format(pkg.name), body=self.i18n['arch.downgrade.impossible'].format(pkg.name),
@@ -308,11 +310,17 @@ class ArchManager(SoftwareManager):
srcinfo = self.aur_client.get_src_info(pkg.name) srcinfo = self.aur_client.get_src_info(pkg.name)
if srcinfo: if srcinfo:
if srcinfo.get('makedepends'):
info['12_makedepends'] = srcinfo['makedepends']
if srcinfo.get('depends'): if srcinfo.get('depends'):
info['11_dependson'] = srcinfo['depends'] info['13_dependson'] = srcinfo['depends']
if srcinfo.get('optdepends'): if srcinfo.get('optdepends'):
info['12_optdepends'] = srcinfo['optdepends'] info['14_optdepends'] = srcinfo['optdepends']
if srcinfo.get('checkdepends'):
info['15_checkdepends'] = srcinfo['checkdepends']
if pkg.pkgbuild: if pkg.pkgbuild:
info['00_pkg_build'] = pkg.pkgbuild info['00_pkg_build'] = pkg.pkgbuild
@@ -355,10 +363,9 @@ class ArchManager(SoftwareManager):
if os.path.exists(temp_dir): if os.path.exists(temp_dir):
shutil.rmtree(temp_dir) shutil.rmtree(temp_dir)
def _install_deps(self, deps: Set[str], pkg_mirrors: dict, root_password: str, handler: ProcessHandler, change_progress: bool = False) -> str: def _install_deps(self, deps: List[Tuple[str, str]], root_password: str, handler: ProcessHandler, change_progress: bool = False) -> str:
""" """
:param deps: :param pkgs_repos:
:param pkg_mirrors:
:param root_password: :param root_password:
:param handler: :param handler:
:return: not installed dependency :return: not installed dependency
@@ -367,27 +374,25 @@ class ArchManager(SoftwareManager):
progress = 0 progress = 0
self._update_progress(handler.watcher, 1, change_progress) self._update_progress(handler.watcher, 1, change_progress)
for pkgname in deps: for dep in deps:
handler.watcher.change_substatus(self.i18n['arch.install.dependency.install'].format(bold('{} ()'.format(dep[0], dep[1]))))
mirror = pkg_mirrors[pkgname] if dep[1] == 'aur':
handler.watcher.change_substatus(self.i18n['arch.install.dependency.install'].format(bold('{} ()'.format(pkgname, mirror)))) installed = self._install_from_aur(pkgname=dep[0], maintainer=None, root_password=root_password, handler=handler, dependency=True, change_progress=False)
if mirror == 'aur':
installed = self._install_from_aur(pkgname=pkgname, maintainer=None, root_password=root_password, handler=handler, dependency=True, change_progress=False)
else: else:
installed = self._install(pkgname=pkgname, maintainer=None, root_password=root_password, handler=handler, install_file=None, mirror=mirror, change_progress=False) installed = self._install(pkgname=dep[0], maintainer=None, root_password=root_password, handler=handler, install_file=None, mirror=dep[1], change_progress=False)
if not installed: if not installed:
return pkgname return dep[0]
progress += progress_increment progress += progress_increment
self._update_progress(handler.watcher, progress, change_progress) self._update_progress(handler.watcher, progress, change_progress)
self._update_progress(handler.watcher, 100, change_progress) self._update_progress(handler.watcher, 100, change_progress)
def _map_mirrors(self, pkgnames: Set[str]) -> dict: def _map_repos(self, pkgnames: Set[str]) -> dict:
pkg_mirrors = pacman.get_mirrors(pkgnames) # getting mirrors set pkg_mirrors = pacman.get_repositories(pkgnames) # getting mirrors set
if len(pkgnames) != pkg_mirrors: # checking if any dep not found in the distro mirrors are from AUR if len(pkgnames) != len(pkg_mirrors): # checking if any dep not found in the distro mirrors are from AUR
nomirrors = {p for p in pkgnames if p not in pkg_mirrors} nomirrors = {p for p in pkgnames if p not in pkg_mirrors}
for pkginfo in self.aur_client.get_info(nomirrors): for pkginfo in self.aur_client.get_info(nomirrors):
if pkginfo.get('Name') in nomirrors: if pkginfo.get('Name') in nomirrors:
@@ -426,12 +431,16 @@ class ArchManager(SoftwareManager):
return True return True
def _make_pkg(self, pkgname: str, maintainer: str, root_password: str, handler: ProcessHandler, build_dir: str, project_dir: str, dependency: bool, skip_optdeps: bool = False, change_progress: bool = True) -> bool: def _should_check_subdeps(self):
return bool(int(os.getenv('BAUH_ARCH_CHECK_SUBDEPS', 1)))
def _build(self, pkgname: str, maintainer: str, root_password: str, handler: ProcessHandler, build_dir: str, project_dir: str, dependency: bool, skip_optdeps: bool = False, change_progress: bool = True) -> bool:
self._pre_download_source(pkgname, project_dir, handler.watcher) self._pre_download_source(pkgname, project_dir, handler.watcher)
self._update_progress(handler.watcher, 50, change_progress) self._update_progress(handler.watcher, 50, change_progress)
if not self._install_missings_deps_and_keys(pkgname, root_password, handler, project_dir):
if not self._handle_deps_and_keys(pkgname, root_password, handler, project_dir, check_subdeps=self._should_check_subdeps()):
return False return False
# building main package # building main package
@@ -456,39 +465,83 @@ class ArchManager(SoftwareManager):
handler.watcher.change_substatus(self.i18n['arch.optdeps.checking'].format(bold(pkgname))) handler.watcher.change_substatus(self.i18n['arch.optdeps.checking'].format(bold(pkgname)))
if self._install_optdeps(pkgname, root_password, handler, project_dir, change_progress=change_progress): if self._install_optdeps(pkgname, root_password, handler, project_dir):
return True return True
return False return False
def _install_missings_deps_and_keys(self, pkgname: str, root_password: str, handler: ProcessHandler, pkgdir: str) -> bool: def _map_known_missing_deps(self, known_deps: Dict[str, str], watcher: ProcessWatcher, check_subdeps: bool = True) -> List[Tuple[str, str]]:
sorted_deps = [] # it will hold the proper order to install the missing dependencies
repo_deps, aur_deps = set(), set()
for dep, repo in known_deps.items():
if repo == 'aur':
aur_deps.add(dep)
else:
repo_deps.add(dep)
if check_subdeps:
for deps in ((repo_deps, 'repo'), (aur_deps, 'aur')):
if deps[0]:
missing_subdeps = self.deps_analyser.get_missing_subdeps_of(deps[0], deps[1])
if missing_subdeps:
for dep in missing_subdeps:
if not dep[1]:
message.show_dep_not_found(dep[0], self.i18n, watcher)
return
for dep in missing_subdeps:
sorted_deps.append(dep)
for dep, repo in known_deps.items():
if repo != 'aur':
sorted_deps.append((dep, repo))
for dep in aur_deps:
sorted_deps.append((dep, 'aur'))
return sorted_deps
def _map_unknown_missing_deps(self, deps: List[str], watcher: ProcessWatcher, check_subdeps: bool = True) -> List[Tuple[str, str]]:
depnames = {RE_SPLIT_VERSION.split(dep)[0] for dep in deps}
dep_repos = self._map_repos(depnames)
if len(depnames) != len(dep_repos): # checking if a dependency could not be found in any mirror
for dep in depnames:
if dep not in dep_repos:
message.show_dep_not_found(dep, self.i18n, watcher)
return
return self._map_known_missing_deps(dep_repos, watcher, check_subdeps)
def _handle_deps_and_keys(self, pkgname: str, root_password: str, handler: ProcessHandler, pkgdir: str, check_subdeps: bool = True) -> bool:
handler.watcher.change_substatus(self.i18n['arch.checking.deps'].format(bold(pkgname))) handler.watcher.change_substatus(self.i18n['arch.checking.deps'].format(bold(pkgname)))
check_res = makepkg.check(pkgdir, handler) check_res = makepkg.check(pkgdir, handler)
if check_res: if check_res:
if check_res.get('missing_deps'): if check_res.get('missing_deps'):
depnames = {RE_SPLIT_VERSION.split(dep)[0] for dep in check_res['missing_deps']} handler.watcher.change_substatus(self.i18n['arch.checking.missing_deps'].format(bold(pkgname)))
dep_mirrors = self._map_mirrors(depnames) sorted_deps = self._map_unknown_missing_deps(check_res['missing_deps'], handler.watcher, check_subdeps=check_subdeps)
for dep in depnames: # cheking if a dependency could not be found in any mirror if sorted_deps is None:
if dep not in dep_mirrors:
message.show_dep_not_found(dep, self.i18n, handler.watcher)
return False return False
handler.watcher.change_substatus(self.i18n['arch.missing_deps_found'].format(bold(pkgname))) handler.watcher.change_substatus(self.i18n['arch.missing_deps_found'].format(bold(pkgname)))
if not confirmation.request_install_missing_deps(pkgname, dep_mirrors, handler.watcher, self.i18n): if not confirmation.request_install_missing_deps(pkgname, sorted_deps, handler.watcher, self.i18n):
handler.watcher.print(self.i18n['action.cancelled']) handler.watcher.print(self.i18n['action.cancelled'])
return False return False
dep_not_installed = self._install_deps(depnames, dep_mirrors, root_password, handler, change_progress=False) dep_not_installed = self._install_deps(sorted_deps, root_password, handler, change_progress=False)
if dep_not_installed: if dep_not_installed:
message.show_dep_not_installed(handler.watcher, pkgname, dep_not_installed, self.i18n) message.show_dep_not_installed(handler.watcher, pkgname, dep_not_installed, self.i18n)
return False return False
# it is necessary to re-check because missing PGP keys are only notified when there are none missing # it is necessary to re-check because missing PGP keys are only notified when there are none missing
return self._install_missings_deps_and_keys(pkgname, root_password, handler, pkgdir) return self._handle_deps_and_keys(pkgname, root_password, handler, pkgdir, check_subdeps=False)
if check_res.get('gpg_key'): if check_res.get('gpg_key'):
if handler.watcher.request_confirmation(title=self.i18n['arch.aur.install.unknown_key.title'], if handler.watcher.request_confirmation(title=self.i18n['arch.aur.install.unknown_key.title'],
@@ -510,7 +563,7 @@ class ArchManager(SoftwareManager):
return True return True
def _install_optdeps(self, pkgname: str, root_password: str, handler: ProcessHandler, pkgdir: str, change_progress: bool = True) -> bool: def _install_optdeps(self, pkgname: str, root_password: str, handler: ProcessHandler, pkgdir: str) -> bool:
with open('{}/.SRCINFO'.format(pkgdir)) as f: with open('{}/.SRCINFO'.format(pkgdir)) as f:
odeps = pkgbuild.read_optdeps_as_dict(f.read()) odeps = pkgbuild.read_optdeps_as_dict(f.read())
@@ -522,17 +575,47 @@ class ArchManager(SoftwareManager):
if not to_install: if not to_install:
return True return True
pkg_mirrors = self._map_mirrors(to_install) pkg_mirrors = self._map_repos(to_install)
if pkg_mirrors: if pkg_mirrors:
final_optdeps = {dep: {'desc': odeps.get(dep), 'mirror': pkg_mirrors.get(dep)} for dep in to_install if dep in pkg_mirrors} final_optdeps = {dep: {'desc': odeps.get(dep), 'mirror': pkg_mirrors.get(dep)} for dep, mirror in pkg_mirrors.items()}
deps_to_install = confirmation.request_optional_deps(pkgname, final_optdeps, handler.watcher, self.i18n) deps_to_install = confirmation.request_optional_deps(pkgname, final_optdeps, handler.watcher, self.i18n)
if not deps_to_install: if not deps_to_install:
return True return True
else: else:
dep_not_installed = self._install_deps(deps_to_install, pkg_mirrors, root_password, handler, change_progress=True) sorted_deps = []
if self._should_check_subdeps():
missing_deps = self._map_known_missing_deps({d: pkg_mirrors[d] for d in deps_to_install}, handler.watcher)
if missing_deps is None:
return True # because the main package installation was successful
if missing_deps:
same_as_selected = len(deps_to_install) == len(missing_deps) and deps_to_install == {d[0] for d in missing_deps}
if not same_as_selected and not confirmation.request_install_missing_deps(None, missing_deps, handler.watcher, self.i18n):
handler.watcher.print(self.i18n['action.cancelled'])
return True # because the main package installation was successful
sorted_deps.extend(missing_deps)
else:
aur_deps, repo_deps = [], []
for dep in deps_to_install:
mirror = pkg_mirrors[dep]
if mirror == 'aur':
aur_deps.append((dep, mirror))
else:
repo_deps.append((dep, mirror))
sorted_deps.extend(repo_deps)
sorted_deps.extend(aur_deps)
dep_not_installed = self._install_deps(sorted_deps, root_password, handler, change_progress=True)
if dep_not_installed: if dep_not_installed:
message.show_optdep_not_installed(dep_not_installed, handler.watcher, self.i18n) message.show_optdep_not_installed(dep_not_installed, handler.watcher, self.i18n)
@@ -644,7 +727,7 @@ class ArchManager(SoftwareManager):
if uncompress: if uncompress:
uncompress_dir = '{}/{}'.format(app_build_dir, pkgname) uncompress_dir = '{}/{}'.format(app_build_dir, pkgname)
return self._make_pkg(pkgname=pkgname, return self._build(pkgname=pkgname,
maintainer=maintainer, maintainer=maintainer,
root_password=root_password, root_password=root_password,
handler=handler, handler=handler,

View File

@@ -0,0 +1,108 @@
from threading import Thread
from typing import Set, List, Tuple
from bauh.gems.arch import pacman
from bauh.gems.arch.aur import AURClient
class DependenciesAnalyser:
def __init__(self, aur_client: AURClient):
self.aur_client = aur_client
def _fill_mirror(self, name: str, output: List[Tuple[str, str]]):
mirror = pacman.read_repository_from_info(name)
if mirror:
output.append((name, mirror))
return
guess = pacman.guess_repository(name)
if guess:
output.append(guess)
return
aur_info = self.aur_client.get_src_info(name)
if aur_info:
output.append((name, 'aur'))
return
output.append((name, ''))
def get_missing_packages(self, names: Set[str], mirror: str = None, in_analysis: Set[str] = None) -> List[Tuple[str, str]]:
"""
:param names:
:param mirror:
:param in_analysis: global set storing all names in analysis to avoid repeated recursion
:return:
"""
global_in_analysis = in_analysis if in_analysis else set()
missing_names = pacman.check_missing({n for n in names if n not in in_analysis})
if missing_names:
missing_root = []
threads = []
if not mirror:
for name in missing_names:
t = Thread(target=self._fill_mirror, args=(name, missing_root))
t.start()
threads.append(t)
for t in threads:
t.join()
threads.clear()
# checking if there is any unknown dependency:
for rdep in missing_root:
if not rdep[1]:
return missing_root
else:
global_in_analysis.add(rdep[0])
else:
for missing in missing_names:
missing_root.append((missing, mirror))
global_in_analysis.add(missing)
missing_sub = []
for rdep in missing_root:
subdeps = self.aur_client.get_all_dependencies(rdep[0]) if rdep[1] == 'aur' else pacman.read_dependencies(rdep[0])
subdeps_not_analysis = {sd for sd in subdeps if sd not in global_in_analysis}
if subdeps_not_analysis:
missing_subdeps = self.get_missing_packages(subdeps_not_analysis, in_analysis=global_in_analysis)
# checking if there is any unknown:
if missing_subdeps:
for subdep in missing_subdeps:
if not subdep[0]:
return [*missing_subdeps, *missing_root]
if subdep[0] not in missing_names:
missing_sub.append(subdep)
return [*missing_sub, *missing_root]
def get_missing_subdeps_of(self, names: Set[str], mirror: str) -> List[Tuple[str, str]]:
missing = []
already_added = {*names}
in_analyses = {*names}
for name in names:
subdeps = self.aur_client.get_all_dependencies(name) if mirror == 'aur' else pacman.read_dependencies(name)
if subdeps:
missing_subdeps = self.get_missing_packages(subdeps, in_analysis=in_analyses)
if missing_subdeps:
for subdep in missing_subdeps: # checking if there is any unknown:
if subdep[0] not in already_added:
missing.append(subdep)
if not subdep[0]:
return missing
return missing

View File

@@ -0,0 +1,5 @@
class PackageNotFoundException(Exception):
def __init__(self, name: str):
self.name = name

View File

@@ -1,11 +1,14 @@
import re import re
from threading import Thread from threading import Thread
from typing import List, Set from typing import List, Set, Tuple
from bauh.commons.system import run_cmd, new_subprocess, new_root_subprocess, SystemProcess from bauh.commons.system import run_cmd, new_subprocess, new_root_subprocess, SystemProcess
from bauh.gems.arch.exceptions import PackageNotFoundException
RE_DEPS = re.compile(r'[\w\-_]+:[\s\w_\-\.]+\s+\[\w+\]') RE_DEPS = re.compile(r'[\w\-_]+:[\s\w_\-\.]+\s+\[\w+\]')
RE_OPTDEPS = re.compile(r'[\w\._\-]+\s*:') RE_OPTDEPS = re.compile(r'[\w\._\-]+\s*:')
RE_DEP_NOTFOUND = re.compile(r'error:.+\'(.+)\'')
RE_DEP_OPERATORS = re.compile(r'[<>=]')
def is_enabled() -> bool: def is_enabled() -> bool:
@@ -13,7 +16,7 @@ def is_enabled() -> bool:
return res and not res.strip().startswith('which ') return res and not res.strip().startswith('which ')
def get_mirrors(pkgs: Set[str]) -> dict: def get_repositories(pkgs: Set[str]) -> dict:
pkgre = '|'.join(pkgs).replace('+', r'\+').replace('.', r'\.') pkgre = '|'.join(pkgs).replace('+', r'\+').replace('.', r'\.')
searchres = new_subprocess(['pacman', '-Ss', pkgre]).stdout searchres = new_subprocess(['pacman', '-Ss', pkgre]).stdout
@@ -26,10 +29,19 @@ def get_mirrors(pkgs: Set[str]) -> dict:
if p in match: if p in match:
mirrors[p] = match.split('/')[0] mirrors[p] = match.split('/')[0]
not_found = {pkg for pkg in pkgs if pkg and pkg not in mirrors}
if not_found: # if there are some packages not found, try to find via the single method:
for dep in not_found:
mirror_data = guess_repository(dep)
if mirror_data:
mirrors[mirror_data[0]] = mirror_data[1]
return mirrors return mirrors
def is_available_from_mirrors(pkg_name: str) -> bool: def is_available_in_repositories(pkg_name: str) -> bool:
return bool(run_cmd('pacman -Ss ' + pkg_name)) return bool(run_cmd('pacman -Ss ' + pkg_name))
@@ -216,3 +228,129 @@ def list_ignored_packages(config_path: str = '/etc/pacman.conf') -> Set[str]:
pacman_conf.terminate() pacman_conf.terminate()
grep.terminate() grep.terminate()
return ignored return ignored
def check_missing(names: Set[str]) -> Set[str]:
installed = new_subprocess(['pacman', '-Qq', *names])
not_installed = set()
for o in installed.stderr:
if o:
err_line = o.decode()
if err_line:
not_found = [n for n in RE_DEP_NOTFOUND.findall(err_line) if n]
if not_found:
not_installed.update(not_found)
return not_installed
def read_repository_from_info(name: str) -> str:
info = new_subprocess(['pacman', '-Si', name])
not_found = False
for o in info.stderr:
if o:
err_line = o.decode()
if RE_DEP_NOTFOUND.findall(err_line):
not_found = True
if not_found:
return
mirror = None
for o in new_subprocess(['grep', '-Po', "Repository\s+:\s+\K.+"], stdin=info.stdout).stdout:
if o:
line = o.decode().strip()
if line:
mirror = line
return mirror
def guess_repository(name: str) -> Tuple[str, str]:
if not name:
raise Exception("'name' cannot be None or blank")
only_name = RE_DEP_OPERATORS.split(name)[0]
res = run_cmd('pacman -Ss {}'.format(only_name))
if res:
lines = res.split('\n')
if lines:
for line in lines:
if line and not line.startswith(' '):
data = line.split('/')
line_name, line_repo = data[1].split(' ')[0], data[0]
provided = read_provides(line_name)
if provided:
found = {p for p in provided if only_name == RE_DEP_OPERATORS.split(p)[0]}
if found:
return line_name, line_repo
def read_provides(name: str) -> Set[str]:
dep_info = new_subprocess(['pacman', '-Si', name])
not_found = False
for o in dep_info.stderr:
if o:
err_line = o.decode()
if err_line:
if RE_DEP_NOTFOUND.findall(err_line):
not_found = True
if not_found:
raise PackageNotFoundException(name)
provides = None
for out in new_subprocess(['grep', '-Po', 'Provides\s+:\s\K(.+)'], stdin=dep_info.stdout).stdout:
if out:
provided_names = [p.strip() for p in out.decode().strip().split(' ') if p]
if provided_names[0].lower() == 'none':
provides = {name}
else:
provides = set(provided_names)
return provides
def read_dependencies(name: str) -> Set[str]:
dep_info = new_subprocess(['pacman', '-Si', name])
not_found = False
for o in dep_info.stderr:
if o:
err_line = o.decode()
if err_line:
if RE_DEP_NOTFOUND.findall(err_line):
not_found = True
if not_found:
raise PackageNotFoundException(name)
depends_on = set()
for out in new_subprocess(['grep', '-Po', 'Depends\s+On\s+:\s\K(.+)'], stdin=dep_info.stdout).stdout:
if out:
line = out.decode().strip()
if line:
depends_on.update([d for d in line.split(' ') if d and d.lower() != 'none'])
return depends_on

View File

@@ -36,7 +36,7 @@ aur.info.conflicts with=té un conflicte amb
arch.install.conflict.popup.title=Sha detectat un conflicte arch.install.conflict.popup.title=Sha detectat un conflicte
arch.install.conflict.popup.body=Les aplicacions {} estan en conflicte. Heu de desinstal·lar una per a instal·lar laltra. Voleu continuar? arch.install.conflict.popup.body=Les aplicacions {} estan en conflicte. Heu de desinstal·lar una per a instal·lar laltra. Voleu continuar?
arch.missing_deps.title=Dependències mancants arch.missing_deps.title=Dependències mancants
arch.missing_deps.body=Shan dinstal·lar les dependències següents abans de continuar amb la instal·lació de {} arch.missing_deps.body=Shan dinstal·lar les {deps} dependències següents abans de continuar amb la instal·lació de {name}
arch.downgrade.error=Error arch.downgrade.error=Error
arch.downgrade.impossible=No sha pogut revertir la versió de {} arch.downgrade.impossible=No sha pogut revertir la versió de {}
aur.history.1_version=versió aur.history.1_version=versió
@@ -45,6 +45,7 @@ aur.history.3_date=data
arch.downloading.package=Sestà baixant el paquet arch.downloading.package=Sestà baixant el paquet
arch.uncompressing.package=Sestà descomprimint el paquet arch.uncompressing.package=Sestà descomprimint el paquet
arch.checking.deps=Sestan comprovant les dependències de {} arch.checking.deps=Sestan comprovant les dependències de {}
arch.checking.missing_deps=Verificació de les dependències que falten de {}
arch.missing_deps_found=Dependències mancants per a {} arch.missing_deps_found=Dependències mancants per a {}
arch.building.package=Sestà compilant el paquet {} arch.building.package=Sestà compilant el paquet {}
arch.checking.conflicts=Sestà comprovant si hi ha conflictes amb {} arch.checking.conflicts=Sestà comprovant si hi ha conflictes amb {}
@@ -69,8 +70,10 @@ aur.info.09_last_modified=darrera modificació
aur.info.10_url=url de baixada aur.info.10_url=url de baixada
aur.info.11_pkg_build_url=url pkgbuild aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dependències aur.info.12_makedepends=dependències de compilació
aur.info.12_optdepends=dependències opcionals aur.info.13_dependson=dependències dinstal·lació
aur.info.14_optdepends=dependències opcionals
aur.info.15_checkdepends=dependències de verificació
aur.info.14_installed_files=Fitxers instal·lats aur.info.14_installed_files=Fitxers instal·lats
arch.install.dep_not_found.title=No sha trobat la dependència arch.install.dep_not_found.title=No sha trobat la dependència
arch.install.dep_not_found.body=No sha trobat la dependència requerida {} a lAUR ni als servidors rèplica per defecte. Sha cancel·lat la instal·lació. arch.install.dep_not_found.body=No sha trobat la dependència requerida {} a lAUR ni als servidors rèplica per defecte. Sha cancel·lat la instal·lació.
@@ -79,7 +82,8 @@ arch.install.dependency.install.error=No sha pogut instal·lar el paquet depe
arch.uninstall.required_by=No es pot desinstal·lar {} perquè és necessari per al funcionament dels paquets següents arch.uninstall.required_by=No es pot desinstal·lar {} perquè és necessari per al funcionament dels paquets següents
arch.uninstall.required_by.advice=Heu de desinstal·lar-los abans de desinstal·lar {} arch.uninstall.required_by.advice=Heu de desinstal·lar-los abans de desinstal·lar {}
arch.install.optdeps.request.title=Dependències opcionals arch.install.optdeps.request.title=Dependències opcionals
arch.install.optdeps.request.body={} sha instal·lat correctament. Hi ha paquets opcionals associats que potser voldreu instal·lar (marqueu els que voleu) arch.install.optdeps.request.body={} sha instal·lat correctament. Hi ha paquets opcionals associats que potser voldreu instal·lar
arch.install.optdeps.request.help=Marqueu els que voleu
arch.install.optdep.error=No sha pogut instal·lar el paquet opcional {} arch.install.optdep.error=No sha pogut instal·lar el paquet opcional {}
arch.optdeps.checking=Sestan comprovant les dependències opcionals de {} arch.optdeps.checking=Sestan comprovant les dependències opcionals de {}
arch.warning.disabled=Sembla que no sha instal·lat {}. No podreu gestionar paquets Arch/AUR. arch.warning.disabled=Sembla que no sha instal·lat {}. No podreu gestionar paquets Arch/AUR.

View File

@@ -4,7 +4,7 @@ gem.aur.install.warning=AUR Pakete werden von einer unabhängigen Nutzergemeinsc
arch.install.conflict.popup.title=Konflikt entdeckt arch.install.conflict.popup.title=Konflikt entdeckt
arch.install.conflict.popup.body=Die Anwendungen {} können nicht gleichzeitig installiert sein. Du musst eine deinstallieren um die andere zu installieren. Fortfahren? arch.install.conflict.popup.body=Die Anwendungen {} können nicht gleichzeitig installiert sein. Du musst eine deinstallieren um die andere zu installieren. Fortfahren?
arch.missing_deps.title=Fehlende Abhängigkeiten arch.missing_deps.title=Fehlende Abhängigkeiten
arch.missing_deps.body=Die folgenden Abhängigkeiten müssten installiert sein, bevor mit der {} Installation fortgefahren werden kann arch.missing_deps.body=Die folgenden {deps} Abhängigkeiten müssten installiert sein, bevor mit der {name} Installation fortgefahren werden kann
arch.downgrade.error=Fehler arch.downgrade.error=Fehler
arch.downgrade.impossible=Downgrade von {} ist nicht möglich arch.downgrade.impossible=Downgrade von {} ist nicht möglich
aur.history.1_version=Version aur.history.1_version=Version
@@ -13,6 +13,7 @@ aur.history.3_date=Datum
arch.downloading.package=Paket herunterladen arch.downloading.package=Paket herunterladen
arch.uncompressing.package=Paket entpacken arch.uncompressing.package=Paket entpacken
arch.checking.deps={} Abhängigkeiten überprüfen arch.checking.deps={} Abhängigkeiten überprüfen
arch.checking.missing_deps=Überprüfen der fehlenden Abhängigkeiten von {}
arch.missing_deps_found=Fehlende Abhängigkeiten für {} arch.missing_deps_found=Fehlende Abhängigkeiten für {}
arch.building.package=Paket {} erstellen arch.building.package=Paket {} erstellen
arch.checking.conflicts=Konflikte mit {} überprüfen arch.checking.conflicts=Konflikte mit {} überprüfen
@@ -37,8 +38,10 @@ aur.info.09_last_modified=Zuletzt verändert
aur.info.10_url=url zum Herunterladen aur.info.10_url=url zum Herunterladen
aur.info.11_pkg_build_url=url pkgbuild aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=Abhängigkeiten aur.info.12_makedepends=Kompilierungsabhängigkeiten
aur.info.12_optdepends=optionale Abhängigkeiten aur.info.13_dependson=Installationsabhängigkeiten
aur.info.14_optdepends=optionale Abhängigkeiten
aur.info.15_checkdepends=Überprüfungsabhängigkeiten
aur.info.14_installed_files=Installationsdateien aur.info.14_installed_files=Installationsdateien
arch.install.dep_not_found.title=Abhängigkeit nicht gefunden arch.install.dep_not_found.title=Abhängigkeit nicht gefunden
arch.install.dep_not_found.body=Nötige Abhängigkeit {} wurde weder im AUR noch in den standard Spiegelservern gefunden. Installation abgebrochen arch.install.dep_not_found.body=Nötige Abhängigkeit {} wurde weder im AUR noch in den standard Spiegelservern gefunden. Installation abgebrochen
@@ -47,7 +50,8 @@ arch.install.dependency.install.error=Paket {} konnte nicht installiert werden.
arch.uninstall.required_by={} konnte nicht deinstalliert werden, da es für die folgenden Pakete benötigt wird. arch.uninstall.required_by={} konnte nicht deinstalliert werden, da es für die folgenden Pakete benötigt wird.
arch.uninstall.required_by.advice=Deinstalliere sie zuerst, bevor du {} deinstalliert arch.uninstall.required_by.advice=Deinstalliere sie zuerst, bevor du {} deinstalliert
arch.install.optdeps.request.title=Optionale Abhängigkeiten arch.install.optdeps.request.title=Optionale Abhängigkeiten
arch.install.optdeps.request.body={} wurde erfolgreich installiert! Es gibt optionale zugehörige Pakete welche du vielleicht auch installieren möchtest (wähle entsprechende aus) arch.install.optdeps.request.body={} wurde erfolgreich installiert! Es gibt optionale zugehörige Pakete welche du vielleicht auch installieren möchtest
arch.install.optdeps.request.help=Wähle entsprechende aus
arch.install.optdep.error=Optionales Paket {} konnte nicht installiert werden arch.install.optdep.error=Optionales Paket {} konnte nicht installiert werden
arch.optdeps.checking={} optionale Abhängigkeiten überprüfen arch.optdeps.checking={} optionale Abhängigkeiten überprüfen
arch.warning.disabled={} scheint nicht intstalliert zu sein. Die Verwaltung von Arch / AUR Pakten wird nicht möglich sein. arch.warning.disabled={} scheint nicht intstalliert zu sein. Die Verwaltung von Arch / AUR Pakten wird nicht möglich sein.

View File

@@ -4,7 +4,7 @@ gem.aur.install.warning=AUR packages are maintained by an independent user commu
arch.install.conflict.popup.title=Conflict detected arch.install.conflict.popup.title=Conflict detected
arch.install.conflict.popup.body=The applications {} are in conflict. You must uninstall one to install the other. Continue ? arch.install.conflict.popup.body=The applications {} are in conflict. You must uninstall one to install the other. Continue ?
arch.missing_deps.title=Missing dependencies arch.missing_deps.title=Missing dependencies
arch.missing_deps.body=The following dependencies must be installed before the {} installation continues arch.missing_deps.body=The following {deps} dependencies must be installed so the {name} installation can continue
arch.downgrade.error=Error arch.downgrade.error=Error
arch.downgrade.impossible=It is not possible to downgrade {} arch.downgrade.impossible=It is not possible to downgrade {}
aur.history.1_version=version aur.history.1_version=version
@@ -14,6 +14,7 @@ arch.downloading.package=Downloading the package
arch.uncompressing.package=Uncompressing the package arch.uncompressing.package=Uncompressing the package
arch.checking.deps=Checking {} dependencies arch.checking.deps=Checking {} dependencies
arch.missing_deps_found=Missing dependencies for {} arch.missing_deps_found=Missing dependencies for {}
arch.checking.missing_deps=Verifying missing dependencies of {}
arch.building.package=Building package {} arch.building.package=Building package {}
arch.checking.conflicts=Checking any conflicts with {} arch.checking.conflicts=Checking any conflicts with {}
arch.installing.package=Installing {} package arch.installing.package=Installing {} package
@@ -37,8 +38,10 @@ aur.info.09_last_modified=last modified
aur.info.10_url=url download aur.info.10_url=url download
aur.info.11_pkg_build_url=url pkgbuild aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dependencies aur.info.12_makedepends=compilation dependencies
aur.info.12_optdepends=optional dependencies aur.info.13_dependson=installation dependencies
aur.info.14_optdepends=optional dependencies
aur.info.15_checkdepends=checking dependencies
aur.info.14_installed_files=Installed files aur.info.14_installed_files=Installed files
arch.install.dep_not_found.title=Dependency not found arch.install.dep_not_found.title=Dependency not found
arch.install.dep_not_found.body=Required dependency {} was not found in AUR nor in default mirrors. Installation cancelled. arch.install.dep_not_found.body=Required dependency {} was not found in AUR nor in default mirrors. Installation cancelled.
@@ -47,7 +50,8 @@ arch.install.dependency.install.error=Could not install dependent package {}. In
arch.uninstall.required_by={} cannot be uninstalled because it is necessary for these following packages to work arch.uninstall.required_by={} cannot be uninstalled because it is necessary for these following packages to work
arch.uninstall.required_by.advice=Uninstall them first before uninstalling {}. arch.uninstall.required_by.advice=Uninstall them first before uninstalling {}.
arch.install.optdeps.request.title=Optional dependencies arch.install.optdeps.request.title=Optional dependencies
arch.install.optdeps.request.body={} was succesfully installed ! There are some optional associated packages that you might want to install ( check those you want ) arch.install.optdeps.request.body={} was succesfully installed ! There are some optional associated packages that you might want to install
arch.install.optdeps.request.help=Check those you want
arch.install.optdep.error=Could not install the optional package {} arch.install.optdep.error=Could not install the optional package {}
arch.optdeps.checking=Checking {} optional dependencies arch.optdeps.checking=Checking {} optional dependencies
arch.warning.disabled={} seems not to be installed. It will not be possible to manage Arch / AUR packages. arch.warning.disabled={} seems not to be installed. It will not be possible to manage Arch / AUR packages.

View File

@@ -36,7 +36,7 @@ aur.info.conflicts with=conflicta
arch.install.conflict.popup.title=Conflicto detectado arch.install.conflict.popup.title=Conflicto detectado
arch.install.conflict.popup.body=Los aplicativos {} estan en conflicto. Debe desinstalar uno para instalar el otro. ¿Continuar? arch.install.conflict.popup.body=Los aplicativos {} estan en conflicto. Debe desinstalar uno para instalar el otro. ¿Continuar?
arch.missing_deps.title=Dependencias faltantes arch.missing_deps.title=Dependencias faltantes
arch.missing_deps.body=Deben instalarse las siguientes dependencias antes de continuar la instalación de {} arch.missing_deps.body=Deben instalarse las siguientes {deps} dependencias para que la instalación de {name} pueda continuar
arch.downgrade.error=Error arch.downgrade.error=Error
arch.downgrade.impossible=No es posible revertir la versión de {} arch.downgrade.impossible=No es posible revertir la versión de {}
aur.history.1_version=versión aur.history.1_version=versión
@@ -45,6 +45,7 @@ aur.history.3_date=fecha
arch.downloading.package=Descargando el paquete arch.downloading.package=Descargando el paquete
arch.uncompressing.package=Descomprimindo el paquete arch.uncompressing.package=Descomprimindo el paquete
arch.checking.deps=Verificando las dependencias de {} arch.checking.deps=Verificando las dependencias de {}
arch.checking.missing_deps=Verificando las dependencias faltantes de {}
arch.missing_deps_found=Dependencias faltantes para {} arch.missing_deps_found=Dependencias faltantes para {}
arch.building.package=Construyendo el paquete {} arch.building.package=Construyendo el paquete {}
arch.checking.conflicts=Verificando se hay conflictos con {} arch.checking.conflicts=Verificando se hay conflictos con {}
@@ -69,8 +70,10 @@ aur.info.09_last_modified=última modificación
aur.info.10_url=url download aur.info.10_url=url download
aur.info.11_pkg_build_url=url pkgbuild aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dependencias aur.info.12_makedepends=dependencias para compilacion
aur.info.12_optdepends=dependencias opcionales aur.info.13_dependson=dependencias para instalación
aur.info.14_optdepends=dependencias opcionales
aur.info.15_checkdepends=dependencias para verificación
aur.info.14_installed_files=Archivos instalados aur.info.14_installed_files=Archivos instalados
arch.install.dep_not_found.title=Dependencia no encontrada arch.install.dep_not_found.title=Dependencia no encontrada
arch.install.dep_not_found.body=No se encontró la dependencia requerida {} en AUR ni en los espejos predeterminados. Instalación cancelada. arch.install.dep_not_found.body=No se encontró la dependencia requerida {} en AUR ni en los espejos predeterminados. Instalación cancelada.
@@ -79,7 +82,8 @@ arch.install.dependency.install.error=No se pudo instalar el paquete dependiente
arch.uninstall.required_by=No se puede desinstalar {} porque es necesario para que los siguientes paquetes funcionen arch.uninstall.required_by=No se puede desinstalar {} porque es necesario para que los siguientes paquetes funcionen
arch.uninstall.required_by.advice=Debe desinstalarlos primero antes de desinstalar {} arch.uninstall.required_by.advice=Debe desinstalarlos primero antes de desinstalar {}
arch.install.optdeps.request.title=Dependencias opcionales arch.install.optdeps.request.title=Dependencias opcionales
arch.install.optdeps.request.body=¡{} se instaló correctamente! Hay algunos paquetes opcionales asociados que es posible que desee instalar ( marque los que desee ) arch.install.optdeps.request.body=¡{} se instaló correctamente! Hay algunos paquetes opcionales asociados que es posible que desee instalar
arch.install.optdeps.request.help=Marque los que desee
arch.install.optdep.error=No se pudo instalar el paquete opcional {} arch.install.optdep.error=No se pudo instalar el paquete opcional {}
arch.optdeps.checking=Verificando las dependencias opcionales de {} arch.optdeps.checking=Verificando las dependencias opcionales de {}
arch.warning.disabled={} parece no estar instalado. No será posible administrar paquetes Arch / AUR. arch.warning.disabled={} parece no estar instalado. No será posible administrar paquetes Arch / AUR.

View File

@@ -4,7 +4,7 @@ gem.aur.install.warning=I pacchetti AUR sono gestiti da una comunità di utenti
arch.install.conflict.popup.title=Conflitto rilevato arch.install.conflict.popup.title=Conflitto rilevato
arch.install.conflict.popup.body=Le applicazioni {} sono in conflitto. È necessario disinstallarne una per installare l'altra. Continua ? arch.install.conflict.popup.body=Le applicazioni {} sono in conflitto. È necessario disinstallarne una per installare l'altra. Continua ?
arch.missing_deps.title=Dipendenze mancanti arch.missing_deps.title=Dipendenze mancanti
arch.missing_deps.body=Le seguenti dipendenze devono essere installate prima che l'installazione di {} continui arch.missing_deps.body=Le seguenti {deps} dipendenze devono essere installate prima che l'installazione di {name} continui
arch.downgrade.error=Errore arch.downgrade.error=Errore
arch.downgrade.impossible=Non è possibile effettuare il downgrade {} arch.downgrade.impossible=Non è possibile effettuare il downgrade {}
aur.history.1_version=versione aur.history.1_version=versione
@@ -13,6 +13,7 @@ aur.history.3_date=data
arch.downloading.package=Download del pacchetto arch.downloading.package=Download del pacchetto
arch.uncompressing.package=Non comprimere il pacchetto arch.uncompressing.package=Non comprimere il pacchetto
arch.checking.deps=Verifica di {} dipendenze arch.checking.deps=Verifica di {} dipendenze
arch.checking.missing_deps=Verifica delle dipendenze mancanti di {}
arch.missing_deps_found=Dipendenze mancanti per {} arch.missing_deps_found=Dipendenze mancanti per {}
arch.building.package=Pacchetto costruito {} arch.building.package=Pacchetto costruito {}
arch.checking.conflicts=Verifica di eventuali conflitti con {} arch.checking.conflicts=Verifica di eventuali conflitti con {}
@@ -37,8 +38,10 @@ aur.info.09_last_modified=ultima modifica
aur.info.10_url=url di download aur.info.10_url=url di download
aur.info.11_pkg_build_url=url pkgbuild aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dipendenze aur.info.12_makedepends=dipendenze di compilazione
aur.info.12_optdepends=dipendenze opzionali aur.info.13_dependson=dipendenze di installazione
aur.info.14_optdepends=dipendenze opzionali
aur.info.15_checkdepends=dipendenze di verifica
aur.info.14_installed_files=File installati aur.info.14_installed_files=File installati
arch.install.dep_not_found.title=Dipendenza non trovata arch.install.dep_not_found.title=Dipendenza non trovata
arch.install.dep_not_found.body=La dipendenza richiesta {} non è stata trovata in AUR né nei mirror predefiniti. Installazione annullata. arch.install.dep_not_found.body=La dipendenza richiesta {} non è stata trovata in AUR né nei mirror predefiniti. Installazione annullata.
@@ -47,7 +50,8 @@ arch.install.dependency.install.error=Impossibile installare il pacchetto dipend
arch.uninstall.required_by={} non può essere disinstallato perché è necessario che i seguenti pacchetti funzionino arch.uninstall.required_by={} non può essere disinstallato perché è necessario che i seguenti pacchetti funzionino
arch.uninstall.required_by.advice= Uninstall them first before uninstalling {}. arch.uninstall.required_by.advice= Uninstall them first before uninstalling {}.
arch.install.optdeps.request.title=Dipendenze opzionali arch.install.optdeps.request.title=Dipendenze opzionali
arch.install.optdeps.request.body={} è stato installato con successo! Ci sono alcuni pacchetti associati opzionali che potresti voler installare (controlla quelli che vuoi) arch.install.optdeps.request.body={} è stato installato con successo! Ci sono alcuni pacchetti associati opzionali che potresti voler installare
arch.install.optdeps.request.help=Controlla quelli che vuoi
arch.install.optdep.error=Impossibile installare il pacchetto opzionale {} arch.install.optdep.error=Impossibile installare il pacchetto opzionale {}
arch.optdeps.checking=Verifica di {} dipendenze opzionali arch.optdeps.checking=Verifica di {} dipendenze opzionali
arch.warning.disabled={} sembra non essere installato. Non sarà possibile gestire i pacchetti Arch/AUR. arch.warning.disabled={} sembra non essere installato. Non sarà possibile gestire i pacchetti Arch/AUR.

View File

@@ -36,7 +36,7 @@ aur.info.conflicts with=conflita
arch.install.conflict.popup.title=Conflito detectado arch.install.conflict.popup.title=Conflito detectado
arch.install.conflict.popup.body=Os aplicativos {} estão em conflito. Você precisa desinstalar um para instalar o outro. Continuar ? arch.install.conflict.popup.body=Os aplicativos {} estão em conflito. Você precisa desinstalar um para instalar o outro. Continuar ?
arch.missing_deps.title=Dependências ausentes arch.missing_deps.title=Dependências ausentes
arch.missing_deps.body=As seguintes dependências devem ser instaladas antes de continuar com a instalação de {} arch.missing_deps.body=As seguintes {deps} dependências devem ser instaladas para que a instalação de {name} continue
arch.downgrade.error=Erro arch.downgrade.error=Erro
arch.downgrade.impossible=Não é possível reverter a versão de {} arch.downgrade.impossible=Não é possível reverter a versão de {}
aur.history.1_version=versão aur.history.1_version=versão
@@ -44,7 +44,8 @@ aur.history.2_release=lançamento
aur.history.3_date=data aur.history.3_date=data
arch.downloading.package=Baixando o pacote arch.downloading.package=Baixando o pacote
arch.uncompressing.package=Descompactando o pacote arch.uncompressing.package=Descompactando o pacote
arch.checking.deps=Checando as dependências de {} arch.checking.deps=Verificando as dependências de {}
arch.checking.missing_deps=Verificando dependências ausentes de {}
arch.missing_deps_found=Dependencias ausentes para {} arch.missing_deps_found=Dependencias ausentes para {}
arch.building.package=Construindo o pacote {} arch.building.package=Construindo o pacote {}
arch.checking.conflicts=Verificando se há conflitos com {} arch.checking.conflicts=Verificando se há conflitos com {}
@@ -69,8 +70,10 @@ aur.info.09_last_modified=última modificação
aur.info.10_url=url download aur.info.10_url=url download
aur.info.11_pkg_build_url=url pkgbuild aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dependências aur.info.12_makedepends=dependências para compilação
aur.info.12_optdepends=dependências opcionais aur.info.13_dependson=dependências para instalação
aur.info.14_optdepends=dependências opcionais
aur.info.15_checkdepends=dependências para verificação
aur.info.14_installed_files=Arquivos instalados aur.info.14_installed_files=Arquivos instalados
arch.install.dep_not_found.title=Dependência não encontrada arch.install.dep_not_found.title=Dependência não encontrada
arch.install.dep_not_found.body=A dependência {} não foi encontrado no AUR nem nos espelhos padrões. Instalação cancelada. arch.install.dep_not_found.body=A dependência {} não foi encontrado no AUR nem nos espelhos padrões. Instalação cancelada.
@@ -79,7 +82,8 @@ arch.install.dependency.install.error=Não foi possível instalar o pacote depen
arch.uninstall.required_by={} não pode ser desinstalado porque ele é necessário para o funcionamento dos seguintes pacotes arch.uninstall.required_by={} não pode ser desinstalado porque ele é necessário para o funcionamento dos seguintes pacotes
arch.uninstall.required_by.advice=Desinstale eles primeiro antes de desinstalar {} arch.uninstall.required_by.advice=Desinstale eles primeiro antes de desinstalar {}
arch.install.optdeps.request.title=Dependências opcionais arch.install.optdeps.request.title=Dependências opcionais
arch.install.optdeps.request.body={} foi instalado com sucesso ! Existem alguns pacotes associados opcionais que você talvez queira instalar ( marque os desejados ) arch.install.optdeps.request.body={} foi instalado com sucesso ! Existem alguns pacotes opcionais associados que você talvez queira instalar
arch.install.optdeps.request.help=Marque os desejados
arch.install.optdep.error=Não foi possível instalar o pacote opcional {} arch.install.optdep.error=Não foi possível instalar o pacote opcional {}
arch.optdeps.checking=Verificando as dependências opcionais de {} arch.optdeps.checking=Verificando as dependências opcionais de {}
arch.warning.disabled={} parece não estar instalado. Não será possível gerenciar pacotes Arch / AUR. arch.warning.disabled={} parece não estar instalado. Não será possível gerenciar pacotes Arch / AUR.

View File

@@ -161,8 +161,11 @@ class SnapManager(SoftwareManager):
if channels: if channels:
opts = [InputOption(label=c[0], value=c[1]) for c in channels] opts = [InputOption(label=c[0], value=c[1]) for c in channels]
channel_select = SingleSelectComponent(type_=SelectViewType.RADIO, label='', options=opts, default_option=opts[0]) channel_select = SingleSelectComponent(type_=SelectViewType.RADIO, label='', options=opts, default_option=opts[0])
body = '<p>{}.</p>'.format(self.i18n['snap.install.available_channels.message'].format(bold(self.i18n['stable']), bold(pkg.name)))
body += '<p>{}:</p>'.format(self.i18n['snap.install.available_channels.help'])
if watcher.request_confirmation(title=self.i18n['snap.install.available_channels.title'], if watcher.request_confirmation(title=self.i18n['snap.install.available_channels.title'],
body=self.i18n['snap.install.available_channels.body'].format(bold(self.i18n['stable']), bold(pkg.name)) + ':', body=body,
components=[channel_select], components=[channel_select],
confirmation_label=self.i18n['continue'], confirmation_label=self.i18n['continue'],
deny_label=self.i18n['cancel']): deny_label=self.i18n['cancel']):

View File

@@ -15,4 +15,5 @@ snap.notifications.api.unavailable=Sembla que lAPI de {} no està disponible
snap.action.refresh.status=Sestà actualitzant snap.action.refresh.status=Sestà actualitzant
snap.action.refresh.label=Actualitza snap.action.refresh.label=Actualitza
snap.install.available_channels.title=Canals disponibles snap.install.available_channels.title=Canals disponibles
snap.install.available_channels.body=No hi ha un canal {} (stable) disponible per a {}. Però més avall nhi ha els següents (seleccioneu-ne un si voleu continuar) snap.install.available_channels.message=No hi ha un canal {} (stable) disponible per a {}. Però més avall nhi ha els següents
snap.install.available_channels.help=Seleccioneu-ne un si voleu continuar

View File

@@ -5,7 +5,8 @@ snap.notifications.api.unavailable=Es scheint als ob die {} API aktuell nicht ve
snap.action.refresh.status=Erneuern snap.action.refresh.status=Erneuern
snap.action.refresh.label=Erneuern snap.action.refresh.label=Erneuern
snap.install.available_channels.title=Verfügbare Channels snap.install.available_channels.title=Verfügbare Channels
snap.install.available_channels.body=Es ist kein {} Channel verfügbar für {}. Es gibt jedoch folgende (wähle einen aus um fortzufahren) snap.install.available_channels.message=Es ist kein {} Channel verfügbar für {}. Es gibt jedoch folgende
snap.install.available_channels.help=Wähle einen aus um fortzufahren
snap.info.commands=Kommandos snap.info.commands=Kommandos
snap.info.contact=Kontakt snap.info.contact=Kontakt
snap.info.description=Beschreibung snap.info.description=Beschreibung

View File

@@ -5,7 +5,8 @@ snap.notifications.api.unavailable=It seems the {} API is unavailable at the mom
snap.action.refresh.status=Refreshing snap.action.refresh.status=Refreshing
snap.action.refresh.label=Refresh snap.action.refresh.label=Refresh
snap.install.available_channels.title=Available channels snap.install.available_channels.title=Available channels
snap.install.available_channels.body=There is no {} channel available for {}. But there are these below ( select one if you want to continue ) snap.install.available_channels.message=There is no {} channel available for {}. But there are these below
snap.install.available_channels.help=Select one if you want to continue
snap.info.commands=commands snap.info.commands=commands
snap.info.contact=contact snap.info.contact=contact
snap.info.description=description snap.info.description=description

View File

@@ -15,4 +15,5 @@ snap.notifications.api.unavailable=Parece que la API de {} no está disponible e
snap.action.refresh.status=Actualizando snap.action.refresh.status=Actualizando
snap.action.refresh.label=Actualizar snap.action.refresh.label=Actualizar
snap.install.available_channels.title=Canales disponibles snap.install.available_channels.title=Canales disponibles
snap.install.available_channels.body=No hay un canal {} ( stable ) disponible para {}. Pero hay estos otros abajo ( seleccione uno si desea continuar ) snap.install.available_channels.message=No hay un canal {} ( stable ) disponible para {}. Pero hay estos otros abajo
snap.install.available_channels.help=Seleccione uno si desea continuar

View File

@@ -5,4 +5,5 @@ snap.notifications.api.unavailable=Sembra che l'API {} non sia al momento dispon
snap.action.refresh.status=Ripristinare snap.action.refresh.status=Ripristinare
snap.action.refresh.label=Ripristina snap.action.refresh.label=Ripristina
snap.install.available_channels.title=Canali disponibili snap.install.available_channels.title=Canali disponibili
snap.install.available_channels.body=Non esiste un {} canale disponibile per {}. Ma ci sono questi sotto (selezionane uno se vuoi continuare) snap.install.available_channels.message=Non esiste un {} canale disponibile per {}. Ma ci sono questi sotto
snap.install.available_channels.help=Selezionane uno se vuoi continuare

View File

@@ -15,4 +15,5 @@ snap.notifications.api.unavailable=Parece que a API de {} está indisponível no
snap.action.refresh.status=Atualizando snap.action.refresh.status=Atualizando
snap.action.refresh.label=Atualizar snap.action.refresh.label=Atualizar
snap.install.available_channels.title=Canais disponíveis snap.install.available_channels.title=Canais disponíveis
snap.install.available_channels.body=Não há um canal {} ( stable ) disponível para {}. Porém existem estes outros abaixo ( selecione algum se quiser continuar ) snap.install.available_channels.message=Não há um canal {} ( stable ) disponível para {}. Porém existem estes outros abaixo
snap.install.available_channels.help=Selecione algum se quiser continuar

View File

@@ -1,6 +1,7 @@
from typing import List from typing import List
from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget, QScrollArea, QFrame
from bauh.api.abstract.view import ViewComponent, SingleSelectComponent, MultipleSelectComponent from bauh.api.abstract.view import ViewComponent, SingleSelectComponent, MultipleSelectComponent
from bauh.view.qt import css from bauh.view.qt import css
@@ -10,7 +11,8 @@ from bauh.view.util.translation import I18n
class ConfirmationDialog(QMessageBox): class ConfirmationDialog(QMessageBox):
def __init__(self, title: str, body: str, i18n: I18n, components: List[ViewComponent] = None, confirmation_label: str = None, deny_label: str = None): def __init__(self, title: str, body: str, i18n: I18n, screen_size: QSize, components: List[ViewComponent] = None,
confirmation_label: str = None, deny_label: str = None):
super(ConfirmationDialog, self).__init__() super(ConfirmationDialog, self).__init__()
self.setWindowTitle(title) self.setWindowTitle(title)
self.setStyleSheet('QLabel { margin-right: 25px; }') self.setStyleSheet('QLabel { margin-right: 25px; }')
@@ -26,8 +28,15 @@ class ConfirmationDialog(QMessageBox):
self.layout().addWidget(QLabel(body), 0, 1) self.layout().addWidget(QLabel(body), 0, 1)
if components: if components:
comps_container = QWidget(parent=self) scroll = QScrollArea(self)
scroll.setFrameShape(QFrame.NoFrame)
scroll.setWidgetResizable(True)
comps_container = QWidget()
comps_container.setLayout(QVBoxLayout()) comps_container.setLayout(QVBoxLayout())
scroll.setWidget(comps_container)
height = 0
for idx, comp in enumerate(components): for idx, comp in enumerate(components):
if isinstance(comp, SingleSelectComponent): if isinstance(comp, SingleSelectComponent):
@@ -37,9 +46,13 @@ class ConfirmationDialog(QMessageBox):
else: else:
raise Exception("Cannot render instances of " + comp.__class__.__name__) raise Exception("Cannot render instances of " + comp.__class__.__name__)
height += inst.sizeHint().height()
comps_container.layout().addWidget(inst) comps_container.layout().addWidget(inst)
self.layout().addWidget(comps_container, 1, 1) height = height if height < int(screen_size.height() / 2.5) else int(screen_size.height() / 2.5)
scroll.setFixedHeight(height)
self.layout().addWidget(scroll, 1, 1)
self.exec_() self.exec_()

View File

@@ -28,6 +28,7 @@ class InfoDialog(QDialog):
# shows complete field string # shows complete field string
self.text_field = QPlainTextEdit() self.text_field = QPlainTextEdit()
self.text_field.setReadOnly(True)
self.layout().addWidget(self.text_field) self.layout().addWidget(self.text_field)
self.text_field.hide() self.text_field.hide()

View File

@@ -379,7 +379,8 @@ class ManageWindow(QWidget):
i18n=self.i18n, i18n=self.i18n,
components=msg['components'], components=msg['components'],
confirmation_label=msg['confirmation_label'], confirmation_label=msg['confirmation_label'],
deny_label=msg['deny_label']) deny_label=msg['deny_label'],
screen_size=self.screen_size)
res = diag.is_confirmed() res = diag.is_confirmed()
self.thread_animate_progress.animate() self.thread_animate_progress.animate()
self.signal_user_res.emit(res) self.signal_user_res.emit(res)

View File

@@ -199,3 +199,6 @@ stable=estable
close=tanca close=tanca
publisher.verified=verificat publisher.verified=verificat
mirror=mirall mirror=mirall
emulator=emulador
do_not.install=no instal·leu
repository=dipòsit

View File

@@ -153,3 +153,6 @@ continue=Weiter
stable=Stabil stable=Stabil
close=Schließen close=Schließen
publisher.verified=Verifiziert publisher.verified=Verifiziert
emulator=emulator
do_not.install=nicht installieren
repository=repository

View File

@@ -154,3 +154,6 @@ stable=stable
close=close close=close
publisher.verified=verified publisher.verified=verified
mirror=mirror mirror=mirror
emulator=emulator
do_not.install=don't install
repository=repository

View File

@@ -198,3 +198,6 @@ stable=estable
close=cerrar close=cerrar
publisher.verified=verificado publisher.verified=verificado
mirror=espejo mirror=espejo
emulator=emulador
do_not.install=no instalar
repository=repositorio

View File

@@ -154,3 +154,6 @@ stable=stabile
close=vicino close=vicino
publisher.verified=verificato publisher.verified=verificato
mirror=specchio mirror=specchio
emulator=emulatore
do_not.install=non installare
repository=deposito

View File

@@ -201,3 +201,6 @@ stable=estável
close=fechar close=fechar
publisher.verified=verificado publisher.verified=verificado
mirror=espelho mirror=espelho
emulator=emulador
do_not.install=não instalar
repository=repositório