Skip to content

Instantly share code, notes, and snippets.

@ksuther
Created April 7, 2016 16:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ksuther/26c54194109c10f5598979e01df2b1b7 to your computer and use it in GitHub Desktop.
Save ksuther/26c54194109c10f5598979e01df2b1b7 to your computer and use it in GitHub Desktop.
Remove duplicate provisioning profiles from MobileDevice
#!/usr/bin/env xcrun swift
// Remove duplicated provisioning profiles in ~/Library/MobileDevice/Provisioning Profiles
// The most recently created profile is kept
// Usage: xcrun swift remove_duplicate_profiles.swift
import Foundation
import Security
let profilesURL = NSURL.fileURLWithPath(("~/Library/MobileDevice/Provisioning Profiles" as NSString).stringByExpandingTildeInPath);
var files = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(profilesURL, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions());
files = files.filter({$0.pathExtension == "mobileprovision" || $0.pathExtension == "provisionprofile"});
var datesForProfiles: Dictionary<String, NSDate> = Dictionary();
var URLsForProfiles: Dictionary<String, NSURL> = Dictionary();
// Go through all the provisioning profiles and figure out which ones are the most recently created
for nextFile in files {
let data = NSData.init(contentsOfURL: nextFile);
var decoder: CMSDecoder?;
var decodedData: CFData?;
CMSDecoderCreate(&decoder);
CMSDecoderUpdateMessage(decoder!, data!.bytes, data!.length);
CMSDecoderFinalizeMessage(decoder!);
CMSDecoderCopyContent(decoder!, &decodedData);
if let plistData = decodedData {
let propertyList = try NSPropertyListSerialization.propertyListWithData(plistData, options: NSPropertyListReadOptions(), format: nil);
let profileName = propertyList["Name"] as! String;
let creationDate = propertyList["CreationDate"] as? NSDate;
let existingCreationDate = datesForProfiles[profileName];
if existingCreationDate == nil || creationDate?.compare(existingCreationDate!) == NSComparisonResult.OrderedDescending {
datesForProfiles[profileName] = creationDate;
URLsForProfiles[profileName] = nextFile;
}
}
}
// Intersect the most recent profiles and all the profiles and move the remaining profiles to the trash
let profilesToKeep = Set(URLsForProfiles.values);
let profilesToRemove = Set(files).subtract(profilesToKeep);
for nextProfileToRemove in profilesToRemove {
print("Removing old profile: \(nextProfileToRemove.lastPathComponent!)");
do {
try NSFileManager.defaultManager().removeItemAtURL(nextProfileToRemove)
} catch let error as NSError {
print("Error removing item: \(error)");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment