app-info 3.0.0.beta2 → 3.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91afee9fd86b49fa4f788f4316df7c689178c6fdfbc0cf3f4743ae5cb7713dde
4
- data.tar.gz: 056f2a2416a1a68ca2f2dcbbc404e9f6c768a5e8a742d942f04177c7044f5ff9
3
+ metadata.gz: f8ca25ba9f5e54dc762996f1b7393593393b29adcbe0622131a905aa2f494141
4
+ data.tar.gz: c2839b1ac586397d1f76833fd9b4947722892ae584d8942ccb8e0d706f207210
5
5
  SHA512:
6
- metadata.gz: 2294ae1a6e8d220c46bd21e4c1062783f2ce7b94ad5b5dffdfe8c62edd6e519a57b326913339f090f62bf955d3103a6bf665227865bceb9f45bb7c78478b04f0
7
- data.tar.gz: ec84bbc24190227bedd91818bdefad90cb1472e1b7ca1db312aca651843315ab037e7b70f2322085eca70bf3ab0319af3af20270da2a006437f76cf4a4ca3f11
6
+ metadata.gz: cb08a20e764b4c8c35c7c03f43c3472b89cf0ebf34889080ef28c52e97c51b8700c91d09acd073cf21ece653c19beab34ecfc4b0477a5c534d23314bb503ff83
7
+ data.tar.gz: c7aa998b3224be94bbb20589fe57906356e93788739383d89703fafd1856f0eca948c33d046561460400590bf727fcd633f98edcfb321f11d740bbe00aa48aa2
data/CHANGELOG.md CHANGED
@@ -9,6 +9,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
9
9
 
10
10
  > List all changes before release a new version.
11
11
 
12
+ ## [3.0.0.beta3] (2023-04-05)
13
+
14
+ ### Added
15
+
16
+ - Android parser `.icons` method add exclude param to filter icons.
17
+
18
+ ### Changed
19
+
20
+ - Rename `.platform` to `.manufacturer`, rename `.opera_sytem` to `.platform` for all parsers.
21
+
22
+ ### Fixed
23
+
24
+ - Minor fixes.
25
+
12
26
  ## [3.0.0.beta2] (2023-04-04)
13
27
 
14
28
  ### Changed
@@ -278,7 +292,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
278
292
 
