xcoder 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,204 @@
1
+ module Xcode
2
+ module Builder
3
+ #
4
+ # This class tries to pull various bits of Xcoder together to provide a higher-level API for common
5
+ # project build tasks.
6
+ #
7
+ class BaseBuilder
8
+ attr_accessor :profile, :identity, :build_path, :keychain, :sdk, :objroot, :symroot
9
+ attr_reader :config, :target
10
+
11
+ def initialize(target, config)
12
+ @target = target
13
+ @config = config
14
+
15
+ @sdk = @target.project.sdk
16
+ @build_path = "#{File.dirname(@target.project.path)}/build/"
17
+ @objroot = @build_path
18
+ @symroot = @build_path
19
+ end
20
+
21
+ def common_environment
22
+ env = {}
23
+ env["OBJROOT"] = "\"#{@objroot}\""
24
+ env["SYMROOT"] = "\"#{@symroot}\""
25
+ env
26
+ end
27
+
28
+ def build_environment
29
+ profile = install_profile
30
+ env = common_environment
31
+ env["OTHER_CODE_SIGN_FLAGS"] = "'--keychain #{@keychain.path}'" unless @keychain.nil?
32
+ env["CODE_SIGN_IDENTITY"] = "\"#{@identity}\"" unless @identity.nil?
33
+ env["PROVISIONING_PROFILE"] = "#{profile.uuid}" unless profile.nil?
34
+ env
35
+ end
36
+
37
+
38
+ def build(options = {:sdk => @sdk})
39
+ cmd = xcodebuild
40
+ cmd << "-sdk #{options[:sdk]}" unless options[:sdk].nil?
41
+
42
+ with_keychain do
43
+ cmd.execute
44
+ end
45
+ self
46
+ end
47
+
48
+ #
49
+ # Invoke the configuration's test target and parse the resulting output
50
+ #
51
+ # If a block is provided, the report is yielded for configuration before the test is run
52
+ #
53
+ def test(options = {:sdk => 'iphonesimulator'}) #, :parser => :OCUnit })
54
+ cmd = xcodebuild
55
+ cmd << "-sdk #{options[:sdk]}" unless options[:sdk].nil?
56
+ cmd.env["TEST_AFTER_BUILD"]="YES"
57
+
58
+ report = Xcode::Test::Report.new
59
+ if block_given?
60
+ yield(report)
61
+ else
62
+ report.add_formatter :stdout
63
+ report.add_formatter :junit, 'test-reports'
64
+ end
65
+
66
+ parser = Xcode::Test::Parsers::OCUnitParser.new report
67
+
68
+ begin
69
+ cmd.execute(false) do |line|
70
+ parser << line
71
+ end
72
+ rescue Xcode::Shell::ExecutionError => e
73
+ puts "Test platform exited: #{e.message}"
74
+ ensure
75
+ parser.flush
76
+ end
77
+
78
+ report
79
+ end
80
+
81
+ def testflight(api_token, team_token)
82
+ raise "Can't find #{ipa_path}, do you need to call builder.package?" unless File.exists? ipa_path
83
+ raise "Can't fins #{dsym_zip_path}, do you need to call builder.package?" unless File.exists? dsym_zip_path
84
+
85
+ testflight = Xcode::Testflight.new(api_token, team_token)
86
+ yield(testflight) if block_given?
87
+ testflight.upload(ipa_path, dsym_zip_path)
88
+ end
89
+
90
+ def clean
91
+ cmd = xcodebuild
92
+ cmd << "-sdk #{@sdk}" unless @sdk.nil?
93
+ cmd << "clean"
94
+ cmd.execute
95
+
96
+ @built = false
97
+ @packaged = false
98
+ self
99
+ end
100
+
101
+ def sign
102
+ cmd = Xcode::Shell::Command.new 'codesign'
103
+ cmd << "--force"
104
+ cmd << "--sign \"#{@identity}\""
105
+ cmd << "--resource-rules=\"#{app_path}/ResourceRules.plist\""
106
+ cmd << "--entitlements \"#{entitlements_path}\""
107
+ cmd << "\"#{ipa_path}\""
108
+ cmd.execute
109
+
110
+
111
+ self
112
+ end
113
+
114
+ def package
115
+ raise "Can't find #{app_path}, do you need to call builder.build?" unless File.exists? app_path
116
+
117
+ #package IPA
118
+ cmd = Xcode::Shell::Command.new 'xcrun'
119
+ cmd << "-sdk #{@sdk}" unless @sdk.nil?
120
+ cmd << "PackageApplication"
121
+ cmd << "-v \"#{app_path}\""
122
+ cmd << "-o \"#{ipa_path}\""
123
+
124
+ unless @profile.nil?
125
+ cmd << "--embed \"#{@profile}\""
126
+ end
127
+
128
+ with_keychain do
129
+ cmd.execute
130
+ end
131
+
132
+ # package dSYM
133
+ cmd = Xcode::Shell::Command.new 'zip'
134
+ cmd << "-r"
135
+ cmd << "-T"
136
+ cmd << "-y \"#{dsym_zip_path}\""
137
+ cmd << "\"#{dsym_path}\""
138
+ cmd.execute
139
+
140
+ self
141
+ end
142
+
143
+ def configuration_build_path
144
+ "#{build_path}/#{@config.name}-#{@sdk}"
145
+ end
146
+
147
+ def entitlements_path
148
+ "#{build_path}/#{@target.name}.build/#{name}-#{@target.project.sdk}/#{@target.name}.build/#{@config.product_name}.xcent"
149
+ end
150
+
151
+ def app_path
152
+ "#{configuration_build_path}/#{@config.product_name}.app"
153
+ end
154
+
155
+ def product_version_basename
156
+ version = @config.info_plist.version
157
+ version = "SNAPSHOT" if version.nil? or version==""
158
+ "#{configuration_build_path}/#{@config.product_name}-#{@config.name}-#{version}"
159
+ end
160
+
161
+ def ipa_path
162
+ "#{product_version_basename}.ipa"
163
+ end
164
+
165
+ def dsym_path
166
+ "#{app_path}.dSYM"
167
+ end
168
+
169
+ def dsym_zip_path
170
+ "#{product_version_basename}.dSYM.zip"
171
+ end
172
+
173
+ private
174
+
175
+ def with_keychain(&block)
176
+ if @keychain.nil?
177
+ yield
178
+ else
179
+ Xcode::Keychains.with_keychain_in_search_path @keychain, &block
180
+ end
181
+ end
182
+
183
+ def install_profile
184
+ return nil if @profile.nil?
185
+ # TODO: remove other profiles for the same app?
186
+ p = ProvisioningProfile.new(@profile)
187
+
188
+ ProvisioningProfile.installed_profiles.each do |installed|
189
+ if installed.identifiers==p.identifiers and installed.uuid==p.uuid
190
+ installed.uninstall
191
+ end
192
+ end
193
+
194
+ p.install
195
+ p
196
+ end
197
+
198
+ def xcodebuild #:yield: Xcode::Shell::Command
199
+ Xcode::Shell::Command.new 'xcodebuild', build_environment
200
+ end
201
+
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,14 @@
1
+ module Xcode
2
+ module Builder
3
+ class ProjectTargetConfigBuilder < BaseBuilder
4
+
5
+ def xcodebuild
6
+ cmd = super
7
+ cmd << "-project \"#{@target.project.path}\""
8
+ cmd << "-target \"#{@target.name}\""
9
+ cmd << "-config \"#{@config.name}\""
10
+ cmd
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ module Xcode
2
+
3
+ class Workspace
4
+ def to_xcodebuild_option
5
+ "-workspace \"#{self.path}\""
6
+ end
7
+ end
8
+
9
+ class Project
10
+ def to_xcodebuild_option
11
+ "-project \"#{self.path}\""
12
+ end
13
+ end
14
+
15
+ module Builder
16
+ class SchemeBuilder < BaseBuilder
17
+
18
+ def initialize(scheme)
19
+ @scheme = scheme
20
+ super @scheme.build_targets.last, @scheme.build_config
21
+ end
22
+
23
+ def xcodebuild
24
+ cmd = super
25
+ cmd << @scheme.parent.to_xcodebuild_option
26
+ cmd << "-scheme \"#{@scheme.name}\""
27
+ cmd
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -418,7 +418,7 @@ module Xcode
418
418
  # @see Builder
