Skip to content

Commit

Permalink
v1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
watr committed Aug 12, 2014
1 parent 0ea2f6c commit 439d379
Show file tree
Hide file tree
Showing 24 changed files with 1,359 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "STPrivilegedTask"]
path = STPrivilegedTask
url = https://github.com/watr/STPrivilegedTask.git
1 change: 1 addition & 0 deletions STPrivilegedTask
Submodule STPrivilegedTask added at d41506
593 changes: 593 additions & 0 deletions Xcode-Selector.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions Xcode-Selector/AppDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDelegate>

@property (weak) IBOutlet NSWindow *window;

@property (weak) IBOutlet NSButton *selectButton;

@property (strong) IBOutlet NSArrayController *xcodeItemsController;

- (IBAction)realoadAction:(id)sender;

- (IBAction)selectAction:(id)sender;

@end
88 changes: 88 additions & 0 deletions Xcode-Selector/AppDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@

#import "AppDelegate.h"
#import "XcodeItem.h"
#import "XcodeHelper.h"

@interface AppDelegate ()

- (void)reload;

@end

@implementation AppDelegate

#pragma mark NSApplicationDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self reload];

[self.window center];
[self.window makeKeyAndOrderFront:self];
}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
return YES;
}

#pragma mark NSTableViewDelegate

- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
[self.selectButton setEnabled:((self.xcodeItemsController.selectedObjects.count == 1) &&
(! ((XcodeItem *)self.xcodeItemsController.selectedObjects[0]).selected))];
}

#pragma mark -

- (IBAction)realoadAction:(id)sender {
[self reload];
}

- (IBAction)selectAction:(id)sender {
XcodeItem *item =
self.xcodeItemsController.selectedObjects[0];

if (item) {
NSString *selectedXcodePath = [XcodeHelper selectedXcodePath];
if (! [selectedXcodePath isEqualToString:item.xcodeDeveloperPath]) {
BOOL result = [XcodeHelper selectXcodeDeveloperDirectoryPath:item.xcodeDeveloperPath];
(void)result;
[self reload];
}
}
}

#pragma mark class extension

- (void)reload
{
NSString *selectedXcodePath = [XcodeHelper selectedXcodePath];
__block BOOL currentSelectedXcodeNotFound = YES;

[self.xcodeItemsController removeObjectsAtArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self.xcodeItemsController.arrangedObjects count])]];

[[XcodeHelper xcodeApplicationPathsExceptOtherVolumes:YES] enumerateObjectsUsingBlock:
^(NSString *xcodeApplicationPath, NSUInteger idx, BOOL *stop) {
XcodeItem *item = [XcodeItem itemWithXcodeApplicationPath:xcodeApplicationPath];

BOOL isSelected = [selectedXcodePath hasPrefix:xcodeApplicationPath];
item.selected = isSelected;
[self.xcodeItemsController addObject:item];

if (isSelected) {
currentSelectedXcodeNotFound = NO;
[self.xcodeItemsController setSelectedObjects:@[item]];
}
}];

if (currentSelectedXcodeNotFound) {
XcodeItem *item = [XcodeItem itemWithXcodeApplicationPath:selectedXcodePath];
item.selected = YES;
[self.xcodeItemsController addObject:item];
[self.xcodeItemsController setSelectedObjects:@[item]];
}
}

@end
283 changes: 283 additions & 0 deletions Xcode-Selector/Base.lproj/MainMenu.xib

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions Xcode-Selector/Images.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "appicon.png",
"scale" : "1x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "appicon@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions Xcode-Selector/Xcode-Selector-Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.prancee.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>LSUIElement</key>
<false/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 prancee.com. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
9 changes: 9 additions & 0 deletions Xcode-Selector/Xcode-Selector-Prefix.pch
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//

#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
16 changes: 16 additions & 0 deletions Xcode-Selector/XcodeHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

#import <Foundation/Foundation.h>

@interface XcodeHelper : NSObject

+ (NSArray *)xcodeApplicationPathsExceptOtherVolumes:(BOOL)except;

+ (NSString *)selectedXcodePath;

+ (NSString *)xcodeTitleWithApplicationPath:(NSString *)xcodeApplicaionPath;

