Beispiel #1
0
    def _import_pgp_keys(self, pkgname: str, root_password: str,
                         handler: ProcessHandler):
        srcinfo = self.aur_client.get_src_info(pkgname)

        if srcinfo.get('validpgpkeys'):
            handler.watcher.print(self.i18n['arch.aur.install.verifying_pgp'])
            keys_to_download = [
                key for key in srcinfo['validpgpkeys']
                if not pacman.verify_pgp_key(key)
            ]

            if keys_to_download:
                keys_str = ''.join([
                    '<br/><span style="font-weight:bold">  - {}</span>'.format(
                        k) for k in keys_to_download
                ])
                msg_body = '{}:<br/>{}<br/><br/>{}'.format(
                    self.i18n['arch.aur.install.pgp.body'].format(
                        bold(pkgname)), keys_str, self.i18n['ask.continue'])

                if handler.watcher.request_confirmation(
                        title=self.i18n['arch.aur.install.pgp.title'],
                        body=msg_body):
                    for key in keys_to_download:
                        handler.watcher.change_substatus(
                            self.i18n['arch.aur.install.pgp.substatus'].format(
                                bold(key)))
                        if not handler.handle(
                                pacman.receive_key(key, root_password)):
                            handler.watcher.show_message(
                                title=self.i18n['error'],
                                body=self.
                                i18n['arch.aur.install.pgp.receive_fail'].
                                format(bold(key)),
                                type_=MessageType.ERROR)
                            return False

                        if not handler.handle(
                                pacman.sign_key(key, root_password)):
                            handler.watcher.show_message(
                                title=self.i18n['error'],
                                body=self.
                                i18n['arch.aur.install.pgp.sign_fail'].format(
                                    bold(key)),
                                type_=MessageType.ERROR)
                            return False

                        handler.watcher.change_substatus(
                            self.i18n['arch.aur.install.pgp.success'])
                else:
                    handler.watcher.print(self.i18n['action.cancelled'])
                    return False
Beispiel #2
0
    def downgrade(self, pkg: FlatpakApplication, root_password: str,
                  watcher: ProcessWatcher) -> bool:
        handler = ProcessHandler(watcher)
        pkg.commit = flatpak.get_commit(pkg.id, pkg.branch, pkg.installation)

        watcher.change_progress(10)
        watcher.change_substatus(self.i18n['flatpak.downgrade.commits'])
        commits = flatpak.get_app_commits(pkg.ref, pkg.origin,
                                          pkg.installation, handler)

        if commits is None:
            return False

        commit_idx = commits.index(pkg.commit)

        # downgrade is not possible if the app current commit in the first one:
        if commit_idx == len(commits) - 1:
            watcher.show_message(
                self.i18n['flatpak.downgrade.impossible.title'],
                self.i18n['flatpak.downgrade.impossible.body'],
                MessageType.WARNING)
            return False

        commit = commits[commit_idx + 1]
        watcher.change_substatus(self.i18n['flatpak.downgrade.reverting'])
        watcher.change_progress(50)
        success = handler.handle(
            SystemProcess(
                subproc=flatpak.downgrade(pkg.ref, commit, pkg.installation,
                                          root_password),
                success_phrases=['Changes complete.', 'Updates complete.'],
                wrong_error_phrase='Warning'))
        watcher.change_progress(100)
        return success
Beispiel #3
0
    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])
Beispiel #4
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 self.is_multithreaded():
                ti = time.time()
                process = self._get_aria2c_process(file_url, output_path, final_cwd)
            else:
                ti = time.time()
                process = self._get_wget_process(file_url, output_path, final_cwd)

            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
Beispiel #5
0
    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
Beispiel #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
Beispiel #7
0
    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
Beispiel #8
0
    def _uninstall(self, pkg_name: str, root_password: str,
                   handler: ProcessHandler) -> bool:
        res = handler.handle(
            SystemProcess(
                new_root_subprocess(['pacman', '-R', pkg_name, '--noconfirm'],
                                    root_password)))

        if res:
            cached_paths = [
                ArchPackage.disk_cache_path(pkg_name, 'aur'),
                ArchPackage.disk_cache_path(pkg_name, 'mirror')
            ]

            for path in cached_paths:
                if os.path.exists(path):
                    shutil.rmtree(path)
                    break

        return res
