Improve resilience of xcode-locator. LSCopyApplicationURLsForBundleIdentifier rarely will return an invalid Xcode bundle, which would lead to xcode-locator failure. To work around this issue, we double check that the given NSBundle has the same bundleIdentifier as Xcode. RELNOTES: None. PiperOrigin-RevId: 214264402
diff --git a/tools/osx/xcode_locator.m b/tools/osx/xcode_locator.m index e247395..cd44267 100644 --- a/tools/osx/xcode_locator.m +++ b/tools/osx/xcode_locator.m
@@ -116,13 +116,14 @@ // and returns nil. static NSMutableDictionary<NSString *, XcodeVersionEntry *> *FindXcodes() __attribute((ns_returns_retained)) { - CFStringRef bundleID = CFSTR("com.apple.dt.Xcode"); + CFStringRef cfBundleID = CFSTR("com.apple.dt.Xcode"); + NSString *bundleID = (__bridge NSString *)cfBundleID; NSMutableDictionary<NSString *, XcodeVersionEntry *> *dict = [[NSMutableDictionary alloc] init]; CFErrorRef cfError; NSArray *array = CFBridgingRelease(LSCopyApplicationURLsForBundleIdentifier( - bundleID, &cfError)); + cfBundleID, &cfError)); if (array == nil) { NSError *nsError = (__bridge NSError *)cfError; fprintf(stderr, "error: %s\n", nsError.description.UTF8String); @@ -150,6 +151,19 @@ continue; } + // LSCopyApplicationURLsForBundleIdentifier seems to sometimes return + // invalid bundles (e.g. an arbitrary folder), which we should ignore (but + // don't treat as an error). + // + // To work around this issue, we double check to make sure the NSBundle's + // bundleIdentifier is that of Xcode's, as invalid bundles won't match. + if (![bundle.bundleIdentifier isEqualToString:bundleID]) { + NSLog(@"WARNING: Ignoring bundle %@ due to bundleID mismatch " + @"(got \"%@\" but expected \"%@\"); info: %@", + url, bundle.bundleIdentifier, bundleID, bundle.infoDictionary); + continue; + } + NSString *versionKey = @"CFBundleShortVersionString"; NSString *version = [bundle.infoDictionary objectForKey:versionKey]; if (version == nil) {