+ (NSString *)xcodeDeveloperDirectoryPathCreateWithApplicationPath:(NSString *)xcodeApplicationPath;

+ (BOOL)selectXcodeDeveloperDirectoryPath:(NSString *)developerDirectoryPath;

@end
93 changes: 93 additions & 0 deletions Xcode-Selector/XcodeHelper.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@

#import "XcodeHelper.h"
#import "STPrivilegedTask.h"

@implementation XcodeHelper

+ (NSString *)selectedXcodePath
{
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/xcode-select"];
[task setArguments:@[@"-p"]];
NSPipe *outPipe = [NSPipe pipe];
[task setStandardOutput:outPipe];

NSFileHandle *fileHandle = [outPipe fileHandleForReading];
[task launch];
[task waitUntilExit];

NSData *data = [fileHandle readDataToEndOfFile];
NSString *outString = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];

return outString;
}

+ (NSArray *)xcodeApplicationPathsExceptOtherVolumes:(BOOL)except;
{
NSMutableArray *xcodePaths = [@[] mutableCopy];
MDQueryRef query = MDQueryCreate(NULL,
(__bridge CFStringRef)(@"kMDItemKind == 'Application' &&"
"kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode"),
NULL,
NULL);
if (MDQueryExecute(query,
kMDQuerySynchronous))
{
NSInteger resultCount = MDQueryGetResultCount(query);
for (NSInteger i = 0; i < resultCount; i++) {
MDItemRef const item = (MDItemRef const)MDQueryGetResultAtIndex(query,
i);
NSString *path = (__bridge_transfer NSString *)MDItemCopyAttribute(item, kMDItemPath);
if (path &&
((! except) ||
(! [path hasPrefix:@"/Volumes/"])))
{
[xcodePaths addObject:path];
}
}
}
return (xcodePaths.count > 0 ? [NSArray arrayWithArray:xcodePaths] : nil);
}

+ (NSString *)xcodeTitleWithApplicationPath:(NSString *)xcodeApplicaionPath
{
NSBundle *xcodeApplicationBundle = [NSBundle bundleWithPath:xcodeApplicaionPath];
__block NSString *title = nil;
if (xcodeApplicationBundle) {
NSDictionary *info = [xcodeApplicationBundle infoDictionary];
NSString *versionString = [info objectForKey:@"CFBundleShortVersionString"];

title = [NSString stringWithFormat:@"%@ (%@)", [[NSFileManager defaultManager] displayNameAtPath:xcodeApplicaionPath], versionString];
}
else {
[[xcodeApplicaionPath pathComponents] enumerateObjectsWithOptions:NSEnumerationReverse
usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *component = (NSString *)obj;
if ([[component pathExtension] isEqualToString:@"app"]) {
title = component;
*stop = YES;
}
}];
}
return title;
}

+ (NSString *)xcodeDeveloperDirectoryPathCreateWithApplicationPath:(NSString *)xcodeApplicationPath
{
return [[xcodeApplicationPath stringByAppendingPathComponent:@"Contents"] stringByAppendingPathComponent:@"Developer"];
}

+ (BOOL)selectXcodeDeveloperDirectoryPath:(NSString *)developerDirectoryPath
{
[STPrivilegedTask launchedPrivilegedTaskWithLaunchPath:@"/usr/bin/xcode-select"
arguments:@[@"-s", developerDirectoryPath]];
BOOL succeeded = ({
NSString *selectedXcodePath = [XcodeHelper selectedXcodePath];
([developerDirectoryPath isEqualToString:[XcodeHelper xcodeDeveloperDirectoryPathCreateWithApplicationPath:selectedXcodePath]]);
});
return succeeded;
}


@end
18 changes: 18 additions & 0 deletions Xcode-Selector/XcodeItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

#import <Foundation/Foundation.h>

@interface XcodeItem : NSObject

@property (nonatomic, copy) NSString *title;

@property (nonatomic, strong) NSImage *image;

@property (nonatomic, copy) NSString *xcodeDeveloperPath;

@property (nonatomic, assign) BOOL selected;

+ (XcodeItem *)itemWithXcodeApplicationPath:(NSString *)path;

- (XcodeItem *)initWithXcodeApplicationPath:(NSString *)path;

@end
Loading

0 comments on commit 439d379

Please sign in to comment.