diff --git a/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj b/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj index a82c07ba8..0154116d1 100644 --- a/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj +++ b/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ E10E4CD717298E5F004AB09E /* project.pbxproj in Resources */ = {isa = PBXBuildFile; fileRef = E164FE2A172188F300263CE3 /* project.pbxproj */; }; + E14015421740248C006C2792 /* XcodeProjectCloser.m in Sources */ = {isa = PBXBuildFile; fileRef = E14015411740248C006C2792 /* XcodeProjectCloser.m */; }; + E1401543174025B8006C2792 /* XcodeProjectCloser.m in Sources */ = {isa = PBXBuildFile; fileRef = E14015411740248C006C2792 /* XcodeProjectCloser.m */; }; E164FDD31720E77100263CE3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E164FDD21720E77100263CE3 /* Cocoa.framework */; }; E164FDDF1720E77100263CE3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E164FDDE1720E77100263CE3 /* main.m */; }; E164FDF51720EBC100263CE3 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = E164FDF41720EBC100263CE3 /* AppController.m */; }; @@ -104,6 +106,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + E14015401740248C006C2792 /* XcodeProjectCloser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XcodeProjectCloser.h; sourceTree = ""; }; + E14015411740248C006C2792 /* XcodeProjectCloser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XcodeProjectCloser.m; sourceTree = ""; }; E164FDCF1720E77100263CE3 /* XcodeCapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XcodeCapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; E164FDD21720E77100263CE3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; E164FDD51720E77100263CE3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -236,6 +240,8 @@ E1E90C371735D82B005C6D5B /* AppController.h */, E164FDFB1720EC5B00263CE3 /* XcodeCapp.m */, E1E90C401735D846005C6D5B /* XcodeCapp.h */, + E14015411740248C006C2792 /* XcodeProjectCloser.m */, + E14015401740248C006C2792 /* XcodeProjectCloser.h */, E1E90C3C1735D846005C6D5B /* Notifications.m */, E1E90C3B1735D846005C6D5B /* Notifications.h */, E1E90C3F1735D846005C6D5B /* UserDefaults.m */, @@ -447,6 +453,7 @@ E1E90C4B1735D8A1005C6D5B /* DDASLLogger.m in Sources */, E1E90C4C1735D8A1005C6D5B /* DDLog.m in Sources */, E1E90C4D1735D8A1005C6D5B /* DDTTYLogger.m in Sources */, + E14015421740248C006C2792 /* XcodeProjectCloser.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -455,6 +462,7 @@ buildActionMask = 2147483647; files = ( E171D262173C168C00210893 /* main.m in Sources */, + E1401543174025B8006C2792 /* XcodeProjectCloser.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tools/XcodeCapp/XcodeCapp/AppController.h b/Tools/XcodeCapp/XcodeCapp/AppController.h index e07a10a81..95708702c 100644 --- a/Tools/XcodeCapp/XcodeCapp/AppController.h +++ b/Tools/XcodeCapp/XcodeCapp/AppController.h @@ -24,16 +24,16 @@ @interface AppController : NSObject -@property (strong) IBOutlet NSMenu *statusMenu; -@property (assign) IBOutlet NSMenuItem *menuItemHistory; -@property (assign) IBOutlet NSMenuItem *menuItemOpenProject; -@property (assign) IBOutlet NSMenuItem *menuItemShowInFinder; +@property (strong) IBOutlet NSMenu *statusMenu; +@property (unsafe_unretained) IBOutlet NSMenuItem *menuItemHistory; +@property (unsafe_unretained) IBOutlet NSMenuItem *menuItemOpenProject; +@property (unsafe_unretained) IBOutlet NSMenuItem *menuItemShowInFinder; @property (strong) IBOutlet NSPanel *aboutWindow; @property (strong) IBOutlet NSWindow *preferencesWindow; -@property (strong) IBOutlet NSWindow *helpWindow; -@property (assign) IBOutlet PDFView *helpView; +@property (strong) IBOutlet NSWindow *helpWindow; +@property (unsafe_unretained) IBOutlet PDFView *helpView; @property (strong) IBOutlet NSUserDefaultsController *preferencesController; @property (strong) IBOutlet XcodeCapp *xcc; @@ -44,7 +44,5 @@ - (IBAction)openHelp:(id)aSender; - (IBAction)openAbout:(id)aSender; -- (BOOL)loadProjectAtPath:(NSString *)path; - @end diff --git a/Tools/XcodeCapp/XcodeCapp/AppController.m b/Tools/XcodeCapp/XcodeCapp/AppController.m index 764f76479..aeb3d19b5 100644 --- a/Tools/XcodeCapp/XcodeCapp/AppController.m +++ b/Tools/XcodeCapp/XcodeCapp/AppController.m @@ -39,6 +39,7 @@ AppController *SharedAppControllerInstance = nil; @property NSString *finderName; @property BOOL appFinishedLaunching; @property NSString *pathToOpenAtLaunch; +@property NSFileManager *fm; @end @@ -55,6 +56,7 @@ AppController *SharedAppControllerInstance = nil; - (void)awakeFromNib { SharedAppControllerInstance = self; + self.fm = [NSFileManager defaultManager]; [self registerDefaultPreferences]; [self initLogging]; @@ -77,7 +79,7 @@ AppController *SharedAppControllerInstance = nil; NSString *path = filename.stringByStandardizingPath; if (self.appFinishedLaunching) - return [self loadProjectAtPath:path]; + return [self loadProjectAtPath:path reopening:YES]; else self.pathToOpenAtLaunch = path; } @@ -110,7 +112,7 @@ AppController *SharedAppControllerInstance = nil; return; } - // If we were opened from the command line, xcc.projectPath will be set. + // If we were opened from the command line, self.pathToOpenAtLaunch will be set. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; if (!self.pathToOpenAtLaunch) @@ -124,7 +126,7 @@ AppController *SharedAppControllerInstance = nil; if (self.pathToOpenAtLaunch) { if ([[NSFileManager defaultManager] fileExistsAtPath:self.pathToOpenAtLaunch]) - [self loadProjectAtPath:self.pathToOpenAtLaunch]; + [self loadProjectAtPath:self.pathToOpenAtLaunch reopening:YES]; else [defaults removeObjectForKey:kDefaultLastOpenedPath]; } @@ -170,9 +172,15 @@ AppController *SharedAppControllerInstance = nil; [DDLogLevel setLogLevel:LOG_LEVEL_VERBOSE]; #else [DDLog addLogger:[DDASLLogger sharedInstance]]; - + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [DDLogLevel setLogLevel:(int)[defaults integerForKey:kDefaultLogLevel]]; + int logLevel = (int)[defaults integerForKey:kDefaultLogLevel]; + NSUInteger modifiers = [NSEvent modifierFlags]; + + if (modifiers & NSAlternateKeyMask) + logLevel = LOG_LEVEL_VERBOSE; + + [DDLogLevel setLogLevel:logLevel]; #endif } @@ -341,7 +349,7 @@ AppController *SharedAppControllerInstance = nil; return; NSString *projectPath = [[openPanel.URLs[0] path] stringByStandardizingPath]; - [self loadProjectAtPath:projectPath]; + [self loadProjectAtPath:projectPath reopening:YES]; } - (void)closeProject:(id)aSender @@ -357,7 +365,7 @@ AppController *SharedAppControllerInstance = nil; - (void)switchToProject:(NSMenuItem *)aSender { - [self loadProjectAtPath:aSender.representedObject]; + [self loadProjectAtPath:aSender.representedObject reopening:NO]; } - (void)clearProjectHistory:(id)aSender @@ -405,22 +413,16 @@ AppController *SharedAppControllerInstance = nil; - (BOOL)validateMenuItem:(NSMenuItem *)aMenuItem { NSMenu *menu = aMenuItem.menu; - - if (aMenuItem == self.menuItemOpenProject) - { - return !!self.xcc.projectPath; - } - else if (menu == self.recentMenu) + + if (menu == self.recentMenu) { // Disable recent items if they don't exist or are not directories, // but enable the Clear History item, which is last in the menu. if ([menu indexOfItem:aMenuItem] == menu.itemArray.count - 1) return YES; - NSFileManager *fm = [NSFileManager defaultManager]; - - BOOL exists, isDirectory; - exists = [fm fileExistsAtPath:aMenuItem.representedObject isDirectory:&isDirectory]; + BOOL isDirectory; + BOOL exists = [self.fm fileExistsAtPath:aMenuItem.representedObject isDirectory:&isDirectory]; return exists && isDirectory; } @@ -437,9 +439,9 @@ AppController *SharedAppControllerInstance = nil; #pragma mark - Private Helpers -- (BOOL)loadProjectAtPath:(NSString *)path +- (BOOL)loadProjectAtPath:(NSString *)path reopening:(BOOL)reopen { - if ([self.xcc.projectPath isEqualToString:path]) + if (!reopen && [self.xcc.projectPath isEqualToString:path]) return YES; [self closeProject:self]; diff --git a/Tools/XcodeCapp/XcodeCapp/Info.plist b/Tools/XcodeCapp/XcodeCapp/Info.plist index 3744f29e9..0467742ec 100644 --- a/Tools/XcodeCapp/XcodeCapp/Info.plist +++ b/Tools/XcodeCapp/XcodeCapp/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.0.4 + 3.0.5 CFBundleSignature ???? CFBundleVersion - 3.0.4 + 3.0.5 LSApplicationCategoryType public.app-category.developer-tools LSUIElement diff --git a/Tools/XcodeCapp/XcodeCapp/Resources/XcodeCapp help.pages b/Tools/XcodeCapp/XcodeCapp/Resources/XcodeCapp help.pages index c0fba7f8b..82f4aff42 100644 Binary files a/Tools/XcodeCapp/XcodeCapp/Resources/XcodeCapp help.pages and b/Tools/XcodeCapp/XcodeCapp/Resources/XcodeCapp help.pages differ diff --git a/Tools/XcodeCapp/XcodeCapp/Resources/help.pdf b/Tools/XcodeCapp/XcodeCapp/Resources/help.pdf index c9325748e..bb4ece531 100644 Binary files a/Tools/XcodeCapp/XcodeCapp/Resources/help.pdf and b/Tools/XcodeCapp/XcodeCapp/Resources/help.pdf differ diff --git a/Tools/XcodeCapp/XcodeCapp/XcodeCapp.h b/Tools/XcodeCapp/XcodeCapp/XcodeCapp.h index c3044e976..6ceb38619 100644 --- a/Tools/XcodeCapp/XcodeCapp/XcodeCapp.h +++ b/Tools/XcodeCapp/XcodeCapp/XcodeCapp.h @@ -55,7 +55,7 @@ extern NSString * const XCCProjectDidFinishLoadingNotification; still queued from the previous load, we compare the projectId returned by a notification with the current projectId. If they don't match, we let the notification drain. */ -@property NSInteger projectId; +@property NSInteger projectId; // An array of paths we add to the NSTask environment @property NSArray *environmentPaths; @@ -69,6 +69,9 @@ extern NSString * const XCCProjectDidFinishLoadingNotification; // Full path to the Cappuccino project root directory @property NSString *projectPath; +// Full path to the .xcodeproj +@property NSString *xcodeProjectPath; + // Full path to parser.j @property NSString *parserPath; diff --git a/Tools/XcodeCapp/XcodeCapp/XcodeCapp.m b/Tools/XcodeCapp/XcodeCapp/XcodeCapp.m index 554ce619d..3d826026d 100644 --- a/Tools/XcodeCapp/XcodeCapp/XcodeCapp.m +++ b/Tools/XcodeCapp/XcodeCapp/XcodeCapp.m @@ -26,6 +26,7 @@ #import "Notifications.h" #import "ProcessSourceOperation.h" #import "UserDefaults.h" +#import "XcodeProjectCloser.h" #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_6 @@ -50,23 +51,6 @@ enum XCCLineSpecifier { }; typedef enum XCCLineSpecifier XCCLineSpecifier; -// Used to close the Xcode project if it is open. -static const char *XCCCloseProjectScript = - "tell application \"Xcode\"\n" - "set docs to (document of every window)\n" - "repeat with doc in docs\n" - "if class of doc is workspace document then\n" - "set docURL to file of doc\n" - "set docPath to docURL as text\n" - "set docPath to POSIX path of docPath\n" - "if docPath begins with \"%@\" then\n" - "close doc\n" - "return\n" - "end if\n" - "end if\n" - "end repeat\n" - "end tell"; - // Where we put the generated Cocoa class files static NSString * const XCCSupportFolderName = @".XcodeSupport"; @@ -109,10 +93,7 @@ static NSArray *XCCDefaultIgnoredPathPredicates = nil; @property NSFileManager *fm; -// Full path to the .xcodeproj -@property NSString *xcodeProjectPath; - -// An NSString version of XCCCloseProjectScript +// An NSString version of XCCCloseXcodeProjectScript @property NSString *closeXcodeProjectScriptSource; // Full path to .xcodecapp-ignore @@ -199,7 +180,6 @@ void fsevents_callback(ConstFSEventStreamRef streamRef, self.fm = [NSFileManager defaultManager]; self.ignoredPathPredicates = [NSMutableArray new]; self.parserPath = [[NSBundle mainBundle].sharedSupportPath stringByAppendingPathComponent:@"parser.j"]; - self.closeXcodeProjectScriptSource = [NSString stringWithUTF8String:XCCCloseProjectScript]; self.appStartedTimestamp = [NSDate date]; self.projectPathsForSourcePaths = [NSMutableDictionary new]; self.xcodecappIgnorePath = @""; @@ -287,6 +267,13 @@ void fsevents_callback(ConstFSEventStreamRef streamRef, return _pathModificationDates; } +- (BOOL)xcodeProjectCanBeOpened +{ + return (self.xcodeProjectPath && + !self.isProcessing && + [self.fm fileExistsAtPath:self.xcodeProjectPath]); +} + #pragma mark - Project Management - (void)loadProjectAtPath:(NSString *)path @@ -445,14 +432,21 @@ void fsevents_callback(ConstFSEventStreamRef streamRef, } } -- (IBAction)synchronizeProject:(id)aSender +- (void)resetProject { NSString *projectPath = self.projectPath; - + [self stop]; [self removeSupportFilesAtPath:projectPath]; [self removeAllCibsAtPath:[projectPath stringByAppendingPathComponent:@"Resources"]]; - [self loadProjectAtPath:projectPath]; + + self.projectPath = projectPath; +} + +- (IBAction)synchronizeProject:(id)aSender +{ + [self resetProject]; + [self loadProjectAtPath:self.projectPath]; } - (void)removeAllCibsAtPath:(NSString *)path @@ -468,21 +462,12 @@ void fsevents_callback(ConstFSEventStreamRef streamRef, - (void)removeSupportFilesAtPath:(NSString *)projectPath { - [self closeXcodeProjectForProject:projectPath]; + [XcodeProjectCloser closeXcodeProjectForProject:projectPath]; [self.fm removeItemAtPath:self.xcodeProjectPath error:nil]; [self.fm removeItemAtPath:self.supportPath error:nil]; } -- (void)closeXcodeProjectForProject:(NSString *)projectPath -{ - NSString *source = [NSString stringWithFormat:self.closeXcodeProjectScriptSource, projectPath]; - NSAppleScript *script = [[NSAppleScript alloc] initWithSource:source]; - - NSAppleEventDescriptor *descriptor; - descriptor = [script executeAndReturnError:nil]; -} - - (void)stop { // Increment the projectId to ensure remaining notifications in the queue for the current project are ignored diff --git a/Tools/XcodeCapp/XcodeCapp/XcodeProjectCloser.h b/Tools/XcodeCapp/XcodeCapp/XcodeProjectCloser.h new file mode 100644 index 000000000..56dc8d3ae --- /dev/null +++ b/Tools/XcodeCapp/XcodeCapp/XcodeProjectCloser.h @@ -0,0 +1,15 @@ +// +// XcodeProjectCloser.h +// XcodeCapp +// +// Created by Aparajita on 5/12/13. +// Copyright (c) 2013 Cappuccino Project. All rights reserved. +// + +#import + +@interface XcodeProjectCloser : NSObject + ++ (void)closeXcodeProjectForProject:(NSString *)projectPath; + +@end diff --git a/Tools/XcodeCapp/XcodeCapp/XcodeProjectCloser.m b/Tools/XcodeCapp/XcodeCapp/XcodeProjectCloser.m new file mode 100644 index 000000000..325df5feb --- /dev/null +++ b/Tools/XcodeCapp/XcodeCapp/XcodeProjectCloser.m @@ -0,0 +1,40 @@ +// +// XcodeProjectCloser.m +// XcodeCapp +// +// Created by Aparajita on 5/12/13. +// Copyright (c) 2013 Cappuccino Project. All rights reserved. +// + +#import "XcodeProjectCloser.h" + + +// Used to close the Xcode project if it is open. +static const char *kCloseXcodeProjectScript = + "tell application \"Xcode\"\n" + "set docs to (document of every window)\n" + "repeat with doc in docs\n" + "if class of doc is workspace document then\n" + "set docPath to path of doc\n" + "if docPath begins with \"%@\" then\n" + "close doc\n" + "return\n" + "end if\n" + "end if\n" + "end repeat\n" + "end tell"; + + +@implementation XcodeProjectCloser + ++ (void)closeXcodeProjectForProject:(NSString *)projectPath +{ + NSString *format = [NSString stringWithUTF8String:kCloseXcodeProjectScript]; + NSString *source = [NSString stringWithFormat:format, projectPath]; + NSAppleScript *script = [[NSAppleScript alloc] initWithSource:source]; + + NSAppleEventDescriptor *descriptor; + descriptor = [script executeAndReturnError:nil]; +} + +@end diff --git a/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib b/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib index 255eca73d..9743d0279 100644 --- a/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib +++ b/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib @@ -186,7 +186,6 @@ - YES AppController @@ -551,7 +550,7 @@ dG9pbmUgTWVyY2FkYWwKICAgIGFudG9pbmUubWVyY2FkYWxAZ21haWwuY29tA - + 256 @@ -799,6 +798,7 @@ dG9pbmUgTWVyY2FkYWwKICAgIGFudG9pbmUubWVyY2FkYWxAZ21haWwuY29tA 268 {{137, 17}, {60, 18}} + YES -2080374784 @@ -868,6 +868,7 @@ dG9pbmUgTWVyY2FkYWwKICAgIGFudG9pbmUubWVyY2FkYWxAZ21haWwuY29tA {431, 292} + {{0, 0}, {2560, 1418}} @@ -947,6 +948,14 @@ dG9pbmUgTWVyY2FkYWwKICAgIGFudG9pbmUubWVyY2FkYWxAZ21haWwuY29tA 695 + + + delegate + + + + 874 + statusMenu @@ -1067,6 +1076,14 @@ dG9pbmUgTWVyY2FkYWwKICAgIGFudG9pbmUubWVyY2FkYWxAZ21haWwuY29tA 872 + + + menuItemOpenXcodeProject + + + + 873 + performClose: @@ -1308,62 +1325,38 @@ dG9pbmUgTWVyY2FkYWwKICAgIGFudG9pbmUubWVyY2FkYWxAZ21haWwuY29tA 800 - - - enabled: isLoadingProject - - - - - - enabled: isLoadingProject - enabled - isLoadingProject - 2 - - - 835 - enabled: projectPath.length - + enabled: projectPath.length enabled projectPath.length - 2 - 836 + 875 - enabled2: isProcessing + enabled: xcodeProjectCanBeOpened - enabled2: isProcessing - enabled2 - isProcessing - - - - - - NSNegateBoolean - - + enabled: xcodeProjectCanBeOpened + enabled + xcodeProjectCanBeOpened + 2 - 837 + 876 @@ -2143,159 +2136,9 @@ dG9pbmUgTWVyY2FkYWwKICAgIGFudG9pbmUubWVyY2FkYWxAZ21haWwuY29tA - 872 - - - - - AppController - NSObject - - id - id - id - id - id - - - - loadProject: - id - - - openAbout: - id - - - openHelp: - id - - - openPreferences: - id - - - showInFinder: - id - - - - NSPanel - PDFView - NSWindow - NSMenuItem - NSMenuItem - NSMenuItem - NSUserDefaultsController - NSWindow - NSMenu - XcodeCapp - - - - aboutWindow - NSPanel - - - helpView - PDFView - - - helpWindow - NSWindow - - - menuItemHistory - NSMenuItem - - - menuItemOpenProject - NSMenuItem - - - menuItemShowInFinder - NSMenuItem - - - preferencesController - NSUserDefaultsController - - - preferencesWindow - NSWindow - - - statusMenu - NSMenu - - - xcc - XcodeCapp - - - - IBProjectSource - ./Classes/AppController.h - - - - XcodeCapp - NSObject - - id - id - id - id - id - - - - clearErrors: - id - - - openErrorInEditor: - id - - - openErrorsPanel: - id - - - openXcodeProject: - id - - - synchronizeProject: - id - - - - NSArrayController - NSTableView - NSPanel - - - - errorListController - NSArrayController - - - errorTable - NSTableView - - - errorsPanel - NSPanel - - - - IBProjectSource - ./Classes/XcodeCapp.h - - - + 876 + 0 IBCocoaFramework diff --git a/Tools/XcodeCapp/xcc/main.m b/Tools/XcodeCapp/xcc/main.m index ba912c8f9..451663896 100644 --- a/Tools/XcodeCapp/xcc/main.m +++ b/Tools/XcodeCapp/xcc/main.m @@ -8,47 +8,138 @@ #import +#import "XcodeProjectCloser.h" + + +static void usage() +{ + fprintf(stderr, "Usage: xcc [options] [directory]\n" + "\n" + "Options:\n" + " --help Show this help and exit\n" + " --reset Resets Xcode support files before opening\n\n"); +} + +static bool handleOptions(NSMutableArray *options, NSString *path) +{ + NSFileManager *fm = [NSFileManager defaultManager]; + + path = path.stringByStandardizingPath.stringByResolvingSymlinksInPath; + + while (options.count) + { + NSString *option = options.lastObject; + [options removeLastObject]; + + if ([options containsObject:option]) + return false; + + if ([option isEqualToString:@"--reset"]) + { + if (!path) + return false; + + NSString *xcodePath = [path stringByAppendingPathComponent:@".XcodeSupport"]; + [fm removeItemAtPath:xcodePath error:nil]; + + NSString *projectName = [NSString stringWithFormat:@"%@.xcodeproj", path.lastPathComponent]; + xcodePath = [path stringByAppendingPathComponent:projectName]; + + [XcodeProjectCloser closeXcodeProjectForProject:xcodePath]; + + [fm removeItemAtPath:xcodePath error:nil]; + printf("Reset %s\n", path.UTF8String); + } + else + return false; + } + + return true; +} + +static NSString* validatePath(NSString *path) +{ + // Use an NSURL to resolve paths that start with "." + NSURL *url = [NSURL fileURLWithPath:path]; + path = url.path; + + NSFileManager *fm = [NSFileManager defaultManager]; + BOOL isDirectory; + BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDirectory]; + + if (exists && isDirectory) + return path; + else + { + if (!exists) + fprintf(stderr, "The directory %s does not exist.\n", path.UTF8String); + else + fprintf(stderr, "%s is not a directory.\n", path.UTF8String); + + return nil; + } +} + + int main(int argc, const char * argv[]) { @autoreleasepool { - BOOL validArgs = argc == 1; - NSMutableArray *arguments = [[NSMutableArray alloc] initWithObjects:@"-b", @"org.cappuccino.xcodecapp", @"-g", nil]; + NSArray *args = [[NSProcessInfo processInfo] arguments]; + BOOL validArgs = args.count == 1; + NSString *path = nil; + NSMutableArray *options = [NSMutableArray new]; - if (argc > 1) + for (NSInteger i = 1; i < args.count; ++i) { - const char *arg = argv[1]; - - if (arg[0] == '-') + NSString *arg = args[i]; + + // Once we get a directory, no other arguments are valid + if (path) { - printf("Usage: xcc [--help | directory]\n"); + validArgs = NO; + break; + } + + if ([arg hasPrefix:@"-"]) + { + [options addObject:arg]; + } + else if (!path) + { + path = validatePath(arg); + + if (path) + validArgs = YES; + else + return 1; } else { - NSString *path = [[NSString stringWithUTF8String:arg] stringByStandardizingPath]; - NSFileManager *fm = [NSFileManager defaultManager]; - BOOL isDirectory; - BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDirectory]; - - if (!exists) - fprintf(stderr, "%s: no such file or directory\n", arg); - else if (!isDirectory) - fprintf(stderr, "%s is not a directory\n", arg); - else - { - validArgs = YES; - [arguments addObject:path]; - } + validArgs = NO; + break; } } if (validArgs) { - NSTask *task = [[NSTask alloc] init]; - task.launchPath = @"/usr/bin/open"; - task.arguments = arguments; - [task launch]; + if (handleOptions(options, path)) + { + NSMutableArray *arguments = [NSMutableArray arrayWithObjects:@"-b", @"org.cappuccino.xcodecapp", @"-g", nil]; + + if (path) + [arguments addObject:path]; + + NSTask *task = [[NSTask alloc] init]; + task.launchPath = @"/usr/bin/open"; + task.arguments = arguments; + [task launch]; + } + else + usage(); } + else + usage(); } return 0;