Skip to content

Commit

Permalink
Use Sparkle's method for copying updates
Browse files Browse the repository at this point in the history
* Tidy up and remove unused methods in NSApplication_BLTRExtensions
* Use the Sparkle method for copying with authentication as defined n SUPlainInstallerInternals
* Tidy up and remove unused methods from QSUpdateController
* Add extra checks to ensure the update is successful (no more silently dying)
* Add an extra step in the install/update process: copy the update to a writable location (App Support folder)
       * Required so that the permissions can correctly be set on the new update and 'moved' to the right location
  • Loading branch information
pjrobertson committed Oct 7, 2012
1 parent 1dce3cd commit 15fe34d
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 64 deletions.
1 change: 0 additions & 1 deletion Quicksilver/Code-App/QSUpdateController.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
//- (NSArray *)installPlugInFromCompressedFile:(NSString *)path;
//-(float) downloadProgress;
- (void)forceStartupCheck;
- (NSString *)installAppFromCompressedFile:(NSString *)path;
- (NSArray *)extractFilesFromQSPkg:(NSString *)path toPath:(NSString *)tempDirectory;
- (IBAction)threadedRequestedCheckForUpdate:(id)sender;
- (void)finishAppInstall;
Expand Down
63 changes: 30 additions & 33 deletions Quicksilver/Code-App/QSUpdateController.m
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ - (void)finishAppInstall {
update = (selection == NSAlertDefaultReturn);
}

//[self installAppFromCompressedFile:path];
NSString *installPath = nil;
if (update) {
installPath = [self installAppFromDiskImage:path];
Expand All @@ -368,68 +367,66 @@ - (void)finishAppInstall {
[appDownload release], appDownload = nil;
}

- (NSString *)installAppFromCompressedFile:(NSString *)path {
NSFileManager *manager = [NSFileManager defaultManager];

NSString *tempDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:@"QSUpdate"];
[manager createDirectoryAtPath:tempDirectory withIntermediateDirectories:NO attributes:nil error:nil];

[updateTask setName:@"Installing Update"];
[updateTask setStatus:@"Extracting Data"];
[updateTask setProgress:-1.0];
NSArray *extracted = [self extractFilesFromQSPkg:path toPath:tempDirectory];
if ([extracted count] != 1) {
NSLog(@"App Update Error");
return nil;
}

NSString *newAppVersionPath = [tempDirectory stringByAppendingPathComponent:[extracted lastObject]];

[updateTask setStatus:@"Copying Application"];
[NSApp replaceWithUpdateFromPath:newAppVersionPath];
[updateTask setStatus:@"Cleaning Up"];

return newAppVersionPath;
}

- (NSString *)installAppFromDiskImage:(NSString *)path {
NSFileManager *manager = [NSFileManager defaultManager];

// Create a temp directory to mount the .dmg
NSString *tempDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString uniqueString]];
[manager createDirectoryAtPath:tempDirectory withIntermediateDirectories:NO attributes:nil error:nil];
[manager createDirectoryAtPath:tempDirectory withIntermediateDirectories:YES
attributes:nil error:nil];

[updateTask setName:@"Installing Update"];
[updateTask setStatus:@"Verifying Data"];
[updateTask setProgress:-1.0];

// mount the .dmg
NSTask *task = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/hdiutil"
arguments:[NSArray arrayWithObjects:@"attach", path, @"-nobrowse", @"-mountpoint", tempDirectory, nil]];

[task waitUntilExit];

if ([task terminationStatus] != 0)
return nil;

NSArray *extracted = [[manager contentsOfDirectoryAtPath:tempDirectory error:nil] pathsMatchingExtensions:[NSArray arrayWithObject:@"app"]];
if ([extracted count] != 1)
return nil;

NSString *newAppVersionPath = [tempDirectory stringByAppendingPathComponent:[extracted lastObject]];
if (!newAppVersionPath)
NSString *mountedAppPath = [tempDirectory stringByAppendingPathComponent:[extracted lastObject]];
if (!mountedAppPath) {
return nil;
}

// Copy Quicksilver.app from the .dmg to a writeable folder (QS App Support folder)
NSString *tempHoldDir = [QSApplicationSupportPath stringByAppendingPathComponent:[NSString uniqueString]];
[manager createDirectoryAtPath:tempHoldDir withIntermediateDirectories:YES attributes:nil error:nil];
NSString *storedAppPath = [tempHoldDir stringByAppendingPathComponent:[mountedAppPath lastPathComponent]];
NSError *copyErr = nil;
[manager copyItemAtPath:mountedAppPath toPath:storedAppPath error:&copyErr];
if (copyErr) {
NSLog(@"Error: %@",copyErr);
}


