Skip to content

Commit

Permalink
Merge of changes from SVN repository:
Browse files Browse the repository at this point in the history
- Changed NTSynchronousTask to also give the status return value and direct stderror output to the outputData.
- Changed includes so this builds as part of an app, too, not just as a framework
- Made sure SUAppcast's dealloc releases some leaked ivars.
- Added infoURL, extracted from link, that can point to a "more Info" page for download-less URLs
- Added support for version attribute on item so we can support update notifications that don't include an enclosure (e.g. paid upgrades, or upgrades that would require a system update)
- Added/improved a few description methods to ease debugging.
- Added SULog so one can ask for a special log with additional information when there are update issues.
- Added mayUpdateAndRestart for apps that absolutely, positively can't restart right now (e.g. cuz they're burning a CD and would produce a coaster).
- Added updaterWillRelaunchApplication delegate method, analogous to the notification. Useful to have app delegate quit helper apps during installation.
- Made SUBasicUpdateDriver's abortUpdate implicitly retain/autorelease the update driver, because the notification center otherwise releases it and it goes away, causing crashes in superclass's abortUpdate.
- Merge of SUKeepDownloadOnFailedInstallKey and SUFixedHTMLDisplaySizeKey.
- Avoid a few warnings about missing prototypes
- Be paranoid, hdiutil can verify the download again, so let it. Better for internal apps where we turn off DSA checks, too.
- SUHost has an -installationPath now, independent from the bundlePath, so one can normalize the app name from "MyApp 1.1b4" back to "MyApp" Users assume the file name contains the correct version number when there is one in it. Saves support a few round-trips each time.
- Be better at threading: Try calling non-thread-safe methods on main thread only, and don't assume delegates know when they need to be thread-safe, call them on main thread where possible.
- Added a method to put the old copy of the app in the trash. 1.5git changed in this spot, so I didn't actually merge the code that uses it back in yet.
- Fix version comparison so it doesn't get confused by bracketed build numbers in version strings
- Make sure cancel button is disabled during extraction, otherwise user would crash.
- Don't put auto-update window at floating window level. It's huge and can't be switched to background! If you're an NSBGOnly where you need that, turn it on only in that case, but don't generally do such nonsense.
- Hide release notes view if there aren't any.
- Test whether we are on dial-up before checking for updates in background. It's not nice to cause (possibly expensive) dial-up periodically.
- Temporarily comment out DSA complaints for easier testing.
- Don't store (possibly already invalidated) one-shot NSTimers in an ivar. It's bad style. Retain it instead.
- Decompress some monster expressions with nested method calls in ternary operators and nested in method calls again.
- Don't use implicit "id" for params or return types.
- finish_installation now puts up a progress window, so user knows update is still not finished.
- Use ThreadSafePreferences (included dummy version that uses regular prefs for projects that don't use ThreadSafePreferences).

- Todo later: Change finish_installation to be prettier.
  • Loading branch information
uliwitness committed Dec 4, 2009
1 parent bbcfe7e commit 43a0a7d
Show file tree
Hide file tree
Showing 100 changed files with 1,985 additions and 397 deletions.
15 changes: 15 additions & 0 deletions Elgato/ThreadSafePreferences.h
@@ -0,0 +1,15 @@
// Header that shouldn't be included in anything but the Sparkle finish_installation tool
// because it includes files also used in EyeTV, but doesn't need to be thread safe
// as it's a single-threaded process anyway.

#if !EYETV && !__TOAST__ && !TURBO

#define ThreadSafePreferences_CopyAppValue CFPreferencesCopyAppValue
#define ThreadSafePreferences_SetValue CFPreferencesSetValue
#define ThreadSafePreferences_Synchronize CFPreferencesSynchronize

#else

#error This header shouldn't be included here!

#endif
2 changes: 1 addition & 1 deletion NTSynchronousTask.h
Expand Up @@ -22,7 +22,7 @@


// pass nil for directory if not needed // pass nil for directory if not needed
// returns the result // returns the result
+ (NSData*)task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input; +(int) task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input output: (NSData**)outData;


@end @end


Expand Down
26 changes: 18 additions & 8 deletions NTSynchronousTask.m
Expand Up @@ -6,7 +6,11 @@
// Copyright 2005 Steve Gehrman. All rights reserved. // Copyright 2005 Steve Gehrman. All rights reserved.
// //


#import "Sparkle.h" #import "SUUpdater.h"

#import "SUAppcast.h"
#import "SUAppcastItem.h"
#import "SUVersionComparisonProtocol.h"
#import "NTSynchronousTask.h" #import "NTSynchronousTask.h"


@interface NTSynchronousTask (Private) @interface NTSynchronousTask (Private)
Expand Down Expand Up @@ -44,6 +48,7 @@ - (id)init;


[[self task] setStandardInput:[self inputPipe]]; [[self task] setStandardInput:[self inputPipe]];
[[self task] setStandardOutput:[self outputPipe]]; [[self task] setStandardOutput:[self outputPipe]];
[[self task] setStandardError:[self outputPipe]];
} }