Beispiel #9
0
    def install(self, pkg: AppImage, root_password: str,
                watcher: ProcessWatcher) -> bool:
        handler = ProcessHandler(watcher)

        out_dir = INSTALLATION_PATH + pkg.name.lower()
        counter = 0
        while True:
            if os.path.exists(out_dir):
                self.logger.info(
                    "Installation dir '{}' already exists. Generating a different one"
                    .format(out_dir))
                out_dir += '-{}'.format(counter)
                counter += 1
            else:
                break

        Path(out_dir).mkdir(parents=True, exist_ok=True)
        pkg.install_dir = out_dir

        if pkg.imported:

            downloaded, file_name = True, pkg.local_file_path.split('/')[-1]

            file_path = out_dir + '/' + file_name

            try:
                moved, output = handler.handle_simple(
                    SimpleProcess(['mv', pkg.local_file_path, file_path]))
            except:
                self.logger.error("Could not rename file '' as '{}'".format(
                    pkg.local_file_path, file_path))
                moved = False

            if not moved:
                watcher.show_message(
                    title=self.i18n['error'].capitalize(),
                    body=self.i18n['appimage.install.imported.rename_error'].
                    format(bold(pkg.local_file_path.split('/')[-1]),
                           bold(output)),
                    type_=MessageType.ERROR)
                return False

        else:
            appimage_url = pkg.url_download_latest_version if pkg.update else pkg.url_download
            file_name = appimage_url.split('/')[-1]
            pkg.version = pkg.latest_version
            pkg.url_download = appimage_url

            file_path = out_dir + '/' + file_name
            downloaded = self.file_downloader.download(
                file_url=pkg.url_download,
                watcher=watcher,
                output_path=file_path,
                cwd=str(Path.home()))

        if downloaded:
            watcher.change_substatus(
                self.i18n['appimage.install.permission'].format(
                    bold(file_name)))
            permission_given = handler.handle(
                SystemProcess(new_subprocess(['chmod', 'a+x', file_path])))

            if permission_given:

                watcher.change_substatus(
                    self.i18n['appimage.install.extract'].format(
                        bold(file_name)))

                try:
                    res, output = handler.handle_simple(
                        SimpleProcess([file_path, '--appimage-extract'],
                                      cwd=out_dir))

                    if 'Error: Failed to register AppImage in AppImageLauncherFS' in output:
                        watcher.show_message(
                            title=self.i18n['error'],
                            body=self.
                            i18n['appimage.install.appimagelauncher.error'].
                            format(appimgl=bold('AppImageLauncher'),
                                   app=bold(pkg.name)),
                            type_=MessageType.ERROR)
                        handler.handle(
                            SystemProcess(
                                new_subprocess(['rm', '-rf', out_dir])))
                        return False
                except:
                    watcher.show_message(title=self.i18n['error'],
                                         body=traceback.format_exc(),
                                         type_=MessageType.ERROR)
                    traceback.print_exc()
                    handler.handle(
                        SystemProcess(new_subprocess(['rm', '-rf', out_dir])))
                    return False

                watcher.change_substatus(
                    self.i18n['appimage.install.desktop_entry'])
                extracted_folder = '{}/{}'.format(out_dir, 'squashfs-root')

                if os.path.exists(extracted_folder):
                    desktop_entry = self._find_desktop_file(extracted_folder)

                    with open('{}/{}'.format(extracted_folder,
                                             desktop_entry)) as f:
                        de_content = f.read()

                    de_content = RE_DESKTOP_EXEC.sub(
                        'Exec={}\n'.format(file_path), de_content)

                    extracted_icon = self._find_icon_file(extracted_folder)

                    if extracted_icon:
                        icon_path = out_dir + '/logo.' + extracted_icon.split(
                            '.')[-1]
                        shutil.copy(
                            '{}/{}'.format(extracted_folder, extracted_icon),
                            icon_path)
                        de_content = RE_DESKTOP_ICON.sub(
                            'Icon={}\n'.format(icon_path), de_content)
                        pkg.icon_path = icon_path

                    Path(DESKTOP_ENTRIES_PATH).mkdir(parents=True,
                                                     exist_ok=True)

                    with open(self._gen_desktop_entry_path(pkg), 'w+') as f:
                        f.write(de_content)

                    shutil.rmtree(extracted_folder)
                    return True
                else:
                    watcher.show_message(
                        title=self.i18n['error'],
                        body='Could extract content from {}'.format(
                            bold(file_name)),
                        type_=MessageType.ERROR)
        else:
            watcher.show_message(
                title=self.i18n['error'],
                body=self.i18n['appimage.install.download.error'].format(
                    bold(pkg.url_download)),
                type_=MessageType.ERROR)

        handler.handle(SystemProcess(new_subprocess(['rm', '-rf', out_dir])))
        return False
