pprof 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7691660bb69c7c6f6f4fedb4722dc0e647183378e5aa79cfa0ce2a80f7e4cef
4
- data.tar.gz: ae54346cc1d76c10a89468b605a698727ff38909f683bed7ff8a6d779c6605b0
3
+ metadata.gz: ae8d524121a74832a72453cd1e7b7a9ab1ca9d109fbca14d8cb1ce1ef8e77747
4
+ data.tar.gz: 682cfa8a82f248b977c384af168129a5395f65fb440411e7d1a919726ec7bfe6
5
5
  SHA512:
6
- metadata.gz: 9b2490137336562c025610bbfc7de8b0fe1a177005b9a7c7cfea21310fedb3f77164745303dc08b1816d3e8dd5a0f7a5aaa71373a71c784921982d36da4e876f
7
- data.tar.gz: 22665cd4ba32a996577a8ed8099348f29193fb88589a32b1faaf8ca03298a971902373d23cdad568c59a1b6e23f59f81e3c0a3e543e8173c18ddd71f098379a5
6
+ metadata.gz: b740f1dd3808135315ea487366acb9f884c43b58067fa96e2c3272591528394371b1102a2db1445f2223aa461a28ba2d077838137b888aadc7b43063c366ccd3
7
+ data.tar.gz: 7e0f924bb2d451bc6fe6aaf4a200f0cdf0dfae5b84b841a9cfc0d2499cdb914cac8fc52074e5c9c7ebfe55fefa9aa305d97b18c91c345208906aab6335f18509
data/README.md CHANGED
@@ -6,7 +6,9 @@
6
6
 
7
7
  `pprof` is a ruby library and binary to manipulate Provisioning Profiles.
8
8
 
9
- It can help you create ruby scripts to list, get information, find and filter local Provisioning Profiles easily.
9
+ It can help you manage the Provisioning Profiles installed on your Mac (find the profiles UUIDs from the app names or bundle IDs, find detailed information on a given profile, clean up expired profiles from your Mac…) directly from the command line.
10
+
11
+ It also supports printing the output in JSON format so you can pipe the result of printing provisioning profiles info into `jq` or similar tools.
10
12
 
11
13
  ## Installation
12
14
 
@@ -32,6 +34,8 @@ _(You might need to run this command with `sudo` if your gem home is a system di
32
34
 
33
35
  ### Using it from the command line
34
36
 
37
+ #### Listing (and filtering) provisioning profiles
38
+
35
39
  ```sh
36
40
  # List all provisioning profiles
37
41
  $ pprof
@@ -65,6 +69,8 @@ $ pprof --has-devices --aps --appid com.foo
65
69
  $ pprof --exp -0 | xargs -0 rm
66
70
  ```
67
71
 
72
+ #### Printing info for a given Provisioning Profile
73
+
68
74
  ```sh
69
75
  # Print info for a given Provisioning Profile
70
76
  $ pprof '12345678-ABCD-EF90-1234-567890ABCDEF'
@@ -80,6 +86,25 @@ $ pprof --certs --devices --info '12345678-ABCD-EF90-1234-567890ABCDEF'
80
86
  $ pprof -cdi '12345678-ABCD-EF90-1234-567890ABCDEF'
81
87
  ```
82
88
 
89
+ #### Printing output in JSON
90
+
91
+ ```sh
92
+ # Print info about all your provisioning profiles as a JSON array
93
+ $ pprof --json
94
+ # Print info about all your provisioning profiles whose name contains "Foo", as a JSON array
95
+ $ pprof --name "Foo" --json
96
+ # Print info about all your provisioning profiles as a JSON array, including list of devices and certificates in each profile
97
+ $ pprof --json --devices --certs
98
+
99
+ # Print info about a specific provisioning profile as JSON object
100
+ $ pprof --json '12345678-ABCD-EF90-1234-567890ABCDEF'
101
+ # Print info about a specific provisioning profile as JSON object, including list of devices and certificates
102
+ $ pprof --json -c -d '12345678-ABCD-EF90-1234-567890ABCDEF'
103
+
104
+ # Use `jq` (https://stedolan.github.io/jq/) to post-process the JSON output and generate some custom JSON array of objects from it
105
+ $ pprof --name 'My App' --json --devices | jq '.[] | {uuid:.UUID, name:.AppIDName, nb_profiles: .ProvisionedDevices|length}'
106
+ ```
107
+
83
108
  ### Using it in Ruby
84
109
 
85
110
  ```ruby
@@ -105,7 +130,8 @@ end
105
130
 
106
131
  # And you can easily loop on all provisioning profiles and manipulate each
107
132
  dir = PProf::ProvisioningProfile::DEFAULT_DIR
108
- Dir["#{dir}/*.mobileprovision"].each do |file|
133
+ # `*.mobileprovision` are typically for iOS profiles, `*.provisionprofile` for Mac profiles
134
+ Dir["#{dir}/*.{mobileprovision,provisionprofile}"].each do |file|
109
135
  p = PProf::ProvisioningProfile.new(file)
110
136
  puts p.name
111
137
  end
data/bin/pprof CHANGED
@@ -40,6 +40,8 @@ parser = OptionParser.new do |opts|
40
40
  |Tips:
41
41
  | - If you want to search for _exact_ match, you can use and anchored RegEx like `/^InHouse$/i`
42
42
  | - To remove all expired certificates, you can use `#{opts.program_name} -e0 | xargs -0 rm`
43
+ | - You can combine the `--json` output with `jq` to generate and filter using some powerful custom outputs.
44
+ | e.g.: `#{opts.program_name} --name 'My App' --json --devices | jq '.[] | {uuid:.UUID, name:.AppIDName, nb_profiles: .ProvisionedDevices|length}'`
43
45
  BANNER
44
46
 
45
47
  opts.separator ''
@@ -86,6 +88,10 @@ parser = OptionParser.new do |opts|
86
88
  filters[:appid] = matcher(appid)
87
89
  end
88
90
 
91
+ opts.on('--platform PLATFORM', 'Filter by Platform (OSX, iOS, xrOS/visionOS, …)') do |platform|
92
+ filters[:platform] = platform
93
+ end
94
+
89
95
  opts.on('--uuid UUID', 'Filter by UUID') do |uuid|
90
96
  filters[:uuid] = matcher(uuid)
91
97
  end
@@ -142,7 +148,7 @@ unless filters.empty? || ARGV.empty?
142
148
  exit
143
149
  end
144
150
 
145
- unless options.empty? || !ARGV.empty?
151
+ unless list_options[:mode] == :json || options.empty? || !ARGV.empty?
146
152
  puts 'You should use option flags only when providing an specific path.'
147
153
  puts parser # Usage
148
154
  exit
@@ -154,7 +160,15 @@ o = PProf::OutputFormatter.new
154
160
  if ARGV.empty?
155
161
  # Print list of matching profiles
156
162
  list_options[:mode] = :path if list_options[:zero] && list_options[:mode] == :table
157
- o.print_filtered_list(PProf::ProvisioningProfile::DEFAULT_DIR, filters, list_options)
163
+ filter_func = o.filter_proc(filters)
164
+ case list_options[:mode]
165
+ when :table
166
+ o.print_table(&filter_func)
167
+ when :json
168
+ o.print_json_list(options: options, &filter_func)
169
+ else
170
+ o.print_list(options: list_options, &filter_func)
171
+ end
158
172
  else
159
173
  begin
160
174
  # Print info about given profile path/UUID
@@ -7,7 +7,7 @@ module PProf
7
7
  # A helper tool to pretty-print Provisioning Profile informations
8
8
  class OutputFormatter
9
9
  # List of properties of a `PProf::ProvisioningProfile` to print when using the `-i` flag
10
- MAIN_PROFILE_KEYS = %i[name uuid app_id_name app_id_prefix creation_date expiration_date ttl team_ids team_name]
10
+ MAIN_PROFILE_KEYS = %i[name uuid app_id_name app_id_prefix creation_date expiration_date ttl team_ids team_name].freeze
11
11
 
12
12
  # Initialize a new OutputFormatter
13
13
  #
@@ -113,7 +113,7 @@ module PProf
113
113
  hash.delete 'DER-Encoded-Profile'
114
114
  hash.delete 'ProvisionedDevices' unless options[:devices]
115
115
  if options[:certs]
116
- hash['DeveloperCertificates'] = developer_certificates.map do |cert|
116
+ hash['DeveloperCertificates'] = profile.developer_certificates.map do |cert|
117
117
  {
118
118
  subject: cert.subject,
119
119
  issuer: cert.issuer,
@@ -140,27 +140,14 @@ module PProf
140
140
  @output.puts JSON.pretty_generate(as_json(profile, options))
141
141
  end
142
142
 
143
- # Prints the filtered list of Provisioning Profiles
144
- #
145
- # Convenience method. Calls self.print_list with a filter block build from a filter hash
146
- #
147
- # @param [String] dir
148
- # The directory to search for the provisioning profiles. Defaults to the standard directory on Mac
143
+ # Generates a lambda which takes a `PProf::ProvisioningProfile` and returns if it should be kept in our listing or not
149
144
  #
150
145
  # @param [Hash<Symbol,Any>] filters
151
146
  # The hash describing the applied filters
147
+ # @return [Lambda] A lambda which takes a `PProf::ProvisioningProfile` and returns `true` if it matches the provided `filters`
152
148
  #
153
- # @param [Hash<Symbol,Any>] list_options
154
- # The way to print the output.
155
- # * Valid values for key `:mode` are:
156
- # - `:table` (for ASCII table output)
157
- # - `:list` (for plain list of only the UUIDs, suitable for piping to `xargs`)
158
- # - `:path` (for plain list of only the paths, suitable for piping to `xargs`)
159
- # * Valid values for key `:zero` are `true` or `false` to decide if we print `\0` at the end of each output.
160
- # Only used by `:list` and `:path` modes
161
- #
162
- def print_filtered_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, filters = {}, list_options = { mode: :table })
163
- filter_func = lambda do |p|
149
+ def filter_proc(filters = {})
150
+ lambda do |p|
164
151
  (filters[:name].nil? || p.name =~ filters[:name]) &&
165
152
  (filters[:appid_name].nil? || p.app_id_name =~ filters[:appid_name]) &&
166
153
  (filters[:appid].nil? || p.entitlements.app_id =~ filters[:appid]) &&
@@ -170,30 +157,22 @@ module PProf
170
157
  (filters[:has_devices].nil? || !(p.provisioned_devices || []).empty? == filters[:has_devices]) &&
171
158
  (filters[:all_devices].nil? || p.provisions_all_devices == filters[:all_devices]) &&
172
159
  (filters[:aps_env].nil? || match_aps_env(p.entitlements.aps_environment, filters[:aps_env])) &&
160
+ (filters[:platform].nil? || p.platform.include?(filters[:platform])) &&
173
161
  true
174
162
  end
175
-
176
- case list_options[:mode]
177
- when :table
178
- print_table(dir, &filter_func)
179
- when :json
180
- print_json_list(dir, list_options, &filter_func)
181
- else
182
- print_list(dir, list_options, &filter_func)
183
- end
184
163
  end
185
164
 
186
165
  # Prints the filtered list as a table
187
166
  #
188
167
  # @param [String] dir
189
- # The directory containing the mobileprovision files to list.
168
+ # The directory containing the mobileprovision/provisionprofile files to list.
190
169
  # Defaults to '~/Library/MobileDevice/Provisioning Profiles'
191
170
  #
192
171
  # @yield each provisioning provile for filtering/validation
193
172
  # The block is given ProvisioningProfile object and should
194
173
  # return true to display the row, false to filter it out
195
174
  #
196
- def print_table(dir = PProf::ProvisioningProfile::DEFAULT_DIR)
175
+ def print_table(dir: PProf::ProvisioningProfile::DEFAULT_DIR)
197
176
  count = 0
198
177
  errors = []
199
178
 
@@ -202,7 +181,7 @@ module PProf
202
181
  @output.puts table.row('UUID', 'Name', 'AppID', 'Expiration Date', ' ', 'Team Name')
203
182
  @output.puts table.separator
204
183
 
205
- Dir['*.mobileprovision', base: dir].each do |file_name|
184
+ Dir['*.{mobileprovision,provisionprofile}', base: dir].each do |file_name|
206
185
  file = File.join(dir, file_name)
207
186
  begin
208
187
  p = PProf::ProvisioningProfile.new(file)
@@ -225,21 +204,21 @@ module PProf
225
204
 
226
205
  # Prints the filtered list of UUIDs or Paths only
227
206
  #
228
- # @param [String] dir
229
- # The directory containing the mobileprovision files to list.
230
- # Defaults to '~/Library/MobileDevice/Provisioning Profiles'
231
207
  # @param [Hash] options
232
208
  # The options hash typically filled while parsing the command line arguments.
233
209
  # - :mode: will print the UUIDs if set to `:list`, the file path otherwise
234
210
  # - :zero: will concatenate the entries with `\0` instead of `\n` if set
211
+ # @param [String] dir
212
+ # The directory containing the mobileprovision/provisionprofile files to list.
213
+ # Defaults to '~/Library/MobileDevice/Provisioning Profiles'
235
214
  #
236
215
  # @yield each provisioning profile for filtering/validation
237
216
  # The block is given ProvisioningProfile object and should
238
217
  # return true to display the row, false to filter it out
239
218
  #
240
- def print_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, options) # rubocop:disable Style/OptionalArguments
219
+ def print_list(options:, dir: PProf::ProvisioningProfile::DEFAULT_DIR)
241
220
  errors = []
