xcodeproject_swift 0.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +30 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +37 -0
  5. data/.travis.yml +13 -0
  6. data/.yardopts +7 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +22 -0
  9. data/README.md +192 -0
  10. data/Rakefile +11 -0
  11. data/lib/xcodeproject.rb +2 -0
  12. data/lib/xcodeproject/build_phase_node.rb +111 -0
  13. data/lib/xcodeproject/data.rb +89 -0
  14. data/lib/xcodeproject/exceptions.rb +29 -0
  15. data/lib/xcodeproject/extend/array.rb +32 -0
  16. data/lib/xcodeproject/extend/hash.rb +35 -0
  17. data/lib/xcodeproject/extend/string.rb +31 -0
  18. data/lib/xcodeproject/file_node.rb +86 -0
  19. data/lib/xcodeproject/formatter.rb +47 -0
  20. data/lib/xcodeproject/node.rb +42 -0
  21. data/lib/xcodeproject/pbx_build_file.rb +63 -0
  22. data/lib/xcodeproject/pbx_file_reference.rb +82 -0
  23. data/lib/xcodeproject/pbx_group.rb +204 -0
  24. data/lib/xcodeproject/pbx_native_target.rb +94 -0
  25. data/lib/xcodeproject/pbx_project.rb +57 -0
  26. data/lib/xcodeproject/project.rb +72 -0
  27. data/lib/xcodeproject/root_node.rb +127 -0
  28. data/lib/xcodeproject/tasks/build_task.rb +59 -0
  29. data/lib/xcodeproject/uuid_generator.rb +37 -0
  30. data/lib/xcodeproject/version.rb +27 -0
  31. data/lib/xcodeproject/xc_build_configuration.rb +98 -0
  32. data/lib/xcodeproject/xc_configuration_list.rb +47 -0
  33. data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-a.h +1 -0
  34. data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-a.m +1 -0
  35. data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-r.h +1 -0
  36. data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-r.m +1 -0
  37. data/resources/example/dir1b/dir2b/file3b.m +0 -0
  38. data/resources/example/dir1b/file2b.m +0 -0
  39. data/resources/example/dir1c/file2c.h +0 -0
  40. data/resources/example/dir1c/file2c.m +0 -0
  41. data/resources/example/example.xcodeproj/project.pbxproj +324 -0
  42. data/resources/example/example/AppDelegate.h +7 -0
  43. data/resources/example/example/AppDelegate.m +49 -0
  44. data/resources/example/example/en.lproj/InfoPlist.strings +2 -0
  45. data/resources/example/example/example-Info.plist +45 -0
  46. data/resources/example/example/example-Prefix.pch +14 -0
  47. data/resources/example/example/main.m +10 -0
  48. data/spec/build_phase_node_spec.rb +103 -0
  49. data/spec/file_node_spec.rb +58 -0
  50. data/spec/pbx_build_file_spec.rb +26 -0
  51. data/spec/pbx_file_reference_spec.rb +42 -0
  52. data/spec/pbx_group_spec.rb +360 -0
  53. data/spec/pbx_native_target_spec.rb +62 -0
  54. data/spec/pbx_project_spec.rb +39 -0
  55. data/spec/project_spec.rb +86 -0
  56. data/spec/spec_helper.rb +67 -0
  57. data/spec/support/shared_examples/file_node_shared_examples.rb +27 -0
  58. data/spec/xc_build_configuration_spec.rb +114 -0
  59. data/spec/xc_configuration_list_spec.rb +23 -0
  60. data/xcodeproject.gemspec +29 -0
  61. metadata +233 -0
