Example #1
0
def get_fields(app_id: str, branch: str, fields: List[str]) -> List[str]:
    cmd = ['flatpak', 'info', app_id]

    if branch:
        cmd.append(branch)

    info = new_subprocess(cmd).stdout

    res = []
    for o in new_subprocess(['grep', '-E', '({}):.+'.format('|'.join(fields)), '-o'], stdin=info).stdout:
        if o:
            res.append(o.decode().split(':')[-1].strip())

    return res
Example #2
0
def list_and_map_installed(
) -> dict:  # returns a dict with with package names as keys and versions as values
    installed = new_subprocess(
        ['pacman', '-Qq']).stdout  # retrieving all installed package names
    allinfo = new_subprocess(
        ['pacman', '-Qi'],
        stdin=installed).stdout  # retrieving all installed packages info

    ignored = {}
    thread_ignored = Thread(target=_fill_ignored, args=(ignored, ))
    thread_ignored.start()

    pkgs, current_pkg = {'mirrors': {}, 'not_signed': {}}, {}
    for out in new_subprocess(
        ['grep', '-E', '(Name|Description|Version|Validated By)'],
            stdin=allinfo
    ).stdout:  # filtering only the Name and Validated By fields:
        if out:
            line = out.decode()

            if line.startswith('Name'):
                current_pkg['name'] = line.split(':')[1].strip()
            elif line.startswith('Version'):
                version = line.split(':')
                current_pkg['version'] = version[len(version) - 1].strip()
            elif line.startswith('Description'):
                current_pkg['description'] = line.split(':')[1].strip()
            elif line.startswith('Validated'):

                if line.split(':')[1].strip().lower() == 'none':
                    pkgs['not_signed'][current_pkg['name']] = {
                        'version': current_pkg['version'],
                        'description': current_pkg['description']
                    }

                current_pkg = {}

    if pkgs and pkgs.get('not_signed'):
        thread_ignored.join()

        if ignored['pkgs']:
            to_del = set()
            for pkg in pkgs['not_signed'].keys():
                if pkg in ignored['pkgs']:
                    to_del.add(pkg)

            for pkg in to_del:
                del pkgs['not_signed'][pkg]

    return pkgs
Example #3
0
def read_updates(version: str, installation: str) -> Dict[str, set]:
    res = {'partial': set(), 'full': set()}
    if version < '1.2':
        try:
            output = run_cmd('{} update --no-related --no-deps --{}'.format(
                'flatpak', installation),
                             ignore_return_code=True)

            if 'Updating in {}'.format(installation) in output:
                for line in output.split('Updating in {}:\n'.format(
                        installation))[1].split('\n'):
                    if not line.startswith('Is this ok'):
                        res['full'].add('{}/{}'.format(
                            installation,
                            line.split('\t')[0].strip()))
        except:
            traceback.print_exc()
    else:
        updates = new_subprocess(
            ['flatpak', 'update', '--{}'.format(installation)]).stdout

        reg = r'[0-9]+\.\s+.+'

        try:
            for o in new_subprocess(['grep', '-E', reg, '-o', '--color=never'],
                                    stdin=updates).stdout:
                if o:
                    line_split = o.decode().strip().split('\t')

                    if version >= '1.5.0':
                        update_id = '{}/{}/{}'.format(line_split[2],
                                                      line_split[3],
                                                      installation)
                    else:
                        update_id = '{}/{}/{}'.format(line_split[2],
                                                      line_split[4],
                                                      installation)

                    if len(line_split) >= 6:
                        if line_split[4] != 'i':
                            if '(partial)' in line_split[-1]:
                                res['partial'].add(update_id)
                            else:
                                res['full'].add(update_id)
                    else:
                        res['full'].add(update_id)
        except:
            traceback.print_exc()

    return res
Example #4
0
File: snap.py Project: dik-b/bauh
def has_apps_field(name: str, ubuntu_distro: bool) -> bool:
    info_path = _get_app_info_path(ubuntu_distro)

    info_out = new_subprocess(['cat', info_path.format(name)]).stdout

    res = False
    for o in new_subprocess(['grep', '-E', 'apps', '--colour=never'],
                            stdin=info_out).stdout:
        if o:
            line = o.decode()

            if line.startswith('apps:'):
                res = True

    return res
Example #5
0
def get_mirrors(pkgs: Set[str]) -> dict:
    pkgre = '|'.join(pkgs)

    searchres = new_subprocess(['pacman', '-Ss', pkgre]).stdout
    mirrors = {}

    for line in new_subprocess(['grep', '-E', '.+/({}) '.format(pkgre)],
                               stdin=searchres).stdout:
        if line:
            match = line.decode()
            for p in pkgs:
                if p in match:
                    mirrors[p] = match.split('/')[0]

    return mirrors
