Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/andymatuschak/Sparkle
Browse files Browse the repository at this point in the history
Conflicts:
	Sparkle.xcodeproj/project.pbxproj
	pt.lproj/SUAutomaticUpdateAlert.xib
	pt_PT.lproj/SUAutomaticUpdateAlert.xib
	tr.lproj/SUAutomaticUpdateAlert.xib
  • Loading branch information
uliwitness committed Oct 11, 2011
2 parents 0bd27c0 + fc725cc commit f6a2e76
Show file tree
Hide file tree
Showing 27 changed files with 2,862 additions and 387 deletions.
1 change: 0 additions & 1 deletion Configurations/ConfigBinaryDelta.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

PRODUCT_NAME = BinaryDelta
GCC_PREFIX_HEADER =
SDKROOT = macosx10.5
MACOSX_DEPLOYMENT_TARGET[arch=i386] = 10.5
MACOSX_DEPLOYMENT_TARGET[arch=ppc64] = 10.5
MACOSX_DEPLOYMENT_TARGET[arch=ppc] = 10.5
Expand Down
2 changes: 1 addition & 1 deletion Configurations/ConfigCommon.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
PREBINDING = NO
ZERO_LINK = NO
CURRENT_PROJECT_VERSION = 1.5
SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk
SDKROOT = macosx10.6
MACOSX_DEPLOYMENT_TARGET[arch=ppc] = 10.4
MACOSX_DEPLOYMENT_TARGET[arch=ppc64] = 10.5
MACOSX_DEPLOYMENT_TARGET[arch=i386] = 10.4
Expand Down
1 change: 1 addition & 0 deletions Configurations/ConfigRelaunch.xcconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Relaunch Tool only

PRODUCT_NAME = finish_installation
SKIP_INSTALL = YES
2 changes: 2 additions & 0 deletions Configurations/ConfigUnitTest.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ WRAPPER_EXTENSION = octest
FRAMEWORK_SEARCH_PATHS = $(DEVELOPER_LIBRARY_DIR)/Frameworks
GCC_PREFIX_HEADER = $(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h
GCC_PRECOMPILE_PREFIX_HEADER = YES
SDKROOT = macosx10.6
MACOSX_DEPLOYMENT_TARGET = 10.6
8 changes: 4 additions & 4 deletions SUAutomaticUpdateDriver.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ - (void)automaticUpdateAlert:(SUAutomaticUpdateAlert *)aua finishedWithChoice:(S
switch (choice)
{
case SUInstallNowChoice:
[self installUpdate];
[self installWithToolAndRelaunch:YES];
break;

case SUInstallLaterChoice:
Expand All @@ -61,15 +61,15 @@ - (void)automaticUpdateAlert:(SUAutomaticUpdateAlert *)aua finishedWithChoice:(S

- (BOOL)shouldInstallSynchronously { return postponingInstallation; }

- (void)installUpdate
- (void)installWithToolAndRelaunch:(BOOL)relaunch
{
showErrors = YES;
[super installUpdate];
[super installWithToolAndRelaunch:relaunch];
}

- (void)applicationWillTerminate:(NSNotification *)note
{
[self installUpdate];
[self installWithToolAndRelaunch:NO];
}

- (void)abortUpdateWithError:(NSError *)error
Expand Down
6 changes: 3 additions & 3 deletions SUBasicUpdateDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@
- (void)unarchiverDidFail:(SUUnarchiver *)ua;
- (void)failedToApplyDeltaUpdate;

- (void)installUpdate;
- (void)installWithToolAndRelaunch:(BOOL)relaunch;
- (void)installerForHost:(SUHost *)host failedWithError:(NSError *)error;

- (void)installAndRelaunchWithTool;
- (void)cleanUp;
- (void)installWithToolAndRelaunch:(BOOL)relaunch;
- (void)cleanUpDownload;

- (void)abortUpdate;
- (void)abortUpdateWithError:(NSError *)error;
Expand Down
117 changes: 59 additions & 58 deletions SUBasicUpdateDriver.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#import "SUPlainInstaller.h"
#import "SUPlainInstallerInternals.h"
#import "SUBinaryDeltaCommon.h"
#import "SUUpdater_Private.h"


@implementation SUBasicUpdateDriver
Expand Down Expand Up @@ -150,17 +151,16 @@ - (void)download:(NSURLDownload *)d decideDestinationWithSuggestedFilename:(NSSt
if ([[name pathExtension] isEqualToString:@"txt"])
name = [name stringByDeletingPathExtension];

// We create a temporary directory in /tmp and stick the file there.
// Not using a GUID here because hdiutil (for DMGs) for some reason chokes on GUIDs. Too long? I really have no idea.
NSString *prefix = [NSString stringWithFormat:@"%@ %@ Update", [host name], [updateItem versionString]];
NSString *desktopFolder = [@"~/Desktop" stringByExpandingTildeInPath];
NSString *downloadFileName = [NSString stringWithFormat:@"%@ %@", [host name], [updateItem versionString]];


[tempDir release];
tempDir = [[desktopFolder stringByAppendingPathComponent:prefix] retain];
tempDir = [[[host appSupportPath] stringByAppendingPathComponent:downloadFileName] retain];
int cnt=1;
while ([[NSFileManager defaultManager] fileExistsAtPath:tempDir] && cnt <= 999)
{
[tempDir release];
tempDir = [[desktopFolder stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %d", prefix, cnt++]] retain];
tempDir = [[[host appSupportPath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %d", downloadFileName, cnt++]] retain];
}

#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
Expand All @@ -170,7 +170,7 @@ - (void)download:(NSURLDownload *)d decideDestinationWithSuggestedFilename:(NSSt
#endif
if (!success)
{
// Okay, something's really broken with /tmp
// Okay, something's really broken with this user's file structure.
[download cancel];
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SUTemporaryDirectoryError userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Can't make a temporary directory for the update download at %@.",tempDir] forKey:NSLocalizedDescriptionKey]]];
}
Expand Down Expand Up @@ -200,9 +200,6 @@ - (void)downloadDidFinish:(NSURLDownload *)d

- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error
{
// Get rid of what we've downloaded so far, if anything.
if (tempDir != nil) // tempDir contains downloadPath, so we implicitly delete both here.
[[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:[tempDir stringByDeletingLastPathComponent] destination:@"" files:[NSArray arrayWithObject:[tempDir lastPathComponent]] tag:NULL];
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:SULocalizedString(@"An error occurred while downloading the update. Please try again later.", nil), NSLocalizedDescriptionKey, [error localizedDescription], NSLocalizedFailureReasonErrorKey, nil]]];
}

Expand Down Expand Up @@ -240,7 +237,7 @@ - (void)failedToApplyDeltaUpdate
- (void)unarchiverDidFinish:(SUUnarchiver *)ua
{
if (ua) { CFRelease(ua); }
[self installUpdate];
[self installWithToolAndRelaunch:YES];
}

- (void)unarchiverDidFail:(SUUnarchiver *)ua
Expand All @@ -257,14 +254,34 @@ - (void)unarchiverDidFail:(SUUnarchiver *)ua

- (BOOL)shouldInstallSynchronously { return NO; }

- (void)installUpdate
- (void)installWithToolAndRelaunch:(BOOL)relaunch
{
if (![updater mayUpdateAndRestart])
{
[self abortUpdate];
return;
}

// Give the host app an opportunity to postpone the install and relaunch.
static BOOL postponedOnce = NO;
if (!postponedOnce && [[updater delegate] respondsToSelector:@selector(updater:shouldPostponeRelaunchForUpdate:untilInvoking:)])
{
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(installWithToolAndRelaunch:)]];
[invocation setSelector:@selector(installWithToolAndRelaunch:)];
[invocation setArgument:&relaunch atIndex:0];
[invocation setTarget:self];
postponedOnce = YES;
if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
return;
}


if ([[updater delegate] respondsToSelector:@selector(updater:willInstallUpdate:)])
[[updater delegate] updater:updater willInstallUpdate:updateItem];

// Copy the relauncher into a temporary directory so we can get to it after the new version's installed.
NSString *relaunchPathToCopy = [SPARKLE_BUNDLE pathForResource:@"finish_installation" ofType:@"app"];
NSString *targetPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[relaunchPathToCopy lastPathComponent]];
NSString *targetPath = [[host appSupportPath] stringByAppendingPathComponent:[relaunchPathToCopy lastPathComponent]];
// Only the paranoid survive: if there's already a stray copy of relaunch there, we would have problems.
NSError *error = nil;
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
Expand All @@ -279,58 +296,41 @@ - (void)installUpdate
else
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:SULocalizedString(@"An error occurred while extracting the archive. Please try again later.", nil), NSLocalizedDescriptionKey, [NSString stringWithFormat:@"Couldn't copy relauncher (%@) to temporary path (%@)! %@", relaunchPathToCopy, targetPath, (error ? [error localizedDescription] : @"")], NSLocalizedFailureReasonErrorKey, nil]]];

[self installAndRelaunchWithTool];
}

- (void)installAndRelaunchWithTool
{
BOOL mayRelaunchAtAll = [updater mayUpdateAndRestart];
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
[[updater delegate] updaterWillRelaunchApplication:updater];

if(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath])
{
// Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin.
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:SULocalizedString(@"An error occurred while relaunching %1$@, but the new version will be available next time you run %1$@.", nil), [host name]], NSLocalizedDescriptionKey, [NSString stringWithFormat:@"Couldn't find the relauncher (expected to find it at %@)", relaunchPath], NSLocalizedFailureReasonErrorKey, nil]]];
// We intentionally don't abandon the update here so that the host won't initiate another.
return;
}