@@ -0,0 +1,82 @@
1
+ #--
2
+ # The MIT License
3
+ #
4
+ # Copyright (c) 2012-2014 Andrei Nesterov <ae.nesterov@gmail.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to
8
+ # deal in the Software without restriction, including without limitation the
9
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ # sell copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ # IN THE SOFTWARE.
23
+ #++
24
+
25
+ require 'xcodeproject/file_node'
26
+ require 'xcodeproject/exceptions'
27
+
28
+ module XcodeProject
29
+ class PBXFileReference < FileNode
30
+ def initialize(root, uuid, data)
31
+ super(root, uuid, data)
32
+ end
33
+
34
+ def remove!
35
+ root.build_files(uuid).each(&:remove!)
36
+
37
+ parent.remove_child_uuid(uuid)
38
+ root.remove_object(uuid)
39
+ end
40
+
41
+ def self.add(root, path)
42
+ uuid, data = root.add_object(create_object_hash(path))
43
+ new(root, uuid, data)
44
+ end
45
+
46
+ private_class_method
47
+
48
+ def self.create_object_hash(path)
49
+ path = path.to_s
50
+ name = File.basename(path)
51
+ ext = File.extname(path)
52
+ raise ParseError, "No such file type '#{name}'." unless FileTypeMap.include?(ext)
53
+
54
+ data = []
55
+ data << %w[isa PBXFileReference]
56
+ data << ['sourceTree', '<group>']
57
+ # data << ['fileEncoding', '4'] # utf-8
58
+ data << ['lastKnownFileType', FileTypeMap[ext]]
59
+ data << ['path', path]
60
+ data << ['name', name] if name != path
61
+
62
+ Hash[data]
63
+ end
64
+
65
+ FileTypeMap = {
66
+ '.h' => 'sourcecode.c.h',
67
+ '.c' => 'sourcecode.c.c',
68
+ '.m' => 'sourcecode.c.objc',
69
+ '.mm' => 'sourcecode.cpp.objcpp',
70
+ '.hpp' => 'sourcecode.cpp.h',
71
+ '.cpp' => 'sourcecode.cpp.cpp',
72
+ '.cc' => 'sourcecode.cpp.cpp',
73
+ '.swift' => 'sourcecode.swift',
74
+ '.mp3' => 'audio.mp3',
75
+ '.png' => 'image.png',
76
+ '.jpeg' => 'image.jpeg',
77
+ '.jpg' => 'image.jpeg',
78
+ '.fnt' => 'text',
79
+ '.txt' => 'text'
80
+ }.freeze
81
+ end
82
+ end
@@ -0,0 +1,204 @@
1
+ #--
2
+ # The MIT License
3
+ #
4
+ # Copyright (c) 2012-2014 Andrei Nesterov <ae.nesterov@gmail.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to
8
+ # deal in the Software without restriction, including without limitation the
9
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ # sell copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ # IN THE SOFTWARE.
23
+ #++
24
+
25
+ require 'xcodeproject/pbx_file_reference'
26
+ require 'xcodeproject/exceptions'
27
+ require 'pathname'
28
+
29
+ module XcodeProject
30
+ class PBXGroup < FileNode
31
+ def initialize(root, uuid, data)
32
+ super(root, uuid, data)
33
+ @children = data['children']
34
+ end
35
+
36
+ def children
37
+ @children.map { |uuid| root.object!(uuid) }
38
+ end
39
+
40
+ def groups
41
+ children.select { |child| child.is_a?(PBXGroup) }
42
+ end
43
+
44
+ def files
45
+ children.select { |child| child.is_a?(PBXFileReference) }
46
+ end
47
+
48
+ def child(gpath)
49
+ gpath = Pathname.new(gpath).cleanpath
50
+
51
+ if gpath == gpath.basename
52
+ name = gpath.to_s
53
+ case name
54
+ when '.'
55
+ self
56
+ when '..'
57
+ parent
58
+ else
59
+ chs = children.select { |obj| obj.name == name }
60
+ raise GroupPathError, 'The group contains two children with the same name.' if chs.size > 1
61
+ chs.first
62
+ end
63
+ else
64
+ pn, name = gpath.split
65
+ group = child(pn)
66
+ group.child(name) if group.is_a?(PBXGroup)
67
+ end
68
+ end
69
+
70
+ def file_ref(gpath)
71
+ obj = child(gpath)
72
+ obj.is_a?(PBXFileReference) ? obj : nil
73
+ end
74
+
75
+ def group?
76
+ data['path'].nil?
77
+ end
78
+
79
+ def dir?
80
+ !group?
81
+ end
82
+
83
+ def group(gpath)
84
+ obj = child(gpath)
85
+ obj.is_a?(PBXGroup) ? obj : nil
86
+ end
87
+
88
+ def add_group(gpath)
89
+ create_group(gpath)
90
+ end
91
+
92
+ def add_dir(path, gpath = nil)
93
+ path = absolute_path(path)
94
+ raise FilePathError, "No such directory '#{path}'." unless path.exist?
95
+
96
+ gpath ||= path.basename
97
+ parent = create_group(gpath, path)
98
+
99
+ chs = path.entries.select { |obj| obj.to_s.start_with?('.') ? false : true }
100
+ chs.each do |pn|
101
+ parent.absolute_path(pn).directory? ? parent.add_dir(pn) : parent.add_file(pn)
102
+ end
103
+ parent
104
+ end
105
+
106
+ def create_group(gpath, path = nil)
107
+ gpath = Pathname.new(gpath).cleanpath
108
+
109
+ if gpath == gpath.basename
110
+ name = gpath.to_s
111
+ case name
112
+ when '.'
113
+ self
114
+ when '..'
115
+ parent
116
+ else
117
+ obj = group(name)
118
+ if obj.nil?
119
+ path = relative_path(path) unless path.nil?
120
+ obj = PBXGroup.add(root, name, path)
121
+ add_child_uuid(obj.uuid)
122
+ end
123
+ obj
124
+ end
125
+ else
126
+ pn, name = gpath.split
127
+ create_group(pn).create_group(name)
128
+ end
129
+ end
130
+
131
+ def add_child_uuid(uuid)
132
+ @children << uuid
133
+ end
134
+
135
+ def remove_child_uuid(uuid)
136
+ @children.delete(uuid)
137
+ end
138
+
139
+ def absolute_path(path)
140
+ path = Pathname.new(path)
141
+ path.absolute? ? path : root.absolute_path(total_path.join(path))
142
+ end
143
+
144
+ def relative_path(path)
145
+ path = Pathname.new(path)
146
+ path.relative? ? path : path.relative_path_from(total_path)
147
+ end
148
+
149
+ def remove_file_ref(gpath)
150
+ obj = file(gpath)
151
+ obj.remove! unless obj.nil?
152
+ end
153
+
154
+ def remove_group(gpath)
155
+ obj = group(gpath)
156
+ obj.remove! unless obj.nil?
157
+ end
158
+
159
+ def remove!
160
+ return if parent.nil?
161
+
162
+ children.each(&:remove!)
163
+
164
+ parent.remove_child_uuid(uuid)
165
+ root.remove_object(uuid)
166
+ end
167
+
168
+ def add_file_ref(path)
169
+ raise FilePathError, "No such file '#{absolute_path(path)}'." unless absolute_path(path).exist?
170
+
171
+ name = File.basename(path)
172
+ obj = file_ref(name)
173
+ if obj.nil?
174
+ obj = PBXFileReference.add(root, relative_path(path))
175
+ add_child_uuid(obj.uuid)
176
+ end
177
+ obj
178
+ end
179
+
180
+ def self.add(root, name, path = nil)
181
+ uuid, data = root.add_object(create_object_hash(name, path))
182
+ PBXGroup.new(root, uuid, data)
183
+ end
184
+
185
+ alias file file_ref
186
+ alias add_file add_file_ref
187
+ alias remove_file remove_file_ref
188
+
189
+ private_class_method
190
+
191
+ def self.create_object_hash(name, path = nil)
192
+ path = path.to_s
193
+
194
+ data = []
195
+ data << %w[isa PBXGroup]
196
+ data << ['children', []]
197
+ data << ['name', name]
198
+ data << ['path', path] unless path.empty?
199
+ data << ['sourceTree', '<group>']
200
+
201
+ Hash[data]
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,94 @@
1
+ #--
2
+ # The MIT License
3
+ #
4
+ # Copyright (c) 2012-2014 Andrei Nesterov <ae.nesterov@gmail.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to
8
+ # deal in the Software without restriction, including without limitation the
9
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ # sell copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ # IN THE SOFTWARE.
23
+ #++
24
+
25
+ require 'xcodeproject/xc_configuration_list'
26
+ require 'xcodeproject/build_phase_node'
27
+
28
+ module XcodeProject
29
+ class PBXNativeTarget < Node
30
+ attr_reader :name
31
+ attr_reader :product_name
32
+ attr_reader :product_reference
33
+ attr_reader :product_type
34
+ attr_reader :dependencies
35
+
36
+ def initialize(root, uuid, data)
37
+ super(root, uuid, data)
38
+
39
+ @name = data['name']
40
+ @product_name = data['productName']
41
+ @product_reference = data['productReference']
42
+ @product_type = data['productType']
43
+ @dependencies = data['dependencies']
44
+ end
45
+
46
+ def sources
47
+ sources_build_phase.files
48
+ end
49
+
50
+ def add_source(file)
51
+ sources_build_phase.add_file(file)
52
+ end
53
+
54
+ def remove_source(file)
55
+ sources_build_phase.remove_file(file)
56
+ end
57
+
58
+ def configs
59
+ build_configurations_list.build_configurations
60
+ end
61
+
62
+ def config(name)
63
+ build_configurations_list.build_configuration(name)
64
+ end
65
+
66
+ def build_configurations_list
67
+ root.object!(data['buildConfigurationList'])
68
+ end
69
+
70
+ def build_phases
71
+ data['buildPhases'].map { |uuid| root.object!(uuid) }
72
+ end
73
+
74
+ def sources_build_phase
75
+ build_phases.select { |obj| obj.is_a?(PBXSourcesBuildPhase) }.first
76
+ end
77
+
78
+ def headers_build_phase
79
+ build_phases.select { |obj| obj.is_a?(PBXHeadersBuildPhase) }.first
80
+ end
81
+
82
+ def resources_build_phase
83
+ build_phases.select { |obj| obj.is_a?(PBXResourcesBuildPhase) }.first
84
+ end
85
+
86
+ def frameworks_build_phase
87
+ build_phases.select { |obj| obj.is_a?(PBXFrameworksBuildPhase) }.first
88
+ end
89
+
90
+ def doctor
91
+ build_phases.each(&:doctor)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,57 @@
1
+ #--
2
+ # The MIT License
3
+ #
4
+ # Copyright (c) 2012-2014 Andrei Nesterov <ae.nesterov@gmail.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to
8
+ # deal in the Software without restriction, including without limitation the
9
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ # sell copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ # IN THE SOFTWARE.
23
+ #++
24
+
25
+ require 'xcodeproject/node'
26
+
27
+ module XcodeProject
28
+ class PBXProject < Node
29
+ attr_reader :main_group
30
+ attr_reader :product_ref_group
31
+ attr_reader :project_dir_path
32
+ attr_reader :compatibility_version
33
+ attr_reader :development_region
34
+ attr_reader :know_regions
35
+ attr_reader :attributes
36
+
37
+ def initialize(root, uuid, data)
38
+ super(root, uuid, data)
39
+
40
+ @main_group = root.object!(data['mainGroup'])
41
+ @product_ref_group = root.object!(data['productRefGroup'])
42
+ @project_dir_path = data['projectDirPath']
43
+ @compatibility_version = data['compatibilityVersion']
44
+ @development_region = data['developmentRegion']
45
+ @know_regions = data['knownRegions']
46
+ @attributes = data['attributes']
47
+ end
48
+
49
+ def targets
50
+ data['targets'].map { |uuid| root.object!(uuid) }
51
+ end
52
+
53
+ def target(name)
54
+ root.find_object('PBXNativeTarget', 'name' => name)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,72 @@
1
+ #--
2
+ # The MIT License
3
+ #
4
+ # Copyright (c) 2012-2014 Andrei Nesterov <ae.nesterov@gmail.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to
8
+ # deal in the Software without restriction, including without limitation the
9
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ # sell copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ # IN THE SOFTWARE.
23
+ #++
24
+
25
+ require 'xcodeproject/tasks/build_task'
26
+ require 'xcodeproject/data'
27
+ require 'pathname'
28
+ require 'find'
29
+
30
+ module XcodeProject
31
+ class Project
32
+ attr_reader :bundle_path
33
+ attr_reader :file_path
34
+ attr_reader :name
35
+
36
+ def self.find(pattern = nil)
37
+ pattern = Pathname.new(pattern.to_s)
38
+ pattern = pattern.join('*.xcodeproj') if pattern.extname != '.xcodeproj'
39
+
40
+ Dir[pattern].map { |path| new(path) }
41
+ end
42
+
43
+ def initialize(path)
44
+ path = Pathname.new(path)
45
+ raise FilePathError, "No such project file '#{path}'." unless path.exist?
46
+
47
+ @bundle_path = path
48
+ @file_path = bundle_path.join('project.pbxproj')
49
+ @name = bundle_path.basename('.*').to_s
50
+ end
51
+
52
+ def change
53
+ data = read
54
+ yield data
55
+ write data
56
+ end
57
+
58
+ def read
59
+ Data.new(JSON.parse(`plutil -convert json -o - "#{file_path}"`), bundle_path.dirname)
60
+ end
61
+
62
+ def write(data)
63
+ File.open(file_path, 'w') do |file|
64
+ file.write(data.to_plist)
65
+ end
66
+ end
67
+
68
+ def doctor
69
+ change(&:doctor)
70
+ end
71
+ end
72
+ end