Exemple #1
0
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())
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
 def list_warnings(self, internet_available: bool) -> List[str]:
     if flatpak.is_installed():
         if not flatpak.has_remotes_set():
             return [
                 self.i18n['flatpak.notification.no_remotes'],
                 self.i18n['flatpak.notification.disable'].format(
                     bold('Flatpak'),
                     bold(self.i18n['manage_window.settings.gems']))
             ]
Exemple #5
0
    def install(self, pkg: SnapApplication, root_password: str,
                watcher: ProcessWatcher) -> bool:
        res, output = ProcessHandler(watcher).handle_simple(
            snap.install_and_stream(pkg.name, pkg.confinement, root_password))

        if 'error:' in output:
            res = False
            if 'not available on stable' in output:
                channels = RE_AVAILABLE_CHANNELS.findall(output)

                if 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])
                    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'],
                            body=body,
                            components=[channel_select],
                            confirmation_label=self.i18n['continue'],
                            deny_label=self.i18n['cancel']):
                        self.logger.info(
                            "Installing '{}' with the custom command '{}'".
                            format(pkg.name, channel_select.value))
                        res = ProcessHandler(watcher).handle(
                            SystemProcess(
                                new_root_subprocess(
                                    channel_select.value.value.split(' '),
                                    root_password=root_password)))

                        if res:
                            pkg.has_apps_field = snap.has_apps_field(
                                pkg.name, self.ubuntu_distro)

                        return res
                else:
                    self.logger.error(
                        "Could not find available channels in the installation output: {}"
                        .format(output))
        else:
            pkg.has_apps_field = snap.has_apps_field(pkg.name,
                                                     self.ubuntu_distro)

        return res
Exemple #6
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
Exemple #7
0
    def confirm_transaction(self,
                            to_install: Optional[Collection[DebianPackage]],
                            removal: Optional[Collection[DebianPackage]],
                            watcher: ProcessWatcher) -> bool:

        components = []

        to_remove_data = self._map_to_remove(removal)

        text_width, select_width = 672, 595

        if to_remove_data:
            to_remove_data[0].sort(key=attrgetter('label'))
            lb_rem = self._i18n['debian.transaction.to_remove'].format(
                no=bold(str(len(to_remove_data[0]))),
                fspace=bold(to_remove_data[1]))

            components.append(TextComponent(html=lb_rem, min_width=text_width))
            components.append(
                MultipleSelectComponent(id_='rem',
                                        options=to_remove_data[0],
                                        label=None,
                                        default_options={*to_remove_data[0]},
                                        max_width=select_width))

        to_install_data = self._map_to_install(to_install)

        if to_install_data:
            to_install_data[0].sort(key=attrgetter('label'))
            lb_deps = self._i18n['debian.transaction.to_install'].format(
                no=bold(str(len(to_install_data[0]))),
                dsize=bold(to_install_data[2]),
                isize=bold(to_install_data[1]))

            components.append(
                TextComponent(html=f'<br/>{lb_deps}', min_width=text_width))
            components.append(
                MultipleSelectComponent(id_='inst',
                                        label='',
                                        options=to_install_data[0],
                                        default_options={*to_install_data[0]},
                                        max_width=select_width))

        return watcher.request_confirmation(
            title=self._i18n['debian.transaction.title'],
            components=components,
            confirmation_label=self._i18n['popup.button.continue'],
            deny_label=self._i18n['popup.button.cancel'],
            body=None,
            min_width=text_width,
            min_height=54)
Exemple #8
0
 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'])
Exemple #9
0
    def run(self):
        if self.create_config:
            self.taskman.update_progress(
                self.task_id, 0, self.i18n['task.waiting_task'].format(
                    bold(self.create_config.task_name)))
            self.create_config.join()
            self.config = self.create_config.config

        ti = time.time()
        self.taskman.update_progress(self.task_id, 1, None)

        self.logger.info("Checking if suggestions should be downloaded")
        should_download = self.should_download(self.config)
        self.taskman.update_progress(self.task_id, 30, None)

        try:
            if should_download:
                suggestions_timestamp = datetime.utcnow().timestamp()
                suggestions_str = self.download()
                self.taskman.update_progress(self.task_id, 70, None)

                if suggestions_str:
                    self.cache_suggestions(suggestions_str,
                                           suggestions_timestamp)
            else:
                self.logger.info("Cached suggestions are up-to-date")
        except:
            self.logger.error("An unexpected exception happened")
            traceback.print_exc()

        self.taskman.update_progress(self.task_id, 100, None)
        self.taskman.finish_task(self.task_id)
        tf = time.time()
        self.logger.info(
            "Took {0:.9f} seconds to download suggestions".format(tf - ti))
