aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar jmmv <jmmv@google.com>2018-07-31 09:10:59 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-07-31 09:12:10 -0700
commita0f77be2887cc69ea43991dfb5a58934eb539c65 (patch)
treeb42835114234b7753d2b3d2e8cc0a48898787b02 /tools
parent04d8a923ffd81b35eca52e34accbab930571d626 (diff)
Break out xcode-locator's main function into smaller chunks.
This is intended to be a refactoring without functional changes for my own sanity in understanding what this code does. Except I couldn't avoid applying some visual improvements to the usage message. RELNOTES: None. PiperOrigin-RevId: 206771539
Diffstat (limited to 'tools')
-rw-r--r--tools/osx/xcode_locator.m170
1 files changed, 99 insertions, 71 deletions
diff --git a/tools/osx/xcode_locator.m b/tools/osx/xcode_locator.m
index 65401006bf..dc967693c3 100644
--- a/tools/osx/xcode_locator.m
+++ b/tools/osx/xcode_locator.m
@@ -107,6 +107,100 @@ static NSString *ExpandVersion(NSString *version) {
return version;
}
+// Searches for all available Xcodes in the system and returns a dictionary that
+// maps version identifiers of any form (X, X.Y, and X.Y.Z) to the directory
+// where the Xcode bundle lives.
+//
+// If there is a problem locating the Xcodes, prints an error message and
+// returns nil.
+static NSMutableDictionary *FindXcodes() __attribute((ns_returns_retained)) {
+ NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
+ CFErrorRef cfError;
+ NSArray *array = CFBridgingRelease(LSCopyApplicationURLsForBundleIdentifier(
+ CFSTR("com.apple.dt.Xcode"), &cfError));
+ if (array == nil) {
+ NSError *nsError = (__bridge NSError *)cfError;
+ fprintf(stderr, "error: %s\n", nsError.description.UTF8String);
+ return nil;
+ }
+ for (NSURL *url in array) {
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (!bundle) {
+ fprintf(stderr, "error: Unable to open bundle at URL: %s\n",
+ url.description.UTF8String);
+ return nil;
+ }
+ NSString *version = bundle.infoDictionary[@"CFBundleShortVersionString"];
+ if (!version) {
+ fprintf(stderr, "error: Unable to extract CFBundleShortVersionString "
+ "from URL: %s\n", url.description.UTF8String);
+ return nil;
+ }
+ version = ExpandVersion(version);
+ NSURL *developerDir =
+ [url URLByAppendingPathComponent:@"Contents/Developer"];
+ XcodeVersionEntry *entry =
+ [[XcodeVersionEntry alloc] initWithVersion:version url:developerDir];
+ AddEntryToDictionary(entry, dict);
+ }
+ return dict;
+}
+
+// Prints out the located Xcodes as a set of lines where each line contains the
+// list of versions for a given Xcode and its location on disk.
+static void DumpAsVersionsOnly(FILE *output, NSMutableDictionary *dict) {
+ NSSet *distinctValues = [[NSSet alloc] initWithArray:[dict allValues]];
+ NSMutableDictionary *aliasDict = [[NSMutableDictionary alloc] init];
+ for (XcodeVersionEntry *value in distinctValues) {
+ NSString *versionString = value.version;
+ if (aliasDict[versionString] == nil) {
+ aliasDict[versionString] = [[NSMutableSet alloc] init];
+ }
+ [aliasDict[versionString]
+ addObjectsFromArray:[dict allKeysForObject:value]];
+ }
+ for (NSString *version in aliasDict) {
+ XcodeVersionEntry *entry = dict[version];
+ fprintf(output, "%s:%s:%s\n",
+ version.UTF8String,
+ [[aliasDict[version] allObjects]
+ componentsJoinedByString: @","].UTF8String,
+ entry.url.fileSystemRepresentation);
+ }
+}
+
+// Prints out the located Xcodes in JSON format.
+static void DumpAsJson(FILE *output, NSMutableDictionary *dict) {
+ fprintf(output, "{\n");
+ for (NSString *version in dict) {
+ XcodeVersionEntry *entry = dict[version];
+ fprintf(output, "\t\"%s\": \"%s\",\n",
+ version.UTF8String, entry.url.fileSystemRepresentation);
+ }
+ fprintf(output, "}\n");
+}
+
+// Dumps usage information.
+static void usage(FILE *output) {
+ fprintf(
+ output,
+ "xcode-locator [-v|<version_number>]"
+ "\n\n"
+ "Given a version number or partial version number in x.y.z format, "
+ "will attempt to return the path to the appropriate developer "
+ "directory."
+ "\n\n"
+ "Omitting a version number will list all available versions in JSON "
+ "format, alongside their paths."
+ "\n\n"
+ "Passing -v will list all available fully-specified version numbers "
+ "along with their possible aliases and their developer directory, "
+ "each on a new line. For example:"
+ "\n\n"
+ "7.3.1:7,7.3,7.3.1:/Applications/Xcode.app/Contents/Developer"
+ "\n");
+}
+
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *versionArg = nil;
@@ -129,56 +223,14 @@ int main(int argc, const char * argv[]) {
}
}
if (versionArg == nil) {
- fprintf(
- stderr,
- "xcode-locator [-v|<version_number>]"
- "\n\n"
- "Given a version number, or partial version number in x.y.z format, "
- "will attempt to return the path to the appropriate developer "
- "directory."
- "\n"
- "Omitting a version number will list all available versions in JSON "
- "format, alongside their paths."
- "\n"
- "Passing -v will list all available fully-specified version numbers "
- "along with their possible aliases and their developer directory, "
- "each on a new line."
- "\n"
- "For example: "
- "'7.3.1:7,7.3,7.3.1:/Applications/Xcode.app/Contents/Developer'."
- "\n");
+ usage(stderr);
return 1;
}
- NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
- CFErrorRef cfError;
- NSArray *array = CFBridgingRelease(LSCopyApplicationURLsForBundleIdentifier(
- CFSTR("com.apple.dt.Xcode"), &cfError));
- if (array == nil) {
- NSError *nsError = (__bridge NSError *)cfError;
- fprintf(stderr, "error: %s\n", nsError.description.UTF8String);
+ NSMutableDictionary *dict = FindXcodes();
+ if (dict == nil) {
return 1;
}
- for (NSURL *url in array) {
- NSBundle *bundle = [NSBundle bundleWithURL:url];
- if (!bundle) {
- fprintf(stderr, "error: Unable to open bundle at URL: %s\n",
- url.description.UTF8String);
- return 1;
- }
- NSString *version = bundle.infoDictionary[@"CFBundleShortVersionString"];
- if (!version) {
- fprintf(stderr, "error: Unable to extract CFBundleShortVersionString "
- "from URL: %s\n", url.description.UTF8String);
- return 1;
- }
- version = ExpandVersion(version);
- NSURL *developerDir =
- [url URLByAppendingPathComponent:@"Contents/Developer"];
- XcodeVersionEntry *entry =
- [[XcodeVersionEntry alloc] initWithVersion:version url:developerDir];
- AddEntryToDictionary(entry, dict);
- }
XcodeVersionEntry *entry = [dict objectForKey:versionArg];
if (entry) {
@@ -187,33 +239,9 @@ int main(int argc, const char * argv[]) {
}
if (versionsOnly) {
- NSSet *distinctValues = [[NSSet alloc] initWithArray:[dict allValues]];
- NSMutableDictionary *aliasDict = [[NSMutableDictionary alloc] init];
- for (XcodeVersionEntry *value in distinctValues) {
- NSString *versionString = value.version;
- if (aliasDict[versionString] == nil) {
- aliasDict[versionString] = [[NSMutableSet alloc] init];
- }
- [aliasDict[versionString]
- addObjectsFromArray:[dict allKeysForObject:value]];
- }
- for (NSString *version in aliasDict) {
- XcodeVersionEntry *entry = dict[version];
- printf("%s:%s:%s\n",
- version.UTF8String,
- [[aliasDict[version] allObjects]
- componentsJoinedByString: @","].UTF8String,
- entry.url.fileSystemRepresentation);
- }
+ DumpAsVersionsOnly(stdout, dict);
} else {
- // Print out list in json format.
- printf("{\n");
- for (NSString *version in dict) {
- XcodeVersionEntry *entry = dict[version];
- printf("\t\"%s\": \"%s\",\n",
- version.UTF8String, entry.url.fileSystemRepresentation);
- }
- printf("}\n");
+ DumpAsJson(stdout, dict);
}
return ([@"" isEqualToString:versionArg] ? 0 : 1);
}