xcodeproject_swift 0.3.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +30 -0
- data/.rspec +2 -0
- data/.rubocop.yml +37 -0
- data/.travis.yml +13 -0
- data/.yardopts +7 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +192 -0
- data/Rakefile +11 -0
- data/lib/xcodeproject.rb +2 -0
- data/lib/xcodeproject/build_phase_node.rb +111 -0
- data/lib/xcodeproject/data.rb +89 -0
- data/lib/xcodeproject/exceptions.rb +29 -0
- data/lib/xcodeproject/extend/array.rb +32 -0
- data/lib/xcodeproject/extend/hash.rb +35 -0
- data/lib/xcodeproject/extend/string.rb +31 -0
- data/lib/xcodeproject/file_node.rb +86 -0
- data/lib/xcodeproject/formatter.rb +47 -0
- data/lib/xcodeproject/node.rb +42 -0
- data/lib/xcodeproject/pbx_build_file.rb +63 -0
- data/lib/xcodeproject/pbx_file_reference.rb +82 -0
- data/lib/xcodeproject/pbx_group.rb +204 -0
- data/lib/xcodeproject/pbx_native_target.rb +94 -0
- data/lib/xcodeproject/pbx_project.rb +57 -0
- data/lib/xcodeproject/project.rb +72 -0
- data/lib/xcodeproject/root_node.rb +127 -0
- data/lib/xcodeproject/tasks/build_task.rb +59 -0
- data/lib/xcodeproject/uuid_generator.rb +37 -0
- data/lib/xcodeproject/version.rb +27 -0
- data/lib/xcodeproject/xc_build_configuration.rb +98 -0
- data/lib/xcodeproject/xc_configuration_list.rb +47 -0
- data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-a.h +1 -0
- data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-a.m +1 -0
- data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-r.h +1 -0
- data/resources/example/dir1a/dir2a/dir3a/dir4a/file5a-r.m +1 -0
- data/resources/example/dir1b/dir2b/file3b.m +0 -0
- data/resources/example/dir1b/file2b.m +0 -0
- data/resources/example/dir1c/file2c.h +0 -0
- data/resources/example/dir1c/file2c.m +0 -0
- data/resources/example/example.xcodeproj/project.pbxproj +324 -0
- data/resources/example/example/AppDelegate.h +7 -0
- data/resources/example/example/AppDelegate.m +49 -0
- data/resources/example/example/en.lproj/InfoPlist.strings +2 -0
- data/resources/example/example/example-Info.plist +45 -0
- data/resources/example/example/example-Prefix.pch +14 -0
- data/resources/example/example/main.m +10 -0
- data/spec/build_phase_node_spec.rb +103 -0
- data/spec/file_node_spec.rb +58 -0
- data/spec/pbx_build_file_spec.rb +26 -0
- data/spec/pbx_file_reference_spec.rb +42 -0
- data/spec/pbx_group_spec.rb +360 -0
- data/spec/pbx_native_target_spec.rb +62 -0
- data/spec/pbx_project_spec.rb +39 -0
- data/spec/project_spec.rb +86 -0
- data/spec/spec_helper.rb +67 -0
- data/spec/support/shared_examples/file_node_shared_examples.rb +27 -0
- data/spec/xc_build_configuration_spec.rb +114 -0
- data/spec/xc_configuration_list_spec.rb +23 -0
- data/xcodeproject.gemspec +29 -0
- metadata +233 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe XcodeProject::PBXNativeTarget do
|
4
|
+
let(:obj) { @data.target('example') }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@data = prepare_example_project.read
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#sources' do
|
11
|
+
it '=> PBXSourcesBuildPhase#files' do
|
12
|
+
files = mock
|
13
|
+
mock(obj).sources_build_phase.mock!.files do files end
|
14
|
+
expect(obj.sources).to eql(files)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#add_source' do
|
19
|
+
it '=> PBXSourcesBuildPhase#add_file' do
|
20
|
+
file = mock
|
21
|
+
mock(obj).sources_build_phase.mock!.add_file(file)
|
22
|
+
obj.add_source(file)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#remove_source' do
|
27
|
+
it '=> PBXSourcesBuildPhase#remove_file' do
|
28
|
+
file = mock
|
29
|
+
mock(obj).sources_build_phase.mock!.remove_file(file)
|
30
|
+
obj.remove_source(file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#build_configurations_list' do
|
35
|
+
it 'returns the build configuration list object' do
|
36
|
+
expect(obj.build_configurations_list).to be_a(XcodeProject::XCConfigurationList)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#configs' do
|
41
|
+
it '=> XCConfigurationList#build_configurations' do
|
42
|
+
res = mock
|
43
|
+
mock(obj).build_configurations_list.mock!.build_configurations do res end
|
44
|
+
expect(obj.configs).to eql(res)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#config' do
|
49
|
+
it '=> XCConfigurationList#build_configuration' do
|
50
|
+
name = mock
|
51
|
+
res = mock
|
52
|
+
mock(obj).build_configurations_list.mock!.build_configuration(name) do res end
|
53
|
+
expect(obj.config(name)).to eql(res)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#build_phases' do
|
58
|
+
it 'returns the array of build phase objects' do
|
59
|
+
expect(obj.build_phases).to be_a(Array)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe XcodeProject::PBXProject do
|
4
|
+
let(:obj) { @data.project }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@data = prepare_example_project.read
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#targets' do
|
11
|
+
it 'returns the array of target objects' do
|
12
|
+
targets = obj.targets
|
13
|
+
expect(targets).to be_a(Array)
|
14
|
+
targets.each do |obj|
|
15
|
+
expect(obj).to be_a(XcodeProject::PBXNativeTarget)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#target' do
|
21
|
+
context 'if the target exists' do
|
22
|
+
it 'returns the object' do
|
23
|
+
expect(obj.target('example')).to be_a(XcodeProject::PBXNativeTarget)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'if the target doesn\'t exist' do
|
28
|
+
it 'returns nil' do
|
29
|
+
expect(obj.target('ghost-target')).to be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#main_group' do
|
35
|
+
it 'returns the main group object' do
|
36
|
+
expect(obj.main_group).to be_a(XcodeProject::PBXGroup)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe XcodeProject::Project do
|
4
|
+
let(:proj) { prepare_example_project }
|
5
|
+
|
6
|
+
describe '#new' do
|
7
|
+
context 'if the project file exists' do
|
8
|
+
it 'constructs an project object' do
|
9
|
+
expect(XcodeProject::Project.new(example_project_bundle_path)).to be_a(XcodeProject::Project)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'if the project file doesn\'t exist' do
|
14
|
+
let(:proj_ne) { "#{example_empty_sandbox_path}/ghost.xcodeproj" }
|
15
|
+
it 'throws the exception' do
|
16
|
+
expect { XcodeProject::Project.new(proj_ne) }.to raise_exception(XcodeProject::FilePathError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#file_path' do
|
22
|
+
it 'returns the project\'s file path' do
|
23
|
+
expect(proj.file_path).to eql(example_project_file_path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#bundle_path' do
|
28
|
+
it 'returns the project\'s bundle path' do
|
29
|
+
expect(proj.bundle_path).to eql(example_project_bundle_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#find' do
|
34
|
+
context 'if a specified directory contains project files' do
|
35
|
+
it 'returns an array of project objects' do
|
36
|
+
projs = XcodeProject::Project.find(example_project_bundle_path)
|
37
|
+
expect(projs.size).to eql(1)
|
38
|
+
expect(projs.first.bundle_path).to eql(proj.bundle_path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'if a specified directory pattern contains project files' do
|
43
|
+
it 'returns an array of project objects' do
|
44
|
+
projs = XcodeProject::Project.find("#{example_sandbox_path}/*")
|
45
|
+
expect(projs.size).to eql(1)
|
46
|
+
expect(projs.first.bundle_path).to eql(proj.bundle_path)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'if a specified directory doesn\'t contain project files' do
|
51
|
+
it 'returns an empty array' do
|
52
|
+
projs = XcodeProject::Project.find(example_empty_sandbox_path)
|
53
|
+
expect(projs.size).to eql(0)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#read' do
|
59
|
+
it 'returns the data object' do
|
60
|
+
expect(proj.read).to be_a(XcodeProject::Data)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'reads the project file' do
|
64
|
+
mock.proxy(proj).file_path
|
65
|
+
proj.read
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#write' do
|
70
|
+
it 'writes the project file' do
|
71
|
+
data = proj.read
|
72
|
+
|
73
|
+
mock.proxy(proj).file_path
|
74
|
+
proj.write(data)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#change' do
|
79
|
+
it 'reads the file file and then writes it' do
|
80
|
+
proj_mock = mock.proxy(proj)
|
81
|
+
proj_mock.read
|
82
|
+
proj_mock.write(is_a(XcodeProject::Data))
|
83
|
+
proj.change { |_data| }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper.rb"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require 'rr'
|
9
|
+
require_relative '../lib/xcodeproject/project'
|
10
|
+
require_relative '../lib/xcodeproject/exceptions'
|
11
|
+
require_relative 'support/shared_examples/file_node_shared_examples'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.run_all_when_everything_filtered = true
|
15
|
+
config.filter_run :focus
|
16
|
+
config.mock_with :rr
|
17
|
+
end
|
18
|
+
|
19
|
+
# Example project file hierarhy
|
20
|
+
#
|
21
|
+
# main
|
22
|
+
# \--group1a
|
23
|
+
# |--group2a
|
24
|
+
# |--dir2c
|
25
|
+
# | \--dir3a
|
26
|
+
# | \--dir4a
|
27
|
+
# | |--file5a-a.m
|
28
|
+
# | |--file5a-a.h
|
29
|
+
# | |--file5a-r.m
|
30
|
+
# | \--file5a-r.h
|
31
|
+
# |
|
32
|
+
# |--file2c.m
|
33
|
+
# \--file2c.h
|
34
|
+
|
35
|
+
def prepare_sandbox
|
36
|
+
` mkdir -p #{example_sandbox_path} ` unless File.exist?(example_sandbox_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def prepare_example_project
|
40
|
+
prepare_sandbox
|
41
|
+
|
42
|
+
proj_source_dir = "#{File.dirname(__FILE__)}/../resources/example"
|
43
|
+
` rm -vr #{example_project_dir} `
|
44
|
+
` cp -vr #{proj_source_dir} #{example_sandbox_path} `
|
45
|
+
|
46
|
+
XcodeProject::Project.new(example_project_bundle_path)
|
47
|
+
end
|
48
|
+
|
49
|
+
def example_sandbox_path
|
50
|
+
Pathname.new('/tmp/example_sandbox')
|
51
|
+
end
|
52
|
+
|
53
|
+
def example_empty_sandbox_path
|
54
|
+
Pathname.new('/tmp/example_sandbox_empty')
|
55
|
+
end
|
56
|
+
|
57
|
+
def example_project_dir
|
58
|
+
example_sandbox_path.join('example')
|
59
|
+
end
|
60
|
+
|
61
|
+
def example_project_bundle_path
|
62
|
+
example_project_dir.join('example.xcodeproj')
|
63
|
+
end
|
64
|
+
|
65
|
+
def example_project_file_path
|
66
|
+
example_project_bundle_path.join('project.pbxproj')
|
67
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
shared_examples 'a file node' do
|
2
|
+
describe '#parent' do
|
3
|
+
context 'if the object is nested file node' do
|
4
|
+
it 'returns the parent object' do
|
5
|
+
file_nodes_gpaths do |gpath|
|
6
|
+
expect(main_group.child(gpath).parent).to be_a(XcodeProject::PBXGroup)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#group_path' do
|
13
|
+
it 'returns the abstract path from project main group' do
|
14
|
+
expect(file_nodes_gpaths.map { |gpath|
|
15
|
+
main_group.child(gpath).group_path
|
16
|
+
}).to eql(file_nodes_gpaths.map { |gpath| Pathname.new(gpath) })
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#total_path' do
|
21
|
+
it 'returns the absolute file path' do
|
22
|
+
expect(file_nodes_gpaths.map { |gpath|
|
23
|
+
main_group.child(gpath).total_path
|
24
|
+
}).to eql(file_nodes_total_paths.map { |gpath| Pathname.new(gpath) })
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe XcodeProject::XCBuildConfiguration do
|
4
|
+
let(:obj) { @data.target('example').config('Release') }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@data = prepare_example_project.read
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#plist_path' do
|
11
|
+
it 'returns plist file path' do
|
12
|
+
expect(obj.send(:plist_path)).to eql(example_project_dir.join('example/example-Info.plist'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#version' do
|
17
|
+
context 'by default' do
|
18
|
+
it 'returns major version' do
|
19
|
+
expect(obj.version).to eql(obj.version(:major))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'if passed :major' do
|
24
|
+
it 'returns major version' do
|
25
|
+
expect(obj.version(:major)).to eql('1.0')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'if passed :minor' do
|
30
|
+
it 'returns minor version' do
|
31
|
+
expect(obj.version(:minor)).to eql('345')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'if passed :both' do
|
36
|
+
it 'returns both, major and minor versions' do
|
37
|
+
expect(obj.version(:both)).to eql('1.0.345')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#change_version' do
|
43
|
+
let(:version) { '2.0' }
|
44
|
+
|
45
|
+
context 'by default' do
|
46
|
+
it 'changes major version' do
|
47
|
+
obj.change_version(version)
|
48
|
+
expect(obj.version(:major)).to eql(version)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'if passed :major' do
|
53
|
+
it 'changes major version' do
|
54
|
+
obj.change_version(version, :major)
|
55
|
+
expect(obj.version(:major)).to eql(version)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'if passed :minor' do
|
60
|
+
it 'changes minor version' do
|
61
|
+
obj.change_version(version, :minor)
|
62
|
+
expect(obj.version(:minor)).to eql(version)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#increment_version' do
|
68
|
+
context 'by default' do
|
69
|
+
let(:next_version) { '1.1' }
|
70
|
+
|
71
|
+
it 'increments major version' do
|
72
|
+
obj.increment_version
|
73
|
+
expect(obj.version(:major)).to eql(next_version)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'if passed :major' do
|
78
|
+
let(:next_version) { '1.1' }
|
79
|
+
|
80
|
+
it 'increments major version' do
|
81
|
+
obj.increment_version(:major)
|
82
|
+
expect(obj.version(:major)).to eql(next_version)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'if passed :minor' do
|
87
|
+
let(:next_version) { '346' }
|
88
|
+
|
89
|
+
it 'increments minor version' do
|
90
|
+
obj.increment_version(:minor)
|
91
|
+
expect(obj.version(:minor)).to eql(next_version)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#read_property' do
|
97
|
+
let(:key) { 'CFBundleShortVersionString' }
|
98
|
+
let(:value) { '1.0' }
|
99
|
+
|
100
|
+
it 'read a property by key from plist file' do
|
101
|
+
expect(obj.send(:read_property, key)).to eql(value)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#write_property' do
|
106
|
+
let(:key) { 'CFBundleShortVersionString' }
|
107
|
+
let(:value) { '1.1' }
|
108
|
+
|
109
|
+
it 'write value by key to plist file' do
|
110
|
+
obj.send(:write_property, key, value)
|
111
|
+
expect(obj.send(:read_property, key)).to eql(value)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe XcodeProject::XCConfigurationList do
|
4
|
+
let(:obj) { @data.target('example').build_configurations_list }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@data = prepare_example_project.read
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#build_configuration' do
|
11
|
+
let(:name) { 'Release' }
|
12
|
+
|
13
|
+
it 'returns build configuration object' do
|
14
|
+
expect(obj.build_configuration(name)).to be_a(XcodeProject::XCBuildConfiguration)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#build_configurations' do
|
19
|
+
it 'returns an array of build configuration objects' do
|
20
|
+
expect(obj.build_configurations).to be_a(Array)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/xcodeproject/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = 'xcodeproject_swift'
|
6
|
+
gem.version = XcodeProject::VERSION
|
7
|
+
gem.summary = 'Read, write and build xcode projects'
|
8
|
+
gem.description = 'XcodeProject is the Ruby API for working with Xcode project files'
|
9
|
+
gem.author = 'Andrei Nesterov'
|
10
|
+
gem.email = 'ae.nesterov@gmail.com'
|
11
|
+
gem.homepage = 'https://github.com/manifest/xcodeproject'
|
12
|
+
gem.rubyforge_project = 'xcodeproject'
|
13
|
+
gem.license = 'MIT'
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
|
20
|
+
gem.required_ruby_version = '>= 2.0.0'
|
21
|
+
gem.add_runtime_dependency 'rake', '>= 10.0'
|
22
|
+
gem.add_runtime_dependency 'json', '~> 1.8'
|
23
|
+
gem.add_runtime_dependency 'uuid', '~> 2.3'
|
24
|
+
gem.add_runtime_dependency 'xcodebuild-rb', '~> 0.2.0'
|
25
|
+
gem.add_development_dependency 'rspec', '~> 3.4', '>= 3.4.0'
|
26
|
+
gem.add_development_dependency 'rr', '~> 1.0.4'
|
27
|
+
gem.add_development_dependency 'redcarpet', '~> 2.1.1'
|
28
|
+
gem.add_development_dependency 'yard', '~> 0.8.2'
|
29
|
+
end
|