xcoder 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -48,7 +48,7 @@ module Xcode
48
48
  # identifier; false if it is not.
49
49
  #
50
50
  def self.is_identifier? value
51
- value =~ /^[0-9A-F]{24,}$/
51
+ value =~ /^[0-9a-fA-F]{24,}$/
52
52
  end
53
53
 
54
54
  #
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, :launch, :test
10
- def initialize(path)
11
- @path = File.expand_path(path)
12
- @root = File.expand_path "#{@path}/../../../../"
13
- @name = File.basename(path).gsub(/\.xcscheme$/,'')
14
- doc = Nokogiri::XML(open(@path))
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
- # def project
21
- # launch.target.project
22
- # end
23
-
24
- def builder
25
- Xcode::Builder.new(self)
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 projet/workspace at the path defined for schemes.
39
+ # within the project/workspace at the path defined for schemes.
36
40
  #
37
- def self.find_in_path(path)
38
- shared_schemes = Dir["#{path}/xcshareddata/xcschemes/*.xcscheme"]
39
- user_specific_schemes = Dir["#{path}/xcuserdata/#{ENV['USER']}.xcuserdatad/xcschemes/*.xcscheme"]
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
- private
47
-
48
- def parse_action(doc, action_name)
49
- action = doc.xpath("//#{action_name.capitalize}Action").first
50
- buildableReference = action.xpath('BuildableProductRunnable/BuildableReference').first
51
- return nil if buildableReference.nil?
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
- project.target(target_name).config(action['buildConfiguration'])
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?(Array) ? bits.join(' ') : bits
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
@@ -1,3 +1,3 @@
1
1
  module Xcode
2
- VERSION = "0.1.13"
2
+ VERSION = "0.1.14"
3
3
  end
@@ -27,7 +27,8 @@ module Xcode
27
27
  #
28
28
  def schemes
29
29
  return @schemes unless @schemes.nil?
30
- @schemes = Xcode::Scheme.find_in_path @path
30
+ @schemes = Xcode::Scheme.find_in_workspace(self)
31
+ @schemes
31
32
  end
32
33
 
33
34
  #
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
- [ "xcodebuild",
15
- "-sdk #{configuration.target.project.sdk}",
16
- "-project \"#{configuration.target.project.path}\"",
17
- "-target \"#{configuration.target.name}\"",
18
- "-configuration \"#{configuration.name}\"",
19
- "OBJROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
20
- "SYMROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"" ]
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
- expected = default_build_parameters
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
- [ "xcodebuild",
74
- "-sdk iphonesimulator",
75
- "-project \"#{configuration.target.project.path}\"",
76
- "-target \"#{configuration.target.name}\"",
77
- "-configuration \"#{configuration.name}\"",
78
- "OBJROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
79
- "SYMROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
80
- "TEST_AFTER_BUILD=YES"
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
- [ "xcodebuild",
86
- "-sdk macosx10.7",
87
- "-project \"#{configuration.target.project.path}\"",
88
- "-target \"#{configuration.target.name}\"",
89
- "-configuration \"#{configuration.name}\"",
90
- "OBJROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
91
- "SYMROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
92
- "TEST_AFTER_BUILD=YES",
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
- expected = macosx_test_parameters
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
- [ "xcodebuild",
129
- "-project \"#{configuration.target.project.path}\"",
130
- "-sdk iphoneos",
131
- "-target \"#{configuration.target.name}\"",
132
- "-configuration \"#{configuration.name}\"",
133
- "OBJROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
134
- "SYMROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
135
- "clean" ]
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
- [ "xcodebuild",
158
- "-sdk iphoneos",
159
- "-project \"#{scheme.launch.target.project.path}\"",
160
- "-scheme \"#{scheme.name}\"",
161
- "OBJROOT=\"#{File.dirname(scheme.launch.target.project.path)}/build/\"",
162
- "SYMROOT=\"#{File.dirname(scheme.launch.target.project.path)}/build/\"" ]
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
- [ "xcodebuild",
176
- "-project \"#{scheme.launch.target.project.path}\"",
177
- "-sdk iphoneos",
178
- "-scheme \"#{scheme.name}\"",
179
- "OBJROOT=\"#{File.dirname(scheme.launch.target.project.path)}/build/\"",
180
- "SYMROOT=\"#{File.dirname(scheme.launch.target.project.path)}/build/\"",
181
- "clean" ]
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