Beispiel #10
0
    def _install_from_aur(self,
                          pkgname: str,
                          maintainer: str,
                          root_password: str,
                          handler: ProcessHandler,
                          dependency: bool,
                          skip_optdeps: bool = False,
                          change_progress: bool = True) -> bool:
        app_build_dir = '{}/build_{}'.format(BUILD_DIR, int(time.time()))

        try:
            if not os.path.exists(app_build_dir):
                build_dir = handler.handle(
                    SystemProcess(
                        new_subprocess(['mkdir', '-p', app_build_dir])))
                self._update_progress(handler.watcher, 10, change_progress)

                if build_dir:
                    file_url = URL_PKG_DOWNLOAD.format(pkgname)
                    file_name = file_url.split('/')[-1]
                    handler.watcher.change_substatus('{} {}'.format(
                        self.i18n['arch.downloading.package'],
                        bold(file_name)))
                    download = handler.handle(
                        SystemProcess(new_subprocess(['wget', file_url],
                                                     cwd=app_build_dir),
                                      check_error_output=False))

                    if download:
                        self._update_progress(handler.watcher, 30,
                                              change_progress)
                        handler.watcher.change_substatus('{} {}'.format(
                            self.i18n['arch.uncompressing.package'],
                            bold(file_name)))
                        uncompress = handler.handle(
                            SystemProcess(
                                new_subprocess([
                                    'tar', 'xvzf', '{}.tar.gz'.format(pkgname)
                                ],
                                               cwd=app_build_dir)))
                        self._update_progress(handler.watcher, 40,
                                              change_progress)

                        if uncompress:
                            uncompress_dir = '{}/{}'.format(
                                app_build_dir, pkgname)
                            return self._make_pkg(
                                pkgname=pkgname,
                                maintainer=maintainer,
                                root_password=root_password,
                                handler=handler,
                                build_dir=app_build_dir,
                                project_dir=uncompress_dir,
                                dependency=dependency,
                                skip_optdeps=skip_optdeps,
                                change_progress=change_progress)
        finally:
            if os.path.exists(app_build_dir):
                handler.handle(
                    SystemProcess(new_subprocess(['rm', '-rf',
                                                  app_build_dir])))

        return False
Beispiel #11
0
    def _install(self,
                 pkgname: str,
                 maintainer: str,
                 root_password: str,
                 mirror: str,
                 handler: ProcessHandler,
                 install_file: str = None,
                 pkgdir: str = '.',
                 change_progress: bool = True):
        check_install_output = []
        pkgpath = install_file if install_file else pkgname

        handler.watcher.change_substatus(
            self.i18n['arch.checking.conflicts'].format(bold(pkgname)))

        for check_out in SimpleProcess(
            ['pacman', '-U' if install_file else '-S', pkgpath],
                root_password=root_password,
                cwd=pkgdir).instance.stdout:
            check_install_output.append(check_out.decode())

        self._update_progress(handler.watcher, 70, change_progress)
        if check_install_output and 'conflict' in check_install_output[-1]:
            conflicting_apps = [
                w[0] for w in re.findall(r'((\w|\-|\.)+)\s(and|are)',
                                         check_install_output[-1])
            ]
            conflict_msg = ' {} '.format(self.i18n['and']).join(
                [bold(c) for c in conflicting_apps])
            if not handler.watcher.request_confirmation(
                    title=self.i18n['arch.install.conflict.popup.title'],
                    body=self.i18n['arch.install.conflict.popup.body'].format(
                        conflict_msg)):
                handler.watcher.print(self.i18n['action.cancelled'])
                return False
            else:  # uninstall conflicts
                self._update_progress(handler.watcher, 75, change_progress)
                to_uninstall = [
                    conflict for conflict in conflicting_apps
                    if conflict != pkgname
                ]

                for conflict in to_uninstall:
                    handler.watcher.change_substatus(
                        self.i18n['arch.uninstalling.conflict'].format(
                            bold(conflict)))
                    if not self._uninstall(conflict, root_password, handler):
                        handler.watcher.show_message(
                            title=self.i18n['error'],
                            body=self.i18n['arch.uninstalling.conflict.fail'].
                            format(bold(conflict)),
                            type_=MessageType.ERROR)
                        return False

        handler.watcher.change_substatus(
            self.i18n['arch.installing.package'].format(bold(pkgname)))
        self._update_progress(handler.watcher, 80, change_progress)
        installed = handler.handle(
            pacman.install_as_process(pkgpath=pkgpath,
                                      root_password=root_password,
                                      aur=install_file is not None,
                                      pkgdir=pkgdir))
        self._update_progress(handler.watcher, 95, change_progress)

        if installed and self.context.disk_cache:
            handler.watcher.change_substatus(
                self.i18n['status.caching_data'].format(bold(pkgname)))
            if self.context.disk_cache:
                disk.save_several({pkgname},
                                  mirror=mirror,
                                  maintainer=maintainer,
                                  overwrite=True)

            self._update_progress(handler.watcher, 100, change_progress)

        return installed
