From 4d28c5fe412ae1f3df98ccf1edf1f6660211b0a5 Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Sat, 22 Jun 2019 11:32:36 -0700 Subject: [PATCH] Use version from Interface in macOS HQ Launcher Prior to this change the macOS HQ Launcher used the version from the settings files. Pull this information in the settings file could result in a situation where the setting file was updated, but interface wasn't. When the launcher ran a second time it would check the settings file and think Interface was updated even though it wasn't. This change resolves the issue by asking interface for its version directly. In the event that Interface doesn't response with a version number HQ Launcher knows how to interoperate HQ Launcher will fall back to using the settings file. Known Issues --- 1) Interface reports different version number formats depending on how its built. A stable interface for getting the build version from interface should be added. --- launchers/darwin/CMakeLists.txt | 2 + launchers/darwin/src/Interface.h | 8 ++ launchers/darwin/src/Interface.m | 100 ++++++++++++++++++++++ launchers/darwin/src/LatestBuildRequest.m | 25 ++++-- 4 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 launchers/darwin/src/Interface.h create mode 100644 launchers/darwin/src/Interface.m diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 76d209d89d..a3fc0dc7c1 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -27,6 +27,8 @@ set(src_files src/LatestBuildRequest.m src/OrganizationRequest.m src/OrganizationRequest.h + src/Interface.h + src/Interface.m src/ErrorViewController.h src/ErrorViewController.m src/Settings.h diff --git a/launchers/darwin/src/Interface.h b/launchers/darwin/src/Interface.h new file mode 100644 index 0000000000..c142aeecf5 --- /dev/null +++ b/launchers/darwin/src/Interface.h @@ -0,0 +1,8 @@ +#import + +@interface Interface : NSObject + +-(id _Nonnull) initWith:(NSString * _Nonnull) aPathToInterface; +-(NSInteger) getVersion:(out NSError * _Nullable * _Nonnull) anError; + +@end diff --git a/launchers/darwin/src/Interface.m b/launchers/darwin/src/Interface.m new file mode 100644 index 0000000000..b007e7faa5 --- /dev/null +++ b/launchers/darwin/src/Interface.m @@ -0,0 +1,100 @@ +#import "Interface.h" + +@implementation Interface +{ + NSString *pathTo; +} + +-(id) initWith:(NSString*)aPathToInterface +{ + [self init]; + self->pathTo = [NSString stringWithFormat:@"%@/Contents/MacOS/interface", aPathToInterface]; + return self; +} + +-(NSInteger) getVersion:(out NSError * _Nullable *) outError +{ + NSTask * interface = [[NSTask alloc] init]; + NSPipe * standardOut = [NSPipe pipe]; + + interface.launchPath = self->pathTo; + interface.arguments = @[ @"--version" ]; + interface.standardOutput = standardOut; + + NSLog(@"calling interface at %@", self->pathTo); + + if (@available(macOS 10.13, *)) { + NSError *error = nil; + if (![interface launchAndReturnError:&error]) { + *outError = [NSError errorWithDomain:@"interface" + code:-1 + userInfo:@{NSUnderlyingErrorKey: error}]; + return 0; + } + } else { + NSError *error = nil; + [interface launch]; + [interface waitUntilExit]; + if (0 != [interface terminationStatus]) { + *outError = [NSError errorWithDomain:@"interface" + code:-1 + userInfo:@{NSUnderlyingErrorKey: error}]; + return 0; + } + } + + NSFileHandle * fh = [standardOut fileHandleForReading]; + NSData * data = [fh readDataToEndOfFile]; + NSString * output = [NSString stringWithUTF8String:[data bytes]]; + if (output == nil) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't start interface", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-1 + userInfo:userInfo]; + return 0; + } + + // Interface returns the build version as a string like this: + // "Interface 33333-DEADBEEF". This code grabs the substring + // between "Interface " and the hyphon ("-") + NSRange start = [output rangeOfString:@"Interface "]; + if (start.length == 0) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-2 + userInfo:userInfo]; + return 0; + } + NSRange end = [output rangeOfString:@"-"]; + if (end.length == 0) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-2 + userInfo:userInfo]; + return 0; + } + NSRange subRange = {start.length, end.location - start.length}; + NSString * versionStr; + @try { + versionStr = [output substringWithRange:subRange]; + } + @catch (NSException *) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-2 + userInfo:userInfo]; + return 0; + } + + return versionStr.integerValue; +} + +@end diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 5119efa8f6..21f63425ab 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -1,9 +1,22 @@ #import "LatestBuildRequest.h" #import "Launcher.h" #import "Settings.h" +#import "Interface.h" @implementation LatestBuildRequest +- (NSInteger) getCurrentVersion { + NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; + NSError * error = nil; + Interface * interface = [[Interface alloc] initWith:interfaceAppPath]; + NSInteger currentVersion = [interface getVersion:&error]; + if (currentVersion == 0 && error != nil) { + NSLog(@"can't get version from interface, falling back to settings: %@", error); + currentVersion = [Settings.sharedSettings latestBuildVersion]; + } + return currentVersion; +} + - (void) requestLatestBuildInfo { NSMutableURLRequest *request = [NSMutableURLRequest new]; [request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]]; @@ -45,8 +58,7 @@ BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]]; dispatch_async(dispatch_get_main_queue(), ^{ - Settings* settings = [Settings sharedSettings]; - NSInteger currentVersion = [settings latestBuildVersion]; + NSInteger currentVersion = [self getCurrentVersion]; NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE"); NSLog(@"Latest Build Request -> current version: %ld", currentVersion); NSLog(@"Latest Build Request -> latest version: %ld", buildNumber.integerValue); @@ -105,11 +117,10 @@ NSDictionary* macInstallerObject = [installers objectForKey:@"mac"]; NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"]; - BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]]; - - Settings* settings = [Settings sharedSettings]; - NSInteger currentVersion = [settings latestBuildVersion]; - BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue); + NSString* interfaceAppPath = [[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; + BOOL appDirectoryExist = [fileManager fileExistsAtPath:interfaceAppPath]; + + BOOL latestVersionAvailable = ([self getCurrentVersion] != buildNumber.integerValue); [[Settings sharedSettings] buildVersion:buildNumber.integerValue]; BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist);