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 +27 -2
- data/lib/xcode/builder.rb +1 -0
- data/lib/xcode/configuration.rb +1 -1
- data/lib/xcode/keychain.rb +29 -0
- data/lib/xcode/project.rb +32 -8
- data/lib/xcode/scheme.rb +33 -0
- data/lib/xcode/target.rb +3 -3
- data/lib/xcode/version.rb +1 -1
- data/lib/xcode/workspace.rb +33 -0
- data/lib/xcoder.rb +37 -13
- data/xcoder.gemspec +1 -0
- metadata +20 -6
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
|
-
|
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
data/lib/xcode/configuration.rb
CHANGED
@@ -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
|
20
|
-
raise "No such target #{name}, available targets are #{@targets.
|
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
|
-
|
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
|
67
|
+
@targets << target
|
44
68
|
end
|
45
69
|
end
|
46
70
|
|
data/lib/xcode/scheme.rb
ADDED
@@ -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
|
21
|
-
raise "No such config #{name}, available configs are #{@configs.
|
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
@@ -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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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: #{
|
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.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
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.
|
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-
|
12
|
+
date: 2011-11-10 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
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: *
|
24
|
+
version_requirements: *70260671242760
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: plist
|
27
|
-
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: *
|
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
|