Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

- More WIP creating finish_installation that waits

for quit, updates and relaunches the app, so
updates don't happen while app is still running.
NSBundle gets royally confused and points to the
old path (loading new NIBs into the old app in the
worst case) when you move a running app.
- Temp folder is now user's desktop, as
NSTemporaryDirectory() doesn't stay the same
between two separate apps, and may be emptied on quit.
- Relaunch gets created in App Support now, for
same reasons as above.
- Less dependency on prefix headers, that only leads
to lazy, un-reusable code.
  • Loading branch information...
commit bbcfe7edf4b2d1b2fd5a3e524182e25f9efd9157 1 parent a11578a
@uliwitness uliwitness authored
View
2  Configurations/ConfigRelaunch.xcconfig
@@ -1,3 +1,3 @@
// Relaunch Tool only
-PRODUCT_NAME = relaunch
+PRODUCT_NAME = finish_installation
View
7 SUAutomaticUpdateDriver.m
@@ -71,13 +71,6 @@ - (void)applicationWillTerminate:(NSNotification *)note
[self installUpdate];
}
-- (void)installerFinishedForHost:(SUHost *)aHost
-{
- if (aHost != host) { return; }
- if (!postponingInstallation)
- [self relaunchHostApp];
-}
-
- (void)abortUpdateWithError:(NSError *)error
{
if (showErrors)
View
3  SUBasicUpdateDriver.h
@@ -44,10 +44,9 @@
- (void)unarchiverDidFail:(SUUnarchiver *)ua;
- (void)installUpdate;
-- (void)installerFinishedForHost:(SUHost *)host;
- (void)installerForHost:(SUHost *)host failedWithError:(NSError *)error;
-- (void)relaunchHostApp;
+- (void)installAndRelaunchWithTool;
- (void)cleanUp;
- (void)abortUpdate;
View
26 SUBasicUpdateDriver.m
@@ -139,11 +139,12 @@ - (void)download:(NSURLDownload *)d decideDestinationWithSuggestedFilename:(NSSt
// 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], [host version]];
- NSString *tempDir = [NSTemporaryDirectory() stringByAppendingPathComponent:prefix];
+ NSString *desktopFolder = [@"~/Desktop" stringByExpandingTildeInPath];
+ NSString *tempDir = [desktopFolder stringByAppendingPathComponent:prefix];
int cnt=1;
while ([[NSFileManager defaultManager] fileExistsAtPath:tempDir] && cnt <= 999)
{
- tempDir = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %d", prefix, cnt++]];
+ tempDir = [desktopFolder stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %d", prefix, cnt++]];
}
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
@@ -227,8 +228,11 @@ - (void)installUpdate
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 = [[NSBundle bundleForClass:[self class]] pathForResource:@"relaunch" ofType:@""];
- NSString *targetPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[relaunchPathToCopy lastPathComponent]];
+ NSString *relaunchPathToCopy = [[NSBundle bundleForClass:[self class]] pathForResource:@"finish_installation" ofType:@""];
+ NSString *appSupportFolder = [[@"~/Library/Application Support/" stringByExpandingTildeInPath] stringByAppendingPathComponent: [host name]];
+ NSString *targetPath = [appSupportFolder stringByAppendingPathComponent:[relaunchPathToCopy lastPathComponent]];
+ [[NSFileManager defaultManager] createDirectoryAtPath: targetPath withIntermediateDirectories: YES attributes: [NSDictionary dictionary] error: NULL];
+
// 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
@@ -242,16 +246,10 @@ - (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]]];
- [SUInstaller installFromUpdateFolder:[downloadPath stringByDeletingLastPathComponent] overHost:host delegate:self synchronously:[self shouldInstallSynchronously] versionComparator:[self _versionComparator]];
-}
-
-- (void)installerFinishedForHost:(SUHost *)aHost
-{
- if (aHost != host) { return; }
- [self relaunchHostApp];
+ [self installAndRelaunchWithTool];
}
-- (void)relaunchHostApp
+- (void)installAndRelaunchWithTool
{
// Give the host app an opportunity to postpone the relaunch.
static BOOL postponedOnce = NO;
@@ -264,8 +262,6 @@ - (void)relaunchHostApp
if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
return;
}
-
- [self cleanUp]; // Clean up the download and extracted files.
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
@@ -282,7 +278,7 @@ - (void)relaunchHostApp
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]], nil]];
+ [NSTask launchedTaskWithLaunchPath:relaunchPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], [downloadPath stringByDeletingLastPathComponent], nil]];
[NSApp terminate:self];
}
View
1  SUHost.m
@@ -7,6 +7,7 @@
#import "SUHost.h"
+#import "SUConstants.h"
#import "SUSystemProfiler.h"
#import <sys/mount.h> // For statfs for isRunningOnReadOnlyVolume
View
12 SUInstaller.m
@@ -9,7 +9,8 @@
#import "SUInstaller.h"
#import "SUPlainInstaller.h"
#import "SUPackageInstaller.h"
-#import "SUHost.h"
+#import "SUHost.h"
+#import "SUConstants.h"
@implementation SUInstaller
@@ -36,10 +37,13 @@ + (BOOL)_isAliasFolderAtPath:(NSString *)path
+ (void)installFromUpdateFolder:(NSString *)updateFolder overHost:(SUHost *)host delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator
{
// Search subdirectories for the application
- NSString *currentFile, *newAppDownloadPath = nil, *bundleFileName = [[host bundlePath] lastPathComponent], *alternateBundleFileName = [[host name] stringByAppendingPathExtension:[[host bundlePath] pathExtension]];
+ NSString *currentFile, *newAppDownloadPath = nil,
+ *bundleFileName = [[host bundlePath] lastPathComponent],
+ *alternateBundleFileName = [[host name] stringByAppendingPathExtension: [[host bundlePath] pathExtension]];
BOOL isPackage = NO;
NSString *fallbackPackagePath = nil;
- NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:updateFolder];
+ NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath: updateFolder];
+
while ((currentFile = [dirEnum nextObject]))
{
NSString *currentPath = [updateFolder stringByAppendingPathComponent:currentFile];
@@ -81,7 +85,7 @@ + (void)installFromUpdateFolder:(NSString *)updateFolder overHost:(SUHost *)host
if ([self _isAliasFolderAtPath:currentPath])
[dirEnum skipDescendents];
}
-
+
// We don't have a valid path. Try to use the fallback package.
if (newAppDownloadPath == nil && fallbackPackagePath != nil)
View
1  SUPackageInstaller.m
@@ -7,6 +7,7 @@
//
#import "SUPackageInstaller.h"
+#import "SUConstants.h"
#ifndef NSAppKitVersionNumber10_4
#define NSAppKitVersionNumber10_4 824
View
1  SUPlainInstaller.m
@@ -8,6 +8,7 @@
#import "SUPlainInstaller.h"
#import "SUPlainInstallerInternals.h"
+#import "SUConstants.h"
NSString *SUInstallerPathKey = @"SUInstallerPath";
NSString *SUInstallerTargetPathKey = @"SUInstallerTargetPath";
View
1  SUPlainInstallerInternals.m
@@ -8,6 +8,7 @@
#import "Sparkle.h"
#import "SUPlainInstallerInternals.h"
+#import "SUConstants.h"
#import <CoreServices/CoreServices.h>
#import <Security/Security.h>
View
51 Sparkle.xcodeproj/project.pbxproj
@@ -7,6 +7,15 @@
objects = {
/* Begin PBXBuildFile section */
+ 552B69D410C0785600050E82 /* SUInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 618FA5000DAE88B40026945C /* SUInstaller.m */; };
+ 552B69D510C0786A00050E82 /* SUHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 61EF67550E25B58D00F754E0 /* SUHost.m */; };
+ 552B69DC10C0788200050E82 /* SUConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 61299A5F09CA6EB100B7442F /* SUConstants.m */; };
+ 552B69E910C0790500050E82 /* SUPlainInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 618FA5040DAE8AB80026945C /* SUPlainInstaller.m */; };
+ 552B69EA10C0790800050E82 /* SUPlainInstallerInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = 61B5F8E509C4CE3C00B25A18 /* SUPlainInstallerInternals.m */; };
+ 552B69ED10C0791000050E82 /* SUSystemProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 61A2279B0D1CEE7600430CCD /* SUSystemProfiler.m */; };
+ 552B69F010C0791800050E82 /* SUPackageInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 618FA5210DAE8E8A0026945C /* SUPackageInstaller.m */; };
+ 552B6A3710C0795600050E82 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61B5F8F609C4CEB300B25A18 /* Security.framework */; };
+ 552B6A5E10C07FC200050E82 /* SUStandardVersionComparator.m in Sources */ = {isa = PBXBuildFile; fileRef = 61A225A30D1C4AC000430CCD /* SUStandardVersionComparator.m */; };
610134730DD250470049ACDF /* SUUpdateDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 610134710DD250470049ACDF /* SUUpdateDriver.h */; settings = {ATTRIBUTES = (); }; };
610134740DD250470049ACDF /* SUUpdateDriver.m in Sources */ = {isa = PBXBuildFile; fileRef = 610134720DD250470049ACDF /* SUUpdateDriver.m */; };
6101347B0DD2541A0049ACDF /* SUProbingUpdateDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 610134790DD2541A0049ACDF /* SUProbingUpdateDriver.h */; settings = {ATTRIBUTES = (); }; };
@@ -90,8 +99,8 @@
61F83F740DBFE141006FDD30 /* SUBasicUpdateDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 61F83F6F0DBFE137006FDD30 /* SUBasicUpdateDriver.h */; settings = {ATTRIBUTES = (); }; };
61FA52880E2D9EA400EF58AD /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Sparkle.framework */; settings = {ATTRIBUTES = (Required, ); }; };
DAAEFC9B0DA5722F0051E0D0 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; };
- DAAEFD4E0DA572330051E0D0 /* relaunch.m in Sources */ = {isa = PBXBuildFile; fileRef = 613242130CD06CEF00106AA4 /* relaunch.m */; };
- DAAEFD510DA572550051E0D0 /* relaunch in Resources */ = {isa = PBXBuildFile; fileRef = DAAEFC960DA571DF0051E0D0 /* relaunch */; };
+ DAAEFD4E0DA572330051E0D0 /* finish_installation.m in Sources */ = {isa = PBXBuildFile; fileRef = 613242130CD06CEF00106AA4 /* finish_installation.m */; };
+ DAAEFD510DA572550051E0D0 /* finish_installation in Resources */ = {isa = PBXBuildFile; fileRef = DAAEFC960DA571DF0051E0D0 /* finish_installation */; };
FAEFA2F70D94AA7500472538 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
FAEFA2F80D94AA7900472538 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; };
FAEFA3040D94AB3400472538 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; };
@@ -202,7 +211,7 @@
613151B30FB49480000DCD59 /* is */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = is; path = is.lproj/SUUpdatePermissionPrompt.nib; sourceTree = "<group>"; };
613151B40FB49488000DCD59 /* is */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = is; path = is.lproj/SUAutomaticUpdateAlert.nib; sourceTree = "<group>"; };
613151B50FB49492000DCD59 /* is */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = is; path = is.lproj/SUUpdateAlert.nib; sourceTree = "<group>"; };
- 613242130CD06CEF00106AA4 /* relaunch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = relaunch.m; sourceTree = "<group>"; };
+ 613242130CD06CEF00106AA4 /* finish_installation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = finish_installation.m; sourceTree = "<group>"; };
615409A8103BA09100125AF1 /* ConfigTestAppReleaseGCSupport.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ConfigTestAppReleaseGCSupport.xcconfig; sourceTree = "<group>"; };
615409C4103BBC4000125AF1 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Sparkle.strings; sourceTree = "<group>"; };
615409C5103BBC5000125AF1 /* cs */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = cs; path = cs.lproj/SUUpdatePermissionPrompt.nib; sourceTree = "<group>"; };
@@ -292,7 +301,7 @@
61F83F700DBFE137006FDD30 /* SUBasicUpdateDriver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUBasicUpdateDriver.m; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* Sparkle.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Sparkle.framework; sourceTree = BUILT_PRODUCTS_DIR; };
- DAAEFC960DA571DF0051E0D0 /* relaunch */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = relaunch; sourceTree = BUILT_PRODUCTS_DIR; };
+ DAAEFC960DA571DF0051E0D0 /* finish_installation */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = finish_installation; sourceTree = BUILT_PRODUCTS_DIR; };
FA1941CA0D94A70100DD942E /* ConfigFrameworkDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ConfigFrameworkDebug.xcconfig; sourceTree = "<group>"; };
FA1941CB0D94A70100DD942E /* ConfigTestAppDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ConfigTestAppDebug.xcconfig; sourceTree = "<group>"; };
FA1941CC0D94A70100DD942E /* ConfigCommonRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ConfigCommonRelease.xcconfig; sourceTree = "<group>"; };
@@ -343,6 +352,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 552B6A3710C0795600050E82 /* Security.framework in Frameworks */,
DAAEFC9B0DA5722F0051E0D0 /* AppKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -355,7 +365,7 @@
children = (
8DC2EF5B0486A6940098B216 /* Sparkle.framework */,
61B5F90209C4CEE200B25A18 /* Sparkle Test App.app */,
- DAAEFC960DA571DF0051E0D0 /* relaunch */,
+ DAAEFC960DA571DF0051E0D0 /* finish_installation */,
612279D90DB5470200AB99EA /* Sparkle Unit Tests.octest */,
);
name = Products;
@@ -427,7 +437,7 @@
6101355D0DD25BB70049ACDF /* Support */ = {
isa = PBXGroup;
children = (
- 613242130CD06CEF00106AA4 /* relaunch.m */,
+ 613242130CD06CEF00106AA4 /* finish_installation.m */,
);
name = Support;
sourceTree = "<group>";
@@ -688,9 +698,9 @@
productReference = 8DC2EF5B0486A6940098B216 /* Sparkle.framework */;
productType = "com.apple.product-type.framework";
};
- DAAEFC950DA571DF0051E0D0 /* relaunch tool */ = {
+ DAAEFC950DA571DF0051E0D0 /* finish_installation tool */ = {
isa = PBXNativeTarget;
- buildConfigurationList = DAAEFC9A0DA571FD0051E0D0 /* Build configuration list for PBXNativeTarget "relaunch tool" */;
+ buildConfigurationList = DAAEFC9A0DA571FD0051E0D0 /* Build configuration list for PBXNativeTarget "finish_installation tool" */;
buildPhases = (
DAAEFC930DA571DF0051E0D0 /* Sources */,
DAAEFC940DA571DF0051E0D0 /* Frameworks */,
@@ -699,9 +709,9 @@
);
dependencies = (
);
- name = "relaunch tool";
+ name = "finish_installation tool";
productName = relaunch;
- productReference = DAAEFC960DA571DF0051E0D0 /* relaunch */;
+ productReference = DAAEFC960DA571DF0051E0D0 /* finish_installation */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
@@ -754,7 +764,7 @@
targets = (
8DC2EF4F0486A6940098B216 /* Sparkle */,
61B5F90109C4CEE200B25A18 /* Sparkle Test App */,
- DAAEFC950DA571DF0051E0D0 /* relaunch tool */,
+ DAAEFC950DA571DF0051E0D0 /* finish_installation tool */,
612279D80DB5470200AB99EA /* Sparkle Unit Tests */,
);
};
@@ -784,7 +794,7 @@
buildActionMask = 2147483647;
files = (
61C2680A0E2DB5D000175E6C /* License.txt in Resources */,
- DAAEFD510DA572550051E0D0 /* relaunch in Resources */,
+ DAAEFD510DA572550051E0D0 /* finish_installation in Resources */,
610D5A750A1670A4004AAD9C /* SUStatus.nib in Resources */,
61AAE8280A321A7F00D8810D /* Sparkle.strings in Resources */,
61AAE8290A321A8000D8810D /* SUAutomaticUpdateAlert.nib in Resources */,
@@ -913,7 +923,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- DAAEFD4E0DA572330051E0D0 /* relaunch.m in Sources */,
+ DAAEFD4E0DA572330051E0D0 /* finish_installation.m in Sources */,
+ 552B69D410C0785600050E82 /* SUInstaller.m in Sources */,
+ 552B69D510C0786A00050E82 /* SUHost.m in Sources */,
+ 552B69DC10C0788200050E82 /* SUConstants.m in Sources */,
+ 552B69E910C0790500050E82 /* SUPlainInstaller.m in Sources */,
+ 552B69EA10C0790800050E82 /* SUPlainInstallerInternals.m in Sources */,
+ 552B69ED10C0791000050E82 /* SUSystemProfiler.m in Sources */,
+ 552B69F010C0791800050E82 /* SUPackageInstaller.m in Sources */,
+ 552B6A5E10C07FC200050E82 /* SUStandardVersionComparator.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -937,7 +955,7 @@
};
DAAEFD500DA572460051E0D0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DAAEFC950DA571DF0051E0D0 /* relaunch tool */;
+ target = DAAEFC950DA571DF0051E0D0 /* finish_installation tool */;
targetProxy = DAAEFD4F0DA572460051E0D0 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
@@ -1109,6 +1127,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = FA1941D40D94A70100DD942E /* ConfigRelaunchRelease.xcconfig */;
buildSettings = {
+ PRODUCT_NAME = finish_installation;
};
name = "Release (GC dual-mode; 10.5-only)";
};
@@ -1216,6 +1235,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = FA1941D30D94A70100DD942E /* ConfigRelaunchDebug.xcconfig */;
buildSettings = {
+ PRODUCT_NAME = finish_installation;
};
name = Debug;
};
@@ -1223,6 +1243,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = FA1941D40D94A70100DD942E /* ConfigRelaunchRelease.xcconfig */;
buildSettings = {
+ PRODUCT_NAME = finish_installation;
};
name = Release;
};
@@ -1269,7 +1290,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- DAAEFC9A0DA571FD0051E0D0 /* Build configuration list for PBXNativeTarget "relaunch tool" */ = {
+ DAAEFC9A0DA571FD0051E0D0 /* Build configuration list for PBXNativeTarget "finish_installation tool" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DAAEFC980DA571DF0051E0D0 /* Debug */,
View
75 finish_installation.m
@@ -1,62 +1,117 @@
#import <AppKit/AppKit.h>
+#import "SUInstaller.h"
+#import "SUHost.h"
+#import "SUStandardVersionComparator.h"
#include <unistd.h>
@interface TerminationListener : NSObject
{
- const char *executablePath;
- pid_t parentProcessId;
+ const char *executablePath;
+ pid_t parentProcessId;
+ const char *folderPath;
+ NSString *selfPath;
}
- (void) relaunch;
+- (void) install;
@end
@implementation TerminationListener
-- (id) initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid
+- (id) initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid folderPath: (const char*)inFolderPath
+ selfPath: (NSString*)inSelfPath
{
self = [super init];
if (self != nil)
{
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ TransformProcessType( &psn, kProcessTransformToForegroundApplication );
+ [[NSApplication sharedApplication] activateIgnoringOtherApps: YES];
+
executablePath = execPath;
parentProcessId = ppid;
+ folderPath = inFolderPath;
+ selfPath = [inSelfPath retain];
if (getppid() == 1) // ppid is launchd (1) => parent terminated already
- [self relaunch];
+ [self install];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(watchdog:) userInfo:nil repeats:YES];
}
return self;
}
+
+-(void) dealloc
+{
+ [selfPath release];
+ selfPath = nil;
+
+ [super dealloc];
+}
+
+
- (void)watchdog:(NSTimer *)timer
{
ProcessSerialNumber psn;
if (GetProcessForPID(parentProcessId, &psn) == procNotFound)
- [self relaunch];
+ [self install];
}
- (void) relaunch
{
[[NSWorkspace sharedWorkspace] openFile:[[NSFileManager defaultManager] stringWithFileSystemRepresentation:executablePath length:strlen(executablePath)]];
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
- [[NSFileManager defaultManager] removeFileAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"relaunch"] handler:nil];
+ [[NSFileManager defaultManager] removeFileAtPath: selfPath handler: nil];
#else
- [[NSFileManager defaultManager] removeItemAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"relaunch"] error:NULL];
+ [[NSFileManager defaultManager] removeItemAtPath: selfPath error: NULL];
#endif
- exit(0);
+ exit(EXIT_SUCCESS);
+}
+
+
+-(void) install
+{
+ NSBundle *theBundle = [NSBundle bundleWithPath: [NSString stringWithUTF8String: executablePath]];
+ SUHost *theHost = [[[SUHost alloc] initWithBundle: theBundle] autorelease];
+
+ [SUInstaller installFromUpdateFolder: [NSString stringWithUTF8String: folderPath]
+ overHost: theHost
+ delegate: self synchronously: YES
+ versionComparator: [SUStandardVersionComparator defaultComparator]];
+}
+
+- (void)installerFinishedForHost:(SUHost *)aHost
+{
+ [self relaunch];
+}
+
+- (void)installerForHost:(SUHost *)host failedWithError:(NSError *)error
+{
+ NSRunAlertPanel( @"", @"%@", @"OK", @"", @"", error );
+ exit(EXIT_FAILURE);
}
@end
int main (int argc, const char * argv[])
{
- if (argc != 3) return EXIT_FAILURE;
+ if (argc != 4) return EXIT_FAILURE;
+
+ NSString* selfPath = nil;
+ if( argv[0][0] == '/' )
+ selfPath = [NSString stringWithUTF8String: argv[0]];
+ else
+ {
+ selfPath = [[NSFileManager defaultManager] currentDirectoryPath];
+ selfPath = [selfPath stringByAppendingPathComponent: [NSString stringWithUTF8String: argv[0]]];
+ }
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
- [[[TerminationListener alloc] initWithExecutablePath:argv[1] parentProcessId:atoi(argv[2])] autorelease];
+ [[[TerminationListener alloc] initWithExecutablePath: argv[1] parentProcessId: atoi(argv[2]) folderPath: argv[3] selfPath: selfPath] autorelease];
[[NSApplication sharedApplication] run];
[pool drain];
Please sign in to comment.
Something went wrong with that request. Please try again.