xcoder 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -12,13 +12,17 @@ and then require the gem in your project/rakefile/etc
12
12
 
13
13
  require 'xcoder'
14
14
 
15
+ ### Load a project
16
+
17
+ project = Xcode.project('MyProject') # Can be the name, the file (e.g. MyProject.xcodeproj) or the path
18
+
15
19
  ### Finding all projects from the current directory down
16
20
 
17
21
  Xcode.find_projects.each {|p| puts p.name }
18
22
 
19
23
  ### Find a configuration for a target on a project
20
24
 
21
- project = Xcode.project(:MyProject).target(:Target).config(:Debug)
25
+ config = Xcode.project(:MyProject).target(:Target).config(:Debug) # returns an Xcode::Configuration object
22
26
 
23
27
  ### Building a configuration
24
28
 
@@ -38,4 +42,25 @@ This will produce a .ipa and a .dSYM.zip
38
42
  config.info_plist do |info|
39
43
  info.version = info.version.to_i + 1
40
44
  info.save
41
- end
45
+ end
46
+
47
+ ### Working with workspaces
48
+
49
+ Loading workspaces can be done in a similar way to projects:
50
+
51
+ Xcode.workspaces.each do |w|
52
+ w.describe # prints a recursive description of the structure of the workspace and its projects
53
+ end
54
+
55
+ Or, if you know the name:
56
+
57
+ workspace = Xcode.workspace('MyWorkspace') # Can be the name, the file (e.g. MyWorkspace.xcworkspace) or the path
58
+
59
+
60
+ ### Schemes
61
+
62
+ There is basic support for schemes, you can access them from a project like so:
63
+
64
+ config = project.scheme('MyScheme').launch # Gets the Launch action for specified scheme. Can also specify 'test' to get the test action
65
+
66
+ The 'launch' and 'test' methods access the different actions within the scheme, and they map to a Xcode::Configuration object (i.e., the schemes map to a target and configuration in a traditional XCode3 project style).
data/lib/xcode/builder.rb CHANGED
@@ -33,6 +33,7 @@ module Xcode
33
33
  cmd << "-project \"#{@target.project.path}\""
34
34
  cmd << "-target \"#{@target.name}\""
35
35
  cmd << "-configuration \"#{@config.name}\""
36
+ cmd << "CODE_SIGN_IDENTITY=\"#{@identity}\""
36
37
  Xcode::Shell.execute(cmd)
37
38
  end
38
39
 
@@ -23,7 +23,7 @@ module Xcode
23
23
  value
24
24
  end
25
25
  end
26
-
26
+
27
27
  def info_plist_location
28
28
  @json['buildSettings']['INFOPLIST_FILE']
29
29
  end
@@ -0,0 +1,29 @@
1
+ module Xcode
2
+ class Keychain
3
+ def initialize(path)
4
+ @path = File.expand_path path
5
+ end
6
+
7
+ def import(cert, password)
8
+ cmd = []
9
+ cmd << "security"
10
+ cmd << "import '#{cert}'"
11
+ cmd << "-k #{@path}"
12
+ cmd << "-P #{password}"
13
+ cmd << "-T /usr/bin/codesign"
14
+ Xcode::Shell.execute(cmd)
15
+ end
16
+
17
+ def unlock(password)
18
+ cmd = []
19
+ cmd << "security"
20
+ cmd << "unlock-keychain #{@path}"
21
+ cmd << "-p #{password}"
22
+ Xcode::Shell.execute(cmd)
23
+ end
24
+
25
+ def self.login_keychain
26
+ Xcode::Keychain.new("~/Library/Keychains/login.keychain")
27
+ end
28
+ end
29
+ end
data/lib/xcode/project.rb CHANGED
@@ -1,29 +1,54 @@
1
1
  require 'json'
2
2
  require 'xcode/target'
3
3
  require 'xcode/configuration'
4
+ require 'xcode/scheme'
4
5
 
5
6
  module Xcode
6
7
  class Project
7
- attr_reader :name, :targets, :sdk, :path
8
+ attr_reader :name, :targets, :sdk, :path, :schemes
8
9
  def initialize(path, sdk=nil)
9
10
  @sdk = sdk || "iphoneos" # FIXME: should support OSX/simulator too
10
11
  @path = File.expand_path path
11
- @targets = {}
12
+ @targets = []
13
+ @schemes = []
12
14
  @name = File.basename(@path).gsub(/\.xcodeproj/,'')
13
15
 
14
16
  parse_pbxproj
17
+ parse_schemes
15
18
  # parse_configurations
16
19
  end
17
-
20
+
18
21
  def target(name)