419
419
  #
420
420
  def builder
421
- Xcode::Builder.new(self)
421
+ Xcode::Builder::ProjectTargetConfigBuilder.new(@target, self)
422
422
  end
423
423
 
424
424
  private
@@ -37,11 +37,10 @@ module Xcode
37
37
  "\"#{kc.path}\""
38
38
  end
39
39
 
40
- cmd = []
41
- cmd << "security"
40
+ cmd = Xcode::Shell::Command.new "security"
42
41
  cmd << "list-keychain"
43
42
  cmd << "-s #{search_list.join(' ')}"
44
- Xcode::Shell.execute(cmd)
43
+ cmd.execute
45
44
  end
46
45
  end
47
46
 
@@ -70,13 +69,12 @@ module Xcode
70
69
  # @param [String] the password to open the certificate file
71
70
  #
72
71
  def import(cert, password)
73
- cmd = []
74
- cmd << "security"
72
+ cmd = Xcode::Shell::Command.new "security"
75
73
  cmd << "import '#{cert}'"
76
74
  cmd << "-k \"#{@path}\""
77
75
  cmd << "-P #{password}"
78
76
  cmd << "-T /usr/bin/codesign"
79
- Xcode::Shell.execute(cmd)
77
+ cmd.execute
80
78
  end