Beispiel #12
0
    def _install_missings_deps_and_keys(self, pkgname: str, root_password: str,
                                        handler: ProcessHandler,
                                        pkgdir: str) -> bool:
        handler.watcher.change_substatus(
            self.i18n['arch.checking.deps'].format(bold(pkgname)))
        check_res = makepkg.check(pkgdir, handler)

        if check_res:
            if check_res.get('missing_deps'):
                depnames = {
                    RE_SPLIT_VERSION.split(dep)[0]
                    for dep in check_res['missing_deps']
                }
                dep_mirrors = self._map_mirrors(depnames)

                for dep in depnames:  # cheking if a dependency could not be found in any mirror
                    if dep not in dep_mirrors:
                        message.show_dep_not_found(dep, self.i18n,
                                                   handler.watcher)
                        return False

                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):
                    handler.watcher.print(self.i18n['action.cancelled'])
                    return False

                dep_not_installed = self._install_deps(depnames,
                                                       dep_mirrors,
                                                       root_password,
                                                       handler,
                                                       change_progress=False)

                if dep_not_installed:
                    message.show_dep_not_installed(handler.watcher, pkgname,
                                                   dep_not_installed,
                                                   self.i18n)
                    return False

                # 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)

            if check_res.get('gpg_key'):
                if handler.watcher.request_confirmation(
                        title=self.i18n['arch.aur.install.unknown_key.title'],
                        body=self.i18n['arch.install.aur.unknown_key.body'].
                        format(bold(pkgname), bold(check_res['gpg_key']))):
                    handler.watcher.change_substatus(
                        self.i18n['arch.aur.install.unknown_key.status'].
                        format(bold(check_res['gpg_key'])))
                    if not handler.handle(gpg.receive_key(
                            check_res['gpg_key'])):
                        handler.watcher.show_message(
                            title=self.i18n['error'],
                            body=self.
                            i18n['arch.aur.install.unknown_key.receive_error'].
                            format(bold(check_res['gpg_key'])))
                        return False
                else:
                    handler.watcher.print(self.i18n['action.cancelled'])
                    return False

        return True
Beispiel #13
0
    def downgrade(self, pkg: ArchPackage, root_password: str,
                  watcher: ProcessWatcher) -> bool:

        handler = ProcessHandler(watcher)
        app_build_dir = '{}/build_{}'.format(BUILD_DIR, int(time.time()))
        watcher.change_progress(5)

        try:
            if not os.path.exists(app_build_dir):
                build_dir = handler.handle(
                    SystemProcess(
                        new_subprocess(['mkdir', '-p', app_build_dir])))

                if build_dir:
                    watcher.change_progress(10)
                    watcher.change_substatus(self.i18n['arch.clone'].format(
                        bold(pkg.name)))
                    clone = handler.handle(
                        SystemProcess(subproc=new_subprocess(
                            ['git', 'clone',
                             URL_GIT.format(pkg.name)],
                            cwd=app_build_dir),
                                      check_error_output=False))
                    watcher.change_progress(30)
                    if clone:
                        watcher.change_substatus(
                            self.i18n['arch.downgrade.reading_commits'])
                        clone_path = '{}/{}'.format(app_build_dir, pkg.name)
                        pkgbuild_path = '{}/PKGBUILD'.format(clone_path)

                        commits = run_cmd("git log", cwd=clone_path)
                        watcher.change_progress(40)

                        if commits:
                            commit_list = re.findall(r'commit (.+)\n', commits)
                            if commit_list:
                                if len(commit_list) > 1:
                                    for idx in range(1, len(commit_list)):
                                        commit = commit_list[idx]
                                        with open(pkgbuild_path) as f:
                                            pkgdict = aur.map_pkgbuild(
                                                f.read())

                                        if not handler.handle(
                                                SystemProcess(
                                                    subproc=new_subprocess(
                                                        [
                                                            'git', 'reset',
                                                            '--hard', commit
                                                        ],
                                                        cwd=clone_path),
                                                    check_error_output=False)):
                                            watcher.print(
                                                'Could not downgrade anymore. Aborting...'
                                            )
                                            return False

                                        if '{}-{}'.format(
                                                pkgdict.get('pkgver'),
                                                pkgdict.get(
                                                    'pkgrel')) == pkg.version:
                                            # current version found
                                            watcher.change_substatus(self.i18n[
                                                'arch.downgrade.version_found']
                                                                     )
                                            break

                                    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)
                                else:
                                    watcher.show_message(
                                        title=self.
                                        i18n['arch.downgrade.error'],
                                        body=self.
                                        i18n['arch.downgrade.impossible'].
                                        format(pkg.name),
                                        type_=MessageType.ERROR)
                                    return False

                        watcher.show_message(
                            title=self.i18n['error'],
                            body=self.i18n['arch.downgrade.no_commits'],
                            type_=MessageType.ERROR)
                        return False

        finally:
            if os.path.exists(app_build_dir):
                handler.handle(
                    SystemProcess(
                        subproc=new_subprocess(['rm', '-rf', app_build_dir])))

        return False