NSString *pathToRelaunch = [host bundlePath];
if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
NSString *relaunchToolPath = [relaunchPath stringByAppendingPathComponent: @"/Contents/MacOS/finish_installation"];
[NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, relaunch ? @"1" : @"0", nil]];

if( mayRelaunchAtAll )
{
// Give the host app an opportunity to postpone the relaunch.
static BOOL postponedOnce = NO;
if (!postponedOnce && [[updater delegate] respondsToSelector:@selector(updater:shouldPostponeRelaunchForUpdate:untilInvoking:)])
{
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(installAndRelaunchWithTool)]];
[invocation setSelector:@selector(installAndRelaunchWithTool)];
[invocation setTarget:self];
postponedOnce = YES;
if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
return;
}

[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
[[updater delegate] updaterWillRelaunchApplication:updater];

if(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath])
{
// Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin.
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:SULocalizedString(@"An error occurred while relaunching %1$@, but the new version will be available next time you run %1$@.", nil), [host name]], NSLocalizedDescriptionKey, [NSString stringWithFormat:@"Couldn't find the relauncher (expected to find it at %@)", relaunchPath], NSLocalizedFailureReasonErrorKey, nil]]];
// We intentionally don't abandon the update here so that the host won't initiate another.
return;
}

NSString *pathToRelaunch = [host bundlePath];
if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
NSString *relaunchToolPath = [relaunchPath stringByAppendingPathComponent: @"/Contents/MacOS/finish_installation"];
[NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, nil]];

[NSApp terminate:self];
}
else
[self abortUpdate];
[NSApp terminate:self];
}

- (void)cleanUp
- (void)cleanUpDownload
{
if (tempDir != nil) // tempDir contains downloadPath, so we implicitly delete both here.
{
BOOL success = NO;
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
[[NSFileManager defaultManager] removeFileAtPath: tempDir handler:nil];
success = [[NSFileManager defaultManager] removeFileAtPath: tempDir handler: nil]; // Clean up the copied relauncher
#else
[[NSFileManager defaultManager] removeItemAtPath: tempDir error:NULL];
NSError * error = nil;
success = [[NSFileManager defaultManager] removeItemAtPath: tempDir error: &error]; // Clean up the copied relauncher
#endif
if( !success )
[[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:[tempDir stringByDeletingLastPathComponent] destination:@"" files:[NSArray arrayWithObject:[tempDir lastPathComponent]] tag:NULL];
}
}

- (void)installerForHost:(SUHost *)aHost failedWithError:(NSError *)error
Expand All @@ -348,6 +348,7 @@ - (void)installerForHost:(SUHost *)aHost failedWithError:(NSError *)error
- (void)abortUpdate
{
[[self retain] autorelease]; // In case the notification center was the last one holding on to us.
[self cleanUpDownload];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super abortUpdate];
}
Expand Down
1 change: 1 addition & 0 deletions SUConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extern NSString *const SUEnableAutomaticChecksKeyOld;
extern NSString *const SUEnableSystemProfilingKey;
extern NSString *const SUSendProfileInfoKey;
extern NSString *const SULastProfileSubmitDateKey;
extern NSString *const SUPromptUserOnFirstLaunchKey;
extern NSString *const SUFixedHTMLDisplaySizeKey;
extern NSString *const SUKeepDownloadOnFailedInstallKey;

Expand Down
1 change: 1 addition & 0 deletions SUConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
NSString *const SUEnableAutomaticChecksKeyOld = @"SUCheckAtStartup";
NSString *const SUSendProfileInfoKey = @"SUSendProfileInfo";
NSString *const SULastProfileSubmitDateKey = @"SULastProfileSubmissionDate";
NSString *const SUPromptUserOnFirstLaunchKey = @"SUPromptUserOnFirstLaunch";
NSString *const SUFixedHTMLDisplaySizeKey = @"SUFixedHTMLDisplaySize";
NSString *const SUKeepDownloadOnFailedInstallKey = @"SUKeepDownloadOnFailedInstall";