81
79
 
82
80
  #
@@ -86,12 +84,11 @@ module Xcode
86
84
  #
87
85
  def identities
88
86
  names = []
89
- cmd = []
90
- cmd << "security"
87
+ cmd = Xcode::Shell::Command.new "security"
91
88
  cmd << "find-certificate"
92
89
  cmd << "-a"
93
90
  cmd << "\"#{@path}\""
94
- data = Xcode::Shell.execute(cmd, false).join("")
91
+ data = cmd.execute(false).join("")
95
92
  data.scan /\s+"labl"<blob>="([^"]+)"/ do |m|
96
93
  names << m[0]
97
94
  end
@@ -102,11 +99,10 @@ module Xcode
102
99
  # Secure the keychain
103
100
  #
104
101
  def lock
105
- cmd = []
106
- cmd << "security"
102
+ cmd = Xcode::Shell::Command.new "security"
107
103
  cmd << "lock-keychain"
108
104
  cmd << "\"#{@path}\""
109
- Xcode::Shell.execute(cmd)
105
+ cmd.execute
110
106
  end
111
107
 
112
108
  #
@@ -115,12 +111,11 @@ module Xcode
115
111
  # @param [String] the password to open the keychain
116
112
  #
117
113
  def unlock(password)
118
- cmd = []
119
- cmd << "security"
114
+ cmd = Xcode::Shell::Command.new "security"
120
115
  cmd << "unlock-keychain"
121
116
  cmd << "-p #{password}"
122
117
  cmd << "\"#{@path}\""
123
- Xcode::Shell.execute(cmd)
118
+ cmd.execute
124
119
  end
125
120
 
126
121
  #
@@ -131,12 +126,11 @@ module Xcode
131
126
  # @return [Xcode::Keychain] an object representing the new keychain
132
127
  #
133
128
  def self.create(path, password)
134
- cmd = []
135
- cmd << "security"
129
+ cmd = Xcode::Shell::Command.new "security"
136
130
  cmd << "create-keychain"
137
131
  cmd << "-p #{password}"
138
132
  cmd << "\"#{path}\""
139
- Xcode::Shell.execute(cmd)
133
+ cmd.execute
140
134
 
141
135
  kc = Xcode::Keychain.new(path)
142
136
  yield(kc) if block_given?
@@ -149,10 +143,9 @@ module Xcode
149
143
  # FIXME: dangerous
150
144
  #
151
145
  def delete
152
- cmd = []
153
- cmd << "security"
146
+ cmd = Xcode::Shell::Command.new "security"
154
147
  cmd << "delete-keychain \"#{@path}\""
155
- Xcode::Shell.execute(cmd)
148
+ cmd.execute
156
149
  end
157
150
 
158
151
  #
data/lib/xcode/project.rb CHANGED
@@ -3,145 +3,145 @@ require 'xcode/resource'
3
3
  require 'xcode/registry'
4
4
 
5
5
  module Xcode
6
-
6
+
7
7
  #
8
8
  # The project is the representation of an Xcode Project folder, the `*.xcodeproj`,
9
9
  # folder that contains a number of workspace files and project files like
10
- # `project.pbxproj`.
11
- #
12
- #
10
+ # `project.pbxproj`.
11
+ #
12
+ #
13
13
  # The Project represents encapsulates the an actual Resource that is ProjectReference
14
14
  # and other objects.
15
- #
16
- class Project
17
-
18
- # @return [String] the name of the project; This value is deteremined from the
19
- # first part of the Xcode project folder name (e.g. "TestProject.xcodeproj"
15
+ #
16
+ class Project
17
+
18
+ # @return [String] the name of the project; This value is deteremined from the
19
+ # first part of the Xcode project folder name (e.g. "TestProject.xcodeproj"
20
20
  # name is "TestProject")
21
21
  attr_reader :name
22
-
22
+
23
23
  # @return [String] the sdks for the project. This is specified during the project
24
24
  # initialization. If none are provided this currently defaults to "iphoneos"
25
25
  attr_reader :sdk
26
-
26
+
27
27
  # @return [String] the expanded file path for the project. This is expanded from the
28
28
  # file path specified during initialization.
29
29
  attr_reader :path
30
-
30
+
31
31
  # @return [Array<Scheme>] the schemes that are found within the project path.
32
32
  attr_reader :schemes
33
-
33
+
34
34
  # @return [Registry] the data that is parsed from the project.pbxproj, it is
35
35
  # in most part a Hash with additional methods included to provide core
36
36
  # functionality.
37
37
  attr_reader :registry
38
-
39
- # @return [ProjectReference] the project object that is contained in the
38
+
39
+ # @return [ProjectReference] the project object that is contained in the
40
40
  # project file that contains additional information
41
41
  attr_reader :project
42
-
42
+
43
43
  #
44
44
  # Initialized with a specific path and sdk.
45
- #
45
+ #
46
46
  # This initialization is not often used. Instead projects are generated
47
47
  # through the Xcode#project method.
48
- #
48
+ #
49
49
  # @see Xcode
50
50
  #
51
51
  # @param [String] path of the project to open.
52
- # @param [String] sdk the sdk value of the project. This will default to
52
+ # @param [String] sdk the sdk value of the project. This will default to
53
53
  # `iphoneos`.
54
- #
54
+ #
55
55
  def initialize(path, sdk=nil)
56
56
  @sdk = sdk || "iphoneos" # FIXME: should support OSX/simulator too
57
57
  @path = File.expand_path path
58
58
  @schemes = nil
59
59
  @groups = []
60
60
  @name = File.basename(@path).gsub(/\.xcodeproj/,'')
61
-
61
+
62
62
  # Parse the Xcode project file and create the registry
63
-
63
+
64
64
  @registry = parse_pbxproj
65
65
  raise "Unable to parse project at #{@path}" if @registry.nil?
66
- @project = Xcode::Resource.new @registry.root, @registry
66
+ @project = Xcode::Resource.new @registry.root, @registry
67
67
  end
68
-
68
+
69
69
  #
70
70
  # @return [Array<Xcode::Scheme>] available schemes for the project
71
71
  #
72
72
  def schemes
73
73
  return @schemes unless @schemes.nil?
74
- @schemes = Xcode::Scheme.find_in_path @path
74
+ @schemes = Xcode::Scheme.find_in_project self
75
75
  end
76
-
77
-
76
+
77
+
78
78
  #
79
79
  # @return [Fixnum] the project's object version
80
- #
80
+ #
81
81
  def object_version
82
82
  @registry.object_version
83
83
  end
84
84
 
85
85
  #
86
86
  # @return [Fixnum] the project's archive version
87
- #
87
+ #
88
88
  def archive_version
89
89
  @registry.archive_version
90
90
  end
91
-
91
+
92
92
  #
93
93
  # @return [Array<Configuration>] a list of configurations global to the project
94
- #
94
+ #
95
95
  def global_configs
96
96
  @project.configs
97
97
  end
98
-
98
+
99
99
  #
100
100
  # @param [String,Symbol] name of the configuration for the project
101
- #
101
+ #
102
102
  # @return [Configuration] the project level configuration with the given name;
103
103
  # raise an exception if no configuration exists with that name.
104
104
  #
105
105
  def global_config(name)
106
106
  @project.config(name)
107
107
  end
108
-
108
+
109
109
  #
110
110
  # Returns the main group of the project where all the files reside.
111
- #
111
+ #
112
112
  # @todo this really could use a better name then groups as it is the main group
113
113
  # but it should likely be something like main_group, root or something
114
114
  # else that conveys that this is the project root for files, and such.
115
- #
115
+ #
116
116
  # @return [Group] the main group, the heart of the action of the file
117
117
  # explorer for the Xcode project. From here all other groups and items
118
118
  # may be found.
119
- #
119
+ #
120
120
  def groups
121
121
  @project.main_group
122
122
  end
123
-
123
+
124
124
  #
125
125
  # Returns the group specified. If any part of the group does not exist along
126
- # the path the group is created. Also paths can be specified to make the
126
+ # the path the group is created. Also paths can be specified to make the
127
127
  # traversing of the groups easier.
128
- #
128
+ #
129
129
  # @note this will attempt to find the paths specified, if it fails to find them
130
130
  # it will create one and then continue traversing.
131
131
  #
132
132
  # @example Traverse a path through the various sub-groups.
133
- #
133
+ #
134
134
  # project.group('Vendor/MyCode/Support Files')
135
135
  # # is equivalent to ...
136
136
  # project.group('Vendor').first.group('MyCode').first.group('Supporting Files')
137
- #
137
+ #
138
138
  # @note this path functionality current is only exercised from the project level
139
139
  # all groups will treat the path division `/` as simply a character.
140
- #
140
+ #
141
141
  # @param [String] name the group name to find/create
142
- #
142
+ #
143
143
  # @return [Group] the group with the specified name.
144
- #
144
+ #
145
145
  def group(name,options = {},&block)
146
146
  @project.group(name,options,&block)
147
147
  end
@@ -157,81 +157,81 @@ module Xcode
157
157
  path, name = File.split(name_with_path)
158
158
  group(path).file(name).first
159
159
  end
160
-
160
+
161
161
  #
162
- # Most Xcode projects have a products group where products are placed. This
162
+ # Most Xcode projects have a products group where products are placed. This
163
163
  # will generate an exception if there is no products group.
164
- #
164
+ #
165
165
  # @return [Group] the 'Products' group of the project.
166
166
  def products_group
167
167
  current_group = groups.group('Products').first
168
168
  current_group.instance_eval(&block) if block_given? and current_group
169
169
  current_group
170
170
  end
171
-
171
+
172
172
  #
173
- # Most Xcode projects have a Frameworks gorup where all the imported
173
+ # Most Xcode projects have a Frameworks gorup where all the imported
174
174
  # frameworks are shown. This will generate an exception if there is no
175
175
  # Frameworks group.
176
- #
176
+ #
177
177
  # @return [Group] the 'Frameworks' group of the projet.
178
178
  def frameworks_group
179
179
  current_group = groups.group('Frameworks').first
180
180
  current_group.instance_eval(&block) if block_given? and current_group
181
181
  current_group
182
182
  end
183
-
183
+
184
184
  #
185
- # This will convert the current project file into a supported Xcode Plist
185
+ # This will convert the current project file into a supported Xcode Plist
186
186
  # format. This format is not json or a traditional plist so several core
187
187
  # Ruby objects gained the #to_xcplist method to save it properly.
188
- #
189
- # Specifically this will add the necessary file header information and the
188
+ #
189
+ # Specifically this will add the necessary file header information and the
190
190
  # surrounding mustache braces around the xcode plist format of the registry.
191
- #
191
+ #
192
192
  # @return [String] Xcode Plist format of the project.
193
193
  def to_xcplist
194
-
194
+
195
195
  # @note The Hash#to_xcplist, which the Registry will save out as xcode,
196
- # saves a semi-colon at the end which needs to be removed to ensure
196
+ # saves a semi-colon at the end which needs to be removed to ensure
197
197
  # the project file can be opened.
198
-
198
+
199
199
  %{// !$*UTF8*$!"\n#{@registry.to_xcplist.gsub(/\};\s*\z/,'}')}}
200
200
  end
201
-
202
- #
201
+
202
+ #
203
203
  # Save the current project at the current path that it exists.
204
- #
204
+ #
205
205
  def save!
206
206
  save @path
207
207
  end
208
-
208
+
209
209
  #
210
210
  # Saves the current project at the specified path.
211
- #
212
- # @note currently this does not support saving the workspaces associated
211
+ #
212
+ # @note currently this does not support saving the workspaces associated
213
213
  # with the project to their new location.
214
- #
214
+ #
215
215
  # @param [String] path the path to save the project
216
216
  #
217
217
  def save(path)
218
-
218
+
219
219
  Dir.mkdir(path) unless File.exists?(path)
220
220
  project_filepath = "#{path}/project.pbxproj"
221
-
221
+
222
222
  # @toodo Save the workspace when the project is saved
223
223
  # FileUtils.cp_r "#{path}/project.xcworkspace", "#{path}/project.xcworkspace"
224
-
224
+
225
225
  Xcode::PLUTILProjectParser.save "#{path}/project.pbxproj", to_xcplist
226
-
226
+
227
227
  end
228
-
228
+
229
229
  #
230
- # Return the scheme with the specified name. Raises an error if no schemes
230
+ # Return the scheme with the specified name. Raises an error if no schemes
231
231
  # match the specified name.
232
- #
232
+ #
233
233
  # @note if two schemes match names, the first matching scheme is returned.
234
- #
234
+ #
235
235
  # @param [String] name of the specific scheme
236
236
  # @return [Scheme] the specific scheme that matches the name specified
237
237
  #
@@ -241,26 +241,26 @@ module Xcode
241
241
  yield scheme if block_given?
242
242
  scheme
243
243
  end
244
-
244
+
245
245
  #
246
246
  # All the targets specified within the project.
247
- #
247
+ #
248
248
  # @return [Array<Target>] an array of all the available targets for
249
249
  # the specific project.
250
- #
250
+ #
251
251
  def targets
252
252
  @project.targets.map do |target|
253
253
  target.project = self
254
254
  target
255
255
  end
256
256
  end
257
-
257
+
258
258
  #
259
259
  # Return the target with the specified name. Raises an error if no targets
260
260
  # match the specified name.
261
- #
261
+ #
262
262
  # @note if two targets match names, the first matching target is returned.
263
- #
263
+ #
264
264
  # @param [String] name of the specific target
265
265
  # @return [Target] the specific target that matches the name specified
266
266
  #
@@ -270,55 +270,55 @@ module Xcode
270
270
  yield target if block_given?
271
271
  target
272
272
  end
273
-
273
+
274
274
  #
275
275
  # Creates a new target within the Xcode project. This will by default not
276
276
  # generate all the additional build phases, configurations, and files
277
277
  # that create a project.
278
- #
278
+ #
279
279
  # Available targts:
280
- #
280
+ #
281
281
  # * native
282
282
  # * aggregate
283
- #
283
+ #
284
284
  # @param [String] name the name to provide to the target. This will also
285
285
  # be the value that other defaults will be based on.
286
286
  # @param [String,Symbol] type the type of build target to create.
287
287
  #
288
288
  # @return [Target] the target created.
289
- #
289
+ #
290
290
  def create_target(name,type=:native)
291
-
291
+
292
292
  target = @registry.add_object Target.send(type)
293
293
  @project.properties['targets'] << target.identifier
294
-
294
+
295
295
  target.name = name
296
-
296
+
297
297
  build_configuration_list = @registry.add_object(ConfigurationList.configration_list)
298
298
  target.build_configuration_list = build_configuration_list.identifier
299
-
299
+
300
300
  target.project = self
301
-
301
+
302
302
  yield target if block_given?
303
-
303
+
304
304
  target.save!
305
305
  end
306
-
306
+
307
307
  #
308
308
  # Remove a target from the Xcode project.
309
- #
309
+ #
310
310
  # @note this will remove the first target that matches the specified name.
311
- #
311
+ #
312
312
  # @note this will remove only the project entry at the moment and not the
313
- # the files that may be associated with the target. All build phases,
313
+ # the files that may be associated with the target. All build phases,
314
314
  # build files, and configurations will automatically be cleaned up when
315
315
  # Xcode is opened.
316
- #
316
+ #
317
317
  # @param [String] name the name of the target to remove from the Xcode
318
318
  # project.
319
319
  #
320
320
  # @return [Target] the target that has been removed.
321
- #
321
+ #
322
322
  def remove_target(name)
323
323
  found_target = targets.find {|target| target.name == name }
324
324
  if found_target
@@ -327,9 +327,9 @@ module Xcode
327
327
  end
328
328
  found_target
329
329
  end
330
-
331
- #
332
- # Prints to STDOUT a description of this project's targets, configuration and schemes.
330
+
331
+ #
332
+ # Prints to STDOUT a description of this project's targets, configuration and schemes.
333
333
  #
334
334
  def describe
335
335
  puts "Project #{name} contains"
@@ -345,25 +345,25 @@ module Xcode
345
345
  puts " + Test action => target:#{s.test.target.name}, config:#{s.test.name}" unless s.test.nil?
346
346
  end
347
347
  end
348
-
348
+
349
349
  private
350
-
350
+
351
351
  #
352
- # Using the sytem tool plutil, the specified project file is parsed and
353
- # converted to JSON, which is then converted to a hash object. This content
354
- # contains all the data within the project file and is used to create the
352
+ # Using the sytem tool plutil, the specified project file is parsed and
353
+ # converted to JSON, which is then converted to a hash object. This content
354
+ # contains all the data within the project file and is used to create the
355
355
  # Registry.
356
- #
356
+ #
357
357
  # @return [Registry] the representation of the project, this is a Hash with
358
358
  # additional methods to provide easier functionality.
359
- #
359
+ #
360
360
  def parse_pbxproj
361
361
  registry = Xcode::PLUTILProjectParser.parse "#{@path}/project.pbxproj"
362
-
362
+
363
363
  class << registry
364
364
  include Xcode::Registry
365
365
  end
366
-
366
+
367
367
  registry
368
368
  end
369
369