return self; return self;
Expand All @@ -64,32 +69,37 @@ - (void)dealloc
[super dealloc]; [super dealloc];
} }


+ (NSData*)task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input; +(int) task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input output: (NSData**)outData
{ {
// we need this wacky pool here, otherwise we run out of pipes, the pipes are internally autoreleased // we need this wacky pool here, otherwise we run out of pipes, the pipes are internally autoreleased
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSData* result=nil; int taskResult = 0;
if( outData )
*outData = nil;


NS_DURING NS_DURING
{ {
NTSynchronousTask* task = [[NTSynchronousTask alloc] init]; NTSynchronousTask* task = [[NTSynchronousTask alloc] init];


[task run:toolPath directory:currentDirectory withArgs:args input:input]; [task run:toolPath directory:currentDirectory withArgs:args input:input];


if ([task result] == 0) taskResult = [task result];
result = [[task output] retain]; if( outData )
*outData = [[task output] retain];


[task release]; [task release];
} }
NS_HANDLER; NS_HANDLER;
taskResult = errCppGeneral;
NS_ENDHANDLER; NS_ENDHANDLER;


[pool drain]; [pool drain];


// retained above // retained above
[result autorelease]; if( outData )
[*outData autorelease];


return result; return taskResult;
} }


@end @end
Expand Down
20 changes: 19 additions & 1 deletion SUAppcast.m
Expand Up @@ -6,8 +6,15 @@
// Copyright 2006 Andy Matuschak. All rights reserved. // Copyright 2006 Andy Matuschak. All rights reserved.
// //


#import "Sparkle.h" #import "SUUpdater.h"

#import "SUAppcast.h"
#import "SUAppcastItem.h"
#import "SUVersionComparisonProtocol.h"
#import "SUAppcast.h" #import "SUAppcast.h"
#import "SUConstants.h"
#import "SULog.h"



@interface SUAppcast (Private) @interface SUAppcast (Private)
- (void)reportError:(NSError *)error; - (void)reportError:(NSError *)error;
Expand All @@ -19,7 +26,12 @@ @implementation SUAppcast
- (void)dealloc - (void)dealloc
{ {
[items release]; [items release];
items = nil;
[userAgentString release]; [userAgentString release];
userAgentString = nil;
[downloadFilename release];
downloadFilename = nil;

[super dealloc]; [super dealloc];
} }


Expand Down Expand Up @@ -59,6 +71,12 @@ - (void)downloadDidFinish:(NSURLDownload *)download
BOOL failed = NO; BOOL failed = NO;
NSArray *xmlItems = nil; NSArray *xmlItems = nil;
NSMutableArray *appcastItems = [NSMutableArray array]; NSMutableArray *appcastItems = [NSMutableArray array];

#if DEBUG
NSString* debugXML = [NSString stringWithContentsOfFile: downloadFilename encoding: NSUTF8StringEncoding error: nil];
SULog(@"<<<< XML >>>>\n%@\n>>>> XML <<<<", debugXML);
#endif

#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
[[NSFileManager defaultManager] removeFileAtPath:downloadFilename handler:nil]; [[NSFileManager defaultManager] removeFileAtPath:downloadFilename handler:nil];
#else #else
Expand Down
4 changes: 4 additions & 0 deletions SUAppcastItem.h
Expand Up @@ -24,6 +24,8 @@
NSString *displayVersionString; NSString *displayVersionString;


NSDictionary *propertiesDictionary; NSDictionary *propertiesDictionary;

NSURL *infoURL; // UK 2007-08-31
} }


// Initializes with data from a dictionary provided by the RSS class. // Initializes with data from a dictionary provided by the RSS class.
Expand All @@ -43,6 +45,8 @@
// Returns the dictionary provided in initWithDictionary; this might be useful later for extensions. // Returns the dictionary provided in initWithDictionary; this might be useful later for extensions.
- (NSDictionary *)propertiesDictionary; - (NSDictionary *)propertiesDictionary;


- (NSURL *)infoURL; // UK 2007-08-31

@end @end


#endif #endif
32 changes: 29 additions & 3 deletions SUAppcastItem.m
Expand Up @@ -6,7 +6,11 @@
// Copyright 2006 Andy Matuschak. All rights reserved. // Copyright 2006 Andy Matuschak. All rights reserved.
// //


#import "Sparkle.h" #import "SUUpdater.h"

#import "SUAppcast.h"
#import "SUAppcastItem.h"
#import "SUVersionComparisonProtocol.h"
#import "SUAppcastItem.h" #import "SUAppcastItem.h"


@implementation SUAppcastItem @implementation SUAppcastItem
Expand Down Expand Up @@ -101,6 +105,16 @@ - (void)setMinimumSystemVersion:(NSString *)systemVersionString
minimumSystemVersion = [systemVersionString copy]; minimumSystemVersion = [systemVersionString copy];
} }



- (NSURL *)infoURL { return [[infoURL retain] autorelease]; } // UK 2007-08-31 (whole method)

- (void)setInfoURL:(NSURL *)aFileURL // UK 2007-08-31 (whole method)
{
if( aFileURL == infoURL ) return;
[infoURL release];
infoURL = [aFileURL copy];
}

- initWithDictionary:(NSDictionary *)dict - initWithDictionary:(NSDictionary *)dict
{ {
return [self initWithDictionary:dict failureReason:nil]; return [self initWithDictionary:dict failureReason:nil];
Expand Down Expand Up @@ -130,7 +144,9 @@ - (void)setMinimumSystemVersion:(NSString *)systemVersionString
// The big caveat with this is that you can't have underscores in your version strings, as that'll confuse Sparkle. // The big caveat with this is that you can't have underscores in your version strings, as that'll confuse Sparkle.
// Feel free to change the separator string to a hyphen or something more suited to your needs if you like. // Feel free to change the separator string to a hyphen or something more suited to your needs if you like.
NSString *newVersion = [enclosure objectForKey:@"sparkle:version"]; NSString *newVersion = [enclosure objectForKey:@"sparkle:version"];
if (newVersion == nil) // no sparkle:version attribute if( newVersion == nil )
newVersion = [dict objectForKey:@"sparkle:version"]; // UK 2007-08-31 Get version from the item, in case it's a download-less item (i.e. paid upgrade).
if (newVersion == nil) // no sparkle:version attribute anywhere?
{ {
// Separate the url by underscores and take the last component, as that'll be closest to the end, // Separate the url by underscores and take the last component, as that'll be closest to the end,
// then we remove the extension. Hopefully, this will be the version. // then we remove the extension. Hopefully, this will be the version.
Expand Down Expand Up @@ -160,7 +176,16 @@ - (void)setMinimumSystemVersion:(NSString *)systemVersionString
[self setDate:[dict objectForKey:@"pubDate"]]; [self setDate:[dict objectForKey:@"pubDate"]];
[self setItemDescription:[dict objectForKey:@"description"]]; [self setItemDescription:[dict objectForKey:@"description"]];


[self setFileURL:[NSURL URLWithString:[[enclosure objectForKey:@"url"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; NSString* theInfoURL = [dict objectForKey:@"link"];
if( theInfoURL )
{
if( ![theInfoURL isKindOfClass: [NSString class]] )
NSLog(@"SUAppcastItem -initWithDictionary: Info URL is not of valid type.");
else
[self setInfoURL:[NSURL URLWithString:theInfoURL]];
}

[self setFileURL:[NSURL URLWithString:[[enclosure objectForKey:@"url"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
[self setDSASignature:[enclosure objectForKey:@"sparkle:dsaSignature"]]; [self setDSASignature:[enclosure objectForKey:@"sparkle:dsaSignature"]];


[self setVersionString:newVersion]; [self setVersionString:newVersion];
Expand Down Expand Up @@ -193,6 +218,7 @@ - (void)dealloc
[self setFileURL:nil]; [self setFileURL:nil];
[self setVersionString:nil]; [self setVersionString:nil];
[self setDisplayVersionString:nil]; [self setDisplayVersionString:nil];
[self setInfoURL:nil];
[propertiesDictionary release]; [propertiesDictionary release];
[super dealloc]; [super dealloc];
} }
Expand Down
2 changes: 1 addition & 1 deletion SUAutomaticUpdateAlert.m
Expand Up @@ -33,7 +33,7 @@ - (void)dealloc
[super dealloc]; [super dealloc];
} }


- (NSString *)description { return [NSString stringWithFormat:@"%@ <%@>", [self class], [host bundlePath]]; } - (NSString *)description { return [NSString stringWithFormat:@"%@ <%@, %@>", [self class], [host bundlePath], [host installationPath]]; }


- (IBAction)installNow:sender - (IBAction)installNow:sender
{ {
Expand Down
1 change: 1 addition & 0 deletions SUAutomaticUpdateDriver.m
Expand Up @@ -10,6 +10,7 @@


#import "SUAutomaticUpdateAlert.h" #import "SUAutomaticUpdateAlert.h"
#import "SUHost.h" #import "SUHost.h"
#import "SUConstants.h"


@implementation SUAutomaticUpdateDriver @implementation SUAutomaticUpdateDriver


Expand Down
80 changes: 49 additions & 31 deletions SUBasicUpdateDriver.m
Expand Up @@ -13,6 +13,9 @@
#import "SUInstaller.h" #import "SUInstaller.h"
#import "SUStandardVersionComparator.h" #import "SUStandardVersionComparator.h"
#import "SUUnarchiver.h" #import "SUUnarchiver.h"
#import "SUConstants.h"
#import "SULog.h"



@implementation SUBasicUpdateDriver @implementation SUBasicUpdateDriver


Expand Down Expand Up @@ -165,6 +168,7 @@ - (void)download:(NSURLDownload *)d decideDestinationWithSuggestedFilename:(NSSt


- (void)downloadDidFinish:(NSURLDownload *)d - (void)downloadDidFinish:(NSURLDownload *)d
{ {
#if 0 // +++
// New in Sparkle 1.5: we're now checking signatures on all non-secure downloads, where "secure" is defined as both the appcast and the download being transmitted over SSL. // New in Sparkle 1.5: we're now checking signatures on all non-secure downloads, where "secure" is defined as both the appcast and the download being transmitted over SSL.
NSURL *downloadURL = [[d request] URL]; NSURL *downloadURL = [[d request] URL];
if (!(([[downloadURL scheme] isEqualToString:@"https"] && [[appcastURL scheme] isEqualToString:@"https"]) || if (!(([[downloadURL scheme] isEqualToString:@"https"] && [[appcastURL scheme] isEqualToString:@"https"]) ||
Expand All @@ -176,6 +180,7 @@ - (void)downloadDidFinish:(NSURLDownload *)d
return; return;
} }
} }
#endif


[self extractUpdate]; [self extractUpdate];
} }
Expand All @@ -200,7 +205,7 @@ - (void)extractUpdate
SUUnarchiver *unarchiver = [SUUnarchiver unarchiverForPath:downloadPath]; SUUnarchiver *unarchiver = [SUUnarchiver unarchiverForPath:downloadPath];
if (!unarchiver) if (!unarchiver)
{ {
NSLog(@"Sparkle Error: No valid unarchiver for %@!", downloadPath); SULog(@"Sparkle Error: No valid unarchiver for %@!", downloadPath);
[self unarchiverDidFail:nil]; [self unarchiverDidFail:nil];
return; return;
} }
Expand Down Expand Up @@ -231,7 +236,11 @@ - (void)installUpdate
NSString *relaunchPathToCopy = [[NSBundle bundleForClass:[self class]] pathForResource:@"finish_installation" ofType:@""]; NSString *relaunchPathToCopy = [[NSBundle bundleForClass:[self class]] pathForResource:@"finish_installation" ofType:@""];
NSString *appSupportFolder = [[@"~/Library/Application Support/" stringByExpandingTildeInPath] stringByAppendingPathComponent: [host name]]; NSString *appSupportFolder = [[@"~/Library/Application Support/" stringByExpandingTildeInPath] stringByAppendingPathComponent: [host name]];
NSString *targetPath = [appSupportFolder stringByAppendingPathComponent:[relaunchPathToCopy lastPathComponent]]; NSString *targetPath = [appSupportFolder stringByAppendingPathComponent:[relaunchPathToCopy lastPathComponent]];
[[NSFileManager defaultManager] createDirectoryAtPath: targetPath withIntermediateDirectories: YES attributes: [NSDictionary dictionary] error: NULL]; #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
[[NSFileManager defaultManager] createDirectoryAtPath: [targetPath stringByDeletingLastPathComponent] attributes: [NSDictionary dictionary]];
#else
[[NSFileManager defaultManager] createDirectoryAtPath: [targetPath stringByDeletingLastPathComponent] withIntermediateDirectories: YES attributes: [NSDictionary dictionary] error: NULL];
#endif


// Only the paranoid survive: if there's already a stray copy of relaunch there, we would have problems. // Only the paranoid survive: if there's already a stray copy of relaunch there, we would have problems.
NSError *error = nil; NSError *error = nil;
Expand All @@ -251,36 +260,43 @@ - (void)installUpdate


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

postponedOnce = YES;
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self]; if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)]) return;
[[updater delegate] updaterWillRelaunchApplication:updater]; }


if(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath]) [[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
{ if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
// Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin. [[updater delegate] updaterWillRelaunchApplication:updater];
[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(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath])
if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)]) {
pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater]; // Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin.
[NSTask launchedTaskWithLaunchPath:relaunchPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], [downloadPath stringByDeletingLastPathComponent], nil]]; [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.
[NSApp terminate:self]; return;
}

NSString *pathToRelaunch = [host bundlePath];
if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
[NSTask launchedTaskWithLaunchPath:relaunchPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], [downloadPath stringByDeletingLastPathComponent], nil]];

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


- (void)cleanUp - (void)cleanUp
Expand All @@ -295,21 +311,23 @@ - (void)cleanUp
- (void)installerForHost:(SUHost *)aHost failedWithError:(NSError *)error - (void)installerForHost:(SUHost *)aHost failedWithError:(NSError *)error
{ {
if (aHost != host) { return; } if (aHost != host) { return; }
[[NSFileManager defaultManager] removeFileAtPath:relaunchPath handler:NULL]; // Clean up the copied relauncher.
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SUInstallationError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:SULocalizedString(@"An error occurred while installing the update. Please try again later.", nil), NSLocalizedDescriptionKey, [error localizedDescription], NSLocalizedFailureReasonErrorKey, nil]]]; [self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SUInstallationError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:SULocalizedString(@"An error occurred while installing the update. Please try again later.", nil), NSLocalizedDescriptionKey, [error localizedDescription], NSLocalizedFailureReasonErrorKey, nil]]];
} }


- (void)abortUpdate - (void)abortUpdate
{ {
[[self retain] autorelease]; // In case the notification center was the last one holding on to us.
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
[super abortUpdate]; [super abortUpdate];
} }


- (void)abortUpdateWithError:(NSError *)error - (void)abortUpdateWithError:(NSError *)error
{ {
if ([error code] != SUNoUpdateError) // Let's not bother logging this. if ([error code] != SUNoUpdateError) // Let's not bother logging this.
NSLog(@"Sparkle Error: %@", [error localizedDescription]); SULog(@"Sparkle Error: %@", [error localizedDescription]);
if ([error localizedFailureReason]) if ([error localizedFailureReason])
NSLog(@"Sparkle Error (continued): %@", [error localizedFailureReason]); SULog(@"Sparkle Error (continued): %@", [error localizedFailureReason]);
if (download) if (download)
[download cancel]; [download cancel];
[self abortUpdate]; [self abortUpdate];
Expand Down

0 comments on commit 43a0a7d

Please sign in to comment.