示例#1
0
文件: worker.py 项目: vinifmor/bauh
    def create_symlink(app: AppImage, file_path: str, logger: logging.Logger, watcher: ProcessWatcher = None):
        logger.info("Creating a symlink for '{}'".format(app.name))
        possible_names = (app.get_clean_name(), '{}-appimage'.format(app.get_clean_name()), app.name.lower(), '{}-appimage'.format(app.name.lower()))

        if os.path.exists(SYMLINKS_DIR) and not os.path.isdir(SYMLINKS_DIR):
            logger.warning("'{}' is not a directory. It will not be possible to create a symlink for '{}'".format(SYMLINKS_DIR, app.name))
            return

        available_system_dirs = (SYMLINKS_DIR, *(l for l in ('/usr/bin', '/usr/local/bin') if os.path.isdir(l)))

        # checking if the link already exists:

        available_name = None
        for name in possible_names:
            available_name = name
            for sysdir in available_system_dirs:
                if os.path.exists('{}/{}'.format(sysdir, name)):
                    available_name = None
                    break

            if available_name:
                break

        if not available_name:
            msg = "It was not possible to create a symlink for '{}' because the names {} are already available on the system".format(app.name,
                                                                                                                                     possible_names)
            logger.warning(msg)
            if watcher:
                watcher.print('[warning] {}'.format(msg))
        else:
            try:
                Path(SYMLINKS_DIR).mkdir(parents=True, exist_ok=True)
            except:
                logger.error("Could not create symlink directory '{}'".format(SYMLINKS_DIR))
                return

            symlink_path = '{}/{}'.format(SYMLINKS_DIR, available_name)

            try:
                os.symlink(src=file_path, dst=symlink_path)
                app.symlink = symlink_path

                msg = "symlink successfully created at {}".format(symlink_path)
                logger.info(msg)

                if watcher:
                    watcher.print(msg)
            except:
                msg = "Could not create the symlink '{}'".format(symlink_path)
                logger.error(msg)

                if watcher:
                    watcher.print('[error] {}'.format(msg))
示例#2
0
 def _gen_desktop_entry_path(self, app: AppImage) -> str:
     return '{}/bauh_appimage_{}.desktop'.format(DESKTOP_ENTRIES_PATH,
                                                 app.get_clean_name())
示例#3
0
    def install(self, pkg: AppImage, root_password: str,
                disk_loader: Optional[DiskCacheLoader],
                watcher: ProcessWatcher) -> TransactionResult:
        handler = ProcessHandler(watcher)

        out_dir = INSTALLATION_PATH + pkg.get_clean_name()
        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 TransactionResult.fail()

        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 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 = '{}/{}'.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 = replace_desktop_entry_exec_command(
                        desktop_entry=de_content,
                        appname=pkg.name,
                        file_path=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)
                        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)

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

                    SymlinksVerifier.create_symlink(app=pkg,
                                                    file_path=file_path,
                                                    logger=self.logger,
                                                    watcher=watcher)
                    return TransactionResult(success=True,
                                             installed=[pkg],
                                             removed=[])
                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 TransactionResult.fail()