pprof 0.4.0 → 0.5.1

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: b8843e85a32a30167805e1aa3cef04d1626b05f7f1d1c130b1558d9e3bfaa809
4
- data.tar.gz: 4ef87037d3779a327d32bb87fb73fc3501d94d4406bb9529fc1049775a23f93e
3
+ metadata.gz: 21276029f4a059802fcc59cdf37a843caa2b38cc11d6af22f76fa2969bf24975
4
+ data.tar.gz: 02eedbe630b35226f7a00c531d0b8075b11ab6f4c705434e2f4e4f3445251c8d
5
5
  SHA512:
6
- metadata.gz: 19fe84e13c4007da01357055deb1350eb0108fe31dd45466827208d7d59f9a858dedc8450e1f0cc2f7863db567263638371ce97536d66b5db054c021c5caa612
7
- data.tar.gz: 065fbe7cd8cc1af06ca4e739ca1e901694cf711039c345cd2bd9086090b80af503b616ce2babeedf0120bb692c8d425472e8ad8b2d645efb4569f42771cd63bc
6
+ metadata.gz: 48eb1f57db15c832e6a9acf454d9c6a5ce3be07dc7db4d5877cccb7c32c96f6cfddcf7b3be78a8af8c2c9374148961273a0a1e22a5f51e13b0d8df7359b20ed7
7
+ data.tar.gz: fdb8efa34984352bc61242ae6452c3e5f6a6e3c11708735c0061d202dae12d8c232458ad88f02d572579221e7d1b8e7e30b1c457048ad626097d80d9825e5aba
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 ''
@@ -64,6 +66,9 @@ parser = OptionParser.new do |opts|
64
66
  opts.on('-p', '--path', 'Print only the paths, one per line (instead of an ASCII table)') do
65
67
  list_options[:mode] = :path
66
68
  end
69
+ opts.on('-j', '--json', 'Print the output information as a JSON') do
70
+ list_options[:mode] = :json
71
+ end
67
72
  opts.on('-0', '--print0', 'Separate each found entry by \\0, to be used by `xargs -0`') do
68
73
  list_options[:zero] = true
69
74
  end
@@ -139,7 +144,7 @@ unless filters.empty? || ARGV.empty?
139
144
  exit
140
145
  end
141
146
 
142
- unless options.empty? || !ARGV.empty?
147
+ unless list_options[:mode] == :json || options.empty? || !ARGV.empty?
143
148
  puts 'You should use option flags only when providing an specific path.'
144
149
  puts parser # Usage
145
150
  exit
@@ -151,14 +156,25 @@ o = PProf::OutputFormatter.new
151
156
  if ARGV.empty?
152
157
  # Print list of matching profiles
153
158
  list_options[:mode] = :path if list_options[:zero] && list_options[:mode] == :table
154
- o.print_filtered_list(PProf::ProvisioningProfile::DEFAULT_DIR, filters, list_options)
159
+ filter_func = o.filter_proc(filters)
160
+ case list_options[:mode]
161
+ when :table
162
+ o.print_table(&filter_func)
163
+ when :json
164
+ o.print_json_list(options: options, &filter_func)
165
+ else
166
+ o.print_list(options: list_options, &filter_func)
167
+ end
155
168
  else
156
169
  begin
157
170
  # Print info about given profile path/UUID
158
171
  p = PProf::ProvisioningProfile.new(ARGV[0])
159
-
160
172
  options = { info: true } if options.empty?
161
- o.print_info(p, options)
173
+ if list_options[:mode] == :json
174
+ o.print_json(p, options)
175
+ else
176
+ o.print_info(p, options)
177
+ end
162
178
  rescue StandardError => e
163
179
  o.print_error(e, ARGV[0])
164
180
  end
@@ -1,9 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  # Module for the pprof tool to manipulate Provisioning Profiles
4
6
  module PProf
5
7
  # A helper tool to pretty-print Provisioning Profile informations
6
8
  class OutputFormatter
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]
11
+
7
12
  # Initialize a new OutputFormatter
8
13
  #
9
14
  # @param [IO] output
@@ -63,8 +68,7 @@ module PProf
63
68
  def print_info(profile, options = nil)
64
69
  options ||= { info: true }
65
70
  if options[:info]
66
- keys = %i[name uuid app_id_name app_id_prefix creation_date expiration_date ttl team_ids
67
- team_name]
71
+ keys = MAIN_PROFILE_KEYS
68
72
  keys.each do |key|
69
73
  @output.puts "- #{key}: #{profile.send(key.to_sym)}"
