xcoder 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +2 -0
- data/README.md +56 -3
- data/Rakefile +8 -2
- data/lib/xcode/buildfile.rb +1 -1
- data/lib/xcode/configuration.rb +77 -4
- data/lib/xcode/configuration_owner.rb +86 -0
- data/lib/xcode/configurations/array_property.rb +6 -2
- data/lib/xcode/configurations/boolean_property.rb +4 -0
- data/lib/xcode/configurations/key_value_array_property.rb +42 -0
- data/lib/xcode/configurations/space_delimited_string_property.rb +4 -0
- data/lib/xcode/configurations/string_property.rb +4 -0
- data/lib/xcode/configurations/targeted_device_family_property.rb +13 -3
- data/lib/xcode/project.rb +13 -31
- data/lib/xcode/project_reference.rb +55 -0
- data/lib/xcode/provisioning_profile.rb +19 -1
- data/lib/xcode/registry.rb +9 -4
- data/lib/xcode/resource.rb +7 -5
- data/lib/xcode/target.rb +0 -64
- data/lib/xcode/test/ocunit_report_parser.rb +11 -2
- data/lib/xcode/version.rb +1 -1
- data/lib/xcoder/rake_task.rb +218 -0
- data/spec/Provisioning/AdHoc.mobileprovision +0 -0
- data/spec/Provisioning/AppStore.mobileprovision +0 -0
- data/spec/configuration_spec.rb +152 -34
- data/spec/project_spec.rb +14 -0
- data/spec/provisioning_profile_spec.rb +53 -0
- metadata +22 -12
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -43,7 +43,7 @@ You can either use the user's login keychain, another named keychain, or simply
|
|
43
43
|
|
44
44
|
#### Creating a temporary keychain
|
45
45
|
|
46
|
-
Xcode::Keychain.
|
46
|
+
Xcode::Keychain.temp do |keychain|
|
47
47
|
# import certs into the keychain
|
48
48
|
# perform builds within this keychain's context
|
49
49
|
end # Keychain is deleted
|
@@ -130,10 +130,63 @@ You can also optionally set a .proxy= property or just set the HTTP_PROXY enviro
|
|
130
130
|
You can invoke your test target/bundle from the builder
|
131
131
|
|
132
132
|
builder.test do |report|
|
133
|
-
report.
|
133
|
+
report.debug = false # default false, set to true to see raw output from xcodebuild
|
134
|
+
|
135
|
+
# The following is the default setup, you wouldnt normally need to do this unless
|
136
|
+
# you want to add new formatters
|
137
|
+
report.formatters = []
|
138
|
+
report.add_formatter :junit, 'test-reports' # Output JUnit format results to test-reports/
|
139
|
+
report.add_formatter :stdout # Output a simplified output to STDOUT
|
134
140
|
end
|
135
141
|
|
136
|
-
This will invoke the test target, capture the output and write the junit reports to the test-reports directory. Currently only junit is supported.
|
142
|
+
This will invoke the test target, capture the output and write the junit reports to the test-reports directory. Currently only junit is supported, although you can write your own formatter quite easily (for an example, look at Xcode::Test::Formatters::JunitFormatter).
|
143
|
+
|
144
|
+
## Rake Tasks
|
145
|
+
|
146
|
+
Xcoder provides a rake task to assist with make it easier to perform common Xcode project actions from the command-line.
|
147
|
+
|
148
|
+
Within your `Rakefile` add the following:
|
149
|
+
|
150
|
+
require 'xcoder/rake_task'
|
151
|
+
|
152
|
+
Then define your Rake Task:
|
153
|
+
|
154
|
+
Xcode::RakeTask.new
|
155
|
+
|
156
|
+
By default this will generate rake tasks within the 'xcode' namespace for
|
157
|
+
all the projects (within the current working directory), all their targets,
|
158
|
+
and all their configs. This will also generate tasks for all of a projects
|
159
|
+
schemes as well.
|
160
|
+
|
161
|
+
All names from the project, schemes, targets, and configs are remove
|
162
|
+
the camel-casing and replacing the cameling with underscores. Spaces
|
163
|
+
are replaced with dashes (-)
|
164
|
+
|
165
|
+
This will generate rake tasks that appear similar to the following:
|
166
|
+
|
167
|
+
rake xcode:project-name:targetname:debug:build
|
168
|
+
rake xcode:project-name:targetname:debug:clean
|
169
|
+
# ...
|
170
|
+
|
171
|
+
You can specify a parameter to change the root rake namespace:
|
172
|
+
|
173
|
+
Xcode::RakeTask.new :apple
|
174
|
+
|
175
|
+
# Resulting Rake Tasks:
|
176
|
+
# rake apple:project-name:targetname:debug:build
|
177
|
+
# rake apple:project-name:targetname:debug:clean
|
178
|
+
# ...
|
179
|
+
|
180
|
+
You can also supply a block to provide additional configuration to specify the folder to search for projects and the projects that should generate tasks for:
|
181
|
+
|
182
|
+
Xcode::RakeTask.new :hudson do |xcoder|
|
183
|
+
xcoder.directory = "projects"
|
184
|
+
xcoder.projects = [ "Project Alpha", "Project Beta" ]
|
185
|
+
end
|
186
|
+
|
187
|
+
rake hudson:project-alpha:targetname:debug:build
|
188
|
+
# ...
|
189
|
+
|
137
190
|
|
138
191
|
## Manipulating a Project
|
139
192
|
|
data/Rakefile
CHANGED
@@ -16,7 +16,7 @@ namespace :doc do
|
|
16
16
|
desc "Generate YARD docs"
|
17
17
|
YARD::Rake::YardocTask.new(:generate) do |t|
|
18
18
|
t.files = ['lib/**/*.rb', '-', 'README.md'] # optional
|
19
|
-
t.options = ["-o ../xcoder-doc"]
|
19
|
+
# t.options = ["-o ../xcoder-doc"]
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -27,7 +27,7 @@ namespace :test_project do
|
|
27
27
|
task :reset do
|
28
28
|
puts "Reseting the TestProject Project File"
|
29
29
|
system "git co -- spec/TestProject"
|
30
|
-
puts "Removing any User schemes generated
|
30
|
+
puts "Removing any User schemes generated in the project"
|
31
31
|
system "rm -rf spec/TestProject/TestProject.xcodeproj/xcuserdata"
|
32
32
|
puts "Removing any installed files"
|
33
33
|
system "git clean -df spec/TestProject"
|
@@ -35,3 +35,9 @@ namespace :test_project do
|
|
35
35
|
|
36
36
|
end
|
37
37
|
|
38
|
+
|
39
|
+
require './lib/xcoder/rake_task'
|
40
|
+
|
41
|
+
Xcode::RakeTask.new :xcode do |xcoder|
|
42
|
+
xcoder.directory = 'spec'
|
43
|
+
end
|
data/lib/xcode/buildfile.rb
CHANGED
@@ -54,7 +54,7 @@ module Xcode
|
|
54
54
|
puts "[#{label}] Set build profile to #{@values[:profile]}"
|
55
55
|
end
|
56
56
|
|
57
|
-
Keychain.
|
57
|
+
Keychain.temp do |kc|
|
58
58
|
kc.import @values[:certificate], @values[:password]
|
59
59
|
|
60
60
|
builder.identity = @values[:identity] || kc.identities.first
|
data/lib/xcode/configuration.rb
CHANGED
@@ -4,6 +4,7 @@ require 'xcode/configurations/targeted_device_family_property'
|
|
4
4
|
require 'xcode/configurations/string_property'
|
5
5
|
require 'xcode/configurations/boolean_property'
|
6
6
|
require 'xcode/configurations/array_property'
|
7
|
+
require 'xcode/configurations/key_value_array_property'
|
7
8
|
|
8
9
|
module Xcode
|
9
10
|
|
@@ -84,7 +85,18 @@ module Xcode
|
|
84
85
|
# Define a getter method
|
85
86
|
|
86
87
|
define_method property_name do
|
87
|
-
|
88
|
+
|
89
|
+
# When the build setting is missing from the existing configuration, look
|
90
|
+
# for the configuration of the target's project (only if we are currently
|
91
|
+
# at the Target level).
|
92
|
+
|
93
|
+
if not build_settings.key?(setting_name) and target.is_a?(Target)
|
94
|
+
project_config = target.project.global_config(name)
|
95
|
+
project_config.send(property_name)
|
96
|
+
else
|
97
|
+
substitute type.open(build_settings[setting_name])
|
98
|
+
end
|
99
|
+
|
88
100
|
end
|
89
101
|
|
90
102
|
# Define a setter method
|
@@ -92,7 +104,39 @@ module Xcode
|
|
92
104
|
define_method "#{property_name}=" do |value|
|
93
105
|
build_settings[setting_name] = unsubstitute(type.save(value))
|
94
106
|
end
|
107
|
+
|
108
|
+
# Define an append method
|
109
|
+
|
110
|
+
define_method "append_to_#{property_name}" do |value|
|
111
|
+
build_settings[setting_name] = unsubstitute type.append(build_settings[setting_name],value)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Define a environment name method (to return the settings name)
|
115
|
+
|
116
|
+
define_method "env_#{property_name}" do
|
117
|
+
setting_name
|
118
|
+
end
|
119
|
+
|
120
|
+
# Define a raw getter
|
121
|
+
|
122
|
+
define_method "raw_#{property_name}" do
|
123
|
+
build_settings[setting_name]
|
124
|
+
end
|
125
|
+
|
126
|
+
# Define a raw setter
|
127
|
+
|
128
|
+
define_method "raw_#{property_name}=" do |value|
|
129
|
+
build_settings[setting_name] = value
|
130
|
+
end
|
131
|
+
|
95
132
|
|
133
|
+
@setting_name_to_property = {} unless @setting_name_to_property
|
134
|
+
@setting_name_to_property[setting_name] = property_name
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.setting_name_to_property(name)
|
139
|
+
@setting_name_to_property[name]
|
96
140
|
end
|
97
141
|
|
98
142
|
#
|
@@ -149,7 +193,7 @@ module Xcode
|
|
149
193
|
# @attribute
|
150
194
|
# Build Setting - "OTHER_CFLAGS"
|
151
195
|
# @see https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW17
|
152
|
-
property :other_c_flags, "OTHER_CFLAGS",
|
196
|
+
property :other_c_flags, "OTHER_CFLAGS", KeyValueArrayProperty
|
153
197
|
|
154
198
|
# @attribute
|
155
199
|
# Build Setting - "GCC_C_LANGUAGE_STANDARD"
|
@@ -202,6 +246,11 @@ module Xcode
|
|
202
246
|
# @see https://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW144
|
203
247
|
property :copy_phase_strip, "COPY_PHASE_STRIP", BooleanProperty
|
204
248
|
|
249
|
+
# @attribute
|
250
|
+
# Build Setting - "OTHER_LDFLAGS"
|
251
|
+
# @see https://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW76
|
252
|
+
property :other_linker_flags, "OTHER_LDFLAGS", SpaceDelimitedString
|
253
|
+
|
205
254
|
#
|
206
255
|
# Opens the info plist associated with the configuration and allows you to
|
207
256
|
# edit the configuration.
|
@@ -236,7 +285,11 @@ module Xcode
|
|
236
285
|
# @return [String,Array,Hash] the value stored for the specified configuration
|
237
286
|
#
|
238
287
|
def get(name)
|
239
|
-
|
288
|
+
if Configuration.setting_name_to_property(name)
|
289
|
+
send Configuration.setting_name_to_property(name)
|
290
|
+
else
|
291
|
+
build_settings[name]
|
292
|
+
end
|
240
293
|
end
|
241
294
|
|
242
295
|
#
|
@@ -246,7 +299,27 @@ module Xcode
|
|
246
299
|
# @param [String,Array,Hash] value the value to store for the specific setting
|
247
300
|
#
|
248
301
|
def set(name, value)
|
249
|
-
|
302
|
+
if Configuration.setting_name_to_property(name)
|
303
|
+
send("#{Configuration.setting_name_to_property(name)}=",value)
|
304
|
+
else
|
305
|
+
build_settings[name] = value
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
#
|
310
|
+
# Append a value to the the configuration value for the given name
|
311
|
+
#
|
312
|
+
# @param [String] name of the the configuration setting
|
313
|
+
# @param [String,Array,Hash] value the value to store for the specific setting
|
314
|
+
#
|
315
|
+
def append(name, value)
|
316
|
+
if Configuration.setting_name_to_property(name)
|
317
|
+
send("append_to_#{Configuration.setting_name_to_property(name)}",value)
|
318
|
+
else
|
319
|
+
# @todo this will likely raise some errors if trying to append a string
|
320
|
+
# to an array, but that likely means a new property should be defined.
|
321
|
+
build_settings[name] = build_settings[name] + value
|
322
|
+
end
|
250
323
|
end
|
251
324
|
|
252
325
|
#
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Xcode
|
2
|
+
module ConfigurationOwner
|
3
|
+
|
4
|
+
#
|
5
|
+
# @return [Array<BuildConfiguration>] the configurations that this target
|
6
|
+
# or project supports. These are generally 'Debug' or 'Release' but may be
|
7
|
+
# custom created configurations.
|
8
|
+
#
|
9
|
+
def configs
|
10
|
+
build_configuration_list.build_configurations.map do |config|
|
11
|
+
config.target = self
|
12
|
+
config
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Return a specific build configuration.
|
18
|
+
#
|
19
|
+
# @note an exception is raised if no configuration matches the specified name.
|
20
|
+
#
|
21
|
+
# @param [String] name of a configuration to return
|
22
|
+
#
|
23
|
+
# @return [BuildConfiguration] a specific build configuration that
|
24
|
+
# matches the specified name.
|
25
|
+
#
|
26
|
+
def config(name)
|
27
|
+
config = configs.select {|config| config.name == name.to_s }.first
|
28
|
+
raise "No such config #{name}, available configs are #{configs.map {|c| c.name}.join(', ')}" if config.nil?
|
29
|
+
yield config if block_given?
|
30
|
+
config
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Create a configuration for the target or project.
|
35
|
+
#
|
36
|
+
# @example creating a new 'App Store Submission' configuration for a project
|
37
|
+
#
|
38
|
+
# project.create_config 'App Store Submission' # => Configuration
|
39
|
+
#
|
40
|
+
# @example creating a new 'Ad Hoc' configuration for a target
|
41
|
+
#
|
42
|
+
# target.create_config 'Ad Hoc' do |config|
|
43
|
+
# # configuration the new debug config.
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# @param [String] name of the configuration to create
|
47
|
+
# @return [BuildConfiguration] that is created
|
48
|
+
#
|
49
|
+
def create_configuration(name)
|
50
|
+
# To create a configuration, we need to create or retrieve the configuration list
|
51
|
+
|
52
|
+
created_config = build_configuration_list.create_config(name) do |config|
|
53
|
+
yield config if block_given?
|
54
|
+
end
|
55
|
+
|
56
|
+
created_config
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Create multiple configurations for a target or project.
|
61
|
+
#
|
62
|
+
# @example creating 'Release' and 'Debug for a new target
|
63
|
+
#
|
64
|
+
# new_target = project.create_target 'UniversalBinary'
|
65
|
+
# new_target.create_configurations 'Debug', 'Release' do |config|
|
66
|
+
# # set up the configurations
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# @param [String,Array<String>] configuration_names the names of the
|
70
|
+
# configurations to create.
|
71
|
+
#
|
72
|
+
def create_configurations(*configuration_names)
|
73
|
+
|
74
|
+
configuration_names.compact.flatten.map do |config_name|
|
75
|
+
created_config = create_configuration config_name do |config|
|
76
|
+
yield config if block_given?
|
77
|
+
end
|
78
|
+
|
79
|
+
created_config.save!
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -16,7 +16,7 @@ module Xcode
|
|
16
16
|
# @param [Array] value to be parsed into the correct format
|
17
17
|
#
|
18
18
|
def open(value)
|
19
|
-
value
|
19
|
+
Array(value)
|
20
20
|
end
|
21
21
|
|
22
22
|
#
|
@@ -24,7 +24,11 @@ module Xcode
|
|
24
24
|
# be in a multitude of formats as long as it responds_to? #to_a
|
25
25
|
#
|
26
26
|
def save(value)
|
27
|
-
value
|
27
|
+
Array(value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def append(original,value)
|
31
|
+
(Array(original) + Array(value)).uniq
|
28
32
|
end
|
29
33
|
|
30
34
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module Xcode
|
3
|
+
module Configuration
|
4
|
+
|
5
|
+
#
|
6
|
+
# Within the a build settings for a configuration there are a number of
|
7
|
+
# settings that are stored as key-value pairs in Arrays.
|
8
|
+
#
|
9
|
+
module KeyValueArrayProperty
|
10
|
+
extend self
|
11
|
+
|
12
|
+
#
|
13
|
+
# As arrays are stored as arrays this is not particularly different.
|
14
|
+
#
|
15
|
+
# @param [Array] value to be parsed into the correct format
|
16
|
+
#
|
17
|
+
def open(value)
|
18
|
+
Array(value)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# @param [Nil,Array,String] value that is being saved back which can
|
23
|
+
# be in a multitude of formats as long as it responds_to? #to_a
|
24
|
+
#
|
25
|
+
def save(value)
|
26
|
+
Array(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# To ensure uniqueness, the original value array is added to the new value
|
31
|
+
# array and then all the key-values pairs are placed in a Hash then mapped
|
32
|
+
# back out to a key=value pair array.
|
33
|
+
#
|
34
|
+
def append(original,value)
|
35
|
+
all_values = (Array(original) + Array(value)).map {|key_value| key_value.split("=") }.flatten
|
36
|
+
Hash[*all_values].map {|k,v| "#{k}=#{v}" }
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -23,16 +23,26 @@ module Xcode
|
|
23
23
|
end
|
24
24
|
|
25
25
|
#
|
26
|
-
# @param [Array<String>] value convert the array of platform names
|
26
|
+
# @param [String,Array<String>] value convert the array of platform names
|
27
27
|
# @return [String] the comma-delimited list of numeric values representing
|
28
28
|
# the platforms.
|
29
29
|
#
|
30
30
|
def save(value)
|
31
31
|
Array(value).map do |platform_name|
|
32
32
|
platforms.map {|number,name| number if name.to_s == platform_name.to_s.downcase }
|
33
|
-
end.flatten.compact.join(",")
|
33
|
+
end.flatten.compact.uniq.join(",")
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
|
+
#
|
37
|
+
# @param [String] original is the current string value stored in the configuration
|
38
|
+
# that needs to be converted into an Array of names.
|
39
|
+
# @param [String,Array<String>] value the new values to include in the device
|
40
|
+
# family.
|
41
|
+
#
|
42
|
+
def append(original,value)
|
43
|
+
save(open(original) + Array(value))
|
44
|
+
end
|
45
|
+
|
36
46
|
private
|
37
47
|
|
38
48
|
def platforms
|
data/lib/xcode/project.rb
CHANGED
@@ -9,9 +9,9 @@ module Xcode
|
|
9
9
|
# folder that contains a number of workspace files and project files like
|
10
10
|
# `project.pbxproj`.
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
12
|
+
#
|
13
|
+
# The Project represents encapsulates the an actual Resource that is ProjectReference
|
14
|
+
# and other objects.
|
15
15
|
#
|
16
16
|
class Project
|
17
17
|
|
@@ -78,6 +78,14 @@ module Xcode
|
|
78
78
|
@registry.archive_version
|
79
79
|
end
|
80
80
|
|
81
|
+
def global_configs
|
82
|
+
@project.configs
|
83
|
+
end
|
84
|
+
|
85
|
+
def global_config(name)
|
86
|
+
@project.config(name)
|
87
|
+
end
|
88
|
+
|
81
89
|
#
|
82
90
|
# Returns the main group of the project where all the files reside.
|
83
91
|
#
|
@@ -115,31 +123,9 @@ module Xcode
|
|
115
123
|
# @return [Group] the group with the specified name.
|
116
124
|
#
|
117
125
|
def group(name,options = {},&block)
|
118
|
-
|
119
|
-
options = { :create => true }.merge(options)
|
120
|
-
|
121
|
-
current_group = @project.main_group
|
122
|
-
|
123
|
-
# @todo consider this traversing and find/create as a normal procedure when
|
124
|
-
# traversing the project.
|
125
|
-
|
126
|
-
name.split("/").each do |path_component|
|
127
|
-
found_group = current_group.group(path_component).first
|
128
|
-
|
129
|
-
if options[:create] and found_group.nil?
|
130
|
-
found_group = current_group.create_group(path_component)
|
131
|
-
end
|
132
|
-
|
133
|
-
current_group = found_group
|
134
|
-
|
135
|
-
break unless current_group
|
136
|
-
end
|
137
|
-
|
138
|
-
current_group.instance_eval(&block) if block_given? and current_group
|
139
|
-
|
140
|
-
current_group
|
126
|
+
@project.group(name,options,&block)
|
141
127
|
end
|
142
|
-
|
128
|
+
|
143
129
|
#
|
144
130
|
# Return the file that matches the specified path. This will traverse
|
145
131
|
# the project's groups and find the file at the end of the path.
|
@@ -159,9 +145,7 @@ module Xcode
|
|
159
145
|
# @return [Group] the 'Products' group of the project.
|
160
146
|
def products_group
|
161
147
|
current_group = groups.group('Products').first
|
162
|
-
|
163
148
|
current_group.instance_eval(&block) if block_given? and current_group
|
164
|
-
|
165
149
|
current_group
|
166
150
|
end
|
167
151
|
|
@@ -173,9 +157,7 @@ module Xcode
|
|
173
157
|
# @return [Group] the 'Frameworks' group of the projet.
|
174
158
|
def frameworks_group
|
175
159
|
current_group = groups.group('Frameworks').first
|
176
|
-
|
177
160
|
current_group.instance_eval(&block) if block_given? and current_group
|
178
|
-
|
179
161
|
current_group
|
180
162
|
end
|
181
163
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Xcode
|
2
|
+
|
3
|
+
module ProjectReference
|
4
|
+
|
5
|
+
#
|
6
|
+
# Returns the group specified. If any part of the group does not exist along
|
7
|
+
# the path the group is created. Also paths can be specified to make the
|
8
|
+
# traversing of the groups easier.
|
9
|
+
#
|
10
|
+
# @note this will attempt to find the paths specified, if it fails to find them
|
11
|
+
# it will create one and then continue traversing.
|
12
|
+
#
|
13
|
+
# @example Traverse a path through the various sub-groups.
|
14
|
+
#
|
15
|
+
# project.group('Vendor/MyCode/Support Files')
|
16
|
+
# # is equivalent to ...
|
17
|
+
# project.group('Vendor').first.group('MyCode').first.group('Supporting Files')
|
18
|
+
#
|
19
|
+
# @note this path functionality current is only exercised from the project level
|
20
|
+
# all groups will treat the path division `/` as simply a character.
|
21
|
+
#
|
22
|
+
# @param [String] name the group name to find/create
|
23
|
+
#
|
24
|
+
# @return [Group] the group with the specified name.
|
25
|
+
#
|
26
|
+
def group(name,options = {},&block)
|
27
|
+
# By default create missing groups along the way
|
28
|
+
options = { :create => true }.merge(options)
|
29
|
+
|
30
|
+
current_group = main_group
|
31
|
+
|
32
|
+
# @todo consider this traversing and find/create as a normal procedure when
|
33
|
+
# traversing the project.
|
34
|
+
|
35
|
+
name.split("/").each do |path_component|
|
36
|
+
found_group = current_group.group(path_component).first
|
37
|
+
|
38
|
+
if options[:create] and found_group.nil?
|
39
|
+
found_group = current_group.create_group(path_component)
|
40
|
+
end
|
41
|
+
|
42
|
+
current_group = found_group
|
43
|
+
|
44
|
+
break unless current_group
|
45
|
+
end
|
46
|
+
|
47
|
+
current_group.instance_eval(&block) if block_given? and current_group
|
48
|
+
|
49
|
+
current_group
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -1,17 +1,31 @@
|
|
1
1
|
module Xcode
|
2
2
|
class ProvisioningProfile
|
3
|
-
attr_reader :path, :name, :uuid, :identifiers
|
3
|
+
attr_reader :path, :name, :uuid, :identifiers, :devices, :appstore
|
4
4
|
def initialize(path)
|
5
5
|
|
6
6
|
raise "Provisioning profile '#{path}' does not exist" unless File.exists? path
|
7
7
|
|
8
8
|
@path = path
|
9
9
|
@identifiers = []
|
10
|
+
@devices = []
|
11
|
+
@appstore = true
|
10
12
|
|
11
13
|
# TODO: im sure this could be done in a nicer way. maybe read out the XML-like stuff and use the plist -> json converter
|
12
14
|
uuid = nil
|
13
15
|
File.open(path, "rb") do |f|
|
14
16
|
input = f.read
|
17
|
+
|
18
|
+
if input=~/ProvisionedDevices/
|
19
|
+
@appstore = false
|
20
|
+
end
|
21
|
+
|
22
|
+
if input=~/<key>ProvisionedDevices<\/key>.*?<array>(.*?)<\/array>/im
|
23
|
+
$1.split(/<string>/).each do |id|
|
24
|
+
next if id.nil? or id.strip==""
|
25
|
+
@devices << id.gsub(/<\/string>/,'').strip
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
15
29
|
input=~/<key>UUID<\/key>.*?<string>(.*?)<\/string>/im
|
16
30
|
@uuid = $1.strip
|
17
31
|
|
@@ -26,6 +40,10 @@ module Xcode
|
|
26
40
|
end
|
27
41
|
|
28
42
|
end
|
43
|
+
|
44
|
+
def appstore?
|
45
|
+
@appstore
|
46
|
+
end
|
29
47
|
|
30
48
|
def self.profiles_path
|
31
49
|
File.expand_path "~/Library/MobileDevice/Provisioning\\ Profiles/"
|