fruity_builder 1.0.2 → 1.1.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
  SHA1:
3
- metadata.gz: 8d8ae8d1b4b33450affa9d95e70c438bac84f250
4
- data.tar.gz: 02aa4a49e613e1f7f330043e61dee0a09788ee45
3
+ metadata.gz: 840aa45bbec96aa6b16e53b63886b335ceb50b29
4
+ data.tar.gz: 35dded1625ff0a3d9d70c16c060e4d9b60fa6650
5
5
  SHA512:
6
- metadata.gz: cab3fe1d9d54fb4b81f2b694ff0bef41c24b0ea65aa5289669c173c4fe9c79185d1eba26e68b67a75076a9401dd81e92d841b1af3e84a04d07aa18a0d1dc656d
7
- data.tar.gz: 2ca8656316a5268d2e216d3cee62a56dfe1fa8b5af58dbf14bfb7c26a197069f671274c7a17690a636db951add469f8b20232cefcc0bffca0a12355ada85d72a
6
+ metadata.gz: b8a112412efd89a4235d4525129da6671ef56d3d6106c88a3ed1940d159e78297c1e8936c6b5ae1bbe1cab290dd9c2332a0478b2375f176aa6aee3090aca3fa1
7
+ data.tar.gz: 976fe8ccf7e0ab35f1129886de885680320c7ce7092a2db57d8e9867d316009afd926a5576ba5eaae66a111fed49d857e9512890393e7b52caa945b933cdacd7
@@ -2,92 +2,94 @@ require 'fruity_builder/lib/execution'
2
2
  require 'ox'
3
3
 
4
4
  module FruityBuilder
5
- class Plistutil < Execution
5
+ module IOS
6
+ class Plistutil < Execution
6
7
 
7
- def self.get_xml(options = {})
8
- if options.key?(:file)
9
- IO.read(options[:file])
10
- elsif options.key?(:xml)
11
- options[:xml]
8
+ def self.get_xml(options = {})
9
+ if options.key?(:file)
10
+ IO.read(options[:file])
11
+ elsif options.key?(:xml)
12
+ options[:xml]
13
+ end
12
14
  end
13
- end
14
15
 
15
- def self.get_bundle_id(options = {})
16
- xml = get_xml(options)
16
+ def self.get_bundle_id(options = {})
17
+ xml = get_xml(options)
17
18
 
18
- raise PlistutilCommandError.new('No XML was passed') unless xml
19
- identifiers = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
20
- identifiers << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
21
- identifiers.flatten.uniq
22
- end
19
+ raise PlistutilCommandError.new('No XML was passed') unless xml
20
+ identifiers = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
21
+ identifiers << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
22
+ identifiers.flatten.uniq
23
+ end
23
24
 
24
- def self.replace_bundle_id(options = {})
25
- xml = get_xml(options)
25
+ def self.replace_bundle_id(options = {})
26
+ xml = get_xml(options)
26
27
 
27
- raise PlistutilCommandError.new('No XML was passed') unless xml
28
+ raise PlistutilCommandError.new('No XML was passed') unless xml
28
29
 
29
- replacements = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
30
- replacements << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
30
+ replacements = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
31
+ replacements << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
31
32
 
32
- replacements.flatten.uniq.each do |replacement|
33
- xml = xml.gsub(replacement, options[:new_id])
34
- end
33
+ replacements.flatten.uniq.each do |replacement|
34
+ xml = xml.gsub(replacement, options[:new_id])
35
+ end
35
36
 
36
- IO.write(options[:file], xml) if options.key?(:file)
37
- xml
38
- end
37
+ IO.write(options[:file], xml) if options.key?(:file)
38
+ xml
39
+ end
39
40
 
40
- # Check to ensure that plistutil is available
41
- # @return [Boolean] true if plistutil is available, false otherwise
42
- def self.plistutil_available?
43
- result = execute('which plistutil')
44
- result.exit == 0
45
- end
41
+ # Check to ensure that plistutil is available
42
+ # @return [Boolean] true if plistutil is available, false otherwise
43
+ def self.plistutil_available?
44
+ result = execute('which plistutil')
45
+ result.exit == 0
46
+ end
46
47
 