279
293
  - Updated dependency of CFPropertly list be a range between 2.3.4. (thanks @[cschroed](https://github.com/cschroed))
280
294
 
281
- [Unreleased]: https://github.com/icyleaf/app-info/compare/v3.0.0.beta2..HEAD
295
+ [Unreleased]: https://github.com/icyleaf/app-info/compare/v3.0.0.beta3..HEAD
296
+ [3.0.0.beta3]: https://github.com/icyleaf/app-info/compare/v3.0.0.beta2...v3.0.0.beta3
282
297
  [3.0.0.beta2]: https://github.com/icyleaf/app-info/compare/v3.0.0.beta1...v3.0.0.beta2
283
298
  [3.0.0.beta1]: https://github.com/icyleaf/app-info/compare/v2.8.5...v3.0.0.beta1
284
299
  [2.8.5]: https://github.com/icyleaf/app-info/compare/v2.8.4...v2.8.5
data/lib/app_info/aab.rb CHANGED
@@ -115,28 +115,48 @@ module AppInfo
115
115
  end
116
116
 
117
117
  # Full icons metadata
118
- # @example
118
+ # @example full icons
119
119
  # aab.icons
120
120
  # # => [
121
121
  # # {
122
- # # name: 'icon.png',
123
- # # file: '/path/to/icon.png',
122
+ # # name: 'ic_launcher.png',
123
+ # # file: '/path/to/ic_launcher.webp',
124
124
  # # dimensions: [29, 29]
125
125
  # # },
126
126
  # # {
127
- # # name: 'icon1.png',
128
- # # file: '/path/to/icon1.png',
127
+ # # name: 'ic_launcher.png',
128
+ # # file: '/path/to/ic_launcher.png',
129
+ # # dimensions: [120, 120]
130
+ # # },
131
+ # # {
132
+ # # name: 'ic_launcher.xml',
133
+ # # file: '/path/to/ic_launcher.xml',
134
+ # # dimensions: [nil, nil]
135
+ # # },
136
+ # # ]
137
+ # @example exclude xml icons
138
+ # aab.icons(filter: :xml)
139
+ # # => [
140
+ # # {
141
+ # # name: 'ic_launcher.png',
142
+ # # file: '/path/to/ic_launcher.webp',
143
+ # # dimensions: [29, 29]
144
+ # # },
145
+ # # {
146
+ # # name: 'ic_launcher.png',
147
+ # # file: '/path/to/ic_launcher.png',
129
148
  # # dimensions: [120, 120]
130
149
  # # }
131
150
  # # ]
151
+ # @param [String, Symbol, Array<Symbol, Array>] filter filter file extension name
132
152
  # @return [Array<Hash{Symbol => String, Array<Integer>}>] icons paths of icons
133
- def icons
153
+ def icons(exclude: nil)
134
154
  @icons ||= manifest.icons.each_with_object([]) do |res, obj|
135
155
  path = res.value
136
156
  filename = ::File.basename(path)
137
157
  filepath = ::File.join(contents, ::File.dirname(path))
138
158
  file = ::File.join(filepath, filename)
139
- FileUtils.mkdir_p filepath
159
+ FileUtils.mkdir_p(filepath)
140
160
 
141
161
  binary_data = read_file(path)
142
162
  ::File.write(file, binary_data, encoding: Encoding::BINARY)
@@ -147,6 +167,8 @@ module AppInfo
147
167
  dimensions: ImageSize.path(file).size
148
168
  }
149
169
  end
170
+
171
+ extract_icon(@icons, exclude: exclude)
150
172
  end
151
173
 
152
174
  def clear!
@@ -23,14 +23,14 @@ module AppInfo
23
23
  file_to_human_size(@file, human_size: human_size)
24
24
  end
25
25
 
26
- # @return [Symbol] {Platform}
27
- def platform
28
- Platform::GOOGLE
26
+ # @return [Symbol] {Manufacturer}
27
+ def manufacturer
28
+ Manufacturer::GOOGLE
29
29
  end
30
30
 
31
- # @return [Symbol] {OperaSystem}
32
- def opera_system
33
- OperaSystem::ANDROID
31
+ # @return [Symbol] {Platform}
32
+ def platform
33
+ Platform::ANDROID
34
34
  end
35
35
 
36
36
  # @return [Symbol] {Device}
@@ -153,6 +153,25 @@ module AppInfo
153
153
 
154
154
  protected
155
155
 
156
+ def extract_icon(icons, exclude: nil)
157
+ excludes = exclude_icon_exts(exclude: exclude)
158
+ icons.reject { |icon| icon_ext_match?(icon[:name], excludes) }
159
+ end
160
+
161
+ def exclude_icon_exts(exclude:)
162
+ case exclude
163
+ when String then [exclude]
164
+ when Array then exclude.map(&:to_s)
165
+ when Symbol then [exclude.to_s]
166
+ end
167
+ end
168
+
169
+ def icon_ext_match?(file, excludes)
170
+ return false if file.nil? || excludes.nil?
171
+
172
+ excludes.include?(::File.extname(file)[1..-1])
173
+ end
174
+
156
175
  def v1sign
157
176
  @v1sign ||= Android::Signature::V1.verify(self)
158
177
  rescue Android::Signature::NotFoundError
data/lib/app_info/apk.rb CHANGED
@@ -70,22 +70,42 @@ module AppInfo
70
70
  end
71
71
 
72
72
  # Full icons metadata
73
- # @example
73
+ # @example full icons
74
74
  # apk.icons
75
75
  # # => [
76
76
  # # {
77
- # # name: 'icon.png',
78
- # # file: '/path/to/icon.png',
77
+ # # name: 'ic_launcher.png',
78
+ # # file: '/path/to/ic_launcher.png',
79
79
  # # dimensions: [29, 29]
80
80
  # # },
81
81
  # # {
82
- # # name: 'icon1.png',
83
- # # file: '/path/to/icon1.png',
82
+ # # name: 'ic_launcher.png',
83
+ # # file: '/path/to/ic_launcher.png',
84
+ # # dimensions: [120, 120]
85
+ # # },
86
+ # # {
87
+ # # name: 'ic_launcher.xml',
88
+ # # file: '/path/to/ic_launcher.xml',
89
+ # # dimensions: [nil, nil]
90
+ # # },
91
+ # # ]
92
+ # @example exclude xml icons
93
+ # apk.icons(exclude: :xml)
94
+ # # => [
95
+ # # {
96
+ # # name: 'ic_launcher.png',
97
+ # # file: '/path/to/ic_launcher.png',
98
+ # # dimensions: [29, 29]
99
+ # # },
100
+ # # {
101
+ # # name: 'ic_launcher.png',
102
+ # # file: '/path/to/ic_launcher.png',
84
103
  # # dimensions: [120, 120]
85
104
  # # }
86
105
  # # ]
106
+ # @param [Boolean] xml return xml icons
87
107
  # @return [Array<Hash{Symbol => String, Array<Integer>}>] icons paths of icons
88
- def icons
108
+ def icons(exclude: nil)
89
109
  @icons ||= apk.icon.each_with_object([]) do |(path, data), obj|
90
110
  icon_name = ::File.basename(path)
91
111
  icon_path = ::File.join(contents, ::File.dirname(path))
@@ -99,6 +119,8 @@ module AppInfo
99
119
  dimensions: ImageSize.path(icon_file).size
100
120
  }