Example #6
0
    def _get_aria2c_process(self, url: str, output_path: str, cwd: str) -> SystemProcess:
        cmd = ['aria2c', url,
               '--no-conf',
               '--max-connection-per-server=16',
               '--split=16',
               '--enable-color=false',
               '--stderr=true',
               '--summary-interval=0',
               '--disable-ipv6',
               '--min-split-size=1M',
               '--allow-overwrite=true',
               '--continue=true',
               '--timeout=5',
               '--max-file-not-found=3',
               '--remote-time=true']

        if output_path:
            output_split = output_path.split('/')
            cmd.append('--dir=' + '/'.join(output_split[:-1]))
            cmd.append('--out=' + output_split[-1])

        return SystemProcess(new_subprocess(cmd=cmd, cwd=cwd),
                             skip_stdout=True,
                             check_error_output=False,
                             success_phrases=['download completed'],
                             output_delay=0.001)
Example #7
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])
Example #8
0
def uninstall(app_ref: str):
    """
    Removes the app by its reference
    :param app_ref:
    :return:
    """
    return new_subprocess([BASE_CMD, 'uninstall', app_ref, '-y'])
Example #9
0
def update(app_ref: str):
    """
    Updates the app reference
    :param app_ref:
    :return:
    """
    return new_subprocess([BASE_CMD, 'update', '-y', app_ref])
Example #10
0
    def _get_wget_process(self, url: str, output_path: str, cwd: str) -> SystemProcess:
        cmd = ['wget', url]

        if output_path:
            cmd.append('-O')
            cmd.append(output_path)

        return SystemProcess(new_subprocess(cmd, cwd=cwd))
Example #11
0
def list_updates_as_str(version: str):
    if version < '1.2':
        return run_cmd('{} update'.format(BASE_CMD), ignore_return_code=True)
    else:
        updates = new_subprocess([BASE_CMD, 'update']).stdout

        out = StringIO()

        reg = r'[0-9]+\.\s+(\w+|\.)+\s+(\w|\.)+' if version >= '1.5.0' else r'[0-9]+\.\s+(\w+|\.)+\s+\w+\s+(\w|\.)+'

        for o in new_subprocess(['grep', '-E', reg, '-o', '--color=never'],
                                stdin=updates).stdout:
            if o:
                out.write('/'.join(o.decode().strip().split('\t')[2:]) + '\n')

        out.seek(0)
        return out.read()
Example #12
0
def uninstall(app_ref: str, installation: str):
    """
    Removes the app by its reference
    :param app_ref:
    :return:
    """
    return new_subprocess(
        ['flatpak', 'uninstall', app_ref, '-y', '--{}'.format(installation)])
Example #13
0
File: gpg.py Project: vinifmor/bauh
def receive_key(key: str, server: Optional[str] = None) -> SystemProcess:
    cmd = ['gpg']

    if server:
        cmd.extend(['--keyserver', server])

    cmd.extend(['--recv-key', key])

    return SystemProcess(new_subprocess(cmd), check_error_output=False)
Example #14
0
File: snap.py Project: jayvdb/bauh
def is_snapd_running() -> bool:
    services = new_subprocess(['systemctl', 'list-units'])

    service, service_running = False, False
    socket, socket_running = False, False
    for o in new_subprocess(['grep', '-Eo', 'snapd.+'], stdin=services.stdout).stdout:
        if o:
            line = o.decode().strip()

            if line:
                line_split = RE_SNAPD_STATUS.split(line)
                running = line_split[3] in SNAPD_RUNNING_STATUS

                if line_split[0] == 'snapd.service':
                    service = True
                    service_running = running
                elif line_split[0] == 'snapd.socket':
                    socket = True
                    socket_running = running

    return socket and socket_running and (not service or (service and service_running))
Example #15
0
def downgrade(app_ref: str, commit: str, installation: str,
              root_password: str) -> subprocess.Popen:
    cmd = [
        'flatpak', 'update', '--no-related', '--no-deps',
        '--commit={}'.format(commit), app_ref, '-y',
        '--{}'.format(installation)
    ]

    if installation == 'system':
        return new_root_subprocess(cmd, root_password)
    else:
        return new_subprocess(cmd)
Example #16
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
Example #17
0
def update(app_ref: str,
           installation: str,
           related: bool = False,
           deps: bool = False):
    """
    Updates the app reference
    :param app_ref:
    :return:
    """
    cmd = ['flatpak', 'update', '-y', app_ref, '--{}'.format(installation)]

    if not related:
        cmd.append('--no-related')

    if not deps:
        cmd.append('--no-deps')

    return new_subprocess(cmd)
Example #18
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
Example #19
0
 def is_downgrade_enabled(self) -> bool:
     try:
         new_subprocess(['git', '--version'])
         return True
     except FileNotFoundError:
         return False
Example #20
0
 def _is_wget_available(self):
     try:
         new_subprocess(['wget', '--version'])
         return True
     except FileNotFoundError:
         return False
Example #21
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
Example #22
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
Example #23
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()