47
- # Gets properties from the IPA and returns them in a hash
48
- # @param [String] path path to the IPA/App
49
- # @return [Hash] list of properties from the app
50
- def self.get_bundle_id_from_app(path)
51
- path = Signing.unpack_ipa(path) if Signing.is_ipa?(path)
52
- get_bundle_id_from_plist("#{path}/Info.plist")
53
- end
48
+ # Gets properties from the IPA and returns them in a hash
49
+ # @param [String] path path to the IPA/App
50
+ # @return [Hash] list of properties from the app
51
+ def self.get_bundle_id_from_app(path)
52
+ path = Signing.unpack_ipa(path) if Signing.is_ipa?(path)
53
+ get_bundle_id_from_plist("#{path}/Info.plist")
54
+ end
54
55
 
55
- # Gets properties from the IPA and returns them in a hash
56
- # @param [String] plist path to the plist
57
- # @return [Hash] list of properties from the app
58
- def self.get_bundle_id_from_plist(plist)
59
- raise PlistutilCommandError.new('plistutil not found') unless plistutil_available?
60
- result = execute("plistutil -i #{plist}")
61
- raise PlistutilCommandError.new(result.stderr) if result.exit != 0
62
- parse_xml(result.stdout)
63
- end
56
+ # Gets properties from the IPA and returns them in a hash
57
+ # @param [String] plist path to the plist
58
+ # @return [Hash] list of properties from the app
59
+ def self.get_bundle_id_from_plist(plist)
60
+ raise PlistutilCommandError.new('plistutil not found') unless plistutil_available?
61
+ result = execute("plistutil -i #{plist}")
62
+ raise PlistutilCommandError.new(result.stderr) if result.exit != 0
63
+ parse_xml(result.stdout)
64
+ end
64
65
 
65
- def self.parse_xml(xml)
66
- info = Ox.parse(xml)
67
- nodes = info.locate('*/dict')
68
- values = {}
69
- last_key = nil
70
- nodes.each do |node|
71
- node.nodes.each do |child|
72
- if child.value == 'key'
73
- if child.nodes.first == 'get-task-allow'
74
- values['get-task-allow'] = nodes.first.nodes[nodes.first.nodes.index(child)+1].value
75
- next
66
+ def self.parse_xml(xml)
67
+ info = Ox.parse(xml)
68
+ nodes = info.locate('*/dict')
69
+ values = {}
70
+ last_key = nil
71
+ nodes.each do |node|
72
+ node.nodes.each do |child|
73
+ if child.value == 'key'
74
+ if child.nodes.first == 'get-task-allow'
75
+ values['get-task-allow'] = nodes.first.nodes[nodes.first.nodes.index(child)+1].value
76
+ next
77
+ end
78
+ last_key = child.nodes.first
79
+ elsif child.value == 'string'
80
+ values[last_key] = child.nodes.first
76
81
  end
77
- last_key = child.nodes.first
78
- elsif child.value == 'string'
79
- values[last_key] = child.nodes.first
80
82
  end
81
83
  end
84
+ values
82
85
  end
83
- values
84
86
  end
85
- end
86
87
 
87
- # plistutil error class
88
- class PlistutilCommandError < StandardError
89
- def initialize(msg)
90
- super(msg)
88
+ # plistutil error class
89
+ class PlistutilCommandError < StandardError
90
+ def initialize(msg)
91
+ super(msg)
92
+ end
91
93
  end
92
94
  end
93
95
  end
@@ -2,117 +2,121 @@ require 'fruity_builder/lib/execution'
2
2
  require 'fruity_builder/plistutil'
3
3
 
4
4
  module FruityBuilder
