Skip to content

Commit

Permalink
[Fix] installer installed packages (#106)
Browse files Browse the repository at this point in the history
* Added dependencies

* Added dependencies only when backup is requested

* Added to is_installed the possibility to check with a package manager or specific package manager

* Removed package dependency cargo-update to avoid installing in CI. It will be installed in non CI when executing dot package update_all at the end of installation

* Fixed packages to be installed

* Fixed conditional when choose registry

* Now arguments can be passed to install and uninstall functions

* Improved uninstall

* Fixed ok message color

* Fixed error checking if a package was installed when package to be checked has a similar name to one installed

* Now you can pass arguments to install and uninstall functions without needed of know which package manager you need to use. Force install and uninstall are completely possible giving to latest function to be used the argument --force. Package managers can be refactored to use this new option

* Added bash recipe

* Added zsh recipe

* Fixed wrong calling to function because of naming.

Co-authored-by: Gabriel Trabanco Llano <gtrabanco@users.noreply.github.com>
  • Loading branch information
gtrabanco and gtrabanco authored Jul 25, 2021
1 parent 48a66cc commit 7095206
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 85 deletions.
12 changes: 10 additions & 2 deletions scripts/core/install
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ dot::load_library "install.sh"
export ZIM_HOME="${SLOTH_PATH:-${DOTLY_PATH:-}}/modules/zimfw"
export PATH="$HOME/.cargo/bin:$PATH"

# Mandatory packages first
script::depends_on docpars fzf

# Packages that are necessary but not in CI env
if [[ "${DOTLY_ENV:-PROD}" != "CI" ]]; then
script::depends_on python-yq jq cargo-update
fi

# OS specific packages
output::answer "Installing specific OS packages if not installed"
if platform::is_macos; then
output::answer "🍎 Setting up macOS platform"
install_macos_custom
Expand All @@ -17,8 +27,6 @@ elif platform::is_linux; then
install_linux_custom
fi

script::depends_on cargo cargo-update docpars zsh fzf python3 python-yq jq

##? Install dotly and setup dotfiles. By default use a interactive backup (backups are not done for core symlinks).
##?
##? Usage:
Expand Down
18 changes: 11 additions & 7 deletions scripts/core/src/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ install_macos_custom() {

mkdir -p "$HOME/bin"

output::answer "Installing needed gnu packages"
if platform::command_exists brew; then
brew cleanup -s | log::file "Brew executing cleanup"
brew cleanup --prune-prefix | log::file "Brew removing dead symlinks"
Expand All @@ -46,11 +45,12 @@ install_macos_custom() {
fi
fi

custom::install bash zsh coreutils findutils gnu-sed python3-pip
output::answer "Installing needed gnu packages"
custom::install coreutils findutils gnu-sed

# To make CI Checks faster this packages are only installed if not CI
if [[ "${DOTLY_ENV:-PROD}" != "CI" ]]; then
custom::install gnutls gnu-tar gnu-which gawk grep make hyperfine docpars zsh fzf python-yq jq
custom::install gnutls gnu-tar gnu-which gawk grep make bash zsh bash-completion@2 zsh-completions python3-pip

# Adds brew zsh and bash to /etc/shells
HOMEBREW_PREFIX="${HOMEBREW_PREFIX:-$(brew --prefix)}"
Expand Down Expand Up @@ -102,17 +102,21 @@ install_linux_custom() {
output::write " 2. Make an issue telling your os and which package manager are you using."
output::answer "${SLOTH_GITHUB_REPOSITORY_NEW_ISSUE_URL}"
output::empty_line
output::anser "Continue with cargo"
custom::install cargo cargo-update docpars hyperfine

if [[ "${DOTLY_ENV:-PROD}" != "CI" ]]; then
output::anser "Continue with cargo"
custom::install cargo cargo-update docpars hyperfine
fi

return
fi

output::answer "Installing Linux Packages"
custom::install bash zsh hyperfine docpars python3-pip build-essential coreutils findutils
custom::install build-essential coreutils findutils

# To make CI Checks faster this packages are only installed if not CI
if [[ "${DOTLY_ENV:-PROD}" != "CI" ]]; then
custom::install fzf python-yq jq
custom::install bash zsh python3-pip python-yq jq

# Required packages output an error
if ! package::is_installed "docpars" || ! package::is_installed "python3-pip" || ! package::is_installed "python-yq"; then
Expand Down
145 changes: 89 additions & 56 deletions scripts/core/src/package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -205,52 +205,68 @@ package::manager_self_update() {
}

#;
# package::is_installed()
# Check if a package is installed with a recipe or any of the available package managers. It does not check if a binary package_name is available
# @param string package_name
# @return boolean
# package::which_package_manager()
# Output which package manager was used to install a package
# @param string package
# @param boolean avoid_registry_check If true avoid check if package is installed with the registry
# @return boolean If package is not installed
#"
package::is_installed() {
package::which_package_manager() {
local package_manager
local -r package_name="${1:-}"
local -r avoid_registry_check=${2:-false}
[[ -z "$package_name" ]] && return 1

# Check every package manager first because maybe registry has used a package manager
for package_manager in $(package::get_all_package_managers "is_available" "is_installed"); do
package::command "$package_manager" "is_available" &&
package::command "$package_manager" is_installed "$package_name" && echo "$package_manager" && return
done

# Because registry::is_installed is defined in core. This is a expected behavior and we do it at
# the end because probably a package was installed with a package manager spite of being a reicpe
if
[[ -n "$(registry::recipe_exists "$package_name")" ]] &&
! $avoid_registry_check &&
[[ -n "$(registry::recipe_exists "$package_name")" ]] &&
registry::command_exists "$package_name" "is_installed"
then
registry::is_installed "$package_name" && return
registry::is_installed "$package_name" && echo "registry" && return
return 1
fi

package::which_package_manager "$package_name" &> /dev/null && return 0

return 1
}

#;
# package::which_package_manager()
# Output which package manager was used to install a package
# @param string package
# @return boolean If package is not installed
# package::is_installed()
# Check if a package is installed with a recipe or any of the available package managers. It does not check if a binary package_name is available
# @param string package_name
# @param string package_manager Can be "any" to use any package manager or registry (same as empty). "auto" to use any one except registry. "recipe" or "registry" are aliases. Can be any other valid package manager in 'scripts/package/src/package_managers'.
# @return boolean
#"
package::which_package_manager() {
package::is_installed() {
local package_manager
local -r package_name="${1:-}"
package_manager="${2:-}"
[[ -z "$package_name" ]] && return 1

# Check every package manager first because maybe registry has used a package manager
for package_manager in $(package::get_all_package_managers "is_available" "is_installed"); do
package::command "$package_manager" "is_available" &&
package::command "$package_manager" is_installed "$package_name" && echo "$package_manager" && return
done
# Allow to use recipe(s) instead of registry
[[ -n "$package_manager" && $package_manager == "recipe"[s] ]] && package_manager="registry"

# Any package manager is the same as empty package_manager
[[ $package_manager == "any" ]] && package_manager=""

if
[[ -n "$(registry::recipe_exists "$package_name")" ]] &&
[[ -z "$package_manager" || $package_manager == "registry" ]] &&
[[ -n "$(registry::recipe_exists "$package_name")" ]] &&
registry::command_exists "$package_name" "is_installed"
then
registry::is_installed "$package_name" && echo "registry" && return
registry::is_installed "$package_name" && return
return 1
elif [[ $package_manager == "auto" || -z "$package_manager" ]]; then
package::which_package_manager "$package_name" true &> /dev/null && return 0
elif [[ -n "$package_manager" ]]; then
package::command_exists "$package_manager" "is_installed" && package::command "$package_manager" "is_installed" "$package_name" && return
fi

return 1
Expand Down Expand Up @@ -280,15 +296,12 @@ package::_install() {
then

if
! package::command "$package_manager" "is_installed" "$package"
package::command "$package_manager" "package_exists" "$package" &&
package::command "$package_manager" "install" "$package" "$@"
then
package::command "$package_manager" "is_installed" "$package" && return
fi

package::command "$package_manager" "is_installed" "$package" && return

elif
package::command_exists "$package_manager" "is_available" &&
package::command_exists "$package_manager" "install" &&
Expand All @@ -297,19 +310,20 @@ package::_install() {
then

package::command "$package_manager" "install" "$package" "$@" &&
package::command_exists "$package_manager" "is_installed" &&
package::command "$package_manager" "is_installed" &&
return

fi

# Not exists or not installed
return 1
}

#;
# package::install()
# Try to install with any available package manager, but if you provided a package manager (second param) it will only try to use that package manager. This avoids to install from registry recipe (use package::install_recipe_first).
# @param string package Package to install
# @param string package_manager Force to use only package manager if define this param
# @param string package_manager Can be "any" to use any package manager or registry. "auto" to use any one except registry. "recipe" or "registry" are aliases. Can be any other valid package manager in 'scripts/package/src/package_managers'.
# @param any args Arguments for package manager wrapper
# @return boolen
#"
Expand All @@ -319,32 +333,35 @@ package::install() {
package="$1"
shift
package_manager="${1:-}"

# Allow to use recipe(s) instead of registry
[[ -n "$package_manager" && $package_manager == "recipe"[s] ]] && package_manager="registry"
if [[ -n "$package_manager" ]]; then
shift
# Allow to use recipe(s) instead of registry
[[ $package_manager == "recipe"[s] ]] && package_manager="registry"
[[ $package_manager == "any" ]] && package_manager=""
fi

if
[[
-n "$package_manager" &&
$package_manager != "auto" ]]
$package_manager != "auto" &&
$package_manager != "registry" ]]
then

if [[ -n "$(package::manager_exists "$package_manager")" ]]; then
shift
package::_install "$package_manager" "$package" "$@"
package::_install "$package_manager" "$package" "$@" &&
return 0
else
output::error "Package manager not found"
return 1
fi
elif
[[
$package_manager != "auto" &&
-n "$(registry::recipe_exists "$package")" ]]
-z "$package_manager" ||
$package_manager == "registry" ]] &&
[[ -n "$(registry::recipe_exists "$package")" ]]
then

[[ -n "$package_manager" ]] && shift

registry::install "$package" "$@" && registry::is_installed "$package" "$@"
registry::install "$package" "$@" && registry::is_installed "$package" "$@" && return 0
else
if platform::command_exists readarray; then
readarray -t all_available_pkgmgrs < <(package::get_available_package_managers)
Expand All @@ -354,28 +371,27 @@ package::install() {
fi
eval "$(array::uniq_unordered "${SLOTH_PACKAGE_MANAGERS_PRECEDENCE[@]}" "${all_available_pkgmgrs[@]}")"

[[ -n "$package_manager" ]] && shift

# Try to install from package managers precedence
# Try to install respecting package managers precedence
for package_manager in "${uniq_values[@]}"; do
if
[[ -n "$(package::manager_exists "$package_manager")" ]] &&
package::load_manager "$package_manager" &&
package::_install "$package_manager" "$package" "$@"
then
return
return 0
fi
done

return 1
fi

return 1
}

#;
# package::uninstall()
# Uninstall the given package, if second parameter is given it will try do it with package manager
# @param string package_name
# @param string package_manager Optional, if not provided will try to look up which package manager should be used. If you set to auto it will try to uninstall with any available package manager ignoring registry (recipes).
# @param string package_manager Can be "any" to use any package manager or registry. "auto" to use any one except registry. "recipe" or "registry" are aliases. Can be any other valid package manager in 'scripts/package/src/package_managers'.
# @param any args Additional arguments to be passed to uninstall function (package_manager is required then)
# @return boolean True if uninstalled and false if still installed
#"
Expand All @@ -384,25 +400,42 @@ package::uninstall() {
[[ $# -lt 1 ]] && return 1
local -r package_name="$1"
shift
package_manager="${2:-}"

local -r recipe_path="$(registry::recipe_exists "$package_name")"
package_manager="${1:-}"
if [[ -n "$package_manager" ]]; then
shift
# Allow to use recipe(s) instead of registry
[[ $package_manager == "recipe"[s] ]] && package_manager="registry"
[[ $package_manager == "any" ]] && package_manager=""
fi

if
[[ -z "$package_manager" || "$package_manager" == "registry" || "$package_manager" == "recipe" ]] &&
[[ $package_manager != "auto" ]] &&
[[ -f "$recipe_path" ]] &&
registry::command_exists "$package_name" "uninstall"
then
registry::command "$package_name" "uninstall" "$@" && ! registry::is_installed "$package_name"
if [[ -z "$package_manager" || $package_manager == "registry" ]]; then
local -r recipe_path="$(registry::recipe_exists "$package_name")"
if
[[ -n "$recipe_path" ]] &&
registry::command_exists "$package_name" "uninstall"
then
registry::uninstall "$package_name" "$@" && ! registry::is_installed "$package_name" && return 0
fi
else
package_manager="${package_manager:-$(package::which_package_manager "$package_name" || echo -n)}"
[[ -z "$package_manager" ]] && return 1 # Could not determine which package manager to be used
[[ $package_manager == "auto" || -z "$package_manager" ]] && package_manager="$(package::which_package_manager "$package_name" || echo -n)"
if
[[
-z "$package_manager" ||
-z "$(package::manager_exists "$package_manager")" ]]
then

echo "Package manager $package_manager"
# Could not determine which package manager to be used or package manager not exists
return 1
fi

if package::command_exists "$package_manager" "uninstall"; then
package::command "$package_manager" "uninstall" "$package_name" "$@" && ! package::is_installed "$package_name"
package::command "$package_manager" "uninstall" "$package_name" "$@" && ! package::is_installed "$package_name" && return 0
fi
fi

# Recipe or package not uninstalled or does not have uninstall wrapper (function) (can happen with both package managers and registry)
return 1
}

#;
Expand Down
10 changes: 6 additions & 4 deletions scripts/core/src/registry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -94,28 +94,30 @@ registry::command() {
# registry::install()
# Install the given recipe
# @param string recipe
# @param any optional args
# @return boolean
#"
registry::install() {
local -r recipe="${1:-}"
local -r command="install"
[[ -z "$recipe" ]] && return 1
shift

registry::command "$recipe" "${command}"
registry::command "$recipe" "install" "$@"
}

#;
# registry::uninstall()
# Uninstall the given recipe
# @param string recipe
# @param any optional args
# @return boolean
#"
registry::uninstall() {
local -r recipe="${1:-}"
local -r command="uninstall"
[[ -z "$recipe" ]] && return 1
shift

registry::command "$recipe" "${command}"
registry::command "$recipe" "uninstall" "$@"
}

#;
Expand Down
Loading

0 comments on commit 7095206

Please sign in to comment.