Skip to content
This repository has been archived by the owner on Sep 4, 2018. It is now read-only.

Better heuristic for finding the .xcodeproj directory #471

Merged
merged 8 commits into from
Aug 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Alcatraz.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@
890A4B41171F031300AFE577 /* Frameworks */,
890A4B40171F031300AFE577 /* Products */,
);
indentWidth = 4;
sourceTree = "<group>";
tabWidth = 4;
usesTabs = 0;
};
890A4B40171F031300AFE577 /* Products */ = {
isa = PBXGroup;
Expand Down
16 changes: 15 additions & 1 deletion Alcatraz/Controllers/ATZPluginWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentN
return YES;
}

- (NSError *)willPresentError:(NSError *)error
{
const NSUInteger maxLength = 500;
NSString *recoverySuggestion = error.userInfo[NSLocalizedRecoverySuggestionErrorKey];
if (recoverySuggestion.length > maxLength) {
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
userInfo[NSLocalizedRecoverySuggestionErrorKey] = [[recoverySuggestion substringToIndex:MIN(maxLength, recoverySuggestion.length)] stringByAppendingString:@"…"];
return [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
}
return error;
}

#pragma mark - Bindings

- (IBAction)installPressed:(ATZFillableButton *)button {
Expand Down Expand Up @@ -209,7 +221,9 @@ - (void)installPackage:(ATZPackage *)package andUpdateControl:(ATZFillableButton
[button setFillRatio:progress animated:YES];
} completion:^(NSError *failure) {
[ATZStyleKit updateButton:button forPackageState:package animated:YES];
if (package.requiresRestart) {
if (failure) {
[self presentError:failure];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not too fond of the modal dialog for network errors, but I guess this is better than just logging.
👍 for now.

} else if (package.requiresRestart) {
[self postNotificationForInstalledPackage:package];
}
}];
Expand Down
7 changes: 7 additions & 0 deletions Alcatraz/Helpers/ATZShell.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@

#import <Foundation/Foundation.h>

static NSString *const ATZShellErrorDomain = @"ATZShellErrorDomain";
NS_ENUM(NSInteger)
{
ATZShellTerminationStatusError = 666,
ATZShellLaunchError = 667
};

@interface ATZShell : NSObject

- (void)executeCommand:(NSString *)command withArguments:(NSArray *)arguments
Expand Down
10 changes: 6 additions & 4 deletions Alcatraz/Helpers/ATZShell.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ - (void)setUpTerminationHandlerForTask:(NSTask *)task completion:(void(^)(NSStri
if (task.terminationStatus == 0) {
completion(output, nil);
} else {
NSString* reason = [NSString stringWithFormat:@"Task exited with status %d", task.terminationStatus];
completion(output, [NSError errorWithDomain:reason code:666 userInfo:@{ NSLocalizedDescriptionKey: reason }]);
NSString *description = [NSString stringWithFormat:@"Task exited with status %d\n\n%@ %@", task.terminationStatus, task.launchPath, [task.arguments componentsJoinedByString:@" "]];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: description, NSLocalizedRecoverySuggestionErrorKey: output };
completion(output, [NSError errorWithDomain:ATZShellErrorDomain code:ATZShellTerminationStatusError userInfo:userInfo]);
}
}];

Expand All @@ -92,8 +93,9 @@ - (void)tryToLaunchTask:(NSTask *)shellTask completionIfFailed:(void(^)(NSString
[shellTask launch];
}
@catch (NSException *exception) {
NSLog(@"Shell command execution failed! %@", exception);
completion(nil, [NSError errorWithDomain:exception.reason code:667 userInfo:nil]);
NSLog(@"Shell command execution failed! %@ (%@)", exception, shellTask.launchPath);
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: exception.reason, NSLocalizedRecoverySuggestionErrorKey: shellTask.launchPath };
completion(nil, [NSError errorWithDomain:ATZShellErrorDomain code:ATZShellLaunchError userInfo:userInfo]);
}
}

Expand Down
7 changes: 7 additions & 0 deletions Alcatraz/Installers/ATZInstaller.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ static NSString *const DOWNLOADING_FORMAT = @"Downloading %@...";
static NSString *const INSTALLING_FORMAT = @"Installing %@...";
static NSString *const UPDATING_FORMAT = @"Updating %@...";

static NSString *const ATZInstallerErrorDomain = @"ATZInstallerErrorDomain";
NS_ENUM(NSInteger)
{
ATZInstallerXcodeProjectNotFoundError = 666,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 🔥 🔥

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kattrali is that good or bad fire? 😬

Copy link
Collaborator

@supermarin supermarin Jun 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guillaume-algis @kattrali knows fires, she has the best fires!

ATZInstallerBundleNotFoundError = 669
};

@interface ATZInstaller : NSObject

+ (instancetype)sharedInstaller;
Expand Down
57 changes: 37 additions & 20 deletions Alcatraz/Installers/ATZPluginInstaller.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
static NSString *const PROJECT = @"-project";
static NSString *const CLEAN = @"clean";
static NSString *const BUILD = @"build";
static NSString *const XCODEPROJ = @".xcodeproj";
static NSString *const XCODEPROJ = @"xcodeproj";
static NSString *const PROJECT_PBXPROJ = @"project.pbxproj";

