From 840cb864a3b41ccff310077eff487c3fa1d6b805 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 5 Jan 2013 09:17:51 -0500 Subject: MAINT-2155: replace embedded mac-updater.app with a Python script. Remove mac-updater subtree from viewer source, along with the update_install bash script that invoked it. Remove all mention of mac-updater in CMakeLists.txt files and in viewer_manifest.py. Change Mac update_install bash script references in viewer_manifest.py and in llupdaterservice.cpp (which invokes it) to new Python update_install.py. Add update_install.py, messageframe.py (which puts up some Tkinter UI) and janitor.py (cloned from vita, it's exactly what we need here). --- .../viewer_components/updater/llupdaterservice.cpp | 4 + .../updater/scripts/darwin/janitor.py | 133 ++++++++ .../updater/scripts/darwin/messageframe.py | 66 ++++ .../updater/scripts/darwin/update_install | 10 - .../updater/scripts/darwin/update_install.py | 336 +++++++++++++++++++++ 5 files changed, 539 insertions(+), 10 deletions(-) create mode 100644 indra/viewer_components/updater/scripts/darwin/janitor.py create mode 100644 indra/viewer_components/updater/scripts/darwin/messageframe.py delete mode 100644 indra/viewer_components/updater/scripts/darwin/update_install create mode 100755 indra/viewer_components/updater/scripts/darwin/update_install.py (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index bc73c72ddc..3fa96dd223 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -60,6 +60,8 @@ namespace { #ifdef LL_WINDOWS std::string scriptFile = "update_install.bat"; +#elif LL_DARWIN + std::string scriptFile = "update_install.py"; #else std::string scriptFile = "update_install"; #endif @@ -71,6 +73,8 @@ namespace #ifdef LL_WINDOWS return LL_COPY_INSTALL_SCRIPT_TO_TEMP; #else + // This is important on Mac because update_install.py looks at its own + // script pathname to discover the viewer app bundle to update. return LL_RUN_INSTALL_SCRIPT_IN_PLACE; #endif }; diff --git a/indra/viewer_components/updater/scripts/darwin/janitor.py b/indra/viewer_components/updater/scripts/darwin/janitor.py new file mode 100644 index 0000000000..cdf33df731 --- /dev/null +++ b/indra/viewer_components/updater/scripts/darwin/janitor.py @@ -0,0 +1,133 @@ +#!/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 new file mode 100644 index 0000000000..8f58848882 --- /dev/null +++ b/indra/viewer_components/updater/scripts/darwin/messageframe.py @@ -0,0 +1,66 @@ +#!/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 b/indra/viewer_components/updater/scripts/darwin/update_install deleted file mode 100644 index e7f36dc5a3..0000000000 --- a/indra/viewer_components/updater/scripts/darwin/update_install +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/bash - -# -# The first argument contains the path to the installer app. The second a path -# to a marker file which should be created if the installer fails.q -# - -cd "$(dirname "$0")" -(../Resources/mac-updater.app/Contents/MacOS/mac-updater -dmg "$1" -name "Second Life Viewer"; if [ $? -ne 0 ]; then echo $3 >> "$2"; fi;) & -exit 0 diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py new file mode 100755 index 0000000000..e8b96e6123 --- /dev/null +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -0,0 +1,336 @@ +#!/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 +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 = "SecondLife Updater" +# Magic bundle identifier used by all Second Life viewer bundles +BUNDLE_IDENTIFIER = "com.secondlife.indra.viewer" + +# 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)) + +# **************************************************************************** +# Main script logic +# **************************************************************************** +def main(dmgfile, markerfile, markertext, appdir=None): + # 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") + try: + os.rename(logname, logname + ".old") + except OSError, err: + # Nonexistence is okay. Anything else, not so much. + if err.errno != errno.EEXIST: + raise + + # 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: + + # 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)) + if not appdir.endswith(".app"): + 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) + 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) + + 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() + 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("Clearing cache...") + + # We don't know whether the previous viewer was old-style or + # new-style (Cocoa). Clear both kinds of caches. + for cachesubdir in "SecondLife", BUNDLE_IDENTIFIER: + wildcard = "~/Library/Caches/%s/*" % cachesubdir + log("rm " + wildcard) + for f in glob.glob(os.path.expanduser(wildcard)): + # Don't try to remove subdirs this way + if os.path.isfile(f): + try: + os.remove(f) + except Exception, err: + log("%s removing %s: %s" % (err.__class__.__name__, f, err)) + + status("Cleaning up...") + + log("touch " + appdir) + os.utime(appdir, None) # set to current time + + command = ["open", appdir] + log(' '.join(command)) + subprocess.check_call(command, stdout=LOGF, stderr=subprocess.STDOUT) + + 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; + # - optionally, the pathname of the Second Life viewer to update. + main(*sys.argv[1:]) -- cgit v1.2.3 From c3542b5e46c6599a4f3003b7a598072c9898412b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 8 Jan 2013 14:50:34 -0500 Subject: MAINT-2155: when permitting missing old logfile, check for ENOENT instead of errno.EEXIST. Sigh. --- indra/viewer_components/updater/scripts/darwin/update_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py index e8b96e6123..87b931fbeb 100755 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -162,7 +162,7 @@ def main(dmgfile, markerfile, markertext, appdir=None): os.rename(logname, logname + ".old") except OSError, err: # Nonexistence is okay. Anything else, not so much. - if err.errno != errno.EEXIST: + if err.errno != errno.ENOENT: raise # Open new updater.log. -- cgit v1.2.3 From 4ca04bd89c3ed2f876ad5780200cdaba5ef469ac Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 8 Jan 2013 22:24:07 -0500 Subject: MAINT-2155: Match window title of mac-updater.app's message window --- indra/viewer_components/updater/scripts/darwin/update_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py index 87b931fbeb..3402f90a2a 100755 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -29,7 +29,7 @@ from janitor import Janitor from messageframe import MessageFrame import Tkinter, tkMessageBox -TITLE = "SecondLife Updater" +TITLE = "Second Life Viewer Updater" # Magic bundle identifier used by all Second Life viewer bundles BUNDLE_IDENTIFIER = "com.secondlife.indra.viewer" -- cgit v1.2.3 From d7e90f4160aaa81e30206c80047b82833c049482 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 7 Feb 2013 11:56:57 -0500 Subject: derive version number from indra/VIEWER_VERSION.txt --- indra/viewer_components/updater/CMakeLists.txt | 7 +++++++ indra/viewer_components/updater/llupdaterservice.cpp | 15 ++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt index ef82290b47..5d84f79dbd 100644 --- a/indra/viewer_components/updater/CMakeLists.txt +++ b/indra/viewer_components/updater/CMakeLists.txt @@ -38,6 +38,13 @@ set(updater_service_HEADER_FILES set_source_files_properties(${updater_service_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties( + llupdaterservice.cpp + PROPERTIES + OBJECT_DEPENDS always_generate_version + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) + list(APPEND updater_service_SOURCE_FILES ${updater_service_HEADER_FILES} diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index bc73c72ddc..d783360f80 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -32,7 +32,6 @@ #include "lltimer.h" #include "llupdatechecker.h" #include "llupdateinstaller.h" -#include "llversionviewer.h" #include #include @@ -44,6 +43,12 @@ #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif +#if ! defined(LL_VIEWER_VERSION_MAJOR) \ + || ! defined(LL_VIEWER_VERSION_MINOR) \ + || ! defined(LL_VIEWER_VERSION_PATCH) \ + || ! defined(LL_VIEWER_VERSION_BUILD) +#error "Version information is undefined" +#endif namespace { @@ -609,10 +614,10 @@ std::string const & ll_get_version(void) { if (version.empty()) { std::ostringstream stream; - stream << LL_VERSION_MAJOR << "." - << LL_VERSION_MINOR << "." - << LL_VERSION_PATCH << "." - << LL_VERSION_BUILD; + stream << LL_VIEWER_VERSION_MAJOR << "." + << LL_VIEWER_VERSION_MINOR << "." + << LL_VIEWER_VERSION_PATCH << "." + << LL_VIEWER_VERSION_BUILD; version = stream.str(); } -- cgit v1.2.3 From 72b4a1962f9f036d2bd8e0094e999d6750a18eae Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 12 Feb 2013 12:42:14 -0500 Subject: correct dependencies for forcing version number recompilations --- indra/viewer_components/updater/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt index 5d84f79dbd..7ab3711fde 100644 --- a/indra/viewer_components/updater/CMakeLists.txt +++ b/indra/viewer_components/updater/CMakeLists.txt @@ -38,6 +38,7 @@ set(updater_service_HEADER_FILES set_source_files_properties(${updater_service_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +add_custom_target(always_generate_version) # force recompilation with version values set_source_files_properties( llupdaterservice.cpp PROPERTIES -- cgit v1.2.3 From c8a588836aedd1d28556b3661c4b41c41d58c858 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 12 Feb 2013 16:33:24 -0500 Subject: remove regeneration control where not needed in updater service --- indra/viewer_components/updater/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt index 7ab3711fde..4343f39e76 100644 --- a/indra/viewer_components/updater/CMakeLists.txt +++ b/indra/viewer_components/updater/CMakeLists.txt @@ -38,11 +38,9 @@ set(updater_service_HEADER_FILES set_source_files_properties(${updater_service_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) -add_custom_target(always_generate_version) # force recompilation with version values set_source_files_properties( llupdaterservice.cpp PROPERTIES - OBJECT_DEPENDS always_generate_version COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake ) -- cgit v1.2.3 From cf1019859def2af4414def7991e95a9020b0688f Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 21 Feb 2013 16:47:52 -0500 Subject: add use of v1.1 update request protocol, with fallback to v1.0 --- indra/viewer_components/updater/CMakeLists.txt | 1 + .../viewer_components/updater/llupdatechecker.cpp | 119 ++++++++++++++++----- indra/viewer_components/updater/llupdatechecker.h | 49 ++++++--- .../updater/llupdatedownloader.cpp | 26 ++--- .../updater/llupdateinstaller.cpp | 2 +- .../viewer_components/updater/llupdaterservice.cpp | 77 ++++++++----- indra/viewer_components/updater/llupdaterservice.h | 14 ++- .../updater/tests/llupdaterservice_test.cpp | 18 +++- 8 files changed, 214 insertions(+), 92 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt index 4343f39e76..c5c78728e7 100644 --- a/indra/viewer_components/updater/CMakeLists.txt +++ b/indra/viewer_components/updater/CMakeLists.txt @@ -19,6 +19,7 @@ include_directories( ${LLPLUGIN_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR}/newview ) set(updater_service_SOURCE_FILES diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 5edbbf9914..6d0758b226 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -62,10 +62,15 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client): } -void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +void LLUpdateChecker::checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) { - mImplementation->checkVersion(protocolVersion, hostUrl, servicePath, channel, version); + mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test); } @@ -74,12 +79,14 @@ void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::str //----------------------------------------------------------------------------- -const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0"; +const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0"; +const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1"; LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client): mClient(client), - mInProgress(false) + mInProgress(false), + mProtocol(sProtocolVersion) { ; // No op. } @@ -91,39 +98,86 @@ LLUpdateChecker::Implementation::~Implementation() } -void LLUpdateChecker::Implementation::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) { llassert(!mInProgress); - if(protocolVersion != sProtocolVersion) throw CheckError("unsupported protocol"); - mInProgress = true; - mVersion = version; - std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version); - LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl; + + mHostUrl = hostUrl; + mServicePath = servicePath; + mChannel = channel; + mVersion = version; + mPlatformVersion = platform_version; + memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); + mWillingToTest = willing_to_test; + + mProtocol = sProtocolVersion; + + std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test); + LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL; mHttpClient.get(checkUrl, this); } void LLUpdateChecker::Implementation::completed(U32 status, - const std::string & reason, - const LLSD & content) + const std::string & reason, + const LLSD & content) { mInProgress = false; - if(status != 200) { - LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl; - mClient.error(reason); - } else if(!content.asBoolean()) { - LL_INFOS("UpdateCheck") << "up to date" << llendl; + if(status != 200) + { + if (status == 404) + { + if (mProtocol == sProtocolVersion) + { + mProtocol = sLegacyProtocolVersion; + std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest); + + LL_WARNS("UpdaterService") + << "update response using " << sProtocolVersion + << " was 404... retry at " << retryUrl + << " with legacy protocol" + << LL_ENDL; + + mHttpClient.get(retryUrl, this); + } + else + { + LL_WARNS("UpdaterService") + << "update response using " << sLegacyProtocolVersion + << " was 404; request failed" + << LL_ENDL; + mClient.error(reason); + } + } + else + { + LL_WARNS("UpdaterService") << "response error " << status << " (" << reason << ")" << LL_ENDL; + mClient.error(reason); + } + } + else if(!content.asBoolean()) + { + LL_INFOS("UpdaterService") << "up to date" << LL_ENDL; mClient.upToDate(); - } else if(content["required"].asBoolean()) { - LL_INFOS("UpdateCheck") << "version invalid" << llendl; + } + else if(content["required"].asBoolean()) + { + LL_INFOS("UpdaterService") << "version invalid" << LL_ENDL; LLURI uri(content["url"].asString()); mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString()); - } else { - LL_INFOS("UpdateCheck") << "newer version " << content["version"].asString() << " available" << llendl; + } + else + { + LL_INFOS("UpdaterService") << "newer version " << content["version"].asString() << " available" << LL_ENDL; LLURI uri(content["url"].asString()); mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString()); } @@ -133,13 +187,18 @@ void LLUpdateChecker::Implementation::completed(U32 status, void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason) { mInProgress = false; - LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl; + LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL; mClient.error(reason); } -std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) { #ifdef LL_WINDOWS static const char * platform = "win"; @@ -162,9 +221,15 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protoc LLSD path; path.append(servicePath); - path.append(protocolVersion); + path.append(mProtocol); path.append(channel); path.append(version); path.append(platform); + if (mProtocol != sLegacyProtocolVersion) + { + path.append(platform_version); + path.append(willing_to_test ? "testok" : "testno"); + path.append((char*)uniqueid); + } return LLURI::buildHTTP(hostUrl, path).asString(); } diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index 23f62a7c5e..b60f21549e 100644 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -29,6 +29,7 @@ #include +#include "llmd5.h" #include "llhttpclient.h" // @@ -37,15 +38,19 @@ class LLUpdateChecker { public: class Client; - class Implementation: - - public LLHTTPClient::Responder + class Implementation: public LLHTTPClient::Responder { public: Implementation(Client & client); ~Implementation(); - void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); + void checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test + ); // Responder: virtual void completed(U32 status, @@ -54,15 +59,28 @@ public: virtual void error(U32 status, const std::string & reason); private: + static const char * sLegacyProtocolVersion; static const char * sProtocolVersion; - + const char* mProtocol; + Client & mClient; LLHTTPClient mHttpClient; - bool mInProgress; - std::string mVersion; - - std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); + bool mInProgress; + std::string mVersion; + std::string mHostUrl; + std::string mServicePath; + std::string mChannel; + std::string mPlatformVersion; + unsigned char mUniqueId[MD5HEX_STR_SIZE]; + bool mWillingToTest; + + std::string buildUrl(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test); LOG_CLASS(LLUpdateChecker::Implementation); }; @@ -74,8 +92,13 @@ public: LLUpdateChecker(Client & client); // Check status of current app on the given host for the channel and version provided. - void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); + void checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test); private: LLPointer mImplementation; diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 75e455e3f6..001dd5ed16 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -301,7 +301,7 @@ void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) llassert(mCurl != 0); mBandwidthLimit = bytesPerSecond; CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); - if(code != CURLE_OK) LL_WARNS("UpdateDownload") << + if(code != CURLE_OK) LL_WARNS("UpdaterService") << "unable to change dowload bandwidth" << LL_ENDL; } else { mBandwidthLimit = bytesPerSecond; @@ -322,13 +322,13 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) size_t lastDigitPos = header.find_last_of("0123456789"); std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1); size_t size = boost::lexical_cast(contentLength); - LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL; + LL_INFOS("UpdaterService") << "download size is " << size << LL_ENDL; mDownloadData["size"] = LLSD(LLSD::Integer(size)); llofstream odataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, odataStream); } catch (std::exception const & e) { - LL_WARNS("UpdateDownload") << "unable to read content length (" + LL_WARNS("UpdaterService") << "unable to read content length (" << e.what() << ")" << LL_ENDL; } } else { @@ -368,7 +368,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); - LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL; + LL_INFOS("UpdaterService") << "progress event " << payload << LL_ENDL; } else { ; // Keep events to a reasonalbe number. } @@ -384,19 +384,19 @@ void LLUpdateDownloader::Implementation::run(void) if(code == CURLE_OK) { LLFile::remove(mDownloadRecordPath); if(validateDownload()) { - LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; + LL_INFOS("UpdaterService") << "download successful" << LL_ENDL; mClient.downloadComplete(mDownloadData); } else { - LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL; + 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"); } } else if(mCancelled && (code == CURLE_WRITE_ERROR)) { - LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL; + LL_INFOS("UpdaterService") << "download canceled by user" << LL_ENDL; // Do not call back client. } else { - LL_WARNS("UpdateDownload") << "download failed with error '" << + LL_WARNS("UpdaterService") << "download failed with error '" << curl_easy_strerror(code) << "'" << LL_ENDL; LLFile::remove(mDownloadRecordPath); if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString()); @@ -446,7 +446,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) { - LL_INFOS("UpdateDownload") << "resuming download from " << mDownloadData["url"].asString() + LL_INFOS("UpdaterService") << "resuming download from " << mDownloadData["url"].asString() << " at byte " << startByte << LL_ENDL; initializeCurlGet(mDownloadData["url"].asString(), false); @@ -476,9 +476,9 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); mDownloadData["path"] = filePath; - LL_INFOS("UpdateDownload") << "downloading " << filePath + LL_INFOS("UpdaterService") << "downloading " << filePath << " from " << uri.asString() << LL_ENDL; - LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL; + LL_INFOS("UpdaterService") << "hash of file is " << hash << LL_ENDL; llofstream dataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, dataStream); @@ -512,11 +512,11 @@ bool LLUpdateDownloader::Implementation::validateDownload(void) std::string hash = mDownloadData["hash"].asString(); if(hash.size() != 0) { - LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL; + LL_INFOS("UpdaterService") << "checking hash..." << LL_ENDL; char digest[33]; LLMD5(fileStream).hex_digest(digest); if(hash != digest) { - LL_WARNS("UpdateDownload") << "download hash mismatch; expeted " << hash << + LL_WARNS("UpdaterService") << "download hash mismatch; expeted " << hash << " but download is " << digest << LL_ENDL; } return hash == digest; diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index 2f87d59373..a0e2c0b362 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -75,7 +75,7 @@ int ll_install_update(std::string const & script, llassert(!"unpossible copy mode"); } - llinfos << "UpdateInstaller: installing " << updatePath << " using " << + LL_INFOS("Updater") << "UpdateInstaller: installing " << updatePath << " using " << actualScriptPath << LL_ENDL; LLProcess::Params params; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index d783360f80..c6c89655d3 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -88,11 +88,14 @@ class LLUpdaterServiceImpl : { static const std::string sListenerName; - std::string mProtocolVersion; - std::string mUrl; - std::string mPath; - std::string mChannel; - std::string mVersion; + std::string mProtocolVersion; + std::string mUrl; + std::string mPath; + std::string mChannel; + std::string mVersion; + std::string mPlatformVersion; + unsigned char mUniqueId[MD5HEX_STR_SIZE]; + bool mWillingToTest; unsigned int mCheckPeriod; bool mIsChecking; @@ -112,11 +115,14 @@ public: LLUpdaterServiceImpl(); virtual ~LLUpdaterServiceImpl(); - void initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version); + void initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string& platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test + ); void setCheckPeriod(unsigned int seconds); void setBandwidthLimit(U64 bytesPerSecond); @@ -174,11 +180,13 @@ LLUpdaterServiceImpl::~LLUpdaterServiceImpl() LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); } -void LLUpdaterServiceImpl::initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version) +void LLUpdaterServiceImpl::initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string & platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test) { if(mIsChecking || mIsDownloading) { @@ -186,11 +194,21 @@ void LLUpdaterServiceImpl::initialize(const std::string& protocol_version, "while updater is running."); } - mProtocolVersion = protocol_version; mUrl = url; mPath = path; mChannel = channel; mVersion = version; + mPlatformVersion = platform_version; + memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); + mWillingToTest = willing_to_test; + LL_DEBUGS("UpdaterService") + << "\n url: " << mUrl + << "\n path: " << mPath + << "\n channel: " << mChannel + << "\n version: " << mVersion + << "\n uniqueid: " << mUniqueId + << "\n willing: " << ( mWillingToTest ? "testok" : "testno" ) + << LL_ENDL; } void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds) @@ -289,7 +307,7 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) // the update. Do not install this update. if(!path.asString().empty()) { - llinfos << "ignoring update dowloaded by different client version" << llendl; + LL_INFOS("UpdaterService") << "ignoring update dowloaded by different client version" << LL_ENDL;; LLFile::remove(path.asString()); LLFile::remove(update_marker_path()); } @@ -317,7 +335,7 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) { mAppExitCallback(); } else if(result != 0) { - llwarns << "failed to run update install script" << LL_ENDL; + LL_WARNS("UpdaterService") << "failed to run update install script" << LL_ENDL; } else { ; // No op. } @@ -352,7 +370,7 @@ bool LLUpdaterServiceImpl::checkForResume() else { // The viewer that started this download is not the same as this viewer; ignore. - llinfos << "ignoring partial download from different viewer version" << llendl; + LL_INFOS("UpdaterService") << "ignoring partial download from different viewer version" << LL_ENDL;; std::string path = download_info["path"].asString(); if(!path.empty()) LLFile::remove(path); LLFile::remove(download_marker_path); @@ -501,8 +519,8 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) if(stream.fail()) requiredValue = 0; } // TODO: notify the user. - llinfos << "found marker " << ll_install_failed_marker_path() << llendl; - llinfos << "last install attempt failed" << llendl; + LL_INFOS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;; + LL_INFOS("UpdaterService") << "last install attempt failed" << LL_ENDL;; LLFile::remove(ll_install_failed_marker_path()); LLSD event; @@ -514,7 +532,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) } else { - mUpdateChecker.checkVersion(mProtocolVersion, mUrl, mPath, mChannel, mVersion); + mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest); setState(LLUpdaterService::CHECKING_FOR_UPDATE); } } @@ -559,13 +577,16 @@ LLUpdaterService::~LLUpdaterService() { } -void LLUpdaterService::initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version) +void LLUpdaterService::initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string& platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test +) { - mImpl->initialize(protocol_version, url, path, channel, version); + mImpl->initialize(url, path, channel, version, platform_version, uniqueid, willing_to_test); } void LLUpdaterService::setCheckPeriod(unsigned int seconds) diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 450f19c1c6..48d3590f1b 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -28,6 +28,7 @@ #include #include +#include "llhasheduniqueid.h" class LLUpdaterServiceImpl; @@ -70,11 +71,14 @@ public: LLUpdaterService(); ~LLUpdaterService(); - void initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version); + void initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string& platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test + ); void setCheckPeriod(unsigned int seconds); void setBandwidthLimit(U64 bytesPerSecond); diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index a49bc4161e..ddaaccc051 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -44,8 +44,13 @@ *****************************************************************************/ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) {} -void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +void LLUpdateChecker::checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) {} LLUpdateDownloader::LLUpdateDownloader(Client & ) {} void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} @@ -171,9 +176,11 @@ namespace tut bool got_usage_error = false; try { - updater.initialize("1.0",test_url, "update" ,test_channel, test_version); + unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111"; + updater.initialize(test_url, "update" ,test_channel, test_version, "1.2.3", id1, true); updater.startChecking(); - updater.initialize("1.0", "other_url", "update", test_channel, test_version); + unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222"; + updater.initialize("other_url", "update", test_channel, test_version, "4.5.6", id2, true); } catch(LLUpdaterService::UsageError) { @@ -187,7 +194,8 @@ namespace tut { DEBUG; LLUpdaterService updater; - updater.initialize("1.0", test_url, "update", test_channel, test_version); + unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333"; + updater.initialize(test_url, "update", test_channel, test_version, "7.8.9", id, true); updater.startChecking(); ensure(updater.isChecking()); updater.stopChecking(); -- cgit v1.2.3 From f76e7cce5f68df3a2fa7874dcb6b0b1cd60d4fa3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 22 Feb 2013 21:06:38 -0500 Subject: MAINT-2328: Mac updater should not clear (part of) viewer cache. Remove the offending code. --- .../updater/scripts/darwin/update_install.py | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py index 3402f90a2a..25efc2b0bc 100755 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -287,21 +287,6 @@ def main(dmgfile, markerfile, markertext, appdir=None): # let our previously-set sys.excepthook handle this raise type, value, traceback - status("Clearing cache...") - - # We don't know whether the previous viewer was old-style or - # new-style (Cocoa). Clear both kinds of caches. - for cachesubdir in "SecondLife", BUNDLE_IDENTIFIER: - wildcard = "~/Library/Caches/%s/*" % cachesubdir - log("rm " + wildcard) - for f in glob.glob(os.path.expanduser(wildcard)): - # Don't try to remove subdirs this way - if os.path.isfile(f): - try: - os.remove(f) - except Exception, err: - log("%s removing %s: %s" % (err.__class__.__name__, f, err)) - status("Cleaning up...") log("touch " + appdir) -- cgit v1.2.3 From fbb9bf89c045e96da00bfbc7f407758c87894e92 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 25 Feb 2013 16:26:40 -0500 Subject: MAINT-2155, DRTVWR-278: Make Mac updater honor app bundle name in .dmg. If you run "/Applications/Second Life Beta Materials.app", and the version manager directs you to update to a .dmg containing a release candidate whose app bundle name is "Second Life Viewer.app", update_install.py used to copy the contents of "Second Life Viewer.app" into "/Applications/Second Life Beta Materials.app". Changed it so that if the application bundle name differs, we leave the running app bundle alone, installing instead to the app bundle name from the .dmg. --- .../updater/scripts/darwin/update_install.py | 98 +++++++++++++++++----- 1 file changed, 75 insertions(+), 23 deletions(-) (limited to 'indra/viewer_components') 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:]) -- cgit v1.2.3 From 49ed1a4e32013cda716998784338a01b12c663ef Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 27 Feb 2013 17:40:39 -0500 Subject: finish changes to update handling, including notices of channel changes --- .../viewer_components/updater/llupdatechecker.cpp | 23 +--- indra/viewer_components/updater/llupdatechecker.h | 14 +-- .../updater/llupdatedownloader.cpp | 135 +++++++++++++++------ .../viewer_components/updater/llupdatedownloader.h | 2 + .../viewer_components/updater/llupdaterservice.cpp | 107 +++++++++------- .../updater/tests/llupdaterservice_test.cpp | 2 +- 6 files changed, 177 insertions(+), 106 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 6d0758b226..734747c811 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -143,8 +143,8 @@ void LLUpdateChecker::Implementation::completed(U32 status, LL_WARNS("UpdaterService") << "update response using " << sProtocolVersion - << " was 404... retry at " << retryUrl - << " with legacy protocol" + << " was 404... retry with legacy protocol" << mProtocol + << "\n at " << retryUrl << LL_ENDL; mHttpClient.get(retryUrl, this); @@ -164,22 +164,9 @@ void LLUpdateChecker::Implementation::completed(U32 status, mClient.error(reason); } } - else if(!content.asBoolean()) - { - LL_INFOS("UpdaterService") << "up to date" << LL_ENDL; - mClient.upToDate(); - } - else if(content["required"].asBoolean()) - { - LL_INFOS("UpdaterService") << "version invalid" << LL_ENDL; - LLURI uri(content["url"].asString()); - mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString()); - } else { - LL_INFOS("UpdaterService") << "newer version " << content["version"].asString() << " available" << LL_ENDL; - LLURI uri(content["url"].asString()); - mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString()); + mClient.response(content); } } @@ -215,8 +202,10 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr { platform = "mac"; } -#else +#elif LL_LINUX static const char * platform = "lnx"; +#else +# error "unsupported platform" #endif LLSD path; diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index b60f21549e..55806137d7 100644 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -117,18 +117,8 @@ public: // An error occurred while checking for an update. virtual void error(std::string const & message) = 0; - // A newer version is available, but the current version may still be used. - virtual void optionalUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) = 0; - - // A newer version is available, and the current version is no longer valid. - virtual void requiredUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) = 0; - - // The checked version is up to date; no newer version exists. - virtual void upToDate(void) = 0; + // A successful response was received from the viewer version manager + virtual void response(LLSD const & content) = 0; }; diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 001dd5ed16..c28ad76c77 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -50,7 +50,9 @@ public: void cancel(void); void download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required); bool isDownloading(void); size_t onHeader(void * header, size_t size); @@ -125,10 +127,12 @@ void LLUpdateDownloader::cancel(void) void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required) { - mImplementation->download(uri, hash, updateVersion, required); + mImplementation->download(uri, hash, updateChannel, updateVersion, info_url, required); } @@ -222,18 +226,28 @@ void LLUpdateDownloader::Implementation::cancel(void) void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required) -{ +{ if(isDownloading()) mClient.downloadError("download in progress"); mDownloadRecordPath = downloadMarkerPath(); mDownloadData = LLSD(); mDownloadData["required"] = required; + mDownloadData["update_channel"] = updateChannel; mDownloadData["update_version"] = updateVersion; - try { + if (!info_url.empty()) + { + mDownloadData["info_url"] = info_url; + } + try + { startDownloading(uri, hash); - } catch(DownloadError const & e) { + } + catch(DownloadError const & e) + { mClient.downloadError(e.what()); } } @@ -249,47 +263,65 @@ void LLUpdateDownloader::Implementation::resume(void) { mCancelled = false; - if(isDownloading()) { + if(isDownloading()) + { mClient.downloadError("download in progress"); } mDownloadRecordPath = downloadMarkerPath(); llifstream dataStream(mDownloadRecordPath); - if(!dataStream) { + if(!dataStream) + { mClient.downloadError("no download marker"); return; } LLSDSerialize::fromXMLDocument(mDownloadData, dataStream); - if(!mDownloadData.asBoolean()) { + if(!mDownloadData.asBoolean()) + { mClient.downloadError("no download information in marker"); return; } std::string filePath = mDownloadData["path"].asString(); - try { - if(LLFile::isfile(filePath)) { + try + { + if(LLFile::isfile(filePath)) + { llstat fileStatus; LLFile::stat(filePath, &fileStatus); - if(fileStatus.st_size != mDownloadData["size"].asInteger()) { + if(fileStatus.st_size != mDownloadData["size"].asInteger()) + { resumeDownloading(fileStatus.st_size); - } else if(!validateDownload()) { + } + else if(!validateDownload()) + { LLFile::remove(filePath); download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), + mDownloadData["update_channel"].asString(), mDownloadData["update_version"].asString(), + mDownloadData["info_url"].asString(), mDownloadData["required"].asBoolean()); - } else { + } + else + { mClient.downloadComplete(mDownloadData); } - } else { + } + else + { download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), + mDownloadData["update_channel"].asString(), mDownloadData["update_version"].asString(), + mDownloadData["info_url"].asString(), mDownloadData["required"].asBoolean()); } - } catch(DownloadError & e) { + } + catch(DownloadError & e) + { mClient.downloadError(e.what()); } } @@ -297,13 +329,18 @@ void LLUpdateDownloader::Implementation::resume(void) void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) { - if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) { + if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) + { llassert(mCurl != 0); mBandwidthLimit = bytesPerSecond; CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); - if(code != CURLE_OK) LL_WARNS("UpdaterService") << - "unable to change dowload bandwidth" << LL_ENDL; - } else { + if(code != CURLE_OK) + { + LL_WARNS("UpdaterService") << "unable to change dowload bandwidth" << LL_ENDL; + } + } + else + { mBandwidthLimit = bytesPerSecond; } } @@ -381,29 +418,44 @@ void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); mDownloadStream.close(); - if(code == CURLE_OK) { + if(code == CURLE_OK) + { LLFile::remove(mDownloadRecordPath); - if(validateDownload()) { + if(validateDownload()) + { LL_INFOS("UpdaterService") << "download successful" << LL_ENDL; mClient.downloadComplete(mDownloadData); - } else { + } + else + { LL_INFOS("UpdaterService") << "download failed hash check" << LL_ENDL; std::string filePath = mDownloadData["path"].asString(); - if(filePath.size() != 0) LLFile::remove(filePath); + if(filePath.size() != 0) + { + LLFile::remove(filePath); + } mClient.downloadError("failed hash check"); } - } else if(mCancelled && (code == CURLE_WRITE_ERROR)) { + } + else if(mCancelled && (code == CURLE_WRITE_ERROR)) + { LL_INFOS("UpdaterService") << "download canceled by user" << LL_ENDL; // Do not call back client. - } else { + } + else + { LL_WARNS("UpdaterService") << "download failed with error '" << curl_easy_strerror(code) << "'" << LL_ENDL; LLFile::remove(mDownloadRecordPath); - if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString()); + if(mDownloadData.has("path")) + { + LLFile::remove(mDownloadData["path"].asString()); + } mClient.downloadError("curl error"); } - if(mHeaderList) { + if(mHeaderList) + { curl_slist_free_all(mHeaderList); mHeaderList = 0; } @@ -421,13 +473,16 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u curl_easy_reset(mCurl); } - if(mCurl == 0) throw DownloadError("failed to initialize curl"); - + if(mCurl == 0) + { + throw DownloadError("failed to initialize curl"); + } throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this)); - if(processHeader) { + if(processHeader) + { throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this)); } @@ -456,7 +511,10 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) boost::format rangeHeaderFormat("Range: bytes=%u-"); rangeHeaderFormat % startByte; mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); - if(mHeaderList == 0) throw DownloadError("cannot add Range header"); + if(mHeaderList == 0) + { + throw DownloadError("cannot add Range header"); + } throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList)); mDownloadStream.open(mDownloadData["path"].asString(), @@ -508,19 +566,26 @@ bool LLUpdateDownloader::Implementation::validateDownload(void) { std::string filePath = mDownloadData["path"].asString(); llifstream fileStream(filePath, std::ios_base::in | std::ios_base::binary); - if(!fileStream) return false; + if(!fileStream) + { + return false; + } std::string hash = mDownloadData["hash"].asString(); - if(hash.size() != 0) { + if(hash.size() != 0) + { LL_INFOS("UpdaterService") << "checking hash..." << LL_ENDL; char digest[33]; LLMD5(fileStream).hex_digest(digest); - if(hash != digest) { - LL_WARNS("UpdaterService") << "download hash mismatch; expeted " << hash << + if(hash != digest) + { + LL_WARNS("UpdaterService") << "download hash mismatch; expected " << hash << " but download is " << digest << LL_ENDL; } return hash == digest; - } else { + } + else + { return true; // No hash check provided. } } diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h index 0d635640cf..f759988f12 100644 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -54,7 +54,9 @@ public: // Start a new download. void download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required=false); // Returns true if a download is in progress. diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index c6c89655d3..324b051b21 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -140,13 +140,9 @@ public: // LLUpdateChecker::Client: virtual void error(std::string const & message); - virtual void optionalUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash); - virtual void requiredUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash); - virtual void upToDate(void); + + // A successful response was received from the viewer version manager + virtual void response(LLSD const & content); // LLUpdateDownloader::Client void downloadComplete(LLSD const & data); @@ -155,6 +151,7 @@ public: bool onMainLoop(LLSD const & event); private: + std::string mNewChannel; std::string mNewVersion; void restartTimer(unsigned int seconds); @@ -334,9 +331,13 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) if((result == 0) && mAppExitCallback) { mAppExitCallback(); - } else if(result != 0) { + } + else if(result != 0) + { LL_WARNS("UpdaterService") << "failed to run update install script" << LL_ENDL; - } else { + } + else + { ; // No op. } } @@ -364,6 +365,7 @@ bool LLUpdaterServiceImpl::checkForResume() { mIsDownloading = true; mNewVersion = download_info["update_version"].asString(); + mNewChannel = download_info["update_channel"].asString(); mUpdateDownloader.resume(); result = true; } @@ -372,7 +374,10 @@ bool LLUpdaterServiceImpl::checkForResume() // 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;; std::string path = download_info["path"].asString(); - if(!path.empty()) LLFile::remove(path); + if(!path.empty()) + { + LLFile::remove(path); + } LLFile::remove(download_marker_path); } } @@ -389,36 +394,43 @@ void LLUpdaterServiceImpl::error(std::string const & message) } } -void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) -{ - stopTimer(); - mNewVersion = newVersion; - mIsDownloading = true; - setState(LLUpdaterService::DOWNLOADING); - mUpdateDownloader.download(uri, hash, newVersion, false); -} - -void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) -{ - stopTimer(); - mNewVersion = newVersion; - mIsDownloading = true; - setState(LLUpdaterService::DOWNLOADING); - mUpdateDownloader.download(uri, hash, newVersion, true); -} - -void LLUpdaterServiceImpl::upToDate(void) +// A successful response was received from the viewer version manager +void LLUpdaterServiceImpl::response(LLSD const & content) { - if(mIsChecking) + if(!content.asBoolean()) // an empty response means "no update" { - restartTimer(mCheckPeriod); - } + LL_INFOS("UpdaterService") << "up to date" << LL_ENDL; + if(mIsChecking) + { + restartTimer(mCheckPeriod); + } - setState(LLUpdaterService::UP_TO_DATE); + setState(LLUpdaterService::UP_TO_DATE); + } + else + { + // there is an update available... + stopTimer(); + mNewChannel = content["channel"].asString(); + if (mNewChannel.empty()) + { + LL_INFOS("UpdaterService") << "no channel supplied, assuming current channel" << LL_ENDL; + mNewChannel = mChannel; + } + mNewVersion = content["version"].asString(); + mIsDownloading = true; + setState(LLUpdaterService::DOWNLOADING); + BOOL required = content["required"].asBoolean(); + LLURI url(content["url"].asString()); + std::string more_info = content["more_info"].asString(); + LL_DEBUGS("UpdaterService") + << "Starting download of " + << ( required ? "required" : "optional" ) << " update " + << "to channel '" << mNewChannel << "' version " << mNewVersion + << "more info '" << more_info << "'" + << LL_ENDL; + mUpdateDownloader.download(url, content["hash"].asString(), mNewChannel, mNewVersion, more_info, required); + } } void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) @@ -436,9 +448,19 @@ void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE); payload["required"] = data["required"]; payload["version"] = mNewVersion; + payload["channel"] = mNewChannel; + payload["info_url"] = data["info_url"]; event["payload"] = payload; + LL_DEBUGS("UpdaterService") + << "Download complete " + << ( data["required"].asBoolean() ? "required" : "optional" ) + << "channel " << mNewChannel + << "version " << mNewVersion + << "info " << data["info_url"].asString() + << LL_ENDL; + LLEventPumps::instance().obtain("mainlooprepeater").post(event); - + setState(LLUpdaterService::TERMINAL); } @@ -512,15 +534,18 @@ 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;; int requiredValue = 0; { llifstream stream(ll_install_failed_marker_path()); stream >> requiredValue; - if(stream.fail()) requiredValue = 0; + if(stream.fail()) + { + requiredValue = 0; + } } // TODO: notify the user. - LL_INFOS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;; - LL_INFOS("UpdaterService") << "last install attempt failed" << LL_ENDL;; + LL_WARNS("UpdaterService") << "last install attempt failed" << LL_ENDL;; LLFile::remove(ll_install_failed_marker_path()); LLSD event; diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index ddaaccc051..51b63dcb7b 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -53,7 +53,7 @@ void LLUpdateChecker::checkVersion(std::string const & hostUrl, bool willing_to_test) {} LLUpdateDownloader::LLUpdateDownloader(Client & ) {} -void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} +void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, std::string const &, std::string const &, bool){} class LLDir_Mock : public LLDir { -- cgit v1.2.3 From 1676dae754d19db28c9efafd90f38d0561fe3d17 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 5 Mar 2013 16:47:03 -0500 Subject: remove old hack for legacy mac updates (no system that needed that will run this version anyway) --- indra/viewer_components/updater/llupdatechecker.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 734747c811..10763b0adc 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -190,18 +190,7 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr #ifdef LL_WINDOWS static const char * platform = "win"; #elif LL_DARWIN - long versMin; - Gestalt(gestaltSystemVersionMinor, &versMin); - - static const char *platform; - if (versMin == 5) //OS 10.5 - { - platform = "mac_legacy"; - } - else - { - platform = "mac"; - } + static const char *platform = "mac"; #elif LL_LINUX static const char * platform = "lnx"; #else -- cgit v1.2.3 From ce73cc392c3f6e2a80c03e30a7dd975408e69f1c Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 6 Mar 2013 15:50:54 -0500 Subject: cosmetic logging fix --- indra/viewer_components/updater/llupdatechecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 10763b0adc..bb171aec01 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -143,7 +143,7 @@ void LLUpdateChecker::Implementation::completed(U32 status, LL_WARNS("UpdaterService") << "update response using " << sProtocolVersion - << " was 404... retry with legacy protocol" << mProtocol + << " was 404... retry with legacy protocol " << mProtocol << "\n at " << retryUrl << LL_ENDL; -- cgit v1.2.3 From 4de02b061411a6647b364754f937de3cfd111810 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 6 Mar 2013 17:39:03 -0500 Subject: more cosmetic logging improvements --- indra/viewer_components/updater/llupdaterservice.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index c1e57122ee..cac6f191df 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -429,9 +429,9 @@ void LLUpdaterServiceImpl::response(LLSD const & content) std::string more_info = content["more_info"].asString(); LL_DEBUGS("UpdaterService") << "Starting download of " - << ( required ? "required" : "optional" ) << " update " - << "to channel '" << mNewChannel << "' version " << mNewVersion - << "more info '" << more_info << "'" + << ( required ? "required" : "optional" ) << " update" + << " to channel '" << mNewChannel << "' version " << mNewVersion + << " more info '" << more_info << "'" << LL_ENDL; mUpdateDownloader.download(url, content["hash"].asString(), mNewChannel, mNewVersion, more_info, required); } @@ -458,9 +458,9 @@ void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) LL_DEBUGS("UpdaterService") << "Download complete " << ( data["required"].asBoolean() ? "required" : "optional" ) - << "channel " << mNewChannel - << "version " << mNewVersion - << "info " << data["info_url"].asString() + << " channel " << mNewChannel + << " version " << mNewVersion + << " info " << data["info_url"].asString() << LL_ENDL; LLEventPumps::instance().obtain("mainlooprepeater").post(event); -- cgit v1.2.3 From 8154621527171267af52a9534e541af1d6c07836 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 26 Mar 2013 18:01:20 -0400 Subject: log any error code and text received as an llsd body in a failure response --- .../viewer_components/updater/llupdatechecker.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index bb171aec01..daa867e692 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -134,6 +134,17 @@ void LLUpdateChecker::Implementation::completed(U32 status, if(status != 200) { + std::string server_error; + if ( content.has("error_code") ) + { + server_error += content["error_code"].asString(); + } + if ( content.has("error_text") ) + { + server_error += server_error.empty() ? "" : ": "; + server_error += content["error_text"].asString(); + } + if (status == 404) { if (mProtocol == sProtocolVersion) @@ -143,7 +154,8 @@ void LLUpdateChecker::Implementation::completed(U32 status, LL_WARNS("UpdaterService") << "update response using " << sProtocolVersion - << " was 404... retry with legacy protocol " << mProtocol + << " was HTTP 404 (" << server_error + << "); retry with legacy protocol " << mProtocol << "\n at " << retryUrl << LL_ENDL; @@ -153,14 +165,18 @@ void LLUpdateChecker::Implementation::completed(U32 status, { LL_WARNS("UpdaterService") << "update response using " << sLegacyProtocolVersion - << " was 404; request failed" + << " was 404 (" << server_error + << "); request failed" << LL_ENDL; mClient.error(reason); } } else { - LL_WARNS("UpdaterService") << "response error " << status << " (" << reason << ")" << LL_ENDL; + LL_WARNS("UpdaterService") << "response error " << status + << " " << reason + << " (" << server_error << ")" + << LL_ENDL; mClient.error(reason); } } -- cgit v1.2.3 From c17db85e73a91c145d6eebe36b3b05e2289deae0 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 27 Mar 2013 13:20:48 -0400 Subject: add platform and platform version to login request parameters for new version manager query --- indra/viewer_components/updater/llupdatechecker.cpp | 20 +++++++------------- indra/viewer_components/updater/llupdatechecker.h | 4 ++++ indra/viewer_components/updater/llupdaterservice.cpp | 11 ++++++++--- indra/viewer_components/updater/llupdaterservice.h | 1 + .../updater/tests/llupdaterservice_test.cpp | 7 ++++--- 5 files changed, 24 insertions(+), 19 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index daa867e692..39f68ac0f5 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -66,11 +66,12 @@ void LLUpdateChecker::checkVersion(std::string const & hostUrl, std::string const & servicePath, std::string const & channel, std::string const & version, + std::string const & platform, std::string const & platform_version, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test) { - mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test); + mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); } @@ -102,6 +103,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, std::string const & servicePath, std::string const & channel, std::string const & version, + std::string const & platform, std::string const & platform_version, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test) @@ -114,13 +116,14 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, mServicePath = servicePath; mChannel = channel; mVersion = version; + mPlatform = platform; mPlatformVersion = platform_version; memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); mWillingToTest = willing_to_test; mProtocol = sProtocolVersion; - std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test); + std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL; mHttpClient.get(checkUrl, this); @@ -150,7 +153,7 @@ void LLUpdateChecker::Implementation::completed(U32 status, if (mProtocol == sProtocolVersion) { mProtocol = sLegacyProtocolVersion; - std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest); + std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); LL_WARNS("UpdaterService") << "update response using " << sProtocolVersion @@ -199,20 +202,11 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr std::string const & servicePath, std::string const & channel, std::string const & version, + std::string const & platform, std::string const & platform_version, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test) { -#ifdef LL_WINDOWS - static const char * platform = "win"; -#elif LL_DARWIN - static const char *platform = "mac"; -#elif LL_LINUX - static const char * platform = "lnx"; -#else -# error "unsupported platform" -#endif - LLSD path; path.append(servicePath); path.append(mProtocol); diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index 55806137d7..8e85587490 100644 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -47,6 +47,7 @@ public: std::string const & servicePath, std::string const & channel, std::string const & version, + std::string const & platform, std::string const & platform_version, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test @@ -70,6 +71,7 @@ public: std::string mHostUrl; std::string mServicePath; std::string mChannel; + std::string mPlatform; std::string mPlatformVersion; unsigned char mUniqueId[MD5HEX_STR_SIZE]; bool mWillingToTest; @@ -78,6 +80,7 @@ public: std::string const & servicePath, std::string const & channel, std::string const & version, + std::string const & platform, std::string const & platform_version, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test); @@ -96,6 +99,7 @@ public: std::string const & servicePath, std::string const & channel, std::string const & version, + std::string const & platform, std::string const & platform_version, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test); diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index cac6f191df..1bd9fa4fc0 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -97,6 +97,7 @@ class LLUpdaterServiceImpl : std::string mPath; std::string mChannel; std::string mVersion; + std::string mPlatform; std::string mPlatformVersion; unsigned char mUniqueId[MD5HEX_STR_SIZE]; bool mWillingToTest; @@ -123,6 +124,7 @@ public: const std::string& path, const std::string& channel, const std::string& version, + const std::string& platform, const std::string& platform_version, const unsigned char uniqueid[MD5HEX_STR_SIZE], const bool& willing_to_test @@ -185,7 +187,8 @@ void LLUpdaterServiceImpl::initialize(const std::string& url, const std::string& path, const std::string& channel, const std::string& version, - const std::string & platform_version, + const std::string& platform, + const std::string& platform_version, const unsigned char uniqueid[MD5HEX_STR_SIZE], const bool& willing_to_test) { @@ -199,6 +202,7 @@ void LLUpdaterServiceImpl::initialize(const std::string& url, mPath = path; mChannel = channel; mVersion = version; + mPlatform = platform; mPlatformVersion = platform_version; memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); mWillingToTest = willing_to_test; @@ -561,7 +565,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) } else { - mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest); + mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); setState(LLUpdaterService::CHECKING_FOR_UPDATE); } } @@ -610,12 +614,13 @@ void LLUpdaterService::initialize(const std::string& url, const std::string& path, const std::string& channel, const std::string& version, + const std::string& platform, const std::string& platform_version, const unsigned char uniqueid[MD5HEX_STR_SIZE], const bool& willing_to_test ) { - mImpl->initialize(url, path, channel, version, platform_version, uniqueid, willing_to_test); + mImpl->initialize(url, path, channel, version, platform, platform_version, uniqueid, willing_to_test); } void LLUpdaterService::setCheckPeriod(unsigned int seconds) diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 48d3590f1b..982f99b861 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -75,6 +75,7 @@ public: const std::string& path, const std::string& channel, const std::string& version, + const std::string& platform, const std::string& platform_version, const unsigned char uniqueid[MD5HEX_STR_SIZE], const bool& willing_to_test diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index a7b8a74b61..4812272ebc 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -48,6 +48,7 @@ void LLUpdateChecker::checkVersion(std::string const & hostUrl, std::string const & servicePath, std::string const & channel, std::string const & version, + std::string const & platform, std::string const & platform_version, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test) @@ -178,10 +179,10 @@ namespace tut try { unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111"; - updater.initialize(test_url, "update" ,test_channel, test_version, "1.2.3", id1, true); + updater.initialize(test_url, "update" ,test_channel, test_version, "win", "1.2.3", id1, true); updater.startChecking(); unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222"; - updater.initialize("other_url", "update", test_channel, test_version, "4.5.6", id2, true); + updater.initialize("other_url", "update", test_channel, test_version, "win", "4.5.6", id2, true); } catch(LLUpdaterService::UsageError) { @@ -196,7 +197,7 @@ namespace tut DEBUG; LLUpdaterService updater; unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333"; - updater.initialize(test_url, "update", test_channel, test_version, "7.8.9", id, true); + updater.initialize(test_url, "update", test_channel, test_version, "win", "7.8.9", id, true); updater.startChecking(); ensure(updater.isChecking()); updater.stopChecking(); -- cgit v1.2.3 From 54e2d2b000f36b35ab5ab53cf3aeee922e54fbe3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 21 Feb 2013 01:13:24 -0500 Subject: MAINT-2389: Change viewer to Boost package without ucontext.h. In autobuild.xml, specify today's build of the Boost package that includes the Boost.Context library, and whose boost::dcoroutines library uses Boost.Context exclusively instead of its previous context-switching underpinnings (source of the ucontext.h dependency). Add BOOST_CONTEXT_LIBRARY to Boost.cmake and Copy3rdPartyLibs.cmake. Link it with the viewer and with the lllogin.cpp test executable. Track new Boost package convention that our (early, unofficial) Boost.Coroutine library is now accessed as boost/dcoroutine/etc.h and boost::dcoroutines::etc. Remove #include from llviewerprecompiledheaders.h and lllogin.cpp: old rule that Boost.Coroutine header must be #included before anything else that might use ucontext.h is gone now that we no longer depend on ucontext.h. In fact remove -D_XOPEN_SOURCE in 00-Common.cmake because that was inserted specifically to work around a known problem with the ucontext.h facilities. --- indra/viewer_components/login/CMakeLists.txt | 5 +++++ indra/viewer_components/login/lllogin.cpp | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt index 7720619df3..28b87bf663 100644 --- a/indra/viewer_components/login/CMakeLists.txt +++ b/indra/viewer_components/login/CMakeLists.txt @@ -46,6 +46,11 @@ if(LL_TESTS) SET(lllogin_TEST_SOURCE_FILES lllogin.cpp ) + set_source_files_properties( + lllogin.cpp + PROPERTIES + LL_TEST_ADDITIONAL_LIBRARIES "${BOOST_CONTEXT_LIBRARY}" + ) LL_ADD_PROJECT_UNIT_TESTS(lllogin "${lllogin_TEST_SOURCE_FILES}") endif(LL_TESTS) diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index bdcb068200..3357ad812d 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -23,7 +23,6 @@ * $/LicenseInfo$ */ -#include #include "linden_common.h" #include "llsd.h" #include "llsdutil.h" -- cgit v1.2.3 From d8ce2ec0a019049b84239f5a0e3a34514b88d247 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 21 Feb 2013 18:57:24 -0500 Subject: MAINT-2389: Tell CMake viewer_components/login depends on Boost.Context This addresses a Linux link failure due to the Linux linker making a single left-to-right pass through libraries. --- indra/viewer_components/login/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt index 28b87bf663..1139fecd16 100644 --- a/indra/viewer_components/login/CMakeLists.txt +++ b/indra/viewer_components/login/CMakeLists.txt @@ -9,6 +9,7 @@ endif(LL_TESTS) include(LLCommon) include(LLMath) include(LLXML) +include(Boost) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -40,6 +41,7 @@ target_link_libraries(lllogin ${LLCOMMON_LIBRARIES} ${LLMATH_LIBRARIES} ${LLXML_LIBRARIES} + ${BOOST_CONTEXT_LIBRARY} ) if(LL_TESTS) -- cgit v1.2.3 From bf6182daa8b4d7cea79310547f71d7a3155e17b0 Mon Sep 17 00:00:00 2001 From: Graham Madarasz Date: Fri, 29 Mar 2013 07:50:08 -0700 Subject: Update Mac and Windows breakpad builds to latest --- indra/viewer_components/CMakeLists.txt | 0 indra/viewer_components/login/CMakeLists.txt | 0 indra/viewer_components/login/lllogin.cpp | 0 indra/viewer_components/login/lllogin.h | 0 indra/viewer_components/login/tests/lllogin_test.cpp | 0 indra/viewer_components/updater/CMakeLists.txt | 0 indra/viewer_components/updater/llupdatechecker.cpp | 0 indra/viewer_components/updater/llupdatechecker.h | 0 indra/viewer_components/updater/llupdatedownloader.cpp | 0 indra/viewer_components/updater/llupdatedownloader.h | 0 indra/viewer_components/updater/llupdateinstaller.cpp | 0 indra/viewer_components/updater/llupdateinstaller.h | 0 indra/viewer_components/updater/llupdaterservice.cpp | 0 indra/viewer_components/updater/llupdaterservice.h | 0 indra/viewer_components/updater/scripts/darwin/update_install | 0 indra/viewer_components/updater/scripts/linux/update_install | 0 indra/viewer_components/updater/tests/llupdaterservice_test.cpp | 0 17 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 indra/viewer_components/CMakeLists.txt mode change 100644 => 100755 indra/viewer_components/login/CMakeLists.txt mode change 100644 => 100755 indra/viewer_components/login/lllogin.cpp mode change 100644 => 100755 indra/viewer_components/login/lllogin.h mode change 100644 => 100755 indra/viewer_components/login/tests/lllogin_test.cpp mode change 100644 => 100755 indra/viewer_components/updater/CMakeLists.txt mode change 100644 => 100755 indra/viewer_components/updater/llupdatechecker.cpp mode change 100644 => 100755 indra/viewer_components/updater/llupdatechecker.h mode change 100644 => 100755 indra/viewer_components/updater/llupdatedownloader.cpp mode change 100644 => 100755 indra/viewer_components/updater/llupdatedownloader.h mode change 100644 => 100755 indra/viewer_components/updater/llupdateinstaller.cpp mode change 100644 => 100755 indra/viewer_components/updater/llupdateinstaller.h mode change 100644 => 100755 indra/viewer_components/updater/llupdaterservice.cpp mode change 100644 => 100755 indra/viewer_components/updater/llupdaterservice.h mode change 100644 => 100755 indra/viewer_components/updater/scripts/darwin/update_install mode change 100644 => 100755 indra/viewer_components/updater/scripts/linux/update_install mode change 100644 => 100755 indra/viewer_components/updater/tests/llupdaterservice_test.cpp (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/CMakeLists.txt b/indra/viewer_components/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp old mode 100644 new mode 100755 diff --git a/indra/viewer_components/login/lllogin.h b/indra/viewer_components/login/lllogin.h old mode 100644 new mode 100755 diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdateinstaller.h b/indra/viewer_components/updater/llupdateinstaller.h old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/scripts/darwin/update_install b/indra/viewer_components/updater/scripts/darwin/update_install old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install old mode 100644 new mode 100755 diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp old mode 100644 new mode 100755 -- cgit v1.2.3 From fc4a6431c958db2d64e096068f4fd2395a53aa54 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 13 May 2013 16:28:50 -0400 Subject: CHOP-942: fix crash if update check times out --- .../viewer_components/updater/llupdatechecker.cpp | 37 ++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'indra/viewer_components') diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 39f68ac0f5..1e768f52d9 100755 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -108,25 +108,30 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test) { - llassert(!mInProgress); - - mInProgress = true; - - mHostUrl = hostUrl; - mServicePath = servicePath; - mChannel = channel; - mVersion = version; - mPlatform = platform; - mPlatformVersion = platform_version; - memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); - mWillingToTest = willing_to_test; + if (!mInProgress) + { + mInProgress = true; + + mHostUrl = hostUrl; + mServicePath = servicePath; + mChannel = channel; + mVersion = version; + mPlatform = platform; + mPlatformVersion = platform_version; + memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); + mWillingToTest = willing_to_test; - mProtocol = sProtocolVersion; + mProtocol = sProtocolVersion; - std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); - LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL; + std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); + LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL; - mHttpClient.get(checkUrl, this); + mHttpClient.get(checkUrl, this); + } + else + { + LL_WARNS("UpdaterService") << "attempting to restart a check when one is in progress; ignored" << LL_ENDL; + } } void LLUpdateChecker::Implementation::completed(U32 status, -- cgit v1.2.3