#!/bin/bash # apt-cyg: install tool for cygwin similar to debian apt-get # # Copyright (C) 2005-9, Stephen Jungels # # 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` BZIP2=`which bzip2 2>/dev/null` TAR=`which tar 2>/dev/null` GAWK=`which awk 2>/dev/null` if ! [[ "$WGET" && "$BZIP2" && "$TAR" && "$GAWK" ]]; then echo You must install wget, tar, gawk and bzip2 to use apt-cyg. exit 1 fi MIRROR="http://ftp.snt.utwente.nl/pub/software/cygwin" function syntax { echo "apt-cyg 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-cyg command [options]" echo echo "Commands:" printf -- " update\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\tRemove packages\n" printf -- " source PACKAGE\t\tDownload source archives to /usr/src\n" printf -- " show\t\t\t\tShow installed packages\n" printf -- " search PATTERN\t\tFind packages matching PATTERN\n" printf -- " describe PATTERN\t\tShow description of package\n" printf -- " packageof COMMAND\t\tLocate parent packages of COMMAND\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 -- " -V, --verbose\t\t\tBe verbose\n" # printf -- " -M, --default-mirror URL\t\t\tSet default mirror\n" } function version { echo "apt-cyg version 0.57" echo "Written by Stephen Jungels" echo "Copyright (c) 2005-9 Stephen Jungels. Released under the GPL." echo "Modified by Daniel Boland 2013/2014 (dboland@xs4all.nl)" echo echo "apt-cyg version 0.6" echo "* fix: bug in mirror location (x86 directory)" echo "* added support for .xz de-compression" echo "* improved recursive action" echo "* added upgrade command" echo "* added source command" echo "apt-cyg version 0.6.1" echo "* modified install sequence: dependencies are installed first." echo "* fix: install overrides folder permissions (/var/log)" echo "apt-cyg version 0.6.2" echo "* fix: hangs on circular references (cyrus-sasl)" echo "apt-cyg version 0.6.3" echo "* added rebasing" echo "apt-cyg version 0.6.4" echo "* added --force option" echo "* added 64bit support" echo "* added support for SHA512 checksum" } cancelled="" force="" function findworkspace { mirrordir="`echo "$MIRROR" | sed -e "s/:/%3a/g" -e "s:/:%2f:g"`" echo Mirror is $MIRROR mkdir -p "/setup/$mirrordir" cd "/setup/$mirrordir" } function update_setup { path=`uname -a | awk '{printf $6}'` if [ $path == i686 ]; then path="x86" fi touch setup.ini mv setup.ini setup.ini.save echo "Downloading package list..." wget -N -q $MIRROR/$path/setup.bz2 if [ $? -eq 0 ]; then bunzip2 setup.bz2 mv setup setup.ini echo Updated setup.ini else wget -N -q $MIRROR/$path/setup.ini if [ $? -eq 0 ]; then echo Updated setup.ini else echo Error updating setup.ini, reverting mv setup.ini.save setup.ini exit 1 fi fi } function install_package { local pkg="$1" local need_rebase=$2 local path="release/$pkg" echo if ! [ -s "$path/desc" ]; then echo "Error: Package $pkg not found or ambiguous name, try updating." rm -R "$path" cancelled="yes" return fi # pick the latest version, which comes first install=`awk '/^install:/ {printf $2; exit}' "$path/desc"` if ! [ "$install" ]; then echo "Warning: could not find \"install\" in package description: obsolete package?" return fi echo "-- Installing $pkg --" echo "Downloading..." file=`basename $install` wget -q "$MIRROR/$install" -O "$path/$file" if [ $? -ne 0 ]; then echo "Error: $MIRROR/$install: download failed." cancelled="yes" return fi # check the md5 digest=`awk '/^install: / {print $4; exit}' "$path/desc"` if [ ${#digest} -eq 32 ]; then digactual=`md5sum "$path/$file" | awk '{print $1}'` else digactual=`sha512sum "$path/$file" | awk '{print $1}'` fi if [ $digest != $digactual ]; then if [ $force ]; then echo "Warning: MD5/SHA512 sum did not match, continuing." else echo "Error: MD5/SHA512 sum did not match, try updating." cancelled="yes" return fi fi echo "Unpacking..." tar -xvf "$path/$file" -C / --no-overwrite-dir >/etc/setup/$pkg.lst if [ $need_rebase -eq 1 ]; then echo "Rebasing..." for dll in `grep "\.dll$" /etc/setup/$pkg.lst`; do rebase -s "/$dll" 2>/dev/null done fi gzip -f "/etc/setup/$pkg.lst" # update the package database echo "$pkg $file 0" >>/etc/setup/installed.db echo "Package $pkg installed." } function crawl_packages { local pkg local result=0 local depth=$1 shift for pkg in $1 do local path="release/$pkg" local need_rebase=0 [ $verbose ] && echo "[depth:$depth:$pkg]" if [ $cancelled ]; then return $result elif [ $pkg == _autorebase ]; then result=1 elif [[ `grep "^$pkg " /etc/setup/installed.db` ]]; then [ $depth -eq 0 ] && echo Package $pkg is already installed. elif [ -f "$path/desc" ]; then echo "Warning: circular reference to package $pkg, skipping." else mkdir -p "$path" awk -v PKG="$pkg" '/^@/ {P=$2}; P==PKG {print}' setup.ini >"$path/desc" requires=`awk -F: '/^requires:/ {print $2}' "$path/desc"` if [ "$requires" ]; then if [ $depth -eq 0 ]; then echo echo Package $pkg requires the following packages: echo $requires echo Reading packages... fi crawl_packages $(($depth+1)) "$requires" need_rebase=$? fi if ! [ $cancelled ]; then install_package "$pkg" $need_rebase fi rm -f "$path/desc" fi done return $result } # process options packages="" command="" verbose="" while [ "$1" ]; do case "$1" in --mirror|-m) MIRROR="$2" shift ;; --help|-h) syntax exit 0 ;; --version|-v) version exit 0 ;; --verbose|-V) verbose="yes" ;; --force|-f) force="yes" ;; -*) echo "$1: No such option." syntax exit 1 ;; update|show|search|describe|packageof|install|remove|upgrade|source) command=$1 ;; *) packages="$packages $1" ;; esac shift done function do_update { findworkspace update_setup } function do_packageof { for pkg in $packages do key=`which "$pkg" 2>/dev/null | sed -r 's/^\///'` if ! [ "$key" ]; then key="$pkg" fi for manifest in /etc/setup/*.lst.gz do if [[ `gunzip -c $manifest | grep "$key"` ]]; then package=`basename $manifest | sed -r 's/.lst.gz//'` echo "Found $key in package $package" fi done done } function do_search { findworkspace for pkg in $packages do echo "" echo Searching for installed packages matching $pkg: awk '/[^ ]+ [^ ]+ 0/ {if ($1 ~ query) print $1}' query="$pkg" /etc/setup/installed.db echo "" echo Searching for installable packages matching $pkg: cat setup.ini | awk -v query="$pkg" \ 'BEGIN{RS="\n\n@ "; FS="\n"; ORS="\n"} {if ($1 ~ query) {print $1}}' done } function do_describe { findworkspace echo for pkg in $packages do awk -v PKG="$pkg" '/^@/ {P=$2}; P==PKG {print}' setup.ini done } function do_install { findworkspace if ! [ -e "setup.ini" ]; then update_setup elif ! [ -s "setup.ini" ]; then echo "Package list corrupted. Trying update..." update_setup # if ! [ $? -eq 0 ]; then # echo "Failure updating setup.ini from $MIRROR." # exit 1 # fi fi crawl_packages 0 "$packages" if ! [ $cancelled ]; then # run all postinstall scripts list=`ls -U /etc/postinstall/*.sh 2>/dev/null` if [ "$list" ]; then echo echo Running postinstall scripts: for script in $list do echo " $script..." $script mv $script $script.done done fi fi } function do_remove { for pkg in $packages do # already=`grep -c "^$pkg " /etc/setup/installed.db` if ! [[ `grep "^$pkg " /etc/setup/installed.db` ]]; then echo Package $pkg is not installed, skipping removal. continue fi # dontremove="cygwin coreutils gawk bzip2 tar wget bash" for req in cygwin coreutils gawk bzip2 tar wget bash do if test "-$pkg-" = "-$req-" then echo "Cannot remove $pkg. Package is part of the system." exit 1 fi done if ! [ -e "/etc/setup/$pkg.lst.gz" ]; then echo Package manifest missing, cannot remove $pkg. exit 1 fi # echo echo "Removing $pkg..." # run preremove scripts if [ -e "/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 | awk '{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 awk -v PKG="$pkg" '$1 != PKG {print}' /etc/setup/installed.db.save >/etc/setup/installed.db echo Package $pkg removed. done } function do_upgrade { do_update for pkg in $packages do desc=`awk -v PKG="$pkg" '/^@/ {P=$2}; P==PKG {print}' setup.ini` file=`echo "$desc" | awk '/^install:/ {printf $2; exit}'` echo if ! [ $file ]; then echo Package $pkg not found or ambiguous name exit 1 fi version=`echo "$desc" | awk '/^version:/ {printf $2; exit}'` doc=`basename $file` if [ -e "release/$pkg/$doc" ]; then echo "Cannot upgrade package $pkg $version: No newer version available." else do_remove "$pkg" rm -f "release/$pkg/desc" # legacy! do_install "$pkg" if ! [ $cancelled ]; then echo echo "Package $pkg upgraded to version $version" fi fi done } function do_source { findworkspace for pkg in $packages do path="release/$pkg" mkdir -p "$path" awk -v PKG="$pkg" '/^@/ {P=$2}; P==PKG {print}' setup.ini >"$path/desc" if ! [ -s "$path/desc" ]; then echo "Package $pkg not found or ambiguous name." rm -R "$path" exit 1 fi source=`awk '/^source:/ {printf $2; exit}' "$path/desc"` if ! [ "$source" ]; then echo "Could not find \"source\" in package description: obsolete package?" exit 1 fi echo echo "Downloading..." file=`basename $source` wget -q "$MIRROR/$source" -O "/usr/src/$file" echo "installed: /usr/src/$file" rm -f "$path/desc" done } function do_show { echo "The following packages are installed:" awk '{print $1}' /etc/setup/installed.db | sort } if ! [ $command ]; then syntax elif [ "$command" == show ]; then do_show elif [ "$command" == update ]; then do_update elif ! [ "$packages" ]; then syntax else do_$command fi