101
121
  end
122
+
123
+ extract_icon(@icons, exclude: exclude)
102
124
  end
103
125
 
104
126
  def clear!
@@ -26,9 +26,9 @@ module AppInfo
26
26
  APPSTORE = :appstore
27
27
  end
28
28
 
29
- # @return [Symbol] {Platform}
30
- def platform
31
- Platform::APPLE
29
+ # @return [Symbol] {Manufacturer}
30
+ def manufacturer
31
+ Manufacturer::APPLE
32
32
  end
33
33
 
34
34
  # return file size
@@ -46,8 +46,8 @@ module AppInfo
46
46
 
47
47
  # @!method device
48
48
  # @see InfoPlist#device
49
- # @!method opera_system
50
- # @see InfoPlist#opera_system
49
+ # @!method platform
50
+ # @see InfoPlist#platform
51
51
  # @!method iphone?
52
52
  # @see InfoPlist#iphone?
53
53
  # @!method ipad?
@@ -72,7 +72,7 @@ module AppInfo
72
72
  # @see InfoPlist#min_sdk_version
73
73
  # @!method min_os_version
74
74
  # @see InfoPlist#min_os_version
75
- def_delegators :info, :device, :opera_system, :iphone?, :ipad?, :universal?, :macos?,
75
+ def_delegators :info, :device, :platform, :iphone?, :ipad?, :universal?, :macos?,
76
76
  :build_version, :name, :release_version, :identifier, :bundle_id,
77
77
  :display_name, :bundle_name, :min_sdk_version, :min_os_version
78
78
 
@@ -6,6 +6,7 @@ module AppInfo
6
6
  class Certificate
7
7
  # Parse Raw data into X509 cerificate wrapper
8
8
  # @param [String] certificate raw data
9
+ # @return [AppInfo::Certificate]
9
10
  def self.parse(data)
10
11
  cert = OpenSSL::X509::Certificate.new(data)
11
12
  new(cert)
@@ -117,18 +118,20 @@ module AppInfo
117
118
  end
118
119
  end
119
120
 
120
- # return size of public key
121
+ # return length of public key
121
122
  # @return [Integer]
122
- def size
123
+ # @raise NotImplementedError
124
+ def length
123
125
  case public_key
124
126
  when OpenSSL::PKey::RSA
125
127
  public_key.n.num_bits
126
128
  when OpenSSL::PKey::DSA, OpenSSL::PKey::DH
127
129
  public_key.p.num_bits
128
130
  when OpenSSL::PKey::EC
129
- raise NotImplementedError, "key size for #{public_key.inspect} not implemented"
131
+ raise NotImplementedError, "key length for #{public_key.inspect} not implemented"
130
132
  end
131
133
  end
134
+ alias size length
132
135
 
133
136
  # return fingerprint of certificate
134
137
  # @return [String]
