xcoder 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/spec/TestProject/TestProject.xcodeproj/project.pbxproj +801 -433
- data/spec/build_phase_spec.rb +1 -1
- data/spec/builder_spec.rb +54 -32
- data/spec/configuration_list_spec.rb +38 -0
- data/spec/configuration_spec.rb +5 -6
- data/spec/group_spec.rb +43 -32
- data/spec/integration/builder_spec.rb +60 -0
- data/spec/integration/cedar_install_spec.rb +107 -0
- data/spec/integration/pull_to_refresh_install_spec.rb +36 -0
- data/spec/integration/reachability_install_spec.rb +43 -0
- data/spec/keychain_spec.rb +2 -2
- data/spec/project_spec.rb +55 -6
- data/spec/scheme_spec.rb +1 -2
- data/spec/spec_helper.rb +2 -1
- data/spec/target_spec.rb +93 -3
- data/spec/test_report_spec.rb +2 -2
- data/spec/workspace_spec.rb +1 -2
- metadata +25 -48
- data/.gitignore +0 -7
- data/.rvmrc +0 -4
- data/Gemfile +0 -11
- data/Guardfile +0 -13
- data/README.md +0 -125
- data/Rakefile +0 -16
- data/lib/xcode/build_file.rb +0 -22
- data/lib/xcode/build_phase.rb +0 -46
- data/lib/xcode/builder.rb +0 -182
- data/lib/xcode/buildfile.rb +0 -101
- data/lib/xcode/configuration.rb +0 -129
- data/lib/xcode/core_ext/array.rb +0 -23
- data/lib/xcode/core_ext/boolean.rb +0 -21
- data/lib/xcode/core_ext/fixnum.rb +0 -5
- data/lib/xcode/core_ext/hash.rb +0 -27
- data/lib/xcode/core_ext/string.rb +0 -11
- data/lib/xcode/file_reference.rb +0 -29
- data/lib/xcode/group.rb +0 -118
- data/lib/xcode/info_plist.rb +0 -41
- data/lib/xcode/keychain.rb +0 -77
- data/lib/xcode/parsers/plutil_project_parser.rb +0 -20
- data/lib/xcode/project.rb +0 -190
- data/lib/xcode/provisioning_profile.rb +0 -53
- data/lib/xcode/registry.rb +0 -120
- data/lib/xcode/resource.rb +0 -187
- data/lib/xcode/scheme.rb +0 -36
- data/lib/xcode/shell.rb +0 -21
- data/lib/xcode/target.rb +0 -94
- data/lib/xcode/test/report_parser.rb +0 -172
- data/lib/xcode/testflight.rb +0 -56
- data/lib/xcode/variant_group.rb +0 -8
- data/lib/xcode/version.rb +0 -3
- data/lib/xcode/workspace.rb +0 -40
- data/lib/xcoder.rb +0 -105
- data/xcoder.gemspec +0 -26
data/lib/xcode/configuration.rb
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
require 'xcode/builder'
|
2
|
-
|
3
|
-
module Xcode
|
4
|
-
|
5
|
-
#
|
6
|
-
# Projects have a number of build configurations. These configurations are
|
7
|
-
# usually the default 'Debug' and 'Release'. However, custom ones can be
|
8
|
-
# defined.
|
9
|
-
#
|
10
|
-
# @see https://developer.apple.com/library/ios/#documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/Building/Building.html
|
11
|
-
#
|
12
|
-
# Each configuration is defined and then a reference of that configuration is
|
13
|
-
# maintained in the Target through the XCConfigurationList.
|
14
|
-
#
|
15
|
-
# @example Xcode configuration
|
16
|
-
#
|
17
|
-
# E21D8ABB14E0F817002E56AA /* Debug */ = {
|
18
|
-
# isa = XCBuildConfiguration;
|
19
|
-
# buildSettings = {
|
20
|
-
# "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
21
|
-
# GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
22
|
-
# GCC_PREFIX_HEADER = "newtarget/newtarget-Prefix.pch";
|
23
|
-
# INFOPLIST_FILE = "newtarget/newtarget-Info.plist";
|
24
|
-
# PRODUCT_NAME = "$(TARGET_NAME)";
|
25
|
-
# WRAPPER_EXTENSION = app;
|
26
|
-
# };
|
27
|
-
# name = Debug;
|
28
|
-
# };
|
29
|
-
#
|
30
|
-
module Configuration
|
31
|
-
|
32
|
-
#
|
33
|
-
# The configuration is defined within a target.
|
34
|
-
# @see PBXNativeTarget
|
35
|
-
#
|
36
|
-
attr_accessor :target
|
37
|
-
|
38
|
-
#
|
39
|
-
# @return the location for the InfoPlist file for the configuration.
|
40
|
-
# @see InfoPlist
|
41
|
-
#
|
42
|
-
def info_plist_location
|
43
|
-
buildSettings['INFOPLIST_FILE']
|
44
|
-
end
|
45
|
-
|
46
|
-
#
|
47
|
-
# Opens the info plist associated with the configuration and allows you to
|
48
|
-
# edit the configuration.
|
49
|
-
#
|
50
|
-
# @example Editing the configuration
|
51
|
-
#
|
52
|
-
# config = Xcode.project('MyProject.xcodeproj').target('Application').config('Debug')
|
53
|
-
# config.info_plist do |plist|
|
54
|
-
# puts plist.version # => 1.0
|
55
|
-
# plist.version = 1.1
|
56
|
-
# marketing_version = 12.1
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# @see InfoPlist
|
60
|
-
#
|
61
|
-
def info_plist
|
62
|
-
# puts @json.inspect
|
63
|
-
info = Xcode::InfoPlist.new(self, info_plist_location)
|
64
|
-
yield info if block_given?
|
65
|
-
info.save
|
66
|
-
info
|
67
|
-
end
|
68
|
-
|
69
|
-
#
|
70
|
-
# @return the name of the product that this configuration will generate.
|
71
|
-
#
|
72
|
-
def product_name
|
73
|
-
substitute(buildSettings['PRODUCT_NAME'])
|
74
|
-
end
|
75
|
-
|
76
|
-
def set_other_linker_flags(value)
|
77
|
-
set 'OTHER_LDFLAGS', value
|
78
|
-
end
|
79
|
-
|
80
|
-
def get(name)
|
81
|
-
buildSettings[name]
|
82
|
-
end
|
83
|
-
|
84
|
-
def set name, value
|
85
|
-
buildSettings[name] = value
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
#
|
90
|
-
# Create a builder for this given project->target->configuration.
|
91
|
-
#
|
92
|
-
# @return [Builder] this is a builder for the configuration.
|
93
|
-
# @see Builder
|
94
|
-
#
|
95
|
-
def builder
|
96
|
-
puts "Making a Builder with #{self} #{self.methods}"
|
97
|
-
Xcode::Builder.new(self)
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
#
|
104
|
-
# Within the configuration properties variables reference the target,
|
105
|
-
# i.e."$(TARGET_NAME)". This method will find and replace the target
|
106
|
-
# constant with the appropriate value.
|
107
|
-
#
|
108
|
-
# @param [String] value is a property of the configuration that may contain
|
109
|
-
# the target variable to replace.
|
110
|
-
#
|
111
|
-
# @return [String] a string without the variable reference.
|
112
|
-
#
|
113
|
-
def substitute(value)
|
114
|
-
if value=~/\$\(.*\)/
|
115
|
-
value.gsub(/\$\((.*)\)/) do |match|
|
116
|
-
case match
|
117
|
-
when "$(TARGET_NAME)"
|
118
|
-
@target.name
|
119
|
-
else
|
120
|
-
raise "Unknown substitution variable #{match}"
|
121
|
-
end
|
122
|
-
end
|
123
|
-
else
|
124
|
-
value
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
end
|
129
|
-
end
|
data/lib/xcode/core_ext/array.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
class Array
|
2
|
-
|
3
|
-
#
|
4
|
-
# Arrays in an Xcode project take a particular format.
|
5
|
-
#
|
6
|
-
# @note the last element in the array can have a comma; it is optional.
|
7
|
-
#
|
8
|
-
# @example output format:
|
9
|
-
#
|
10
|
-
# (
|
11
|
-
# ITEM1,
|
12
|
-
# ITEM2,
|
13
|
-
# ITEM3
|
14
|
-
# )
|
15
|
-
#
|
16
|
-
def to_xcplist
|
17
|
-
plist_of_items = map {|item| item.to_xcplist }.join(",\n")
|
18
|
-
|
19
|
-
%{(
|
20
|
-
#{plist_of_items}
|
21
|
-
)}
|
22
|
-
end
|
23
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class TrueClass
|
4
|
-
|
5
|
-
#
|
6
|
-
# Xcode project's expect boolean trues to be the word YES.
|
7
|
-
#
|
8
|
-
def to_xcplist
|
9
|
-
"YES"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class FalseClass
|
14
|
-
|
15
|
-
#
|
16
|
-
# Xcode project's expect boolean trues to be the word NO.
|
17
|
-
#
|
18
|
-
def to_xcplist
|
19
|
-
"NO"
|
20
|
-
end
|
21
|
-
end
|
data/lib/xcode/core_ext/hash.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
class Hash
|
2
|
-
|
3
|
-
#
|
4
|
-
# Hashes in an Xcode project take a particular format.
|
5
|
-
#
|
6
|
-
# @note the keys are represeted in this output with quotes; this is actually
|
7
|
-
# optional for certain keys based on their format. This is done to ensure
|
8
|
-
# that all keys that do not conform are ensured proper output.
|
9
|
-
#
|
10
|
-
# @example output format:
|
11
|
-
#
|
12
|
-
# {
|
13
|
-
# "KEY" = "VALUE";
|
14
|
-
# "KEY" = "VALUE";
|
15
|
-
# "KEY" = "VALUE";
|
16
|
-
# }
|
17
|
-
#
|
18
|
-
def to_xcplist
|
19
|
-
plist_of_items = map do |k,v|
|
20
|
-
"\"#{k}\" = #{v.to_xcplist};"
|
21
|
-
end.join("\n")
|
22
|
-
|
23
|
-
%{{
|
24
|
-
#{plist_of_items}
|
25
|
-
}}
|
26
|
-
end
|
27
|
-
end
|
data/lib/xcode/file_reference.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module Xcode
|
2
|
-
|
3
|
-
#
|
4
|
-
# Within the project file the PBXFileReference represents the object
|
5
|
-
# representation to the file on the file sytem. This is usually your source
|
6
|
-
# files within your project.
|
7
|
-
#
|
8
|
-
module FileReference
|
9
|
-
|
10
|
-
# This is the group for which this file is contained within.
|
11
|
-
attr_accessor :supergroup
|
12
|
-
|
13
|
-
def self.with_properties_for_framework(name)
|
14
|
-
{ 'isa' => "PBXFileReference",
|
15
|
-
'lastKnownFileType' => "wrapper.framework",
|
16
|
-
'name' => "#{name}.framework",
|
17
|
-
'path' => "System/Library/Frameworks/#{name}.framework",
|
18
|
-
'sourceTree' => "SDKROOT" }
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.with_properties_for_path(path)
|
22
|
-
{ 'isa' => 'PBXFileReference',
|
23
|
-
'path' => path,
|
24
|
-
'sourceTree' => '<group>' }
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
data/lib/xcode/group.rb
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
module Xcode
|
2
|
-
|
3
|
-
#
|
4
|
-
# Within the project file there are logical separation of resources into groups
|
5
|
-
# these groups may contain subgroups, files, or other objects. They have
|
6
|
-
# children.
|
7
|
-
#
|
8
|
-
# PBXGroup here provides the methods to traverse the groups to find these
|
9
|
-
# children resources as well as provide the ability to generate child
|
10
|
-
# resources.
|
11
|
-
#
|
12
|
-
module Group
|
13
|
-
|
14
|
-
#
|
15
|
-
# Return the hash that maps to the properties for a logical group
|
16
|
-
#
|
17
|
-
# @param [String] name of the logical group
|
18
|
-
#
|
19
|
-
def self.with_properties_for_logical_group(name)
|
20
|
-
{ 'isa' => 'PBXGroup',
|
21
|
-
'name' => name,
|
22
|
-
'sourceTree' => '<group>',
|
23
|
-
'children' => [] }
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
# This is the group for which this file is contained within.
|
28
|
-
attr_accessor :supergroup
|
29
|
-
|
30
|
-
#
|
31
|
-
# @example Return all the sub-groups of the main group
|
32
|
-
#
|
33
|
-
# main_group = Xcode.project('MyProject.xcodeproj').groups
|
34
|
-
# main_group.groups
|
35
|
-
#
|
36
|
-
# @return [Array] the sub-groups contained within this group.
|
37
|
-
#
|
38
|
-
def groups
|
39
|
-
children.map do |group|
|
40
|
-
# TODO: this will return all children when it should just return subgroups
|
41
|
-
group.supergroup = self
|
42
|
-
group
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
#
|
47
|
-
# Find all the child groups that have a name that matches the specified name.
|
48
|
-
#
|
49
|
-
# @param [String] name of the group that you are looking to return.
|
50
|
-
# @return [Array<PBXGroup>] the groups with the same matching name. This
|
51
|
-
# could be no groups, one group, or multiple groups.
|
52
|
-
#
|
53
|
-
def group(name)
|
54
|
-
groups.find_all {|group| group.name == name }
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
#
|
59
|
-
# Adds a group as a child to current group with the given name.
|
60
|
-
#
|
61
|
-
# @note A group may be added that has the same name as another group as they
|
62
|
-
# are distinguished by a unique identifier and not by name.
|
63
|
-
#
|
64
|
-
# @param [String] name of the group that you want to add as a child group of
|
65
|
-
# the specified group.
|
66
|
-
#
|
67
|
-
def add_group(name)
|
68
|
-
|
69
|
-
# Groups that represent a physical path often have the key 'path' with
|
70
|
-
# the value being it's path name.
|
71
|
-
#
|
72
|
-
# Groups that represent a logical group often have the key 'name' with
|
73
|
-
# the value being it's group name.
|
74
|
-
|
75
|
-
new_identifier = @registry.add_object Group.with_properties_for_logical_group(name)
|
76
|
-
|
77
|
-
# Add the group's identifier to the list of children
|
78
|
-
|
79
|
-
@properties['children'] << new_identifier
|
80
|
-
|
81
|
-
# Find the newly added group to return
|
82
|
-
|
83
|
-
groups.find {|group| group.identifier == new_identifier }
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
#
|
88
|
-
# Add a file to the specified group. Currently the file creation requires
|
89
|
-
# the path to the physical file.
|
90
|
-
#
|
91
|
-
# @param [String] path to the file that is being added.
|
92
|
-
#
|
93
|
-
def add_file(path)
|
94
|
-
|
95
|
-
new_identifier = @registry.add_object FileReference.with_properties_for_path(path)
|
96
|
-
|
97
|
-
@properties['children'] << new_identifier
|
98
|
-
|
99
|
-
children.find {|file| file.identifier == new_identifier }
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
|
104
|
-
def add_framework framework_name
|
105
|
-
new_identifier = @registry.add_object FileReference.with_properties_for_framework(framework_name)
|
106
|
-
|
107
|
-
# Add the framework to the group
|
108
|
-
|
109
|
-
@properties['children'] << new_identifier
|
110
|
-
|
111
|
-
children.find {|file| file.identifier == new_identifier }
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
end
|
data/lib/xcode/info_plist.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'plist'
|
2
|
-
require 'pp'
|
3
|
-
|
4
|
-
module Xcode
|
5
|
-
|
6
|
-
#
|
7
|
-
# @see https://developer.apple.com/library/ios/#documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html
|
8
|
-
#
|
9
|
-
class InfoPlist
|
10
|
-
def initialize(config, plist_location)
|
11
|
-
@config = config
|
12
|
-
|
13
|
-
@plist_location = File.expand_path("#{File.dirname(@config.target.project.path)}/#{plist_location}")
|
14
|
-
unless File.exists?(@plist_location)
|
15
|
-
puts 'Plist not found ' + @plist_location
|
16
|
-
exit 1
|
17
|
-
end
|
18
|
-
@plist = Plist::parse_xml(@plist_location)
|
19
|
-
end
|
20
|
-
|
21
|
-
def marketing_version
|
22
|
-
@plist['CFBundleShortVersionString']
|
23
|
-
end
|
24
|
-
|
25
|
-
def marketing_version=(version)
|
26
|
-
@plist['CFBundleShortVersionString'] = version
|
27
|
-
end
|
28
|
-
|
29
|
-
def version
|
30
|
-
@plist['CFBundleVersion']
|
31
|
-
end
|
32
|
-
|
33
|
-
def version=(version)
|
34
|
-
@plist['CFBundleVersion'] = version.to_s
|
35
|
-
end
|
36
|
-
|
37
|
-
def save
|
38
|
-
File.open(@plist_location, 'w') {|f| f << @plist.to_plist}
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/xcode/keychain.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module Xcode
|
2
|
-
class Keychain
|
3
|
-
attr_accessor :name, :path
|
4
|
-
|
5
|
-
TEMP_PASSWORD = "build_keychain_password"
|
6
|
-
def initialize(name)
|
7
|
-
@name = name
|
8
|
-
@path = File.expand_path "~/Library/Keychains/#{name}"
|
9
|
-
end
|
10
|
-
|
11
|
-
def import(cert, password)
|
12
|
-
cmd = []
|
13
|
-
cmd << "security"
|
14
|
-
cmd << "import '#{cert}'"
|
15
|
-
cmd << "-k '#{@path}'"
|
16
|
-
cmd << "-P #{password}"
|
17
|
-
cmd << "-T /usr/bin/codesign"
|
18
|
-
Xcode::Shell.execute(cmd)
|
19
|
-
end
|
20
|
-
|
21
|
-
def certificates
|
22
|
-
names = []
|
23
|
-
cmd = []
|
24
|
-
cmd << "security"
|
25
|
-
cmd << "find-certificate"
|
26
|
-
cmd << "-a"
|
27
|
-
cmd << "#{@name}"
|
28
|
-
data = Xcode::Shell.execute(cmd, false).join("")
|
29
|
-
data.scan /\s+"labl"<blob>="([^"]+)"/ do |m|
|
30
|
-
names << m[0]
|
31
|
-
end
|
32
|
-
names
|
33
|
-
end
|
34
|
-
|
35
|
-
def unlock(password)
|
36
|
-
cmd = []
|
37
|
-
cmd << "security"
|
38
|
-
cmd << "unlock-keychain"
|
39
|
-
cmd << "-p #{password}"
|
40
|
-
cmd << "#{@name}"
|
41
|
-
Xcode::Shell.execute(cmd)
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.create(name, password)
|
45
|
-
cmd = []
|
46
|
-
cmd << "security"
|
47
|
-
cmd << "create-keychain"
|
48
|
-
cmd << "-p #{password}"
|
49
|
-
cmd << "#{name}"
|
50
|
-
Xcode::Shell.execute(cmd)
|
51
|
-
|
52
|
-
Xcode::Keychain.new(name)
|
53
|
-
end
|
54
|
-
|
55
|
-
# FIXME: dangerous
|
56
|
-
def delete
|
57
|
-
cmd = []
|
58
|
-
cmd << "security"
|
59
|
-
cmd << "delete-keychain #{name}"
|
60
|
-
Xcode::Shell.execute(cmd)
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.temp_keychain(name, &block)
|
64
|
-
kc = Xcode::Keychain.create(name, TEMP_PASSWORD)
|
65
|
-
begin
|
66
|
-
kc.unlock(TEMP_PASSWORD)
|
67
|
-
block.call(kc)
|
68
|
-
ensure
|
69
|
-
kc.delete
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.login_keychain
|
74
|
-
Xcode::Keychain.new("login.keychain")
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|