diff options
Diffstat (limited to 'indra')
| -rwxr-xr-x | indra/lib/python/indra/util/llmanifest.py | 33 | ||||
| -rwxr-xr-x | indra/newview/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | indra/newview/VIEWER_VERSION.txt | 2 | ||||
| -rwxr-xr-x | indra/newview/installers/windows/installer_template.nsi | 28 | ||||
| -rwxr-xr-x | indra/newview/viewer_manifest.py | 257 | ||||
| -rwxr-xr-x | indra/viewer_components/updater/llupdatedownloader.cpp | 52 | ||||
| -rwxr-xr-x | indra/viewer_components/updater/llupdaterservice.cpp | 56 | ||||
| -rwxr-xr-x | indra/viewer_components/updater/scripts/darwin/update_install.py | 12 | 
8 files changed, 222 insertions, 223 deletions
| diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 52b4acbc94..1d85aa2978 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -85,7 +85,8 @@ def get_default_platform(dummy):              }[sys.platform]  DEFAULT_SRCTREE = os.path.dirname(sys.argv[0]) -RELEASE_CHANNEL = 'Second Life Release' +CHANNEL_VENDOR_BASE = 'Second Life' +RELEASE_CHANNEL = CHANNEL_VENDOR_BASE + ' Release'  ARGUMENTS=[      dict(name='actions', @@ -112,13 +113,14 @@ ARGUMENTS=[           default="Release"),      dict(name='dest', description='Destination directory.', default=DEFAULT_SRCTREE),      dict(name='grid', -         description="""Which grid the client will try to connect to. Even -        though it's not strictly a grid, 'firstlook' is also an acceptable -        value for this parameter.""", -         default=""), +         description="""Which grid the client will try to connect to.""", +         default=None),      dict(name='channel',           description="""The channel to use for updates, packaging, settings name, etc.""",           default='CHANNEL UNSET'), +    dict(name='channel_suffix', +         description="""Addition to the channel for packaging and channel value, but not application name (used internally)""", +         default=None),      dict(name='installer_name',           description=""" The name of the file that the installer should be          packaged up into. Only used on Linux at the moment.""", @@ -213,9 +215,9 @@ def main():              print "Unable to read versionfile '%s'" % args['versionfile']              raise -    # default and agni are default -    if args['grid'] in ['default', 'agni']: -        args['grid'] = '' +    # unspecified, default, and agni are default +    if args['grid'] in ['', 'default', 'agni']: +        args['grid'] = None      if 'actions' in args:          args['actions'] = args['actions'].split() @@ -286,21 +288,24 @@ def main():          base_channel_name = args['channel']          # Build each additional package.          package_id_list = additional_packages.split(" ") +        args['channel'] = base_channel_name          for package_id in package_id_list:              try: -                args['package_id'] = package_id -                args['channel'] = base_channel_name + os.environ[package_id + "_viewer_channel_suffix"] +                if package_id + "_viewer_channel_suffix" in os.environ: +                    args['channel_suffix'] = os.environ[package_id + "_viewer_channel_suffix"] +                else: +                    args['channel_suffix'] = None                  if package_id + "_sourceid" in os.environ:                      args['sourceid'] = os.environ[package_id + "_sourceid"]                  else: -                    args['sourceid'] = "" +                    args['sourceid'] = None                  args['dest'] = base_dest_prefix + os.sep + package_id + os.sep + base_dest_postfix              except KeyError:                  sys.stderr.write("Failed to create package for package_id: %s" % package_id)                  sys.stderr.flush()                  continue              if touch: -                print 'Creating additional package for ', package_id, ' in ', args['dest'] +                print 'Creating additional package for "', package_id, '" in ', args['dest']              wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)              wm.do(*args['actions'])              if touch: @@ -332,7 +337,7 @@ class LLManifest(object):      manifests = {}      def for_platform(self, platform, arch = None):          if arch: -            platform = platform + '_' + arch +            platform = platform + '_' + arch + '_'          return self.manifests[platform.lower()]      for_platform = classmethod(for_platform) @@ -349,8 +354,6 @@ class LLManifest(object):          self.created_paths = []          self.package_name = "Unknown" -    def default_grid(self): -        return self.args.get('grid', None) == ''      def default_channel(self):          return self.args.get('channel', None) == RELEASE_CHANNEL diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1fea6dea9f..c5e1cde4e6 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1748,6 +1748,7 @@ if (WINDOWS)        ARGS          ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py          --actions=copy +        --arch=${ARCH}          --artwork=${ARTWORK_DIR}          --build=${CMAKE_CURRENT_BINARY_DIR}          --buildtype=${CMAKE_BUILD_TYPE} @@ -1815,6 +1816,7 @@ if (WINDOWS)          COMMAND ${PYTHON_EXECUTABLE}          ARGS            ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py +          --arch=${ARCH}            --artwork=${ARTWORK_DIR}            --build=${CMAKE_CURRENT_BINARY_DIR}            --buildtype=${CMAKE_BUILD_TYPE} @@ -1939,7 +1941,6 @@ if (LINUX)          --configuration=${CMAKE_CFG_INTDIR}          --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged          --grid=${GRID} -        --installer_name=${product}          --source=${CMAKE_CURRENT_SOURCE_DIR}          --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched        DEPENDS @@ -2017,6 +2018,7 @@ if (DARWIN)      ARGS        ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py        --actions=copy +      --arch=${ARCH}        --artwork=${ARTWORK_DIR}        --build=${CMAKE_CURRENT_BINARY_DIR}        --buildtype=${CMAKE_BUILD_TYPE} @@ -2049,6 +2051,7 @@ if (DARWIN)          COMMAND ${PYTHON_EXECUTABLE}          ARGS            ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py +          --arch=${ARCH}            --artwork=${ARTWORK_DIR}            --build=${CMAKE_CURRENT_BINARY_DIR}            --buildtype=${CMAKE_BUILD_TYPE} diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 8b7b0b52e5..3609cf7707 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.6.12 +3.6.13 diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 8a6114f0d5..dd316cdbdf 100755 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -72,16 +72,8 @@ LangString LanguageCode ${LANG_RUSSIAN}  "ru"  LangString LanguageCode ${LANG_TURKISH}  "tr"
  LangString LanguageCode ${LANG_TRADCHINESE}  "zh"
 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 -;; Tweak for different servers/builds (this placeholder is replaced by viewer_manifest.py)
 -;; For example:
 -;; !define INSTFLAGS "%(flags)s"
 -;; !define INSTNAME   "SecondLife%(grid_caps)s"
 -;; !define SHORTCUT   "Second Life (%(grid_caps)s)"
 -;; !define URLNAME   "secondlife%(grid)s"
 -;; !define UNINSTALL_SETTINGS 1
 -
 -%%GRID_VARS%%
 +;; this placeholder is replaced by viewer_manifest.py
 +%%INST_VARS%%
  Name ${INSTNAME}
 @@ -109,7 +101,6 @@ Page instfiles  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  Var INSTPROG
  Var INSTEXE
 -Var INSTFLAGS
  Var INSTSHORTCUT
  Var COMMANDLINE         ; command line passed to this installer, set in .onInit
  Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer
 @@ -147,7 +138,7 @@ label_ask_launch:  label_launch:
  	# Assumes SetOutPath $INSTDIR
 -	Exec '"$INSTDIR\$INSTEXE" $INSTFLAGS $SHORTCUT_LANG_PARAM'
 +	Exec '"$INSTDIR\$INSTEXE" $SHORTCUT_LANG_PARAM'
  label_no_launch:
  	Pop $R0
  FunctionEnd
 @@ -720,7 +711,6 @@ ShowUninstDetails show  Section Uninstall
  ; Start with some default values.
 -StrCpy $INSTFLAGS ""
  StrCpy $INSTPROG "${INSTNAME}"
  StrCpy $INSTEXE "${INSTEXE}"
  StrCpy $INSTSHORTCUT "${SHORTCUT}"
 @@ -919,7 +909,6 @@ Section ""						; (default section)  SetShellVarContext all			; install for all users (if you change this, change it in the uninstall as well)
  ; Start with some default values.
 -StrCpy $INSTFLAGS "${INSTFLAGS}"
  StrCpy $INSTPROG "${INSTNAME}"
  StrCpy $INSTEXE "${INSTEXE}"
  StrCpy $INSTSHORTCUT "${SHORTCUT}"
 @@ -966,7 +955,7 @@ StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)"  CreateDirectory	"$SMPROGRAMS\$INSTSHORTCUT"
  SetOutPath "$INSTDIR"
  CreateShortCut	"$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \
 -				"$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM"
 +				"$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM"
  WriteINIStr		"$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \
 @@ -985,9 +974,9 @@ CreateShortCut	"$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \  ; Other shortcuts
  SetOutPath "$INSTDIR"
  CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
 -        "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM"
 +        "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM"
  CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \
 -        "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM"
 +        "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM"
  CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
  				'"$INSTDIR\uninst.exe"' ''
 @@ -996,7 +985,6 @@ CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \  ; Write registry
  WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" "$INSTDIR"
  WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version" "${VERSION_LONG}"
 -WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Flags" "$INSTFLAGS"
  WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Shortcut" "$INSTSHORTCUT"
  WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" "$INSTEXE"
  WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayName" "$INSTPROG (remove only)"
 @@ -1009,13 +997,13 @@ WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" ""  WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" '"$INSTDIR\$INSTEXE"'
  ;; URL param must be last item passed to viewer, it ignores subsequent params
  ;; to avoid parameter injection attacks.
 -WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"'
 +WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$INSTEXE" -url "%1"'
  WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info"(default)" "URL:Second Life"
  WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "URL Protocol" ""
  WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" '"$INSTDIR\$INSTEXE"'
  ;; URL param must be last item passed to viewer, it ignores subsequent params
  ;; to avoid parameter injection attacks.
 -WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"'
 +WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$INSTEXE" -url "%1"'
  ; write out uninstaller
  WriteUninstaller "$INSTDIR\uninst.exe"
 diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 894e368427..9e8623c1f9 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -38,7 +38,7 @@ viewer_dir = os.path.dirname(__file__)  # Put it FIRST because some of our build hosts have an ancient install of  # indra.util.llmanifest under their system Python!  sys.path.insert(0, os.path.join(viewer_dir, os.pardir, "lib", "python")) -from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors +from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors, CHANNEL_VENDOR_BASE, RELEASE_CHANNEL  try:      from llbase import llsd  except ImportError: @@ -112,21 +112,29 @@ class ViewerManifest(LLManifest):                                    Persist=1,                                    Type='String',                                    Value=''), +                    CmdLineGridChoice=dict(Comment='Default grid', +                                  Persist=0, +                                  Type='String', +                                  Value=''),                      CmdLineChannel=dict(Comment='Command line specified channel name',                                          Persist=0,                                          Type='String',                                          Value=''))                  settings_install = {} -                for key, setting in (("sourceid", "sourceid"), -                                     ("channel", "CmdLineChannel")): -                    if key in self.args: -                        # only set if value is non-empty -                        if self.args[key]: -                            # copy corresponding setting from settings_template -                            settings_install[setting] = settings_template[setting].copy() -                            # then fill in Value -                            settings_install[setting]["Value"] = self.args[key] -                            print "Put %s '%s' in settings_install.xml" % (setting, self.args[key]) +                if 'sourceid' in self.args and self.args['sourceid']: +                    settings_install['sourceid'] = settings_template['sourceid'].copy() +                    settings_install['sourceid']['Value'] = self.args['sourceid'] +                    print "Set sourceid in settings_install.xml to '%s'" % self.args['sourceid'] + +                if 'channel_suffix' in self.args and self.args['channel_suffix']: +                    settings_install['CmdLineChannel'] = settings_template['CmdLineChannel'].copy() +                    settings_install['CmdLineChannel']['Value'] = self.channel_with_pkg_suffix() +                    print "Set CmdLineChannel in settings_install.xml to '%s'" % self.channel_with_pkg_suffix() + +                if 'grid' in self.args and self.args['grid']: +                    settings_install['CmdLineGridChoice'] = settings_template['CmdLineGridChoice'].copy() +                    settings_install['CmdLineGridChoice']['Value'] = self.grid() +                    print "Set CmdLineGridChoice in settings_install.xml to '%s'" % self.grid()                  # did we actually copy anything into settings_install dict?                  if settings_install: @@ -197,62 +205,72 @@ class ViewerManifest(LLManifest):      def grid(self):          return self.args['grid'] +      def channel(self):          return self.args['channel'] -    def channel_unique(self): -        return self.channel().replace("Second Life", "").strip() -    def channel_oneword(self): -        return "".join(self.channel_unique().split()) -    def channel_lowerword(self): -        return self.channel_oneword().lower() + +    def channel_with_pkg_suffix(self): +        fullchannel=self.channel() +        if 'channel_suffix' in self.args and self.args['channel_suffix']: +            fullchannel+=' '+self.args['channel_suffix'] +        return fullchannel + +    def channel_variant(self): +        global CHANNEL_VENDOR_BASE +        return self.channel().replace(CHANNEL_VENDOR_BASE, "").strip() + +    def channel_type(self): # returns 'release', 'beta', 'project', or 'test' +        global CHANNEL_VENDOR_BASE +        channel_qualifier=self.channel().replace(CHANNEL_VENDOR_BASE, "").lower().strip() +        if channel_qualifier.startswith('release'): +            channel_type='release' +        elif channel_qualifier.startswith('beta'): +            channel_type='beta' +        elif channel_qualifier.startswith('project'): +            channel_type='project' +        else: +            channel_type='test' +        return channel_type + +    def channel_variant_app_suffix(self): +        # get any part of the compiled channel name after the CHANNEL_VENDOR_BASE +        suffix=self.channel_variant() +        # by ancient convention, we don't use Release in the app name +        if self.channel_type() == 'release': +            suffix=suffix.replace('Release', '').strip() +        # for the base release viewer, suffix will now be null - for any other, append what remains +        if len(suffix) > 0: +            suffix = "_"+ ("_".join(suffix.split())) +        # the additional_packages mechanism adds more to the installer name (but not to the app name itself) +        if 'channel_suffix' in self.args and self.args['channel_suffix']: +            suffix+='_'+("_".join(self.args['channel_suffix'].split())) +        return suffix + +    def installer_base_name(self): +        global CHANNEL_VENDOR_BASE +        # a standard map of strings for replacing in the templates +        substitution_strings = { +            'channel_vendor_base' : '_'.join(CHANNEL_VENDOR_BASE.split()), +            'channel_variant_underscores':self.channel_variant_app_suffix(), +            'version_underscores' : '_'.join(self.args['version']), +            'arch':self.args['arch'] +            } +        return "%(channel_vendor_base)s%(channel_variant_underscores)s_%(version_underscores)s_%(arch)s" % substitution_strings      def app_name(self): -        app_suffix='Test' -        channel_type=self.channel_lowerword() -        if channel_type.startswith('release') : +        global CHANNEL_VENDOR_BASE +        channel_type=self.channel_type() +        if channel_type == 'release':              app_suffix='Viewer' -        elif re.match('^(beta|project).*',channel_type) : -            app_suffix=self.channel_unique() -        return "Second Life "+app_suffix -         +        else: +            app_suffix=self.channel_variant() +        return CHANNEL_VENDOR_BASE + ' ' + app_suffix + +    def app_name_oneword(self): +        return ''.join(self.app_name().split()) +          def icon_path(self): -        icon_path="icons/" -        channel_type=self.channel_lowerword() -        print "Icon channel type '%s'" % channel_type -        if channel_type.startswith('release') : -            icon_path += 'release' -        elif re.match('^beta.*',channel_type) : -            icon_path += 'beta' -        elif re.match('^project.*',channel_type) : -            icon_path += 'project' -        else : -            icon_path += 'test' -        return icon_path - -    def flags_list(self): -        """ Convenience function that returns the command-line flags -        for the grid""" - -        # The original role of this method seems to have been to build a -        # grid-specific viewer: one that would, on launch, preselect a -        # particular grid. (Apparently that dates back to when the protocol -        # between viewer and simulator required them to be updated in -        # lockstep, so that "the beta grid" required "a beta viewer.") But -        # those viewer command-line switches no longer work without tweaking -        # user_settings/grids.xml. In fact, going forward, it's unclear what -        # use case that would address. - -        # This method also set a channel-specific (or grid-and-channel- -        # specific) user_settings/settings_something.xml file. It has become -        # clear that saving user settings in a channel-specific file causes -        # more problems (confusion) than it solves, so we've discontinued that. - -        # In fact we now avoid forcing viewer command-line switches at all, -        # instead introducing a settings_install.xml file. Command-line -        # switches don't aggregate well; for instance the generated --channel -        # switch actually prevented the user specifying --channel on the -        # command line. Settings files have well-defined override semantics. -        return None +        return "icons/" + self.channel_type()      def extract_names(self,src):          try: @@ -277,15 +295,9 @@ class ViewerManifest(LLManifest):          random.shuffle(names)          return ', '.join(names) -class WindowsManifest(ViewerManifest): +class Windows_i686_Manifest(ViewerManifest):      def final_exe(self): -        app_suffix="Test" -        channel_type=self.channel_lowerword() -        if channel_type.startswith('release') : -            app_suffix='' -        elif re.match('^(beta|project).*',channel_type) : -            app_suffix=''.join(self.channel_unique().split()) -        return "SecondLife"+app_suffix+".exe" +        return self.app_name_oneword()+".exe"      def test_msvcrt_and_copy_action(self, src, dst):          # This is used to test a dll manifest. @@ -334,7 +346,7 @@ class WindowsManifest(ViewerManifest):              print "Doesn't exist:", src      def construct(self): -        super(WindowsManifest, self).construct() +        super(Windows_i686_Manifest, self).construct()          if self.is_packaging_viewer():              # Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe. @@ -567,65 +579,33 @@ class WindowsManifest(ViewerManifest):              'version_short' : '.'.join(self.args['version'][:-1]),              'version_dashes' : '-'.join(self.args['version']),              'final_exe' : self.final_exe(), -            'grid':self.args['grid'], -            'grid_caps':self.args['grid'].upper(),              'flags':'', -            'channel':self.channel(), -            'channel_oneword':self.channel_oneword(), -            'channel_unique':self.channel_unique(), -            'subchannel_underscores':'_'.join(self.channel_unique().split()) +            'app_name':self.app_name(), +            'app_name_oneword':self.app_name_oneword()              } +        installer_file = self.installer_base_name() + '_Setup.exe' +        substitution_strings['installer_file'] = installer_file +                  version_vars = """          !define INSTEXE  "%(final_exe)s"          !define VERSION "%(version_short)s"          !define VERSION_LONG "%(version)s"          !define VERSION_DASHES "%(version_dashes)s"          """ % substitution_strings -        if self.default_channel(): -            if self.default_grid(): -                # release viewer -                installer_file = "Second_Life_%(version_dashes)s_Setup.exe" -                grid_vars_template = """ -                OutFile "%(installer_file)s" -                !define INSTFLAGS "%(flags)s" -                !define INSTNAME   "SecondLifeViewer" -                !define SHORTCUT   "Second Life Viewer" -                !define URLNAME   "secondlife" -                Caption "Second Life" -                """ -            else: -                # alternate grid viewer -                installer_file = "Second_Life_%(version_dashes)s_(%(grid_caps)s)_Setup.exe" -                grid_vars_template = """ -                OutFile "%(installer_file)s" -                !define INSTFLAGS "%(flags)s" -                !define INSTNAME   "SecondLife%(grid_caps)s" -                !define SHORTCUT   "Second Life (%(grid_caps)s)" -                !define URLNAME   "secondlife%(grid)s" -                !define UNINSTALL_SETTINGS 1 -                Caption "Second Life %(grid)s ${VERSION}" -                """ +         +        if self.channel_type() == 'release': +            substitution_strings['caption'] = CHANNEL_VENDOR_BASE          else: -            # some other channel (grid name not used) -            installer_file = "Second_Life_%(version_dashes)s_%(subchannel_underscores)s_Setup.exe" -            grid_vars_template = """ +            substitution_strings['caption'] = self.app_name() + ' ${VERSION}' + +        inst_vars_template = """              OutFile "%(installer_file)s" -            !define INSTFLAGS "%(flags)s" -            !define INSTNAME   "SecondLife%(channel_oneword)s" -            !define SHORTCUT   "%(channel)s" +            !define INSTNAME   "%(app_name_oneword)s" +            !define SHORTCUT   "%(app_name)s"              !define URLNAME   "secondlife" -            !define UNINSTALL_SETTINGS 1 -            Caption "%(channel)s ${VERSION}" +            Caption "%(caption)s"              """ -        if 'installer_name' in self.args: -            installer_file = self.args['installer_name'] -        else: -            installer_file = installer_file % substitution_strings -        if len(self.args['package_id']) > 0: -            installer_file = installer_file.replace(self.args['package_id'], "") -            installer_file = installer_file.replace(".exe", self.args['package_id'] + ".exe") -        substitution_strings['installer_file'] = installer_file          tempfile = "secondlife_setup_tmp.nsi"          # the following replaces strings in the nsi template @@ -633,7 +613,7 @@ class WindowsManifest(ViewerManifest):          self.replace_in("installers/windows/installer_template.nsi", tempfile, {                  "%%VERSION%%":version_vars,                  "%%SOURCE%%":self.get_src_prefix(), -                "%%GRID_VARS%%":grid_vars_template % substitution_strings, +                "%%INST_VARS%%":inst_vars_template % substitution_strings,                  "%%INSTALL_FILES%%":self.nsi_file_commands(True),                  "%%DELETE_FILES%%":self.nsi_file_commands(False)}) @@ -663,7 +643,7 @@ class WindowsManifest(ViewerManifest):          self.package_file = installer_file -class DarwinManifest(ViewerManifest): +class Darwin_i386_Manifest(ViewerManifest):      def is_packaging_viewer(self):          # darwin requires full app bundle packaging even for debugging.          return True @@ -685,7 +665,7 @@ class DarwinManifest(ViewerManifest):              # most everything goes in the Resources directory              if self.prefix(src="", dst="Resources"): -                super(DarwinManifest, self).construct() +                super(Darwin_i386_Manifest, self).construct()                  if self.prefix("cursors_mac"):                      self.path("*.tif") @@ -821,6 +801,7 @@ class DarwinManifest(ViewerManifest):              self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))      def package_finish(self): +        global CHANNEL_VENDOR_BASE          # Sign the app if requested.          if 'signature' in self.args:              identity = self.args['signature'] @@ -850,17 +831,9 @@ class DarwinManifest(ViewerManifest):          # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning.          #  If we really need differently named volumes, we'll need to create multiple DS_Store file images, or use some other trick. -        volname="Second Life Installer"  # DO NOT CHANGE without understanding comment above +        volname=CHANNEL_VENDOR_BASE+" Installer"  # DO NOT CHANGE without understanding comment above -        if len(self.args['package_id']) > 0: -            imagename = imagename + self.args['package_id'] -        elif self.default_channel(): -            if not self.default_grid(): -                # beta case -                imagename = imagename + '_' + self.args['grid'].upper() -        else: -            # first look, etc -            imagename = imagename + '_' + self.channel_oneword().upper() +        imagename = self.installer_base_name()          sparsename = imagename + ".sparseimage"          finalname = imagename + ".dmg" @@ -894,7 +867,7 @@ class DarwinManifest(ViewerManifest):              # will use the release .DS_Store, and will look broken.              # - Ambroff 2008-08-20              dmg_template = os.path.join( -                'installers', 'darwin', '%s-dmg' % self.channel_lowerword()) +                'installers', 'darwin', '%s-dmg' % self.channel_type())              if not os.path.exists (self.src_path_of(dmg_template)):                  dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') @@ -977,8 +950,9 @@ class LinuxManifest(ViewerManifest):              # recurse              self.end_prefix("res-sdl") -        # Get the icons based on the channel +        # Get the icons based on the channel type          icon_path = self.icon_path() +        print "DEBUG: icon_path '%s'" % icon_path          if self.prefix(src=icon_path, dst="") :              self.path("secondlife_256.png","secondlife_icon.png")              if self.prefix(src="",dst="res-sdl") : @@ -1004,18 +978,7 @@ class LinuxManifest(ViewerManifest):              self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))      def package_finish(self): -        if 'installer_name' in self.args: -            installer_name = self.args['installer_name'] -        else: -            installer_name_components = ['SecondLife_', self.args.get('arch')] -            installer_name_components.extend(self.args['version']) -            installer_name = "_".join(installer_name_components) -            if self.default_channel(): -                if not self.default_grid(): -                    installer_name += '_' + self.args['grid'].upper() -            else: -                installer_name += '_' + self.channel_oneword().upper() -        installer_name = installer_name + self.args['package_id'] +        installer_name = self.installer_base_name()          self.strip_binaries() @@ -1057,9 +1020,9 @@ class LinuxManifest(ViewerManifest):              print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"              self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure -class Linux_i686Manifest(LinuxManifest): +class Linux_i686_Manifest(LinuxManifest):      def construct(self): -        super(Linux_i686Manifest, self).construct() +        super(Linux_i686_Manifest, self).construct()          if self.prefix("../packages/lib/release", dst="lib"):              self.path("libapr-1.so") @@ -1145,9 +1108,9 @@ class Linux_i686Manifest(LinuxManifest):              self.strip_binaries() -class Linux_x86_64Manifest(LinuxManifest): +class Linux_x86_64_Manifest(LinuxManifest):      def construct(self): -        super(Linux_x86_64Manifest, self).construct() +        super(Linux_x86_64_Manifest, self).construct()          # support file for valgrind debug tool          self.path("secondlife-i686.supp") diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index c28ad76c77..c42112af80 100755 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -77,7 +77,8 @@ private:  	void run(void);  	void startDownloading(LLURI const & uri, std::string const & hash);  	void throwOnCurlError(CURLcode code); -	bool validateDownload(void); +	bool validateDownload(const std::string& filePath); +	bool validateOrRemove(const std::string& filePath);  	LOG_CLASS(LLUpdateDownloader::Implementation);  }; @@ -295,9 +296,8 @@ void LLUpdateDownloader::Implementation::resume(void)  			{  				resumeDownloading(fileStatus.st_size);  			} -			else if(!validateDownload()) +			else if(!validateOrRemove(filePath))  			{ -				LLFile::remove(filePath);  				download(LLURI(mDownloadData["url"].asString()),  						 mDownloadData["hash"].asString(),  						 mDownloadData["update_channel"].asString(), @@ -421,19 +421,13 @@ void LLUpdateDownloader::Implementation::run(void)  	if(code == CURLE_OK)  	{  		LLFile::remove(mDownloadRecordPath); -		if(validateDownload()) +		if(validateOrRemove(mDownloadData["path"]))  		{  			LL_INFOS("UpdaterService") << "download successful" << LL_ENDL;  			mClient.downloadComplete(mDownloadData);  		}  		else  		{ -			LL_INFOS("UpdaterService") << "download failed hash check" << LL_ENDL; -			std::string filePath = mDownloadData["path"].asString(); -			if(filePath.size() != 0) -			{ -				LLFile::remove(filePath); -			}  			mClient.downloadError("failed hash check");  		}  	} @@ -449,7 +443,9 @@ void LLUpdateDownloader::Implementation::run(void)  		LLFile::remove(mDownloadRecordPath);  		if(mDownloadData.has("path"))  		{ -			LLFile::remove(mDownloadData["path"].asString()); +			std::string filePath = mDownloadData["path"].asString(); +			LL_INFOS("UpdaterService") << "removing " << filePath << LL_ENDL; +			LLFile::remove(filePath);  		}  		mClient.downloadError("curl error");  	} @@ -561,31 +557,49 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)  	}  } +bool LLUpdateDownloader::Implementation::validateOrRemove(const std::string& filePath) +{ +	bool valid = validateDownload(filePath); +	if (! valid) +	{ +		LL_INFOS("UpdaterService") << "removing " << filePath << LL_ENDL; +		LLFile::remove(filePath); +	} +	return valid; +} -bool LLUpdateDownloader::Implementation::validateDownload(void) +bool LLUpdateDownloader::Implementation::validateDownload(const std::string& filePath)  { -	std::string filePath = mDownloadData["path"].asString();  	llifstream fileStream(filePath, std::ios_base::in | std::ios_base::binary);  	if(!fileStream)  	{ +		LL_INFOS("UpdaterService") << "can't open " << filePath << ", invalid" << LL_ENDL;  		return false;  	}  	std::string hash = mDownloadData["hash"].asString(); -	if(hash.size() != 0) +	if (! hash.empty())  	{ -		LL_INFOS("UpdaterService") << "checking hash..." << LL_ENDL;  		char digest[33];  		LLMD5(fileStream).hex_digest(digest); -		if(hash != digest) +		if (hash == digest) +		{ +			LL_INFOS("UpdaterService") << "verified hash " << hash +									   << " for downloaded " << filePath << LL_ENDL; +			return true; +		} +		else  		{ -			LL_WARNS("UpdaterService") << "download hash mismatch; expected " << hash << -				" but download is " << digest << LL_ENDL; +			LL_WARNS("UpdaterService") << "download hash mismatch for " +									   << filePath << ": expected " << hash +									   << " but computed " << digest << LL_ENDL; +			return false;  		} -		return hash == digest;  	}  	else  	{ +		LL_INFOS("UpdaterService") << "no hash specified for " << filePath +								   << ", unverified" << LL_ENDL;  		return true; // No hash check provided.  	}  } diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 16950e1d62..cb3be5bbdc 100755 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -296,37 +296,49 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)  		update_marker.close();  		// Get the path to the installer file. -		LLSD path = update_info.get("path"); -		if(update_info["current_version"].asString() != ll_get_version()) +		std::string path(update_info.get("path")); +		std::string downloader_version(update_info["current_version"]); +		if (downloader_version != ll_get_version())  		{  			// This viewer is not the same version as the one that downloaded -			// the update.  Do not install this update. -			if(!path.asString().empty()) +			// the update. Do not install this update. +			LL_INFOS("UpdaterService") << "ignoring update downloaded by " +									   << "different viewer version " +									   << downloader_version << LL_ENDL; +			if (! path.empty())  			{ -				LL_INFOS("UpdaterService") << "ignoring update dowloaded by different client version" << LL_ENDL;; -				LLFile::remove(path.asString()); +				LL_INFOS("UpdaterService") << "removing " << path << LL_ENDL; +				LLFile::remove(path);  				LLFile::remove(update_marker_path());  			} -			else -			{ -				; // Nothing to clean up. -			} -			 +  			foundInstall = false;  		}  -		else if(path.isDefined() && !path.asString().empty()) +		else if (path.empty()) +		{ +			LL_WARNS("UpdaterService") << "Marker file " << update_marker_path() +									   << " 'path' entry empty, ignoring" << LL_ENDL; +			foundInstall = false; +		} +		else if (! LLFile::isfile(path)) +		{ +			LL_WARNS("UpdaterService") << "Nonexistent installer " << path +									   << ", ignoring" << LL_ENDL; +			foundInstall = false; +		} +		else  		{  			if(launchInstaller)  			{  				setState(LLUpdaterService::INSTALLING); -				 +  				LLFile::remove(update_marker_path());  				int result = ll_install_update(install_script_path(), -											   update_info["path"].asString(), +											   path,  											   update_info["required"].asBoolean(),  											   install_script_mode());	 -				 +  				if((result == 0) && mAppExitCallback)  				{  					mAppExitCallback(); @@ -360,7 +372,8 @@ bool LLUpdaterServiceImpl::checkForResume()  			LLSD download_info;  			LLSDSerialize::fromXMLDocument(download_info, download_marker_stream);  			download_marker_stream.close(); -			if(download_info["current_version"].asString() == ll_get_version()) +			std::string downloader_version(download_info["current_version"]); +			if (downloader_version == ll_get_version())  			{  				mIsDownloading = true;  				mNewVersion = download_info["update_version"].asString(); @@ -371,10 +384,13 @@ bool LLUpdaterServiceImpl::checkForResume()  			else   			{  				// The viewer that started this download is not the same as this viewer; ignore. -				LL_INFOS("UpdaterService") << "ignoring partial download from different viewer version" << LL_ENDL;; +				LL_INFOS("UpdaterService") << "ignoring partial download " +										   << "from different viewer version " +										   << downloader_version << LL_ENDL;  				std::string path = download_info["path"].asString();  				if(!path.empty())  				{ +					LL_INFOS("UpdaterService") << "removing " << path << LL_ENDL;  					LLFile::remove(path);  				}  				LLFile::remove(download_marker_path); @@ -539,7 +555,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)  		// Check for failed install.  		if(LLFile::isfile(ll_install_failed_marker_path()))  		{ -			LL_DEBUGS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;; +			LL_DEBUGS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;  			int requiredValue = 0;   			{  				llifstream stream(ll_install_failed_marker_path()); @@ -552,12 +568,12 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)  			// TODO: notify the user.  			LL_WARNS("UpdaterService") << "last install attempt failed" << LL_ENDL;;  			LLFile::remove(ll_install_failed_marker_path()); -			 +  			LLSD event;  			event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR);  			event["required"] = LLSD(requiredValue);  			LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event); -			 +  			setState(LLUpdaterService::TERMINAL);  		}  		else diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py index 10d507c9ef..08f4f0ebb9 100755 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -199,6 +199,11 @@ def main(dmgfile, markerfile, markertext):          # 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!) @@ -376,6 +381,13 @@ def main(dmgfile, markerfile, markertext):              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 | 