@@ -166,10 +169,8 @@ module AppInfo
166
169
  @cert.send(method.to_sym, *args, &block) || super
167
170
  end
168
171
 
169
- def respond_to_missing?(method_name, *args)
170
- @cert.key?(method_name.to_sym) ||
171
- @cert.respond_to?(method_name) ||
172
- super
172
+ def respond_to_missing?(method, *args)
173
+ @cert.respond_to?(method.to_sym) || super
173
174
  end
174
175
  end
175
176
  end
@@ -30,14 +30,15 @@ module AppInfo
30
30
  UNKNOWN = :unknown
31
31
  end
32
32
 
33
- # Platform
34
- module Platform
33
+ # Manufacturer
34
+ module Manufacturer
35
35
  APPLE = :apple
36
36
  GOOGLE = :google
37
- WINDOWS = :windows
37
+ MICROSOFT = :microsoft
38
38
  end
39
39
 
40
- module OperaSystem
40
+ # Platform
41
+ module Platform
41
42
  MACOS = :macos
42
43
  IOS = :ios
43
44
  ANDROID = :android
data/lib/app_info/dsym.rb CHANGED
@@ -7,9 +7,9 @@ module AppInfo
7
7
  class DSYM < File
8
8
  include Helper::Archive
9
9
 
10
- # @return [Symbol] {Platform}
11
- def platform
12
- Platform::APPLE
10
+ # @return [Symbol] {Manufacturer}
11
+ def manufacturer
12
+ Manufacturer::APPLE
13
13
  end
14
14
 
15
15
  def each_file(&block)
data/lib/app_info/file.rb CHANGED
@@ -22,13 +22,13 @@ module AppInfo
22
22
  }.call
23
23
  end
24
24
 
25
- # @abstract Subclass and override {#opera_system} to implement.
26
- def opera_system
25
+ # @abstract Subclass and override {#platform} to implement.
26
+ def platform
27
27
  not_implemented_error!(__method__)
28
28
  end
29
29
 
30
- # @abstract Subclass and override {#platform} to implement.
31
- def platform
30
+ # @abstract Subclass and override {#manufacturer} to implement.
31
+ def manufacturer
32
32
  not_implemented_error!(__method__)
33
33
  end
34
34
 
@@ -17,18 +17,18 @@ module AppInfo
17
17
  Device::MACOS => %w[CFBundleIconFile CFBundleIconName]
18
18
  }.freeze
19
19
 
20
- # @return [Symbol] {Platform}
21
- def platform
22
- Platform::APPLE
20
+ # @return [Symbol] {Manufacturer}
21
+ def manufacturer
22
+ Manufacturer::APPLE
23
23
  end
24
24
 
25
- # @return [Symbol] {OperaSystem}
26
- def opera_system
25
+ # @return [Symbol] {Platform}
26
+ def platform
27
27
  case device
28
28
  when Device::MACOS
29
- OperaSystem::MACOS
29
+ Platform::MACOS
30
30
  when Device::IPHONE, Device::IPAD, Device::UNIVERSAL
31
- OperaSystem::IOS
31
+ Platform::IOS
32
32
  end
33
33
  end
34
34
 
@@ -40,7 +40,7 @@ module AppInfo
40
40
  Device::IPAD
41
41
  elsif device_family == [1, 2]
42
42
  Device::UNIVERSAL
43
- elsif !info.try(:[], 'DTSDKName').nil? || !info.try(:[], 'DTPlatformName').nil?
43
+ elsif !info.try(:[], 'DTSDKName').nil? || !info.try(:[], 'DTManufacturerName').nil?
44
44
  Device::MACOS
45
45
  else
46
46
  raise NotImplementedError, "Unkonwn device: #{device_family}"
@@ -7,20 +7,20 @@ module AppInfo
7
7
  # Apple code signing: provisioning profile parser
8
8
  # @see https://developer.apple.com/documentation/technotes/tn3125-inside-code-signing-provisioning-profiles
9
9
  class MobileProvision < File
10
- # @return [Symbol] {Platform}
11
- def platform
12
- Platform::APPLE
10
+ # @return [Symbol] {Manufacturer}
11
+ def manufacturer
12
+ Manufacturer::APPLE
13
13
  end