// Copy the Application over the current app
[updateTask setStatus:@"Copying Application"];
[NSApp replaceWithUpdateFromPath:newAppVersionPath];
BOOL copySuccess = [NSApp moveToPath:[[NSBundle mainBundle] bundlePath] fromPath:storedAppPath];
[updateTask setStatus:@"Cleaning Up"];

// Unmount .dmg and tidyup
task = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/hdiutil"
arguments:[NSArray arrayWithObjects:@"detach", tempDirectory, nil]];
[task waitUntilExit];
[[NSFileManager defaultManager] removeItemAtPath:tempDirectory error:nil];
[manager removeItemAtPath:tempDirectory error:nil];
[manager removeItemAtPath:tempHoldDir error:nil];

[tempPath release];
tempPath = nil;
return newAppVersionPath;
if(!copySuccess) {
// Move failed, so return nil and display an error message
return nil;
}
return tempHoldDir;
}

- (NSArray *)extractFilesFromQSPkg:(NSString *)path toPath:(NSString *)tempDirectory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@

@interface NSApplication (Relaunching)
- (IBAction)relaunch:(id)sender;
- (BOOL)moveToPath:(NSString *)launchPath fromPath:(NSString *)newPath;
- (void)requestRelaunch:(id)sender;
- (void)relaunchFromPath:(NSString *)path;
- (void)relaunchAfterMovingFromPath:(NSString *)newPath;
- (void)relaunchAtPath:(NSString *)launchPath movedFromPath:(NSString *)newPath;
- (void)replaceWithUpdateFromPath:(NSString *)newPath;
@end

enum {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#import "NSApplication_BLTRExtensions.h"
#import "NSFileManager_BLTRExtensions.h"
#import "NSString_BLTRExtensions.h"
#import "SUPlainInstallerInternals.h"

#import <unistd.h>

@implementation NSApplication (Info)
Expand Down Expand Up @@ -77,37 +79,15 @@ - (void)requestRelaunch:(id)sender {
[self relaunch:self];
}

- (void)relaunchAfterMovingFromPath:(NSString *)newPath {
[self relaunchAtPath:[[NSBundle mainBundle] bundlePath] movedFromPath:newPath];
}

- (NSInteger)moveToPath:(NSString *)launchPath fromPath:(NSString *)newPath {
NSFileManager *manager = [NSFileManager defaultManager];
NSString *tempPath = [[launchPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.old.app",[[NSProcessInfo processInfo] processName]]];
//NSLog(@"temp %@ new %@", tempPath, newPath);
BOOL status;
status = [manager moveItemAtPath:launchPath toPath:tempPath error:nil];
#ifdef DEBUG
if (VERBOSE) NSLog(@"Move Old %@", status ? @"DONE" : @"FAILED");
#endif
status = [manager copyItemAtPath:newPath toPath:launchPath error:nil];
#ifdef DEBUG
if (VERBOSE) NSLog(@"Copy New %@", status ? @"DONE" : @"FAILED");
#endif
status = [manager movePathToTrash:tempPath];
#ifdef DEBUG
if (VERBOSE) NSLog(@"Trash Old %@", status? @"DONE" : @"FAILED");
#endif
return status;
}

- (void)replaceWithUpdateFromPath:(NSString *)newPath {
[self moveToPath:[[NSBundle mainBundle] bundlePath] fromPath:newPath];
// Use a method taken from Sparkle that deals with: Authentication, Quarantine and more
- (BOOL)moveToPath:(NSString *)launchPath fromPath:(NSString *)newPath {
return [SUPlainInstaller copyPathWithAuthentication:newPath overPath:launchPath temporaryName:nil error:nil];
}

- (void)relaunchAtPath:(NSString *)launchPath movedFromPath:(NSString *)newPath {
[self moveToPath:launchPath fromPath:newPath];
[self relaunchFromPath:launchPath];
if([self moveToPath:launchPath fromPath:newPath]) {
[self relaunchFromPath:launchPath];
}
}

- (void)relaunchFromPath:(NSString *)path {
Expand Down

0 comments on commit 15fe34d

Please sign in to comment.