#!/bin/bash #emacs: -*- mode: shell-script; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- #ex: set sts=4 ts=4 sw=4 et: # play safe set -e set -u ############ # Defaults # ############ nd_autoinstall_version=0.1 # To be set by cmdline args ai_envfile= ai_package= ai_verbose= ai_dialog_title= ai_force=0 ai_file= print_verbose() { [ -z "$ai_verbose" ] || echo "I: $*" } print_version() { cat << EOT nd-autoinstall $nd_autoinstall_version Copyright (C) 2010 Yaroslav Halchenko Licensed under GNU Public License version 3 or later. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Yaroslav Halchenko for the NeuroDebian project. EOT } print_help() { cat << EOT Usage: nd-autoinstall [options] COMMAND [command_options] Runs the COMMAND if it is available, otherwise installs PACKAGE first, and then runs the command. If an environment file is specified, it gets sourced first (PACKAGE gets installed if environment file is not available). Options: -p, --package=PACKAGE Name of the package to be installed if named differently than COMMAND. -e, --environment-file=FILE File to be sourced before invocation of the COMMAND. If not found, PACKAGE gets installed first. -f, --force Skip all checks and install package(s) provided via --package. -F, --file=FILE If specified file is not present, install the PACKAGE and run the COMMAND. -v, --verbose Enable additional progress messages. -t, --title Optinal title of the installation dialog. -h, --help Print short description, usage summary and option list. --version Print version information and exit. Exit status: exit status of the COMMAND - if COMMAND is available (or got sucesfully installed) 2 - incorrect invocation of nd-autoinstall 3 - PACKAGE installation failure EOT } ################################ # Commandline options handling # ################################ # Parse commandline options (taken from the getopt examples from the Debian util-linux package) # Note that we use `"$@"' to let each command-line parameter expand to a # separate word. The quotes around `$@' are essential! # We need CLOPTS as the `eval set --' would nuke the return value of getopt. CLOPTS=`getopt -o h,e:,p:,t:,f,F:,v --long help,version,environment-file:,package:,title:,verbose,force,file: -n 'nd-autoinstall' -- "$@"` if [ $? != 0 ] ; then echo "Terminating..." >&2 exit 2 fi # Note the quotes around `$CLOPTS': they are essential! eval set -- "$CLOPTS" while true ; do case "$1" in -e|--environment-file) shift; ai_envfile="$1"; shift;; -f|--force) ai_force=1; shift;; -F|--file) shift; ai_file="$1"; shift;; -p|--package) shift; ai_package="$1"; shift;; -t|--title) shift; ai_dialog_title="$1"; shift;; -v|--verbose) ai_verbose=1; shift;; -h|--help) print_help; exit 0;; --version) print_version; exit 0;; --) shift ; break ;; *) echo "Internal error! ($1)"; exit 1;; esac done if [ $# -lt 1 ] ; then print_help >&2 exit 2 fi ai_command="$1"; shift [ -z "$ai_package" ] && ai_package=$(basename "$ai_command") [ -z "$ai_dialog_title" ] && ai_dialog_title="Package installation" ai_envfile_failed= if [ ! -z "$ai_envfile" ]; then source "$ai_envfile" || ai_envfile_failed=1 fi # # Decide either installation is necessary # do_install=0 if [ ! -z "$ai_envfile_failed" ]; then print_verbose "Environment file $ai_envfile failed to source. Install $ai_package" do_install=1 fi if [ ! -z "$ai_file" ] && [ ! -e "$ai_file" ]; then print_verbose "File $ai_file absent. Install $ai_package" do_install=1 fi if ! which "$ai_command" > /dev/null && [ ! -e "$ai_command" ]; then print_verbose "Command $ai_command is not available. Install $ai_package" do_install=1 fi if [ $ai_force -eq 1 ]; then print_verbose "Force installation of $ai_package" do_install=1 fi if [ $do_install -eq 1 ]; then # Figure out amount of space to download/occupy space_info="$(LC_ALL=C apt-get --trivial-only --print-uris install $ai_package 2>/dev/null \ | grep -e '^\(Need to get \|After this\)' || : )" if [ $ai_force -eq 0 ]; then if ! zenity --question \ --text="To run '$ai_command', $ai_package package needs to be installed. $space_info Do you want to proceed?"; then exit 2 fi fi print_verbose "Need to install $ai_package to run $ai_command" logfile=$(mktemp -u /tmp/nd-autoinstall-XXXXXX.log) { SUDO_ASKPASS="/usr/bin/ssh-askpass" /usr/bin/sudo -A \ DEBIAN_FRONTEND=gnome /usr/bin/apt-get install -y $ai_package 2>&1 \ && rm -f $logfile; } \ | tee $logfile \ | zenity --title="$ai_dialog_title" \ --text="Installing $ai_package $space_info" \ --progress --pulsate --auto-close --auto-kill if [ -e $logfile ] ; then zenity --title="Installation of $ai_package has failed: see $logfile" \ --window-icon=error \ --width=800 --height=600 \ --text-info --filename=$logfile exit 3 fi [ -z "$ai_envfile_failed" ] || source "$ai_envfile" || { zenity --text="Failed to source $ai_envfile even after installing $ai_package" \ --window-icon=error --error exit 1 } fi if which $ai_command > /dev/null 2>&1; then # only run if executable print_verbose "Running $ai_command" $ai_command "$@" fi