5
- # Namespace for all methods encapsulating idevice calls
6
- class Signing < Execution
5
+ module IOS
6
+ # Namespace for all methods encapsulating idevice calls
7
+ class Signing < Execution
8
+
9
+ # Check to see if the path is an IPA
10
+ def self.is_ipa?(path)
11
+ return true if (File.extname path).downcase == '.ipa'
12
+ false
13
+ end
7
14
 
8
- # Check to see if the path is an IPA
9
- def self.is_ipa?(path)
10
- return true if (File.extname path).downcase == '.ipa'
11
- false
12
- end
15
+ def self.unpack_ipa(path)
16
+ folder = File.dirname(path)
17
+ target = (File.basename path, (File.extname path))
13
18
 
14
- def self.unpack_ipa(path)
15
- folder = File.dirname(path)
16
- target = (File.basename path, (File.extname path))
19
+ # Check to see if the target has already been unzipped
20
+ return Dir["#{folder}/#{target}/Payload/*.app"].first if File.exists? ("#{folder}/#{target}/Payload/")
17
21
 
18
- # Check to see if the target has already been unzipped
19
- return Dir["#{folder}/#{target}/Payload/*.app"].first if File.exists? ("#{folder}/#{target}/Payload/")
22
+ result = execute("unzip '#{path}' -d '#{folder}/#{target}'")
23
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
20
24
 
21
- result = execute("unzip '#{path}' -d '#{folder}/#{target}'")
22
- raise SigningCommandError.new(result.stderr) if result.exit != 0
25
+ Dir["#{folder}/#{target}/Payload/*.app"].first
26
+ end
23
27
 
24
- Dir["#{folder}/#{target}/Payload/*.app"].first
25
- end
28
+ def self.is_app_signed?(app_path)
29
+ app_path = unpack_ipa(app_path) if is_ipa?(app_path)
30
+ result = execute("codesign -d -vvvv '#{app_path}'")
26
31
 
27
- def self.is_app_signed?(app_path)
28
- app_path = unpack_ipa(app_path) if is_ipa?(app_path)
29
- result = execute("codesign -d -vvvv '#{app_path}'")
32
+ if result.exit != 0
33
+ return false if /is not signed/.match(result.stderr)
34
+ raise SigningCommandError.new(result.stderr)
35
+ end
30
36
 
31
- if result.exit != 0
32
- return false if /is not signed/.match(result.stderr)
33
- raise SigningCommandError.new(result.stderr)
37
+ true
34
38
  end
35
39
 
36
- true
37
- end
38
-
39
- def self.sign_app(options = {})
40
- cert = options[:cert]
41
- entitlements = options[:entitlements]
42
- app = options[:app]
43
- original_app = nil
40
+ def self.sign_app(options = {})
41
+ cert = options[:cert]
42
+ entitlements = options[:entitlements]
43
+ app = options[:app]
44
+ original_app = nil
44
45
 
45
- if is_ipa?(app)
46
- original_app = app
47
- app = unpack_ipa(app)
48
- end
46
+ if is_ipa?(app)
47
+ original_app = app
48
+ app = unpack_ipa(app)
49
+ end
49
50
 
50
- # Check to see if the entitlements passed in is a file or the XML
51
- unless File.exists?(entitlements)
52
- file = Tempfile.new('entitlements')
53
- file.write(entitlements)
54
- file.close
55
- entitlements = file.path
56
- end
51
+ command = "codesign --force --sign '#{cert}'"
52
+ # Check to see if the entitlements passed in is a file or the XML
53
+ unless File.exists?(entitlements)
54
+ file = Tempfile.new('entitlements')
55
+ file.write(entitlements)
56
+ file.close
57
+ entitlements = file.path
58
+ command = command + " --entitlements #{entitlements}"
59
+ end
57
60
 
58
- result = execute("codesign --force --sign '#{cert}' --entitlements #{entitlements} '#{app}'")
61
+ result = execute(command + " '#{app}'")
59
62
 
60
- raise SigningCommandError.new(result.stderr) if result.exit != 0
63
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
61
64
 
