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.
This commit is contained in:
Matt Hardcastle 2019-06-22 11:32:36 -07:00
parent 3a5aa4194e
commit 4d28c5fe41
4 changed files with 128 additions and 7 deletions

View file

@ -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

View file

@ -0,0 +1,8 @@
#import <Foundation/Foundation.h>
@interface Interface : NSObject
-(id _Nonnull) initWith:(NSString * _Nonnull) aPathToInterface;
-(NSInteger) getVersion:(out NSError * _Nullable * _Nonnull) anError;
@end

View file

@ -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

View file

@ -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);