14
14
 
15
- # @return [Symbol] {OperaSystem}
16
- def opera_system
17
- case opera_systems[0]
15
+ # @return [Symbol] {Platform}
16
+ def platform
17
+ case platforms[0]
18
18
  when :macos
19
- OperaSystem::MACOS
19
+ Platform::MACOS
20
20
  when :ios
21
- OperaSystem::IOS
21
+ Platform::IOS
22
22
  else
23
- raise NotImplementedError, "Unkonwn opera_system: #{opera_systems[0]}"
23
+ raise NotImplementedError, "Unkonwn platform: #{platforms[0]}"
24
24
  end
25
25
  end
26
26
 
@@ -43,7 +43,7 @@ module AppInfo
43
43
  end
44
44
 
45
45
  # @return [Array<Symbol>]
46
- def opera_systems
46
+ def platforms
47
47
  return unless platforms = mobileprovision.try(:[], 'Platform')
48
48
 
49
49
  platforms.map do |v|
@@ -111,13 +111,13 @@ module AppInfo
111
111
  # @see https://stackoverflow.com/questions/1003066/what-does-get-task-allow-do-in-xcode
112
112
  # @return [Boolea]
113
113
  def development?
114
- case opera_system
115
- when OperaSystem::IOS
114
+ case platform
115
+ when Platform::IOS
116
116
  entitlements['get-task-allow'] == true
117
- when OperaSystem::MACOS
117
+ when Platform::MACOS
118
118
  !devices.nil?
119
119
  else
120
- raise NotImplementedError, "Unknown opera_system: #{opera_system}"
120
+ raise NotImplementedError, "Unknown platform: #{platform}"
121
121
  end
122
122
  end
123
123
 
@@ -126,26 +126,26 @@ module AppInfo
126
126
  # @see https://developer.apple.com/library/archive/qa/qa1830/_index.html
127
127
  # @return [Boolea]
128
128
  def appstore?
129
- case opera_system
130
- when OperaSystem::IOS
129
+ case platform
130
+ when Platform::IOS
131
131
  !development? && entitlements.key?('beta-reports-active')
132
- when OperaSystem::MACOS
132
+ when Platform::MACOS
133
133
  !development?
134
134
  else
135
- raise NotImplementedError, "Unknown opera_system: #{opera_system}"
135
+ raise NotImplementedError, "Unknown platform: #{platform}"
136
136
  end
137
137
  end
138
138
 
139
139
  # @return [Boolea]
140
140
  def adhoc?
141
- return false if opera_system == OperaSystem::MACOS # macOS no need adhoc
141
+ return false if platform == Platform::MACOS # macOS no need adhoc
142
142
 
143
143
  !development? && !devices.nil?
144
144
  end
145
145
 
146
146
  # @return [Boolea]
147
147
  def enterprise?
148
- return false if opera_system == OperaSystem::MACOS # macOS no need adhoc
148
+ return false if platform == Platform::MACOS # macOS no need adhoc
149
149
 
150
150
  !development? && !adhoc? && !appstore?
151
151
  end
data/lib/app_info/pe.rb CHANGED
@@ -24,16 +24,16 @@ module AppInfo
24
24
  0x5128 => 'RISC-v 128'
25
25
  }.freeze
26
26
 
27
+ # @return [Symbol] {Manufacturer}
28
+ def manufacturer
29
+ Manufacturer::MICROSOFT
30
+ end
31
+
27
32
  # @return [Symbol] {Platform}
28
33
  def platform
29
34
  Platform::WINDOWS
30
35
  end
31
36
 
32
- # @return [Symbol] {OperaSystem}
33
- def opera_system
34
- OperaSystem::WINDOWS
35
- end
36
-
37
37
  # @return [Symbol] {Device}
38
38
  def device
39
39
  Device::WINDOWS
@@ -68,11 +68,48 @@ module AppInfo
68
68
  # @!method assembly_version
69
69
  # @see VersionInfo#assembly_version
70
70
  # @return [String]
