pbxplorer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # pbxplorer
2
+
3
+ pbxplorer is a set of Ruby classes for parsing, editing, and saving Xcode project (.pbxproj) files. It can also be used to explore the contents of a project using the interactive Ruby shell.
4
+
5
+ ### Dependencies
6
+
7
+ pbxplorer has no Ruby dependencies outside of the standard library. It uses the OS X **plutil** command to parse the project file.
8
+
9
+ ### Overview
10
+
11
+ An Xcode project (.pbxproj) file is essentially a hash of objects keyed by UUID. The objects are hashes of properties keyed by name. The associated values can be strings, arrays, or hashes.
12
+
13
+ Each object hash contains an "isa" property that identifies its type. pbxplorer loads a project file hash and replaces each generic object hash with a specific subclass based on its type.
14
+
15
+ ### Class Hierarchy
16
+
17
+ PBXObject and PBXBuildPhase are abstract superclasses. All other subclasses of PBXObject correspond to object hashes in the project, based on their "isa" property.
18
+
19
+ ```
20
+ PBXObject
21
+ PBXBuildFile
22
+ PBXBuildPhase
23
+ PBXFrameworksBuildPhase
24
+ PBXResourcesBuildPhase
25
+ PBXShellScriptBuildPhase
26
+ PBXSourcesBuildPhase
27
+ PBXFileReference
28
+ PBXGroup
29
+ PBXProject
30
+ PBXNativeTarget
31
+ XCBuildConfiguration
32
+ XCConfigurationList
33
+ XCProjectFile
34
+ ```
35
+
36
+ ### Reference Hierarchy
37
+
38
+ In the project file, objects are referenced from other objects by UUID. pbxplorer includes convenience methods to return the objects themselves rather than the UUIDs. Below are the method names and object types returned.
39
+
40
+ ```
41
+ PBXProject
42
+ build_configuration_list: XCConfigurationList
43
+ main_group: PBXGroup
44
+ targets: [PBXNativeTarget]
45
+
46
+ XCConfigurationList
47
+ build_configurations: [XCBuildConfiguration]
48
+
49
+ PBXGroup
50
+ children: [PBXGroup|PBXFileReference]
51
+ subgroups: [PBXGroup]
52
+ file_refs: [PBXFileReference]
53
+
54
+ PBXNativeTarget
55
+ build_configuration_list: XCBuildConfigurationList
56
+ build_phases: [PBXBuildPhase]
57
+ product_file_ref: PBXFileReference
58
+
59
+ PBXBuildPhase
60
+ build_files: [PBXBuildFile]
61
+
62
+ PBXBuildFile
63
+ file_ref: PBXFileReference
64
+ ```
65
+
66
+ ### Interactive Use
67
+
68
+ To get started:
69
+
70
+ ```ruby
71
+ $ irb
72
+ >> require 'pbxplorer'
73
+ => true
74
+ >> XCProjectFile.help
75
+ project_file = XCProjectFile.new '/path/to/project.pbxproj'
76
+ => XCProjectFile
77
+ ```
78
+
79
+ The help displays a suggested statement followed by the type of the assigned result. Enter the statement in the shell, editing as necessary:
80
+
81
+ ```ruby
82
+ >> project_file = XCProjectFile.new 'project.pbxproj'
83
+ => {
84
+ rootObject = "4D0B81831657473000DEF560"
85
+ objects = < 63 objects >
86
+ }
87
+ ```
88
+
89
+ This`XCProjectFile`instance contains a reference to the root object (a`PBXProject`instance), and the collection of all objects.
90
+
91
+ Get help from the **project_file** object:
92
+
93
+ ```ruby
94
+ >> project_file.help
95
+ project = project_file.project
96
+ => PBXProject
97
+ ```
98
+
99
+ Enter the statement:
100
+
101
+ ```ruby
102
+ >> project = project_file.project
103
+ => 4D0B81831657473000DEF560 = {
104
+ attributes = {"CLASSPREFIX"=>"Example", "LastUpgradeCheck"=>"0450", "ORGANIZATIONNAME"=>"Example"}
105
+ projectRoot = ""
106
+ hasScannedForEncodings = "0"
107
+ mainGroup = "4D0B81811657473000DEF560"
108
+ buildConfigurationList = "4D0B81861657473000DEF560"
109
+ compatibilityVersion = "Xcode 3.2"
110
+ productRefGroup = "4D0B818D1657473000DEF560"
111
+ projectDirPath = ""
112
+ knownRegions = ["en"]
113
+ targets = ["4D0B818B1657473000DEF560", "4D0B81AC1657473100DEF560"]
114
+ developmentRegion = "English"
115
+ isa = "PBXProject"
116
+ }
117
+ ```
118
+
119
+ This`PBXProject`instance contains an array of references to targets (`PBXNativeTarget`instances).
120
+
121
+ Get help from the **project** object:
122
+
123
+ ```ruby
124
+ >> project.help
125
+ target = project.targets.first
126
+ => PBXNativeTarget
127
+ list = project.build_configuration_list
128
+ => XCConfigurationList
129
+ group = project.main_group
130
+ => PBXGroup
131
+ ```
132
+
133
+ This time the help suggests three objects we can retrieve next; the first`PBXNativeTarget`instance, the sole`XCConfigurationList`instance, and the main`PBXGroup`instance.
134
+
135
+ Enter the target statement:
136
+
137
+ ```ruby
138
+ >> target = project.targets.first
139
+ => 4D0B818B1657473000DEF560 = {
140
+ productName = "Example"
141
+ productReference = "4D0B818C1657473000DEF560"
142
+ name = "Example"
143
+ dependencies = []
144
+ buildConfigurationList = "4D0B81BF1657473100DEF560"
145
+ productType = "com.apple.product-type.application"
146
+ buildPhases = ["4D0B81881657473000DEF560", "4D0B81891657473000DEF560", "4D0B818A1657473000DEF560"]
147
+ isa = "PBXNativeTarget"
148
+ buildRules = []
149
+ }
150
+ ```
151
+
152
+ You can continue exploring the object graph in this manner, down to `PBXFileReference`objects, which contain no references to other objects.
153
+
154
+ ### Example: removing a source file
155
+
156
+ ```ruby
157
+ file_ref = project_file.objects_of_class(PBXFileReference, { "path" => "ExampleTests.m" }).first
158
+ build_phases = project_file.objects_of_class PBXBuildPhase
159
+ build_files = project_file.objects_of_class PBXBuildFile, { "fileRef" => file_ref.uuid }
160
+ build_file_uuids = build_files.map { |obj| obj.uuid }
161
+ groups = project_file.objects_of_class PBXGroup
162
+
163
+ build_phases.each { |phase| phase["files"] -= build_file_uuids }
164
+ build_files.each { |obj| project_file.remove_object obj }
165
+ groups.each { |group| group["children"].delete file_ref }
166
+ project_file.remove_object file_ref
167
+
168
+ project_file.save
169
+ ```
170
+
171
+ ### Example: adding a source file
172
+
173
+ ```ruby
174
+ file_ref = project_file.new_object PBXFileReference, { "path" => "Example.c", "sourceTree" => "<group>", "lastKnownFileType" => "sourcecode.c.c" }
175
+ build_file = project_file.new_object PBXBuildFile, { "fileRef" => file_ref.uuid }
176
+
177
+ build_phases = project_file.objects_of_class PBXSourcesBuildPhase
178
+ build_phases.each { |phase| phase["files"] << build_file.uuid }
179
+
180
+ project_file.save
181
+ ```
182
+
183
+ ## LICENSE
184
+
185
+ MIT license.
186
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
data/lib/pbxplorer.rb ADDED
@@ -0,0 +1,266 @@
1
+ require 'json'
2
+
3
+ class String
4
+ alias to_plist to_json
5
+ end
6
+
7
+ class Array
8
+ def to_plist
9
+ items = self.map { |item| "#{item.to_plist}" }
10
+ "( #{items.join ","} )"
11
+ end
12
+ end
13
+
14
+ class Hash
15
+ def to_plist
16
+ items = self.map { |key, val| "#{key.to_plist} = #{val.to_plist};\n" }
17
+ "{ #{items.join} }"
18
+ end
19
+ end
20
+
21
+ class PBXObject < Hash
22
+ attr_accessor :project_file
23
+ attr_reader :uuid
24
+
25
+ def self.filter objs, attrs
26
+ objs.select do |obj|
27
+ attrs.select { |key, val| obj[key] == val }.length == attrs.length
28
+ end
29
+ end
30
+
31
+ def self.objects_of_class objs, attrs=nil
32
+ objs = objs.select { |obj| obj.class <= self }
33
+ objs = self.filter(objs, attrs) if attrs
34
+ objs
35
+ end
36
+
37
+ def initialize hash={}, uuid=""
38
+ 24.times { uuid += "0123456789ABCDEF"[rand(16),1] } if uuid.empty?
39
+
40
+ @project = nil
41
+ @uuid = uuid
42
+
43
+ self.merge! hash
44
+ self["isa"] ||= self.class.to_s
45
+ end
46
+
47
+ def inspect
48
+ props = self.map { |key, val| " #{key} = #{val.inspect}\n" }
49
+ "#{@uuid} = {\n#{props.join}}"
50
+ end
51
+
52
+ def help
53
+ puts "(no help available)"
54
+ end
55
+ end
56
+
57
+ class PBXFileReference < PBXObject
58
+ end
59
+
60
+ class PBXBuildFile < PBXObject
61
+ def file_ref
62
+ self.project_file.object_with_uuid self["fileRef"]
63
+ end
64
+
65
+ def help
66
+ puts "file_ref = build_file.file_ref"
67
+ PBXFileReference
68
+ end
69
+ end
70
+
71
+ class PBXBuildPhase < PBXObject
72
+ def build_files
73
+ self.project_file.objects_with_uuids self["files"]
74
+ end
75
+
76
+ def help
77
+ puts "build_file = build_phase.build_files.first"
78
+ PBXBuildFile
79
+ end
80
+ end
81
+
82
+ class PBXSourcesBuildPhase < PBXBuildPhase
83
+ end
84
+
85
+ class PBXFrameworksBuildPhase < PBXBuildPhase
86
+ end
87
+
88
+ class PBXResourcesBuildPhase < PBXBuildPhase
89
+ end
90
+
91
+ class PBXShellScriptBuildPhase < PBXBuildPhase
92
+ end
93
+
94
+ class PBXGroup < PBXObject
95
+ def children recursive=false
96
+ children = self.project_file.objects_with_uuids self["children"]
97
+
98
+ if recursive
99
+ subgroups = PBXGroup.objects_of_class children
100
+ subgroups.each { |subgroup| children << subgroup.children(true) }
101
+ end
102
+
103
+ children.flatten
104
+ end
105
+
106
+ def file_refs recursive=false
107
+ PBXFileReference.objects_of_class self.children(recursive)
108
+ end
109
+
110
+ def subgroups recursive=false
111
+ PBXGroup.objects_of_class self.children(recursive)
112
+ end
113
+
114
+ def help
115
+ puts "file_ref = group.file_refs.first\n=> " + PBXFileReference.to_s
116
+ puts "group = group.subgroups.first"
117
+ PBXGroup
118
+ end
119
+ end
120
+
121
+ class PBXNativeTarget < PBXObject
122
+ def build_phases
123
+ self.project_file.objects_with_uuids self["buildPhases"]
124
+ end
125
+
126
+ def build_configuration_list
127
+ self.project_file.object_with_uuid self["buildConfigurationList"]
128
+ end
129
+
130
+ def product_file_ref
131
+ self.project_file.object_with_uuid self["productReference"]
132
+ end
133
+
134
+ def help
135
+ puts "build_phase = PBXSourcesBuildPhase.objects_of_class(target.build_phases).first"
136
+ PBXSourcesBuildPhase
137
+ end
138
+ end
139
+
140
+ class XCBuildConfiguration < PBXObject
141
+ end
142
+
143
+ class XCConfigurationList < PBXObject
144
+ def build_configurations
145
+ self.project_file.objects_with_uuids self["buildConfigurations"]
146
+ end
147
+
148
+ def help
149
+ puts "config = list.build_configurations.first"
150
+ XCBuildConfiguration
151
+ end
152
+ end
153
+
154
+ class PBXProject < PBXObject
155
+ def targets
156
+ self.project_file.objects_with_uuids self["targets"]
157
+ end
158
+
159
+ def build_configuration_list
160
+ self.project_file.object_with_uuid self["buildConfigurationList"]
161
+ end
162
+
163
+ def main_group
164
+ self.project_file.object_with_uuid self["mainGroup"]
165
+ end
166
+
167
+ def help
168
+ puts "target = project.targets.first\n=> " + PBXNativeTarget.to_s
169
+ puts "list = project.build_configuration_list\n=> " + XCConfigurationList.to_s
170
+ puts "group = project.main_group"
171
+ PBXGroup
172
+ end
173
+ end
174
+
175
+ class XCProjectFile
176
+ def self.help
177
+ puts "project_file = XCProjectFile.new '/path/to/project.pbxproj'"
178
+ XCProjectFile
179
+ end
180
+
181
+ def initialize path
182
+ @path = path
183
+ @path += "/project.pbxproj" if File.directory? @path
184
+
185
+ @json = JSON.parse(`plutil -convert json -o - "#{@path}"`)
186
+
187
+ objs = @json["objects"]
188
+ @json["objects"] = {}
189
+
190
+ objs.each do |uuid, hash|
191
+ klass = PBXObject
192
+ begin
193
+ klass = Object.const_get hash["isa"]
194
+ rescue
195
+ end
196
+
197
+ self.add_object klass.new(hash, uuid)
198
+ end
199
+ end
200
+
201
+ def save path=nil
202
+ path ||= @path
203
+ File.open(path, "w") { |f| f.write @json.to_plist }
204
+ end
205
+
206
+ def project
207
+ self.object_with_uuid @json["rootObject"]
208
+ end
209
+
210
+ def uuids
211
+ @json["objects"].keys
212
+ end
213
+
214
+ def objects
215
+ @json["objects"].values
216
+ end
217
+
218
+ def objects_of_class klass, attrs=nil
219
+ klass.objects_of_class self.objects, attrs
220
+ end
221
+
222
+ def objects_with_uuids uuids, attrs=nil
223
+ objs = uuids.map { |uuid| self.object_with_uuid uuid }.reject { |obj| !obj }
224
+ objs = PBXObject.filter(objs, attrs) if attrs
225
+ objs
226
+ end
227
+
228
+ def object_with_uuid uuid
229
+ @json["objects"][uuid]
230
+ end
231
+
232
+ def new_object klass, attrs={}
233
+ obj = klass.new attrs
234
+ self.add_object obj
235
+ obj
236
+ end
237
+
238
+ def add_object obj
239
+ obj.project_file = self
240
+ @json["objects"][obj.uuid] = obj
241
+ end
242
+
243
+ def remove_object obj
244
+ obj.project_file = nil
245
+ @json["objects"].delete obj.uuid
246
+ end
247
+
248
+ def remove_file_ref file_ref
249
+ build_files = self.objects_of_class PBXBuildFile, { "fileRef" => file_ref.uuid }
250
+ build_file_uuids = build_files.map { |obj| obj.uuid }
251
+
252
+ build_files.each { |build_file| self.remove_object build_file }
253
+ self.objects_of_class(PBXBuildPhase).each { |phase| phase["files"] -= build_file_uuids }
254
+ self.objects_of_class(PBXGroup).each { |group| group["children"].delete file_ref }
255
+ self.remove_object file_ref
256
+ end
257
+
258
+ def help
259
+ puts "project = project_file.project"
260
+ PBXProject
261
+ end
262
+
263
+ def inspect
264
+ "{\n rootObject = #{@json['rootObject'].inspect}\n objects = < #{@json['objects'].length} objects >\n}"
265
+ end
266
+ end
data/pbxplorer.gemspec ADDED
@@ -0,0 +1,11 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "pbxplorer"
3
+ s.version = "1.0.0"
4
+ s.date = "2013-03-19"
5
+ s.summary = "Xcode project file editor"
6
+ s.description = "pbxplorer is a set of Ruby classes for parsing, editing, and saving Xcode project (.pbxproj) files. It can also be used to explore the contents of a project using the interactive Ruby shell."
7
+ s.authors = ["Mark Smith"]
8
+ s.email = "mark@camazotz.com"
9
+ s.files = Dir["{test,lib}/**/*"] + ["README.md", "Rakefile", "pbxplorer.gemspec"]
10
+ s.homepage = "http://github.com/mjmsmith/pbxplorer"
11
+ end
@@ -0,0 +1,445 @@
1
+ // !$*UTF8*$!
2
+ {
3
+ archiveVersion = 1;
4
+ classes = {
5
+ };
6
+ objectVersion = 46;
7
+ objects = {
8
+
9
+ /* Begin PBXBuildFile section */
10
+ 4D0B81911657473000DEF560 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D0B81901657473000DEF560 /* UIKit.framework */; };
11
+ 4D0B81931657473000DEF560 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D0B81921657473000DEF560 /* Foundation.framework */; };
12
+ 4D0B81951657473000DEF560 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D0B81941657473000DEF560 /* CoreGraphics.framework */; };
13
+ 4D0B819B1657473000DEF560 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4D0B81991657473000DEF560 /* InfoPlist.strings */; };
14
+ 4D0B819D1657473000DEF560 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D0B819C1657473000DEF560 /* main.m */; };
15
+ 4D0B81A11657473000DEF560 /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D0B81A01657473000DEF560 /* ExampleAppDelegate.m */; };
16
+ 4D0B81A31657473000DEF560 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D0B81A21657473000DEF560 /* Default.png */; };
17
+ 4D0B81A51657473000DEF560 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D0B81A41657473000DEF560 /* Default@2x.png */; };
18
+ 4D0B81A71657473000DEF560 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D0B81A61657473000DEF560 /* Default-568h@2x.png */; };
19
+ 4D0B81AF1657473100DEF560 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D0B81AE1657473100DEF560 /* SenTestingKit.framework */; };
20
+ 4D0B81B01657473100DEF560 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D0B81901657473000DEF560 /* UIKit.framework */; };
21
+ 4D0B81B11657473100DEF560 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D0B81921657473000DEF560 /* Foundation.framework */; };
22
+ 4D0B81B91657473100DEF560 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4D0B81B71657473100DEF560 /* InfoPlist.strings */; };
23
+ 4D0B81BC1657473100DEF560 /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D0B81BB1657473100DEF560 /* ExampleTests.m */; };
24
+ /* End PBXBuildFile section */
25
+
26
+ /* Begin PBXContainerItemProxy section */
27
+ 4D0B81B21657473100DEF560 /* PBXContainerItemProxy */ = {
28
+ isa = PBXContainerItemProxy;
29
+ containerPortal = 4D0B81831657473000DEF560 /* Project object */;
30
+ proxyType = 1;
31
+ remoteGlobalIDString = 4D0B818B1657473000DEF560;
32
+ remoteInfo = Example;
33
+ };
34
+ /* End PBXContainerItemProxy section */
35
+
36
+ /* Begin PBXFileReference section */
37
+ 4D0B818C1657473000DEF560 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
38
+ 4D0B81901657473000DEF560 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
39
+ 4D0B81921657473000DEF560 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
40
+ 4D0B81941657473000DEF560 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
41
+ 4D0B81981657473000DEF560 /* Example-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Example-Info.plist"; sourceTree = "<group>"; };
42
+ 4D0B819A1657473000DEF560 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
43
+ 4D0B819C1657473000DEF560 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
44
+ 4D0B819E1657473000DEF560 /* Example-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Example-Prefix.pch"; sourceTree = "<group>"; };
45
+ 4D0B819F1657473000DEF560 /* ExampleAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExampleAppDelegate.h; sourceTree = "<group>"; };
46
+ 4D0B81A01657473000DEF560 /* ExampleAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = "<group>"; };
47
+ 4D0B81A21657473000DEF560 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
48
+ 4D0B81A41657473000DEF560 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = "<group>"; };
49
+ 4D0B81A61657473000DEF560 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
50
+ 4D0B81AD1657473100DEF560 /* ExampleTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
51
+ 4D0B81AE1657473100DEF560 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
52
+ 4D0B81B61657473100DEF560 /* ExampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleTests-Info.plist"; sourceTree = "<group>"; };
53
+ 4D0B81B81657473100DEF560 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
54
+ 4D0B81BA1657473100DEF560 /* ExampleTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExampleTests.h; sourceTree = "<group>"; };
55
+ 4D0B81BB1657473100DEF560 /* ExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleTests.m; sourceTree = "<group>"; };
56
+ /* End PBXFileReference section */
57
+
58
+ /* Begin PBXFrameworksBuildPhase section */
59
+ 4D0B81891657473000DEF560 /* Frameworks */ = {
60
+ isa = PBXFrameworksBuildPhase;
61
+ buildActionMask = 2147483647;
62
+ files = (
63
+ 4D0B81911657473000DEF560 /* UIKit.framework in Frameworks */,
64
+ 4D0B81931657473000DEF560 /* Foundation.framework in Frameworks */,
65
+ 4D0B81951657473000DEF560 /* CoreGraphics.framework in Frameworks */,
66
+ );
67
+ runOnlyForDeploymentPostprocessing = 0;
68
+ };
69
+ 4D0B81A91657473100DEF560 /* Frameworks */ = {
70
+ isa = PBXFrameworksBuildPhase;
71
+ buildActionMask = 2147483647;
72
+ files = (
73
+ 4D0B81AF1657473100DEF560 /* SenTestingKit.framework in Frameworks */,
74
+ 4D0B81B01657473100DEF560 /* UIKit.framework in Frameworks */,
75
+ 4D0B81B11657473100DEF560 /* Foundation.framework in Frameworks */,
76
+ );
77
+ runOnlyForDeploymentPostprocessing = 0;
78
+ };
79
+ /* End PBXFrameworksBuildPhase section */
80
+
81
+ /* Begin PBXGroup section */
82
+ 4D0B81811657473000DEF560 = {
83
+ isa = PBXGroup;
84
+ children = (
85
+ 4D0B81961657473000DEF560 /* Example */,
86
+ 4D0B81B41657473100DEF560 /* ExampleTests */,
87
+ 4D0B818F1657473000DEF560 /* Frameworks */,
88
+ 4D0B818D1657473000DEF560 /* Products */,
89
+ );
90
+ sourceTree = "<group>";
91
+ };
92
+ 4D0B818D1657473000DEF560 /* Products */ = {
93
+ isa = PBXGroup;
94
+ children = (
95
+ 4D0B818C1657473000DEF560 /* Example.app */,
96
+ 4D0B81AD1657473100DEF560 /* ExampleTests.octest */,
97
+ );
98
+ name = Products;
99
+ sourceTree = "<group>";
100
+ };
101
+ 4D0B818F1657473000DEF560 /* Frameworks */ = {
102
+ isa = PBXGroup;
103
+ children = (
104
+ 4D0B81901657473000DEF560 /* UIKit.framework */,
105
+ 4D0B81921657473000DEF560 /* Foundation.framework */,
106
+ 4D0B81941657473000DEF560 /* CoreGraphics.framework */,
107
+ 4D0B81AE1657473100DEF560 /* SenTestingKit.framework */,
108
+ );
109
+ name = Frameworks;
110
+ sourceTree = "<group>";
111
+ };
112
+ 4D0B81961657473000DEF560 /* Example */ = {
113
+ isa = PBXGroup;
114
+ children = (
115
+ 4D0B819F1657473000DEF560 /* ExampleAppDelegate.h */,
116
+ 4D0B81A01657473000DEF560 /* ExampleAppDelegate.m */,
117
+ 4D0B81971657473000DEF560 /* Supporting Files */,
118
+ );
119
+ path = Example;
120
+ sourceTree = "<group>";
121
+ };
122
+ 4D0B81971657473000DEF560 /* Supporting Files */ = {
123
+ isa = PBXGroup;
124
+ children = (
125
+ 4D0B81981657473000DEF560 /* Example-Info.plist */,
126
+ 4D0B81991657473000DEF560 /* InfoPlist.strings */,
127
+ 4D0B819C1657473000DEF560 /* main.m */,
128
+ 4D0B819E1657473000DEF560 /* Example-Prefix.pch */,
129
+ 4D0B81A21657473000DEF560 /* Default.png */,
130
+ 4D0B81A41657473000DEF560 /* Default@2x.png */,
131
+ 4D0B81A61657473000DEF560 /* Default-568h@2x.png */,
132
+ );
133
+ name = "Supporting Files";
134
+ sourceTree = "<group>";
135
+ };
136
+ 4D0B81B41657473100DEF560 /* ExampleTests */ = {
137
+ isa = PBXGroup;
138
+ children = (
139
+ 4D0B81BA1657473100DEF560 /* ExampleTests.h */,
140
+ 4D0B81BB1657473100DEF560 /* ExampleTests.m */,
141
+ 4D0B81B51657473100DEF560 /* Supporting Files */,
142
+ );
143
+ path = ExampleTests;
144
+ sourceTree = "<group>";
145
+ };
146
+ 4D0B81B51657473100DEF560 /* Supporting Files */ = {
147
+ isa = PBXGroup;
148
+ children = (
149
+ 4D0B81B61657473100DEF560 /* ExampleTests-Info.plist */,
150
+ 4D0B81B71657473100DEF560 /* InfoPlist.strings */,
151
+ );
152
+ name = "Supporting Files";
153
+ sourceTree = "<group>";
154
+ };
155
+ /* End PBXGroup section */
156
+
157
+ /* Begin PBXNativeTarget section */
158
+ 4D0B818B1657473000DEF560 /* Example */ = {
159
+ isa = PBXNativeTarget;
160
+ buildConfigurationList = 4D0B81BF1657473100DEF560 /* Build configuration list for PBXNativeTarget "Example" */;
161
+ buildPhases = (
162
+ 4D0B81881657473000DEF560 /* Sources */,
163
+ 4D0B81891657473000DEF560 /* Frameworks */,
164
+ 4D0B818A1657473000DEF560 /* Resources */,
165
+ );
166
+ buildRules = (
167
+ );
168
+ dependencies = (
169
+ );
170
+ name = Example;
171
+ productName = Example;
172
+ productReference = 4D0B818C1657473000DEF560 /* Example.app */;
173
+ productType = "com.apple.product-type.application";
174
+ };
175
+ 4D0B81AC1657473100DEF560 /* ExampleTests */ = {
176
+ isa = PBXNativeTarget;
177
+ buildConfigurationList = 4D0B81C21657473100DEF560 /* Build configuration list for PBXNativeTarget "ExampleTests" */;
178
+ buildPhases = (
179
+ 4D0B81A81657473100DEF560 /* Sources */,
180
+ 4D0B81A91657473100DEF560 /* Frameworks */,
181
+ 4D0B81AA1657473100DEF560 /* Resources */,
182
+ 4D0B81AB1657473100DEF560 /* ShellScript */,
183
+ );
184
+ buildRules = (
185
+ );
186
+ dependencies = (
187
+ 4D0B81B31657473100DEF560 /* PBXTargetDependency */,
188
+ );
189
+ name = ExampleTests;
190
+ productName = ExampleTests;
191
+ productReference = 4D0B81AD1657473100DEF560 /* ExampleTests.octest */;
192
+ productType = "com.apple.product-type.bundle";
193
+ };
194
+ /* End PBXNativeTarget section */
195
+
196
+ /* Begin PBXProject section */
197
+ 4D0B81831657473000DEF560 /* Project object */ = {
198
+ isa = PBXProject;
199
+ attributes = {
200
+ CLASSPREFIX = Example;
201
+ LastUpgradeCheck = 0450;
202
+ ORGANIZATIONNAME = Example;
203
+ };
204
+ buildConfigurationList = 4D0B81861657473000DEF560 /* Build configuration list for PBXProject "Example" */;
205
+ compatibilityVersion = "Xcode 3.2";
206
+ developmentRegion = English;
207
+ hasScannedForEncodings = 0;
208
+ knownRegions = (
209
+ en,
210
+ );
211
+ mainGroup = 4D0B81811657473000DEF560;
212
+ productRefGroup = 4D0B818D1657473000DEF560 /* Products */;
213
+ projectDirPath = "";
214
+ projectRoot = "";
215
+ targets = (
216
+ 4D0B818B1657473000DEF560 /* Example */,
217
+ 4D0B81AC1657473100DEF560 /* ExampleTests */,
218
+ );
219
+ };
220
+ /* End PBXProject section */
221
+
222
+ /* Begin PBXResourcesBuildPhase section */
223
+ 4D0B818A1657473000DEF560 /* Resources */ = {
224
+ isa = PBXResourcesBuildPhase;
225
+ buildActionMask = 2147483647;
226
+ files = (
227
+ 4D0B819B1657473000DEF560 /* InfoPlist.strings in Resources */,
228
+ 4D0B81A31657473000DEF560 /* Default.png in Resources */,
229
+ 4D0B81A51657473000DEF560 /* Default@2x.png in Resources */,
230
+ 4D0B81A71657473000DEF560 /* Default-568h@2x.png in Resources */,
231
+ );
232
+ runOnlyForDeploymentPostprocessing = 0;
233
+ };
234
+ 4D0B81AA1657473100DEF560 /* Resources */ = {
235
+ isa = PBXResourcesBuildPhase;
236
+ buildActionMask = 2147483647;
237
+ files = (
238
+ 4D0B81B91657473100DEF560 /* InfoPlist.strings in Resources */,
239
+ );
240
+ runOnlyForDeploymentPostprocessing = 0;
241
+ };
242
+ /* End PBXResourcesBuildPhase section */
243
+
244
+ /* Begin PBXShellScriptBuildPhase section */
245
+ 4D0B81AB1657473100DEF560 /* ShellScript */ = {
246
+ isa = PBXShellScriptBuildPhase;
247
+ buildActionMask = 2147483647;
248
+ files = (
249
+ );
250
+ inputPaths = (
251
+ );
252
+ outputPaths = (
253
+ );
254
+ runOnlyForDeploymentPostprocessing = 0;
255
+ shellPath = /bin/sh;
256
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
257
+ };
258
+ /* End PBXShellScriptBuildPhase section */
259
+
260
+ /* Begin PBXSourcesBuildPhase section */
261
+ 4D0B81881657473000DEF560 /* Sources */ = {
262
+ isa = PBXSourcesBuildPhase;
263
+ buildActionMask = 2147483647;
264
+ files = (
265
+ 4D0B819D1657473000DEF560 /* main.m in Sources */,
266
+ 4D0B81A11657473000DEF560 /* ExampleAppDelegate.m in Sources */,
267
+ );
268
+ runOnlyForDeploymentPostprocessing = 0;
269
+ };
270
+ 4D0B81A81657473100DEF560 /* Sources */ = {
271
+ isa = PBXSourcesBuildPhase;
272
+ buildActionMask = 2147483647;
273
+ files = (
274
+ 4D0B81BC1657473100DEF560 /* ExampleTests.m in Sources */,
275
+ );
276
+ runOnlyForDeploymentPostprocessing = 0;
277
+ };
278
+ /* End PBXSourcesBuildPhase section */
279
+
280
+ /* Begin PBXTargetDependency section */
281
+ 4D0B81B31657473100DEF560 /* PBXTargetDependency */ = {
282
+ isa = PBXTargetDependency;
283
+ target = 4D0B818B1657473000DEF560 /* Example */;
284
+ targetProxy = 4D0B81B21657473100DEF560 /* PBXContainerItemProxy */;
285
+ };
286
+ /* End PBXTargetDependency section */
287
+
288
+ /* Begin PBXVariantGroup section */
289
+ 4D0B81991657473000DEF560 /* InfoPlist.strings */ = {
290
+ isa = PBXVariantGroup;
291
+ children = (
292
+ 4D0B819A1657473000DEF560 /* en */,
293
+ );
294
+ name = InfoPlist.strings;
295
+ sourceTree = "<group>";
296
+ };
297
+ 4D0B81B71657473100DEF560 /* InfoPlist.strings */ = {
298
+ isa = PBXVariantGroup;
299
+ children = (
300
+ 4D0B81B81657473100DEF560 /* en */,
301
+ );
302
+ name = InfoPlist.strings;
303
+ sourceTree = "<group>";
304
+ };
305
+ /* End PBXVariantGroup section */
306
+
307
+ /* Begin XCBuildConfiguration section */
308
+ 4D0B81BD1657473100DEF560 /* Debug */ = {
309
+ isa = XCBuildConfiguration;
310
+ buildSettings = {
311
+ ALWAYS_SEARCH_USER_PATHS = NO;
312
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
313
+ CLANG_CXX_LIBRARY = "libc++";
314
+ CLANG_ENABLE_OBJC_ARC = YES;
315
+ CLANG_WARN_EMPTY_BODY = YES;
316
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
317
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
318
+ COPY_PHASE_STRIP = NO;
319
+ GCC_C_LANGUAGE_STANDARD = gnu99;
320
+ GCC_DYNAMIC_NO_PIC = NO;
321
+ GCC_OPTIMIZATION_LEVEL = 0;
322
+ GCC_PREPROCESSOR_DEFINITIONS = (
323
+ "DEBUG=1",
324
+ "$(inherited)",
325
+ );
326
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
327
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
328
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
329
+ GCC_WARN_UNUSED_VARIABLE = YES;
330
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
331
+ ONLY_ACTIVE_ARCH = YES;
332
+ SDKROOT = iphoneos;
333
+ };
334
+ name = Debug;
335
+ };
336
+ 4D0B81BE1657473100DEF560 /* Release */ = {
337
+ isa = XCBuildConfiguration;
338
+ buildSettings = {
339
+ ALWAYS_SEARCH_USER_PATHS = NO;
340
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
341
+ CLANG_CXX_LIBRARY = "libc++";
342
+ CLANG_ENABLE_OBJC_ARC = YES;
343
+ CLANG_WARN_EMPTY_BODY = YES;
344
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
345
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
346
+ COPY_PHASE_STRIP = YES;
347
+ GCC_C_LANGUAGE_STANDARD = gnu99;
348
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
349
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
350
+ GCC_WARN_UNUSED_VARIABLE = YES;
351
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
352
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
353
+ SDKROOT = iphoneos;
354
+ VALIDATE_PRODUCT = YES;
355
+ };
356
+ name = Release;
357
+ };
358
+ 4D0B81C01657473100DEF560 /* Debug */ = {
359
+ isa = XCBuildConfiguration;
360
+ buildSettings = {
361
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
362
+ GCC_PREFIX_HEADER = "Example/Example-Prefix.pch";
363
+ INFOPLIST_FILE = "Example/Example-Info.plist";
364
+ PRODUCT_NAME = "$(TARGET_NAME)";
365
+ WRAPPER_EXTENSION = app;
366
+ };
367
+ name = Debug;
368
+ };
369
+ 4D0B81C11657473100DEF560 /* Release */ = {
370
+ isa = XCBuildConfiguration;
371
+ buildSettings = {
372
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
373
+ GCC_PREFIX_HEADER = "Example/Example-Prefix.pch";
374
+ INFOPLIST_FILE = "Example/Example-Info.plist";
375
+ PRODUCT_NAME = "$(TARGET_NAME)";
376
+ WRAPPER_EXTENSION = app;
377
+ };
378
+ name = Release;
379
+ };
380
+ 4D0B81C31657473100DEF560 /* Debug */ = {
381
+ isa = XCBuildConfiguration;
382
+ buildSettings = {
383
+ BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
384
+ FRAMEWORK_SEARCH_PATHS = (
385
+ "\"$(SDKROOT)/Developer/Library/Frameworks\"",
386
+ "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
387
+ );
388
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
389
+ GCC_PREFIX_HEADER = "Example/Example-Prefix.pch";
390
+ INFOPLIST_FILE = "ExampleTests/ExampleTests-Info.plist";
391
+ PRODUCT_NAME = "$(TARGET_NAME)";
392
+ TEST_HOST = "$(BUNDLE_LOADER)";
393
+ WRAPPER_EXTENSION = octest;
394
+ };
395
+ name = Debug;
396
+ };
397
+ 4D0B81C41657473100DEF560 /* Release */ = {
398
+ isa = XCBuildConfiguration;
399
+ buildSettings = {
400
+ BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
401
+ FRAMEWORK_SEARCH_PATHS = (
402
+ "\"$(SDKROOT)/Developer/Library/Frameworks\"",
403
+ "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
404
+ );
405
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
406
+ GCC_PREFIX_HEADER = "Example/Example-Prefix.pch";
407
+ INFOPLIST_FILE = "ExampleTests/ExampleTests-Info.plist";
408
+ PRODUCT_NAME = "$(TARGET_NAME)";
409
+ TEST_HOST = "$(BUNDLE_LOADER)";
410
+ WRAPPER_EXTENSION = octest;
411
+ };
412
+ name = Release;
413
+ };
414
+ /* End XCBuildConfiguration section */
415
+
416
+ /* Begin XCConfigurationList section */
417
+ 4D0B81861657473000DEF560 /* Build configuration list for PBXProject "Example" */ = {
418
+ isa = XCConfigurationList;
419
+ buildConfigurations = (
420
+ 4D0B81BD1657473100DEF560 /* Debug */,
421
+ 4D0B81BE1657473100DEF560 /* Release */,
422
+ );
423
+ defaultConfigurationIsVisible = 0;
424
+ defaultConfigurationName = Release;
425
+ };
426
+ 4D0B81BF1657473100DEF560 /* Build configuration list for PBXNativeTarget "Example" */ = {
427
+ isa = XCConfigurationList;
428
+ buildConfigurations = (
429
+ 4D0B81C01657473100DEF560 /* Debug */,
430
+ 4D0B81C11657473100DEF560 /* Release */,
431
+ );
432
+ defaultConfigurationIsVisible = 0;
433
+ };
434
+ 4D0B81C21657473100DEF560 /* Build configuration list for PBXNativeTarget "ExampleTests" */ = {
435
+ isa = XCConfigurationList;
436
+ buildConfigurations = (
437
+ 4D0B81C31657473100DEF560 /* Debug */,
438
+ 4D0B81C41657473100DEF560 /* Release */,
439
+ );
440
+ defaultConfigurationIsVisible = 0;
441
+ };
442
+ /* End XCConfigurationList section */
443
+ };
444
+ rootObject = 4D0B81831657473000DEF560 /* Project object */;
445
+ }
@@ -0,0 +1,132 @@
1
+ require "rubygems"
2
+ require "tempfile"
3
+ require "test/unit"
4
+ require "pbxplorer"
5
+
6
+ class XCProjectFileTest < Test::Unit::TestCase
7
+ def setup
8
+ @pf = XCProjectFile.new "test"
9
+ end
10
+
11
+ def test_read
12
+ assert_not_nil @pf.project
13
+ assert_equal @pf.uuids.length, 63
14
+ assert_equal @pf.objects.length, 63
15
+ end
16
+
17
+ def test_objects_of_class
18
+ assert_equal @pf.objects_of_class(PBXObject).length, 63
19
+ assert_equal @pf.objects_of_class(PBXBuildPhase).length, 7
20
+ assert_equal @pf.objects_of_class(PBXSourcesBuildPhase).length, 2
21
+
22
+ assert_equal @pf.objects_of_class(PBXFileReference).length, 19
23
+ objs = @pf.objects_of_class PBXFileReference, {"name" => "Foundation.framework"}
24
+ assert_equal objs.length, 1
25
+ assert_equal @pf.objects_of_class(PBXBuildFile, {"fileRef" => objs.first.uuid}).length, 2
26
+ end
27
+
28
+ def test_objects_with_uuids
29
+ fr = @pf.objects_of_class(PBXFileReference, {"name" => "Foundation.framework"}).first
30
+ objs = @pf.objects_of_class(PBXBuildFile, {"fileRef" => fr.uuid})
31
+ uuids = objs.map {|obj| obj.uuid}
32
+
33
+ assert_equal @pf.objects_with_uuids(uuids).length, 2
34
+ uuids << "garbage"
35
+ assert_equal @pf.objects_with_uuids(uuids).length, 2
36
+ end
37
+
38
+ def test_object_with_uuid
39
+ assert_not_nil @pf.object_with_uuid(@pf.project.uuid)
40
+ assert_nil @pf.object_with_uuid("garbage")
41
+ end
42
+
43
+ def test_create_remove_object
44
+ obj = @pf.add_object PBXFileReference.new
45
+ assert_equal @pf.objects.length, 64
46
+ assert_not_nil @pf.object_with_uuid(obj.uuid)
47
+
48
+ @pf.remove_object obj
49
+ assert_equal @pf.objects.length, 63
50
+ assert_nil @pf.object_with_uuid(obj.uuid)
51
+ end
52
+
53
+ def test_add_remove_object
54
+ obj = PBXFileReference.new
55
+ @pf.add_object obj
56
+ assert_equal @pf.objects.length, 64
57
+ assert_not_nil @pf.object_with_uuid(obj.uuid)
58
+
59
+ @pf.remove_object obj
60
+ assert_equal @pf.objects.length, 63
61
+ assert_nil @pf.object_with_uuid(obj.uuid)
62
+ end
63
+
64
+ def test_save
65
+ path = nil
66
+ Tempfile.open("test_save_") { |f| path = f.path }
67
+ @pf.save path
68
+ new_pf = XCProjectFile.new path
69
+
70
+ assert_not_nil new_pf
71
+ assert_equal @pf.objects.length, new_pf.objects.length
72
+ end
73
+
74
+ def test_edit_save
75
+ path = nil
76
+ Tempfile.open("test_save_") { |f| path = f.path }
77
+
78
+ obj = @pf.add_object PBXFileReference.new
79
+ @pf.save path
80
+
81
+ old_pf = XCProjectFile.new "test"
82
+ new_pf = XCProjectFile.new path
83
+
84
+ assert_not_nil new_pf
85
+ assert_equal (old_pf.objects.length + 1), new_pf.objects.length
86
+ assert_nil old_pf.object_with_uuid obj.uuid
87
+ assert_not_nil new_pf.object_with_uuid obj.uuid
88
+ end
89
+
90
+ def test_remove_file_ref
91
+ path = nil
92
+ Tempfile.open("test_save_") { |f| path = f.path }
93
+
94
+ fr = @pf.objects_of_class(PBXFileReference, {"name" => "Foundation.framework"}).first
95
+ bfs = @pf.objects_of_class(PBXBuildFile, {"fileRef" => fr.uuid})
96
+ @pf.remove_file_ref fr
97
+ @pf.save path
98
+
99
+ old_pf = XCProjectFile.new "test"
100
+ new_pf = XCProjectFile.new path
101
+
102
+ assert_not_nil new_pf
103
+ assert_equal (old_pf.objects.length - 3), new_pf.objects.length
104
+ (bfs + [fr]).each do |obj|
105
+ assert_not_nil old_pf.object_with_uuid obj.uuid
106
+ assert_nil new_pf.object_with_uuid obj.uuid
107
+ end
108
+ end
109
+ end
110
+
111
+ class PBXProjectTest < Test::Unit::TestCase
112
+ def setup
113
+ @project = XCProjectFile.new("test").project
114
+ end
115
+
116
+ def test_properties
117
+ assert_equal @project.targets.length, 2
118
+ assert_equal @project.build_configuration_list.uuid, "4D0B81861657473000DEF560"
119
+ assert_equal @project.main_group.uuid, "4D0B81811657473000DEF560"
120
+ end
121
+ end
122
+
123
+ class XCConfigurationListTest < Test::Unit::TestCase
124
+ def setup
125
+ @list = XCProjectFile.new("test").project.build_configuration_list
126
+ end
127
+
128
+ def test_properties
129
+ assert_equal @list.build_configurations.length, 2
130
+ end
131
+ end
132
+
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pbxplorer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Mark Smith
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-03-19 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: pbxplorer is a set of Ruby classes for parsing, editing, and saving Xcode project (.pbxproj) files. It can also be used to explore the contents of a project using the interactive Ruby shell.
22
+ email: mark@camazotz.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - test/project.pbxproj
31
+ - test/test_pbxplorer.rb
32
+ - lib/pbxplorer.rb
33
+ - README.md
34
+ - Rakefile
35
+ - pbxplorer.gemspec
36
+ has_rdoc: true
37
+ homepage: http://github.com/mjmsmith/pbxplorer
38
+ licenses: []
39
+
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ segments:
50
+ - 0
51
+ version: "0"
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.6
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Xcode project file editor
66
+ test_files: []
67
+