62
- zip_app(app, original_app) if original_app
63
- end
65
+ zip_app(app, original_app) if original_app
66
+ end
64
67
 
65
- def self.zip_app(payload_path, ipa_path)
66
- result = execute("cd #{File.dirname(payload_path)}; zip -r #{ipa_path} ../Payload ")
67
- raise SigningCommandError.new(result.stderr) if result.exit != 0
68
+ def self.zip_app(payload_path, ipa_path)
69
+ result = execute("cd #{File.dirname(payload_path)}; zip -r #{ipa_path} ../Payload ")
70
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
68
71
 
69
- true
70
- end
72
+ true
73
+ end
71
74
 
72
- def self.get_signing_certs
73
- result = execute('security find-identity -p codesigning -v')
75
+ def self.get_signing_certs
76
+ result = execute('security find-identity -p codesigning -v')
74
77
 
75
- raise SigningCommandError.new(result.stderr) if result.exit != 0
78
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
76
79
 
77
- certs = []
78
- result.stdout.split("\n").each do |line|
79
- if /\)\s*(\S*)\s*"(.*)"/.match(line)
80
- certs << { id: Regexp.last_match[1], name: Regexp.last_match[2] }
80
+ certs = []
81
+ result.stdout.split("\n").each do |line|
82
+ if /\)\s*(\S*)\s*"(.*)"/.match(line)
83
+ certs << { id: Regexp.last_match[1], name: Regexp.last_match[2] }
84
+ end
81
85
  end
86
+ certs
82
87
  end
83
- certs
84
- end
85
88
 
86
- def self.get_entitlements(app_path, raw = false)
87
- app_path = unpack_ipa(app_path) if is_ipa?(app_path)
88
- result = execute("codesign -d --entitlements - #{app_path}")
89
+ def self.get_entitlements(app_path, raw = false)
90
+ app_path = unpack_ipa(app_path) if is_ipa?(app_path)
91
+ result = execute("codesign -d --entitlements - #{app_path}")
89
92
 
90
- if result.exit != 0
91
- raise SigningCommandError.new(result.stderr)
92
- end
93
+ if result.exit != 0
94
+ raise SigningCommandError.new(result.stderr)
95
+ end
93
96
 
94
- # Clean up the result as it occasionally contains invalid UTF-8 characters
95
- xml = result.stdout.to_s.encode('UTF-8', 'UTF-8', invalid: :replace)
96
- xml = xml[xml.index('<')..xml.length]
97
+ # Clean up the result as it occasionally contains invalid UTF-8 characters
98
+ xml = result.stdout.to_s.encode('UTF-8', 'UTF-8', invalid: :replace)
99
+ xml = xml[xml.index('<')..xml.length]
97
100
 
98
- return xml if raw
99
- entitlements = Plistutil.parse_xml(xml)
100
- return entitlements
101
- end
101
+ return xml if raw
102
+ entitlements = Plistutil.parse_xml(xml)
103
+ return entitlements
104
+ end
102
105
 
103
- def self.enable_get_tasks(app_path)
104
- entitlements = get_entitlements(app_path, raw: true)
106
+ def self.enable_get_tasks(app_path)
107
+ entitlements = get_entitlements(app_path, raw: true)
105
108
 
106
- return entitlements if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<true\/>/).count > 0
109
+ return entitlements if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<true\/>/).count > 0
107
110
 
108
- entitlements.gsub('<false/>', '<true/>') if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<false\/>/)
111
+ entitlements.gsub('<false/>', '<true/>') if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<false\/>/)
112
+ end
109
113
  end
110
- end
111
114
 
112
- # Signing error class
113
- class SigningCommandError < StandardError
114
- def initialize(msg)
115
- super(msg)
115
+ # Signing error class
116
+ class SigningCommandError < StandardError
117
+ def initialize(msg)
118
+ super(msg)
119
+ end
116
120
  end
117
121
  end
118
122
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fruity_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - BBC
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-02-19 00:00:00.000000000 Z
12
+ date: 2016-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ox