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.
@@ -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,7 @@
1
+
2
+ module IOSDevTools
3
+
4
+ autoload :ApplicationBundle, 'ios_dev_tools/application_bundle'
5
+ autoload :ProvisioningProfile, 'ios_dev_tools/provisioning_profile'
6
+
7
+ end
@@ -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
+