app-info 2.5.4 → 2.6.3

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.
data/lib/app_info/apk.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  require 'ruby_apk'
4
4
  require 'image_size'
5
5
  require 'forwardable'
6
- require 'app_info/util'
7
6
 
8
7
  module AppInfo
9
8
  # Parse APK file
@@ -24,8 +23,8 @@ module AppInfo
24
23
  @file = file
25
24
  end
26
25
 
27
- def size(humanable = false)
28
- AppInfo::Util.file_size(@file, humanable)
26
+ def size(human_size: false)
27
+ AppInfo::Util.file_size(@file, human_size)
29
28
  end
30
29
 
31
30
  def os
@@ -77,6 +76,7 @@ module AppInfo
77
76
  def min_sdk_version
78
77
  manifest.min_sdk_ver
79
78
  end
79
+ alias min_os_version min_sdk_version
80
80
 
81
81
  def target_sdk_version
82
82
  manifest.doc
@@ -110,29 +110,23 @@ module AppInfo
110
110
  end
111
111
 
112
112
  def apk
113
- Zip.warn_invalid_date = false # fix invaild date format warnings
114
-
115
113
  @apk ||= ::Android::Apk.new(@file)
116
114
  end
117
115
 
118
116
  def icons
119
- unless @icons
120
- @icons = apk.icon.each_with_object([]) do |(path, data), obj|
121
- icon_name = File.basename(path)
122
- icon_path = File.join(contents, File.dirname(path))
123
- icon_file = File.join(icon_path, icon_name)
124
- FileUtils.mkdir_p icon_path
125
- File.open(icon_file, 'wb') { |f| f.write(data) }
126
-
127
- obj << {
128
- name: icon_name,
129
- file: icon_file,
130
- dimensions: ImageSize.path(icon_file).size
131
- }
132
- end
117
+ @icons ||= apk.icon.each_with_object([]) do |(path, data), obj|
118
+ icon_name = File.basename(path)
119
+ icon_path = File.join(contents, File.dirname(path))
120
+ icon_file = File.join(icon_path, icon_name)
121
+ FileUtils.mkdir_p icon_path
122
+ File.write(icon_file, data, encoding: Encoding::BINARY)
123
+
124
+ obj << {
125
+ name: icon_name,
126
+ file: icon_file,
127
+ dimensions: ImageSize.path(icon_file).size
128
+ }
133
129
  end
134
-
135
- @icons
136
130
  end
137
131
 
138
132
  def clear!
@@ -164,6 +158,7 @@ module AppInfo
164
158
  # Android Certificate
165
159
  class Certificate
166
160
  attr_reader :path, :certificate
161
+
167
162
  def initialize(path, certificate)
168
163
  @path = path
169
164
  @certificate = certificate
@@ -173,6 +168,7 @@ module AppInfo
173
168
  # Android Sign
174
169
  class Sign
175
170
  attr_reader :path, :sign
171
+
176
172
  def initialize(path, sign)
177
173
  @path = path
178
174
  @sign = sign
@@ -4,7 +4,71 @@
4
4
  # Copy from https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/try.rb
5
5
 
6
6
  module AppInfo
7
- module Tryable #:nodoc:
7
+ module Tryable # :nodoc:
8
+ ##
9
+ # :method: try
10
+ #
11
+ # :call-seq:
12
+ # try(*a, &b)
13
+ #
14
+ # Invokes the public method whose name goes as first argument just like
15
+ # +public_send+ does, except that if the receiver does not respond to it the
16
+ # call returns +nil+ rather than raising an exception.
17
+ #
18
+ # This method is defined to be able to write
19
+ #
20
+ # @person.try(:name)
21
+ #
22
+ # instead of
23
+ #
24
+ # @person.name if @person
25
+ #
26
+ # +try+ calls can be chained:
27
+ #
28
+ # @person.try(:spouse).try(:name)
29
+ #
30
+ # instead of
31
+ #
32
+ # @person.spouse.name if @person && @person.spouse
33
+ #
34
+ # +try+ will also return +nil+ if the receiver does not respond to the method:
35
+ #
36
+ # @person.try(:non_existing_method) # => nil
37
+ #
38
+ # instead of
39
+ #
40
+ # @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
41
+ #
42
+ # +try+ returns +nil+ when called on +nil+ regardless of whether it responds
43
+ # to the method:
44
+ #
45
+ # nil.try(:to_i) # => nil, rather than 0
46
+ #
47
+ # Arguments and blocks are forwarded to the method if invoked:
48
+ #
49
+ # @posts.try(:each_slice, 2) do |a, b|
50
+ # ...
51
+ # end
52
+ #
53
+ # The number of arguments in the signature must match. If the object responds
54
+ # to the method the call is attempted and +ArgumentError+ is still raised
55
+ # in case of argument mismatch.
56
+ #
57
+ # If +try+ is called without arguments it yields the receiver to a given
58
+ # block unless it is +nil+:
59
+ #
60
+ # @person.try do |p|
61
+ # ...
62
+ # end
63
+ #
64
+ # You can also call try with a block without accepting an argument, and the block
65
+ # will be instance_eval'ed instead:
66
+ #
67
+ # @person.try { upcase.truncate(50) }
68
+ #
69
+ # Please also note that +try+ is defined on +Object+. Therefore, it won't work
70
+ # with instances of classes that do not have +Object+ among their ancestors,
71
+ # like direct subclasses of +BasicObject+.
8
72
  def try(method_name = nil, *args, &block)
