Skip to content

Instantly share code, notes, and snippets.

@adamnew123456
Created April 5, 2015 17:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamnew123456/8358f23f3ac8a3b9bb02 to your computer and use it in GitHub Desktop.
Save adamnew123456/8358f23f3ac8a3b9bb02 to your computer and use it in GitHub Desktop.
USM Fix
#!/bin/sh
set -u
USAGE='Usage: usm COMMAND ...
usm help
usm init
usm copy-script
usm add SOFTWARE VERSION
usm set-current SOFTWARE VERSION
usm ls [SOFTWARE] [SOFTWARE] ...
usm path SOFTWARE VERSION
usm rm SOFTWARE VERSION'
HELP='Usage: usm COMMAND ...
Commands:
help
Show this help page.
init
Initializes a fresh USM repository. The location should be contained
in the environment variable USM_PATH - otherwise, $HOME/Apps
becomes the location for the new USM repository.
Note that this calls create-script automatically, and will thus
clobber the file $HOME/.usm-env
copy-script
Copies the USM startup script to $HOME/.usm-env
add SOFTWARE VERSION
Configures a directory for a new version of the given software.
Also, if there is no version of SOFTWARE already installed, then
VERSION becomes the default version.
set-current SOFTWARE VERSION
Sets VERSION to be the current version of SOFTWARE. This changes
which version is added to $PATH, $PKG_CONFIG_PATH, $MANPATH, and
whatever other variables are added via ~/.usm-env
ls [SOFTWARE...]
Lists out the software installed in USM, and all of the versions
of each software. If SOFTWARE is given, only versions of SOFTWARE
are listed.
path SOFTWARE VERSION
Gets the absolute path to the directory storing VERSION of
SOFTWARE.
rm SOFTWARE VERSION
Removes VERSION of SOFTWARE - if VERSION is the last remaining
version, then the whole directory containing SOFTWARE is removed.'
if [ -z "$USM_PATH" ]; then
echo '$USM_PATH not set - aborting'
exit 1
fi
STARTUP_SCRIPT="`sed '1,/^BEGIN ENV SCRIPT/d' < "$0" | sed "s:%USM_PATH%:$USM_PATH:g"`"
# Make sure that a particular software-version combo exists - if not, then
# exit with an error
assert_software_exists() {
_SOFTWARE="$1"
_VERSION="$2"
test -d "$USM_PATH/$_SOFTWARE/$_VERSION"
_IS_A_DIRECTORY=$?
# Make sure that we include symlinks, otherwise a test for the version
# 'current' would always fail
test -L "$USM_PATH/$_SOFTWARE/$_VERSION"
_IS_A_LINK=$?
if [ $_IS_A_DIRECTORY -ne 0 -a $_IS_A_LINK -ne 0 ]; then
echo "$_VERSION of $_SOFTWARE does not exist"
exit 1
fi
}
# Initializes the USM repository, by creating the root and running
# usm_copy_script
usm_init() {
echo "Creating $USM_PATH"
mkdir "$USM_PATH"
usm_copy_script
}
# Copies the startup script ($STARTUP_SCRIPT) into $HOME/.usm-env
usm_copy_script() {
echo "Writing startup script to $HOME/.usm-env"
echo "$STARTUP_SCRIPT" > "$HOME/.usm-env"
}
# Adds a directory for a new version of a software
usm_add() {
_SOFTWARE="$1"
_VERSION="$2"
if [ "$_VERSION" = "current" ]; then
echo "Cannot used the reserved name 'current' as a version"
exit 1
fi
echo "Installing $_SOFTWARE $_VERSION"
# Make the base directory if this is the first version
if [ ! -d "$USM_PATH/$_SOFTWARE" ]; then
_IS_NEW=1
mkdir "$USM_PATH/$_SOFTWARE"
else
_IS_NEW=0
fi
# Make the directory for the version
mkdir "$USM_PATH/$_SOFTWARE/$_VERSION"
# If this is the first version, then update the current link to this
# version so the user isn't left without a 'current'
if [ $_IS_NEW -ne 0 ]; then
usm_set_current "$_SOFTWARE" "$_VERSION"
fi
}
# Sets the current version by updating a symbolic link
usm_set_current() {
assert_software_exists "$1" "$2"
_SOFTWARE="$1"
_VERSION="$2"
if [ "$_VERSION" = "current" ]; then
echo "Cannot used the reserved name 'current' as a version"
exit 1
fi
echo "Making $_VERSION the current for $_SOFTWARE"
_CURRENT_SYMLINK="$USM_PATH/$_SOFTWARE/current"
rm -f "$_CURRENT_SYMLINK"
ln -s "$USM_PATH/$_SOFTWARE/$_VERSION" "$_CURRENT_SYMLINK"
}
# Lists the versions of a single software
list_software() {
# This is a little weird, but it is the most reliable way to ensure
# that a given software exists in general, since all of them have a
# 'current' version
assert_software_exists "$1" "current"
_SOFTWARE="$1"
echo "$_SOFTWARE"
_CURRENT_VERSION="$(readlink "$USM_PATH/$_SOFTWARE/current")"
for _VERSION in "$USM_PATH/$_SOFTWARE/"*; do
if [ "$_VERSION" != "$USM_PATH/$_SOFTWARE/current" ]; then
if [ "$_CURRENT_VERSION" = "$_VERSION" ]; then
echo "* $(basename "$_VERSION")"
else
echo "- $(basename "$_VERSION")"
fi
fi
done
}
# Lists the versions of all software given
usm_ls() {
if [ $# -eq 0 ]; then
# The goal here is to get a list of all the software contained inside
# $USM_PATH, in order. Since the shell should sort it for us, the only
# odd thing is the 'set -- ...' line, which is necessary to 'append' to
# the list of arguments
for _SOFTWARE in "$USM_PATH/"*; do
set -- "$@" "$_SOFTWARE"
done
fi
while [ $# -gt 0 ]; do
list_software "$(basename "$1")"
shift
done
}
# Prints out the absolute path to a particular software-version combo
usm_path() {
_SOFTWARE="$1"
_VERSION="$2"
echo "$USM_PATH/$_SOFTWARE/$_VERSION"
}
# Removes a version of a particular software, removing the software itself
# if this is the last version
usm_rm() {
assert_software_exists "$1" "$2"
_SOFTWARE="$1"
_VERSION="$2"
_CURRENT_VERSION="$(readlink "$USM_PATH/$_SOFTWARE/current")"
# If there is only one version left, then just remove the whole
# software directory - this actually counts all versions, excluding the
# 'current' symlink
_NUM_VERSIONS=0
for _ITER_VERSION in "$USM_PATH/$_SOFTWARE/"*; do
if [ "$_ITER_VERSION" != "$USM_PATH/$_SOFTWARE/current" ]; then
_NUM_VERSIONS=$((_NUM_VERSIONS + 1))
fi
done
if [ $_NUM_VERSIONS -eq 1 ]; then
echo "Only one version of $_SOFTWARE - deleting $_SOFTWARE"
rm -rf "$USM_PATH/$_SOFTWARE"
else
# Ensure that we're not deleting the current version, since that
# would leave the user's shell in a bad state (since they would have
# a dangling symlink)
if [ "$_CURRENT_VERSION" = "$USM_PATH/$_SOFTWARE/$_VERSION" ]; then
echo "$_VERSION is the current version - please select another"
echo "current version using 'usm set-current $_SOFTWARE VERSION'."
exit 1
fi
echo "Removing $_SOFTWARE $_VERSION"
rm -rf "$USM_PATH/$_SOFTWARE/$_VERSION"
fi
}
if [ $# -eq 0 ]; then
echo "$USAGE"
exit 1
fi
COMMAND=$1
# Push all the other arguments forward so we don't have to deal with
# the command later.
shift
case "$COMMAND" in
help)
echo "$HELP"
exit 1;;
init)
if [ $# -ne 0 ]; then
echo "'usm init' takes 0 arguments, got $#"
exit 1
fi
usm_init
;;
copy-script)
if [ $# -ne 0 ]; then
echo "'usm copy-script' takes 0 arguments, got $#"
exit 1
fi
usm_copy_script ;;
add)
if [ $# -ne 2 ]; then
echo "'usm add SOFTWARE VERSION' takes 2 arguments, got $#"
exit 1
fi
usm_add "$@" ;;
set-current)
if [ $# -ne 2 ]; then
echo "'usm set-current SOFTWARE VERSION' takes 2 arguments, got $#"
exit 1
fi
usm_set_current "$@" ;;
ls)
usm_ls "$@" ;;
path)
if [ $# -ne 2 ]; then
echo "'usm path SOFTWARE VERSION' takes 2 arguments, got $#"
exit 1
fi
usm_path "$@" ;;
rm)
if [ $# -ne 2 ]; then
echo "'usm rm SOFTWARE VERSION' takes 2 arguments, got $#"
exit 1
fi
usm_rm "$@" ;;
*)
echo "$USAGE"
exit 1 ;;
esac
### The following embeds the literal content of the .usm-env script here,
### which is accessible via a bit of POSIX sed magic.
exit 0
BEGIN ENV SCRIPT
#!/bin/sh
# This is the USM initialization file - source it from your shell RC file
# to load USM in your shell automatically, or source it from a script
# which needs USM to run.
USM_PATH="%USM_PATH%"
export USM_PATH
# Updates a : separated variable, if a specific entry is not already
# present
update_if_not_in_var() {
varname=$1
value=$2
varvalue="`eval echo '$'"$varname"`"
varupdate="$varname=\"$varvalue:$value\""
echo "$varvalue" | grep -s -q "$value" || eval "$varupdate"
}
for f in "$USM_PATH"/*; do
update_if_not_in_var PATH "$f/current/bin"
update_if_not_in_var PKG_CONFIG_PATH "$f/current/lib/pkgconfig"
update_if_not_in_var MANPATH "$f/current/man"
update_if_not_in_var MANPATH "$f/current/share/man"
done
export PATH
export PKG_CONFIG_PATH
export MANPATH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment