zerg_xcode 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/Manifest +9 -0
- data/RUBYFORGE +2 -2
- data/lib/zerg_xcode/objects/pbx_container_item_proxy.rb +10 -0
- data/lib/zerg_xcode/objects/pbx_group.rb +3 -0
- data/lib/zerg_xcode/objects/pbx_project.rb +11 -0
- data/lib/zerg_xcode/objects/pbx_target_dependency.rb +7 -0
- data/lib/zerg_xcode/objects/xc_configuration_list.rb +3 -0
- data/lib/zerg_xcode/objects/xcode_object.rb +16 -2
- data/lib/zerg_xcode/plugins/import.rb +306 -1
- data/lib/zerg_xcode.rb +4 -0
- data/test/objects/pbx_container_item_proxy_test.rb +14 -0
- data/test/objects/pbx_group_test.rb +12 -0
- data/test/objects/pbx_project_test.rb +12 -0
- data/test/objects/pbx_target_dependency_test.rb +14 -0
- data/test/objects/xc_configuration_list_test.rb +12 -0
- data/test/objects/xcode_object_test.rb +26 -0
- data/test/plugins/import_test.rb +211 -2
- data/testdata/FlatTestApp/FlatTestApp.xcodeproj/project.pbxproj +332 -0
- data/testdata/ZergSupport.xcodeproj/project.pbxproj +33 -52
- data/zerg_xcode.gemspec +5 -5
- metadata +19 -2
data/CHANGELOG
CHANGED
data/Manifest
CHANGED
@@ -6,8 +6,12 @@ lib/zerg_xcode/file_format/lexer.rb
|
|
6
6
|
lib/zerg_xcode/file_format/parser.rb
|
7
7
|
lib/zerg_xcode/file_format/paths.rb
|
8
8
|
lib/zerg_xcode/objects/pbx_build_file.rb
|
9
|
+
lib/zerg_xcode/objects/pbx_container_item_proxy.rb
|
10
|
+
lib/zerg_xcode/objects/pbx_group.rb
|
9
11
|
lib/zerg_xcode/objects/pbx_native_target.rb
|
10
12
|
lib/zerg_xcode/objects/pbx_project.rb
|
13
|
+
lib/zerg_xcode/objects/pbx_target_dependency.rb
|
14
|
+
lib/zerg_xcode/objects/xc_configuration_list.rb
|
11
15
|
lib/zerg_xcode/objects/xcode_object.rb
|
12
16
|
lib/zerg_xcode/plugins/core/core.rb
|
13
17
|
lib/zerg_xcode/plugins/help.rb
|
@@ -28,8 +32,12 @@ test/file_format/lexer_test.rb
|
|
28
32
|
test/file_format/parser_test.rb
|
29
33
|
test/file_format/path_test.rb
|
30
34
|
test/objects/pbx_build_file_test.rb
|
35
|
+
test/objects/pbx_container_item_proxy_test.rb
|
36
|
+
test/objects/pbx_group_test.rb
|
31
37
|
test/objects/pbx_native_target_test.rb
|
32
38
|
test/objects/pbx_project_test.rb
|
39
|
+
test/objects/pbx_target_dependency_test.rb
|
40
|
+
test/objects/xc_configuration_list_test.rb
|
33
41
|
test/objects/xcode_object_test.rb
|
34
42
|
test/plugins/core/core_test.rb
|
35
43
|
test/plugins/import_test.rb
|
@@ -38,6 +46,7 @@ test/plugins/ls_test.rb
|
|
38
46
|
test/plugins/retarget_test.rb
|
39
47
|
test/plugins/test_helper.rb
|
40
48
|
test/shortcuts_test.rb
|
49
|
+
testdata/FlatTestApp/FlatTestApp.xcodeproj/project.pbxproj
|
41
50
|
testdata/project.pbxproj
|
42
51
|
testdata/project.pbxproj.compat
|
43
52
|
testdata/TestApp/TestApp.xcodeproj/project.pbxproj
|
data/RUBYFORGE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Quickstart for Rubyforge:
|
2
2
|
|
3
|
-
1)
|
3
|
+
1) Get the code
|
4
4
|
git clone git@github.com:costan/zerg_xcode.git
|
5
5
|
|
6
6
|
2) Install the rubyforge gem
|
@@ -30,7 +30,7 @@ Releasing a new gemspec to Github
|
|
30
30
|
rake package
|
31
31
|
|
32
32
|
2) Copy the spec
|
33
|
-
cp pkg/zerg_xcode
|
33
|
+
cp pkg/zerg_xcode-*/zerg_xcode.gemspec .
|
34
34
|
|
35
35
|
3) Commit the spec
|
36
36
|
git add zerg_xcode.gemspec
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Proxy for another object.
|
2
|
+
#
|
3
|
+
# Unsure these are useful, since each object has an unique ID. They are probably
|
4
|
+
# implementation artifacts.
|
5
|
+
class ZergXcode::Objects::PBXContainerItemProxy < ZergXcode::XcodeObject
|
6
|
+
# The proxied object.
|
7
|
+
def target
|
8
|
+
self['remoteGlobalIDString']
|
9
|
+
end
|
10
|
+
end
|
@@ -3,12 +3,23 @@ class ZergXcode::Objects::PBXProject < ZergXcode::XcodeObject
|
|
3
3
|
# Used to implement save!
|
4
4
|
attr_accessor :source_filename
|
5
5
|
|
6
|
+
# :nodoc: override to copy the new metadata
|
7
|
+
def copy_metadata(source)
|
8
|
+
super
|
9
|
+
self.source_filename = source.source_filename
|
10
|
+
end
|
11
|
+
|
6
12
|
# Saves a project that was loaded by ZergXcode.load
|
7
13
|
def save!
|
8
14
|
raise 'Project not loaded by ZergXcode.load' unless @source_filename
|
9
15
|
ZergXcode.dump self, @source_filename
|
10
16
|
end
|
11
17
|
|
18
|
+
# The root path of the project.
|
19
|
+
def root_path
|
20
|
+
ZergXcode::Paths.project_root_at source_filename
|
21
|
+
end
|
22
|
+
|
12
23
|
# All the files referenced by the project.
|
13
24
|
def all_files
|
14
25
|
files = []
|
@@ -71,6 +71,16 @@ class ZergXcode::XcodeObject
|
|
71
71
|
visit_hash(@attrs, &accept)
|
72
72
|
self
|
73
73
|
end
|
74
|
+
|
75
|
+
# Convenience method mapping over visit and exploring each object once.
|
76
|
+
def visit_once(&accept)
|
77
|
+
visited = Set.new([self])
|
78
|
+
self.visit do |object, parent, key, value|
|
79
|
+
visited << object
|
80
|
+
next_value = yield object, parent, key, value
|
81
|
+
visited.include?(value) ? false : next_value
|
82
|
+
end
|
83
|
+
end
|
74
84
|
|
75
85
|
def visit_hash(hash, &accept)
|
76
86
|
hash.each_key do |key|
|
@@ -137,8 +147,12 @@ class ZergXcode::XcodeObject
|
|
137
147
|
|
138
148
|
def shallow_copy
|
139
149
|
new_object = self.class.new @attrs.dup
|
140
|
-
new_object.
|
150
|
+
new_object.copy_metadata self
|
141
151
|
return new_object
|
142
|
-
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def copy_metadata(source)
|
155
|
+
self.archive_id, self.version = source.archive_id, source.version
|
156
|
+
end
|
143
157
|
end
|
144
158
|
|
@@ -1,4 +1,9 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
|
1
4
|
class ZergXcode::Plugins::Import
|
5
|
+
include ZergXcode::Objects
|
6
|
+
|
2
7
|
def help
|
3
8
|
{:short => 'imports the objects from a project into another project',
|
4
9
|
:long => <<"END" }
|
@@ -14,6 +19,306 @@ END
|
|
14
19
|
source = ZergXcode.load args.shift
|
15
20
|
target = ZergXcode.load(args.shift || '.')
|
16
21
|
|
17
|
-
|
22
|
+
file_ops = import_project! source, target
|
23
|
+
target.save!
|
24
|
+
execute_file_ops! file_ops
|
25
|
+
end
|
26
|
+
|
27
|
+
# Executes the given file operations.
|
28
|
+
def execute_file_ops!(file_ops)
|
29
|
+
file_ops.each do |op|
|
30
|
+
case op[:op]
|
31
|
+
when :delete
|
32
|
+
FileUtils.rm_r op[:path] if File.exist? op[:path]
|
33
|
+
when :copy
|
34
|
+
target_dir = File.dirname op[:to]
|
35
|
+
FileUtils.mkdir_p target_dir unless File.exist? target_dir
|
36
|
+
if File.exist? op[:from]
|
37
|
+
FileUtils.cp_r op[:from], op[:to]
|
38
|
+
else
|
39
|
+
print "Source does not have file #{op[:from]}\n"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Imports the objects of the source project into the target project.
|
46
|
+
#
|
47
|
+
# Attempts to preserve reference integrity in the target project, as follows.
|
48
|
+
# If the source objects have counterparts in the target, their contents is
|
49
|
+
# merged into the target project's objects.
|
50
|
+
#
|
51
|
+
# Returns an array of file operations that need to be performed to migrate the
|
52
|
+
# files associated with the two projects.
|
53
|
+
#
|
54
|
+
# The target project is modified in place.
|
55
|
+
def import_project!(source, target)
|
56
|
+
old_target_paths = target.all_files.map { |file| file[:path] }
|
57
|
+
|
58
|
+
# duplicate the source, because the duplicate's object graph will be warped
|
59
|
+
scrap_source = ZergXcode::XcodeObject.from source
|
60
|
+
|
61
|
+
mappings = cross_reference scrap_source, target
|
62
|
+
bins = bin_mappings mappings, scrap_source
|
63
|
+
|
64
|
+
# special case for merging targets
|
65
|
+
map! scrap_source, mappings
|
66
|
+
merge! scrap_source['targets'], target['targets']
|
67
|
+
|
68
|
+
# merge the object graphs
|
69
|
+
bins[:merge].each do |object|
|
70
|
+
map! object, mappings
|
71
|
+
merge! object, mappings[object]
|
72
|
+
end
|
73
|
+
bins[:overwrite].each do |object|
|
74
|
+
map! object, mappings
|
75
|
+
overwrite! object, mappings[object]
|
76
|
+
end
|
77
|
+
|
78
|
+
# make sure all the mappings point in the right place
|
79
|
+
target.visit_once do |object, parent, key, value|
|
80
|
+
if mappings[value]
|
81
|
+
next mappings[value]
|
82
|
+
else
|
83
|
+
next true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
new_target_paths = target.all_files.map { |file| file[:path] }
|
88
|
+
source_paths = source.all_files.map { |file| file[:path] }
|
89
|
+
return compute_deletes(target.root_path, old_target_paths,
|
90
|
+
new_target_paths) +
|
91
|
+
compute_copies(source.root_path, source_paths, target.root_path)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Computes the file delete operations in a merge.
|
95
|
+
#
|
96
|
+
# Deletes all the files that aren't in the target project anymore.
|
97
|
+
def compute_deletes(root, old_paths, new_paths)
|
98
|
+
new_path_set = Set.new(new_paths)
|
99
|
+
old_paths.select { |path| path[0, 2] == './' }.
|
100
|
+
reject { |path| new_path_set.include? path }.
|
101
|
+
map { |path| { :op => :delete, :path => clean_join(root, path) } }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Computes the file copy operations in a merge.
|
105
|
+
#
|
106
|
+
# Copies all the files from the source project assuming they received the same
|
107
|
+
# path in the target project. The assumption is correct if source was imported
|
108
|
+
# into target.
|
109
|
+
def compute_copies(source_root, source_paths, target_root)
|
110
|
+
source_paths.select { |path| path[0, 2] == './' }.map do |path|
|
111
|
+
{ :op => :copy, :from => clean_join(source_root, path),
|
112
|
+
:to => clean_join(target_root, path) }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def clean_join(root, path)
|
117
|
+
Pathname.new(File.join(root, path)).cleanpath.to_s
|
118
|
+
end
|
119
|
+
|
120
|
+
# Bins merge mappings for a project into mappings to be merged and mappings to
|
121
|
+
# be overwritten.
|
122
|
+
def bin_mappings(mappings, source)
|
123
|
+
merge_set = Set.new
|
124
|
+
overwrite_set = Set.new
|
125
|
+
|
126
|
+
# the project's top-level attributes are always merged
|
127
|
+
source.attrs.each do |attr|
|
128
|
+
merge_set << source[attr] if mappings[source[attr]]
|
129
|
+
end
|
130
|
+
|
131
|
+
mappings.each do |source_object, target_object|
|
132
|
+
next if source_object == target_object
|
133
|
+
next if merge_set.include? source_object
|
134
|
+
|
135
|
+
if source_object.kind_of?(PBXGroup) && source_object['path'].nil?
|
136
|
+
merge_set << source_object
|
137
|
+
elsif source_object.kind_of? XCConfigurationList
|
138
|
+
merge_set << source_object
|
139
|
+
else
|
140
|
+
overwrite_set << source_object
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
overwrite_set.delete source
|
145
|
+
{ :merge => merge_set, :overwrite => overwrite_set }
|
146
|
+
end
|
147
|
+
|
148
|
+
# Modifies an object's attributes according to the given mappings.
|
149
|
+
# This explores the object graph, but does not go into sub-objects.
|
150
|
+
def map!(object, mappings)
|
151
|
+
object.visit_once do |object, parent, key, value|
|
152
|
+
if mappings[value]
|
153
|
+
parent[key] = mappings[value]
|
154
|
+
next false
|
155
|
+
end
|
156
|
+
next true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Merges the contents of a source object into the target object.
|
161
|
+
#
|
162
|
+
# Warning: the target will share internal objects with the source. This is
|
163
|
+
# intended to be used in a bigger-level opration, where the source will be
|
164
|
+
# thrown away afterwards.
|
165
|
+
def merge!(source, target)
|
166
|
+
if source.class != target.class
|
167
|
+
raise "Attempting to merge-combine different kinds of objects - " +
|
168
|
+
"#{source.class} != #{target.class}"
|
169
|
+
end
|
170
|
+
|
171
|
+
case source
|
172
|
+
when ZergXcode::XcodeObject
|
173
|
+
merge! source._attr_hash, target._attr_hash
|
174
|
+
when Hash
|
175
|
+
source.each_key do |key|
|
176
|
+
if !target.has_key?(key)
|
177
|
+
target[key] = source[key]
|
178
|
+
elsif source[key].kind_of? ZergXcode::XcodeObject
|
179
|
+
target[key] = source[key]
|
180
|
+
elsif source[key].kind_of?(String)
|
181
|
+
target[key] = source[key]
|
182
|
+
elsif !source[key].kind_of?(Enumerable)
|
183
|
+
target[key] = source[key]
|
184
|
+
else
|
185
|
+
merge! source[key], target[key]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
when Enumerable
|
189
|
+
target_set = Set.new(target.to_a)
|
190
|
+
source.each do |value|
|
191
|
+
next if target_set.include? value
|
192
|
+
target << value
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Overwrites the contents of the target object with the source object.
|
198
|
+
#
|
199
|
+
# Warning: the target will share internal objects with the source. This is
|
200
|
+
# intended to be used in a bigger-level opration, where the source will be
|
201
|
+
# thrown away afterwards.
|
202
|
+
def overwrite!(source, target)
|
203
|
+
if source.class != target.class
|
204
|
+
raise "Attempting to overwrite-combine different kinds of objects - " +
|
205
|
+
"#{source.class} != #{target.class}"
|
206
|
+
end
|
207
|
+
|
208
|
+
case source
|
209
|
+
when ZergXcode::XcodeObject
|
210
|
+
overwrite! source._attr_hash, target._attr_hash
|
211
|
+
when Hash
|
212
|
+
target.clear
|
213
|
+
target.merge! source
|
214
|
+
when Enumerable
|
215
|
+
target.clear
|
216
|
+
source.each { |value| target << value }
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Cross-references the objects in two object graphs that are to be merged.
|
221
|
+
# Returns a Hash associating objects in both the source and the target object
|
222
|
+
# graphs with the corresponding objects in the
|
223
|
+
def cross_reference(source, target, mappings = {})
|
224
|
+
if source.class != target.class
|
225
|
+
raise "Attempting to cross-reference different kinds of objects - " +
|
226
|
+
"#{source.class} != #{target.class}"
|
227
|
+
end
|
228
|
+
|
229
|
+
case target
|
230
|
+
when ZergXcode::XcodeObject
|
231
|
+
cross_op = :cross_reference_objects
|
232
|
+
when Hash
|
233
|
+
cross_op = :cross_reference_hashes
|
234
|
+
when Enumerable
|
235
|
+
cross_op = :cross_reference_enumerables
|
236
|
+
else
|
237
|
+
return mappings
|
238
|
+
end
|
239
|
+
|
240
|
+
self.send cross_op, source, target, mappings
|
241
|
+
end
|
242
|
+
|
243
|
+
def cross_reference_objects(source, target, mappings)
|
244
|
+
return mappings if mappings[source] || mappings[target]
|
245
|
+
return mappings if source.xref_key != target.xref_key
|
246
|
+
|
247
|
+
mappings[target] = target
|
248
|
+
mappings[source] = target
|
249
|
+
cross_reference source._attr_hash, target._attr_hash, mappings
|
250
|
+
end
|
251
|
+
private :cross_reference_objects
|
252
|
+
|
253
|
+
def cross_reference_hashes(source, target, mappings)
|
254
|
+
source.each_key do |key|
|
255
|
+
p [source.keys, key] if source[key].nil?
|
256
|
+
cross_reference source[key], target[key], mappings if target[key]
|
257
|
+
end
|
258
|
+
mappings
|
259
|
+
end
|
260
|
+
private :cross_reference_hashes
|
261
|
+
|
262
|
+
def cross_reference_enumerables(source, target, mappings)
|
263
|
+
source_keys = {}
|
264
|
+
source.each do |value|
|
265
|
+
next unless value.kind_of? ZergXcode::XcodeObject
|
266
|
+
source_keys[value.xref_key] = value
|
267
|
+
end
|
268
|
+
target.each do |value|
|
269
|
+
next unless value.kind_of? ZergXcode::XcodeObject
|
270
|
+
next unless source_value = source_keys[value.xref_key]
|
271
|
+
cross_reference source_value, value, mappings
|
272
|
+
end
|
273
|
+
mappings
|
274
|
+
end
|
275
|
+
private :cross_reference_enumerables
|
276
|
+
end
|
277
|
+
|
278
|
+
class ZergXcode::XcodeObject
|
279
|
+
def xref_key
|
280
|
+
# If the object doesn't have a merge name, use its (unique) object_id.
|
281
|
+
[isa, xref_name || object_id]
|
282
|
+
end
|
283
|
+
|
284
|
+
def xref_name
|
285
|
+
# Do not use this to override xref_name for specific objects. Only use
|
286
|
+
# it for object families.
|
287
|
+
case isa.to_s
|
288
|
+
when /BuildPhase$/
|
289
|
+
isa.to_s
|
290
|
+
else
|
291
|
+
self['name'] || self['explicitPath'] || self['path']
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
class ZergXcode::Objects::PBXBuildFile
|
297
|
+
def xref_name
|
298
|
+
self['fileRef'].xref_name
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
class ZergXcode::Objects::PBXProject
|
303
|
+
def xref_name
|
304
|
+
isa.to_s
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
class ZergXcode::Objects::XCConfigurationList
|
309
|
+
def xref_name
|
310
|
+
isa.to_s
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
class ZergXcode::Objects::PBXContainerItemProxy
|
315
|
+
def xref_name
|
316
|
+
self['remoteInfo']
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
class ZergXcode::Objects::PBXTargetDependency
|
321
|
+
def xref_name
|
322
|
+
target.xref_name
|
18
323
|
end
|
19
324
|
end
|
data/lib/zerg_xcode.rb
CHANGED
@@ -10,8 +10,12 @@ require 'zerg_xcode/file_format/paths.rb'
|
|
10
10
|
|
11
11
|
require 'zerg_xcode/objects/xcode_object.rb'
|
12
12
|
require 'zerg_xcode/objects/pbx_build_file.rb'
|
13
|
+
require 'zerg_xcode/objects/pbx_container_item_proxy.rb'
|
14
|
+
require 'zerg_xcode/objects/pbx_group.rb'
|
13
15
|
require 'zerg_xcode/objects/pbx_native_target.rb'
|
14
16
|
require 'zerg_xcode/objects/pbx_project.rb'
|
17
|
+
require 'zerg_xcode/objects/pbx_target_dependency.rb'
|
18
|
+
require 'zerg_xcode/objects/xc_configuration_list.rb'
|
15
19
|
require 'zerg_xcode/plugins/core/core.rb'
|
16
20
|
|
17
21
|
require 'zerg_xcode/shortcuts.rb'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'zerg_xcode'
|
4
|
+
|
5
|
+
class PBXContainerItemProxyTest < Test::Unit::TestCase
|
6
|
+
PBXContainerItemProxy = ZergXcode::Objects::PBXContainerItemProxy
|
7
|
+
|
8
|
+
def test_target
|
9
|
+
proj = ZergXcode.load 'testdata/ZergSupport.xcodeproj/project.pbxproj'
|
10
|
+
proxy = proj['targets'][2]['dependencies'].first['targetProxy']
|
11
|
+
assert_equal PBXContainerItemProxy, proxy.class
|
12
|
+
assert_equal proj['targets'][1], proxy.target
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'zerg_xcode'
|
4
|
+
|
5
|
+
class PBXGroupTest < Test::Unit::TestCase
|
6
|
+
PBXGroup = ZergXcode::Objects::PBXGroup
|
7
|
+
|
8
|
+
def test_instantiation
|
9
|
+
proj = ZergXcode.load 'testdata/project.pbxproj'
|
10
|
+
assert_equal PBXGroup, proj['mainGroup'].class
|
11
|
+
end
|
12
|
+
end
|
@@ -59,4 +59,16 @@ class PBXProjectTest < Test::Unit::TestCase
|
|
59
59
|
and_return(nil)
|
60
60
|
project.save!
|
61
61
|
end
|
62
|
+
|
63
|
+
def test_root_path
|
64
|
+
project = ZergXcode.load('testdata/ZergSupport.xcodeproj')
|
65
|
+
assert_equal 'testdata', project.root_path
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_copy_metadata
|
69
|
+
project = ZergXcode.load('testdata/ZergSupport.xcodeproj')
|
70
|
+
clone = ZergXcode::XcodeObject.from project
|
71
|
+
|
72
|
+
assert_equal project.source_filename, clone.source_filename
|
73
|
+
end
|
62
74
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'zerg_xcode'
|
4
|
+
|
5
|
+
class PBXTargetDependencyTest < Test::Unit::TestCase
|
6
|
+
PBXTargetDependency = ZergXcode::Objects::PBXTargetDependency
|
7
|
+
|
8
|
+
def test_target
|
9
|
+
proj = ZergXcode.load 'testdata/ZergSupport.xcodeproj/project.pbxproj'
|
10
|
+
dependency = proj['targets'][2]['dependencies'].first
|
11
|
+
assert_equal PBXTargetDependency, dependency.class
|
12
|
+
assert_equal proj['targets'][1], dependency.target
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'zerg_xcode'
|
4
|
+
|
5
|
+
class XCConfigurationListTest < Test::Unit::TestCase
|
6
|
+
XCConfigurationList = ZergXcode::Objects::XCConfigurationList
|
7
|
+
|
8
|
+
def test_instantiation
|
9
|
+
proj = ZergXcode.load 'testdata/project.pbxproj'
|
10
|
+
assert_equal XCConfigurationList, proj['buildConfigurationList'].class
|
11
|
+
end
|
12
|
+
end
|
@@ -46,6 +46,32 @@ class ObjectTest < Test::Unit::TestCase
|
|
46
46
|
assert_equal golden_visited.sort, visited.sort
|
47
47
|
end
|
48
48
|
|
49
|
+
def test_visit_once
|
50
|
+
golden_visited = [
|
51
|
+
[49, 'sub1', @sub1],
|
52
|
+
[39, 'array', @sub1[:array]],
|
53
|
+
[39, '0', 'a'],
|
54
|
+
[39, '1', 'b'],
|
55
|
+
[39, '2', 'c'],
|
56
|
+
[39, 'string', 's'],
|
57
|
+
[39, 'root', @root],
|
58
|
+
[49, 'sub2', @sub2],
|
59
|
+
[42, 'hash', @sub2[:hash]],
|
60
|
+
[42, 'k', 'v'],
|
61
|
+
[42, 'k2', 'v2'],
|
62
|
+
[42, 'sub1', @sub1],
|
63
|
+
]
|
64
|
+
@sub1['root'] = @root
|
65
|
+
|
66
|
+
visited = []
|
67
|
+
@root.visit_once do |object, parent, key, value|
|
68
|
+
assert_equal value, parent[key], 'Parent/Key/Value check'
|
69
|
+
visited << [object.archive_id, key.to_s, value]
|
70
|
+
next true
|
71
|
+
end
|
72
|
+
assert_equal golden_visited.sort, visited.sort
|
73
|
+
end
|
74
|
+
|
49
75
|
def test_mutating_visit
|
50
76
|
golden_visited = [
|
51
77
|
[49, 'sub1', @sub1],
|