242
- Dir['*.mobileprovision', base: dir].each do |file_name|
221
+ Dir['*.{mobileprovision,provisionprofile}', base: dir].each do |file_name|
243
222
  file = File.join(dir, file_name)
244
223
  p = PProf::ProvisioningProfile.new(file)
245
224
  next if block_given? && !yield(p)
@@ -254,21 +233,21 @@ module PProf
254
233
 
255
234
  # Prints the filtered list of profiles as a JSON array
256
235
  #
257
- # @param [String] dir
258
- # The directory containing the mobileprovision files to list.
259
- # Defaults to '~/Library/MobileDevice/Provisioning Profiles'
260
236
  # @param [Hash] options
261
237
  # The options hash typically filled while parsing the command line arguments.
262
- # - :mode: will print the UUIDs if set to `:list`, the file path otherwise
263
- # - :zero: will concatenate the entries with `\0` instead of `\n` if set
238
+ # - :certs: will print the UUIDs if set to `:list`, the file path otherwise
239
+ # - :devices: will concatenate the entries with `\0` instead of `\n` if set
240
+ # @param [String] dir
241
+ # The directory containing the mobileprovision/provisionprofile files to list.
242
+ # Defaults to '~/Library/MobileDevice/Provisioning Profiles'
264
243
  #
