xcoder 0.1.0 → 0.1.1

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.
Files changed (53) hide show
  1. data/spec/TestProject/TestProject.xcodeproj/project.pbxproj +801 -433
  2. data/spec/build_phase_spec.rb +1 -1
  3. data/spec/builder_spec.rb +54 -32
  4. data/spec/configuration_list_spec.rb +38 -0
  5. data/spec/configuration_spec.rb +5 -6
  6. data/spec/group_spec.rb +43 -32
  7. data/spec/integration/builder_spec.rb +60 -0
  8. data/spec/integration/cedar_install_spec.rb +107 -0
  9. data/spec/integration/pull_to_refresh_install_spec.rb +36 -0
  10. data/spec/integration/reachability_install_spec.rb +43 -0
  11. data/spec/keychain_spec.rb +2 -2
  12. data/spec/project_spec.rb +55 -6
  13. data/spec/scheme_spec.rb +1 -2
  14. data/spec/spec_helper.rb +2 -1
  15. data/spec/target_spec.rb +93 -3
  16. data/spec/test_report_spec.rb +2 -2
  17. data/spec/workspace_spec.rb +1 -2
  18. metadata +25 -48
  19. data/.gitignore +0 -7
  20. data/.rvmrc +0 -4
  21. data/Gemfile +0 -11
  22. data/Guardfile +0 -13
  23. data/README.md +0 -125
  24. data/Rakefile +0 -16
  25. data/lib/xcode/build_file.rb +0 -22
  26. data/lib/xcode/build_phase.rb +0 -46
  27. data/lib/xcode/builder.rb +0 -182
  28. data/lib/xcode/buildfile.rb +0 -101
  29. data/lib/xcode/configuration.rb +0 -129
  30. data/lib/xcode/core_ext/array.rb +0 -23
  31. data/lib/xcode/core_ext/boolean.rb +0 -21
  32. data/lib/xcode/core_ext/fixnum.rb +0 -5
  33. data/lib/xcode/core_ext/hash.rb +0 -27
  34. data/lib/xcode/core_ext/string.rb +0 -11
  35. data/lib/xcode/file_reference.rb +0 -29
  36. data/lib/xcode/group.rb +0 -118
  37. data/lib/xcode/info_plist.rb +0 -41
  38. data/lib/xcode/keychain.rb +0 -77
  39. data/lib/xcode/parsers/plutil_project_parser.rb +0 -20
  40. data/lib/xcode/project.rb +0 -190
  41. data/lib/xcode/provisioning_profile.rb +0 -53
  42. data/lib/xcode/registry.rb +0 -120
  43. data/lib/xcode/resource.rb +0 -187
  44. data/lib/xcode/scheme.rb +0 -36
  45. data/lib/xcode/shell.rb +0 -21
  46. data/lib/xcode/target.rb +0 -94
  47. data/lib/xcode/test/report_parser.rb +0 -172
  48. data/lib/xcode/testflight.rb +0 -56
  49. data/lib/xcode/variant_group.rb +0 -8
  50. data/lib/xcode/version.rb +0 -3
  51. data/lib/xcode/workspace.rb +0 -40
  52. data/lib/xcoder.rb +0 -105
  53. data/xcoder.gemspec +0 -26
