def install_package(pearl_env: PearlEnvironment, package: Package, args: Namespace): """ Installs the Pearl package. """ if package.is_installed(): raise PackageAlreadyInstalledError( '{} package is already installed.'.format(package)) messenger.print('{cyan}* {normal}Installing {pkg} package'.format( cyan=Color.CYAN, normal=Color.NORMAL, pkg=package, )) package.dir.mkdir(parents=True, exist_ok=True) if package.is_local(): check_and_copy(Path(package.url), package.dir) else: quiet = "false" if args.verbose else "true" script = dedent(""" install_git_repo {pkgurl} {pkgdir} "" {quiet} """).format(pkgdir=package.dir, pkgurl=package.url, quiet=quiet) run_pearl_bash(script, pearl_env, input=_DEFAULT_INPUT if args.no_confirm else None) package.vardir.mkdir(parents=True, exist_ok=True) hook = 'post_install' try: _run( hook, pearl_env, package, input=_DEFAULT_INPUT if args.no_confirm else None, enable_xtrace=(args.verbose >= 2), enable_errexit=(not args.force), ) except Exception as exc: msg = "Error while performing {} hook function. Rolling back...".format( hook) if args.force: message = "{}: {}".format(msg, exc.args) if args.verbose: messenger.exception(message) else: messenger.error(message) else: args.force = True remove_package( pearl_env, package, args=args, ) raise HookFunctionError(msg) from exc
def remove_pearl(pearl_env: PearlEnvironment, args: Namespace): """ Removes completely the Pearl environment. """ for repo_name, repo_packages in pearl_env.packages.items(): if ask(f"Are you sure to REMOVE all the installed packages in {repo_name} repository?", yes_as_default_answer=False, no_confirm=args.no_confirm): package_list = [] for _, package in repo_packages.items(): if package.is_installed(): package_list.append(package) args.packages = package_list remove_packages(pearl_env, args=args) if ask("Are you sure to REMOVE all the Pearl hooks?", yes_as_default_answer=False, no_confirm=args.no_confirm): unapply(f"source {pearl_env.home}/boot/sh/pearl.sh", f"{os.environ['HOME']}/.bashrc") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Deactivated Pearl for Bash') unapply(f"source {pearl_env.home}/boot/sh/pearl.sh", f"{os.environ['HOME']}/.zshrc") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Deactivated Pearl for Zsh') unapply(f"source {pearl_env.home}/boot/fish/pearl.fish", f"{os.environ['HOME']}/.config/fish/config.fish") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Deactivated Pearl for Fish shell') unapply(f"source {pearl_env.home}/boot/vim/pearl.vim", f"{os.environ['HOME']}/.vimrc") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Deactivated Pearl for Vim editor') unapply(f"(load-file \"{pearl_env.home}/boot/emacs/pearl.el\")", f"{os.environ['HOME']}/.emacs") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Deactivated Pearl for Emacs editor') if ask("Are you sure to REMOVE the Pearl config $PEARL_HOME directory (NOT RECOMMENDED)?", yes_as_default_answer=False, no_confirm=args.no_confirm): shutil.rmtree(str(pearl_env.home))
def info_package(pearl_env: PearlEnvironment, package: Package, args: Namespace): """ Provide info about a package. """ requires = pearl_env.required_by(package) messenger.print( dedent(""" {cyan}Name{normal}: {full_name} {cyan}Description{normal}: {description} {cyan}Homepage{normal}: {homepage} {cyan}URL{normal}: {url} {cyan}Author{normal}: {author} {cyan}License{normal}: {license} {cyan}Operating Systems{normal}: {os} {cyan}Keywords{normal}: {keywords} {cyan}Installed{normal}: {installed} {cyan}Pkg Directory{normal}: {pkg_dir} {cyan}Var Directory{normal}: {var_dir} {cyan}Depends on{normal}: {depends} {cyan}Required by{normal}: {requires} """.format( cyan=Color.CYAN, normal=Color.NORMAL, full_name=package.full_name, description=package.description, homepage=package.homepage, url=package.url, author=package.author, license=package.license, os=tuple(o.name.lower() for o in package.os), keywords=package.keywords, installed=package.is_installed(), pkg_dir=package.dir, var_dir=package.vardir, depends=tuple(d.full_name for d in package.depends), requires=tuple(r.full_name for r in requires), ))) return package, requires
def remove_package(pearl_env: PearlEnvironment, package: Package, args: Namespace): """ Remove the Pearl package. """ if not package.is_installed(): raise PackageNotInstalledError( '{} package has not been installed.'.format(package)) messenger.print('{cyan}* {normal}Removing {pkg} package'.format( cyan=Color.CYAN, normal=Color.NORMAL, pkg=package, )) hook = 'pre_remove' try: _run( hook, pearl_env, package, input=_DEFAULT_INPUT if args.no_confirm else None, enable_xtrace=(args.verbose >= 2), enable_errexit=(not args.force), ) except Exception as exc: msg = "Error while performing {} hook function".format(hook) if not args.force: raise HookFunctionError(msg) from exc message = "{}: {}".format(msg, exc.args) if args.verbose: messenger.exception(message) else: messenger.error(message) shutil.rmtree(str(package.dir))
def list_packages(pearl_env: PearlEnvironment, args: Namespace): """ Lists or searches Pearl packages. """ uninstalled_packages = [] installed_packages = [] pattern = args.pattern if hasattr(args, 'pattern') else ".*" regex = re.compile('{}'.format(pattern), flags=re.IGNORECASE) for _, repo_packages in pearl_env.packages.items(): for _, package in repo_packages.items(): if not regex.search(package.full_name) \ and not regex.search(package.description) \ and all([regex.search(key) is None for key in package.keywords]): continue if package.is_installed(): installed_packages.append(package) else: uninstalled_packages.append(package) total_packages = uninstalled_packages + installed_packages for package in total_packages: if args.package_only: template = "{reponame}/{package}" messenger.print( template.format( reponame=package.repo_name, package=package.name, )) else: label = "[installed]" if package.is_installed() else "" template = "{pink}{{reponame}}/{cyan}{{package}} {{installed}}{normal}".format( pink=Color.PINK, cyan=Color.CYAN, normal=Color.NORMAL, ) messenger.print( template.format( reponame=package.repo_name, package=package.name, installed=label, )) messenger.print(" {}".format(package.description)) return total_packages
def init_pearl(pearl_env: PearlEnvironment, _: Namespace): """ Initializes the Pearl environment by setting up the PEARL_HOME files and directories and the `pearl.conf` file. """ messenger.print( f'{Color.CYAN}* {Color.NORMAL}Setting up $PEARL_HOME directory as {pearl_env.home}' ) (pearl_env.home / 'bin').mkdir(parents=True, exist_ok=True) (pearl_env.home / 'packages').mkdir(parents=True, exist_ok=True) (pearl_env.home / 'repos').mkdir(parents=True, exist_ok=True) (pearl_env.home / 'var').mkdir(parents=True, exist_ok=True) static = Path(pkg_resources.resource_filename('pearllib', 'static/')) if (pearl_env.home / 'boot').exists(): (pearl_env.home / 'boot').unlink() (pearl_env.home / 'boot').symlink_to(static / 'boot') if not pearl_env.config_filename.exists(): messenger.print( f'{Color.CYAN}* {Color.NORMAL}Creating the Pearl configuration file {pearl_env.config_filename} from template $PEARL_HOME' ) pearl_env.config_filename.parent.mkdir(parents=True, exist_ok=True) pearl_conf_template = static / 'templates/pearl.conf.template' shutil.copyfile(str(pearl_conf_template), str(pearl_env.config_filename)) apply(f"source {pearl_env.home}/boot/sh/pearl.sh", f"{os.environ['HOME']}/.bashrc") messenger.print(f'{Color.CYAN}* {Color.NORMAL}Activated Pearl for Bash') apply(f"source {pearl_env.home}/boot/sh/pearl.sh", f"{os.environ['HOME']}/.zshrc") messenger.print(f'{Color.CYAN}* {Color.NORMAL}Activated Pearl for Zsh') apply(f"source {pearl_env.home}/boot/fish/pearl.fish", f"{os.environ['HOME']}/.config/fish/config.fish") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Activated Pearl for Fish shell') apply(f"source {pearl_env.home}/boot/vim/pearl.vim", f"{os.environ['HOME']}/.vimrc") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Activated Pearl for Vim editor') apply(f"(load-file \"{pearl_env.home}/boot/emacs/pearl.el\")", f"{os.environ['HOME']}/.emacs") messenger.print( f'{Color.CYAN}* {Color.NORMAL}Activated Pearl for Emacs editor') messenger.info('') messenger.info("Done! Open a new terminal and have fun!") messenger.info('') messenger.info("To get the list of Pearl packages available:") messenger.print(" >> pearl list")
def update_package(pearl_env: PearlEnvironment, package: Package, args: Namespace): """ Updates the Pearl package. """ if not package.is_installed(): raise PackageNotInstalledError( '{} package has not been installed.'.format(package)) messenger.print('{cyan}* {normal}Updating {pkg} package'.format( cyan=Color.CYAN, normal=Color.NORMAL, pkg=package, )) if package.has_url_changed(): messenger.info("The package URL for {} has changed to {}".format( package.full_name, package.url)) messenger.info("Replacing the package with the new repository...") remove_package(pearl_env, package, args) install_package(pearl_env, package, args) hook = 'pre_update' try: _run( hook, pearl_env, package, input=_DEFAULT_INPUT if args.no_confirm else None, enable_xtrace=(args.verbose >= 2), enable_errexit=(not args.force), ) except Exception as exc: msg = "Error while performing {} hook function".format(hook) if not args.force: raise HookFunctionError(msg) from exc message = "{}: {}".format(msg, exc.args) if args.verbose: messenger.exception(message) else: messenger.error(message) if package.is_local(): check_and_copy(Path(package.url), package.dir) else: quiet = "false" if args.verbose else "true" script = dedent(""" update_git_repo {pkgdir} "" {quiet} """).format(pkgdir=package.dir, quiet=quiet) run_pearl_bash(script, pearl_env, input=_DEFAULT_INPUT if args.no_confirm else None) hook = 'post_update' try: _run( hook, pearl_env, package, input=_DEFAULT_INPUT if args.no_confirm else None, enable_xtrace=(args.verbose >= 2), enable_errexit=(not args.force), ) except Exception as exc: msg = "Error while performing {} hook function".format(hook) if not args.force: raise HookFunctionError(msg) from exc message = "{}: {}".format(msg, exc.args) if args.verbose: messenger.exception(message) else: messenger.error(message)