diff options
Diffstat (limited to 'indra/viewer_components/updater/scripts')
5 files changed, 0 insertions, 834 deletions
diff --git a/indra/viewer_components/updater/scripts/darwin/janitor.py b/indra/viewer_components/updater/scripts/darwin/janitor.py deleted file mode 100644 index cdf33df731..0000000000 --- a/indra/viewer_components/updater/scripts/darwin/janitor.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/python -"""\ -@file   janitor.py -@author Nat Goodspeed -@date   2011-09-14 -@brief  Janitor class to clean up arbitrary resources - -2013-01-04 cloned from vita because it's exactly what update_install.py needs. - -$LicenseInfo:firstyear=2011&license=viewerlgpl$ -Copyright (c) 2011, Linden Research, Inc. -$/LicenseInfo$ -""" - -import sys -import functools -import itertools - -class Janitor(object): -    """ -    Usage: - -    Basic: -    self.janitor = Janitor(sys.stdout) # report cleanup actions on stdout -    ... -    self.janitor.later(os.remove, some_temp_file) -    self.janitor.later(os.remove, some_other_file) -    ... -    self.janitor.cleanup()          # perform cleanup actions - -    Context Manager: -    with Janitor() as janitor:      # clean up quietly -        ... -        janitor.later(shutil.rmtree, some_temp_directory) -        ... -    # exiting 'with' block performs cleanup - -    Test Class: -    class TestMySoftware(unittest.TestCase, Janitor): -        def __init__(self): -            Janitor.__init__(self)  # quiet cleanup -            ... - -        def setUp(self): -            ... -            self.later(os.rename, saved_file, original_location) -            ... - -        def tearDown(self): -            Janitor.tearDown(self)  # calls cleanup() -            ... -            # Or, if you have no other tearDown() logic for -            # TestMySoftware, you can omit the TestMySoftware.tearDown() -            # def entirely and let it inherit Janitor.tearDown(). -    """ -    def __init__(self, stream=None): -        """ -        If you pass stream= (e.g.) sys.stdout or sys.stderr, Janitor will -        report its cleanup operations as it performs them. If you don't, it -        will perform them quietly -- unless one or more of the actions throws -        an exception, in which case you'll get output on stderr. -        """ -        self.stream   = stream -        self.cleanups = [] - -    def later(self, func, *args, **kwds): -        """ -        Pass the callable you want to call at cleanup() time, plus any -        positional or keyword args you want to pass it. -        """ -        # Get a name string for 'func' -        try: -            # A free function has a __name__ -            name = func.__name__ -        except AttributeError: -            try: -                # A class object (even builtin objects like ints!) support -                # __class__.__name__ -                name = func.__class__.__name__ -            except AttributeError: -                # Shrug! Just use repr() to get a string describing this func. -                name = repr(func) -        # Construct a description of this operation in Python syntax from -        # args, kwds. -        desc = "%s(%s)" % \ -               (name, ", ".join(itertools.chain((repr(a) for a in args), -                                                ("%s=%r" % (k, v) for (k, v) in kwds.iteritems())))) -        # Use functools.partial() to bind passed args and keywords to the -        # passed func so we get a nullary callable that does what caller -        # wants. -        bound = functools.partial(func, *args, **kwds) -        self.cleanups.append((desc, bound)) - -    def cleanup(self): -        """ -        Perform all the actions saved with later() calls. -        """ -        # Typically one allocates resource A, then allocates resource B that -        # depends on it. In such a scenario it's appropriate to delete B -        # before A -- so perform cleanup actions in reverse order. (This is -        # the same strategy used by atexit().) -        while self.cleanups: -            # Until our list is empty, pop the last pair. -            desc, bound = self.cleanups.pop(-1) - -            # If requested, report the action. -            if self.stream is not None: -                print >>self.stream, desc - -            try: -                # Call the bound callable -                bound() -            except Exception, err: -                # This is cleanup. Report the problem but continue. -                print >>(self.stream or sys.stderr), "Calling %s\nraised  %s: %s" % \ -                      (desc, err.__class__.__name__, err) - -    def tearDown(self): -        """ -        If a unittest.TestCase subclass (or a nose test class) adds Janitor as -        one of its base classes, and has no other tearDown() logic, let it -        inherit Janitor.tearDown(). -        """ -        self.cleanup() - -    def __enter__(self): -        return self - -    def __exit__(self, type, value, tb): -        # Perform cleanup no matter how we exit this 'with' statement -        self.cleanup() -        # Propagate any exception from the 'with' statement, don't swallow it -        return False diff --git a/indra/viewer_components/updater/scripts/darwin/messageframe.py b/indra/viewer_components/updater/scripts/darwin/messageframe.py deleted file mode 100644 index 8f58848882..0000000000 --- a/indra/viewer_components/updater/scripts/darwin/messageframe.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/python -"""\ -@file   messageframe.py -@author Nat Goodspeed -@date   2013-01-03 -@brief  Define MessageFrame class for popping up messages from a command-line -        script. - -$LicenseInfo:firstyear=2013&license=viewerlgpl$ -Copyright (c) 2013, Linden Research, Inc. -$/LicenseInfo$ -""" - -import Tkinter as tk -import os - -# Tricky way to obtain the filename of the main script (default title string) -import __main__ - -# This class is intended for displaying messages from a command-line script. -# Getting the base class right took a bit of trial and error. -# If you derive from tk.Frame, the destroy() method doesn't actually close it. -# If you derive from tk.Toplevel, it pops up a separate Tk frame too. destroy() -# closes this frame, but not that one. -# Deriving from tk.Tk appears to do the right thing. -class MessageFrame(tk.Tk): -    def __init__(self, text="", title=os.path.splitext(os.path.basename(__main__.__file__))[0], -                 width=320, height=120): -        tk.Tk.__init__(self) -        self.grid() -        self.title(title) -        self.var = tk.StringVar() -        self.var.set(text) -        self.msg = tk.Label(self, textvariable=self.var) -        self.msg.grid() -        # from http://stackoverflow.com/questions/3352918/how-to-center-a-window-on-the-screen-in-tkinter : -        self.update_idletasks() - -        # The constants below are to adjust for typical overhead from the -        # frame borders. -        xp = (self.winfo_screenwidth()  / 2) - (width  / 2) - 8 -        yp = (self.winfo_screenheight() / 2) - (height / 2) - 20 -        self.geometry('{0}x{1}+{2}+{3}'.format(width, height, xp, yp)) -        self.update() - -    def set(self, text): -        self.var.set(text) -        self.update() - -if __name__ == "__main__": -    # When run as a script, just test the MessageFrame. -    import sys -    import time - -    frame = MessageFrame("something in the way she moves....") -    time.sleep(3) -    frame.set("smaller") -    time.sleep(3) -    frame.set("""this has -several -lines""") -    time.sleep(3) -    frame.destroy() -    print "Destroyed!" -    sys.stdout.flush() -    time.sleep(3) diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py deleted file mode 100755 index 08f4f0ebb9..0000000000 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ /dev/null @@ -1,412 +0,0 @@ -#!/usr/bin/python -"""\ -@file   update_install.py -@author Nat Goodspeed -@date   2012-12-20 -@brief  Update the containing Second Life application bundle to the version in -        the specified disk image file. - -        This Python implementation is derived from the previous mac-updater -        application, a funky mix of C++, classic C and Objective-C. - -$LicenseInfo:firstyear=2012&license=viewerlgpl$ -Copyright (c) 2012, Linden Research, Inc. -$/LicenseInfo$ -""" - -import os -import sys -import cgitb -from contextlib import contextmanager -import errno -import glob -import plistlib -import re -import shutil -import subprocess -import tempfile -import time -from janitor import Janitor -from messageframe import MessageFrame -import Tkinter, tkMessageBox - -TITLE = "Second Life Viewer Updater" -# Magic bundle identifier used by all Second Life viewer bundles -BUNDLE_IDENTIFIER = "com.secondlife.indra.viewer" -# Magic OS directory name that causes Cocoa viewer to crash on OS X 10.7.5 -# (see MAINT-3331) -STATE_DIR = os.path.join( -    os.environ["HOME"], "Library", "Saved Application State", -    BUNDLE_IDENTIFIER + ".savedState") - -# Global handle to the MessageFrame so we can update message -FRAME = None -# Global handle to logfile, once it's open -LOGF  = None - -# **************************************************************************** -#   Logging and messaging -# -#   This script is normally run implicitly by the old viewer to update to the -#   new viewer. Its UI consists of a MessageFrame and possibly a Tk error box. -#   Log details to updater.log -- especially uncaught exceptions! -# **************************************************************************** -def log(message): -    """write message only to LOGF (also called by status() and fail())""" -    # If we don't even have LOGF open yet, at least write to Console log -    logf = LOGF or sys.stderr -    logf.writelines((time.strftime("%Y-%m-%dT%H:%M:%SZ ", time.gmtime()), message, '\n')) -    logf.flush() - -def status(message): -    """display and log normal progress message""" -    log(message) - -    global FRAME -    if not FRAME: -        FRAME = MessageFrame(message, TITLE) -    else: -        FRAME.set(message) - -def fail(message): -    """log message, produce error box, then terminate with nonzero rc""" -    log(message) - -    # If we haven't yet called status() (we don't yet have a FRAME), perform a -    # bit of trickery to bypass the spurious "main window" that Tkinter would -    # otherwise pop up if the first call is showerror(). -    if not FRAME: -        root = Tkinter.Tk() -        root.withdraw() - -    # If we do have a LOGF available, mention it in the error box. -    if LOGF: -        message = "%s\n(Updater log in %s)" % (message, LOGF.name) - -    # We explicitly specify the WARNING icon because, at least on the Tkinter -    # bundled with the system-default Python 2.7 on Mac OS X 10.7.4, the -    # ERROR, QUESTION and INFO icons are all the silly Tk rocket ship. At -    # least WARNING has an exclamation in a yellow triangle, even though -    # overlaid by a smaller image of the rocket ship. -    tkMessageBox.showerror(TITLE, -"""An error occurred while updating Second Life: -%s -Please download the latest viewer from www.secondlife.com.""" % message, -                           icon=tkMessageBox.WARNING) -    sys.exit(1) - -def exception(err): -    """call fail() with an exception instance""" -    fail("%s exception: %s" % (err.__class__.__name__, str(err))) - -def excepthook(type, value, traceback): -    """ -    Store this hook function into sys.excepthook until we have a logfile. -    """ -    # At least in older Python versions, it could be tricky to produce a -    # string from 'type' and 'value'. For instance, an OSError exception would -    # pass type=OSError and value=some_tuple. Empirically, this funky -    # expression seems to work. -    exception(type(*value)) -sys.excepthook = excepthook - -class ExceptHook(object): -    """ -    Store an instance of this class into sys.excepthook once we have a logfile -    open. -    """ -    def __init__(self, logfile): -        # There's no magic to the cgitb.enable() function -- it merely stores -        # an instance of cgitb.Hook into sys.excepthook, passing enable()'s -        # params into Hook.__init__(). Sadly, enable() doesn't forward all its -        # params using (*args, **kwds) syntax -- another story. But the point -        # is that all the goodness is in the cgitb.Hook class. Capture an -        # instance. -        self.hook = cgitb.Hook(file=logfile, format="text") - -    def __call__(self, type, value, traceback): -        # produce nice text traceback to logfile -        self.hook(type, value, traceback) -        # Now display an error box. -        excepthook(type, value, traceback) - -def write_marker(markerfile, markertext): -    log("writing %r to %s" % (markertext, markerfile)) -    try: -        with open(markerfile, "w") as markerf: -            markerf.write(markertext) -    except IOError, err: -        # write_marker() is invoked by fail(), and fail() is invoked by other -        # error-handling functions. If we try to invoke any of those, we'll -        # get infinite recursion. If for any reason we can't write markerfile, -        # try to log it -- otherwise shrug. -        log("%s exception: %s" % (err.__class__.__name__, err)) - -# **************************************************************************** -#   Utility -# **************************************************************************** -@contextmanager -def allow_errno(errn): -    """ -    Execute body of 'with' statement, accepting OSError with specific errno -    'errn'. Propagate any other exception, or an OSError with any other errno. -    """ -    try: -        # run the body of the 'with' statement -        yield -    except OSError, err: -        # unless errno == passed errn, re-raise the exception -        if err.errno != errn: -            raise - -# **************************************************************************** -#   Main script logic -# **************************************************************************** -def main(dmgfile, markerfile, markertext): -    # Should we fail, we're supposed to write 'markertext' to 'markerfile'. -    # Wrap the fail() function so we do that. -    global fail -    oldfail = fail -    def fail(message): -        write_marker(markerfile, markertext) -        oldfail(message) - -    try: -        # Starting with the Cocoafied viewer, we'll find viewer logs in -        # ~/Library/Application Support/$CFBundleIdentifier/logs rather than in -        # ~/Library/Application Support/SecondLife/logs as before. This could be -        # obnoxious -- but we Happen To Know that markerfile is a path specified -        # within the viewer's logs directory. Use that. -        logsdir = os.path.dirname(markerfile) - -        # Move the old updater.log file out of the way -        logname = os.path.join(logsdir, "updater.log") -        # Nonexistence is okay. Anything else, not so much. -        with allow_errno(errno.ENOENT): -            os.rename(logname, logname + ".old") - -        # Open new updater.log. -        global LOGF -        LOGF = open(logname, "w") - -        # Now that LOGF is in fact open for business, use it to log any further -        # uncaught exceptions. -        sys.excepthook = ExceptHook(LOGF) - -        # log how this script was invoked -        log(' '.join(repr(arg) for arg in sys.argv)) - -        # prepare for other cleanup -        with Janitor(LOGF) as janitor: - -            # Under some circumstances, this script seems to be invoked with a -            # nonexistent pathname. Check for that. -            if not os.path.isfile(dmgfile): -                fail(dmgfile + " has been deleted") - -            # Try to derive the name of the running viewer app bundle from our -            # own pathname. (Hopefully the old viewer won't copy this script -            # to a temp dir before running!) -            # Somewhat peculiarly, this script is currently packaged in -            # Appname.app/Contents/MacOS with the viewer executable. But even -            # if we decide to move it to Appname.app/Contents/Resources, we'll -            # still find Appname.app two levels up from dirname(__file__). -            appdir = os.path.abspath(os.path.join(os.path.dirname(__file__), -                                                  os.pardir, os.pardir)) -            if not appdir.endswith(".app"): -                # This can happen if either this script has been copied before -                # being executed, or if it's in an unexpected place in the app -                # bundle. -                fail(appdir + " is not an application directory") - -            # We need to install into appdir's parent directory -- can we? -            installdir = os.path.abspath(os.path.join(appdir, os.pardir)) -            if not os.access(installdir, os.W_OK): -                fail("Can't modify " + installdir) - -            # invent a temporary directory -            tempdir = tempfile.mkdtemp() -            log("created " + tempdir) -            # clean it up when we leave -            janitor.later(shutil.rmtree, tempdir) - -            status("Mounting image...") - -            mntdir = os.path.join(tempdir, "mnt") -            log("mkdir " + mntdir) -            os.mkdir(mntdir) -            command = ["hdiutil", "attach", dmgfile, "-mountpoint", mntdir] -            log(' '.join(command)) -            # Instantiating subprocess.Popen launches a child process with the -            # specified command line. stdout=PIPE passes a pipe to its stdout. -            hdiutil = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=LOGF) -            # Popen.communicate() reads that pipe until the child process -            # terminates, returning (stdout, stderr) output. Select just stdout. -            hdiutil_out = hdiutil.communicate()[0] -            if hdiutil.returncode != 0: -                fail("Couldn't mount " + dmgfile) -            # hdiutil should report the devnode. Find that. -            found = re.search(r"/dev/[^ ]*\b", hdiutil_out) -            if not found: -                # If we don't spot the devnode, log it and continue -- we only -                # use it to detach it. Don't fail the whole update if we can't -                # clean up properly. -                log("Couldn't spot devnode in hdiutil output:\n" + hdiutil_out) -            else: -                # If we do spot the devnode, detach it when done. -                janitor.later(subprocess.call, ["hdiutil", "detach", found.group(0)], -                              stdout=LOGF, stderr=subprocess.STDOUT) - -            status("Searching for app bundle...") - -            for candidate in glob.glob(os.path.join(mntdir, "*.app")): -                log("Considering " + candidate) -                try: -                    # By convention, a valid Mac app bundle has a -                    # Contents/Info.plist file containing at least -                    # CFBundleIdentifier. -                    CFBundleIdentifier = \ -                        plistlib.readPlist(os.path.join(candidate, "Contents", -                                                        "Info.plist"))["CFBundleIdentifier"] -                except Exception, err: -                    # might be IOError, xml.parsers.expat.ExpatError, KeyError -                    # Any of these means it's not a valid app bundle. Instead -                    # of aborting, just skip this candidate and continue. -                    log("%s not a valid app bundle: %s: %s" % -                        (candidate, err.__class__.__name__, err)) -                    continue - -                if CFBundleIdentifier == BUNDLE_IDENTIFIER: -                    break - -                log("unrecognized CFBundleIdentifier: " + CFBundleIdentifier) - -            else: -                fail("Could not find Second Life viewer in " + dmgfile) - -            # Here 'candidate' is the new viewer to install -            log("Found " + candidate) - -            # This logic was changed to make Mac updates behave more like -            # Windows. Most of the time, the user doesn't change the name of -            # the app bundle on our .dmg installer (e.g. "Second Life Beta -            # Viewer.app"). Most of the time, the version manager directs a -            # given viewer to update to another .dmg containing an app bundle -            # with THE SAME name. In that case, everything behaves as usual. - -            # The case that was changed is when the version manager offers (or -            # mandates) an update to a .dmg containing a different app bundle -            # name. This can happen, for instance, to a user who's downloaded -            # a "project beta" viewer, and the project subsequently publishes -            # a Release Candidate viewer. Say the project beta's app bundle -            # name is something like "Second Life Beta Neato.app". Anyone -            # launching that viewer will be offered an update to the -            # corresponding Release Candidate viewer -- which will be built as -            # a release viewer, with app bundle name "Second Life Viewer.app". - -            # On Windows, we run the NSIS installer, which will update/replace -            # the embedded install directory name, e.g. Second Life Viewer. -            # But the Mac installer used to locate the app bundle name in the -            # mounted .dmg file, then ignore that name, copying its contents -            # into the app bundle directory of the running viewer. That is, -            # we'd install the Release Candidate from the .dmg's "Second -            # Life.app" into "/Applications/Second Life Beta Neato.app". This -            # is undesired behavior. - -            # Instead, having found the app bundle name on the mounted .dmg, -            # we try to install that app bundle name into the parent directory -            # of the running app bundle. - -            # Are we installing a different app bundle name? If so, call it -            # out, both in the log and for the user -- this is an odd case. -            # (Presumably they've already agreed to a similar notification in -            # the viewer before the viewer launched this script, but still.) -            bundlename = os.path.basename(candidate) -            if os.path.basename(appdir) == bundlename: -                # updating the running app bundle, which we KNOW exists -                appexists = True -            else: -                # installing some other app bundle -                newapp = os.path.join(installdir, bundlename) -                appexists = os.path.exists(newapp) -                message = "Note: %s %s %s" % \ -                          (appdir, "updating" if appexists else "installing new", newapp) -                status(message) -                # okay, we have no further need of the name of the running app -                # bundle. -                appdir = newapp - -            status("Preparing to copy files...") - -            if appexists: -                # move old viewer to temp location in case copy from .dmg fails -                aside = os.path.join(tempdir, os.path.basename(appdir)) -                log("mv %r %r" % (appdir, aside)) -                # Use shutil.move() instead of os.rename(). move() first tries -                # os.rename(), but falls back to shutil.copytree() if the dest is -                # on a different filesystem. -                shutil.move(appdir, aside) - -            status("Copying files...") - -            # shutil.copytree()'s target must not already exist. But we just -            # moved appdir out of the way. -            log("cp -p %r %r" % (candidate, appdir)) -            try: -                # The viewer app bundle does include internal symlinks. Keep them -                # as symlinks. -                shutil.copytree(candidate, appdir, symlinks=True) -            except Exception, err: -                # copy failed -- try to restore previous viewer before crumping -                type, value, traceback = sys.exc_info() -                if appexists: -                    log("exception response: mv %r %r" % (aside, appdir)) -                    shutil.move(aside, appdir) -                # let our previously-set sys.excepthook handle this -                raise type, value, traceback - -            status("Cleaning up...") - -            log("touch " + appdir) -            os.utime(appdir, None)      # set to current time - -            # MAINT-3331: remove STATE_DIR. Empirically, this resolves a -            # persistent, mysterious crash after updating our viewer on an OS -            # X 10.7.5 system. -            log("rm -rf '%s'" % STATE_DIR) -            with allow_errno(errno.ENOENT): -                shutil.rmtree(STATE_DIR) - -            command = ["open", appdir] -            log(' '.join(command)) -            subprocess.check_call(command, stdout=LOGF, stderr=subprocess.STDOUT) - -        # If all the above succeeded, delete the .dmg file. We don't do this -        # as a janitor.later() operation because we only want to do it if we -        # get this far successfully. Note that this is out of the scope of the -        # Janitor: we must detach the .dmg before removing it! -        log("rm " + dmgfile) -        os.remove(dmgfile) - -    except Exception, err: -        # Because we carefully set sys.excepthook -- and even modify it to log -        # the problem once we have our log file open -- you might think we -        # could just let exceptions propagate. But when we do that, on -        # exception in this block, we FIRST restore the no-side-effects fail() -        # and THEN implicitly call sys.excepthook(), which calls the (no-side- -        # effects) fail(). Explicitly call sys.excepthook() BEFORE restoring -        # fail(). Only then do we get the enriched fail() behavior. -        sys.excepthook(*sys.exc_info()) - -    finally: -        # When we leave main() -- for whatever reason -- reset fail() the way -        # it was before, because the bound markerfile, markertext params -        # passed to this main() call are no longer applicable. -        fail = oldfail - -if __name__ == "__main__": -    # We expect this script to be invoked with: -    # - the pathname to the .dmg we intend to install; -    # - the pathname to an update-error marker file to create on failure; -    # - the content to write into the marker file. -    main(*sys.argv[1:]) diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install deleted file mode 100755 index 03089f192e..0000000000 --- a/indra/viewer_components/updater/scripts/linux/update_install +++ /dev/null @@ -1,220 +0,0 @@ -#! /bin/bash - -# @file   update_install -# @author Nat Goodspeed -# @date   2013-01-09 -# @brief  Update the containing Second Life application bundle to the version in -#         the specified tarball. -#  -#         This bash implementation is derived from the previous linux-updater.bin -#         application. -#  -# $LicenseInfo:firstyear=2013&license=viewerlgpl$ -# Copyright (c) 2013, Linden Research, Inc. -# $/LicenseInfo$ - -# **************************************************************************** -#   script parameters -# **************************************************************************** -tarball="$1"                        # the file to install -markerfile="$2"                     # create this file 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 { -    # our log file will be open as stderr -- but until we set up that -    # redirection, logging to stderr is better than nothing -    echo "$*" 1>&2 -} - -# We display status by leaving one background xmessage process running. This -# is the pid of that process. -statuspid="" - -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="$*" & -         # MAINT-2333: use bouncing progress bar -         "$zenpath" --progress --pulsate --no-cancel --title "Second Life Viewer Updater" \ -                    --width=320 --height=120 --text "$*" </dev/null & -         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 { -    # Log the message -    log "$@" -    # tell subsequent viewer things went south -    echo "$mandatory" > "$markerfile" -    # add boilerplate -    errorbox "An error occurred while updating Second Life: -$* -Please download the latest viewer from www.secondlife.com." -    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 { -    # If we have write permission to both parent directories, shouldn't need -    # sudo. -    if [ -w "$(dirname "$1")" -a -w "$(dirname "$2")" ] -    then err="$(mv "$@" 2>&1)" -    else # use available sudo program; mysudo sets $? and $err -         mysudo mv "$@" -    fi -} - -# **************************************************************************** -#   main script logic -# **************************************************************************** -mydir="$(dirname "$0")" -# We happen to know that the viewer specifies a marker-file pathname within -# the logs directory. -logsdir="$(dirname "$markerfile")" -logname="$logsdir/updater.log" - -# move aside old updater.log; we're about to create a new one -[ -f "$logname" ] && mv "$logname" "$logname.old" - -# Set up redirections for this script such that stderr is logged. (But first -# move the previous stderr to file descriptor 3.) -exec 3>&2- 2> "$logname" - -# Rather than setting up a special pipeline to timestamp every line of stderr, -# produce header lines into log file indicating timestamp and the arguments -# with which we were invoked. -date 1>&2 -log "$0 $*" - -# Log every command we execute, along with any stderr it might produce -set -x - -status 'Installing Second Life...' - -# 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 -# path derived from `dirname INSTALL_DIR` -- but it seems modern 'mv' can -# handle moving across filesystems?? -tempdir="$(mktemp -d)" -tempinstall="$tempdir/install" -# capture the actual error message, if any -err="$(mkdir -p "$tempinstall" 2>&1)" || fail "$err" -cleanup rm -rf "$tempdir" - -# 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 -# 'install' subdir with --strip 1 effectively renames that top-level -# 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" - -INSTALL_DIR="$(cd "$mydir/.." ; pwd)" - -# Considering we're launched from a subdirectory of INSTALL_DIR, would be -# surprising if it did NOT already exist... -if [ -e "$INSTALL_DIR" ] -then backup="$INSTALL_DIR.backup" -     backupn=1 -     while [ -e "$backup" ] -     do backup="$INSTALL_DIR.backup.$backupn" -        ((backupn += 1)) -     done -     # on error, fail with actual error message from sudo_mv: permissions, -     # cross-filesystem mv, ...? -     sudo_mv "$INSTALL_DIR" "$backup" || fail "$err" -fi -# We unpacked the tarball into tempinstall. Move that. -if ! sudo_mv "$tempinstall" "$INSTALL_DIR" -then # If we failed to move the temp install to INSTALL_DIR, try to restore -     # INSTALL_DIR from backup. Save $err because next sudo_mv will trash it! -     realerr="$err" -     sudo_mv "$backup" "$INSTALL_DIR" -     fail "$realerr" -fi - -# Removing the tarball here, rather than with a 'cleanup' action, means we -# only remove it if we succeeded. -rm -f "$tarball" - -# Launch the updated viewer. Restore original stderr from file descriptor 3, -# though -- otherwise updater.log gets cluttered with the viewer log! -"$INSTALL_DIR/secondlife" 2>&3- & diff --git a/indra/viewer_components/updater/scripts/windows/update_install.bat b/indra/viewer_components/updater/scripts/windows/update_install.bat deleted file mode 100644 index 96687226a8..0000000000 --- a/indra/viewer_components/updater/scripts/windows/update_install.bat +++ /dev/null @@ -1,3 +0,0 @@ -start /WAIT %1 /SKIP_DIALOGS
 -IF ERRORLEVEL 1 ECHO %3 > %2
 -DEL %1
  | 
