From 7ed13a2ba2f42942a6c85226bfeb5fb08b7176b8 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Tue, 23 Jul 2019 16:56:09 -0700 Subject: [PATCH] auto-updater --- launchers/darwin/CMakeLists.txt | 10 ++- launchers/darwin/src/DownloadLauncher.h | 8 ++ launchers/darwin/src/DownloadLauncher.m | 74 +++++++++++++++++++ launchers/darwin/src/LatestBuildRequest.m | 12 ++- launchers/darwin/src/Launcher.h | 5 +- launchers/darwin/src/Launcher.m | 52 ++++++++----- .../darwin/src/LauncherCommandlineArgs.h | 8 ++ .../darwin/src/LauncherCommandlineArgs.m | 30 ++++++++ launchers/darwin/src/main.mm | 1 + launchers/darwin/src/updater/main.m | 37 +++++++++- 10 files changed, 214 insertions(+), 23 deletions(-) create mode 100644 launchers/darwin/src/DownloadLauncher.h create mode 100644 launchers/darwin/src/DownloadLauncher.m create mode 100644 launchers/darwin/src/LauncherCommandlineArgs.h create mode 100644 launchers/darwin/src/LauncherCommandlineArgs.m diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 6114c656d2..fe7f4298ce 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -20,6 +20,8 @@ set(src_files src/DownloadInterface.m src/DownloadDomainContent.h src/DownloadDomainContent.m + src/DownloadLauncher.h + src/DownloadLauncher.m src/DownloadScripts.h src/DownloadScripts.m src/CredentialsRequest.h @@ -34,6 +36,8 @@ set(src_files src/Interface.m src/ErrorViewController.h src/ErrorViewController.m + src/LauncherCommandlineArgs.h + src/LauncherCommandlineArgs.m src/Settings.h src/Settings.m src/LaunchInterface.h @@ -106,8 +110,12 @@ add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/images "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND updater + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/updater" "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") + install( - TARGETS HQLauncher updater + TARGETS HQLauncher BUNDLE DESTINATION "." COMPONENT applications ) diff --git a/launchers/darwin/src/DownloadLauncher.h b/launchers/darwin/src/DownloadLauncher.h new file mode 100644 index 0000000000..2f97910cd8 --- /dev/null +++ b/launchers/darwin/src/DownloadLauncher.h @@ -0,0 +1,8 @@ +#import + +@interface DownloadLauncher : NSObject { +} + +- (void) downloadLauncher:(NSString*) launcherUrl; + +@end diff --git a/launchers/darwin/src/DownloadLauncher.m b/launchers/darwin/src/DownloadLauncher.m new file mode 100644 index 0000000000..d2538c897b --- /dev/null +++ b/launchers/darwin/src/DownloadLauncher.m @@ -0,0 +1,74 @@ +#import "DownloadLauncher.h" +#import "Launcher.h" + + +@implementation DownloadLauncher + +- (void) downloadLauncher:(NSString *)launcherUrl +{ + NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:launcherUrl] + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:60.0]; + + NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; + NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; + NSURLSessionDownloadTask *downloadTask = [defaultSession downloadTaskWithRequest:request]; + [downloadTask resume]; +} + +-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { + CGFloat prog = (float)totalBytesWritten/totalBytesExpectedToWrite; + NSLog(@"Launcher downloaded %f", (100.0*prog)); + +} + +-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { + // unused in this example +} + +-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { + NSLog(@"Did finish downloading to url"); + NSError *error = nil; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *destinationFileName = downloadTask.originalRequest.URL.lastPathComponent; + NSString* finalFilePath = [[[Launcher sharedLauncher] getDownloadPathForContentAndScripts] stringByAppendingPathComponent:destinationFileName]; + NSURL *destinationURL = [NSURL URLWithString: [finalFilePath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]] relativeToURL: [NSURL URLWithString:@"file://"]]; + NSLog(@"desintation %@", destinationURL); + if([fileManager fileExistsAtPath:[destinationURL path]]) + { + [fileManager removeItemAtURL:destinationURL error:nil]; + } + + NSLog(@"location: %@", location.path); + NSLog(@"destination: %@", destinationURL); + BOOL success = [fileManager moveItemAtURL:location toURL:destinationURL error:&error]; + + + NSLog(success ? @"TRUE" : @"FALSE"); + Launcher* sharedLauncher = [Launcher sharedLauncher]; + + if (error) { + NSLog(@"Download Launcher: failed to move file to destintation -> error: %@", error); + [sharedLauncher displayErrorPage]; + return; + } + NSLog(@"extracting domain content file"); + BOOL extractionSuccessful = [sharedLauncher extractZipFileAtDestination:[sharedLauncher getDownloadPathForContentAndScripts] :[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:destinationFileName]]; + + if (!extractionSuccessful) { + [sharedLauncher displayErrorPage]; + return; + } + NSLog(@"finished extracting content file"); + + + [[Launcher sharedLauncher] runAutoupdater]; +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { + NSLog(@"completed; error: %@", error); + if (error) { + [[Launcher sharedLauncher] displayErrorPage]; + } +} +@end diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index deb6d9795b..a2650a194f 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -58,9 +58,11 @@ NSFileManager* fileManager = [NSFileManager defaultManager]; NSArray *values = [json valueForKey:@"results"]; + NSDictionary *launcherValues = [json valueForKey:@"launcher"]; NSDictionary *value = [values objectAtIndex:0]; - + NSString* launcherVersion = [launcherValues valueForKey:@"version"]; + NSString* launcherUrl = [[launcherValues valueForKey:@"mac"] valueForKey:@"url"]; NSString* buildNumber = [value valueForKey:@"latest_version"]; NSDictionary* installers = [value objectForKey:@"installers"]; NSDictionary* macInstallerObject = [installers objectForKey:@"mac"]; @@ -71,16 +73,22 @@ dispatch_async(dispatch_get_main_queue(), ^{ NSInteger currentVersion = [self getCurrentVersion]; + NSInteger currentLauncherVersion = atoi(LAUNCHER_BUILD_VERSION); + NSLog(@"Latest Build Request -> current launcher version %ld", currentLauncherVersion); + NSLog(@"Latest Build Request -> latest launcher version %ld", launcherVersion.integerValue); + NSLog(@"Latest Build Request -> launcher url %@", launcherUrl); 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); NSLog(@"Latest Build Request -> mac url: %@", macInstallerUrl); BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue); + BOOL latestLauncherVersionAvailable = (currentLauncherVersion != launcherVersion.integerValue); [[Settings sharedSettings] buildVersion:buildNumber.integerValue]; BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist); NSLog(@"Latest Build Request -> SHOULD DOWNLOAD: %@", shouldDownloadInterface ? @"TRUE" : @"FALSE"); - [sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl]; + [sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl + :latestLauncherVersionAvailable :launcherUrl]; }); }]; diff --git a/launchers/darwin/src/Launcher.h b/launchers/darwin/src/Launcher.h index de67850bfe..d20f58dee7 100644 --- a/launchers/darwin/src/Launcher.h +++ b/launchers/darwin/src/Launcher.h @@ -2,6 +2,7 @@ #import "DownloadInterface.h" #import "CredentialsRequest.h" #import "DownloadDomainContent.h" +#import "DownloadLauncher.h" #import "LatestBuildRequest.h" #import "OrganizationRequest.h" #import "DownloadScripts.h" @@ -44,6 +45,7 @@ struct LatestBuildInfo { @property (nonatomic, retain) DownloadInterface* downloadInterface; @property (nonatomic, retain) CredentialsRequest* credentialsRequest; @property (nonatomic, retain) DownloadDomainContent* downloadDomainContent; +@property (nonatomic, retain) DownloadLauncher* downloadLauncher; @property (nonatomic, retain) DownloadScripts* downloadScripts; @property (nonatomic, retain) LatestBuildRequest* latestBuildRequest; @property (nonatomic, retain) OrganizationRequest* organizationRequest; @@ -74,11 +76,12 @@ struct LatestBuildInfo { - (void) showLoginScreen; - (void) restart; - (NSString*) getLauncherPath; +- (void) runAutoupdater; - (ProcessState) currentProccessState; - (void) setCurrentProcessState:(ProcessState) aProcessState; - (void) setLoginErrorState:(LoginError) aLoginError; - (LoginError) getLoginErrorState; -- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl; +- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl; - (void) interfaceFinishedDownloading; - (NSString*) getDownloadPathForContentAndScripts; - (void) launchInterface; diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 1a84e9143d..38027d6fd3 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -3,6 +3,7 @@ #import "SplashScreen.h" #import "LoginScreen.h" #import "DisplayNameScreen.h" +#import "LauncherCommandlineArgs.h" #import "ProcessScreen.h" #import "ErrorViewController.h" #import "Settings.h" @@ -32,6 +33,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; self.username = [[NSString alloc] initWithString:@"Default Property Value"]; self.downloadInterface = [DownloadInterface alloc]; self.downloadDomainContent = [DownloadDomainContent alloc]; + self.downloadLauncher = [DownloadLauncher alloc]; self.credentialsRequest = [CredentialsRequest alloc]; self.latestBuildRequest = [LatestBuildRequest alloc]; self.organizationRequest = [OrganizationRequest alloc]; @@ -362,28 +364,44 @@ static BOOL const DELETE_ZIP_FILES = TRUE; [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: loginScreen]; } -- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl +- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl { - self.shouldDownloadInterface = shouldDownload; - self.interfaceDownloadUrl = downloadUrl; - self.latestBuildRequestFinished = TRUE; - if ([self isLoadedIn]) { - Launcher* sharedLauncher = [Launcher sharedLauncher]; - [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; - if (shouldDownload) { - ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; - [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; - [self startUpdateProgressIndicatorTimer]; - [self.downloadInterface downloadInterface: downloadUrl]; - return; - } - [self interfaceFinishedDownloading]; + NSDictionary* launcherArguments = [LauncherCommandlineArgs arguments]; + if (newLauncherAvailable && ![launcherArguments valueForKey: @"--noUpdate"]) { + [self.downloadLauncher downloadLauncher: launcherUrl]; } else { - [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; - [self showLoginScreen]; + self.shouldDownloadInterface = shouldDownload; + self.interfaceDownloadUrl = downloadUrl; + self.latestBuildRequestFinished = TRUE; + if ([self isLoadedIn]) { + Launcher* sharedLauncher = [Launcher sharedLauncher]; + [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; + if (shouldDownload) { + ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; + [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; + [self startUpdateProgressIndicatorTimer]; + [self.downloadInterface downloadInterface: downloadUrl]; + return; + } + [self interfaceFinishedDownloading]; + } else { + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; + [self showLoginScreen]; + } } } +-(void)runAutoupdater +{ + NSTask* task = [[NSTask alloc] init]; + NSString* newLauncher = [[[Launcher sharedLauncher] getDownloadPathForContentAndScripts] stringByAppendingPathComponent: @"HQ Launcher.app"]; + task.launchPath = [newLauncher stringByAppendingString:@"/Contents/Resources/updater"]; + task.arguments = @[[[NSBundle mainBundle] bundlePath], newLauncher]; + [task launch]; + + [NSApp terminate:self]; +} + -(void)onSplashScreenTimerFinished:(NSTimer *)timer { [self.latestBuildRequest requestLatestBuildInfo]; diff --git a/launchers/darwin/src/LauncherCommandlineArgs.h b/launchers/darwin/src/LauncherCommandlineArgs.h new file mode 100644 index 0000000000..c348e50987 --- /dev/null +++ b/launchers/darwin/src/LauncherCommandlineArgs.h @@ -0,0 +1,8 @@ +#import +#import + +@interface LauncherCommandlineArgs : NSObject { +} ++(NSDictionary*) arguments; +@end + diff --git a/launchers/darwin/src/LauncherCommandlineArgs.m b/launchers/darwin/src/LauncherCommandlineArgs.m new file mode 100644 index 0000000000..0c53da2b71 --- /dev/null +++ b/launchers/darwin/src/LauncherCommandlineArgs.m @@ -0,0 +1,30 @@ +#import "LauncherCommandlineArgs.h" + +@implementation LauncherCommandlineArgs ++(NSDictionary*) arguments +{ + + NSArray* arguments = [[NSProcessInfo processInfo] arguments]; + if (arguments.count < 2) + { + return nil; + } + + NSMutableDictionary* argsDict = [[NSMutableDictionary alloc] init]; + NSMutableArray* args = [arguments mutableCopy]; + + for (NSString* arg in args) + { + if ([arg rangeOfString:@"="].location != NSNotFound && [arg rangeOfString:@"--"].location != NSNotFound) { + NSArray* components = [arg componentsSeparatedByString:@"="]; + NSString* key = [components objectAtIndex:0]; + NSString* value = [components objectAtIndex:1]; + [argsDict setObject:value forKey:key]; + } else if ([arg rangeOfString:@"--"].location != NSNotFound) { + [argsDict setObject:@TRUE forKey:arg]; + } + } + NSLog(@"AGS: %@", argsDict); + return argsDict; +} +@end diff --git a/launchers/darwin/src/main.mm b/launchers/darwin/src/main.mm index b6555aad87..8651ffe3ff 100644 --- a/launchers/darwin/src/main.mm +++ b/launchers/darwin/src/main.mm @@ -1,5 +1,6 @@ #import "Launcher.h" #import "Settings.h" +#import "LauncherCommandlineArgs.h" void redirectLogToDocuments() { diff --git a/launchers/darwin/src/updater/main.m b/launchers/darwin/src/updater/main.m index cef16f1530..31b333c5d9 100644 --- a/launchers/darwin/src/updater/main.m +++ b/launchers/darwin/src/updater/main.m @@ -1,4 +1,37 @@ -int main(int argc, const char* argv[]) +#import +#import + +@interface UpdaterHelper : NSObject ++(NSURL*) NSStringToNSURL: (NSString*) path; +@end + +@implementation UpdaterHelper ++(NSURL*) NSStringToNSURL: (NSString*) path { - NSLog(@"Hello World"); + return [NSURL URLWithString: [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]] relativeToURL: [NSURL URLWithString:@"file://"]]; +} +@end + +int main(int argc, char const* argv[]) +{ + if (argc < 3) + { + NSLog(@"Error: wrong number of arguments"); + return 0; + } + + for (int index = 0; index < argc; index++) { + NSLog(@"argv at index %d = %s", index, argv[index]); + } + NSString* oldLauncher = [NSString stringWithUTF8String:argv[1]]; + NSString* newLauncher = [NSString stringWithUTF8String:argv[2]]; + NSFileManager* fileManager = [NSFileManager defaultManager]; + [fileManager removeItemAtURL:[UpdaterHelper NSStringToNSURL:oldLauncher] error:nil]; + [fileManager moveItemAtURL: [UpdaterHelper NSStringToNSURL: newLauncher] toURL: [UpdaterHelper NSStringToNSURL:oldLauncher] error:nil]; + NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; + NSURL* applicationURL = [UpdaterHelper NSStringToNSURL: [oldLauncher stringByAppendingString: @"/Contents/MacOS/HQ Launcher"]]; + NSArray* arguments =@[]; + NSLog(@"Launcher agruments: %@", arguments); + [workspace launchApplicationAtURL:applicationURL options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:nil]; + return 0; }