Package: pearlcli
PearlBecause only in the best Shells you will find a Pearl...Project StatusCommunicationTable of ContentsDescriptionQuickstartInstallationDependenciesLinuxOSXCreate your own Pearl packageCreate your own Pearl repositoryTroubleshootingContributingDescriptionPearlis a lightweight package manager for automating reproducible environments
between different systems (Linux and OSX).
It can be used for dotfiles, plugins, programs and any form of code
accessible via git.As soon as a package gets installed, its content can be activated out of the box
according to certain events, like, for instance, a shell startup (Bash, Zsh or Fish) or
an editor startup (Vim or Emacs). This is possible via a smart and simplehook mechanismthat integrates the package content within the Pearl ecosystem.The main advantages on using Pearl are:Create your own Pearl package in a very simple way.Full control and sync of your dotfiles across different systems.Automatic bootstrap of the package content whenever shells or editors get started.Access to a wide range of existing packages via theOPH (Official Pearl Hub).Allows to create your own shareable package repository.Stable codebase with 100+ unit tests and exhaustive integration tests viaTravisfor Linux and OSX.Small number ofdependenciesneeded in order to ensure compatibility with most of the systems.Comparison with similar solution: AnsibleYou could achieve something similar from what Pearl provide by usingAnsible. Ansible is a powerful software for IT
automation which can be widely used for many use cases.
Despite of this, Ansible has few drawbacks when using it for lightweight forms of automation:Pearl uses bash for writing simple scripts for automation:it makes easier the integration with other programs in the system (without existing Playbooks may be hard and tedious to achieve this in Ansible);bash is a powerful, accessible and well-known language;Ansible requires way more dependencies than Pearl;Ansible requires knowledge about how Ansible Playbooks works;Pearl uses built-infunctionsandvariableswhich heavily simplify construction of scripts for automation;Pearl makes easier to remove packages and restore the system to an initial state;QuickstartThe Pearl command allows to:create,list,search,install,update,emerge,removethe Pearl packages defined according to the configuration located in$XDG_CONFIG_HOME/pearl/pearl.conf(defaults to~/.config/pearl/pearl.conf)CreateCommandcreatehelps you create a new local Pearl package:$pearlcreatemydotfiles~/dotfilesThis will create a directorypearl-configin~/dotfilescontaining all the templates to help you
start writing a Pearl package.~/dotfilesdoes not need to be an empty directory.
Additionally, the local repository in$XDG_CONFIG_HOME/pearl/pearl.confwill be updated with
the new package entry calledmydotfiles.For more information about thepearl-configcontent look at thesectionbelow.ListList all the available packages:$pearllist
...
pearl/dot-gitAwesomegitdotfiles(https://github.com/pearl-hub/git)pearl/sesaila[installed]AwesomealiasesforBash,ZshandFishshells(https://github.com/pearl-hub/sesaila)pearl/airline[installed]Status/tablineforvim(https://github.com/vim-airline/vim-airline)pearl/trash-cli[installed]Commandlineinterfacetothefreedesktop.orgtrashcan(https://github.com/pearl-hub/trash-cli)...SearchSearch forvimPearl packages:$pearlsearchvim
*Updatinghttps://github.com/pearl-hub/repo.gitrepository
pearl/dot-vimAwesomevimdotfiles(https://github.com/pearl-hub/vim)InstallInstallpearl/dot-vimpackage (as soon as the package is installed the package is ready out of the box in vim editor!):$pearlinstalldot-vim
*Updatinghttps://github.com/pearl-hub/repo.gitrepository
*Installingpearl/dot-vimpackageInstallpearl/trash-clipackage:$pearlinstalltrash-cli
*Updatinghttps://github.com/pearl-hub/repo.gitrepository
*Installingpearl/trash-clipackage
$trash-h
Usage:trash[OPTION]...FILE...

Putfilesintrash
...
...UpdateUpdatepearl/dot-vimpackage:$pearlupdatedot-vim
*Updatinghttps://github.com/pearl-hub/repo.gitrepository
*Updatingpearl/dot-vimpackageUpdate Pearl and all its packages installed:$pearlupdate
...
*Updatinghttps://github.com/pearl-hub/repo.gitrepository
*UpdatingPearlscript
*Updatingpearl/dot-vimpackage
*Updatingpearl/airlinepackage
*Updatingpearl/trash-clipackage
*Updatingpearl/capricapackage
...EmergeEmerge is an idempotent command for either installing or updating a package
depending whether the package is already installed or not. This command turns
to be particularly useful for establishing dependencies between packages.
See the sectionbelowfor more details.RemoveRemovepearl/dot-vimpackage:$pearlremovedot-vim
*Updatinghttps://github.com/pearl-hub/repo.gitrepository
*Removingpearl/dot-vimpackageRemove Pearl and all its packages installed:$pearlremove
...
AreyousuretoREMOVEallthePearlpackagesin$PEARL_HOMEfolder?(N/y)*Updatinghttps://github.com/pearl-hub/repo.gitrepository
*Removingpearl/dot-vimpackage
*Removingpearl/airlinepackage
*Removingpearl/trash-clipackage
*Removingpearl/capricapackage
...Recommended Pearl Hub packages to install:cmdkyratrangersesailatrash-clitxumFor dotfiles packages take a lookhere.Check out theOPH (Official Pearl Hub)for more packages you might be interested.InstallationDependenciesBefore installing Pearl be sure that all dependencies are properly installed in your system.
The Pearl dependencies are the following:Mandatorypython (>=3.5)bash (>=4.1)git (>=1.8)OptionalThe following are not mandatory dependencies but can be handy to have for the hook functions in Pearl package.
All the Linux distributions have these dependencies already installed.GNU coreutilsgrepsedAdditional shells supportedPearl supports also the following shells:fish (>=2.2.0)zsh (>=5.2)LinuxArch LinuxPearl can be installed in Arch Linux through AUR.
The package ispearl-git.For example, to install Pearl viayayAUR helper:yay -S pearl-gitAny other AUR helpers can be foundhere.Other Linux distributionsAssuming all Pearldependenciesare properly installed
in the system, to install Pearl you can use thepipcommand.
Unless there is a specific use case, it is not a good option to use virtual environments such asvirtualenvorcondabecause otherwise Pearl will be only visible within that environment.
It is recommended to use the system-widepipwhich is generally locate in/usr/bin/pip.
The following will install the package in your$HOMEdirectory (~/.local/):/usr/bin/pip install --user pearlcli
export PATH="~/.local/bin:$PATH"Pearl command will be located in~/.local/bin/pearlTo create the$PEARL_HOMEdirectory and the new pearl configuration file from template, run:pearl initOSXIn order to install all Pearl dependencies, you first need to installHomebrew.To install all the needed dependencies via Homebrew:brewupdate
brewinstallbashgitcoreutilsgrepgnu-sedpythonThe following will install the package under/usr/local:/usr/local/bin/pip3 install pearlcli
# If the bin path is not already in $PATH:
export PATH="/usr/local/bin:$PATH"Pearl command will be located in/usr/local/bin/pearlTo create the$PEARL_HOMEdirectory and the new pearl configuration file from template, run:pearl initIMPORTANT NOTE: Pearl gets loaded through~/.bashrc. The problem is that in OSX,
the terminal opens a login shell and only~/.bash_profilewill get executed.
Run the following only if~/.bashrcis not loaded within~/.bash_profilefile:echo"[[ -f ~/.bashrc ]] && source ~/.bashrc">>~/.bash_profileThis will make sure that~/.bashrcwill run at shell startup.Create your own Pearl packageAny git repository is already a Pearl package. For instance, in order
to manage a dotfiles repository in Pearl, you just need to change
the Pearl configuration file located in$XDG_CONFIG_HOME/pearl/pearl.conf.Add the following line topearl.conffile:PEARL_PACKAGES = {
    "mydotfiles": {
        "url": "https://github.com/user/mydotfiles.git",
        "description": "My dotfiles"
    },
}In other words, update thePEARL_PACKAGESdictionary with a new entry containing the
name of the package (i.e.mydotfiles),
the git url (i.e.https://github.com/user/mydotfiles.git) and an optional description.That's it!The package will be ready to beinstalled,updated,emergedandremovedvia the Pearl system.Structure of a Pearl packageYour own git repository can contain anoptionaldirectory
namedpearl-configused by Pearl to integrate the package with the Pearl environment./ (package root)
│
├── pearl-config (optional directory)
│   │
│   ├── hooks.sh
│   ├── config.sh
│   ├── config.bash
│   ├── config.zsh
│   ├── config.fish
│   ├── config.vim
│   └── config.el
│
└── (additional package content)The files insidepearl-configare alsooptionalscripts:hooks.sh- contains thehooks functionsexecuted during theinstall,updateandremoveevents.config.sh- will be sourced whenever a new Bash/Zsh shell is starting up.config.bash- will be sourced whenever a new Bash shell is starting up.config.zsh- will be sourced whenever a new Zsh shell is starting up.config.fish- will be sourced whenever a new Fish shell is starting up.config.vim- will be executed whenever Vim editor is starting up.config.el- will be sourced whenever Emacs editor is starting up.The following variables can be used in any of the previous scripts:PEARL_HOME- Pearl location ($XDG_DATA_HOME/pearlwhich by default is$HOME/.local/share/pearl)PEARL_PKGDIR- Pearl package locationPEARL_PKGVARDIR- Pearl package location containing data needed for packagePEARL_PKGNAME- Pearl package namePEARL_PKGREPONAME- Pearl package repo name (useful to detect and interact with packages within the same repo)Additionally, the scripthooks.shcan use the utility functions available inBuavaand Pearlutilsdirectory that
make easier the integration with Pearl ecosystem.Useful examples of Pearl packages can be checked in theOfficial Pearl Hub.The hooks.sh scriptHook functionspost_install- Calledafteran installation of the package occurs.pre_update- Calledbeforean update of the package occurs.post_update- Calledafteran update of the package occurs.pre_remove- Calledbeforea removal of the package occurs.An hooks.sh script examplepost_install() {
    warn "Remember to setup your config located in: ~/.dotfile"
    # Do a smart backup before modifying the file
    backup ${HOME}/.dotfile
    "# New dotfile" > ${HOME}/.dotfile
    link tmux "$PEARL_PKGDIR/mytmux.conf"

    info "Awesome - new package installed!"
    return 0
}
post_update() {
    post_install
    return 0
}
pre_remove() {
    info "dotfiles package removed"
    unlink tmux "$PEARL_PKGDIR/mytmux.conf"

    # Do an idempotent delete
    delete ${HOME}/.dotfile
    return 0
}Theinfoandwarnare functions that print a message
using different colors (namely cyan and yellow).Thelinkunlinkare idempotent functions (the result will not change
if the function will be called multiple times) that are able
to link/unlink a config file in order to be loaded at startup by a certain program.Thebackupkeeps the last three backups of the file and do not perform backup
if the file has not been modified since the latest backup. Thedeleteis a
function for idempotent remove (it will not raise an error if the file
no longer exist).All these functions belong to theBuavapackage
inutils.shand to the Pearlutils.shscript. You can use them
inside thehooks.shto any hook function.Very important note: All the hook functionsmustbeidempotent(the commands of each hook function must produce the same result even if
the command gets executed multiple times).
All buava commands are idempotent and this will help to write hook functions
very quickly.Note: For OSX system, the GNU versionsedandgrepare automatically
imported inhooks.shand can be directly used if needed.Create a Pearl package from a local directoryPearl package system will work even for local directories. This is particularly useful
whenever a Pearl package needs to be tested before pushing to a git repository.For instance, the following lines inpearl.conffile will add a package located in/home/joe/dotfiles:PEARL_PACKAGES = {
    "mydotfiles": {
        "url": "/home/user/mydotfiles",
        "description": "My dotfiles"
    },
}The directory path must be an absolute path.The package will be ready to beinstalled,updated,emergedandremovedvia the Pearl system.The directory content can be structured in the exact way as described
in thesectionabove.Define dependencies between Pearl packagesSuppose you have a packagemypackwhich depends on another packagemydep,
you can update themypackhooks.shfile in this way:post_install() {
    # Install/update the dependency here:
    pearl emerge ${PEARL_PKGREPONAME}/mydep
}
post_update() {
    post_install
}
pre_remove() {
    # Uncomment below to strictly remove the dependency
    # during the removal of the current package:
    #pearl remove ${PEARL_PKGREPONAME}/mydep
}ThePEARL_PKGREPONAMEvariable will make sure to define dependencies only
between packages of the same repository.
To see a real example in Pearl Hub, take a look at theKyrat hooks.sh.Use third-party git repository not available in Pearl HubIf you want to use a third-party git repository
that is not available in theOfficial Pearl Hub,
you can:Create your own git repository and use thePEARL_PKGVARDIRdirectory (recommended)Create your own git repository and usegit submodulePoint directly to the third-party git repositoryTo see examples of Pearl packages from third-party git repos take a look at theOfficial Pearl Hub.Create your own git repository and use thePEARL_PKGVARDIRdirectory (recommended)You can use thePEARL_PKGVARDIRdirectory during the installation phase to install the third-party git repository.
This is the best way to incorporate third-party project into Pearl ecosystem.Here it is an example ofhooks.shfile which install the ranger file manager into the directory${PEARL_PKGVARDIR}/ranger:function post_install(){
    install_or_update_git_repo https://github.com/ranger/ranger.git "${PEARL_PKGVARDIR}/ranger" master
}

function post_update(){
    post_install
}

function pre_remove(){
    rm -rf ${PEARL_PKGVARDIR}/ranger
}The functioninstall_or_update_git_repocomes from theBuavalibrary inutils.shwhich is natively available in Pearl during the installation.
You can even use the functionsinstall_git_repoorupdate_git_repowhich respectively install or update the git repository.For a full example take a look at therangerPearl Hub package.Create your own git repository and use git submoduleInside your git repository, you just need to add the third-party git repo as agit submodule.
For instance, to add thepowerlinein your Pearl package,
you can introduce a submodule in themoduledirectory:git submodule add https://github.com/powerline/powerline.git moduleThe filesystem structure of the package will become something like this:/ (package root)
│
├── pearl-config   (optional directory)
├── module/        (contains third-party code)
└── (additional package content)Then, you just need to modify the config scripts in order to integrate the third-party
project inside Pearl environment.Point directly to the third-party git repositoryLet's suppose you want to install thevim-railsplugin.
In your Pearl configuration ($XDG_CONFIG_HOME/pearl/pearl.conf), add your new Pearl package:PEARL_PACKAGES = {
    "vim-rails": {
        "url": "https://github.com/tpope/vim-rails.git",
        "description": "Ruby on Rails power tools"
    },
}Install the package:pearl install vim-railsVoila', your new vim plugin is ready to be used!This approach is particularly useful whenever you do not need to specify
any pearl config to"enrich"the third-party project inside
the Pearl environment.Create your own Pearl repositoryA Pearl repository is just a git repository containing a file located inpearl-config/pearl.confwith a list of packages. For instance, theOPHrepository is availablehere.In order to use the new repository (i.e. "https://github.com/myrepo/pearl-repo.git"),
update thepearl.conffile by adding the following line:PEARL_REPOS += ("https://github.com/myrepo/pearl-repo.git")TroubleshootingCorrupted Pearl Home directoryQ: What should I do if I accidentally removed files/packages in$PEARL_HOME?A: You can recover the structure of the$PEARL_HOMEby running:$> pearl initThe command will create all the essential directories and symlinks in$PEARL_HOME.
It is harmless to run theinitcommand multiple times since it is idempotent.Corrupted packageQ: Why I can no longer update/remove a package?A: This is probably because either one of the hook functions
is failing or the package content is corrupted. You can forcely remove the package:$> pearl remove <packagename>which bypass hook functions that are failing. If that does not even work,
you can delete a package by simply removing its directory:$> rm -rf $PEARL_HOME/packages/pearl/<packagename>After that, you can reinstall the package again.
The Pearl packages contain a dedicated directoryvarfor storing
data needed for the package itself.
Thevardata are always managed by the package and they never gets deleted by Pearl
during the package removal.
If you want to delete the content invarpackage:$> rm -rf $PEARL_HOME/var/pearl/<packagename>Package shell variables/functions not visible in current shell after installationQ: Why are not package's environment variables/functions visible in
my current shell after installing/updating the package?A: After package install/update, the variables or
functions related to the current shell and defined inpearl-config/config.*may not be available because a reload of Pearl configuration file is required.
You can fix this by simply run the function:pearl-sourcewhich reloads the configuration.
The use of such function is not always required but depends
whether the variables/functions involve the current shell where the
packageinstall/updateoccurred (i.e. a new variable defined inconfig.shand the current shell is a bash or zsh). Alternatively, user can always
create a new shell and the package resources will be available as
expected.Error during package installQ: Why Do I get the following error:Error on executing 'post_install' hook. Rolling back...A: This occurs when thepost_installhook function fails.
Pearl will attempt to roll back and force a removal of the package. In this way
you can attempt to install the package again once the hook function gets
fixed.ContributingYou could help improving Pearl and theOPHin the following ways:Reporting BugsSuggesting EnhancementsWriting CodeChange Log2.1.1- 2020-01-13Replaceinstall.shwithhooks.shinstall.shwill still be valid until next releasesFail if no command is specified2.1.0- 2020-01-12AddcreatecommandFix procedure to install Pearl in OSXFix ci to upload to PyPI2.0.2- 2020-01-11Add instructions to install Pearl in Arch LinuxFix bug for version option2.0.1- 2020-01-11Manual intervention to switch to Pearl v2Migration pageCodebase re-written in PythonRemove thepost_removepearl.confis not a python script. This requires manual intervention. Take a look at thepearl.conf.templatefile in codebasepearl-metadatadirectory is finally deprecatedAdd--no-confirmoptionAdd--forceoptionThis option bypasses failures even during the hook function executionAdd--verboseoption-vvallows to enable xtrace in hook functionsAdd--update-reposoptionShortcut commands (i.e.ito specifyinstallcommand) are no longer availablePearl file locations change drastically in order to be complaint with theXDG Base Directory SpecificationAs of now,pearl.confresides in$XDG_CONFIG_HOME/pearl(default~/.config/pearl)The new location for$PEARL_HOMEis$XDG_DATA_HOME/pearl(default~/.local/share/pearl)Remove the variables$PEARL_ROOTand$PEARL_TEMPORARY1.8.2- 2019-10-13UpdateREADME.mdfile1.8.1- 2019-07-13Updatebuava:New view action forsetup_configurationhelper function1.8.0- 2019-06-03Add roll back mechanism during install packageAddgrepandsedas optional dependencies since they may be used in hook functionsAdd newerbuava:backupfunctiondeletefunctionideavimandgvimdotfiles for (un)linkfunctionsinstall_or_update_vim_plugin_git_repofunctionAdd GNUsedandgrepfor OSX compat functions1.7.2- 2019-01-15Fix variablesPEARL_PKGNAMEPEARL_PKGREPONAMEfor vim and emacs boot1.7.1- 2018-08-11Deprecate pathogenEnsure tocdwhen updating package pointing to local directoryFix when package specified with full name does not existMore log info when Git URL package changeProceed even ifinstall.shis syntatically incorrect (prevent block for fixing the broken package)Improve doc and add section about comparison with Ansible1.7.0- 2018-07-05Add the idempotentemergecommand which update/install packages.No longer support the use of USR1 signal to source the Pearl config to the parent process. To explictly do that runpearl-sourcecommand instead.1.6.3- 2018-06-22Location of the repo file ispearl-config/pearl.conf. Backward compatibility will be kept until 2.0.0Make the branch name inferred from repo's HEAD rather than hardcode the branch withmaster1.6.2- 2018-06-09Add variablesPEARL_PKGNAMEPEARL_PKGREPONAMEFix boot vim for deprecatingpearl-metadataUpdate doc to use dynamic updates for third-party git reposAdd the buava git repo helpers1.6.1- 2018-02-04Fix importosx-compat.shFix update Pearl submodules during updates1.6.0- 2018-02-03Change directory name topearl-config. Pearl version2.0.0will deprecatepearl-metadatalink_to_pathto customize symlink nameChanges inbuavafor Pearl configs:osx_detectfunction to detect the OS platformImprovedchoosefunction with indexesAddsshfor[un]linkfunction1.5.6- 2017-08-31Fix Integ tests1.5.5- 2017-08-31Update Buava:UpdatedownloadfunctionAddchoose,inputandcontain_elementsfunctions1.5.4- 2017-08-28Update Buava:Adddownloadfunctionvimperator gtk2 programs for[un]linkfunctions1.5.3- 2017-06-29AddPear test utilsas new dependencyAddBunitas new dependencyAddBuavaas new dependencyInform about the trap on USR1 signal1.5.2- 2017-01-07Add support for new OSX image in TravisFallback to a default temp directory ifttydoes not work1.5.1- 2016-11-15Fix git --no-parser log for missing newline1.5.0- 2016-11-13Provide (un)link from/to in utils.shProvide list of last commits during add/update packageFixunlink_from_pathwhen source file is a symlink1.4.5- 2016-11-11Provide (un)link from/to PATH variable in utils.sh1.4.4- 2016-09-26Improving doc and add checkstyle1.4.3- 2016-05-25Remove the requirement of updating the PATH on OSX1.4.2- 2016-05-10Add support for OSXAdd check for existingPEARL_HOMEvariable for emacs/vim boot scriptsAddPEARL_HOME/bindirectory to have symlinks for the Pearl packages executablesAvoid pollutingPATHvariable by introducing a check first1.4.1- 2016-04-30Introduce$PEARL_PKGVARDIRon boot scriptsPackages do not need to havemasteras default branchChange the installation process to avoidpipe bash problemEnsure to get the most updatedpost_updatefunctionRefactor unit tests intest-package.sh1.4.0- 2016-04-23Add a dedicated directory$PEARL_PKGVARDIRfor the Pearl packages in order to store data
needed during the execution of the package itselfAdd warning in case of an old version of git or bashIntroduce$PEARL_PKGDIRenvironment variable for emacs and vim config filesChange the definition of public API1.3.1- 2016-04-21Fix compatibility with Bash 4.1Integration tests with fixed Bash and Git versions1.3.0- 2016-04-20Provide the definition of public APIAdd the emacs hookUse a better approach to return values from bash functionsChange location of the boot files for pearl.fish and pearl.shIntroduce the standard documentation for functionsUse try/catch approach to handle errors1.2.0- 2016-04-14Fix the removal of packages by querying the local directoryAdd (un)link functions for utils.sh1.1.0- 2016-04-09Check if Git URL changed during updatesIntroduce the template for new Pearl packagesLocal directories can be used as Pearl packagesAdd VERSION file1.0.1- 2016-04-08Update docsAdd travis and integration testsIntroduce the installer1.0.0- 2016-04-03Initial commit.