#!/usr/bin/env bash # Installs Debian packages on a Debian system # with no root access, in the user home # (sourceable) if [ ! -f /etc/apt/sources.list ]; then # Not a Debian system return 0 fi ARCH=$(dpkg --print-architecture) DEBLOC_DB=$HOME/.config/debloc/$ARCH DEBLOC_ROOT=$HOME/.debloc/$ARCH DEBLOC_LD=$DEBLOC_ROOT/ld if [ -z $DEBIAN_MIRROR ]; then DEBIAN_MIRROR="$(cat /etc/apt/sources.list | grep '^deb ' | grep main | grep -v backports)" DEBIAN_MIRROR="$(echo -e "$DEBIAN_MIRROR" | cut -d ' ' -f 2 | sed 's/\/$//' | sort | uniq)" fi mkdir -p $DEBLOC_DB &> /dev/null mkdir -p $DEBLOC_ROOT &> /dev/null function _debloc-setVars { export PATH="$1/usr/bin:$1/usr/games/:$1/usr/lib/git-core:$PATH" export LIBRARY_PATH="$2:$LIBRARY_PATH" export C_INCLUDE_PATH="$1/usr/include:$C_INCLUDE_PATH" export CPLUS_INCLUDE_PATH="$1/usr/include:$CPLUS_INCLUDE_PATH" export LD_LIBRARY_PATH="$2:$LD_LIBRARY_PATH" export PYTHONPATH="$1/usr/lib/python3/dist-packages:$PYTHONPATH" export QT_QPA_PLATFORM_PLUGIN_PATH="$1/usr/lib/x86_64-linux-gnu/qt5/plugins/platforms" } _debloc-setVars "$DEBLOC_ROOT" "$DEBLOC_LD" # Tell if a package exists function _debloc-exists { # package if [[ -n $DEBIAN_DB && -f $DEBIAN_DB ]]; then grep "^Package: $1\$" $DEBIAN_DB --quiet else LANG=C apt-cache show $1 &> /dev/null fi if [ $? == 0 ]; then return 1 else return 0 fi } # Return the real package associated with a virtual package # If not a virtual package, return the input function _debloc-filterVirtual { # package pkg=$1 if [[ -n $DEBIAN_DB && -f $DEBIAN_DB ]]; then echo $pkg else LANG=C apt-cache policy $1 | grep "Candidate" | grep "(none)" > /dev/null if [ $? == 0 ]; then # TODO This is not really accurate LANG=C apt-cache showpkg $pkg | tail -1 | cut -d ' ' -f 1 else echo $pkg fi fi return 0 } # Tell if a package is installed via debloc function _debloc-locallyInstalled { # package if [ -f $DEBLOC_DB/$1 ]; then return 1 else return 0 fi } # Tell if a package is installed system-wide function _debloc-globallyInstalled { # package STATUS=$(mktemp) LANG=C dpkg --list $1 &> $STATUS if [ $? != 0 ]; then rm -f $STATUS > /dev/null return 0 fi cat $STATUS | grep '^Status:' | grep ' installed' --quiet if [ $? != 0 ]; then rm -f $STATUS > /dev/null return 0 else rm -f $STATUS > /dev/null return 1 fi } # Get informations about a package function _debloc-packageShow { # package pkg=$1 if [[ -n $DEBIAN_DB && -f $DEBIAN_DB ]]; then startline=$(grep "^Package: ${pkg}\$" $DEBIAN_DB --line-number | tail -1 | cut -d ':' -f 1) if [ -z "$startline" ]; then return 0 fi sed -n "$startline,$(expr $startline + 100)p" $DEBIAN_DB | while read line; do if [ -z "$line" ]; then return 0 fi echo $line done return 1 else LANG=C apt-cache show $pkg | while read line; do if [ -z "$line" ]; then return 0 fi echo "$line" done return 0 fi } # Get the path of a package function _debloc-packagePath { # package _debloc-packageShow $1 | grep "^Filename:" | head -1 | cut -d ':' -f 2 | sed -e 's/^[[:space:]]*//' return 0 } # Get the md5sum of a package function _debloc-packageMd5sum { # package _debloc-packageShow $1 | grep "^MD5sum:" | cut -d ':' -f 2 | sed -e 's/^[[:space:]]*//' return 0 } # Update symbolics links in $DEBLOC_ROOT/lib function _debloc-ldconfig { mkdir -p $DEBLOC_LD &> /dev/null rm -f $DEBLOC_LD &> /dev/null find $DEBLOC_ROOT{/usr,}/lib -type f -name "*.so*" | while read lib; do ln --symbolic --force "$lib" "$DEBLOC_LD/$(basename $lib)" done &> /dev/null find $DEBLOC_ROOT{/usr,}/lib -type l -name "*.so*" | while read link; do yes | cp --force --no-dereference --preserve=links "$link" "$DEBLOC_LD" &> /dev/null done &> /dev/null } # Install debian archive function _debloc-installDeb { # path TMP_DIR=$(mktemp -d) &> /dev/null $(cd $TMP_DIR; ar x "$1") TAR_FILE=$(find $TMP_DIR -type f -name "data.tar.*" | head -1) if [ -e "$TAR_FILE" ]; then # Output for DB saving tar tf $TAR_FILE tar xf $TAR_FILE -C $DEBLOC_ROOT # _debloc-ldconfig mkdir -p $DEBLOC_LD &> /dev/null tar tf $TAR_FILE | grep '^.\(/usr\)\?/lib/' | grep '\.so' | while read file; do lib=$(readlink -f $DEBLOC_ROOT/$file) if [ -f $lib ]; then ln --symbolic --force "$lib" "$DEBLOC_LD/$(basename $file)" fi if [ -h $lib ]; then yes | cp --force --no-dereference --preserve=links "$(basename $link)" "$DEBLOC_LD/" &> /dev/null fi done fi rm -rf $TMP_DIR &> /dev/null return 0 } # Install package function _debloc-install { # package pkg=$1 DEB_FILE=$(mktemp) &> /dev/null path=$(_debloc-packagePath $pkg) echo -e "${DEBIAN_MIRROR}" | while read mirror; do if [ -z $mirror ]; then continue fi url=${mirror}/${path} echo "→ Downloading $url" wget "$url" --quiet -O $DEB_FILE if [ $? == 0 ]; then break fi done if [ ! -s $DEB_FILE ]; then echo "→ Failed (no deb file)!" rm $DEBLOC_DB/$pkg &> /dev/null return 4 fi echo "→ Verifying sums" theo=$(_debloc-packageMd5sum $pkg) real=$(md5sum $DEB_FILE | cut -d ' ' -f 1) if [ "$theo" != "$real" ]; then rm -f $DEB_FILE &> /dev/null echo "→ Failed (sum doesn't match)!" rm $DEBLOC_DB/$pkg &> /dev/null return 5 fi echo "→ Installing" _debloc-installDeb $DEB_FILE > $DEBLOC_DB/$pkg echo "→ Done!" rm -f $DEB_FILE &> /dev/null return 0 } # Get the dependencies of a package function _debloc-packageDeps { # package _debloc-packageShow $1 | grep '^Depends:' | sed 's/Depends: //' | sed 's/, /\n/g' | cut -d ' ' -f 1 return 0 } # Install package with dependencies function _debloc-installDeps { # package pkg=$1 echo "Installing $pkg" touch $DEBLOC_DB/$pkg # To prevent cyclic deps _debloc-packageDeps $pkg | while read dep; do dep=$(_debloc-filterVirtual $dep) _debloc-locallyInstalled $dep if [ $? == 1 ]; then echo "- Dependency $dep is already installed with Debloc" continue fi _debloc-globallyInstalled $dep if [ $? == 1 ]; then echo "- Dependency $dep is already installed on the system" continue fi _debloc-installDeps $dep | while read line; do echo "- $line"; done done _debloc-install $pkg return 0 } # Install package with dependencies (user version with verifications) function debloc-install { # package for pkg in $*; do pkg=$(_debloc-filterVirtual $pkg) _debloc-exists $pkg if [ $? == 0 ]; then echo "Unknown package $pkg" continue fi _debloc-locallyInstalled $pkg if [ $? == 1 ]; then echo "Package $pkg is already installed with Debloc" continue fi _debloc-globallyInstalled $pkg if [ $? == 1 ]; then echo "Package $pkg is already installed on the system" continue fi _debloc-installDeps $pkg done return 0 } # Install debian archive (user version with verifications) function debloc-deb { # path for path in $*; do if [ ! -f "$path" ]; then echo "$path is not a file" return 6 fi echo "Installing $(basename $path)" _debloc-installDeb "$(readlink -f $path)" > $DEBLOC_DB/$(basename $path) done return 0 } # Remove every package installed with Debloc function debloc-flush { rm -rf $DEBLOC_ROOT/* &> /dev/null rm -f $DEBLOC_DB/* &> /dev/null }