Skip to content

Commit

Permalink
Merge pull request sparkle-project#1251 from ksuther/objc-messaging-i…
Browse files Browse the repository at this point in the history
…d-fixes

Silence Xcode 10 "Messaging unqualified id" warnings by specifying types
  • Loading branch information
kornelski authored Jun 14, 2018
2 parents 7d931e2 + 3034eca commit e452b7f
Show file tree
Hide file tree
Showing 22 changed files with 37 additions and 50 deletions.
2 changes: 1 addition & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Secure and reliable software update framework for Cocoa developers.
## Requirements

* Runtime: macOS 10.7 or greater
* Build: Xcode 7 and 10.8 SDK or greater
* Build: Xcode 7 and 10.11 SDK or greater
* HTTPS server for serving updates (see [App Transport Security](http://sparkle-project.org/documentation/app-transport-security/))

## Usage
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/Autoupdate/Autoupdate.m
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ int main(int __unused argc, const char __unused *argv[])
{
@autoreleasepool
{
NSArray *args = [[NSProcessInfo processInfo] arguments];
NSArray<NSString *> *args = [[NSProcessInfo processInfo] arguments];
if (args.count < 5 || args.count > 7) {
return EXIT_FAILURE;
}
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SPUURLRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ - (instancetype)initWithURL:(NSURL *)url cachePolicy:(NSURLRequestCachePolicy)ca

+ (instancetype)URLRequestWithRequest:(NSURLRequest *)request
{
return [[[self class] alloc] initWithURL:request.URL cachePolicy:request.cachePolicy timeoutInterval:request.timeoutInterval httpHeaderFields:request.allHTTPHeaderFields networkServiceType:request.networkServiceType];
return [(SPUURLRequest *)[[self class] alloc] initWithURL:request.URL cachePolicy:request.cachePolicy timeoutInterval:request.timeoutInterval httpHeaderFields:request.allHTTPHeaderFields networkServiceType:request.networkServiceType];
}

+ (BOOL)supportsSecureCoding
Expand Down
5 changes: 0 additions & 5 deletions Sparkle/SUAppcast.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
SU_EXPORT @interface SUAppcast : NSObject

@property (copy, nullable) NSString *userAgentString;

#if __has_feature(objc_generics)
@property (copy, nullable) NSDictionary<NSString *, NSString *> *httpHeaders;
#else
@property (copy, nullable) NSDictionary *httpHeaders;
#endif

- (void)fetchAppcastFromURL:(NSURL *)url inBackground:(BOOL)bg completionBlock:(void (^)(NSError *_Nullable))err;
- (SUAppcast *)copyWithoutDeltaUpdates;
Expand Down
4 changes: 2 additions & 2 deletions Sparkle/SUAppcastItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ - (BOOL)isDeltaUpdate

- (BOOL)isCriticalUpdate
{
return [[self.propertiesDictionary objectForKey:SUAppcastElementTags] containsObject:SUAppcastElementCriticalUpdate];
return [(NSArray *)[self.propertiesDictionary objectForKey:SUAppcastElementTags] containsObject:SUAppcastElementCriticalUpdate];
}

- (BOOL)isMacOsUpdate
Expand Down Expand Up @@ -97,7 +97,7 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict failureReason:(NSString

// 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.
NSArray *fileComponents = [[enclosure objectForKey:SURSSAttributeURL] componentsSeparatedByString:@"_"];
NSArray<NSString *> *fileComponents = [(NSString *)[enclosure objectForKey:SURSSAttributeURL] componentsSeparatedByString:@"_"];
if ([fileComponents count] > 1) {
newVersion = [[fileComponents lastObject] stringByDeletingPathExtension];
}
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUAutomaticUpdateAlert.m
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ - (NSString *)descriptionText

- (NSTouchBar *)makeTouchBar
{
NSTouchBar *touchBar = [[NSClassFromString(@"NSTouchBar") alloc] init];
NSTouchBar *touchBar = [(NSTouchBar *)[NSClassFromString(@"NSTouchBar") alloc] init];
touchBar.defaultItemIdentifiers = @[SUAutomaticUpdateAlertTouchBarIndentifier,];
touchBar.principalItemIdentifier = SUAutomaticUpdateAlertTouchBarIndentifier;
touchBar.delegate = self;
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUBinaryDeltaCommon.m
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ BOOL modifyPermissions(NSString *path, mode_t desiredPermissions)
return NO;
}
mode_t newMode = ([permissions unsignedShortValue] & ~PERMISSION_FLAGS) | desiredPermissions;
int (*changeModeFunc)(const char *, mode_t) = [[attributes objectForKey:NSFileType] isEqualToString:NSFileTypeSymbolicLink] ? lchmod : chmod;
int (*changeModeFunc)(const char *, mode_t) = [(NSString *)[attributes objectForKey:NSFileType] isEqualToString:NSFileTypeSymbolicLink] ? lchmod : chmod;
if (changeModeFunc([path fileSystemRepresentation], newMode) != 0) {
return NO;
}
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUDSAVerifier.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ + (BOOL)validatePath:(NSString *)path withEncodedDSASignature:(NSString *)encode
return NO;
}

SUDSAVerifier *verifier = [[self alloc] initWithPublicKeyData:[pkeyString dataUsingEncoding:NSUTF8StringEncoding]];
SUDSAVerifier *verifier = [(SUDSAVerifier *)[self alloc] initWithPublicKeyData:[pkeyString dataUsingEncoding:NSUTF8StringEncoding]];

if (!verifier) {
return NO;
Expand Down
8 changes: 4 additions & 4 deletions Sparkle/SUFileManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ - (instancetype)initWithAuthorizationToolPath:(NSString *)authorizationToolPath

+ (instancetype)defaultManager
{
return [[self alloc] initWithAuthorizationToolPath:nil];
return [(SUFileManager *)[self alloc] initWithAuthorizationToolPath:nil];
}

+ (instancetype)fileManagerWithAuthorizationToolPath:(NSString *)authorizationToolPath
{
return [[self alloc] initWithAuthorizationToolPath:authorizationToolPath];
return [(SUFileManager *)[self alloc] initWithAuthorizationToolPath:authorizationToolPath];
}

- (instancetype)fileManagerByPreservingAuthorizationRights
Expand Down Expand Up @@ -269,7 +269,7 @@ - (BOOL)_itemExistsAtURL:(NSURL *)fileURL isDirectory:(BOOL *)isDirectory
}

if (isDirectory != NULL) {
*isDirectory = [[attributes objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory];
*isDirectory = [(NSString *)[attributes objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory];
}

return YES;
Expand Down Expand Up @@ -304,7 +304,7 @@ - (int)_removeXAttr:(const char *)attr fromFile:(NSString *)file options:(int)op
- (BOOL)_removeQuarantineWithAuthenticationAtRootURL:(NSURL *)rootURL error:(NSError *__autoreleasing *)error
{
// Because this is a system utility, it's fine to follow the symbolic link if one exists
if (![_fileManager fileExistsAtPath:@(XATTR_UTILITY_PATH)]) {
if (![_fileManager fileExistsAtPath:(NSString *)@(XATTR_UTILITY_PATH)]) {
if (error != NULL) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileNoSuchFileError userInfo:@{ NSLocalizedDescriptionKey: @"xattr utility does not exist on this system." }];
}
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUHost.m
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ - (id)objectForInfoDictionaryKey:(NSString *)key

- (BOOL)boolForInfoDictionaryKey:(NSString *)key
{
return [[self objectForInfoDictionaryKey:key] boolValue];
return [(NSNumber *)[self objectForInfoDictionaryKey:key] boolValue];
}

- (id)objectForUserDefaultsKey:(NSString *)defaultName
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUOperatingSystem.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ + (NSOperatingSystemVersion)operatingSystemVersion
NSURL *url = [coreServices URLByAppendingPathComponent:@"SystemVersion.plist"];
assert(url != nil);
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:url];
NSArray *components = [ [dictionary objectForKey: @"ProductVersion"] componentsSeparatedByString:@"."];
NSArray<NSString *> *components = [ (NSString *)[dictionary objectForKey: @"ProductVersion"] componentsSeparatedByString:@"."];
version.majorVersion = components.count > 0 ? [ [components objectAtIndex:0] integerValue] : 0;
version.minorVersion = components.count > 1 ? [ [components objectAtIndex:1] integerValue] : 0;
version.patchVersion = components.count > 2 ? [ [components objectAtIndex:2] integerValue] : 0;
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUPipedUnarchiver.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ - (void)extractArchivePipingDataToCommand:(NSString *)command arguments:(NSArray

// Get the file size.
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.archivePath error:nil];
NSUInteger expectedLength = [[attributes objectForKey:NSFileSize] unsignedIntegerValue];
NSUInteger expectedLength = [(NSNumber *)[attributes objectForKey:NSFileSize] unsignedIntegerValue];
if (expectedLength > 0) {
NSFileHandle *archiveInput = [NSFileHandle fileHandleForReadingAtPath:self.archivePath];

Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUStatusController.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ - (void)setMaxProgressValue:(double)value

- (NSTouchBar *)makeTouchBar
{
NSTouchBar *touchBar = [[NSClassFromString(@"NSTouchBar") alloc] init];
NSTouchBar *touchBar = [(NSTouchBar *)[NSClassFromString(@"NSTouchBar") alloc] init];
touchBar.defaultItemIdentifiers = @[ SUStatusControllerTouchBarIndentifier,];
touchBar.principalItemIdentifier = SUStatusControllerTouchBarIndentifier;
touchBar.delegate = self;
Expand Down
4 changes: 2 additions & 2 deletions Sparkle/SUUpdateAlert.m
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ - (NSString *)descriptionText
return finalString;
}

- (void)webView:(WebView *)sender didFinishLoadForFrame:frame
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
if ([frame parentFrame] == nil) {
self.webViewFinishedLoading = YES;
Expand Down Expand Up @@ -329,7 +329,7 @@ - (NSArray *)webView:(WebView *)__unused sender contextMenuItemsForElement:(NSDi

- (NSTouchBar *)makeTouchBar
{
NSTouchBar *touchBar = [[NSClassFromString(@"NSTouchBar") alloc] init];
NSTouchBar *touchBar = [(NSTouchBar *)[NSClassFromString(@"NSTouchBar") alloc] init];
touchBar.defaultItemIdentifiers = @[SUUpdateAlertTouchBarIndentifier,];
touchBar.principalItemIdentifier = SUUpdateAlertTouchBarIndentifier;
touchBar.delegate = self;
Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SUUpdatePermissionPrompt.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ typedef NS_ENUM(NSInteger, SUPermissionPromptResult) {
+ (void)promptWithHost:(SUHost *)host systemProfile:(NSArray *)profile reply:(void (^)(SUUpdatePermissionResponse *))reply;

- (IBAction)toggleMoreInfo:(id)sender;
- (IBAction)finishPrompt:(id)sender;
- (IBAction)finishPrompt:(NSButton *)sender;
@end

#endif
8 changes: 4 additions & 4 deletions Sparkle/SUUpdatePermissionPrompt.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ @implementation SUUpdatePermissionPrompt

- (BOOL)shouldAskAboutProfile
{
return [[self.host objectForInfoDictionaryKey:SUEnableSystemProfilingKey] boolValue];
return [(NSNumber *)[self.host objectForInfoDictionaryKey:SUEnableSystemProfilingKey] boolValue];
}

- (instancetype)initWithHost:(SUHost *)aHost systemProfile:(NSArray *)profile reply:(void (^)(SUUpdatePermissionResponse *))reply
Expand Down Expand Up @@ -80,7 +80,7 @@ + (void)promptWithHost:(SUHost *)host systemProfile:(NSArray *)profile reply:(vo
}

if (![NSApp modalWindow]) { // do not prompt if there is is another modal window on screen
SUUpdatePermissionPrompt *prompt = [[[self class] alloc] initWithHost:host systemProfile:profile reply:reply];
SUUpdatePermissionPrompt *prompt = [(SUUpdatePermissionPrompt *)[[self class] alloc] initWithHost:host systemProfile:profile reply:reply];
NSWindow *window = [prompt window];
if (window) {
[NSApp runModalForWindow:window];
Expand Down Expand Up @@ -159,7 +159,7 @@ - (IBAction)toggleMoreInfo:(id)__unused sender
[self.moreInfoView setHidden:!self.isShowingMoreInfo];
}

- (IBAction)finishPrompt:(id)sender
- (IBAction)finishPrompt:(NSButton *)sender
{
SUUpdatePermissionResponse *response = [[SUUpdatePermissionResponse alloc] initWithAutomaticUpdateChecks:([sender tag] == 1) sendSystemProfile:self.shouldSendProfile];
self.reply(response);
Expand All @@ -170,7 +170,7 @@ - (IBAction)finishPrompt:(id)sender

- (NSTouchBar *)makeTouchBar
{
NSTouchBar *touchBar = [[NSClassFromString(@"NSTouchBar") alloc] init];
NSTouchBar *touchBar = [(NSTouchBar *)[NSClassFromString(@"NSTouchBar") alloc] init];
touchBar.defaultItemIdentifiers = @[SUUpdatePermissionPromptTouchBarIndentifier,];
touchBar.principalItemIdentifier = SUUpdatePermissionPromptTouchBarIndentifier;
touchBar.delegate = self;
Expand Down
4 changes: 0 additions & 4 deletions Sparkle/SUUpdater.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,7 @@ SU_EXPORT @interface SUUpdater : NSObject
The keys of this dictionary are HTTP header fields (NSString) and values are corresponding values (NSString)
*/
#if __has_feature(objc_generics)
@property (copy) NSDictionary<NSString *, NSString *> *httpHeaders;
#else
@property (copy) NSDictionary *httpHeaders;
#endif

/*!
A property indicating whether or not the user's system profile information is sent when checking for updates.
Expand Down
8 changes: 4 additions & 4 deletions Sparkle/SUUpdater.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ + (SUUpdater *)updaterForBundle:(NSBundle *)bundle
if (bundle == nil) bundle = [NSBundle mainBundle];
id updater = [sharedUpdaters objectForKey:[NSValue valueWithNonretainedObject:bundle]];
if (updater == nil) {
updater = [[[self class] alloc] initForBundle:bundle];
updater = [(SUUpdater *)[[self class] alloc] initForBundle:bundle];
}
return updater;
}
Expand Down Expand Up @@ -315,7 +315,7 @@ - (void)checkForUpdatesInBackground
}

// Do not use reachability for a preflight check. This can be deceptive and a bad idea. Apple does not recommend doing it.
SUUpdateDriver *theUpdateDriver = [[(automatic ? [SUAutomaticUpdateDriver class] : [SUScheduledUpdateDriver class])alloc] initWithUpdater:self];
SUUpdateDriver *theUpdateDriver = [(SUBasicUpdateDriver *)[(automatic ? [SUAutomaticUpdateDriver class] : [SUScheduledUpdateDriver class])alloc] initWithUpdater:self];

[self checkForUpdatesWithDriver:theUpdateDriver];
}
Expand Down Expand Up @@ -537,7 +537,7 @@ - (NSURL *)parameterizedFeedURL
const NSTimeInterval oneWeek = 60 * 60 * 24 * 7;
sendingSystemProfile &= (-[lastSubmitDate timeIntervalSinceNow] >= oneWeek);

NSArray *parameters = @[];
NSArray<NSDictionary<NSString *, NSString *> *> *parameters = @[];
if ([self.delegate respondsToSelector:@selector(feedParametersForUpdater:sendingSystemProfile:)]) {
parameters = [parameters arrayByAddingObjectsFromArray:[self.delegate feedParametersForUpdater:self sendingSystemProfile:sendingSystemProfile]];
}
Expand All @@ -550,7 +550,7 @@ - (NSURL *)parameterizedFeedURL

// Build up the parameterized URL.
NSMutableArray *parameterStrings = [NSMutableArray array];
for (NSDictionary *currentProfileInfo in parameters) {
for (NSDictionary<NSString *, NSString *> *currentProfileInfo in parameters) {
[parameterStrings addObject:[NSString stringWithFormat:@"%@=%@", escapeURLComponent([[currentProfileInfo objectForKey:@"key"] description]), escapeURLComponent([[currentProfileInfo objectForKey:@"value"] description])]];
}

Expand Down
4 changes: 0 additions & 4 deletions Sparkle/SUUpdaterDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ SU_EXPORT extern NSString *const SUUpdaterAppcastNotificationKey;
\return An array of dictionaries with keys: "key", "value", "displayKey", "displayValue", the latter two being specifically for display to the user.
*/
#if __has_feature(objc_generics)
- (NSArray<NSDictionary<NSString *, NSString *> *> *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile;
#else
- (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile;
#endif

/*!
Returns a custom appcast URL.
Expand Down
2 changes: 1 addition & 1 deletion TestApplication/SUTestApplicationDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ - (void)applicationDidFinishLaunching:(NSNotification * __unused)notification
NSBundle *mainBundle = [NSBundle mainBundle];

// Check if we are already up to date
if ([[mainBundle objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey] isEqualToString:UPDATED_VERSION]) {
if ([(NSString *)[mainBundle objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey] isEqualToString:UPDATED_VERSION]) {
NSAlert *alreadyUpdatedAlert = [[NSAlert alloc] init];
alreadyUpdatedAlert.messageText = @"Update succeeded!";
alreadyUpdatedAlert.informativeText = @"This is the updated version of Sparkle Test App.\n\nDelete and rebuild the app to test updates again.";
Expand Down
2 changes: 1 addition & 1 deletion TestApplication/SUTestWebServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
NSString *requestLine = lines.count >= 3 ? [lines objectAtIndex:0] : nil;
NSArray *parts = requestLine ? [requestLine componentsSeparatedByString:@" "] : nil;
// Only process GET requests for existing files
if ([[parts objectAtIndex:0] isEqualToString:@"GET"]) {
if ([(NSString *)[parts objectAtIndex:0] isEqualToString:@"GET"]) {
// Use NSURL to strip out query parameters
NSString *path = [NSURL URLWithString:[parts objectAtIndex:1] relativeToURL:nil].path;
NSString *filePath = [self.workingDirectory stringByAppendingString:path];
Expand Down
16 changes: 8 additions & 8 deletions fileop/fileop.m
Original file line number Diff line number Diff line change
Expand Up @@ -85,47 +85,47 @@ int main(int argc, const char *argv[])
// This tool should be executed as root, so we should not try to authorize
SUFileManager *fileManager = [SUFileManager defaultManager];

if ([command isEqualToString:@(SUFileOpRemoveQuarantineCommand)]) {
if ([command isEqualToString:(NSString *)@(SUFileOpRemoveQuarantineCommand)]) {
if (![fileManager releaseItemFromQuarantineAtRootURL:fileURL error:NULL]) {
exit(SUQuarantineRemovalFailure);
}
} else if ([command isEqualToString:@(SUFileOpCopyCommand)]) {
} else if ([command isEqualToString:(NSString *)@(SUFileOpCopyCommand)]) {
if (destinationURL != nil) {
if (![fileManager copyItemAtURL:fileURL toURL:destinationURL error:NULL]) {
exit(SUCopyFailure);
}
} else {
exit(SUInvalidOrNoDestination | SUCopyFailure);
}
} else if ([command isEqualToString:@(SUFileOpMoveCommand)]) {
} else if ([command isEqualToString:(NSString *)@(SUFileOpMoveCommand)]) {
if (destinationURL != nil) {
if (![fileManager moveItemAtURL:fileURL toURL:destinationURL error:NULL]) {
exit(SUMoveFailure);
}
} else {
exit(SUInvalidOrNoDestination | SUMoveFailure);
}
} else if ([command isEqualToString:@(SUFileOpChangeOwnerAndGroupCommand)]) {
} else if ([command isEqualToString:(NSString *)@(SUFileOpChangeOwnerAndGroupCommand)]) {
if (destinationURL != nil) {
if (![fileManager changeOwnerAndGroupOfItemAtRootURL:fileURL toMatchURL:destinationURL error:NULL]) {
exit(SUChangeOwnerAndGroupFailure);
}
} else {
exit(SUInvalidOrNoDestination | SUChangeOwnerAndGroupFailure);
}
} else if ([command isEqualToString:@(SUFileOpUpdateModificationAndAccessTimeCommand)]) {
} else if ([command isEqualToString:(NSString *)@(SUFileOpUpdateModificationAndAccessTimeCommand)]) {
if (![fileManager updateModificationAndAccessTimeOfItemAtURL:fileURL error:NULL]) {
exit(SUTouchFailure);
}
} else if ([command isEqualToString:@(SUFileOpMakeDirectoryCommand)]) {
} else if ([command isEqualToString:(NSString *)@(SUFileOpMakeDirectoryCommand)]) {
if (![fileManager makeDirectoryAtURL:fileURL error:NULL]) {
exit(SUMakeDirectoryFailure);
}
} else if ([command isEqualToString:@(SUFileOpRemoveCommand)]) {
} else if ([command isEqualToString:(NSString *)@(SUFileOpRemoveCommand)]) {
if (![fileManager removeItemAtURL:fileURL error:NULL]) {
exit(SURemoveFailure);
}
} else if ([command isEqualToString:@(SUFileOpInstallCommand)]) {
} else if ([command isEqualToString:(NSString *)@(SUFileOpInstallCommand)]) {
// The one command that can *only* be run as the root user
NSString *installerPath = @"/usr/sbin/installer";

Expand Down

0 comments on commit e452b7f

Please sign in to comment.