ios_dev_tools 0.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.
- data/bin/ios_sign +115 -0
- data/lib/ios_dev_tools.rb +7 -0
- data/lib/ios_dev_tools/application_bundle.rb +98 -0
- data/lib/ios_dev_tools/provisioning_profile.rb +30 -0
- metadata +64 -0
data/bin/ios_sign
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'ios_dev_tools'
|
5
|
+
|
6
|
+
$be_verbose=false
|
7
|
+
|
8
|
+
def verbose_msg message
|
9
|
+
|
10
|
+
puts message if $be_verbose
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def error_msg message
|
15
|
+
|
16
|
+
puts "\nERROR:\t#{message}\n"
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_options(args)
|
21
|
+
|
22
|
+
options = Hash.new
|
23
|
+
OptionParser.new do |opts|
|
24
|
+
|
25
|
+
opts.banner = "Usage: ios_sign.rb -i \"iPhone Distribution: Name\" -p path/to/profile -o output/ipa/file [options] inputIpa"
|
26
|
+
|
27
|
+
opts.separator ""
|
28
|
+
opts.separator "Options:"
|
29
|
+
|
30
|
+
opts.on("-p", "--profile PATH_TO_PROFILE", "Path to profile") do |profile_location|
|
31
|
+
options[:profile_location] = profile_location
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on("-b", "--bundle-id [BUNDLE_IDENTIFIER]", "Bundle identifier") do |bundle_id|
|
35
|
+
options[:bundle_id] = bundle_id
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on("-o", "--output OUTPUT_IPA_FILE", "Output ipa archive") do |output_ipa|
|
39
|
+
options[:output_ipa] = output_ipa
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on("-i", "--identity IDENTITY", "Identity") do |identity|
|
43
|
+
options[:identity] = identity
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("-t", "--temp [TEMP_FOLDER]", "Temporary folder location") do |temp_folder|
|
47
|
+
options[:temp_folder] = temp_folder
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.separator ""
|
51
|
+
opts.separator "Common options:"
|
52
|
+
|
53
|
+
opts.on("-v", "--verbose", "Run verbosely") do |v|
|
54
|
+
options[:verbose] = v
|
55
|
+
end
|
56
|
+
|
57
|
+
# No argument, shows at tail. This will print an options summary.
|
58
|
+
# Try it and see!
|
59
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
60
|
+
puts opts
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
|
64
|
+
end.parse!(args)
|
65
|
+
|
66
|
+
options[:input_file]=ARGV[0]
|
67
|
+
mandatory=[options[:profile_location],options[:identity],options[:output_ipa],options[:input_file]]
|
68
|
+
expected_number=mandatory.count
|
69
|
+
real_number=mandatory.compact.count
|
70
|
+
if expected_number != real_number
|
71
|
+
# one of mandatory switches is missing
|
72
|
+
# display help and exit
|
73
|
+
parse_options ["-h"]
|
74
|
+
end
|
75
|
+
|
76
|
+
$be_verbose=(options[:verbose]!=nil)
|
77
|
+
|
78
|
+
return options
|
79
|
+
end
|
80
|
+
|
81
|
+
def main
|
82
|
+
|
83
|
+
options=parse_options ARGV
|
84
|
+
|
85
|
+
verbose_msg "Passed options:\n#{options.inspect}"
|
86
|
+
|
87
|
+
begin
|
88
|
+
provisioning_profile=IOSDevTools::ProvisioningProfile.new options[:profile_location]
|
89
|
+
application_bundle=IOSDevTools::ApplicationBundle.new options[:input_file] do |ab|
|
90
|
+
ab.temp_folder=options[:temp_folder]
|
91
|
+
end
|
92
|
+
rescue => error
|
93
|
+
error_msg error
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
|
97
|
+
new_bundle_id = options[:bundle_id]
|
98
|
+
new_bundle_id ||= application_bundle.bundle_id
|
99
|
+
|
100
|
+
if not provisioning_profile.is_compatible_with_bundle_id new_bundle_id
|
101
|
+
error_msg "Provisioning profile identifier [#{provisioning_profile.application_identifier}] is not compatible with bundle identifier [#{new_bundle_id}]\n \
|
102
|
+
\tMaybe you should use -b switch to overwrite the bundle identifier?"
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
|
106
|
+
application_bundle.bundle_id = new_bundle_id
|
107
|
+
application_bundle.set_provisioning_profile provisioning_profile.profile_location
|
108
|
+
application_bundle.sign_with_identity options[:identity]
|
109
|
+
application_bundle.package_to_ipa options[:output_ipa]
|
110
|
+
|
111
|
+
puts "\nApplication archive created and signed: #{options[:output_ipa]}"
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
main
|
@@ -0,0 +1,98 @@
|
|
1
|
+
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module IOSDevTools
|
5
|
+
|
6
|
+
#
|
7
|
+
#
|
8
|
+
#
|
9
|
+
class ApplicationBundle
|
10
|
+
|
11
|
+
attr_accessor :is_application_folder
|
12
|
+
attr_accessor :is_valid_zip_archive
|
13
|
+
attr_accessor :src_location
|
14
|
+
attr_accessor :location
|
15
|
+
attr_accessor :temp_folder
|
16
|
+
attr_accessor :plist_buddy_cmd
|
17
|
+
attr_accessor :application_name
|
18
|
+
|
19
|
+
def initialize file_or_folder_location
|
20
|
+
|
21
|
+
raise "Application bundle \"#{file_or_folder_location}\" doesn't exist" if not File.exists? file_or_folder_location
|
22
|
+
|
23
|
+
@is_application_folder=File.directory?(file_or_folder_location) && file_or_folder_location.end_with?(".app")
|
24
|
+
if not @is_application_folder
|
25
|
+
@is_valid_zip_archive=`file #{file_or_folder_location}`.include? "Zip archive data"
|
26
|
+
raise "[#{file_or_folder_location}] is not a valid application archive" if not @is_valid_zip_archive
|
27
|
+
end
|
28
|
+
|
29
|
+
yield self if block_given?
|
30
|
+
|
31
|
+
@src_location=file_or_folder_location
|
32
|
+
@temp_folder||="temp"
|
33
|
+
@plist_buddy_cmd||="/usr/libexec/PlistBuddy"
|
34
|
+
|
35
|
+
if not @is_application_folder
|
36
|
+
# wipe out temp folder
|
37
|
+
`rm -Rf #{temp_folder}/Payload 2>&1 > /dev/null`
|
38
|
+
# unzip application bundle
|
39
|
+
`unzip -q "#{@src_location}" -d #{@temp_folder}`
|
40
|
+
# point to unzipped location
|
41
|
+
@location=Dir.glob("#{@temp_folder}/Payload/*")[0]
|
42
|
+
else
|
43
|
+
@location=@src_location
|
44
|
+
end
|
45
|
+
|
46
|
+
@application_name=Pathname.new(@location).basename
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def display_name
|
51
|
+
`#{@plist_buddy_cmd} -c "Print :CFBundleDisplayName" "#{@location}/Info.plist"`.strip
|
52
|
+
end
|
53
|
+
|
54
|
+
def display_name= new_name
|
55
|
+
return if not new_name
|
56
|
+
`#{@plist_buddy_cmd} -c "Set :CFBundleDisplayName #{new_name}" "#{@location}/Info.plist"`
|
57
|
+
end
|
58
|
+
|
59
|
+
def bundle_id
|
60
|
+
`#{@plist_buddy_cmd} -c "Print :CFBundleIdentifier" "#{@location}/Info.plist"`.strip
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundle_id= new_bundle_id
|
64
|
+
return if not new_bundle_id
|
65
|
+
`#{@plist_buddy_cmd} -c "Set :CFBundleIdentifier #{new_bundle_id}" "#{@location}/Info.plist"`
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_provisioning_profile new_provisioning_profile_location
|
69
|
+
return if not new_provisioning_profile_location
|
70
|
+
`cp "#{new_provisioning_profile_location}" "#{@location}/embedded.mobileprovision"`
|
71
|
+
end
|
72
|
+
|
73
|
+
def sign_with_identity new_identity
|
74
|
+
return if not new_identity
|
75
|
+
`/usr/bin/codesign -f -s "#{new_identity}" --resource-rules="#{@location}/ResourceRules.plist" "#{@location}" 2>&1`
|
76
|
+
end
|
77
|
+
|
78
|
+
def current_identity
|
79
|
+
|
80
|
+
invalid_signature=`codesign -d -vv "#{@location}" 2>&1`.include? "invalid signature"
|
81
|
+
return "Invalid signature" if invalid_signature
|
82
|
+
|
83
|
+
codesign_output=`codesign -d -vv "#{@location}" 2>&1 | grep "Authority"`
|
84
|
+
info=codesign_output.lines.first
|
85
|
+
return info.strip.split("=")[1] if info
|
86
|
+
|
87
|
+
return nil
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def package_to_ipa ipa_file_location
|
92
|
+
return if not ipa_file_location
|
93
|
+
`(cd #{@temp_folder} && zip -qr ../temp.ipa *) && mv temp.ipa "#{ipa_file_location}"`
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module IOSDevTools
|
4
|
+
|
5
|
+
class ProvisioningProfile
|
6
|
+
|
7
|
+
attr_accessor :profile_location
|
8
|
+
|
9
|
+
def initialize profile_location
|
10
|
+
|
11
|
+
raise "Profisioning profile file \"#{profile_location}\" doesn't exist" if not File.exists? profile_location
|
12
|
+
|
13
|
+
@profile_location=profile_location
|
14
|
+
|
15
|
+
yield self if block_given?
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def application_identifier
|
20
|
+
`egrep -a -A 2 application-identifier "#{@profile_location}" | grep string | sed -e 's/<string>//' -e 's/<\\/string>//' -e 's/ //' | awk '{split($0,a,"."); i = length(a); for(ix=2; ix <= i;ix++){ s=s a[ix]; if(i!=ix){s=s "."};} print s;}'`.strip
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_compatible_with_bundle_id bundle_id
|
24
|
+
bundle_id_prefix=application_identifier.sub(/\*$/,"")
|
25
|
+
bundle_id.start_with? bundle_id_prefix
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ios_dev_tools
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Marcin Maciukiewicz
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2013-12-28 00:00:00 +00:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Set of ruby wrappers around iOS dev tasks
|
22
|
+
email: mm@csquirrel.com
|
23
|
+
executables:
|
24
|
+
- ios_sign
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/ios_dev_tools.rb
|
31
|
+
- lib/ios_dev_tools/application_bundle.rb
|
32
|
+
- lib/ios_dev_tools/provisioning_profile.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: https://github.com/cSquirrel/ios_dev_tools
|
35
|
+
licenses:
|
36
|
+
- MIT
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project: nowarning
|
59
|
+
rubygems_version: 1.3.6
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: iOS Dev Tools
|
63
|
+
test_files: []
|
64
|
+
|