def update_file(self, pkg: AppImage, root_password: Optional[str], watcher: ProcessWatcher): max_width = 350 file_chooser = FileChooserComponent(label=self.i18n['file'].capitalize(), allowed_extensions={'AppImage', '*'}, search_path=get_default_manual_installation_file_dir(), max_width=max_width) input_version = TextInputComponent(label=self.i18n['version'].capitalize(), max_width=max_width) file_chooser.observers.append(ManualInstallationFileObserver(None, input_version)) while True: if watcher.request_confirmation(title=self.i18n['appimage.custom_action.manual_update.details'], body=None, components=[FormComponent(label='', components=[file_chooser, input_version], spaces=False)], confirmation_label=self.i18n['proceed'].capitalize(), deny_label=self.i18n['cancel'].capitalize(), min_height=100, max_width=max_width + 150): if not file_chooser.file_path or not os.path.isfile(file_chooser.file_path) or not file_chooser.file_path.lower().strip().endswith('.appimage'): watcher.request_confirmation(title=self.i18n['error'].capitalize(), body=self.i18n['appimage.custom_action.install_file.invalid_file'], deny_button=False) else: break else: return False pkg.local_file_path = file_chooser.file_path pkg.version = input_version.get_value() reqs = UpgradeRequirements(to_install=None, to_remove=None, to_upgrade=[UpgradeRequirement(pkg=pkg)], cannot_upgrade=None) return self.upgrade(reqs, root_password=root_password, watcher=watcher)
def uninstall(self, pkg: AppImage, root_password: Optional[str], watcher: ProcessWatcher, disk_loader: DiskCacheLoader = None) -> TransactionResult: if os.path.exists(pkg.get_disk_cache_path()): handler = ProcessHandler(watcher) if not handler.handle(SystemProcess(new_subprocess(['rm', '-rf', pkg.get_disk_cache_path()]))): watcher.show_message(title=self.i18n['error'], body=self.i18n['appimage.uninstall.error.remove_folder'].format(bold(pkg.get_disk_cache_path()))) return TransactionResult.fail() de_path = self._gen_desktop_entry_path(pkg) if os.path.exists(de_path): os.remove(de_path) self.revert_ignored_update(pkg) if pkg.symlink and os.path.islink(pkg.symlink): self.logger.info(f"Removing symlink '{pkg.symlink}'") try: os.remove(pkg.symlink) self.logger.info(f"symlink '{pkg.symlink}' successfully removed") except: msg = f"could not remove symlink '{pkg.symlink}'" self.logger.error(msg) if watcher: watcher.print(f"[error] {msg}") self._add_self_latest_version(pkg) # only for self installation return TransactionResult(success=True, installed=None, removed=[pkg])
def show_dep_not_installed(watcher: ProcessWatcher, pkgname: str, depname: str, i18n: I18n): watcher.show_message( title=i18n['error'], body=i18n['arch.install.dependency.install.error'].format( bold(depname), bold(pkgname)), type_=MessageType.ERROR)
def download_package_signature(self, pkg: dict, file_url: str, output_path: str, root_password: str, watcher: ProcessWatcher): try: self.logger.info("Downloading package '{}' signature".format( pkg['n'])) sig_downloaded = self.downloader.download( file_url=file_url + '.sig', watcher=None, output_path=output_path + '.sig', cwd='.', root_password=root_password, display_file_size=False, max_threads=1) if not sig_downloaded: msg = "Could not download package '{}' signature".format( pkg['n']) self.logger.warning(msg) watcher.print('[warning] {}'.format(msg)) else: msg = "Package '{}' signature successfully downloaded".format( pkg['n']) self.logger.info(msg) watcher.print(msg) except: self.logger.warning( "An error occurred while download package '{}' signature". format(pkg['n'])) traceback.print_exc()
def change_channel(self, pkg: SnapApplication, root_password: str, watcher: ProcessWatcher) -> bool: if not internet.is_available(): raise NoInternetException() try: channel = self._request_channel_installation( pkg=pkg, snap_config=None, snapd_client=SnapdClient(self.logger), watcher=watcher, exclude_current=True) if not channel: watcher.show_message( title=self.i18n['snap.action.channel.label'], body=self.i18n['snap.action.channel.error.no_channel']) return False return ProcessHandler(watcher).handle_simple( snap.refresh_and_stream(app_name=pkg.name, root_password=root_password, channel=channel))[0] except: return False
def install(self, pkg: ArchPackage, root_password: str, watcher: ProcessWatcher, skip_optdeps: bool = False) -> bool: clean_config = False if not self.local_config: self.local_config = read_config() clean_config = True if self.local_config['optimize'] and not os.path.exists( CUSTOM_MAKEPKG_FILE): watcher.change_substatus(self.i18n['arch.makepkg.optimizing']) ArchCompilationOptimizer(self.context.logger).optimize() res = self._install_from_aur(pkg.name, pkg.maintainer, root_password, ProcessHandler(watcher), dependency=False, skip_optdeps=skip_optdeps) if res: if os.path.exists(pkg.get_disk_data_path()): with open(pkg.get_disk_data_path()) as f: data = f.read() if data: data = json.loads(data) pkg.fill_cached_data(data) if clean_config: self.local_config = None return res
def install(self, pkg: FlatpakApplication, root_password: str, watcher: ProcessWatcher) -> bool: config = read_config() install_level = config['installation_level'] if install_level is not None: self.logger.info("Default Flaptak installation level defined: {}".format(install_level)) if install_level not in ('user', 'system'): watcher.show_message(title=self.i18n['error'].capitalize(), body=self.i18n['flatpak.install.bad_install_level.body'].format(field=bold('installation_level'), file=bold(CONFIG_FILE)), type_=MessageType.ERROR) return False pkg.installation = install_level else: user_level = watcher.request_confirmation(title=self.i18n['flatpak.install.install_level.title'], body=self.i18n['flatpak.install.install_level.body'].format(bold(pkg.name)), confirmation_label=self.i18n['no'].capitalize(), deny_label=self.i18n['yes'].capitalize()) pkg.installation = 'user' if user_level else 'system' remotes = flatpak.list_remotes() handler = ProcessHandler(watcher) if pkg.installation == 'user' and not remotes['user']: handler.handle_simple(flatpak.set_default_remotes('user')) elif pkg.installation == 'system' and not remotes['system']: if user.is_root(): handler.handle_simple(flatpak.set_default_remotes('system')) else: user_password, valid = watcher.request_root_password() if not valid: watcher.print('Operation aborted') return False else: if not handler.handle_simple(flatpak.set_default_remotes('system', user_password)): watcher.show_message(title=self.i18n['error'].capitalize(), body=self.i18n['flatpak.remotes.system_flathub.error'], type_=MessageType.ERROR) watcher.print("Operation cancelled") return False res = handler.handle(SystemProcess(subproc=flatpak.install(str(pkg.id), pkg.origin, pkg.installation), wrong_error_phrase='Warning')) if res: try: fields = flatpak.get_fields(str(pkg.id), pkg.branch, ['Ref', 'Branch']) if fields: pkg.ref = fields[0] pkg.branch = fields[1] except: traceback.print_exc() return res
def show_deps_not_installed(watcher: ProcessWatcher, pkgname: str, depnames: Iterable[str], i18n: I18n): deps = ', '.join((bold(d) for d in depnames)) watcher.show_message( title=i18n['error'].capitalize(), body=i18n['arch.install.dependency.install.error'].format( deps, bold(pkgname)), type_=MessageType.ERROR)
def install_file(self, root_password: Optional[str], watcher: ProcessWatcher) -> bool: max_width = 350 file_chooser = FileChooserComponent(label=self.i18n['file'].capitalize(), allowed_extensions={'AppImage', '*'}, search_path=get_default_manual_installation_file_dir(), max_width=max_width) input_name = TextInputComponent(label=self.i18n['name'].capitalize(), max_width=max_width) input_version = TextInputComponent(label=self.i18n['version'].capitalize(), max_width=max_width) file_chooser.observers.append(ManualInstallationFileObserver(input_name, input_version)) input_description = TextInputComponent(label=self.i18n['description'].capitalize(), max_width=max_width) cat_ops = [InputOption(label=self.i18n['category.none'].capitalize(), value=0)] cat_ops.extend([InputOption(label=self.i18n.get(f'category.{c.lower()}', c.lower()).capitalize(), value=c) for c in self.context.default_categories]) inp_cat = SingleSelectComponent(label=self.i18n['category'], type_=SelectViewType.COMBO, options=cat_ops, default_option=cat_ops[0], max_width=max_width) form = FormComponent(label='', components=[file_chooser, input_name, input_version, input_description, inp_cat], spaces=False) while True: if watcher.request_confirmation(title=self.i18n['appimage.custom_action.install_file.details'], body=None, components=[form], confirmation_label=self.i18n['proceed'].capitalize(), deny_label=self.i18n['cancel'].capitalize(), min_height=100, max_width=max_width + 150): if not file_chooser.file_path or not os.path.isfile(file_chooser.file_path) or not file_chooser.file_path.lower().strip().endswith('.appimage'): watcher.request_confirmation(title=self.i18n['error'].capitalize(), body=self.i18n['appimage.custom_action.install_file.invalid_file'], deny_button=False) elif not input_name.get_value() or not input_name.get_value().strip(): watcher.request_confirmation(title=self.i18n['error'].capitalize(), body=self.i18n['appimage.custom_action.install_file.invalid_name'], deny_button=False) else: break else: return False appim = AppImage(i18n=self.i18n, imported=True) appim.name = input_name.get_value().strip() appim.local_file_path = file_chooser.file_path appim.version = input_version.get_value() appim.latest_version = input_version.get_value() appim.description = input_description.get_value() appim.categories = ['Imported'] if inp_cat.get_selected() != cat_ops[0].value: appim.categories.append(inp_cat.get_selected()) res = self.install(root_password=root_password, pkg=appim, disk_loader=None, watcher=watcher).success if res: appim.installed = True self.cache_to_disk(appim, None, False) return res
def _display_file_size(self, file_url: str, base_substatus, watcher: ProcessWatcher): try: size = self.http_client.get_content_length(file_url) if size: watcher.change_substatus(base_substatus + ' ( {} )'.format(size)) except: pass
def downgrade(self, pkg: SnapApplication, root_password: str, watcher: ProcessWatcher) -> bool: if not snap.is_installed(): watcher.print("'snap' seems not to be installed") return False if not snapd.is_running(): watcher.print("'snapd' seems not to be running") return False return ProcessHandler(watcher).handle_simple( snap.downgrade_and_stream(pkg.name, root_password))[0]
def download(self, file_url: str, watcher: ProcessWatcher, output_path: str, cwd: str) -> bool: self.logger.info('Downloading {}'.format(file_url)) handler = ProcessHandler(watcher) file_name = file_url.split('/')[-1] final_cwd = cwd if cwd else '.' success = False ti = time.time() try: if output_path and os.path.exists(output_path): self.logger.info( 'Removing old file found before downloading: {}'.format( output_path)) os.remove(output_path) self.logger.info("Old file {} removed".format(output_path)) if self.is_multithreaded(): ti = time.time() process = self._get_aria2c_process(file_url, output_path, final_cwd) downloader = 'aria2c' else: ti = time.time() process = self._get_wget_process(file_url, output_path, final_cwd) downloader = 'wget' file_size = self.http_client.get_content_length(file_url) msg = bold('[{}] ').format( downloader) + self.i18n['downloading'] + ' ' + bold( file_url.split('/')[-1]) + (' ( {} )'.format(file_size) if file_size else '') watcher.change_substatus(msg) if isinstance(process, SimpleProcess): success = handler.handle_simple(process) else: success = handler.handle(process) except: traceback.print_exc() self._rm_bad_file(file_name, output_path, final_cwd) tf = time.time() self.logger.info(file_name + ' download took {0:.2f} minutes'.format((tf - ti) / 60)) if not success: self.logger.error("Could not download '{}'".format(file_name)) self._rm_bad_file(file_name, output_path, final_cwd) return success
def _pre_download_source(self, pkgname: str, project_dir: str, watcher: ProcessWatcher) -> bool: if self.context.file_downloader.is_multithreaded(): srcinfo = self.aur_client.get_src_info(pkgname) pre_download_files = [] for attr in SOURCE_FIELDS: if srcinfo.get(attr): if attr == 'source_x86_x64' and not self.context.is_system_x86_64( ): continue else: for f in srcinfo[attr]: if RE_PRE_DOWNLOADABLE_FILES.findall(f): pre_download_files.append(f) if pre_download_files: downloader = self.context.file_downloader.get_default_client_name( ) for f in pre_download_files: fdata = f.split('::') args = {'watcher': watcher, 'cwd': project_dir} if len(fdata) > 1: args.update({ 'file_url': fdata[1], 'output_path': fdata[0] }) else: args.update({ 'file_url': fdata[0], 'output_path': None }) file_size = self.context.http_client.get_content_length( args['file_url']) file_size = int(file_size) / (1024** 2) if file_size else None watcher.change_substatus( bold('[{}] ').format(downloader) + self.i18n['downloading'] + ' ' + bold(args['file_url'].split('/')[-1]) + ' ( {0:.2f} Mb )'.format(file_size) if file_size else '') if not self.context.file_downloader.download(**args): watcher.print( 'Could not download source file {}'.format( args['file_url'])) return False return True
def _make_exports_dir(self, watcher: ProcessWatcher) -> bool: if not os.path.exists(EXPORTS_PATH): self.logger.info("Creating dir '{}'".format(EXPORTS_PATH)) watcher.print('Creating dir {}'.format(EXPORTS_PATH)) try: Path(EXPORTS_PATH).mkdir(parents=True, exist_ok=True) except: watcher.print('Error while creating the directory {}'.format(EXPORTS_PATH)) return False return True
def show_dep_not_found(depname: str, i18n: I18n, watcher: ProcessWatcher): body = '<p>{}</p><p>{}</p><p></p><p>{}</p>'.format( i18n['arch.install.dep_not_found.body.l1'].format(bold(depname)), i18n['arch.install.dep_not_found.body.l2'], i18n['arch.install.dep_not_found.body.l3']) watcher.show_message( title=i18n['arch.install.dep_not_found.title'].capitalize(), body=body, type_=MessageType.ERROR)
def update(self, pkg: AppImage, root_password: str, watcher: ProcessWatcher) -> bool: if not self.uninstall(pkg, root_password, watcher): watcher.show_message(title=self.i18n['error'], body=self.i18n['appimage.error.uninstall_current_version'], type_=MessageType.ERROR) return False if self.install(pkg, root_password, watcher): self.cache_to_disk(pkg, None, False) return True return False
def _concat_file_size(self, file_url: str, base_substatus: StringIO, watcher: ProcessWatcher): watcher.change_substatus(f'{base_substatus.getvalue()} ( ? Mb )') try: size = self.http_client.get_content_length(file_url) if size: base_substatus.write(f' ( {size} )') watcher.change_substatus(base_substatus.getvalue()) except: pass
def download_electron_sha256(self, version: str, url: str, widevine: bool, watcher: ProcessWatcher) -> bool: self.logger.info("Downloading Electron {} sha526".format(version)) sha256_path = self._get_electron_file_path(url=url, relative=False) if not self.http_client.exists(url): self.logger.warning("The file {} seems not to exist".format(url)) watcher.show_message(title=self.i18n['message.file.not_exist'], body=self.i18n['message.file.not_exist.body'].format(bold(url)), type_=MessageType.ERROR) return False return self.file_downloader.download(file_url=url, watcher=watcher, output_path=sha256_path, cwd=ELECTRON_PATH)
def uninstall(self, pkg: AppImage, root_password: str, watcher: ProcessWatcher) -> bool: if os.path.exists(pkg.get_disk_cache_path()): handler = ProcessHandler(watcher) if not handler.handle(SystemProcess(new_subprocess(['rm', '-rf', pkg.get_disk_cache_path()]))): watcher.show_message(title=self.i18n['error'], body=self.i18n['appimage.uninstall.error.remove_folder'].format(bold(pkg.get_disk_cache_path()))) return False de_path = self._gen_desktop_entry_path(pkg) if os.path.exists(de_path): os.remove(de_path) return True
def upgrade(self, requirements: UpgradeRequirements, root_password: str, watcher: ProcessWatcher) -> bool: flatpak_version = flatpak.get_version() for req in requirements.to_upgrade: watcher.change_status("{} {} ({})...".format(self.i18n['manage_window.status.upgrading'], req.pkg.name, req.pkg.version)) related, deps = False, False ref = req.pkg.ref if req.pkg.partial and flatpak_version < '1.5': related, deps = True, True ref = req.pkg.base_ref try: res = ProcessHandler(watcher).handle(SystemProcess(subproc=flatpak.update(app_ref=ref, installation=req.pkg.installation, related=related, deps=deps))) watcher.change_substatus('') if not res: self.logger.warning("Could not upgrade '{}'".format(req.pkg.id)) return False except: watcher.change_substatus('') self.logger.error("An error occurred while upgrading '{}'".format(req.pkg.id)) traceback.print_exc() return False watcher.change_substatus('') return True
def show_dep_not_found(depname: str, i18n: I18n, watcher: ProcessWatcher, dependent: Optional[str] = None): source = f" {bold('(' + dependent + ')')}" if dependent else '' body = f"<p>{i18n['arch.install.dep_not_found.body.l1'].format(dep=bold(depname), source=source)}</p>" \ f"<p><{i18n['arch.install.dep_not_found.body.l2']}</p>" \ f"<p>{i18n['arch.install.dep_not_found.body.l3']}</p>" watcher.show_message( title=i18n['arch.install.dep_not_found.title'].capitalize(), body=body, type_=MessageType.ERROR)
def downgrade(self, pkg: AppImage, root_password: str, watcher: ProcessWatcher) -> bool: versions = self.get_history(pkg) if len(versions.history) == 1: watcher.show_message( title=self.i18n['appimage.downgrade.impossible.title'], body=self.i18n['appimage.downgrade.impossible.body'].format( bold(pkg.name)), type_=MessageType.ERROR) return False elif versions.pkg_status_idx == -1: watcher.show_message( title=self.i18n['appimage.downgrade.impossible.title'], body=self.i18n['appimage.downgrade.unknown_version.body']. format(bold(pkg.name)), type_=MessageType.ERROR) return False elif versions.pkg_status_idx == len(versions.history) - 1: watcher.show_message( title=self.i18n['appimage.downgrade.impossible.title'], body=self.i18n['appimage.downgrade.first_version'].format( bold(pkg.name)), type_=MessageType.ERROR) return False else: if self.uninstall(pkg, root_password, watcher): old_release = versions.history[versions.pkg_status_idx + 1] pkg.version = old_release['0_version'] pkg.latest_version = pkg.version pkg.url_download = old_release['2_url_download'] if self.install(pkg, root_password, watcher): self.cache_to_disk(pkg, None, False) return True else: watcher.show_message( title=self.i18n['error'], body=self.i18n['appimage.downgrade.install_version']. format(bold(pkg.version), bold(pkg.url_download)), type_=MessageType.ERROR) else: watcher.show_message( title=self.i18n['error'], body=self.i18n['appimage.error.uninstall_current_version']. format(bold(pkg.name)), type_=MessageType.ERROR) return False
def launch_timeshift(self, root_password: str, watcher: ProcessWatcher): if self._is_timeshift_launcher_available(): try: Popen(['timeshift-launcher'], stderr=STDOUT) return True except: traceback.print_exc() watcher.show_message(title=self.i18n["error"].capitalize(), body=self.i18n['action.backups.tool_error'].format(bold('Timeshift')), type_=MessageType.ERROR) return False else: watcher.show_message(title=self.i18n["error"].capitalize(), body=self.i18n['action.backups.tool_error'].format(bold('Timeshift')), type_=MessageType.ERROR) return False
def request_optional_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatcher, i18n: I18n) -> Set[str]: opts = [] for p, d in pkg_mirrors.items(): op = InputOption( '{}{} ( {}: {} )'.format(p, ': ' + d['desc'] if d['desc'] else '', i18n['repository'], d['mirror'].upper()), p) op.icon_path = _get_mirror_icon(d['mirror']) opts.append(op) view_opts = MultipleSelectComponent(label='', options=opts, default_options=set(opts)) install = watcher.request_confirmation( title=i18n['arch.install.optdeps.request.title'], body='<p>{}.</p><p>{}:</p>'.format( i18n['arch.install.optdeps.request.body'].format(bold(pkgname)), i18n['arch.install.optdeps.request.help']), components=[view_opts], confirmation_label=i18n['install'].capitalize(), deny_label=i18n['do_not.install'].capitalize()) if install: return {o.value for o in view_opts.values}
def request_providers(providers_map: Dict[str, Set[str]], repo_map: Dict[str, str], watcher: ProcessWatcher, i18n: I18n) -> Set[str]: msg = "<p>{}.</p><p>{}.</p>".format(i18n['arch.dialog.providers.line1'], i18n['arch.dialog.providers.line2']) repo_icon_path = get_repo_icon_path() aur_icon_path = get_icon_path() form = FormComponent([], label='') for dep, providers in providers_map.items(): opts = [] providers_list = [*providers] providers_list.sort() for p in providers_list: 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))) form.components.append(SingleSelectComponent(label=bold(dep.lower()), options=opts, default_option=opts[0], type_=SelectViewType.COMBO, max_per_line=1)) if watcher.request_confirmation(title=i18n['arch.providers'].capitalize(), body=msg, components=[form], confirmation_label=i18n['proceed'].capitalize(), deny_label=i18n['cancel'].capitalize()): return {s.get_selected() for s in form.components}
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( name=bold(pkgname) if pkgname else '', deps=bold(str(len(deps))))) opts = [] repo_deps = [d[0] for d in deps if d[1] != 'aur'] sizes = pacman.get_update_size(repo_deps) if repo_deps else {} for dep in deps: size = sizes.get(dep[0]) op = InputOption( '{} ({}: {}) - {}: {}'.format( dep[0], i18n['repository'], dep[1].lower(), i18n['size'].capitalize(), get_human_size_str(size) if size else '?'), dep[0]) op.read_only = True op.icon_path = _get_repo_icon(dep[1]) opts.append(op) 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(), deny_label=i18n['cancel'].capitalize())
def request_optional_deps(pkgname: str, pkg_repos: dict, watcher: ProcessWatcher, i18n: I18n) -> Set[str]: opts = [] repo_deps = [ p for p, data in pkg_repos.items() if data['repository'] != 'aur' ] sizes = pacman.get_update_size(repo_deps) if repo_deps else {} for p, d in pkg_repos.items(): size = sizes.get(p) op = InputOption( '{}{} ({}: {}) - {}: {}'.format( p, ': ' + d['desc'] if d['desc'] else '', i18n['repository'], d['repository'].lower(), i18n['size'].capitalize(), get_human_size_str(size) if size else '?'), p) op.icon_path = _get_repo_icon(d['repository']) opts.append(op) view_opts = MultipleSelectComponent(label='', options=opts, default_options=set(opts)) install = watcher.request_confirmation( title=i18n['arch.install.optdeps.request.title'], body='<p>{}.</p><p>{}:</p>'.format( i18n['arch.install.optdeps.request.body'].format(bold(pkgname)), i18n['arch.install.optdeps.request.help']), components=[view_opts], confirmation_label=i18n['install'].capitalize(), deny_label=i18n['do_not.install'].capitalize()) if install: return {o.value for o in view_opts.values}
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( name=bold(pkgname) if pkgname else '', deps=bold(str(len(deps))))) opts = [] 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.icon_path = _get_mirror_icon(dep[1]) opts.append(op) 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(), deny_label=i18n['cancel'].capitalize())
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'])
def request_optional_deps(pkgname: str, pkg_repos: dict, watcher: ProcessWatcher, i18n: I18n) -> Set[str]: opts = [] repo_deps = [p for p, data in pkg_repos.items() if data['repository'] != 'aur'] sizes = pacman.map_update_sizes(repo_deps) if repo_deps else {} for p, d in pkg_repos.items(): size = sizes.get(p) label = f"{p} ({i18n['repository']}: {d['repository'].lower()}) | " \ f"{i18n['size'].capitalize()}: {get_human_size_str(size) if size is not None else '?'}" op = InputOption(label=label, value=p, tooltip=d.get('desc') or None) op.icon_path = _get_repo_icon(d['repository']) opts.append(op) view_opts = MultipleSelectComponent(label='', options=opts, default_options=set(opts)) msg = f"<p>{i18n['arch.install.optdeps.request.success'].format(pkg=bold(pkgname))}</p>" \ f"<p>{i18n['arch.install.optdeps.request.body']}:</p>" install = watcher.request_confirmation(title=i18n['arch.install.optdeps.request.title'], body=msg, components=[view_opts], confirmation_label=i18n['install'].capitalize(), deny_label=i18n['do_not.install'].capitalize(), min_width=600, min_height=200) if install: return {o.value for o in view_opts.values}