19
- target = @targets[name.to_s.to_sym]
20
- raise "No such target #{name}, available targets are #{@targets.keys}" if target.nil?
22
+ target = @targets.select {|t| t.name == name.to_s}.first
23
+ raise "No such target #{name}, available targets are #{@targets.map {|t| t.name}.join(', ')}" if target.nil?
21
24
  yield target if block_given?
22
25
  target
23
26
  end
24
27
 
28
+ def describe
29
+ puts "Project #{name} contains"
30
+ targets.each do |t|
31
+ puts " + target:#{t.name}"
32
+ t.configs.each do |c|
33
+ puts " + config:#{c.name}"
34
+ end
35
+ end
36
+ schemes.each do |s|
37
+ puts " + scheme #{s.name}"
38
+ puts " + Launch action => target:#{s.launch.target.name}, config:#{s.launch.name}" unless s.launch.nil?
39
+ puts " + Test action => target:#{s.test.target.name}, config:#{s.test.name}" unless s.test.nil?
40
+ end
41
+ end
42
+
25
43
  private
26
44
 
45
+ def parse_schemes
46
+ # schemes are in project/xcshareddata/xcschemes/*.xcscheme
47
+ Dir["#{@path}/xcshareddata/xcschemes/*.xcscheme"].each do |scheme|
48
+ @schemes << Xcode::Scheme.new(self, scheme)
49
+ end
50
+ end
51
+
27
52
  def parse_pbxproj
28
53
  json = JSON.parse(`plutil -convert json -o - "#{@path}/project.pbxproj"`)
29
54
 
@@ -36,11 +61,10 @@ module Xcode
36
61
  buildConfigurations = json['objects'][buildConfigurationList]['buildConfigurations']
37
62
 
38
63
  buildConfigurations.each do |buildConfiguration|
39
- config = Xcode::Configuration.new(target, json['objects'][buildConfiguration])
40
- target.configs[config.name.to_sym] = config
64
+ target.configs << Xcode::Configuration.new(target, json['objects'][buildConfiguration])
41
65
  end
42
66
 
43
- @targets[target.name.to_sym] = target
67
+ @targets << target
44
68
  end
45
69
  end
46
70
 
@@ -0,0 +1,33 @@
1
+ require 'nokogiri'
2
+
3
+ module Xcode
4
+
5
+ # Schemes are an XML file that describe build, test, launch and profile actions
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
+ class Scheme
9
+ attr_reader :project, :path, :name, :launch, :test
10
+ def initialize(project, path)
11
+ @project = project
12
+ @path = 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')
18
+ end
19
+
20
+
21
+ private
22
+
23
+ def parse_action(doc, action_name)
24
+ action = doc.xpath("//#{action_name.capitalize}Action").first
25
+ buildableReference = action.xpath('BuildableProductRunnable/BuildableReference').first
26
+ return nil if buildableReference.nil?
27
+
28
+ target_name = buildableReference['BlueprintName']
29
+ @project.target(target_name).config(action['buildConfiguration'])
30
+ end
31
+
32
+ end
33
+ end
data/lib/xcode/target.rb CHANGED
@@ -5,7 +5,7 @@ module Xcode
5
5
  def initialize(project, json)
6
6
  @project = project
7
7
  @json = json
8
- @configs = {}
8
+ @configs = []
9
9
  end
10
10
 
11
11
  def productName
@@ -17,8 +17,8 @@ module Xcode
17
17
  end
18
18
 
19
19
  def config(name)
20
- config = @configs[name.to_s.to_sym]
21
- raise "No such config #{name}, available configs are #{@configs.keys}" if config.nil?
20
+ config = @configs.select {|c| c.name == name.to_s}.first
21
+ raise "No such config #{name}, available configs are #{@configs.map {|c| c.name}.join(', ')}" if config.nil?
22
22
  yield config if block_given?
23
23
  config
24
24
  end
data/lib/xcode/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Xcode
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  end
@@ -0,0 +1,33 @@
1
+ require 'xcode/project'
2
+
3
+ module Xcode
4
+ class Workspace
5
+ attr_reader :projects, :name, :path
6
+ def initialize(path)
7
+ path = "#{path}.xcworkspace" unless path=~/\.xcworkspace/
8
+ path = "#{path}/contents.xcworkspacedata" unless path=~/xcworkspacedata$/
9
+
10
+ @name = File.basename(path.gsub(/\.xcworkspace\/contents\.xcworkspacedata/,''))
11
+ @projects = []
12
+ @path = File.expand_path path
13
+
14
+ File.open(@path).read.split(/<FileRef/).each do |line|
15
+ if line=~/location\s*=\s*\"group\:(.+?)\"/
16
+ project_path = "#{workspace_root}/#{$1}"
17
+ @projects << Xcode::Project.new(project_path)
18
+ end
19
+ end
20
+ end
21
+
22
+ def describe
23
+ puts "Workspace #{name} contains:"
24
+ projects.each do |p|
25
+ p.describe
26
+ end
27
+ end
28
+
29
+ def workspace_root
30
+ File.dirname(File.dirname(@path))
31
+ end
32
+ end
33
+ end
data/lib/xcoder.rb CHANGED
@@ -5,30 +5,44 @@ require "xcode/project"
5
5
  require "xcode/info_plist"