Expand Down
1 change: 1 addition & 0 deletions SUHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- (id)initWithBundle:(NSBundle *)aBundle;
- (NSBundle *)bundle;
- (NSString *)bundlePath;
- (NSString *)appSupportPath;
- (NSString *)installationPath;
- (NSString *)name;
- (NSString *)version;
Expand Down
28 changes: 21 additions & 7 deletions SUHost.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#import "SUConstants.h"
#import "SUSystemProfiler.h"
#import <sys/mount.h> // For statfs for isRunningOnReadOnlyVolume
#import "ThreadSafePreferences.h"
#import "SULog.h"


Expand Down Expand Up @@ -46,6 +45,21 @@ - (NSString *)bundlePath
return [bundle bundlePath];
}

- (NSString *)appSupportPath
{
NSArray *appSupportPaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *appSupportPath = nil;
if (!appSupportPaths || [appSupportPaths count] == 0)
{
SULog(@"Failed to find app support directory! Using ~/Library/Application Support...");
appSupportPath = [@"~/Library/Application Support" stringByExpandingTildeInPath];
}
else
appSupportPath = [appSupportPaths objectAtIndex:0];
appSupportPath = [appSupportPath stringByAppendingPathComponent:[self name]];
return appSupportPath;
}

- (NSString *)installationPath
{
#if NORMALIZE_INSTALLED_APP_NAME
Expand Down Expand Up @@ -164,7 +178,7 @@ - (id)objectForUserDefaultsKey:(NSString *)defaultName
if (bundle == [NSBundle mainBundle])
return [[NSUserDefaults standardUserDefaults] objectForKey:defaultName];

CFPropertyListRef obj = ThreadSafePreferences_CopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
CFPropertyListRef obj = CFPreferencesCopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
return [(id)CFMakeCollectable(obj) autorelease];
}

Expand All @@ -177,8 +191,8 @@ - (void)setObject:(id)value forUserDefaultsKey:(NSString *)defaultName;
}
else
{
ThreadSafePreferences_SetValue((CFStringRef)defaultName, value, (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
ThreadSafePreferences_Synchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFPreferencesSetValue((CFStringRef)defaultName, value, (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFPreferencesSynchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
}
}

Expand All @@ -188,7 +202,7 @@ - (BOOL)boolForUserDefaultsKey:(NSString *)defaultName
return [[NSUserDefaults standardUserDefaults] boolForKey:defaultName];

BOOL value;
CFPropertyListRef plr = ThreadSafePreferences_CopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
CFPropertyListRef plr = CFPreferencesCopyAppValue((CFStringRef)defaultName, (CFStringRef)[bundle bundleIdentifier]);
if (plr == NULL)
value = NO;
else
Expand All @@ -208,8 +222,8 @@ - (void)setBool:(BOOL)value forUserDefaultsKey:(NSString *)defaultName
}
else
{
ThreadSafePreferences_SetValue((CFStringRef)defaultName, (CFBooleanRef)[NSNumber numberWithBool:value], (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
ThreadSafePreferences_Synchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFPreferencesSetValue((CFStringRef)defaultName, (CFBooleanRef)[NSNumber numberWithBool:value], (CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFPreferencesSynchronize((CFStringRef)[bundle bundleIdentifier], kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
}
}

Expand Down
5 changes: 3 additions & 2 deletions SUPipedUnarchiver.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ - (void)extractArchivePipingDataToCommand:(NSString *)command
{
// *** GETS CALLED ON NON-MAIN THREAD!!!

SULog(@"Extracting %@ using '%@'",archivePath,command);

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
FILE *fp = NULL, *cmdFP = NULL;

SULog(@"Extracting %@ using '%@'",archivePath,command);

// Get the file size.
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
NSNumber *fs = [[[NSFileManager defaultManager] fileAttributesAtPath:archivePath traverseLink:NO] objectForKey:NSFileSize];
Expand Down Expand Up @@ -98,7 +99,7 @@ - (void)extractArchivePipingDataToCommand:(NSString *)command
finally:
if (fp)
fclose(fp);
[pool drain];
[pool release];
}

- (void)extractTAR
Expand Down
4 changes: 4 additions & 0 deletions SUStatusController.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ - (NSString *)description { return [NSString stringWithFormat:@"%@ <%@, %@>", [s

- (void)awakeFromNib
{
if ([host isBackgroundApplication]) {
[[self window] setLevel:NSFloatingWindowLevel];
}

[[self window] center];
[[self window] setFrameAutosaveName:@"SUStatusFrame"];
[progressBar setUsesThreadedAnimation:YES];
Expand Down
Loading

0 comments on commit f6a2e76

Please sign in to comment.