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))
def _gen_desktop_entry_path(self, app: AppImage) -> str: return '{}/bauh_appimage_{}.desktop'.format(DESKTOP_ENTRIES_PATH, app.get_clean_name())
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()