@implementation ATZPluginInstaller
Expand Down Expand Up @@ -92,7 +92,9 @@ - (void)reloadXcodeForPackage:(ATZPackage *)plugin completion:(void(^)(NSError *
NSLog(@"Trying to reload plugin: %@ with bundle: %@", plugin.name, pluginBundle);

if (!pluginBundle) {
completion([NSError errorWithDomain:@"Bundle was not found" code:669 userInfo:nil]);
NSString *description = [NSString stringWithFormat:@"Bundle for %@ was not found", plugin.name];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: description };
completion([NSError errorWithDomain:ATZInstallerErrorDomain code:ATZInstallerBundleNotFoundError userInfo:userInfo]);
return;
}
else if ([pluginBundle isLoaded]) {
Expand All @@ -113,12 +115,10 @@ - (void)reloadXcodeForPackage:(ATZPackage *)plugin completion:(void(^)(NSError *
#pragma mark - Private

- (void)buildPlugin:(ATZPlugin *)plugin completion:(void (^)(NSError *))completion {

NSString *xcodeProjPath;

@try { xcodeProjPath = [self findXcodeprojPathForPlugin:plugin]; }
@catch (NSException *exception) {
completion([NSError errorWithDomain:exception.reason code:666 userInfo:nil]);
NSError *xcodeProjError;
NSString *xcodeProjPath = [self findXcodeprojPathForPackage:plugin error:&xcodeProjError];
if (!xcodeProjPath) {
completion(xcodeProjError);
return;
}

Expand All @@ -130,25 +130,42 @@ - (void)buildPlugin:(ATZPlugin *)plugin completion:(void (^)(NSError *))completi
}];
}

- (NSString *)findXcodeprojPathForPlugin:(ATZPlugin *)plugin {
NSString *clonedDirectory = [self pathForDownloadedPackage:plugin];
NSString *xcodeProjFilename = [plugin.name stringByAppendingString:XCODEPROJ];
- (NSString *)findXcodeprojPathForPackage:(ATZPackage *)package error:(NSError **)error {
NSString *clonedDirectory = [self pathForDownloadedPackage:package];
NSString *xcodeProjFilename = [package.name stringByAppendingPathExtension:XCODEPROJ];
NSMutableArray *allXcodeProjFilenames = [NSMutableArray new];

NSDirectoryEnumerator *enumerator = [[NSFileManager sharedManager] enumeratorAtPath:clonedDirectory];
NSString *directoryEntry;

while (directoryEntry = [enumerator nextObject])
if ([directoryEntry.pathComponents.lastObject isEqualToString:xcodeProjFilename])
for (NSString *directoryEntry in enumerator)
{
NSString *fileName = directoryEntry.pathComponents.lastObject;
if ([fileName isEqualToString:xcodeProjFilename]) {
return [clonedDirectory stringByAppendingPathComponent:directoryEntry];
} else if ([fileName.pathExtension isEqualToString:XCODEPROJ]) {
[allXcodeProjFilenames addObject:directoryEntry];
}
}

NSLog(@"Wasn't able to find: %@ in %@", xcodeProjFilename, clonedDirectory);
@throw [NSException exceptionWithName:@"Not found" reason:@".xcodeproj was not found" userInfo:nil];
if (allXcodeProjFilenames.count == 1) {
return [clonedDirectory stringByAppendingPathComponent:allXcodeProjFilenames[0]];
}

if (error) {
NSString *description = [NSString stringWithFormat:@"No .xcodeproj file was found for %@", package.name];
NSString *recoverySuggestion;
if (allXcodeProjFilenames.count == 0) {
recoverySuggestion = [NSString stringWithFormat:@"No .xcodeproj file was found in \"%@\"", clonedDirectory];
} else {
recoverySuggestion = [NSString stringWithFormat:@"Found several .xcodeproj files in \"%@\" {%@}", clonedDirectory, [allXcodeProjFilenames componentsJoinedByString:@","]];
}
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: description, NSLocalizedRecoverySuggestionErrorKey: recoverySuggestion };
*error = [NSError errorWithDomain:ATZInstallerErrorDomain code:ATZInstallerXcodeProjectNotFoundError userInfo:userInfo];
}
return nil;
}

- (NSString *)installNameFromPbxproj:(ATZPackage *)package {
NSString *pbxprojPath = [[[[self pathForDownloadedPackage:package]
stringByAppendingPathComponent:package.name] stringByAppendingString:XCODEPROJ]
stringByAppendingPathComponent:PROJECT_PBXPROJ];
NSString *pbxprojPath = [[self findXcodeprojPathForPackage:package error:NULL] stringByAppendingPathComponent:PROJECT_PBXPROJ];

return [ATZPbxprojParser xcpluginNameFromPbxproj:pbxprojPath];
}
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.0

- Plugins are no longer required to have a .xcodeproj filename matching their `name` in `packages.json` (#471)

## 1.1.19

- Fix a crash caused by invalid downloaded image data being displayed anyway. #320 #334 #335 #479
Expand Down