xcoder 0.1.13 → 0.1.14
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.
- data/README.md +37 -33
- data/lib/xcode/builder.rb +3 -234
- data/lib/xcode/builder/base_builder.rb +204 -0
- data/lib/xcode/builder/project_target_config_builder.rb +14 -0
- data/lib/xcode/builder/scheme_builder.rb +32 -0
- data/lib/xcode/configuration.rb +1 -1
- data/lib/xcode/keychain.rb +14 -21
- data/lib/xcode/project.rb +109 -109
- data/lib/xcode/registry.rb +1 -1
- data/lib/xcode/scheme.rb +82 -35
- data/lib/xcode/shell.rb +3 -1
- data/lib/xcode/shell/command.rb +42 -0
- data/lib/xcode/version.rb +1 -1
- data/lib/xcode/workspace.rb +2 -1
- data/spec/builder_spec.rb +68 -62
- data/spec/registry_spec.rb +51 -0
- data/spec/scheme_spec.rb +5 -5
- data/spec/xcode_spec.rb +1 -0
- metadata +18 -12
data/lib/xcode/registry.rb
CHANGED
data/lib/xcode/scheme.rb
CHANGED
@@ -1,60 +1,107 @@
|
|
1
1
|
require 'nokogiri'
|
2
2
|
|
3
3
|
module Xcode
|
4
|
-
|
4
|
+
|
5
5
|
# Schemes are an XML file that describe build, test, launch and profile actions
|
6
6
|
# For the purposes of Xcoder, we want to be able to build and test
|
7
|
-
# The scheme's build action only describes a target, so we need to look at launch for the config
|
8
7
|
class Scheme
|
9
|
-
attr_reader :path, :name, :
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@launch = parse_action(doc, 'launch')
|
17
|
-
@test = parse_action(doc, 'test')
|
8
|
+
attr_reader :parent, :path, :name, :build_config, :build_targets
|
9
|
+
|
10
|
+
#
|
11
|
+
# Parse all the schemes given the current project.
|
12
|
+
#
|
13
|
+
def self.find_in_project(project)
|
14
|
+
find_in_path(project, project.path)
|
18
15
|
end
|
19
|
-
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
|
17
|
+
#
|
18
|
+
# Parse all the schemes given the current workspace.
|
19
|
+
#
|
20
|
+
def self.find_in_workspace(workspace)
|
21
|
+
schemes = find_in_path(workspace, workspace.path)
|
22
|
+
|
23
|
+
# Project level schemes
|
24
|
+
workspace.projects.each do |project|
|
25
|
+
schemes+=project.schemes
|
26
|
+
end
|
27
|
+
|
28
|
+
schemes
|
26
29
|
end
|
27
30
|
|
28
|
-
#
|
29
|
-
# Parse all the scheme files that can be found in the given project or workspace. Schemes
|
31
|
+
# Parse all the scheme files that can be found at the given path. Schemes
|
30
32
|
# can be defined as `shared` schemes and then `user` specific schemes. Parsing
|
31
33
|
# the schemes will load the shared ones and then the current acting user's
|
32
34
|
# schemes.
|
35
|
+
#
|
33
36
|
#
|
37
|
+
# @param project or workspace in which the scheme is contained
|
34
38
|
# @return [Array<Scheme>] the shared schemes and user specific schemes found
|
35
|
-
# within the
|
39
|
+
# within the project/workspace at the path defined for schemes.
|
36
40
|
#
|
37
|
-
def self.find_in_path(path)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
(shared_schemes + user_specific_schemes).map do |scheme|
|
42
|
-
Xcode::Scheme.new(scheme)
|
41
|
+
def self.find_in_path(parent, path)
|
42
|
+
all_schemes_paths(path).map do |scheme_path|
|
43
|
+
Xcode::Scheme.new(parent: parent, root: path, path: scheme_path)
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
def initialize(params={})
|
48
|
+
@parent = params[:parent]
|
49
|
+
@path = File.expand_path params[:path]
|
50
|
+
@root = File.expand_path(File.join(params[:root],'..'))
|
51
|
+
@name = File.basename(path).gsub(/\.xcscheme$/,'')
|
52
|
+
doc = Nokogiri::XML(open(@path))
|
52
53
|
|
54
|
+
parse_build_actions(doc)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns a builder for building this scheme
|
58
|
+
def builder
|
59
|
+
Xcode::Builder::SchemeBuilder.new(self)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
#
|
65
|
+
# @return an array of all the scheme filepaths found within the project
|
66
|
+
# or workspace path provided.
|
67
|
+
#
|
68
|
+
def self.all_schemes_paths(path)
|
69
|
+
shared_schemes_paths(path) + current_user_schemes_paths(path)
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# @return an array of all the shared scheme filespaths found within the
|
74
|
+
# project or workspace path provided.
|
75
|
+
#
|
76
|
+
def self.shared_schemes_paths(root)
|
77
|
+
Dir["#{root}/xcshareddata/xcschemes/*.xcscheme"]
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# @return an array of all the current user's scheme filespaths found within the
|
82
|
+
# project or workspace path provided.
|
83
|
+
#
|
84
|
+
def self.current_user_schemes_paths(root)
|
85
|
+
Dir["#{root}/xcuserdata/#{ENV['USER']}.xcuserdatad/xcschemes/*.xcscheme"]
|
86
|
+
end
|
87
|
+
|
88
|
+
def target_from_build_reference(buildableReference)
|
53
89
|
project_name = buildableReference['ReferencedContainer'].gsub(/^container:/,'')
|
54
|
-
project = Xcode.project "#{@root}/#{project_name}"
|
55
90
|
target_name = buildableReference['BlueprintName']
|
91
|
+
project_path = File.join @root, project_name
|
92
|
+
project = Xcode.project project_path
|
93
|
+
project.target(target_name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_build_actions(doc)
|
97
|
+
# Build Config
|
98
|
+
@build_targets = []
|
56
99
|
|
57
|
-
|
100
|
+
@build_config = doc.xpath("//LaunchAction").first['buildConfiguration']
|
101
|
+
|
102
|
+
build_action_entries = doc.xpath("//BuildAction//BuildableReference").each do |ref|
|
103
|
+
@build_targets << target_from_build_reference(ref)
|
104
|
+
end
|
58
105
|
end
|
59
106
|
|
60
107
|
end
|
data/lib/xcode/shell.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'xcode/shell/command.rb'
|
2
|
+
|
1
3
|
module Xcode
|
2
4
|
module Shell
|
3
5
|
|
@@ -5,7 +7,7 @@ module Xcode
|
|
5
7
|
|
6
8
|
def self.execute(bits, show_output=true)
|
7
9
|
out = []
|
8
|
-
cmd = bits.is_a?(
|
10
|
+
cmd = bits.is_a?(Xcode::Shell::Command) ? bits.to_s : bits
|
9
11
|
|
10
12
|
puts "EXECUTE: #{cmd}"
|
11
13
|
IO.popen (cmd) do |f|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Xcode
|
4
|
+
module Shell
|
5
|
+
class Command
|
6
|
+
attr_accessor :env
|
7
|
+
|
8
|
+
def initialize(cmd, environment={})
|
9
|
+
@cmd = cmd
|
10
|
+
@args = []
|
11
|
+
@env = environment
|
12
|
+
end
|
13
|
+
|
14
|
+
def <<(arg)
|
15
|
+
@args << arg
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{to_a.join(' ')}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_a
|
23
|
+
out = []
|
24
|
+
out << @cmd
|
25
|
+
out+=@args
|
26
|
+
out+=(@env.map {|k,v| "#{k}=#{v}"})
|
27
|
+
out
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(obj)
|
31
|
+
return false unless obj.is_a? Xcode::Shell::Command
|
32
|
+
# to_s==obj.to_s
|
33
|
+
Set.new(obj.to_a) == Set.new(self.to_a)
|
34
|
+
end
|
35
|
+
|
36
|
+
def execute(show_output=true, &block) #:yield: output
|
37
|
+
Xcode::Shell.execute(self, show_output, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/xcode/version.rb
CHANGED
data/lib/xcode/workspace.rb
CHANGED
data/spec/builder_spec.rb
CHANGED
@@ -10,25 +10,35 @@ describe Xcode::Builder do
|
|
10
10
|
|
11
11
|
describe "#build" do
|
12
12
|
|
13
|
-
let(:default_build_parameters) do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
let(:default_build_parameters) do
|
14
|
+
cmd = Xcode::Shell::Command.new "xcodebuild"
|
15
|
+
cmd << "-project \"#{configuration.target.project.path}\""
|
16
|
+
cmd << "-target \"#{configuration.target.name}\""
|
17
|
+
cmd << "-config \"#{configuration.name}\""
|
18
|
+
cmd << "-sdk #{configuration.target.project.sdk}"
|
19
|
+
cmd.env["OBJROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
20
|
+
cmd.env["SYMROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
21
|
+
cmd
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:macosx_build_parameters) do
|
25
|
+
cmd = Xcode::Shell::Command.new "xcodebuild"
|
26
|
+
cmd << "-project \"#{configuration.target.project.path}\""
|
27
|
+
cmd << "-target \"#{configuration.target.name}\""
|
28
|
+
cmd << "-config \"#{configuration.name}\""
|
29
|
+
cmd << "-sdk macosx10.7"
|
30
|
+
cmd.env["OBJROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
31
|
+
cmd.env["SYMROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
32
|
+
cmd
|
21
33
|
end
|
22
34
|
|
23
35
|
it "should build the project with the default parameters" do
|
24
|
-
Xcode::Shell.should_receive(:execute).with(default_build_parameters)
|
36
|
+
Xcode::Shell.should_receive(:execute).with(default_build_parameters,true)
|
25
37
|
subject.build
|
26
38
|
end
|
27
39
|
|
28
40
|
it "should allow the override of the sdk" do
|
29
|
-
|
30
|
-
expected[1] = '-sdk macosx10.7'
|
31
|
-
Xcode::Shell.should_receive(:execute).with(expected)
|
41
|
+
Xcode::Shell.should_receive(:execute).with(macosx_build_parameters, true)
|
32
42
|
subject.build :sdk => 'macosx10.7'
|
33
43
|
end
|
34
44
|
|
@@ -70,27 +80,27 @@ describe Xcode::Builder do
|
|
70
80
|
end
|
71
81
|
|
72
82
|
let(:iphonesimulator_test_parameters) do
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
cmd = Xcode::Shell::Command.new "xcodebuild"
|
84
|
+
cmd << "-project \"#{configuration.target.project.path}\""
|
85
|
+
cmd << "-target \"#{configuration.target.name}\""
|
86
|
+
cmd << "-config \"#{configuration.name}\""
|
87
|
+
cmd << "-sdk iphonesimulator"
|
88
|
+
cmd.env["OBJROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
89
|
+
cmd.env["SYMROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
90
|
+
cmd.env["TEST_AFTER_BUILD"]="YES"
|
91
|
+
cmd
|
82
92
|
end
|
83
93
|
|
84
94
|
let(:macosx_test_parameters) do
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
95
|
+
cmd = Xcode::Shell::Command.new "xcodebuild"
|
96
|
+
cmd << "-project \"#{configuration.target.project.path}\""
|
97
|
+
cmd << "-target \"#{configuration.target.name}\""
|
98
|
+
cmd << "-config \"#{configuration.name}\""
|
99
|
+
cmd << "-sdk macosx10.7"
|
100
|
+
cmd.env["OBJROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
101
|
+
cmd.env["SYMROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
102
|
+
cmd.env["TEST_AFTER_BUILD"]="YES"
|
103
|
+
cmd
|
94
104
|
end
|
95
105
|
|
96
106
|
|
@@ -99,15 +109,8 @@ describe Xcode::Builder do
|
|
99
109
|
subject.test :sdk => 'iphonesimulator'
|
100
110
|
end
|
101
111
|
|
102
|
-
it "should be able to run the test target on macosx10.7" do
|
103
|
-
Xcode::Shell.should_receive(:execute).with(macosx_test_parameters, false)
|
104
|
-
subject.test :sdk => 'macosx10.7'
|
105
|
-
end
|
106
|
-
|
107
112
|
it "should allow the override of the sdk" do
|
108
|
-
|
109
|
-
expected[1] = '-sdk macosx10.7'
|
110
|
-
Xcode::Shell.should_receive(:execute).with(expected, false)
|
113
|
+
Xcode::Shell.should_receive(:execute).with(macosx_test_parameters, false)
|
111
114
|
subject.test :sdk => 'macosx10.7'
|
112
115
|
end
|
113
116
|
|
@@ -125,19 +128,20 @@ describe Xcode::Builder do
|
|
125
128
|
describe "#clean" do
|
126
129
|
|
127
130
|
let(:default_clean_parameters) do
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
131
|
+
cmd = Xcode::Shell::Command.new "xcodebuild"
|
132
|
+
cmd << "-project \"#{configuration.target.project.path}\""
|
133
|
+
cmd << "-target \"#{configuration.target.name}\""
|
134
|
+
cmd << "-config \"#{configuration.name}\""
|
135
|
+
cmd << "-sdk iphoneos"
|
136
|
+
cmd << "clean"
|
137
|
+
cmd.env["OBJROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
138
|
+
cmd.env["SYMROOT"]="\"#{File.dirname(configuration.target.project.path)}/build/\""
|
139
|
+
cmd
|
136
140
|
end
|
137
141
|
|
138
142
|
|
139
143
|
it "should clean the project with the default parameter" do
|
140
|
-
Xcode::Shell.should_receive(:execute).with(default_clean_parameters)
|
144
|
+
Xcode::Shell.should_receive(:execute).with(default_clean_parameters, true)
|
141
145
|
subject.clean
|
142
146
|
end
|
143
147
|
|
@@ -154,16 +158,17 @@ describe Xcode::Builder do
|
|
154
158
|
describe "#build" do
|
155
159
|
|
156
160
|
let(:default_build_parameters) do
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
161
|
+
cmd = Xcode::Shell::Command.new "xcodebuild"
|
162
|
+
cmd << "-project \"#{scheme.build_targets.last.project.path}\""
|
163
|
+
cmd << "-scheme \"#{scheme.name}\""
|
164
|
+
cmd << "-sdk iphoneos"
|
165
|
+
cmd.env["OBJROOT"]="\"#{File.dirname(scheme.build_targets.last.project.path)}/build/\""
|
166
|
+
cmd.env["SYMROOT"]="\"#{File.dirname(scheme.build_targets.last.project.path)}/build/\""
|
167
|
+
cmd
|
163
168
|
end
|
164
169
|
|
165
170
|
it "should build the project with the default parameters" do
|
166
|
-
Xcode::Shell.should_receive(:execute).with(default_build_parameters)
|
171
|
+
Xcode::Shell.should_receive(:execute).with(default_build_parameters, true)
|
167
172
|
subject.build
|
168
173
|
end
|
169
174
|
|
@@ -172,18 +177,19 @@ describe Xcode::Builder do
|
|
172
177
|
describe "#clean" do
|
173
178
|
|
174
179
|
let(:default_clean_parameters) do
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
180
|
+
cmd = Xcode::Shell::Command.new "xcodebuild"
|
181
|
+
cmd << "-project \"#{scheme.build_targets.last.project.path}\""
|
182
|
+
cmd << "-scheme \"#{scheme.name}\""
|
183
|
+
cmd << "-sdk iphoneos"
|
184
|
+
cmd << "clean"
|
185
|
+
cmd.env["OBJROOT"]="\"#{File.dirname(scheme.build_targets.last.project.path)}/build/\""
|
186
|
+
cmd.env["SYMROOT"]="\"#{File.dirname(scheme.build_targets.last.project.path)}/build/\""
|
187
|
+
cmd
|
182
188
|
end
|
183
189
|
|
184
190
|
|
185
191
|
it "should clean the project with the default parameter" do
|
186
|
-
Xcode::Shell.should_receive(:execute).with(default_clean_parameters)
|
192
|
+
Xcode::Shell.should_receive(:execute).with(default_clean_parameters, true)
|
187
193
|
subject.clean
|
188
194
|
end
|
189
195
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Xcode::Registry do
|
4
|
+
|
5
|
+
def self.is_identifier? value
|
6
|
+
value =~ /^[0-9A-F]{24,}$/
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "ClassMethods" do
|
10
|
+
subject { described_class }
|
11
|
+
|
12
|
+
describe "#is_identifier?" do
|
13
|
+
context "when the value is valid hexadecimal 24 character length string" do
|
14
|
+
context "when it is all uppercase" do
|
15
|
+
let(:input) { "0123456789ABCDEF01234567" }
|
16
|
+
|
17
|
+
it "should be an identifier" do
|
18
|
+
subject.is_identifier?(input).should be_true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when it uses lowercase characters" do
|
23
|
+
let(:input) { "0123456789abcdef01234567" }
|
24
|
+
|
25
|
+
it "should be an identifier" do
|
26
|
+
subject.is_identifier?(input).should be_true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the value is less than 24 characters" do
|
32
|
+
let(:input) { "0123456789ABCDEF" }
|
33
|
+
|
34
|
+
it "should not be an identifier" do
|
35
|
+
subject.is_identifier?(input).should be_false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when it contains other than hexadecimal characters" do
|
40
|
+
let(:input) { "0123456789ABCDEFGHIJKLMNO" }
|
41
|
+
|
42
|
+
it "should not be an identifier" do
|
43
|
+
subject.is_identifier?(input).should be_false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|