diff options
Diffstat (limited to 'indra')
| -rwxr-xr-x | indra/viewer_components/updater/scripts/darwin/update_install.py | 98 | 
1 files changed, 75 insertions, 23 deletions
| diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py index 25efc2b0bc..2fc6fcdb29 100755 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -139,7 +139,7 @@ def write_marker(markerfile, markertext):  # ****************************************************************************  #   Main script logic  # **************************************************************************** -def main(dmgfile, markerfile, markertext, appdir=None): +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 @@ -179,18 +179,19 @@ def main(dmgfile, markerfile, markertext, appdir=None):          # prepare for other cleanup          with Janitor(LOGF) as janitor: -            # Hopefully caller explicitly stated the viewer bundle to update. -            # But if not, try to derive it from our own pathname. (The only -            # trouble with that is that the old viewer might copy this script -            # to a temp dir before running.) -            if not appdir: -                # 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)) +            # 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? @@ -260,15 +261,66 @@ def main(dmgfile, markerfile, markertext, appdir=None):              # 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...") -            # 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) +            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...") @@ -282,8 +334,9 @@ def main(dmgfile, markerfile, markertext, appdir=None):              except Exception, err:                  # copy failed -- try to restore previous viewer before crumping                  type, value, traceback = sys.exc_info() -                log("exception response: mv %r %r" % (aside, appdir)) -                shutil.move(aside, appdir) +                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 @@ -316,6 +369,5 @@ 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; -    # - optionally, the pathname of the Second Life viewer to update. +    # - the content to write into the marker file.      main(*sys.argv[1:]) | 
