-
-
Save tpoechtrager/75db965b025c5bf62b9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
## | |
## TODO: | |
## * Locking | |
## * --help | |
## * upgrade | |
## * clear-cache | |
## | |
set -e | |
export LC_ALL=C | |
pushd "${0%/*}" &>/dev/null | |
MIRROR="$OSXCROSS_MACPORTS_MIRROR" | |
if [ -z "$MIRROR" ]; then | |
MIRROR="http://packages.macports.org" | |
fi | |
PUBKEYURL="https://svn.macports.org/repository/" | |
PUBKEYURL+="macports/trunk/base/macports-pubkey.pem" | |
PUBKEYSHA256="7f429799b3609b95ef1eb024182c973d" | |
PUBKEYSHA256+="35a4e1ef326abea4a0599cfb9ff70c77" | |
if [ -n "$OSXCROSS_MACPORTS_ENABLE_HTTPS" ]; then | |
MIRROR=$(echo $MIRROR | sed 's/http:/https:/g') | |
fi | |
if [ -z "$MACOSX_DEPLOYMENT_TARGET" ]; then | |
export MACOSX_DEPLOYMENT_TARGET=10.7 | |
fi | |
ROOT="$PWD" | |
PUBKEY="$ROOT/mp-pubkey.pem" | |
INSTALLDB="$ROOT/INSTALLED" | |
CACHE="$ROOT/cache" | |
INSTALL="$ROOT/target" | |
LASTPKGNAME="" | |
if [ ! -d "$CACHE" ]; then | |
echo "creating cache directory: $CACHE" | |
mkdir -p $CACHE | |
fi | |
if [ ! -d "$INSTALL" ]; then | |
echo "creating install directory: $INSTALL" | |
mkdir -p $INSTALL | |
fi | |
errorMsg() | |
{ | |
echo "$@" 1>&2 | |
} | |
verboseMsg() | |
{ | |
if [ -n "$VERBOSE" ]; then | |
errorMsg "$@" | |
fi | |
} | |
verbosePlaceHolder() | |
{ | |
if [ -n "$VERBOSE" ]; then | |
errorMsg "" | |
fi | |
} | |
require() | |
{ | |
set +e | |
which $1 &>/dev/null | |
if [ $? -ne 0 ]; then | |
errorMsg "$1 is required" | |
exit 1 | |
fi | |
set -e | |
} | |
require "wget" | |
require "openssl" | |
require "sw_vers" | |
unsupportedDepTarget() | |
{ | |
errorMsg "unsupported deployment target" | |
errorMsg -n "add 'export MACOSX_DEPLOYMENT_TARGET=10.6' (or later) " | |
errorMsg "to your bashrc." | |
exit 1 | |
} | |
case $(sw_vers -productVersion) in | |
10.6 ) OSXVERSION="darwin_10" ;; | |
10.7 ) OSXVERSION="darwin_11" ;; | |
10.8 ) OSXVERSION="darwin_12" ;; | |
10.9 ) OSXVERSION="darwin_13" ;; | |
10.10 ) OSXVERSION="darwin_14" ;; | |
* ) unsupportedDepTarget ;; | |
esac | |
getFileStdout() | |
{ | |
verbosePlaceHolder | |
local xargs="" | |
[ -z "$VERBOSE" ] && xargs+="--quiet" | |
wget "$1" -O- $xargs | |
#verbosePlaceHolder | |
} | |
getFile() | |
{ | |
verbosePlaceHolder | |
local xargs="" | |
if [ $# -ge 2 ]; then | |
xargs+="-O $2 " | |
else | |
xargs+="-P $CACHE " | |
fi | |
[ -z "$VERBOSE" ] && xargs+="--quiet" | |
wget -c "$1" $xargs | |
#verbosePlaceHolder | |
} | |
verifyFileIntegrity() | |
{ | |
local file="$1" | |
if [ ! -e "$PUBKEY" ]; then | |
echo "downloading macports public key ..." | |
getFile $PUBKEYURL "$PUBKEY" | |
fi | |
local hash=$(openssl sha256 "$PUBKEY" | awk '{print $2}') | |
if [ "$hash" != "$PUBKEYSHA256" ]; then | |
errorMsg "invalid macports public key! ($hash != $PUBKEYSHA256)" | |
exit 1 | |
fi | |
verboseMsg "verifying file integrity ..." | |
set +e | |
openssl dgst -ripemd160 -verify "$PUBKEY" -signature \ | |
"$CACHE/$file.rmd160" "$CACHE/$file" 1>/dev/null | |
if [ $? -ne 0 ]; then | |
errorMsg "file integrity check failed ($CACHE/$file)" | |
exit 2 | |
fi | |
set -e | |
} | |
getPkgUrl() | |
{ | |
local pkgname="$1" | |
local pkgs | |
local pkg | |
set +e | |
pkgs=$(getFileStdout "$MIRROR/$pkgname" | grep -o -E 'href="([^"#]+)"' | \ | |
cut -d'"' -f2 | grep '.tbz2$') | |
local ec=$? | |
set -e | |
if [ $ec -ne 0 ]; then | |
errorMsg "no packages found" | |
return | |
fi | |
verboseMsg " candidates for $pkgname:" | |
for p in $pkgs; do | |
verboseMsg " $p" | |
done | |
local pkg=$(echo "$pkgs" | grep $OSXVERSION | sort | uniq | tail -n1) | |
verboseMsg " selected: $pkg" | |
if [ -z "$pkg" ]; then | |
verboseMsg -n " " | |
errorMsg "no suitable version found for $OSXVERSION" | |
return | |
fi | |
echo "$MIRROR/$pkgname/$pkg" | |
} | |
pkgInstalled() | |
{ | |
local pkgname="$1" | |
if [ ! -e "$INSTALLDB" ]; then | |
echo 0 | |
return | |
fi | |
set +e | |
grep -x "$pkgname" "$INSTALLDB" &>/dev/null | |
local status=$? | |
set -e | |
if [ $status -eq 0 ]; then | |
echo 1 | |
else | |
echo 0 | |
fi | |
} | |
installPkg() | |
{ | |
local pkgname="$1" | |
LASTPKGNAME=$pkgname | |
if [ $(pkgInstalled $pkgname) -eq 1 ]; then | |
continue | |
fi | |
echo "searching for package $pkgname ..." | |
local pkgurl=$(getPkgUrl "$pkgname") | |
local pkgfile=$(echo "$pkgurl" | awk -F'/' '{print $NF}') | |
if [ -z "$pkgurl" ]; then | |
local oldpkgname=$pkgname | |
pkgname=$(echo "$pkgname" | cut -f1 -d'-') | |
if [ "$pkgname" != "$oldpkgname" ]; then | |
echo "trying $pkgname instead ..." | |
else | |
exit 3 | |
fi | |
installPkg $pkgname | |
return | |
fi | |
echo "downloading $pkgfile ..." | |
getFile "$pkgurl" | |
verboseMsg "downloading $pkgname.rmd160 ..." | |
getFile "$pkgurl.rmd160" | |
verifyFileIntegrity "$pkgfile" | |
pushd $INSTALL &>/dev/null | |
echo "installing $pkgname ..." | |
verboseMsg " extracting $pkgfile ..." | |
tar xf "$CACHE/$pkgfile" | |
if [ -d opt/local ]; then | |
verboseMsg " fixing permissions ..." | |
find opt/local -type d -exec chmod 770 {} \; | |
find opt/local -type f -exec chmod 660 {} \; | |
if [ -d opt/local/lib ]; then | |
if [ -n "$STATIC" ]; then | |
[ -n "$VERBOSE" ] && echo -n " " | |
echo "removing dylibs ..." | |
find opt/local/lib -name "*.dylib" -exec rm {} \; | |
else | |
find opt/local/lib -type f -name "*.dylib" -exec chmod +x {} \; | |
fi | |
fi | |
verboseMsg " fixing directories ..." | |
set +e | |
cp -r opt/local/* $INSTALL | |
local status=$? | |
set -e | |
if [ $status -eq 1 ]; then | |
errorMsg "removing broken symlinks ..." | |
find . -type l -exec \ | |
sh -c 'readlink -f "{}" 1>/dev/null || rm "{}"' -- "{}" \; | |
cp -r opt/local/* $INSTALL | |
fi | |
rm -rf opt | |
fi | |
local pkgdeps=$(grep '@pkgdep' \+CONTENTS | cut -d\ -f2 | \ | |
rev | cut -f2-100 -d\- | rev) | |
popd &>/dev/null # INSTALL | |
for pkgdep in $pkgdeps; do | |
installPkg $pkgdep | |
done | |
test -e "$INSTALLDB" && cp "$INSTALLDB" "$INSTALLDB.old" | |
echo "$pkgname" >> "$INSTALLDB" | |
} | |
installPkgs() | |
{ | |
local packages="$1" | |
for pkgname in $packages; do | |
if [ $(pkgInstalled $pkgname) == "1" ]; then | |
errorMsg "$pkgname is already installed" | |
continue | |
fi | |
installPkg $pkgname | |
rm -f $INSTALL/+* | |
done | |
} | |
updateSearchCache() | |
{ | |
pushd $CACHE &>/dev/null | |
echo "generating index cache (this may take several minutes ...)" | |
getFile $MIRROR $CACHE/packages | |
cat packages | grep -o -E 'href="([^"#]+)"' | cut -d'"' -f2 | \ | |
sed 's/.\{1\}$//' | uniq | sort > INDEXCACHE | |
rm -f packages | |
echo "generated index cache for $(cat INDEXCACHE | wc -l) packages" | |
popd &>/dev/null | |
} | |
searchPkg() | |
{ | |
local pkg="$1" | |
pushd $CACHE &>/dev/null | |
if [ ! -e INDEXCACHE ]; then | |
updateSearchCache | |
fi | |
local packages=$(grep -i "$pkg" INDEXCACHE) | |
if [ -z "$packages" ]; then | |
echo "no matching packages found for $1" | |
return | |
fi | |
for pkg in $packages; do | |
echo $pkg | |
done | |
popd &>/dev/null | |
} | |
_exit() | |
{ | |
local ec=$? | |
if [ $ec -ne 0 ]; then | |
if [ -n "$LASTPKGNAME" ]; then | |
errorMsg "failed to install $LASTPKGNAME, try with '-v'" | |
fi | |
if [ $ec -eq 3 ]; then | |
errorMsg -n "use '$0 fake-install <pkgname>' to " | |
errorMsg "fake install non-existing packages" | |
fi | |
fi | |
} | |
showHelpText() | |
{ | |
errorMsg "TODO" | |
exit 1 | |
} | |
main() | |
{ | |
local args | |
local cmd | |
for opt in $@; do | |
if [[ $opt == -* ]]; then | |
if [ $opt == "-v" -o $opt == "--verbose" ]; then | |
VERBOSE=1 | |
elif [ $opt == "-v=2" -o $opt == "--verbose=2" ]; then | |
set -x | |
VERBOSE=1 | |
elif [ $opt == "-s" -o $opt == "--static" ]; then | |
STATIC=1 | |
elif [ $opt == "-h" -o $opt == "--help" ]; then | |
showHelpText | |
else | |
errorMsg "unknown option: $opt" | |
exit 1 | |
fi | |
else | |
if [ -z "$cmd" ]; then | |
cmd="$opt" | |
else | |
args+="$opt " | |
fi | |
fi | |
done | |
if [ -z "$cmd" ]; then | |
errorMsg "no command given" | |
showHelpText | |
fi | |
case "$cmd" in | |
updatecache ) | |
updateSearchCache | |
exit | |
;; | |
upgrade ) | |
echo "TODO" | |
exit | |
;; | |
esac | |
local packages="$args" | |
if [ -z "$packages" ]; then | |
errorMsg "no package name given" | |
exit 1 | |
fi | |
case "$cmd" in | |
install ) | |
installPkgs "$packages" | |
;; | |
fake*install ) | |
for pkgname in $args; do | |
if [ $(pkgInstalled $pkgname) -eq 0 ]; then | |
echo $pkgname >> $INSTALLDB | |
fi | |
done | |
echo "done" | |
;; | |
search ) | |
for pkgname in $args; do | |
searchPkg $pkgname | |
done | |
;; | |
esac | |
} | |
trap _exit EXIT | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment