-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pipsi.sh
111 lines (101 loc) · 3.65 KB
/
pipsi.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/bin/bash
action=$1
name=$2
shift 2
if [[ -n ${name} && ${name} == --global ]]; then
global=true
name=''
else
global=$(arguments get global $*)
fi
bootstrap=false
if [[ -z ${name} ]]; then
bootstrap=true
name='pipsi'
fi
# set paths, try variables pipsi itself uses first and fall-back to
# defaults; take the 'global' option into account
declare -a pipsi_opts=( )
pipsi_bin_dir="${PIPSI_BIN_DIR:-"${HOME}/.local/bin"}"
pipsi_home="${PIPSI_HOME:-"${HOME}/.local/venvs"}"
if [[ ${global} == true ]]; then
pipsi_bin_dir="${PIPSI_GLOBAL_BIN_DIR:-"/usr/local/bin"}"
pipsi_home="${PIPSI_GLOBAL_HOME:-"/usr/local/lib/pipsi"}"
pipsi_opts+=( --bin-dir=${pipsi_bin_dir} --home=${pipsi_home} )
fi
pip="${pipsi_home}/${name}/bin/pip"
# if bin_dir or home are not writable, automatically attempt to elevate
# permissions using sudo
get_su() {
su=''
bake test -w "${pipsi_bin_dir}/" || su='sudo'
bake test -w "${pipsi_home}/" || su='sudo'
printf '%s' "${su}"
}
# return STATUS_MISSING if pipsi (local or global, according to option)
# is missing, return 0 otherwise
# note this is only useful in case of operating on pipsi itself, if any
# pipsi is available it is capable of installing packages either
# locally or globally
status_have_pipsi() {
bake which pipsi &>/dev/null || return "${STATUS_MISSING}"
if [[ ${global} == true ]]; then
bake type -ap pipsi |grep -q '^/usr' || return "${STATUS_MISSING}"
else
bake type -ap pipsi |grep -q "^${HOME}" || return "${STATUS_MISSING}"
fi
}
case "${action}" in
desc)
printf '%s\n' \
'asserts presence of packages installed via pipsi' \
'* pipsi (install/upgrade pipsi itself)' \
'* pipsi package-name (works on given package from pypi)' \
'--global (work on global packages instead of per-user)'
;;
status)
needs_exec "python3" || return "${STATUS_FAILED_PRECONDITION}"
if ${bootstrap}; then # operate on pipsi itself
status_have_pipsi || {
status="$?"
needs_exec "curl" || return "${STATUS_FAILED_PRECONDITION}"
needs_exec "git" || return "${STATUS_FAILED_PRECONDITION}"
return "${status}"
}
# pipsi is available, fall back to common check for up-to-date
else # operate on provided package
bake which pipsi || return "${STATUS_FAILED_PRECONDITION}"
# check output of `pipsi list` to see if package is installed
[[ $(bake pipsi "${pipsi_opts[@]}" list) =~ "Package \"${name}\"" ]] \
|| return "${STATUS_MISSING}"
fi
# pipsi doesn't provide a way to check if package is up-to-date,
# so for now have to use `pip` directly
! bake "${pip}" list --outdated --format=legacy | egrep "^${name} " \
|| return "${STATUS_OUTDATED}"
return "${STATUS_OK}"
;;
install)
su="$(get_su)"
if ${bootstrap}; then # operate on pipsi itself
# escape the pipe as we want `bake` to evaluate it lazily
# install pipsi from git master for now as release on pypi is
# ancient, master contains many fixes and some new features
bake curl -fsSL \
https://raw.githubusercontent.com/mitsuhiko/pipsi/master/get-pipsi.py \
\| "${su}" python3 - "${pipsi_opts[@]}" \
--ignore-existing \
--src 'git+https://github.com/mitsuhiko/pipsi.git#egg=pipsi'
else # operate on provided package
bake "${su}" pipsi "${pipsi_opts[@]}" install "${name}"
fi
bake "${pip}" install --upgrade pip setuptools
;;
upgrade|delete|remove)
if [ "$action" = "delete" ] || [ "$action" = "remove" ]; then
action="uninstall"
fi
bake "$(get_su)" pipsi "${pipsi_opts[@]}" "${action}" "${name}"
;;
*) return 1 ;;
esac