265
244
  # @yield each provisioning profile for filtering/validation
266
245
  # The block is given ProvisioningProfile object and should
267
246
  # return true to display the row, false to filter it out
268
247
  #
269
- def print_json_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, options) # rubocop:disable Style/OptionalArguments
248
+ def print_json_list(options:, dir: PProf::ProvisioningProfile::DEFAULT_DIR)
270
249
  errors = []
271
- profiles = Dir['*.mobileprovision', base: dir].map do |file_name|
250
+ profiles = Dir['*.{mobileprovision,provisionprofile}', base: dir].map do |file_name|
272
251
  file = File.join(dir, file_name)
273
252
  p = PProf::ProvisioningProfile.new(file)
274
253
  as_json(p, options) unless block_given? && !yield(p)
@@ -21,11 +21,13 @@ module PProf
21
21
  # File path or UUID of the ProvisioningProfile
22
22
  #
23
23
  def initialize(file)
24
- path = if file =~ /^[0-9A-F-]*$/i
25
- "#{PProf::ProvisioningProfile::DEFAULT_DIR}/#{file}.mobileprovision"
24
+ path = if file.match?(/^[0-9A-F-]*$/i)
25
+ Dir["#{PProf::ProvisioningProfile::DEFAULT_DIR}/#{file}.{mobileprovision,provisionprofile}"].first
26
26
  else
27
27
  file
28
28
  end
29
+ raise "Unable to find Provisioning Profile with UUID #{file}." if file.nil?
30
+
29
31
  xml = nil
30
32
  begin
31
33
  pkcs7 = OpenSSL::PKCS7.new(File.read(path))
@@ -41,7 +43,7 @@ module PProf
41
43
  xml = `security cms -D -i "#{path}" 2> /dev/null`
42
44
  end
43
45
  @plist = Plist.parse_xml(xml)
44
- raise "Unable to parse file #{file}." if @plist.nil?
46
+ raise "Unable to parse file #{path}." if @plist.nil?
45
47
  end
46
48
 
47
49
  # The name of the Provisioning Profile
@@ -58,6 +60,14 @@ module PProf
58
60
  @plist['UUID']
59
61
  end
60
62
 
63
+ # The list of Platforms the Provisioning Profile is for.
64
+ # Typical values include `OSX`, `iOS`, `xrOS`, `visionOS`, …
65
+ #
66
+ # @return [Array<String>]
67
+ def platform
68
+ @plist['Platform']
69
+ end
70
+
61
71
  # The name of the Application Identifier associated with this Provisioning Profile
62
72
  #
63
73
  # @note This is not the AppID itself, but rather the name you associated to that
data/lib/pprof/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module PProf
4
4
  # Module version
5
- VERSION = '0.5.0'
5
+ VERSION = '1.0.0'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pprof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Olivier Halligon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-09 00:00:00.000000000 Z
11
+ date: 2025-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: plist
@@ -59,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0'
61
61
  requirements: []
62
- rubygems_version: 3.0.3
62
+ rubygems_version: 3.5.17
63
63
  signing_key:
64
64
  specification_version: 4
65
65
  summary: A Provisioning Profiles library