Beispiel #14
0
    def _install(self, pkg: AppImage, watcher: ProcessWatcher, pre_downloaded_file: Optional[Tuple[str, str]] = None) \
            -> TransactionResult:

        handler = ProcessHandler(watcher)
        out_dir = f'{INSTALLATION_DIR}/{pkg.get_clean_name()}'
        counter = 0
        while True:
            if os.path.exists(out_dir):
                self.logger.info(f"Installation dir '{out_dir}' already exists. Generating a different one")
                out_dir += f'-{counter}'
                counter += 1
            else:
                break

        Path(out_dir).mkdir(parents=True, exist_ok=True)
        pkg.install_dir = out_dir

        if pkg.imported:

            downloaded, file_name = True, pkg.local_file_path.split('/')[-1]

            install_file_path = out_dir + '/' + file_name

            try:
                moved, output = handler.handle_simple(SimpleProcess(['mv', pkg.local_file_path, install_file_path]))
            except:
                output = ''
                self.logger.error(f"Could not rename file '{pkg.local_file_path}' as '{install_file_path}'")
                moved = False

            if not moved:
                watcher.show_message(title=self.i18n['error'].capitalize(),
                                     body=self.i18n['appimage.install.imported.rename_error'].format(bold(pkg.local_file_path.split('/')[-1]),
                                                                                                     bold(output)),
                                     type_=MessageType.ERROR)

                return TransactionResult.fail()

        else:
            download_data = pre_downloaded_file if pre_downloaded_file else self._download(pkg, watcher)

            if not download_data:
                return TransactionResult.fail()

            file_name, download_path = download_data[0], download_data[1]

            install_file_path = f'{out_dir}/{file_name}'

            try:
                shutil.move(download_path, install_file_path)
            except OSError:
                watcher.show_message(title=self.i18n['error'],
                                     body=self.i18n['error.mvfile'].formmat(src=bold(download_path),
                                                                            dest=bold(install_file_path)))
                return TransactionResult.fail()

        watcher.change_substatus(self.i18n['appimage.install.permission'].format(bold(file_name)))
        permission_given = handler.handle(SystemProcess(new_subprocess(['chmod', 'a+x', install_file_path])))

        if permission_given:

            watcher.change_substatus(self.i18n['appimage.install.extract'].format(bold(file_name)))

            try:
                res, output = handler.handle_simple(
                    SimpleProcess([install_file_path, '--appimage-extract'], cwd=out_dir))

                if 'Error: Failed to register AppImage in AppImageLauncherFS' in output:
                    watcher.show_message(title=self.i18n['error'],
                                         body=self.i18n['appimage.install.appimagelauncher.error'].format(
                                             appimgl=bold('AppImageLauncher'), app=bold(pkg.name)),
                                         type_=MessageType.ERROR)
                    handler.handle(SystemProcess(new_subprocess(['rm', '-rf', out_dir])))
                    return TransactionResult.fail()
            except:
                watcher.show_message(title=self.i18n['error'],
                                     body=traceback.format_exc(),
                                     type_=MessageType.ERROR)
                traceback.print_exc()
                handler.handle(SystemProcess(new_subprocess(['rm', '-rf', out_dir])))
                return TransactionResult.fail()

            watcher.change_substatus(self.i18n['appimage.install.desktop_entry'])
            extracted_folder = f'{out_dir}/squashfs-root'

            if os.path.exists(extracted_folder):
                desktop_entry = self._find_desktop_file(extracted_folder)

                with open(f'{extracted_folder}/{desktop_entry}') as f:
                    de_content = f.read()

                if de_content:
                    de_content = replace_desktop_entry_exec_command(desktop_entry=de_content,
                                                                    appname=pkg.name,
                                                                    file_path=install_file_path)
                extracted_icon = self._find_icon_file(extracted_folder)

                if extracted_icon:
                    icon_path = out_dir + '/logo.' + extracted_icon.split('/')[-1].split('.')[-1]
                    shutil.copy(extracted_icon, icon_path)

                    if de_content:
                        de_content = RE_DESKTOP_ICON.sub(f'Icon={icon_path}\n', de_content)

                    pkg.icon_path = icon_path

                if not de_content:
                    de_content = pkg.to_desktop_entry()

                Path(DESKTOP_ENTRIES_DIR).mkdir(parents=True, exist_ok=True)

                with open(self._gen_desktop_entry_path(pkg), 'w+') as f:
                    f.write(de_content)

                try:
                    shutil.rmtree(extracted_folder)
                except:
                    traceback.print_exc()

                SymlinksVerifier.create_symlink(app=pkg, file_path=install_file_path, logger=self.logger,
                                                watcher=watcher)
                return TransactionResult(success=True, installed=[pkg], removed=[])
            else:
                watcher.show_message(title=self.i18n['error'],
                                     body=f'Could extract content from {bold(file_name)}',
                                     type_=MessageType.ERROR)

        handler.handle(SystemProcess(new_subprocess(['rm', '-rf', out_dir])))
        return TransactionResult.fail()
Beispiel #15
0
    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)))
        check_res = makepkg.check(pkgdir,
                                  optimize=self.local_config['optimize'],
                                  handler=handler)

        if check_res:
            if check_res.get('missing_deps'):
                handler.watcher.change_substatus(
                    self.i18n['arch.checking.missing_deps'].format(
                        bold(pkgname)))
                sorted_deps = self._map_unknown_missing_deps(
                    check_res['missing_deps'],
                    handler.watcher,
                    check_subdeps=check_subdeps)

                if sorted_deps is None:
                    return False

                handler.watcher.change_substatus(
                    self.i18n['arch.missing_deps_found'].format(bold(pkgname)))

                if not confirmation.request_install_missing_deps(
                        pkgname, sorted_deps, handler.watcher, self.i18n):
                    handler.watcher.print(self.i18n['action.cancelled'])
                    return False

                dep_not_installed = self._install_deps(sorted_deps,
                                                       root_password,
                                                       handler,
                                                       change_progress=False)

                if dep_not_installed:
                    message.show_dep_not_installed(handler.watcher, pkgname,
                                                   dep_not_installed,
                                                   self.i18n)
                    return False

                # it is necessary to re-check because missing PGP keys are only notified when there are none missing
                return self._handle_deps_and_keys(pkgname,
                                                  root_password,
                                                  handler,
                                                  pkgdir,
                                                  check_subdeps=False)

            if check_res.get('gpg_key'):
                if handler.watcher.request_confirmation(
                        title=self.i18n['arch.aur.install.unknown_key.title'],
                        body=self.i18n['arch.install.aur.unknown_key.body'].
                        format(bold(pkgname), bold(check_res['gpg_key']))):
                    handler.watcher.change_substatus(
                        self.i18n['arch.aur.install.unknown_key.status'].
                        format(bold(check_res['gpg_key'])))
                    if not handler.handle(gpg.receive_key(
                            check_res['gpg_key'])):
                        handler.watcher.show_message(
                            title=self.i18n['error'],
                            body=self.
                            i18n['arch.aur.install.unknown_key.receive_error'].
                            format(bold(check_res['gpg_key'])))
                        return False
                else:
                    handler.watcher.print(self.i18n['action.cancelled'])
                    return False

            if check_res.get('validity_check'):
                handler.watcher.show_message(
                    title=self.i18n['arch.aur.install.validity_check.title'],
                    body=self.i18n['arch.aur.install.validity_check.body'].
                    format(bold(pkgname)),
                    type_=MessageType.ERROR)
                return False

        return True