Exemple #10
0
    def run(self):
        ti = time.time()
        self._log.info("Begin: Debian applications indexation")

        self._taskman.update_progress(
            self._id, 1, self._i18n['task.waiting_task'].format(
                bold(self._i18n['debian.task.map_apps.status'])))
        self._mapping_apps.join()

        finish_msg = None
        if self._mapping_apps.cached:
            finish_msg = self._i18n['task.canceled']
        else:
            status = self._i18n['debian.task.update_apps_idx.status']
            self._taskman.update_progress(self._id, 50, status)
            self._change_substatus(status)

            try:
                self._indexer.update_index(self._mapping_apps.apps)
            except:
                finish_msg = self._i18n['error']

        self._taskman.update_progress(self._id, 100, finish_msg)
        self._taskman.finish_task(self._id)

        tf = time.time()
        self._log.info(
            f"Finish: Debian applications indexation ({tf - ti:.4f} seconds)")
Exemple #11
0
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}
Exemple #12
0
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}
Exemple #13
0
def confirm_missing_deps(deps: Collection[Tuple[str, str]], watcher: ProcessWatcher, i18n: I18n) -> bool:
    opts = []

    total_isize, total_dsize = None, None
    pkgs_data = pacman.map_updates_data(pkgs=tuple(d[0] for d in deps if d[1] != 'aur'), description=True) or dict()

    for dep in deps:
        ver, desc, isize, dsize = None, None, None, None
        data = pkgs_data.get(dep[0])

        if data:
            desc, isize, dsize = (data.get(f) for f in ('des', 's', 'ds'))

            if isize is not None:
                if total_isize is None:
                    total_isize = 0

                total_isize += isize

            if dsize is not None:
                if total_dsize is None:
                    total_dsize = 0

                total_dsize += dsize

        label = f"{dep[0]} | " \
                f"{i18n['size'].capitalize()}: {get_human_size_str(isize) if isize is not None else '?'}" \
                f"{' ({}: {})'.format(i18n['download'].capitalize(), get_human_size_str(dsize)) if dsize else ''}"

        op = InputOption(label=label, value=dep[0], tooltip=desc)
        op.read_only = True
        op.icon_path = _get_repo_icon(dep[1])
        opts.append(op)

    comp = MultipleSelectComponent(label='', options=opts, default_options=set(opts))

    body = StringIO()
    body.write('<p>')
    body.write(i18n['arch.missing_deps.body'].format(deps=bold(str(len(deps)))))

    if total_isize is not None or total_dsize is not None:
        body.write(' (')

        if total_isize is not None:
            body.write(f"{i18n['size'].capitalize()}: {bold(get_human_size_str(total_isize))} | ")

        if total_dsize is not None:
            body.write(f"{i18n['download'].capitalize()}: {bold(get_human_size_str(total_dsize))}")

        body.write(')')

    body.write(':</p>')

    return watcher.request_confirmation(title=i18n['arch.missing_deps.title'],
                                        body=body.getvalue(),
                                        components=[comp],
                                        confirmation_label=i18n['continue'].capitalize(),
                                        deny_label=i18n['cancel'].capitalize(),
                                        min_width=625)
Exemple #14
0
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)
Exemple #15
0
        def custom_action():
            if action.i18n_confirm_key:
                body = self.i18n[action.i18n_confirm_key].format(
                    bold(pkg.model.name))
            else:
                body = '{} ?'.format(self.i18n[action.i18n_label_key])

            if dialog.ask_confirmation(title=self.i18n[action.i18n_label_key],
                                       body=self._parag(body),
                                       i18n=self.i18n):
                self.window.begin_execute_custom_action(pkg, action)
