xcode-install 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/xcode/install.rb +48 -6
- data/lib/xcode/install/cleanup.rb +14 -0
- data/lib/xcode/install/command.rb +1 -0
- data/lib/xcode/install/install.rb +10 -2
- data/lib/xcode/install/version.rb +1 -1
- data/spec/fixtures/xcode_63.json +46 -0
- data/spec/install_spec.rb +25 -0
- data/spec/json_spec.rb +1 -0
- data/spec/spec_helper.rb +3 -0
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f35f3bf3a7aac145047a95d07c5bdb1344600dc
|
4
|
+
data.tar.gz: 283c261a2a28d86116dcfcad1677f2df5e000a2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99fb6cb82e6131948512f46f082c7eff162e4c414bba18da8c32d36346ff8080ea3ade45a413d43973c43098346443488a8ec6f6b947439ad4e1c82f536f9fd5
|
7
|
+
data.tar.gz: 760efcea4598e41a98dde02f23345ed7de599d70dd43ee6782da57c1a8a6be26481db2df9b7cedf5079eb4db09661001e9486b279a8908a8aa77c8eb1384da64
|
data/lib/xcode/install.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "fastlane_core"
|
2
2
|
require "fastlane_core/developer_center/developer_center"
|
3
3
|
require "nokogiri"
|
4
|
+
require "rubygems/version"
|
4
5
|
require "xcode/install/command"
|
5
6
|
require "xcode/install/version"
|
6
7
|
|
@@ -62,6 +63,10 @@ module XcodeInstall
|
|
62
63
|
FileUtils.mkdir_p(CACHE_DIR)
|
63
64
|
end
|
64
65
|
|
66
|
+
def cache_dir
|
67
|
+
CACHE_DIR
|
68
|
+
end
|
69
|
+
|
65
70
|
def current_symlink
|
66
71
|
File.symlink?(SYMLINK_PATH) ? SYMLINK_PATH : nil
|
67
72
|
end
|
@@ -84,20 +89,38 @@ module XcodeInstall
|
|
84
89
|
end
|
85
90
|
|
86
91
|
def installed_versions
|
87
|
-
@installed ||= installed.map { |x| InstalledXcode.new(x) }
|
92
|
+
@installed ||= installed.map { |x| InstalledXcode.new(x) }.sort {
|
93
|
+
|a,b| Gem::Version.new(a.version) <=> Gem::Version.new(b.version)
|
94
|
+
}
|
88
95
|
end
|
89
96
|
|
90
|
-
def install_dmg(dmgPath, suffix = '')
|
97
|
+
def install_dmg(dmgPath, suffix = '', switch = true, clean = true)
|
91
98
|
xcode_path = "/Applications/Xcode#{suffix}.app"
|
92
99
|
|
93
100
|
`hdiutil mount -nobrowse -noverify #{dmgPath}`
|
94
101
|
puts 'Please authenticate for Xcode installation...'
|
95
102
|
source = Dir.glob('/Volumes/Xcode/Xcode*.app').first
|
103
|
+
|
104
|
+
if source.nil?
|
105
|
+
puts 'No `Xcode.app` found in DMG.'
|
106
|
+
return
|
107
|
+
end
|
108
|
+
|
96
109
|
`sudo ditto "#{source}" "#{xcode_path}"`
|
97
110
|
`umount "/Volumes/Xcode"`
|
98
111
|
|
99
|
-
|
100
|
-
|
112
|
+
enable_developer_mode
|
113
|
+
`sudo xcodebuild -license` unless xcode_license_approved?
|
114
|
+
|
115
|
+
if switch
|
116
|
+
`sudo rm -f #{SYMLINK_PATH}` unless current_symlink.nil?
|
117
|
+
`sudo ln -sf #{xcode_path} #{SYMLINK_PATH}` unless SYMLINK_PATH.exist?
|
118
|
+
|
119
|
+
`sudo xcode-select --switch #{xcode_path}`
|
120
|
+
puts `xcodebuild -version`
|
121
|
+
end
|
122
|
+
|
123
|
+
FileUtils.rm_f(dmgPath) if clean
|
101
124
|
end
|
102
125
|
|
103
126
|
def list_current
|
@@ -127,12 +150,18 @@ module XcodeInstall
|
|
127
150
|
|
128
151
|
CACHE_DIR = Pathname.new("#{ENV['HOME']}/Library/Caches/XcodeInstall")
|
129
152
|
LIST_FILE = CACHE_DIR + Pathname.new('xcodes.bin')
|
153
|
+
MINIMUM_VERSION = Gem::Version.new('4.3')
|
130
154
|
SYMLINK_PATH = Pathname.new('/Applications/Xcode.app')
|
131
155
|
|
132
156
|
def devcenter
|
133
157
|
@devcenter ||= FastlaneCore::DeveloperCenter.new
|
134
158
|
end
|
135
159
|
|
160
|
+
def enable_developer_mode
|
161
|
+
`sudo /usr/sbin/DevToolsSecurity -enable`
|
162
|
+
`sudo /usr/sbin/dseditgroup -o edit -t group -a staff _developer`
|
163
|
+
end
|
164
|
+
|
136
165
|
def get_seedlist
|
137
166
|
@xcodes = parse_seedlist(devcenter.download_seedlist)
|
138
167
|
@xcodes += prereleases
|
@@ -151,7 +180,9 @@ module XcodeInstall
|
|
151
180
|
def parse_seedlist(seedlist)
|
152
181
|
seedlist['data'].select {
|
153
182
|
|t| /^Xcode [0-9]/.match(t['name'])
|
154
|
-
}.map { |x| Xcode.new(x) }.
|
183
|
+
}.map { |x| Xcode.new(x) }.reject { |x| x.version < MINIMUM_VERSION }.sort {
|
184
|
+
|a,b| a.dateModified <=> b.dateModified
|
185
|
+
}
|
155
186
|
end
|
156
187
|
|
157
188
|
def list_versions
|
@@ -170,6 +201,10 @@ module XcodeInstall
|
|
170
201
|
@xcodes = Marshal.load(File.read(LIST_FILE)) if LIST_FILE.exist? && xcodes.nil?
|
171
202
|
xcodes || get_seedlist
|
172
203
|
end
|
204
|
+
|
205
|
+
def xcode_license_approved?
|
206
|
+
!(`/usr/bin/xcrun clang 2>&1` =~ /license/ && !$?.success?)
|
207
|
+
end
|
173
208
|
end
|
174
209
|
|
175
210
|
class InstalledXcode
|
@@ -194,12 +229,19 @@ module XcodeInstall
|
|
194
229
|
attr_reader :name
|
195
230
|
attr_reader :path
|
196
231
|
attr_reader :url
|
232
|
+
attr_reader :version
|
197
233
|
|
198
234
|
def initialize(json)
|
199
235
|
@dateModified = json['dateModified'].to_i
|
200
236
|
@name = json['name'].gsub(/^Xcode /, '')
|
201
237
|
@path = json['files'].first['remotePath']
|
202
238
|
@url = "https://developer.apple.com/devcenter/download.action?path=#{@path}"
|
239
|
+
|
240
|
+
begin
|
241
|
+
@version = Gem::Version.new(@name.split(' ')[0])
|
242
|
+
rescue
|
243
|
+
@version = Installer::MINIMUM_VERSION
|
244
|
+
end
|
203
245
|
end
|
204
246
|
|
205
247
|
def self.new_prelease(version, url)
|
@@ -208,4 +250,4 @@ module XcodeInstall
|
|
208
250
|
'files' => [{'remotePath' => url.split('=').last}]})
|
209
251
|
end
|
210
252
|
end
|
211
|
-
end
|
253
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module XcodeInstall
|
2
|
+
class Command
|
3
|
+
class Cleanup < Command
|
4
|
+
self.command = 'cleanup'
|
5
|
+
self.summary = 'Cleanup cached downloads.'
|
6
|
+
|
7
|
+
def run
|
8
|
+
installer = XcodeInstall::Installer.new
|
9
|
+
return if installer.cache_dir.nil? || installer.cache_dir.to_s.length < 5
|
10
|
+
FileUtils.rm_f(Dir.glob("#{installer.cache_dir}/*"))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -8,9 +8,17 @@ module XcodeInstall
|
|
8
8
|
CLAide::Argument.new('VERSION', :true),
|
9
9
|
]
|
10
10
|
|
11
|
+
def self.options
|
12
|
+
[['--no-switch', 'Don’t switch to this version after installation'],
|
13
|
+
['--no-clean', 'Don’t delete DMG after installation.']].concat(super)
|
14
|
+
end
|
15
|
+
|
11
16
|
def initialize(argv)
|
12
17
|
@installer = Installer.new
|
13
18
|
@version = argv.shift_argument
|
19
|
+
@should_clean = argv.flag?('clean', true)
|
20
|
+
@should_switch = argv.flag?('switch', true)
|
21
|
+
super
|
14
22
|
end
|
15
23
|
|
16
24
|
def validate!
|
@@ -22,8 +30,8 @@ module XcodeInstall
|
|
22
30
|
dmgPath = @installer.download(@version)
|
23
31
|
raise Informative, "Failed to download Xcode #{@version}." if dmgPath.nil?
|
24
32
|
|
25
|
-
@installer.install_dmg(dmgPath, "-#{@version}")
|
33
|
+
@installer.install_dmg(dmgPath, "-#{@version.split(' ')[0]}", @should_switch, @should_clean)
|
26
34
|
end
|
27
35
|
end
|
28
36
|
end
|
29
|
-
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"active": true,
|
3
|
+
"availableInMemberSite": true,
|
4
|
+
"categories": [
|
5
|
+
{
|
6
|
+
"active": null,
|
7
|
+
"dateCreated": 1052825460000,
|
8
|
+
"dateModified": 1079108316000,
|
9
|
+
"enabled": true,
|
10
|
+
"id": 187,
|
11
|
+
"name": "Developer Tools",
|
12
|
+
"sortOrder": 28
|
13
|
+
}
|
14
|
+
],
|
15
|
+
"dateAvailable": null,
|
16
|
+
"dateCreated": 1425695047000,
|
17
|
+
"dateDisabled": null,
|
18
|
+
"dateModified": 1425943753000,
|
19
|
+
"description": "This is the complete Xcode developer toolset for Mac, iPhone, and iPad. It includes the Xcode IDE, iOS Simulator, and all required tools and frameworks for building OS X and iOS apps.",
|
20
|
+
"files": [
|
21
|
+
{
|
22
|
+
"active": true,
|
23
|
+
"dateCreated": 1425696402000,
|
24
|
+
"dateModified": 1425929405000,
|
25
|
+
"fileSize": 2778059898,
|
26
|
+
"format": {
|
27
|
+
"active": null,
|
28
|
+
"dateCreated": 1066327569000,
|
29
|
+
"dateModified": null,
|
30
|
+
"description": "Disk Image",
|
31
|
+
"extension": ".dmg",
|
32
|
+
"id": 12
|
33
|
+
},
|
34
|
+
"id": 35240,
|
35
|
+
"name": "Xcode 6.3",
|
36
|
+
"remotePath": "/Developer_Tools/Xcode_6.2/Xcode_6.2.dmg",
|
37
|
+
"sortOrder": null,
|
38
|
+
"state": "ENABLED"
|
39
|
+
}
|
40
|
+
],
|
41
|
+
"id": 23600,
|
42
|
+
"name": "Xcode 6.3",
|
43
|
+
"prerelease": false,
|
44
|
+
"releasedSeed": true,
|
45
|
+
"state": "ENABLED"
|
46
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
module XcodeInstall
|
4
|
+
describe Command::Install do
|
5
|
+
before do
|
6
|
+
Installer.any_instance.stubs(:exists).returns(true)
|
7
|
+
Installer.any_instance.stubs(:installed).returns([])
|
8
|
+
fixture = Pathname.new('spec/fixtures/xcode_63.json').read
|
9
|
+
xcode = Xcode.new(JSON.parse(fixture))
|
10
|
+
Installer.any_instance.stubs(:seedlist).returns([xcode])
|
11
|
+
end
|
12
|
+
|
13
|
+
it "downloads and installs" do
|
14
|
+
Installer.any_instance.expects(:download).with("6.3").returns("/some/path")
|
15
|
+
Installer.any_instance.expects(:install_dmg).with("/some/path", "-6.3", true, true)
|
16
|
+
Command::Install.run(["6.3"])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "downloads and installs and does not switch if --no-switch given" do
|
20
|
+
Installer.any_instance.expects(:download).with("6.3").returns("/some/path")
|
21
|
+
Installer.any_instance.expects(:install_dmg).with("/some/path", "-6.3", false, true)
|
22
|
+
Command::Install.run(["6.3", "--no-switch"])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/spec/json_spec.rb
CHANGED
@@ -16,6 +16,7 @@ module XcodeInstall
|
|
16
16
|
installer = Installer.new
|
17
17
|
|
18
18
|
seedlist = installer.send(:parse_seedlist, JSON.parse(fixture))
|
19
|
+
installer.stubs(:installed_versions).returns([])
|
19
20
|
installer.stubs(:xcodes).returns(seedlist)
|
20
21
|
|
21
22
|
installer.list.should == "6.1\n6.1.1\n6.2"
|
data/spec/spec_helper.rb
CHANGED
@@ -6,6 +6,9 @@ ROOT = Pathname.new(File.expand_path('../../', __FILE__))
|
|
6
6
|
$:.unshift((ROOT + 'lib').to_s)
|
7
7
|
$:.unshift((ROOT + 'spec').to_s)
|
8
8
|
|
9
|
+
ENV['DELIVER_USER'] = "xcode-install"
|
10
|
+
ENV['DELIVER_PASSWORD'] = "12345password"
|
11
|
+
|
9
12
|
require 'bundler/setup'
|
10
13
|
require 'bacon'
|
11
14
|
require 'mocha-on-bacon'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xcode-install
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boris Bügling
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- Rakefile
|
97
97
|
- bin/xcode-install
|
98
98
|
- lib/xcode/install.rb
|
99
|
+
- lib/xcode/install/cleanup.rb
|
99
100
|
- lib/xcode/install/command.rb
|
100
101
|
- lib/xcode/install/install.rb
|
101
102
|
- lib/xcode/install/installed.rb
|
@@ -104,7 +105,9 @@ files:
|
|
104
105
|
- lib/xcode/install/update.rb
|
105
106
|
- lib/xcode/install/version.rb
|
106
107
|
- spec/fixtures/xcode.json
|
108
|
+
- spec/fixtures/xcode_63.json
|
107
109
|
- spec/fixtures/yolo.json
|
110
|
+
- spec/install_spec.rb
|
108
111
|
- spec/json_spec.rb
|
109
112
|
- spec/spec_helper.rb
|
110
113
|
- xcode-install.gemspec
|
@@ -134,7 +137,9 @@ specification_version: 4
|
|
134
137
|
summary: Xcode installation manager.
|
135
138
|
test_files:
|
136
139
|
- spec/fixtures/xcode.json
|
140
|
+
- spec/fixtures/xcode_63.json
|
137
141
|
- spec/fixtures/yolo.json
|
142
|
+
- spec/install_spec.rb
|
138
143
|
- spec/json_spec.rb
|
139
144
|
- spec/spec_helper.rb
|
140
145
|
has_rdoc:
|