71
- def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version
71
+ # @!method file_version
72
+ # @see VersionInfo#file_version
73
+ # @return [String]
74
+ # @!method file_description
75
+ # @see VersionInfo#file_description
76
+ # @return [String]
77
+ # @!method copyright
78
+ # @see VersionInfo#copyright
79
+ # @return [String]
80
+ # @return [String]
81
+ # @!method special_build
82
+ # @see VersionInfo#special_build
83
+ # @return [String]
84
+ # @!method private_build
85
+ # @see VersionInfo#private_build
86
+ # @return [String]
87
+ # @!method original_filename
88
+ # @see VersionInfo#original_filename
89
+ # @return [String]
90
+ # @!method internal_name
91
+ # @see VersionInfo#internal_name
92
+ # @return [String]
93
+ # @!method legal_trademarks
94
+ # @see VersionInfo#legal_trademarks
95
+ # @return [String]
96
+ def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
97
+ :file_version, :file_description, :copyright, :special_build, :private_build,
98
+ :original_filename, :internal_name, :legal_trademarks
72
99
 
73
100
  alias name product_name
74
- alias release_version product_version
75
- alias build_version assembly_version
101
+
102
+ # Find {#product_version} then fallback to {#file_version}
103
+ # @return [String, nil]
104
+ def release_version
105
+ product_version || file_version
106
+ end
107
+
108
+ # Find {#special_build}, {#private_build} then fallback to {#assembly_version}
109
+ # @return [String, nil]
110
+ def build_version
111
+ special_build || private_build || assembly_version
112
+ end
76
113
 
77
114
  # @return [String]
78
115
  def archs
@@ -189,7 +226,7 @@ module AppInfo
189
226
 
190
227
  # VersionInfo class
191
228
  #
192
- # Ref: https://learn.microsoft.com/zh-cn/windows/win32/menurc/versioninfo-resource
229
+ # @see https://learn.microsoft.com/zh-cn/windows/win32/menurc/versioninfo-resource
193
230
  class VersionInfo
194
231
  def initialize(raw)
195
232
  @raw = raw
@@ -220,11 +257,36 @@ module AppInfo
220
257
  @file_version ||= value_of('FileVersion')
221
258
  end
222
259
 
223
- # @return [String]
260
+ # @return [String, nil]
224
261
  def file_description
225
262
  @file_description ||= value_of('FileDescription')
226
263
  end
227
264
 
265
+ # @return [String, nil]
266
+ def special_build
267
+ @special_build ||= value_of('SpecialBuild')
268
+ end
269
+
270
+ # @return [String, nil]
271
+ def private_build
272
+ @private_build ||= value_of('PrivateBuild')
273
+ end
274
+
275
+ # @return [String]
276
+ def original_filename
277
+ @original_filename ||= value_of('OriginalFilename')
278
+ end
279
+
280
+ # @return [String]
281
+ def internal_name
282
+ @internal_name ||= value_of('InternalName')
283
+ end
284
+
285
+ # @return [String]
286
+ def legal_trademarks
287
+ @legal_trademarks ||= value_of('LegalTrademarks')
288
+ end
289
+
228
290
  # @return [String]
229
291
  def copyright
230
292
  @copyright ||= value_of('LegalCopyright')
@@ -10,14 +10,14 @@ module AppInfo
10
10
 
11
11
  NAMESPACE = UUIDTools::UUID.sha1_create(UUIDTools::UUID_DNS_NAMESPACE, 'icyleaf.com')
12
12
 
13
- # @return [Symbol] {Platform}
14
- def platform
15
- Platform::GOOGLE
13
+ # @return [Symbol] {Manufacturer}
14
+ def manufacturer
15
+ Manufacturer::GOOGLE
16
16
  end
17
17
 
18
- # @return [Symbol] {OperaSystem}
19
- def opera_system
20
- OperaSystem::ANDROID
18
+ # @return [Symbol] {Platform}
19
+ def platform
20
+ Platform::ANDROID
21
21
  end
22
22
 
23
23
  # @return [String]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppInfo
4
- VERSION = '3.0.0.beta2'
4
+ VERSION = '3.0.0.beta3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: app-info
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.beta2
4
+ version: 3.0.0.beta3
5
5
  platform: ruby
6
6
  authors:
7
7
  - icyleaf
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-06 00:00:00.000000000 Z
11
+ date: 2023-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: CFPropertyList