Skip to content
Snippets Groups Projects
Commit 9e755ee9 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

MAINT-1481: Clean up update_install UI, including error output.

Capture actual error output from mkdir and mv; display it to user.
Introduce mysudo function used by sudo_mv function for graphical sudo command.
Since update_install actually only displays a single status message, just use
zenity --info instead of a zenity progress box: need not update its message.
Borrow semantics for clear_message and status functions from xmenity script.
Introduce errorbox function so we only have to make zenity/xmessage test once.
Move cleanup, onexit to top so we can use for clear_message.
parent 83f62544
No related branches found
No related tags found
No related merge requests found
...@@ -13,78 +13,136 @@ ...@@ -13,78 +13,136 @@
# Copyright (c) 2013, Linden Research, Inc. # Copyright (c) 2013, Linden Research, Inc.
# $/LicenseInfo$ # $/LicenseInfo$
# ****************************************************************************
# script parameters
# ****************************************************************************
tarball="$1" # the file to install tarball="$1" # the file to install
markerfile="$2" # create this file on failure markerfile="$2" # create this file on failure
mandatory="$3" # what to write to markerfile on failure mandatory="$3" # what to write to markerfile on failure
# ****************************************************************************
# helper functions
# ****************************************************************************
# empty array
cleanups=()
# add a cleanup action to execute on exit
function cleanup {
# wacky bash syntax for appending to array
cleanups[${#cleanups[*]}]="$*"
}
# called implicitly on exit
function onexit {
for action in "${cleanups[@]}"
do # don't quote, support actions consisting of multiple words
$action
done
}
trap 'onexit' EXIT
# write to log file
function log { function log {
# our log file will be open as stderr -- but until we set up that # our log file will be open as stderr -- but until we set up that
# redirection, logging to stderr is better than nothing # redirection, logging to stderr is better than nothing
echo "$*" 1>&2 echo "$*" 1>&2
} }
function status { # We display status by leaving one background xmessage process running. This
log "$@" # is the pid of that process.
# Prefix with '#' so xmenity will recognize it as a status message statuspid=""
echo "#$*"
function clear_message {
[ -n "$statuspid" ] && kill $statuspid
statuspid=""
} }
# make sure we remove any message box we might have put up
cleanup clear_message
# can we use zenity, or must we fall back to xmessage?
zenpath="$(which zenity)"
if [ -n "$zenpath" ]
then # zenity on PATH and is executable
# display a message box and continue
function status {
# clear any previous message
clear_message
# put up a new zenity box and capture its pid
"$zenpath" --info --title "Second Life Viewer Updater" \
--width=320 --height=120 --text="$*" &
statuspid=$!
}
# display an error box and wait for user
function errorbox {
"$zenpath" --error --title "Second Life Viewer Updater" \
--width=320 --height=120 --text="$*"
}
else # no zenity, use xmessage instead
# display a message box and continue
function status {
# clear any previous message
clear_message
# put up a new xmessage and capture its pid
xmessage -buttons OK:2 -center "$*" &
statuspid=$!
}
# display an error box and wait for user
function errorbox {
xmessage -buttons OK:2 -center "$*"
}
fi
# display an error box and terminate
function fail { function fail {
# Log the message # Log the message
log "$@" log "$@"
# tell subsequent viewer things went south # tell subsequent viewer things went south
echo "$mandatory" > "$markerfile" echo "$mandatory" > "$markerfile"
# add boilerplate # add boilerplate
local msg="An error occurred while updating Second Life: errorbox "An error occurred while updating Second Life:
$* $*
Please download the latest viewer from www.secondlife.com." Please download the latest viewer from www.secondlife.com."
# Restate test from xmenity to detect whether we can use zenity or must
# fall back to xmessage
zenpath="$(which zenity)"
if [ -n "$zenpath" -a -x "$zenpath" ]
then "$zenpath" --error --title "Second Life Viewer Updater" \
--width=320 --height=120 --text="$msg"
else xmessage -buttons -OK:2 -center "$msg"
fi
exit 1 exit 1
} }
# Find a graphical sudo program and define mysudo function. On error, $? is
# nonzero; output is in $err instead of being written to stdout/stderr.
gksudo="$(which gksudo)"
kdesu="$(which kdesu)"
if [ -n "$gksudo" ]
then function mysudo {
# gksudo allows you to specify description
err="$("$gksudo" --description "Second Life Viewer Updater" "$@" 2>&1)"
}
elif [ -n "$kdesu" ]
then function mysudo {
err="$("$kdesu" "$@" 2>&1)"
}
else # couldn't find either one, just try it anyway
function mysudo {
err="$("$@" 2>&1)"
}
fi
# Move directories, using mysudo if we think it necessary. On error, $? is
# nonzero; output is in $err instead of being written to stdout/stderr.
function sudo_mv { function sudo_mv {
# If we have write permission to both parent directories, shouldn't need # If we have write permission to both parent directories, shouldn't need
# sudo. # sudo.
if [ -w "$(dirname "$1")" -a -w "$(dirname "$2")" ] if [ -w "$(dirname "$1")" -a -w "$(dirname "$2")" ]
then mv "$1" "$2" then err="$(mv "$@" 2>&1)"
else # use one of the likely sudo programs else # use available sudo program; mysudo sets $? and $err
sudo="$(which gksudo)" mysudo mv "$@"
if [ -z "$sudo" ]
then sudo="$(which kdesu)"
fi
if [ -z "$sudo" ]
then # couldn't find either one, just try it anyway
mv "$1" "$2"
else # even with sudo, could fail, e.g. different filesystems
"$sudo" mv "$1" "$2"
fi
fi fi
} }
# empty array # ****************************************************************************
cleanups=() # main script logic
# ****************************************************************************
function cleanup {
# wacky bash syntax for appending to array
cleanups[${#cleanups[*]}]="$*"
}
function onexit {
for action in "${cleanups[@]}"
do # don't quote, support actions consisting of multiple words
$action
done
}
trap 'onexit' EXIT
mydir="$(dirname "$0")" mydir="$(dirname "$0")"
# We happen to know that the viewer specifies a marker-file pathname within # We happen to know that the viewer specifies a marker-file pathname within
# the logs directory. # the logs directory.
...@@ -97,9 +155,6 @@ logname="$logsdir/updater.log" ...@@ -97,9 +155,6 @@ logname="$logsdir/updater.log"
# Set up redirections for this script such that stderr is logged. (But first # Set up redirections for this script such that stderr is logged. (But first
# move the previous stderr to file descriptor 3.) # move the previous stderr to file descriptor 3.)
exec 3>&2- 2> "$logname" exec 3>&2- 2> "$logname"
# Piping to xmenity requires that we end with a line consisting of the string
# "100" to terminate zenity progress bar.
cleanup echo 100
# Rather than setting up a special pipeline to timestamp every line of stderr, # Rather than setting up a special pipeline to timestamp every line of stderr,
# produce header lines into log file indicating timestamp and the arguments # produce header lines into log file indicating timestamp and the arguments
...@@ -114,17 +169,19 @@ status 'Installing Second Life...' ...@@ -114,17 +169,19 @@ status 'Installing Second Life...'
# Creating tempdir under /tmp means it's possible that tempdir is on a # Creating tempdir under /tmp means it's possible that tempdir is on a
# different filesystem than INSTALL_DIR. One is tempted to create tempdir on a # different filesystem than INSTALL_DIR. One is tempted to create tempdir on a
# path derived from `dirname INSTALL_DIR`, but then we might need to add # path derived from `dirname INSTALL_DIR` -- but it seems modern 'mv' can
# another sudo prompt to create it. # handle moving across filesystems??
tempdir="/tmp/$(basename "$0").$$" tempdir="/tmp/$(basename "$0").$$"
tempinstall="$tempdir/install" tempinstall="$tempdir/install"
mkdir -p "$tempinstall" || fail "Couldn't create $tempinstall" # capture the actual error message, if any
err="$(mkdir -p "$tempinstall" 2>&1)" || fail "$err"
cleanup rm -rf "$tempdir" cleanup rm -rf "$tempdir"
# If we already knew the name of the tarball's top-level directory, we could # If we already knew the name of the tarball's top-level directory, we could
# just move that when all was said and done. Since we don't, untarring to the # just move that when all was said and done. Since we don't, untarring to the
# 'install' subdir with --strip 1 effectively renames that top-level # 'install' subdir with --strip 1 effectively renames that top-level
# directory. # directory.
# untar failures tend to be voluminous -- don't even try to capture, just log
tar --strip 1 -xjf "$tarball" -C "$tempinstall" || fail "Untar command failed" tar --strip 1 -xjf "$tarball" -C "$tempinstall" || fail "Untar command failed"
INSTALL_DIR="$(cd "$mydir/.." ; pwd)" INSTALL_DIR="$(cd "$mydir/.." ; pwd)"
...@@ -138,16 +195,21 @@ then backup="$INSTALL_DIR.backup" ...@@ -138,16 +195,21 @@ then backup="$INSTALL_DIR.backup"
do backup="$INSTALL_DIR.backup.$backupn" do backup="$INSTALL_DIR.backup.$backupn"
((backupn += 1)) ((backupn += 1))
done done
sudo_mv "$INSTALL_DIR" "$backup" || fail "Couldn't move $INSTALL_DIR to $backup" # on error, fail with actual error message from sudo_mv: permissions,
# cross-filesystem mv, ...?
sudo_mv "$INSTALL_DIR" "$backup" || fail "$err"
fi fi
# We unpacked the tarball into tempinstall. Move that. # We unpacked the tarball into tempinstall. Move that.
if ! sudo_mv "$tempinstall" "$INSTALL_DIR" if ! sudo_mv "$tempinstall" "$INSTALL_DIR"
then # If we failed to move the temp install to INSTALL_DIR, try to restore then # If we failed to move the temp install to INSTALL_DIR, try to restore
# INSTALL_DIR from backup # INSTALL_DIR from backup. Save $err because next sudo_mv will trash it!
realerr="$err"
sudo_mv "$backup" "$INSTALL_DIR" sudo_mv "$backup" "$INSTALL_DIR"
fail "Couldn't move $1 to $2" fail "$realerr"
fi fi
# Removing the tarball here, rather than with a 'cleanup' action, means we
# only remove it if we succeeded.
rm -f "$tarball" rm -f "$tarball"
# Launch the updated viewer. Restore original stderr from file descriptor 3, # Launch the updated viewer. Restore original stderr from file descriptor 3,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment