Skip to content

Instantly share code, notes, and snippets.

@zats
Last active March 5, 2021 01:32
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save zats/b532ed0730037c319494 to your computer and use it in GitHub Desktop.
Save zats/b532ed0730037c319494 to your computer and use it in GitHub Desktop.
Update all your plugins for the latest Xcode beta with a single
#!/usr/bin/env xcrun swift
// $ chmod +x script.swift
// $ ./script.swift
// or $ ./script.swift -xcode=/Applications/Xcode-beta.app
import Foundation
@noreturn private func failWithError(message: String) {
print("🚫 \(message)")
exit(EXIT_FAILURE)
}
private func warnWithMessage(message: String) {
print("⚠️ \(message)")
}
let xcodeCompatibilityUUIDKey = "DVTPlugInCompatibilityUUID"
let pluginCompatibilityUUIDsKey = "DVTPlugInCompatibilityUUIDs"
let xcodeArgumentPrefix = "-xcode="
let arguments = Process.arguments
let xcodeArgument: String = arguments.filter{ $0.hasPrefix(xcodeArgumentPrefix) }.first ?? "\(xcodeArgumentPrefix)/Applications/Xcode.app"
let xcodePath = xcodeArgument.substringFromIndex(xcodeArgument.startIndex.advancedBy(xcodeArgumentPrefix.characters.count))
let xcodeInfoURL = NSURL(fileURLWithPath: xcodePath).URLByAppendingPathComponent("Contents/Info.plist")
print("Xcode: \(xcodePath)")
let fileManager = NSFileManager.defaultManager()
// Xcode Info.plist
guard let dic = NSDictionary(contentsOfURL: xcodeInfoURL), compatibilityUUIDValue = dic[xcodeCompatibilityUUIDKey] as? String else {
failWithError("Failed to read \(xcodeCompatibilityUUIDKey) from \(xcodeInfoURL)")
}
print("DVTPlugInCompatibilityUUID: \(compatibilityUUIDValue)")
// Xcode plugins
let pluginsURL = NSURL(fileURLWithPath: ("~/Library/Application Support/Developer/Shared/Xcode/Plug-ins" as NSString).stringByExpandingTildeInPath)
guard let pluginURLs = try? fileManager.contentsOfDirectoryAtURL(pluginsURL, includingPropertiesForKeys: nil, options: [.SkipsSubdirectoryDescendants, .SkipsPackageDescendants]) else {
failWithError("No Xcode plugins found at \(pluginsURL)")
}
for pluginURL in pluginURLs {
if pluginURL.pathExtension != "xcplugin" {
continue
}
guard let pluginName = (pluginURL.lastPathComponent as NSString?)?.stringByDeletingPathExtension else {
continue
}
let pluginInfoPlistURL = pluginURL.URLByAppendingPathComponent("Contents/Info.plist")
guard var pluginInfoPlist = NSMutableDictionary(contentsOfURL: pluginInfoPlistURL) else {
warnWithMessage("Failed to read Info.plist at \(pluginInfoPlistURL)")
continue
}
// Updating DVTPlugInCompatibilityUUIDs section if needed
if pluginInfoPlist[pluginCompatibilityUUIDsKey] == nil {
pluginInfoPlist[pluginCompatibilityUUIDsKey] = [compatibilityUUIDValue]
} else if var compatibilityUUIDs = pluginInfoPlist[pluginCompatibilityUUIDsKey] as? [String] {
if compatibilityUUIDs.contains(compatibilityUUIDValue) {
print("\(pluginName) is already compatible")
continue
}
compatibilityUUIDs.append(compatibilityUUIDValue)
pluginInfoPlist[pluginCompatibilityUUIDsKey] = compatibilityUUIDs
}
guard let infoPlistData = try? NSPropertyListSerialization.dataWithPropertyList(pluginInfoPlist, format: .XMLFormat_v1_0, options: 0) else {
failWithError("Failed to write Info.plist at \(pluginInfoPlistURL)")
}
do {
try infoPlistData.writeToURL(pluginInfoPlistURL, options: [.DataWritingAtomic])
print("\(pluginName) ✅")
} catch {
failWithError("Failed to write plugin Info plist at \(pluginInfoPlistURL)")
}
}
exit(EXIT_SUCCESS)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment