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 +4 -4
- data/README.md +28 -2
- data/bin/pprof +16 -2
- data/lib/pprof/output_formatter.rb +22 -43
- data/lib/pprof/provisioning_profile.rb +13 -3
- data/lib/pprof/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae8d524121a74832a72453cd1e7b7a9ab1ca9d109fbca14d8cb1ce1ef8e77747
|
4
|
+
data.tar.gz: 682cfa8a82f248b977c384af168129a5395f65fb440411e7d1a919726ec7bfe6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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.
|
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
|
-
#
|
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
|
-
|
154
|
-
|
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
|
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
|
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
|
-
# - :
|
263
|
-
# - :
|
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
|
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
|
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 #{
|
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
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.
|
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:
|
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.
|
62
|
+
rubygems_version: 3.5.17
|
63
63
|
signing_key:
|
64
64
|
specification_version: 4
|
65
65
|
summary: A Provisioning Profiles library
|