Skip to content

Commit

Permalink
0.9.26
Browse files Browse the repository at this point in the history
  • Loading branch information
vinifmor authored Jan 31, 2022
2 parents 4b9c27f + b821519 commit 3759df9
Show file tree
Hide file tree
Showing 26 changed files with 518 additions and 240 deletions.
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,36 @@ 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/).

## [0.9.26] 2022-01-31

### Improvements
- Arch
- not rechecking sub-dependencies of an AUR dependency to be installed
- allowing AUR packages to be installed as dependencies of a repository package
- always listing repository packages as primary options when multiple providers for a given dependency are available
- installation: explicitly marking installed dependent packages as "dependencies" (`--asdeps`)
- settings:
- "Auto-define dependency providers" property renamed to "Auto-match dependency by name"
- new property 'prefer_repository_provider': automatically picks the single package from the repositories among several external (AUR) available as the provider for a given dependency

### Fixes
- General
- not handling unicode decode errors when reading a subprocess output

- Arch
- not upgrading a package when a dependent package relies on a specific version with epoch (e.g: alsa-plugins 1:1.2.6-1 would not be upgraded to 1:1.2.6-2 because lib32-alsa-plugins relies on 1:1.2.6)
- not informing all the provided packages on the transaction context to the dependency sorting algorithm (could lead to a wrong installation order)
- not displaying all possible AUR providers for a given dependency
- not displaying any substatus when retrieving packages (pacman)

- UI:
- settings panel: confirmation dialog icon when launched alone

