Module: XCSim
- Defined in:
- lib/xcsim/rbConstants.rb,
lib/xcsim/rbList.rb,
lib/xcsim/rbOSID.rb,
lib/xcsim/rbReports.rb,
lib/xcsim/rbDeviceID.rb,
lib/xcsim/rbDeviceSet.rb,
lib/xcsim/rbOSDevices.rb,
lib/xcsim/rbAppBundles.rb,
lib/xcsim/rbBundleInfo.rb
Overview
XCSim module contains utility for parsing iOS Simulator metadata plist files and providing access to the bundle and data directories of the applications installed on iOS Simulator.
Defined Under Namespace
Classes: BundleInfo, BundleNotFoundError, DeviceID, DeviceListItem, DeviceNotFoundError, GetBundle, GetDeviceList, NonUniqueBundleIDError, OSDevices, OSID, OSNotFoundError
Constant Summary collapse
- SIMULATORS_ROOT =
Absolute path of the directory, which stores all of thr iOS Simulator data
File.("~/Library/Developer/CoreSimulator/Devices")
- DEVICE_APP_BUNDLES_RELATIVE_PATH =
Path for the application bundles directory relative to a concrete iOS Simulator device dir
"data/Containers/Bundle/Application"
- DEVICE_APP_DATA_RELATIVE_PATH =
Path for the application data directory relative to a concrete iOS Simulator device dir
"data/Containers/Data/Application"
- DEVICE_SET_PLIST =
Name of the
device_set.plist
file "device_set.plist"
- BUNDLE_METADATA_PLIST =
Name of the plist file containing a certain application’s metadata
".com.apple.mobile_container_manager.metadata.plist"
- METADATA_ID =
A key in application metadata plist file, which corresponds to the bundle ID of the application
"MCMMetadataIdentifier"
- @@deviceSet =
parseDeviceSet("#{XCSim::SIMULATORS_ROOT}/#{XCSim::DEVICE_SET_PLIST}")
Class Method Summary collapse
-
.defaultDeviceName ⇒ Object
Returns the default device name for use in #xcsim bundle mode when no
:device
option is provided. -
.defaultOSName ⇒ Object
Returns default OS name for use in #xcsim bundle mode when no
:os
option is provided. -
.deviceSet ⇒ Object
Returns default device set of OSDevices class (as parsed by #parseDeviceSet with default iOS Simulators path).
-
.findBundleDataPath(deviceID, bundleID) ⇒ Object
call-seq: findBundleDataPath(deviceID, bundleID) => String.
-
.parseDeviceSet(path) ⇒ Object
call-seq: parseDeviceSet(absolutePath) => Hash.
-
.parseInstalledBundles(deviceID) ⇒ Object
call-seq: parseInstalledBundles(deviceID) => Hash.
-
.reportFromDeviceList(list) ⇒ Object
Prepares a more human-readable report from an array of DeviceListItem objects.
Class Method Details
.defaultDeviceName ⇒ Object
Returns the default device name for use in #xcsim bundle mode when no :device
option is provided.
61 62 63 |
# File 'lib/xcsim/rbDeviceSet.rb', line 61 def self.defaultDeviceName "iPhone 5s" end |
.defaultOSName ⇒ Object
Returns default OS name for use in #xcsim bundle mode when no :os
option is provided. Selects the OS with the highest version number as the default.
55 56 57 |
# File 'lib/xcsim/rbDeviceSet.rb', line 55 def self.defaultOSName @@deviceSet.keys.max.to_s end |
.deviceSet ⇒ Object
Returns default device set of OSDevices class (as parsed by #parseDeviceSet with default iOS Simulators path)
49 50 51 |
# File 'lib/xcsim/rbDeviceSet.rb', line 49 def self.deviceSet @@deviceSet end |
.findBundleDataPath(deviceID, bundleID) ⇒ Object
call-seq:
findBundleDataPath(deviceID, bundleID) => String
deviceID
-
A DeviceID object representing the device simulator on which the application is installed
bundleID
-
Bundle ID of the application to search for
Finds an absolute path for application data directory of an application with a given bundle ID installed on a given device.
Searches for directories matching bundleID
inside the application data directory of the device. Raises a NonUniqueBundleIDError if multiple matching directories are found (bundle IDs are expected to be unique). Returns the found directory or nil
otherwise.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/xcsim/rbAppBundles.rb', line 45 def self.findBundleDataPath(deviceID, bundleID) path = deviceID.appDataPath return nil unless File.directory? path subdirs = Dir.entries(path).select do |entry| File.directory? File.join(path, entry) and !(entry =='.' || entry == '..') end = subdirs.map do |dir| = "#{path}/#{dir}/#{BUNDLE_METADATA_PLIST}" if File.exists? plist = CFPropertyList::List.new(:file => ) plist = CFPropertyList.native_types(plist.value) { :plist => plist, :dir => "#{path}/#{dir}" } else nil end end .compact result = .select{ |pair| pair[:plist][METADATA_ID] == bundleID } if result.count > 1 raise NonUniqueBundleIDError.new(deviceID, bundleID, result.map{|pair| pair[:dir]}) elsif result.empty? return nil else result.first[:dir] end end |
.parseDeviceSet(path) ⇒ Object
call-seq:
parseDeviceSet(absolutePath) => Hash
Parses a device_set.plist
file located at the given path
Returns a Hash of OSID => OSDevices
for iOS Simulator OSes, which have at least one device simulator installed.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/xcsim/rbDeviceSet.rb', line 18 def self.parseDeviceSet(path) plist = CFPropertyList::List.new(:file => path) plist = CFPropertyList.native_types(plist.value) defaultDevices = plist["DefaultDevices"] osIDs = defaultDevices .keys .map{|s| OSID.fromPrefixedString(s) } .compact oses = osIDs.map do |id| osDevices = defaultDevices[id.key] devices = osDevices .keys .map{ |s| DeviceID.fromPrefixedString(s, osDevices[s])} .compact .select{ |device| File.directory? device.appBundlesPath } .select{ |device| File.directory? device.appDataPath } (devices.count > 0) ? OSDevices.new(id, devices) : nil end .compact osHash = {} oses.each{ |os| osHash[os.id] = os } osHash end |
.parseInstalledBundles(deviceID) ⇒ Object
call-seq:
parseInstalledBundles(deviceID) => Hash
deviceID
-
A DeviceID object to search installed app bundles for
Searches the given iOS Simulator device for installed application bundles (excluding the system applications such as Safari) and returns a Hash of bundle ID string => BundleInfo
containing BundleInfo instances corresponding the found bundles.
May raise a NonUniqueBundleIDError if multiple data directories are found for one of the bundles.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/xcsim/rbAppBundles.rb', line 92 def self.parseInstalledBundles(deviceID) path = deviceID.appBundlesPath return {} unless File.directory? path subdirs = Dir.entries(path).select do |entry| File.directory? File.join(path, entry) and !(entry =='.' || entry == '..') end bundlePlists = subdirs.map do |dir| plistPath = "#{path}/#{dir}/#{BUNDLE_METADATA_PLIST}" if File.exists? plistPath plist = CFPropertyList::List.new(:file => plistPath) plist = CFPropertyList.native_types(plist.value) { :plist => plist, :dir => "#{path}/#{dir}" } else nil end end .compact bundleInfos = bundlePlists.map do |pair| bundleID = pair[:plist][METADATA_ID] bundlePath = pair[:dir] dataPath = findBundleDataPath(deviceID, bundleID) BundleInfo.new(bundleID, bundlePath, dataPath) end bundleInfosHash = {} bundleInfos.each{ |info| bundleInfosHash[info.bundleID] = info } bundleInfosHash end |
.reportFromDeviceList(list) ⇒ Object
Prepares a more human-readable report from an array of DeviceListItem objects.
Depending on the unique OS versions and device models referenced by the list
items, may return one of the following results:
- List of application bundles
-
When
list
contains a single item - List of device names
-
When
list
contains multiple devices from a single OS version - List of OS version strings
-
When
list
contains a multiple devices from multiple OS version
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/xcsim/rbReports.rb', line 13 def self.reportFromDeviceList(list) uniqueOSes = list.map{ |item| item.os.id }.uniq uniqueDevices = list.map { |item| item.device.name }.uniq countByOS = {} list.each do |item| count = countByOS[item.os.id] || 0 countByOS[item.os.id] = count+1 end if uniqueOSes.empty? || uniqueDevices.empty? raise ArgumentError elsif uniqueOSes.count == 1 && uniqueDevices.count == 1 list.first.bundles elsif uniqueOSes.count == 1 list.map{ |item| item.device.name } elsif false == (countByOS.values.include? 1) countByOS.map { |id, count| "#{id} (#{count} devices)"} else list end end |