#!/bin/bash # Install tool for Cygwin similar to Debian apt-get # # Copyright (C) 2005-9, Stephen Jungels # Copyright (C) 2013-2015 Daniel Boland # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # (http://www.fsf.org/licensing/licenses/gpl.html) # this script requires some packages WGET=`which wget 2>/dev/null` TAR=`which tar 2>/dev/null` GAWK=`which awk 2>/dev/null` GREP=`which grep 2>/dev/null` if ! [[ "$WGET" && "$TAR" && "$GAWK" && "$GREP" ]]; then echo You must install wget, tar, gawk and grep to use apt-get. exit 1 fi CONF=/etc/apt MIRRORLIST=$CONF/sources.list OSPATH=`uname -a | $GAWK '{printf $6}'` DEFMIRROR="http://ftp.snt.utwente.nl/pub/software/cygwin" MIRROR="" COMMAND="" STATUS="" if [ $OSPATH == i686 ]; then OSPATH="x86" fi function syntax { echo "apt-get is a simple command line interface for downloading and" echo "installing Cygwin packages. The most frequently used commands are" echo "update and install." echo echo "Usage: apt-get command [options]" echo echo "Commands:" printf -- " update\t\t\t\tRetrieve new list of packages\n" printf -- " upgrade PACKAGE\t\tPerform an upgrade on PACKAGE\n" printf -- " install PACKAGE\t\tInstall new packages\n" printf -- " remove PACKAGE\t\t\tRemove packages\n" printf -- " source PACKAGE\t\t\tDownload source archives to /usr/src\n" printf -- " show PACKAGE\t\t\tShow a readable record for the package\n" printf -- " search PATTERN\t\t\tFind packages matching PATTERN\n" printf -- " packageof COMMAND\t\tLocate parent packages of COMMAND\n" printf -- " list\t\t\t\tList installed packages\n" echo echo "Options:" printf -- " -m, --mirror URL\t\tUse mirror\n" printf -- " -h, --help\t\t\tThis help text\n" printf -- " -f, --force\t\t\tForce MD5/SHA512 checksum match\n" printf -- " -v, --version\t\t\tPrint version and exit\n" printf -- " -M, --add-mirror URL\t\tPermanently add mirror to $MIRRORLIST\n" printf -- " -V, --verbose\t\t\tBe verbose\n" } function version { cat <&1` if [ $? -ne 0 ]; then echo "$out" | tail -2 exit 1 fi touch setup.ini mv setup.ini setup.ini.save echo -n " updating package list... " if $WGET -N -q $MIRROR/$OSPATH/setup.bz2; then bunzip2 setup.bz2 mv setup setup.ini echo done. elif $WGET -N -q $MIRROR/$OSPATH/setup.ini; then echo done. else echo echo " error: could not update setup.ini: reverting" mv setup.ini.save setup.ini exit 1 fi } function find_workspace { dir=`echo "$1" | sed 's/:/%3a/g; s:/:%2f:g'` mkdir -p "/setup/$dir" cd "/setup/$dir" MIRROR="$1" if ! [ -f "setup.ini" ]; then update_setup elif ! [ -s "setup.ini" ]; then echo "Package list corrupted. Trying update." update_setup else return 1 fi } function find_mirror { for url in `cat $MIRRORLIST 2>/dev/null`; do find_workspace "$url" if [[ `$GREP "^@ $1$" setup.ini` ]]; then echo "Found package '$1' on $url" return fi done echo "Mirror is $DEFMIRROR" find_workspace "$DEFMIRROR" } function add_mirror { out=`$WGET --spider "$1" 2>&1` if [ $? -ne 0 ]; then echo "$out" | tail -2 exit 1 elif [ "$1" == "$DEFMIRROR" ]; then return elif ! [[ `$GREP "$1" $MIRRORLIST 2>/dev/null` ]]; then mkdir -p $CONF echo "$1" >>$MIRRORLIST fi } function update_mirrors { for url in `cat $MIRRORLIST 2>/dev/null` $DEFMIRROR; do echo "Mirror $url" find_workspace "$url" || update_setup done } function install_package { local pkg="$1" local need_rebase=$2 # pick the latest version, which comes first install=`$GAWK '/^install:/ {printf $2; exit}' "$pkg.hint"` if ! [ "$install" ]; then echo " warning: could not find \"install\" in package description: obsolete package?" return fi echo "Installing $pkg:" echo -n " downloading... " local file=`basename $install` local path=`dirname $install` mkdir -p "$path" if ! $WGET -q "$MIRROR/$install" -O "$install"; then echo "error" echo "$MIRROR/$install: download failed: try updating" cancelled="yes" return fi echo done. # check md5 sum digest=`$GAWK '/^install: / {print $4; exit}' "$pkg.hint"` if [ ${#digest} -eq 32 ]; then digactual=`md5sum "$install" | $GAWK '{print $1}'` else digactual=`sha512sum "$install" | $GAWK '{print $1}'` fi if [ $digest != $digactual ]; then if [ $force ]; then echo " warning: MD5/SHA512 checksum did not match: continuing." else echo " error: MD5/SHA512 checksum did not match: try updating." cancelled="yes" return fi fi echo -n " unpacking... " $TAR -xvf "$install" -C / --no-overwrite-dir >/etc/setup/$pkg.lst echo done. if [ $need_rebase ]; then echo -n " rebasing... " for dll in `$GREP "\.dll$" /etc/setup/$pkg.lst`; do rebase -s "/$dll" 2>/dev/null done echo done. fi gzip -f "/etc/setup/$pkg.lst" # update the package database echo "$pkg $file 0" >>/etc/setup/installed.db # save hint file $GAWK '$1 ~ /^version:/ {exit}; $1 != "@" {print}' "$pkg.hint" >"$path/setup.hint" } function remove_package { local pkg="$1" # if [[ `echo "cygwin coreutils gawk tar wget bash libgcc1 libgmp10 liblzma5" | grep "\b$pkg\b"` ]]; then if [[ $pkg =~ cygwin|coreutils|gawk|tar|wget|bash|libgcc|libgmp|liblzma ]]; then echo "Error: cannot remove '$pkg': package is part of the system." cancelled="yes" return elif ! [[ `$GREP "^$pkg " /etc/setup/installed.db` ]]; then echo "Package '$pkg' is not installed: skipping removal." return elif ! [ -f "/etc/setup/$pkg.lst.gz" ]; then echo "Error: package manifest missing: cannot remove '$pkg'." return fi echo -n "Removing $pkg... " # run preremove scripts if [ -f "/etc/preremove/$pkg.sh" ]; then /etc/preremove/$pkg.sh rm "/etc/preremove/$pkg.sh" fi # remove installed files gunzip -c /etc/setup/$pkg.lst.gz | $GAWK '{print "/" $0}' | xargs rm -f 2>/dev/null rm "/etc/setup/$pkg.lst.gz" rm -f /etc/postinstall/$pkg.sh.done # remove entry from package database cp /etc/setup/installed.db /etc/setup/installed.db.save $GAWK -v PKG="$pkg" '$1 != PKG {print}' /etc/setup/installed.db.save >/etc/setup/installed.db echo done. } function crawl_package { local depth=$1 local package="$2" [ $verbose ] && printf " [$depth:in:$package]" if [[ `$GREP "^$package " /etc/setup/installed.db` ]]; then [ $depth -eq 0 ] && echo "Package $package is already installed." [ $verbose ] && echo " [$depth:out:$package]" return fi [ $verbose ] && echo " [parsing:$package.hint]" $GAWK -v PKG="$package" '/^@/ {P=$2}; P==PKG {print}' setup.ini >$package.hint if ! [ -s "$package.hint" ]; then rm -f $package.hint echo " error: package '$package' not found or ambiguous name: try updating." cancelled="yes" return fi requires=`$GAWK -F: '/^requires:/ {print $2}' "$package.hint"` if [ $depth -eq 0 ]; then echo Package $package requires the following packages: $requires echo " reading packages..." fi local pkg local need_rebase="" for pkg in $requires do if [ $pkg == _autorebase ]; then need_rebase="yes" elif [ -f "$pkg.hint" ]; then echo "Warning: circular reference to '$pkg' in package $package, skipping." elif [ $cancelled ]; then break else crawl_package $(($depth+1)) "$pkg" fi done [ $cancelled ] || [ $verbose ] || install_package "$package" $need_rebase rm -f $package.hint [ $verbose ] && echo " [$depth:out:$package]" } # process options packages="" verbose="" mirror="" function set_mirror { out=`$WGET --spider "$1" 2>&1` if [ $? -ne 0 ]; then echo "$out" | tail -2 exit 1 fi echo "Mirror is $1" find_workspace "$1" mirror="$1" } function set_package { if [ "$packages" ]; then packages="$packages $1" else packages="$1" fi } while [ "$1" ]; do case "$1" in --mirror|-m) set_mirror "$2" shift ;; --help|-h) syntax exit 0 ;; --version|-v) version exit 0 ;; --verbose|-V) verbose="yes" ;; --force|-f) force="yes" ;; --add-mirror|-M) add_mirror "$2" shift ;; -*) echo "$1: No such option." syntax exit 1 ;; update|show|search|describe|packageof|install|remove|upgrade|source|list|test) COMMAND=$1 ;; *) set_package "$1" ;; esac shift done function do_update { if [ "$mirror" ]; then update_setup else update_mirrors fi } function do_packageof { for pkg in $packages do key=`which "$pkg" 2>/dev/null | sed -r 's/^\///'` [ "$key" ] || key="$pkg" for manifest in /etc/setup/*.lst.gz do out=`gunzip -c $manifest | $GREP "$key" | awk '{print " " $0}'` if [ "$out" ]; then package=`basename $manifest | sed -r 's/.lst.gz//'` echo "Found $key in package $package:" echo "$out" fi done done } function do_search { pat=`echo "$packages" | sed 's/ /\|/g;'` echo "Installed:" $GAWK -v QUERY="$pat" '$1 ~ QUERY {print " " $1}' /etc/setup/installed.db for url in `cat $MIRRORLIST 2>/dev/null` $DEFMIRROR; do echo "Mirror $url:" dir=`echo "$url" | sed 's/:/%3a/g; s:/:%2f:g'` $GREP -E "^@ " /setup/$dir/setup.ini | $GAWK -v QUERY="$pat" '$2 ~ QUERY {print " " $2}' done } function do_show { for pkg in $packages do [ "$mirror" ] || find_mirror "$pkg" echo $GAWK -v PKG="$pkg" '/^@/ {P=$2}; P==PKG {print}' setup.ini done } function do_postinstall { list=`ls -U /etc/postinstall/*.sh 2>/dev/null` if [ "$list" ]; then echo Running postinstall scripts: for script in $list do echo " $script..." $script mv $script $script.done done fi [ "$STATUS" ] && echo "$STATUS" rm -f /usr/bin/apt-cyg # legacy! [ -f $0.new ] && mv $0.new $0 # self-install } function do_install { for pkg in $packages do [ "$mirror" ] || find_mirror "$pkg" crawl_package 0 "$pkg" if [ $cancelled ]; then STATUS="Package '$pkg' could not be installed." break fi done do_postinstall } function do_remove { for pkg in $packages do remove_package "$pkg" done } function do_upgrade { [ "$mirror" ] && update_setup for pkg in $packages do [ "$mirror" ] || find_mirror "$pkg" hint=`$GAWK -v PKG="$pkg" '/^@/ {P=$2}; P==PKG {print}' setup.ini` file=`echo "$hint" | $GAWK '/^install:/ {printf $2; exit}'` if ! [ "$file" ]; then STATUS="Error: package '$pkg' not found or ambiguous name." break fi doc=`basename $file` version=`echo "$hint" | $GAWK '/^version: / {print $2; exit}'` if [[ `$GREP "\b$doc\b" /etc/setup/installed.db` ]]; then echo "Package $pkg $version: already at newest version." else remove_package "$pkg" crawl_package 0 "$pkg" if [ $cancelled ]; then STATUS="Package $pkg could not be upgraded." break else echo "Package $pkg upgraded to version $version." fi fi done do_postinstall } function do_source { for pkg in $packages do [ "$mirror" ] || find_mirror "$pkg" $GAWK -v PKG="$pkg" '/^@/ {P=$2}; P==PKG {print}' setup.ini >"$pkg.hint" if ! [ -s "$pkg.hint" ]; then echo "Package $pkg not found or ambiguous name." rm -f "$pkg.hint" exit 1 fi source=`$GAWK '/^source:/ {printf $2; exit}' "$pkg.hint"` if ! [ "$source" ]; then echo "Could not find \"source\" in package description: obsolete package?" exit 1 fi echo echo "Installing $pkg source" echo -n " downloading... " file=`basename $source` $WGET -q "$MIRROR/$source" -O "/usr/src/$file" echo done. echo " installed: /usr/src/$file" rm -f "$pkg.hint" done } function do_list { echo "The following packages are installed:" $GAWK '{print $1}' /etc/setup/installed.db | sort } function do_test { verbose="yes" for pkg in $packages do [ "$mirror" ] || find_mirror "$pkg" crawl_package 0 "$pkg" done } if ! [ $COMMAND ]; then syntax elif [[ $COMMAND =~ ^(update|list)$ ]]; then do_$COMMAND elif [ "$packages" ]; then do_$COMMAND else syntax fi