Exemple #16
0
        def custom_action():
            if action.i18n_confirm_key:
                body = self.i18n[action.i18n_confirm_key].format(bold(pkg.model.name))
            else:
                body = '{} ?'.format(self.i18n[action.i18n_label_key])

            if ConfirmationDialog(icon=QIcon(pkg.model.get_type_icon_path()),
                                  title=self.i18n[action.i18n_label_key],
                                  body=self._parag(body),
                                  i18n=self.i18n).ask():
                self.window.begin_execute_custom_action(pkg, action)
Exemple #17
0
    def confirm_removal(self, source_pkg: str,
                        dependencies: Collection[DebianPackage],
                        watcher: ProcessWatcher) -> bool:
        dep_views = []
        freed_space = 0
        for p in sorted(dependencies, key=attrgetter('name')):
            if p.transaction_size is not None:
                size = p.transaction_size * (-1
                                             if p.transaction_size < 0 else 1)
                freed_space += size
                size_str = get_human_size_str(size)
            else:
                size_str = '?'

            dep_views.append(
                InputOption(label=f"{p.name}: -{size_str}",
                            value=p.name,
                            read_only=True,
                            icon_path=DEBIAN_ICON_PATH,
                            tooltip=p.description))

        deps_container = MultipleSelectComponent(id_='deps',
                                                 label='',
                                                 options=dep_views,
                                                 default_options={*dep_views},
                                                 max_width=537)

        freed_space_str = bold('-' + get_human_size_str(freed_space))
        body_text = TextComponent(html=self._i18n['debian.remove_deps'].format(
            no=bold(str(len(dependencies))),
            pkg=bold(source_pkg),
            fspace=freed_space_str),
                                  min_width=653)

        return watcher.request_confirmation(
            title=self._i18n['debian.transaction.title'],
            components=[body_text, deps_container],
            confirmation_label=self._i18n['popup.button.continue'],
            deny_label=self._i18n['popup.button.cancel'],
            min_height=200,
            body=None)
Exemple #18
0
    def list_warnings(self, internet_available: bool) -> List[str]:
        dbfiles = glob.glob('{}/*.db'.format(APPIMAGE_CACHE_PATH))

        if not dbfiles or len({
                f
                for f in (DATABASE_APPS_FILE, DATABASE_RELEASES_FILE)
                if f in dbfiles
        }) != 2:
            return [
                self.i18n['appimage.warning.missing_db_files'].format(
                    appimage=bold('AppImage'))
            ]
Exemple #19
0
    def _generate_backup(self, app_config: dict, i18n: I18n,
                         root_password: str) -> bool:
        if timeshift.is_available():
            if app_config['backup']['mode'] not in ('only_one', 'incremental'):
                self.show_message(title=self.i18n['error'].capitalize(),
                                  body='{}: {}'.format(
                                      self.i18n['action.backup.invalid_mode'],
                                      bold(app_config['backup']['mode'])),
                                  type_=MessageType.ERROR)
                return False

            if not user.is_root() and not root_password:
                root_pwd, valid = self.request_root_password()
            else:
                root_pwd, valid = root_password, True

            if not valid:
                return False

            handler = ProcessHandler(self)
            if app_config['backup']['mode'] == 'only_one':
                self.change_substatus('[{}] {}'.format(
                    i18n['core.config.tab.backup'].lower(),
                    i18n['action.backup.substatus.delete']))
                deleted, _ = handler.handle_simple(
                    timeshift.delete_all_snapshots(root_pwd))

                if not deleted and not self.request_confirmation(
                        title=i18n['core.config.tab.backup'],
                        body='{}. {}'.format(
                            i18n['action.backup.error.delete'],
                            i18n['action.backup.error.proceed']),
                        confirmation_label=i18n['yes'].capitalize(),
                        deny_label=i18n['no'].capitalize()):
                    return False

            self.change_substatus('[{}] {}'.format(
                i18n['core.config.tab.backup'].lower(),
                i18n['action.backup.substatus.create']))
            created, _ = handler.handle_simple(
                timeshift.create_snapshot(root_pwd,
                                          app_config['backup']['type']))

            if not created and not self.request_confirmation(
                    title=i18n['core.config.tab.backup'],
                    body='{}. {}'.format(i18n['action.backup.error.create'],
                                         i18n['action.backup.error.proceed']),
                    confirmation_label=i18n['yes'].capitalize(),
                    deny_label=i18n['no'].capitalize()):
                return False

        return True