### UI
- new logo by [DN-debug](https://github.com/DN-debug)
- new dark theme (**knight**) based on Kimi-dark gtk by [DN-debug](https://github.com/DN-debug)


## [0.9.25] 2021-12-24
### Improvements
- General
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ suggest_unneeded_uninstall: false # if the dependencies apparently no longer ne
suggest_optdep_uninstall: false # if the optional dependencies associated with uninstalled packages should be suggested for uninstallation. Only the optional dependencies that are not dependencies of other packages will be suggested. Default: false (to prevent new users from making mistakes)
categories_exp: 24 # It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization.
aur_rebuild_detector: true # it checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ('rebuild-detector' must be installed). Default: true.
prefer_repository_provider: true # when there is just one repository provider for a given a dependency and several from AUR, it will be automatically picked.
```


Expand Down
2 changes: 1 addition & 1 deletion bauh/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.9.25'
__version__ = '0.9.26'
__app_name__ = 'bauh'

import os
Expand Down
45 changes: 38 additions & 7 deletions bauh/commons/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,12 @@ def handle(self, process: SystemProcess, error_output: StringIO = None, output_h

if not process.skip_stdout:
for output in process.subproc.stdout:
line = output.decode().strip()

try:
line = output.decode().strip()
except UnicodeDecodeError:
line = None

if line:
self._notify_watcher(line)

Expand All @@ -148,7 +153,11 @@ def handle(self, process: SystemProcess, error_output: StringIO = None, output_h

for output in process.subproc.stderr:
if output:
line = output.decode().strip()
try:
line = output.decode().strip()
except UnicodeDecodeError:
line = None

if line:
self._notify_watcher(line)

Expand Down Expand Up @@ -181,7 +190,10 @@ def handle_simple(self, proc: SimpleProcess, output_handler=None, notify_watcher
output = StringIO()
for o in proc.instance.stdout:
if o:
line = o.decode()
try:
line = o.decode()
except UnicodeDecodeError:
continue

output.write(line)

Expand Down Expand Up @@ -223,7 +235,7 @@ def handle_simple(self, proc: SimpleProcess, output_handler=None, notify_watcher

def run_cmd(cmd: str, expected_code: int = 0, ignore_return_code: bool = False, print_error: bool = True,
cwd: str = '.', global_interpreter: bool = USE_GLOBAL_INTERPRETER, extra_paths: Set[str] = None,
custom_user: Optional[str] = None) -> str:
custom_user: Optional[str] = None) -> Optional[str]:
"""
runs a given command and returns its default output
:return:
Expand All @@ -240,7 +252,12 @@ def run_cmd(cmd: str, expected_code: int = 0, ignore_return_code: bool = False,

final_cmd = f"runuser -u {custom_user} -- {cmd}" if custom_user else cmd
res = subprocess.run(final_cmd, **args)
return res.stdout.decode() if ignore_return_code or res.returncode == expected_code else None

if ignore_return_code or res.returncode == expected_code:
try:
return res.stdout.decode()
except UnicodeDecodeError:
pass


def new_subprocess(cmd: List[str], cwd: str = '.', shell: bool = False, stdin = None,
Expand Down Expand Up @@ -306,7 +323,13 @@ def get_human_size_str(size) -> str:
def run(cmd: List[str], success_code: int = 0, custom_user: Optional[str] = None) -> Tuple[bool, str]:
final_cmd = ['runuser', '-u', custom_user, '--', *cmd] if custom_user else cmd
p = subprocess.run(final_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.DEVNULL)
return p.returncode == success_code, p.stdout.decode()

try:
output = p.stdout.decode()
except UnicodeDecodeError:
output = ''

return p.returncode == success_code, output


def check_active_services(*names: str) -> Dict[str, bool]:
Expand Down Expand Up @@ -351,4 +374,12 @@ def execute(cmd: str, shell: bool = False, cwd: Optional[str] = None, output: bo
params['env'] = custom_env

p = subprocess.run(**params)
return p.returncode, p.stdout.decode() if p.stdout else None

output = None
if p.stdout:
try:
output = p.stdout.decode()
except UnicodeDecodeError:
output = None

return p.returncode, output
41 changes: 39 additions & 2 deletions bauh/gems/arch/aur.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import re
import urllib.parse
from typing import Set, List, Iterable, Dict, Optional
from typing import Set, List, Iterable, Dict, Optional, Generator, Tuple

import requests

Expand Down Expand Up @@ -119,6 +119,43 @@ def get_info(self, names: Iterable[str]) -> List[dict]:
except:
return []

def map_provided(self, pkgname: str, pkgver: str, provided: Optional[Iterable[str]] = None, strip_epoch: bool = True) -> Set[str]:
all_provided = {pkgname, f"{pkgname}={pkgver.split('-')[0] if strip_epoch else pkgver}"}

if provided:
for provided in provided:
all_provided.add(provided)
all_provided.add(provided.split('=', 1)[0])

return all_provided

def gen_updates_data(self, names: Iterable[str]) -> Generator[Tuple[str, dict], None, None]:
for package in self.get_info(names):
pkgname, pkgver = package['Name'], package['Version'].split('-')[0]

deps = set()

for dtype in ('Depends', 'MakeDepends', 'CheckDepends'):
dep_set = package.get(dtype)
if dep_set:
deps.update(dep_set)

conflicts = set()
pkg_conflicts = package.get('Conflicts')

if pkg_conflicts:
conflicts.update(pkg_conflicts)

yield pkgname, {
'v': pkgver,
'b': package.get('PackageBase', pkgname),
'r': 'aur',
'p': self.map_provided(pkgname=pkgname, pkgver=pkgver, provided=package.get('Provides'), strip_epoch=False),
'd': deps,
'c': conflicts,
'ds': None,
's': None}

def get_src_info(self, name: str, real_name: Optional[str] = None) -> dict:
srcinfo = self.srcinfo_cache.get(name)

Expand Down Expand Up @@ -229,7 +266,7 @@ def read_index(self) -> Iterable[str]:
def clean_caches(self):
self.srcinfo_cache.clear()

def map_update_data(self, pkgname: str, latest_version: Optional[str], srcinfo: Optional[dict] = None) -> dict:
def map_update_data(self, pkgname: str, latest_version: Optional[str] = None, srcinfo: Optional[dict] = None) -> dict:
info = self.get_src_info(pkgname) if not srcinfo else srcinfo

provided = set()
Expand Down
3 changes: 2 additions & 1 deletion bauh/gems/arch/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ def get_default_config(self) -> dict:
'aur_idx_exp': 1,
'categories_exp': 24,
'aur_rebuild_detector': False,
"aur_rebuild_detector_no_bin": True}
"aur_rebuild_detector_no_bin": True,
"prefer_repository_provider": True}
21 changes: 14 additions & 7 deletions bauh/gems/arch/confirmation.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,22 @@ def request_providers(providers_map: Dict[str, Set[str]], repo_map: Dict[str, st
for dep, providers in providers_map.items():
opts = []

providers_list = [*providers]
providers_list.sort()
repo_providers, aur_providers = {}, {}

for p in providers_list:
for p in providers:
repo = repo_map.get(p, 'aur')
opts.append(InputOption(label=p,
value=p,
icon_path=aur_icon_path if repo == 'aur' else repo_icon_path,
tooltip='{}: {}'.format(i18n['repository'].capitalize(), repo)))

if repo == 'aur':
aur_providers[p] = repo
else:
repo_providers[p] = repo

for current_providers in (repo_providers, aur_providers):
for pname, repo in sorted(current_providers.items()):
opts.append(InputOption(label=pname,
value=pname,
icon_path=aur_icon_path if repo == 'aur' else repo_icon_path,
tooltip='{}: {}'.format(i18n['repository'].capitalize(), repo)))

form.components.append(SingleSelectComponent(label=bold(dep.lower()),
options=opts,
Expand Down
51 changes: 22 additions & 29 deletions bauh/gems/arch/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def __init__(self, context: ApplicationContext, disk_cache_updater: Optional[Arc
self.enabled = True
self.arch_distro = context.distro == 'arch'
self.categories = {}
self.deps_analyser = DependenciesAnalyser(self.aur_client, self.i18n)
self.deps_analyser = DependenciesAnalyser(self.aur_client, self.i18n, self.logger)
self.http_client = context.http_client
self._custom_actions: Optional[Dict[str, CustomSoftwareAction]] = None
self.index_aur = None
Expand Down Expand Up @@ -1760,7 +1760,8 @@ def _install_deps(self, context: TransactionContext, deps: List[Tuple[str, str]]
status_handler.start()
installed, _ = context.handler.handle_simple(pacman.install_as_process(pkgpaths=repo_dep_names,
root_password=context.root_password,
file=False),
file=False,
as_deps=True),
output_handler=status_handler.handle)

if installed:
Expand Down Expand Up @@ -2082,6 +2083,7 @@ def _list_missing_deps(self, context: TransactionContext) -> List[Tuple[str, str
remote_provided_map=context.get_remote_provided_map(),
remote_repo_map=context.get_remote_repo_map(),
automatch_providers=context.config['automatch_providers'],
prefer_repository_provider=context.config['prefer_repository_provider'],
watcher=context.watcher)

tf = time.time()
Expand All @@ -2108,9 +2110,10 @@ def _handle_missing_deps(self, context: TransactionContext) -> bool:
return True

def _handle_aur_package_deps_and_keys(self, context: TransactionContext) -> bool:
handled_deps = self._handle_missing_deps(context)
if not handled_deps:
return False
if not context.dependency:
handled_deps = self._handle_missing_deps(context)
if not handled_deps:
return False

check_res = makepkg.check(project_dir=context.project_dir,
optimize=bool(context.config['optimize']),
Expand Down Expand Up @@ -2196,6 +2199,7 @@ def _install_optdeps(self, context: TransactionContext) -> bool:
remote_provided_map=remote_provided_map,
remote_repo_map=remote_repo_map,
automatch_providers=context.config['automatch_providers'],
prefer_repository_provider=context.config['prefer_repository_provider'],
sort=False)

if missing_deps is None:
Expand Down Expand Up @@ -2332,7 +2336,7 @@ def _install(self, context: TransactionContext) -> bool:
to_install = []

if context.missing_deps:
to_install.extend((d[0] for d in context.missing_deps))
to_install.extend((d[0] for d in context.missing_deps if d[1] != 'aur'))

to_install.extend(pkgpaths)

Expand All @@ -2356,7 +2360,8 @@ def _install(self, context: TransactionContext) -> bool:
status_handler = None

installed_with_same_name = self.read_installed(disk_loader=context.disk_loader, internet_available=True, names=context.get_package_names()).installed
context.watcher.change_substatus(self.i18n['arch.installing.package'].format(bold(context.name)))
context.watcher.change_substatus(self.i18n['arch.installing.package'].format(bold(context.name))) #

installed = self._handle_install_call(context=context, to_install=to_install, status_handler=status_handler)

if status_handler:
Expand Down Expand Up @@ -2423,7 +2428,8 @@ def _call_pacman_install(self, context: TransactionContext, to_install: List[str
root_password=context.root_password,
file=context.has_install_files(),
pkgdir=context.project_dir,
overwrite_conflicting_files=overwrite_files),
overwrite_conflicting_files=overwrite_files,
as_deps=context.dependency),
output_handler=status_handler.handle if status_handler else None)

def _handle_install_call(self, context: TransactionContext, to_install: List[str], status_handler) -> bool:
Expand Down Expand Up @@ -2599,29 +2605,9 @@ def install(self, pkg: ArchPackage, root_password: str, disk_loader: Optional[Di
return TransactionResult(success=pkg_installed, installed=installed, removed=removed)

def _install_from_repository(self, context: TransactionContext) -> bool:
try:
missing_deps = self._list_missing_deps(context)
except PackageNotFoundException:
self.logger.error("Package '{}' was not found")
if not self._handle_missing_deps(context):
return False

if missing_deps is None:
return False # called off by the user

if missing_deps:
if any((dep for dep in missing_deps if dep[1] == 'aur')):
context.watcher.show_message(title=self.i18n['error'].capitalize(),
body=self.i18n['arch.install.repo_pkg.error.aur_deps'],
type_=MessageType.ERROR)
return False

context.missing_deps = missing_deps
context.watcher.change_substatus(self.i18n['arch.missing_deps_found'].format(bold(context.name)))

if not confirmation.request_install_missing_deps(context.name, missing_deps, context.watcher, self.i18n):
context.watcher.print(self.i18n['action.cancelled'])
return False

res = self._install(context)

if res and not context.skip_opt_deps:
Expand Down Expand Up @@ -2841,6 +2827,12 @@ def get_settings(self, screen_width: int, screen_height: int) -> Optional[ViewCo
tooltip_key='arch.config.automatch_providers.tip',
value=bool(arch_config['automatch_providers']),
max_width=max_width),
self._gen_bool_selector(id_='prefer_repo_provider',
label_key='arch.config.prefer_repository_provider',
tooltip_key='arch.config.prefer_repository_provider.tip',
value=bool(arch_config['prefer_repository_provider']),
max_width=max_width,
tooltip_params=['AUR']),
self._gen_bool_selector(id_='check_dependency_breakage',
label_key='arch.config.check_dependency_breakage',
tooltip_key='arch.config.check_dependency_breakage.tip',
Expand Down Expand Up @@ -2953,6 +2945,7 @@ def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[
arch_config['mirrors_sort_limit'] = form.get_component('mirrors_sort_limit').get_int_value()
arch_config['repositories_mthread_download'] = form.get_component('mthread_download').get_selected()
arch_config['automatch_providers'] = form.get_single_select_component('autoprovs').get_selected()
arch_config['prefer_repository_provider'] = form.get_single_select_component('prefer_repo_provider').get_selected()
arch_config['edit_aur_pkgbuild'] = form.get_single_select_component('edit_aur_pkgbuild').get_selected()
arch_config['aur_remove_build_dir'] = form.get_single_select_component('aur_remove_build_dir').get_selected()
arch_config['aur_build_dir'] = form.get_component('aur_build_dir').file_path
Expand Down
Loading

0 comments on commit 3759df9

Please sign in to comment.