9
73
  if method_name.nil? && block_given?
10
74
  if block.arity.zero?
@@ -17,6 +81,18 @@ module AppInfo
17
81
  end
18
82
  end
19
83
 
84
+ ##
85
+ # :method: try!
86
+ #
87
+ # :call-seq:
88
+ # try!(*a, &b)
89
+ #
90
+ # Same as #try, but raises a +NoMethodError+ exception if the receiver is
91
+ # not +nil+ and does not implement the tried method.
92
+ #
93
+ # "a".try!(:upcase) # => "A"
94
+ # nil.try!(:upcase) # => nil
95
+ # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
20
96
  def try!(method_name = nil, *args, &block)
21
97
  if method_name.nil? && block_given?
22
98
  if block.arity.zero?
@@ -33,82 +109,4 @@ end
33
109
 
34
110
  class Object
35
111
  include AppInfo::Tryable
36
-
37
- ##
38
- # :method: try
39
- #
40
- # :call-seq:
41
- # try(*a, &b)
42
- #
43
- # Invokes the public method whose name goes as first argument just like
44
- # +public_send+ does, except that if the receiver does not respond to it the
45
- # call returns +nil+ rather than raising an exception.
46
- #
47
- # This method is defined to be able to write
48
- #
49
- # @person.try(:name)
50
- #
51
- # instead of
52
- #
53
- # @person.name if @person
54
- #
55
- # +try+ calls can be chained:
56
- #
57
- # @person.try(:spouse).try(:name)
58
- #
59
- # instead of
60
- #
61
- # @person.spouse.name if @person && @person.spouse
62
- #
63
- # +try+ will also return +nil+ if the receiver does not respond to the method:
64
- #
65
- # @person.try(:non_existing_method) # => nil
66
- #
67
- # instead of
68
- #
69
- # @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
70
- #
71
- # +try+ returns +nil+ when called on +nil+ regardless of whether it responds
72
- # to the method:
73
- #
74
- # nil.try(:to_i) # => nil, rather than 0
75
- #
76
- # Arguments and blocks are forwarded to the method if invoked:
77
- #
78
- # @posts.try(:each_slice, 2) do |a, b|
79
- # ...
80
- # end
81
- #
82
- # The number of arguments in the signature must match. If the object responds
83
- # to the method the call is attempted and +ArgumentError+ is still raised
84
- # in case of argument mismatch.
85
- #
86
- # If +try+ is called without arguments it yields the receiver to a given
87
- # block unless it is +nil+:
88
- #
89
- # @person.try do |p|
90
- # ...
91
- # end
92
- #
93
- # You can also call try with a block without accepting an argument, and the block
94
- # will be instance_eval'ed instead:
95
- #
96
- # @person.try { upcase.truncate(50) }
97
- #
98
- # Please also note that +try+ is defined on +Object+. Therefore, it won't work
99
- # with instances of classes that do not have +Object+ among their ancestors,
100
- # like direct subclasses of +BasicObject+.
101
-
102
- ##
103
- # :method: try!
104
- #
105
- # :call-seq:
106
- # try!(*a, &b)
107
- #
108
- # Same as #try, but raises a +NoMethodError+ exception if the receiver is
109
- # not +nil+ and does not implement the tried method.
110
- #
111
- # "a".try!(:upcase) # => "A"
112
- # nil.try!(:upcase) # => nil
113
- # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
114
112
  end
data/lib/app_info/dsym.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'macho'
4
- require 'app_info/util'
5
4
 
6
5
  module AppInfo
7
6
  # DSYM parser
@@ -130,8 +129,8 @@ module AppInfo
130
129
  @file.filetype
131
130
  end
132
131
 
133
- def size(humanable = false)
134
- return Util.size_to_humanable(@size) if humanable
132
+ def size(human_size: false)
133
+ return Util.size_to_human_size(@size) if human_size
135
134
 
136
135
  @size
137
136
  end
@@ -152,7 +151,7 @@ module AppInfo
152
151
  cpu_name: cpu_name,
153
152
  cpu_type: cpu_type,
154
153
  size: size,
155
- humanable_size: size(true)
154
+ human_size: size(human_size: true)
156
155
  }
157
156
  end
158
157
  end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'cfpropertylist'
5
+ require 'app_info/png_uncrush'
6
+
7
+ module AppInfo
8
+ # iOS Info.plist parser
9
+ class InfoPlist
10
+ extend Forwardable
11
+
12
+ def initialize(file)
13
+ @file = file
14
+ end
15
+
16
+ def version
17
+ release_version || build_version
18
+ end
19
+
20
+ def build_version
21
+ info.try(:[], 'CFBundleVersion')
22
+ end
23
+
24
+ def release_version
25
+ info.try(:[], 'CFBundleShortVersionString')
26
+ end
27
+
28
+ def identifier
29
+ info.try(:[], 'CFBundleIdentifier')
30
+ end
31
+ alias bundle_id identifier
32
+
33
+ def name
34
+ display_name || bundle_name
35
+ end
36
+
37
+ def display_name
38
+ info.try(:[], 'CFBundleDisplayName')
39
+ end
40
+
41
+ def bundle_name
42
+ info.try(:[], 'CFBundleName')
43
+ end
44
+
45
+ def min_os_version
46
+ min_sdk_version || min_system_version
47
+ end
48
+
49
+ #
50
+ # Extract the Minimum OS Version from the Info.plist (iOS Only)
51
+ #
52
+ def min_sdk_version
53
+ info.try(:[], 'MinimumOSVersion')
54
+ end
55
+
56
+ #
57
+ # Extract the Minimum OS Version from the Info.plist (macOS Only)
58
+ #
59
+ def min_system_version
60
+ info.try(:[], 'LSMinimumSystemVersion')
61
+ end
62
+
63
+ def icons
64
+ @icons ||= ICON_KEYS[device_type]
65
+ end
66
+
67
+ def device_type
68
+ device_family = info.try(:[], 'UIDeviceFamily')
69
+ if device_family == [1]
70
+ AppInfo::Device::IPHONE
71
+ elsif device_family == [2]
72
+ AppInfo::Device::IPAD
73
+ elsif device_family == [1, 2]
74
+ AppInfo::Device::UNIVERSAL
75
+ elsif !info.try(:[], 'DTSDKName').nil? || !info.try(:[], 'DTPlatformName').nil?
76
+ AppInfo::Device::MACOS
77
+ end
78
+ end
79
+
80
+ def iphone?
81
+ device_type == Device::IPHONE
82
+ end
83
+
84
+ def ipad?
85
+ device_type == Device::IPAD
86
+ end
87
+
88
+ def universal?
89
+ device_type == Device::UNIVERSAL
90
+ end
91
+
92
+ def macos?
93
+ device_type == Device::MACOS
94
+ end
95
+
96
+ def device_family
97
+ info.try(:[], 'UIDeviceFamily') || []
98
+ end
99
+
100
+ def release_type
101
+ if stored?
102
+ 'Store'
103
+ else
104
+ build_type
105
+ end
106
+ end
107
+
108
+ def [](key)
109
+ info.try(:[], key.to_s)
110
+ end
111
+
112
+ def_delegators :info, :to_h
113
+
114
+ def method_missing(method_name, *args, &block)
115
+ info.try(:[], Util.format_key(method_name)) ||
116
+ info.send(method_name) ||
117
+ super
118
+ end
119
+
120
+ def respond_to_missing?(method_name, *args)
121
+ info.key?(Util.format_key(method_name)) ||
122
+ info.respond_to?(method_name) ||
123
+ super
124
+ end
125
+
126
+ private
127
+
128
+ def info
129
+ return unless File.file?(@file)
130
+
131
+ @info ||= CFPropertyList.native_types(CFPropertyList::List.new(file: @file).value)
132
+ end
133
+
134
+ def app_path
135
+ @app_path ||= case device_type
136
+ when Device::MACOS
137
+ File.dirname(@file)
138
+ else
139
+ File.expand_path('../', @file)
140
+ end
141
+ end
142
+ end
143
+ end
@@ -3,7 +3,7 @@
3
3
  require 'forwardable'
4
4
 
5
5
  module AppInfo
6
- # iOS Plugin parser
6
+ # iOS Framework parser
7
7
  class Framework
8
8
  extend Forwardable
9
9
 
@@ -11,7 +11,7 @@ module AppInfo
11
11
  files = Dir.glob(File.join(path, name.to_s, '*'))
12
12
  return [] if files.empty?
13
13
 
14
- files.each_with_object([]) do |file, obj|
14
+ files.sort.each_with_object([]) do |file, obj|
15
15
  obj << new(file)
16
16
  end
17
17
  end
@@ -41,7 +41,7 @@ module AppInfo
41
41
  end
42
42
 
43
43
  def info
44
- @info ||= InfoPlist.new(file)
44
+ @info ||= InfoPlist.new(File.join(file, 'Info.plist'))
45
45
  end
46
46
 
47
47
  def to_s