data/lib/xcode/scheme.rb DELETED
@@ -1,36 +0,0 @@
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
- def builder
21
- Xcode::Builder.new(self)
22
- end
23
-
24
- private
25
-
26
- def parse_action(doc, action_name)
27
- action = doc.xpath("//#{action_name.capitalize}Action").first
28
- buildableReference = action.xpath('BuildableProductRunnable/BuildableReference').first
29
- return nil if buildableReference.nil?
30
-
31
- target_name = buildableReference['BlueprintName']
32
- @project.target(target_name).config(action['buildConfiguration'])
33
- end
34
-
35
- end
36
- end
data/lib/xcode/shell.rb DELETED
@@ -1,21 +0,0 @@
1
- module Xcode
2
- module Shell
3
- def self.execute(bits, show_output=true)
4
- out = []
5
- cmd = bits.is_a?(Array) ? bits.join(' ') : bits
6
-
7
- puts "EXECUTE: #{cmd}"
8
- IO.popen (cmd) do |f|
9
- f.each do |line|
10
- puts line if show_output
11
- yield(line) if block_given?
12
- out << line
13
- end
14
- end
15
- #Process.wait
16
- raise "Error (#{$?.exitstatus}) executing '#{cmd}'\n\n #{out.join(" ")}" if $?.exitstatus>0
17
- #puts "RETURN: #{out.inspect}"
18
- out
19
- end
20
- end
21
- end
data/lib/xcode/target.rb DELETED
@@ -1,94 +0,0 @@
1
- require_relative 'build_file'
2
-
3
- module Xcode
4
-
5
- #
6
- # Within a project a user may define a number of targets. These targets may
7
- # be to generate the application, generate a universal framework, or execute
8
- # tests.
9
- #
10
- #
11
- # @example Target as Hash
12
- #
13
- # E21D8AA914E0F817002E56AA /* newtarget */ = {
14
- # isa = PBXNativeTarget;
15
- # buildConfigurationList = E21D8ABD14E0F817002E56AA /* Build configuration list for PBXNativeTarget "newtarget" */;
16
- # buildPhases = (
17
- # E21D8AA614E0F817002E56AA /* Sources */,
18
- # E21D8AA714E0F817002E56AA /* Frameworks */,
19
- # E21D8AA814E0F817002E56AA /* Resources */,
20
- # );
21
- # buildRules = (
22
- # );
23
- # dependencies = (
24
- # );
25
- # name = newtarget;
26
- # productName = newtarget;
27
- # productReference = E21D8AAA14E0F817002E56AA /* newtarget.app */;
28
- # productType = "com.apple.product-type.application";
29
- # };
30
- #
31
- #
32
- module Target
33
-
34
- # A reference to the project for which these targets reside.
35
- attr_accessor :project
36
-
37
- #
38
- # @return [PBXBuildConfiguration] the configurations that this target supports.
39
- # these are generally 'Debug' or 'Release' but may be custom designed
40
- # configurations.
41
- #
42
- def configs
43
- buildConfigurationList.buildConfigurations.map do |config|
44
- config.target = self
45
- config
46
- end
47
- end
48
-
49
- #
50
- # Return a specific build configuration. When one is not found to match,
51
- # an exception is raised.
52
- #
53
- # @param [String] name of a configuration to return
54
- # @return [PBXBuildConfiguration] a specific build configuration that
55
- # matches the specified name.
56
- #
57
- def config(name)
58
- config = configs.select {|config| config.name == name.to_s }.first
59
- raise "No such config #{name}, available configs are #{configs.map {|c| c.name}.join(', ')}" if config.nil?
60
- yield config if block_given?
61
- config
62
- end
63
-
64
- #
65
- # A ruby-friendly alias for the property defined at buildPhases.
66
- #
67
- def build_phases
68
- buildPhases
69
- end
70
-
71
- #
72
- # @return [BuildPhase] the framework specific build phase of the target.
73
- #
74
- def framework_build_phase
75
- build_phases.find {|phase| phase.isa == 'PBXFrameworksBuildPhase' }
76
- end
77
-
78
- #
79
- # @return [BuildPhase] the sources specific build phase of the target.
80
- #
81
- def sources_build_phase
82
- build_phases.find {|phase| phase.isa == 'PBXSourcesBuildPhase' }
83
- end
84
-
85
- #
86
- # @return [BuildPhase] the resources specific build phase of the target.
87
- #
88
- def resources_build_phase
89
- build_phases.find {|phase| phase.isa == 'PBXResourcesBuildPhase' }
90
- end
91
-
92
- end
93
-
94
- end
@@ -1,172 +0,0 @@
1
- require 'time'
2
- require 'FileUtils'
3
- require 'socket'
4
- require 'builder'
5
-
6
- module Xcode
7
- module Test
8
- module Formatters
9
- class JunitFormatter
10
- def initialize(dir)
11
- @dir = dir
12
- end
13
-
14
- def string_to_xml(s)
15
- s.gsub(/&/, '&amp;').gsub(/'/, '&quot;').gsub(/</, '&lt;')
16
- end
17
-
18
- def write(report)
19
- if report.end_time.nil?
20
- raise "Report #{report} #{report.name} has a nil end time!?"
21
- end
22
- xml = ::Builder::XmlMarkup.new( :indent => 2 )
23
- xml.instruct! :xml, :encoding => "UTF-8"
24
- xml.testsuite(:errors => report.total_error_tests,
25
- :failures => report.total_failed_tests,
26
- :hostname => Socket.gethostname,
27
- :name => report.name,
28
- :tests => report.tests.count,
29
- :time => (report.end_time - report.start_time),
30
- :timestamp => report.end_time
31
- ) do |p|
32
-
33
- report.tests.each do |t|
34
- p.testcase(:classname => report.name,
35
- :name => t.name,
36
- :time => t.time
37
- ) do |e|
38
-
39
- if t.error?
40
- e.failure t.error_location, :message => t.error_message, :type => 'Failure'
41
- end
42
- end
43
- end
44
- end
45
-
46
- File.open("#{@dir}/TEST-#{report.name}.xml", 'w') do |current_file|
47
- current_file.write xml.target!
48
- end
49
-
50
- end
51
- end
52
- end
53
-
54
- class SuiteReport
55
- attr_accessor :tests, :name, :start_time, :end_time
56
-
57
- def initialize(name, start_time)
58
- @name = name
59
- @start_time = start_time
60
- @tests = []
61
- end
62
-
63
- def finish(time)
64
- raise "Time is nil" if time.nil?
65
- @end_time = time
66
- end
67
-
68
- def total_error_tests
69
- @tests.select {|t| t.error? }.count
70
- end
71
-
72
- def total_passed_tests
73
- @tests.select {|t| t.passed? }.count
74
- end
75
-
76
- def total_failed_tests
77
- @tests.select {|t| t.failed? }.count
78
- end
79
-
80
- end
81
-
82
- class CaseReport
83
- attr_reader :name, :time, :error_message, :error_location
84
-
85
- def initialize(name)
86
- @name = name
87
- end
88
-
89
- def passed?
90
- @passed
91
- end
92
-
93
- def failed?
94
- error? or !@passed
95
- end
96
-
97
- def error?
98
- !@error_message.nil?
99
- end
100
-
101
- def passed(time)
102
- @passed = true
103
- @time = time
104
- end
105
-
106
- def failed(time)
107
- @passed = false
108
- @time = time
109
- end
110
-
111
- def error(error_message,error_location)
112
- @error_message = error_message
113
- @error_location = error_location
114
- end
115
- end
116
-
117
- class ReportParser
118
-
119
- attr_reader :exit_code, :reports
120
-
121
- def initialize
122
- @exit_code = 0
123
- @reports = []
124
- end
125
-
126
- def write(dir, format=:junit)
127
- dir = File.expand_path(dir)
128
- FileUtils.mkdir_p(dir)
129
-
130
- formatter = Formatters.const_get("#{format.to_s.capitalize}Formatter").new(dir)
131
- @reports.each do |r|
132
- formatter.write(r)
133
- end
134
- end
135
-
136
- def <<(piped_row)
137
- case piped_row
138
-
139
- when /Test Suite '(\S+)'.*started at\s+(.*)/
140
- name = $1
141
- time = Time.parse($2)
142
- @reports << SuiteReport.new(name, time) unless name=~/\// # ignore if its a file path
143
-
144
- when /Test Suite '(\S+)'.*finished at\s+(.*)./
145
- @reports.last.finish(Time.parse($2))
146
-
147
- when /Test Case '-\[\S+\s+(\S+)\]' started./
148
- test = CaseReport.new($1)
149
- @reports.last.tests << test
150
-
151
- when /Test Case '-\[\S+\s+(\S+)\]' passed \((.*) seconds\)/
152
- @reports.last.tests.last.passed($2.to_f)
153
-
154
- when /(.*): error: -\[(\S+) (\S+)\] : (.*)/
155
- @reports.last.tests.last.error(error_message,error_location)
156
- @exit_code = 1 # should terminate
157
-
158
- when /Test Case '-\[\S+ (\S+)\]' failed \((\S+) seconds\)/
159
- @reports.last.tests.last.failed($2.to_f)
160
- @exit_code = 1 # should terminate
161
-
162
- when /failed with exit code (\d+)/
163
- @exit_code = $1.to_i
164
-
165
- when
166
- /BUILD FAILED/
167
- @exit_code = -1;
168
- end
169
- end
170
- end
171
- end
172
- end
@@ -1,56 +0,0 @@
1
- require 'rest-client'
2
- require 'json'
3
-
4
- module Xcode
5
- class Testflight
6
- attr_accessor :api_token, :team_token, :notify, :proxy, :notes, :lists
7
-
8
- def initialize(api_token, team_token)
9
- @api_token = api_token
10
- @team_token = team_token
11
- @notify = true
12
- @notes = nil
13
- @lists = []
14
- @proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
15
- end
16
-
17
- def upload(ipa_path, dsymzip_path=nil)
18
- puts "Uploading to Testflight..."
19
-
20
- # RestClient.proxy = @proxy || ENV['http_proxy'] || ENV['HTTP_PROXY']
21
- # RestClient.log = '/tmp/restclient.log'
22
- #
23
- # response = RestClient.post('http://testflightapp.com/api/builds.json',
24
- # :file => File.new(ipa_path),
25
- # :dsym => File.new(dsymzip_path),
26
- # :api_token => @api_token,
27
- # :team_token => @team_token,
28
- # :notes => @notes,
29
- # :notify => @notify ? 'True' : 'False',
30
- # :distribution_lists => @lists.join(',')
31
- # )
32
- #
33
- # json = JSON.parse(response)
34
- # puts " + Done, got: #{json.inspect}"
35
- # json
36
-
37
- cmd = []
38
- cmd << 'curl'
39
- cmd << "--proxy #{@proxy}" unless @proxy.nil?
40
- cmd << "-X POST http://testflightapp.com/api/builds.json"
41
- cmd << "-F file=@\"#{ipa_path}\""
42
- cmd << "-F dsym=@\"#{dsymzip_path}\"" unless dsymzip_path.nil?
43
- cmd << "-F api_token='#{@api_token}'"
44
- cmd << "-F team_token='#{@team_token}'"
45
- cmd << "-F notes=\"#{@notes}\"" unless @notes.nil?
46
- cmd << "-F notify=#{@notify ? 'True' : 'False'}"
47
- cmd << "-F distribution_lists='#{@lists.join(',')}'" unless @lists.count==0
48
-
49
- response = Xcode::Shell.execute(cmd)
50
-
51
- json = JSON.parse(response.join(''))
52
- puts " + Done, got: #{json.inspect}"
53
- json
54
- end
55
- end
56
- end
@@ -1,8 +0,0 @@
1
- require_relative 'group'
2
-
3
- module Xcode
4
-
5
- module VariantGroup
6
- include Group ; extend Group
7
- end
8
- end
data/lib/xcode/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module Xcode
2
- VERSION = "0.1.0"
3
- end
@@ -1,40 +0,0 @@
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 project(name)
23
- project = @projects.select {|c| c.name == name.to_s}.first
24
- raise "No such project #{name}, available projects are #{@projects.map {|c| c.name}.join(', ')}" if project.nil?
25
- yield project if block_given?
26
- project
27
- end
28
-
29
- def describe
30
- puts "Workspace #{name} contains:"
31
- projects.each do |p|
32
- p.describe
33
- end
34
- end
35
-
36
- def workspace_root
37
- File.dirname(File.dirname(@path))
38
- end
39
- end
40
- end
data/lib/xcoder.rb DELETED
@@ -1,105 +0,0 @@
1
- require 'find'
2
- require 'fileutils'
3
- require "xcode/version"
4
- require "xcode/project"
5
- require "xcode/info_plist"
6
- require "xcode/shell"
7
- require 'plist'
8
- require 'xcode/keychain'
9
- require 'xcode/workspace'
10
- require 'xcode/buildfile'
11
-
12
- module Xcode
13
- @@projects = nil
14
- @@workspaces = nil
15
- @@sdks = nil
16
-
17
- def self.projects
18
- @@projects = parse_projects if @@projects.nil?
19
- @@projects
20
- end
21
-
22
- def self.workspaces
23
- @@workspaces = parse_workspaces if @@workspaces.nil?
24
- @@workspaces
25
- end
26
-
27
- def self.project(name)
28
- name = name.to_s
29
-
30
- return Xcode::Project.new(name) if name=~/\.xcodeproj/
31
-
32
- self.projects.each do |p|
33
- return p if p.name == name
34
- end
35
- raise "Unable to find a project named #{name}. However, I did find these projects: #{self.projects.map {|p| p.name}.join(', ') }"
36
- end
37
-
38
- def self.workspace(name)
39
- name = name.to_s
40
-
41
- return Xcode::Workspace.new(name) if name=~/\.xcworkspace/
42
-
43
- self.workspaces.each do |p|
44
- return p if p.name == name
45
- end
46
- raise "Unable to find a workspace named #{name}. However, I did find these workspaces: #{self.workspaces.map {|p| p.name}.join(', ') }"
47
- end
48
-
49
- def self.find_projects(dir='.')
50
- parse_projects(dir)
51
- end
52
-
53
- def self.is_sdk_available?(sdk)
54
- parse_sdks if @@sdks.nil?
55
- @@sdks.values.include? sdk
56
- end
57
-
58
- def self.available_sdks
59
- parse_sdks if @@sdks.nil?
60
- @@sdks
61
- end
62
-
63
- private
64
- def self.parse_sdks
65
- @@sdks = {}
66
- parsing = false
67
- `xcodebuild -showsdks`.split("\n").each do |l|
68
- l.strip!
69
- if l=~/(.*)\s+SDKs:/
70
- parsing = true
71
- elsif l=~/^\s*$/
72
- parsing = false
73
- elsif parsing
74
- l=~/([^\t]+)\t+\-sdk (.*)/
75
- @@sdks[$1.strip] = $2.strip unless $1.nil? and $2.nil?
76
- end
77
- end
78
- end
79
-
80
- def self.parse_workspaces(dir='.')
81
- projects = []
82
- Find.find(dir) do |path|
83
- if path=~/\.xcworkspace$/ and !(path=~/\.xcodeproj\//)
84
- projects << Xcode::Workspace.new(path)
85
- end
86
- end
87
- projects
88
- end
89
-
90
- def self.parse_projects(dir='.')
91
- projects = []
92
- Find.find(dir) do |path|
93
- if path=~/(.*)\.xcodeproj$/
94
- projects << Xcode::Project.new(path)
95
- end
96
- end
97
- projects
98
- end
99
- end
100
-
101
- require 'xcode/core_ext/hash'
102
- require 'xcode/core_ext/array'
103
- require 'xcode/core_ext/string'
104
- require 'xcode/core_ext/boolean'
105
- require 'xcode/core_ext/fixnum'