lib/xcode/install.rb in xcode-install-1.1.0 vs lib/xcode/install.rb in xcode-install-1.2.0
- old
+ new
@@ -1,7 +1,8 @@
require 'fileutils'
require 'pathname'
+require 'rexml/document'
require 'spaceship'
require 'json'
require 'rubygems/version'
require 'xcode/install/command'
require 'xcode/install/version'
@@ -10,24 +11,25 @@
CACHE_DIR = Pathname.new("#{ENV['HOME']}/Library/Caches/XcodeInstall")
class Curl
COOKIES_PATH = Pathname.new('/tmp/curl-cookies.txt')
def fetch(url, directory = nil, cookies = nil, output = nil, progress = true)
- options = cookies.nil? ? '' : "-b '#{cookies}' -c #{COOKIES_PATH}"
- # options += ' -vvv'
+ options = cookies.nil? ? [] : ['--cookie', cookies, '--cookie-jar', COOKIES_PATH]
+ # options << ' -vvv'
uri = URI.parse(url)
output ||= File.basename(uri.path)
output = (Pathname.new(directory) + Pathname.new(output)) if directory
- progress = progress ? '-#' : '-s'
- command = "curl #{options} -L -C - #{progress} -o #{output} #{url}"
- IO.popen(command).each do |fd|
- puts(fd)
- end
- result = $CHILD_STATUS.to_i == 0
+ progress = progress ? '--progress-bar' : '--silent'
+ command = ['curl', *options, '--location', '--continue-at', '-', progress, '--output', output, url].map(&:to_s)
+ io = IO.popen(command)
+ io.each { |line| puts line }
+ io.close
+ result = $?.exitstatus == 0
+
FileUtils.rm_f(COOKIES_PATH)
result
end
end
@@ -67,31 +69,31 @@
installed.map { |x| InstalledXcode.new(x) }.sort do |a, b|
Gem::Version.new(a.version) <=> Gem::Version.new(b.version)
end
end
- def install_dmg(dmgPath, suffix = '', switch = true, clean = true)
+ def install_dmg(dmg_path, suffix = '', switch = true, clean = true)
xcode_path = "/Applications/Xcode#{suffix}.app"
- `hdiutil mount -nobrowse -noverify #{dmgPath}`
+ mount_dir = mount(dmg_path)
puts 'Please authenticate for Xcode installation...'
- source = Dir.glob('/Volumes/Xcode/Xcode*.app').first
+ source = Dir.glob(File.join(mount_dir, 'Xcode*.app')).first
if source.nil?
- out <<-HELP
-No `Xcode.app` found in DMG. Please remove #{dmgPath} if you suspect a corrupted
+ out = <<-HELP
+No `Xcode.app` found in DMG. Please remove #{dmg_path} if you suspect a corrupted
download or run `xcversion update` to see if the version you tried to install
has been pulled by Apple. If none of this is true, please open a new GH issue.
HELP
- $stderr.puts out.gsub("\n", ' ')
+ $stderr.puts out.tr("\n", ' ')
return
end
`sudo ditto "#{source}" "#{xcode_path}"`
`umount "/Volumes/Xcode"`
- if not verify_integrity(xcode_path)
+ unless verify_integrity(xcode_path)
`sudo rm -f #{xcode_path}`
return
end
enable_developer_mode
@@ -105,11 +107,11 @@
`sudo xcode-select --switch #{xcode_path}`
puts `xcodebuild -version`
end
- FileUtils.rm_f(dmgPath) if clean
+ FileUtils.rm_f(dmg_path) if clean
end
def install_version(version, switch = true, clean = true, install = true, progress = true, url = nil)
dmg_path = get_dmg(version, progress, url)
fail Informative, "Failed to download Xcode #{version}." if dmg_path.nil?
@@ -152,11 +154,11 @@
private
def spaceship
@spaceship ||= begin
begin
- Spaceship.login(ENV["XCODE_INSTALL_USER"], ENV["XCODE_INSTALL_PASSWORD"])
+ Spaceship.login(ENV['XCODE_INSTALL_USER'], ENV['XCODE_INSTALL_PASSWORD'])
rescue Spaceship::Client::InvalidUserCredentialsError
$stderr.puts 'The specified Apple developer account credentials are incorrect.'
exit(1)
rescue Spaceship::Client::NoUserCredentialsError
$stderr.puts <<-HELP
@@ -164,12 +166,12 @@
XCODE_INSTALL_USER and XCODE_INSTALL_PASSWORD environment variables.
HELP
exit(1)
end
- if ENV.key?("XCODE_INSTALL_TEAM_ID")
- Spaceship.client.team_id = ENV["XCODE_INSTALL_TEAM_ID"]
+ if ENV.key?('XCODE_INSTALL_TEAM_ID')
+ Spaceship.client.team_id = ENV['XCODE_INSTALL_TEAM_ID']
end
Spaceship.client
end
end
@@ -194,19 +196,19 @@
download(version, progress, url)
end
def fetch_seedlist
- @xcodes = parse_seedlist(spaceship.send(:request, :get, '/services-account/QH65B2/downloadws/listDownloads.action', {
- start: "0",
- limit: "1000",
- sort: "dateModified",
- dir: "DESC",
- searchTextField: "",
- searchCategories: "",
- search: "false",
- }).body)
+ @xcodes = parse_seedlist(spaceship.send(:request, :get,
+ '/services-account/QH65B2/downloadws/listDownloads.action',
+ start: '0',
+ limit: '1000',
+ sort: 'dateModified',
+ dir: 'DESC',
+ searchTextField: '',
+ searchCategories: '',
+ search: 'false').body)
names = @xcodes.map(&:name)
@xcodes += prereleases.reject { |pre| names.include?(pre.name) }
File.open(LIST_FILE, 'w') do |f|
@@ -241,19 +243,19 @@
installed = installed_versions.map(&:version)
seedlist.map(&:name).reject { |x| installed.include?(x) }
end
def prereleases
- body=spaceship.send(:request, :get, '/xcode/download/').body
- links=body.scan(/<a.+?href="(.+?.dmg)".*>(.*)<\/a>/)
+ body = spaceship.send(:request, :get, '/xcode/download/').body
+ links = body.scan(%r{<a.+?href="(.+?.dmg)".*>(.*)</a>})
links = links.map do |link|
- parent = link[0].scan(/path=(\/.*\/.*\/)/).first.first
+ parent = link[0].scan(%r{path=(/.*/.*/)}).first.first
match = body.scan(/#{Regexp.quote(parent)}(.+?.pdf)/).first
if match
- link += [parent + match.first]
+ link + [parent + match.first]
else
- link += [nil]
+ link + [nil]
end
end
links.map { |pre| Xcode.new_prerelease(pre[1].strip.gsub(/.*Xcode /, ''), pre[0], pre[2]) }
end
@@ -264,10 +266,26 @@
def verify_integrity(path)
puts `/usr/sbin/spctl --assess --verbose=4 --type execute #{path}`
$?.exitstatus == 0
end
+
+ def hdiutil(*args)
+ io = IO.popen(['hdiutil', *args])
+ result = io.read
+ io.close
+ fail Informative, 'Failed to invoke hdiutil.' unless $?.exitstatus == 0
+ result
+ end
+
+ def mount(dmg_path)
+ plist = hdiutil('mount', '-plist', '-nobrowse', '-noverify', dmg_path.to_s)
+ document = REXML::Document.new(plist)
+ node = REXML::XPath.first(document, "//key[.='mount-point']/following-sibling::*[1]")
+ fail Informative, 'Failed to mount image.' unless node
+ node.text
+ end
end
class Simulator
attr_reader :version
attr_reader :name
@@ -325,11 +343,11 @@
:private
def prepare_package
puts 'Mounting DMG'
- mount_location = `hdiutil mount -nobrowse -noverify #{dmg_path}`.scan(/\/Volumes.*\n/).first.chomp
+ mount_location = mount(dmg_path)
puts 'Expanding pkg'
expanded_pkg_path = CACHE_DIR + identifier
FileUtils.rm_rf(expanded_pkg_path)
`pkgutil --expand #{mount_location}/*.pkg #{expanded_pkg_path}`
puts "Expanded pkg into #{expanded_pkg_path}"
@@ -380,11 +398,11 @@
def initialize(path)
@path = Pathname.new(path)
end
def version
- @version ||= get_version
+ @version ||= fetch_version
end
def bundle_version
@bundle_version ||= Gem::Version.new(plist_entry(':DTXcode').to_i.to_s.split(//).join('.'))
end
@@ -424,11 +442,11 @@
def plist_entry(keypath)
`/usr/libexec/PlistBuddy -c "Print :#{keypath}" "#{path}/Contents/Info.plist"`.chomp
end
- def get_version
+ def fetch_version
output = `DEVELOPER_DIR='' "#{@path}/Contents/Developer/usr/bin/xcodebuild" -version`
return '0.0' if output.nil? # ¯\_(ツ)_/¯
output.split("\n").first.split(' ')[1]
end
end
@@ -465,10 +483,9 @@
url == other.url && version == other.version
end
def self.new_prerelease(version, url, release_notes_path)
new('name' => version,
- 'dateModified' => Time.now.to_i,
'files' => [{ 'remotePath' => url.split('=').last }],
'release_notes_path' => release_notes_path)
end
end
end