6
6
  require "xcode/shell"
7
7
  require 'plist'
8
+ require 'xcode/keychain'
9
+ require 'xcode/workspace'
8
10
 
9
11
  module Xcode
10
12
  @@projects = nil
13
+ @@workspaces = nil
11
14
  @@sdks = nil
12
15
 
16
+ def self.projects
17
+ @@projects = parse_projects if @@projects.nil?
18
+ @@projects
19
+ end
20
+
21
+ def self.workspaces
22
+ @@workspaces = parse_workspaces if @@workspaces.nil?
23
+ @@workspaces
24
+ end
25
+
13
26
  def self.project(name)
14
27
  name = name.to_s
15
- if @@projects.nil?
16
- @@projects = parse_projects
17
- end
18
- @@projects.each do |p|
28
+
29
+ return Xcode::Project.new(name) if name=~/\.xcodeproj/
30
+
31
+ self.projects.each do |p|
19
32
  return p if p.name == name
20
33
  end
21
- raise "Unable to find project named #{name}. However, I did find these projects: #{@@projects.map {|p| p.name}.join(', ') }"
34
+ raise "Unable to find a project named #{name}. However, I did find these projects: #{self.projects.map {|p| p.name}.join(', ') }"
22
35
  end
23
36
 
24
- def self.import_certificate(cert, password, keychain="~/Library/Keychains/login.keychain")
25
- cmd = []
26
- cmd << "security"
27
- cmd << "import '#{cert}'"
28
- cmd << "-k #{keychain}"
29
- cmd << "-P #{password}"
30
- cmd << "-T /usr/bin/codesign"
31
- Xcode::Shell.execute(cmd)
37
+ def self.workspace(name)
38
+ name = name.to_s
39
+
40
+ return Xcode::Workspace.new(name) if name=~/\.xcworkspace/
41
+
42
+ self.workspaces.each do |p|
43
+ return p if p.name == name
44
+ end
45
+ raise "Unable to find a workspace named #{name}. However, I did find these workspaces: #{self.workspaces.map {|p| p.name}.join(', ') }"
32
46
  end
33
47
 
34
48
  def self.find_projects(dir='.')
@@ -61,6 +75,16 @@ module Xcode
61
75
  end
62
76
  end
63
77
  end
78
+
79
+ def self.parse_workspaces(dir='.')
80
+ projects = []
81
+ Find.find(dir) do |path|
82
+ if path=~/\.xcworkspace$/ and !(path=~/\.xcodeproj\//)
83
+ projects << Xcode::Workspace.new(path)
84
+ end
85
+ end
86
+ projects
87
+ end
64
88
 
65
89
  def self.parse_projects(dir='.')
66
90
  projects = []
data/xcoder.gemspec CHANGED
@@ -20,4 +20,5 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.add_runtime_dependency "json"
22
22
  s.add_runtime_dependency "plist"
23
+ s.add_runtime_dependency "nokogiri"
23
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xcoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-08 00:00:00.000000000Z
12
+ date: 2011-11-10 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70283870191140 !ruby/object:Gem::Requirement
16
+ requirement: &70260671242760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70283870191140
24
+ version_requirements: *70260671242760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: plist
27
- requirement: &70283870190720 !ruby/object:Gem::Requirement
27
+ requirement: &70260671242340 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,18 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70283870190720
35
+ version_requirements: *70260671242340
36
+ - !ruby/object:Gem::Dependency
37
+ name: nokogiri
38
+ requirement: &70260671241920 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70260671241920
36
47
  description: Provides a ruby based object-model for parsing project structures and
37
48
  invoking builds
38
49
  email:
@@ -49,11 +60,14 @@ files:
49
60
  - lib/xcode/builder.rb
50
61
  - lib/xcode/configuration.rb
51
62
  - lib/xcode/info_plist.rb
63
+ - lib/xcode/keychain.rb
52
64
  - lib/xcode/project.rb
53
65
  - lib/xcode/provisioning_profile.rb
66
+ - lib/xcode/scheme.rb
54
67
  - lib/xcode/shell.rb
55
68
  - lib/xcode/target.rb
56
69
  - lib/xcode/version.rb
70
+ - lib/xcode/workspace.rb
57
71
  - lib/xcoder.rb
58
72
  - xcoder.gemspec
59
73
  homepage: https://github.com/rayh/xcoder