70
74
  end
@@ -93,27 +97,57 @@ module PProf
93
97
  # rubocop:enable Style/GuardClause
94
98
  end
95
99
 
96
- # Prints the filtered list of Provisioning Profiles
100
+ # Returns a Provisioning Profile hash ready to be printed as a JSON output
97
101
  #
98
- # Convenience method. Calls self.print_list with a filter block build from a filter hash
102
+ # @param [Array<PProf::ProvisioningProfile>] profile
103
+ # List of provisioning profiles to include in the JSON output
104
+ # @param [Hash] options
105
+ # Options to indicate what to include in the generated JSON.
106
+ # `:certs`: if set to `true`, output will also include the info about `DeveloperCertificates` in each profile
107
+ # `:devices`: if set to `true`, output will also include the list of `ProvisionedDevices` for each profile
99
108
  #
100
- # @param [String] dir
101
- # The directory to search for the provisioning profiles. Defaults to the standard directory on Mac
109
+ # @return [Hash] The hash ready to be `JSON.pretty_generate`'d
110
+ #
111
+ def as_json(profile, options = {})
112
+ hash = profile.to_hash.dup
113
+ hash.delete 'DER-Encoded-Profile'
114
+ hash.delete 'ProvisionedDevices' unless options[:devices]
115
+ if options[:certs]
116
+ hash['DeveloperCertificates'] = profile.developer_certificates.map do |cert|
117
+ {
118
+ subject: cert.subject,
119
+ issuer: cert.issuer,
120
+ serial: cert.serial,
121
+ expires: cert.not_after
122
+ }
123
+ end
124
+ else
125
+ hash.delete 'DeveloperCertificates'
126
+ end
127
+ hash
128
+ end
129
+
130
+ # Prints a Provisioning Profile as JSON
131
+ #
132
+ # @param [Array<PProf::ProvisioningProfile>] profile
133
+ # List of provisioning profiles to include in the JSON output
134
+ # @param [Hash] options
135
+ # Options to indicate what to include in the generated JSON.
136
+ # `:certs`: if set to `true`, output will also include the info about `DeveloperCertificates` in each profile
137
+ # `:devices`: if set to `true`, output will also include the list of `ProvisionedDevices` for each profile
138
+ #
139
+ def print_json(profile, options = {})
140
+ @output.puts JSON.pretty_generate(as_json(profile, options))
141
+ end
142
+
143
+ # Generates a lambda which takes a `PProf::ProvisioningProfile` and returns if it should be kept in our listing or not
102
144
  #
103
145
  # @param [Hash<Symbol,Any>] filters
104
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`
105
148
  #
106
- # @param [Hash<Symbol,Any>] list_options
107
- # The way to print the output.
108
- # * Valid values for key `:mode` are:
109
- # - `:table` (for ASCII table output)
110
- # - `:list` (for plain list of only the UUIDs, suitable for piping to `xargs`)
111
- # - `:path` (for plain list of only the paths, suitable for piping to `xargs`)
112
- # * Valid values for key `:zero` are `true` or `false` to decide if we print `\0` at the end of each output.
113
- # Only used by `:list` and `:path` modes
114
- #
115
- def print_filtered_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, filters = {}, list_options = { mode: :table })
116
- filter_func = lambda do |p|
149
+ def filter_proc(filters = {})
150
+ lambda do |p|
117
151
  (filters[:name].nil? || p.name =~ filters[:name]) &&
118
152
  (filters[:appid_name].nil? || p.app_id_name =~ filters[:appid_name]) &&
119
153
  (filters[:appid].nil? || p.entitlements.app_id =~ filters[:appid]) &&
@@ -125,13 +159,6 @@ module PProf
125
159
  (filters[:aps_env].nil? || match_aps_env(p.entitlements.aps_environment, filters[:aps_env])) &&
126
160
  true
127
161
  end
128
-
129
- case list_options[:mode]
130
- when :table
131
- print_table(dir, &filter_func)
132
- else
133
- print_list(dir, list_options, &filter_func)
134
- end
135
162
  end
136
163
 
137
164
  # Prints the filtered list as a table
@@ -144,7 +171,7 @@ module PProf
144
171
  # The block is given ProvisioningProfile object and should
145
172
  # return true to display the row, false to filter it out
146
173
  #
147
- def print_table(dir = PProf::ProvisioningProfile::DEFAULT_DIR)
174
+ def print_table(dir: PProf::ProvisioningProfile::DEFAULT_DIR)
148
175
  count = 0
149
176
  errors = []
150
177
 
@@ -181,21 +208,21 @@ module PProf
181
208
  # Defaults to '~/Library/MobileDevice/Provisioning Profiles'
182
209
  # @param [Hash] options
183
210
  # The options hash typically filled while parsing the command line arguments.
184
- # - :mode: will print the UUIDs if set to `:uuid`, the file path otherwise
211
+ # - :mode: will print the UUIDs if set to `:list`, the file path otherwise
185
212
  # - :zero: will concatenate the entries with `\0` instead of `\n` if set
186
213
  #
187
214
  # @yield each provisioning profile for filtering/validation
188
215
  # The block is given ProvisioningProfile object and should
189
216
  # return true to display the row, false to filter it out
190
217
  #
191
- def print_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, options) # rubocop:disable Style/OptionalArguments
218
+ def print_list(dir: PProf::ProvisioningProfile::DEFAULT_DIR, options:) # rubocop:disable Style/OptionalArguments
192
219
  errors = []
193
220
  Dir['*.mobileprovision', base: dir].each do |file_name|
194
221
  file = File.join(dir, file_name)
195
222
  p = PProf::ProvisioningProfile.new(file)
196
223
  next if block_given? && !yield(p)
197
224
 
198
- @output.print options[:mode] == :uuid ? p.uuid.chomp : file.chomp
225
+ @output.print options[:mode] == :list ? p.uuid.chomp : file.chomp
199
226
  @output.print options[:zero] ? "\0" : "\n"
200
227
  rescue StandardError => e
201
228
  errors << { message: e, file: file }
@@ -203,6 +230,33 @@ module PProf
203
230
  errors.each { |e| print_error(e[:message], e[:file]) } unless errors.empty?
204
231
  end
205
232
 
233
+ # Prints the filtered list of profiles as a JSON array
234
+ #
235
+ # @param [String] dir
236
+ # The directory containing the mobileprovision files to list.
237
+ # Defaults to '~/Library/MobileDevice/Provisioning Profiles'
238
+ # @param [Hash] options
239
+ # The options hash typically filled while parsing the command line arguments.
240
+ # - :certs: will print the UUIDs if set to `:list`, the file path otherwise
241
+ # - :devices: will concatenate the entries with `\0` instead of `\n` if set
242
+ #
243
+ # @yield each provisioning profile for filtering/validation
244
+ # The block is given ProvisioningProfile object and should
245
+ # return true to display the row, false to filter it out
246
+ #
247
+ def print_json_list(dir: PProf::ProvisioningProfile::DEFAULT_DIR, options:) # rubocop:disable Style/OptionalArguments
248
+ errors = []
249
+ profiles = Dir['*.mobileprovision', base: dir].map do |file_name|
250
+ file = File.join(dir, file_name)
251
+ p = PProf::ProvisioningProfile.new(file)
252
+ as_json(p, options) unless block_given? && !yield(p)
253
+ rescue StandardError => e
254
+ errors << { message: e, file: file }
255
+ end.compact
256
+ errors.each { |e| print_error(e[:message], e[:file]) } unless errors.empty?
257
+ @output.puts JSON.pretty_generate(profiles)
258
+ end
259
+
206
260
  def self.match_aps_env(actual, expected)
207
261
  return false if actual.nil? # false if no Push entitlements
208
262
  return true if expected == true # true if Push present but we don't filter on specific env
@@ -146,7 +146,7 @@ module PProf
146
146
  #
147
147
  # @return [Hash]
148
148
  def to_hash
149
- @dict
149
+ @plist
150
150
  end
151
151
 
152
152
  # The human-readable string representation of this Provisioning Profile
data/lib/pprof/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module PProf
4
4
  # Module version
5
- VERSION = '0.4.0'
5
+ VERSION = '0.5.1'
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.4.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Olivier Halligon
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-28 00:00:00.000000000 Z
11
+ date: 2022-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: plist
@@ -44,7 +44,7 @@ licenses:
44
44
  - MIT
45
45
  metadata:
46
46
  rubygems_mfa_required: 'true'
47
- post_install_message:
47
+ post_install_message:
48
48
  rdoc_options: []
49
49
  require_paths:
50
50
  - lib
@@ -52,15 +52,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
- version: 2.7.0
55
+ version: 2.6.4
56
56
  required_rubygems_version: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0'
61
61
  requirements: []
62
- rubygems_version: 3.2.19
63
- signing_key:
62
+ rubygems_version: 3.0.3
63
+ signing_key:
64
64
  specification_version: 4
65
65
  summary: A Provisioning Profiles library
66
66
  test_files: []