lib/xcode/install.rb in xcode-install-2.1.1 vs lib/xcode/install.rb in xcode-install-2.2.0
- old
+ new
@@ -18,20 +18,29 @@
uri = URI.parse(url)
output ||= File.basename(uri.path)
output = (Pathname.new(directory) + Pathname.new(output)) if directory
+ retry_options = ['--retry', '3']
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
+ command = ['curl', *options, *retry_options, '--location', '--continue-at', '-', progress, '--output', output, url].map(&:to_s)
- result = $?.exitstatus == 0
+ # Run the curl command in a loop, retry when curl exit status is 18
+ # "Partial file. Only a part of the file was transferred."
+ # https://curl.haxx.se/mail/archive-2008-07/0098.html
+ # https://github.com/KrauseFx/xcode-install/issues/210
+ 3.times do
+ io = IO.popen(command)
+ io.each { |line| puts line }
+ io.close
+ exit_code = $?.exitstatus
+ return exit_code.zero? unless exit_code == 18
+ end
+ false
+ ensure
FileUtils.rm_f(COOKIES_PATH)
- result
end
end
class Installer
attr_reader :xcodes
@@ -111,11 +120,11 @@
`sudo -p "#{prompt}" ditto "#{source}" "#{xcode_path}"`
`umount "/Volumes/Xcode"`
end
unless verify_integrity(xcode_path)
- `sudo rm -f #{xcode_path}`
+ `sudo rm -rf #{xcode_path}`
return
end
enable_developer_mode
xcode = InstalledXcode.new(xcode_path)
@@ -249,11 +258,11 @@
search: 'false').body)
names = @xcodes.map(&:name)
@xcodes += prereleases.reject { |pre| names.include?(pre.name) }
- File.open(LIST_FILE, 'w') do |f|
+ File.open(LIST_FILE, 'wb') do |f|
f << Marshal.dump(xcodes)
end
xcodes
end
@@ -296,15 +305,15 @@
link + [nil]
end
end
links = links.map { |pre| Xcode.new_prerelease(pre[2].strip.gsub(/.*Xcode /, ''), pre[0], pre[3]) }
- if links.count == 0
+ if links.count.zero?
rg = %r{platform-title.*Xcode.* beta.*<\/p>}
scan = body.scan(rg)
- if scan.count == 0
+ if scan.count.zero?
rg = %r{Xcode.* GM.*<\/p>}
scan = body.scan(rg)
end
return [] if scan.empty?
@@ -323,18 +332,18 @@
xcodes || fetch_seedlist
end
def verify_integrity(path)
puts `/usr/sbin/spctl --assess --verbose=4 --type execute #{path}`
- $?.exitstatus == 0
+ $?.exitstatus.zero?
end
def hdiutil(*args)
io = IO.popen(['hdiutil', *args])
result = io.read
io.close
- unless $?.exitstatus == 0
+ unless $?.exitstatus.zero?
file_path = args[-1]
if `file -b #{file_path}`.start_with?('HTML')
fail Informative, "Failed to mount #{file_path}, logging into your account from a browser should tell you what is going wrong."
end
fail Informative, 'Failed to invoke hdiutil.'
@@ -377,17 +386,17 @@
s.version == version
end
end
end
- def download
- result = Curl.new.fetch(source, CACHE_DIR)
+ def download(progress)
+ result = Curl.new.fetch(source, CACHE_DIR, nil, nil, progress)
result ? dmg_path : nil
end
- def install
- download unless dmg_path.exist?
+ def install(progress)
+ download(progress)
prepare_package unless pkg_path.exist?
puts "Please authenticate to install #{name}..."
`sudo installer -pkg #{pkg_path} -target /`
fail Informative, "Could not install #{name}, please try again" unless installed?
source_receipts_dir = '/private/var/db/receipts'
@@ -489,15 +498,23 @@
def available_simulators
@available_simulators ||= JSON.parse(`curl -Ls #{downloadable_index_url} | plutil -convert json -o - -`)['downloadables'].map do |downloadable|
Simulator.new(downloadable)
end
+ rescue JSON::ParserError
+ return []
end
def install_components
- Dir.glob("#{@path}/Contents/Resources/Packages/*.pkg").each do |pkg|
- `sudo installer -pkg #{pkg} -target /`
+ # starting with Xcode 9, we have `xcodebuild -runFirstLaunch` available to do package
+ # postinstalls using a documented option
+ if Gem::Version.new(@version) >= Gem::Version.new('9')
+ `sudo #{@path}/Contents/Developer/usr/bin/xcodebuild -runFirstLaunch`
+ else
+ Dir.glob("#{@path}/Contents/Resources/Packages/*.pkg").each do |pkg|
+ `sudo installer -pkg #{pkg} -target /`
+ end
end
osx_build_version = `sw_vers -buildVersion`.chomp
tools_version = `/usr/libexec/PlistBuddy -c "Print :ProductBuildVersion" "#{@path}/Contents/version.plist"`.chomp
cache_dir = `getconf DARWIN_USER_CACHE_DIR`.chomp
`touch #{cache_dir}com.apple.dt.Xcode.InstallCheckCache_#{osx_build_version}_#{tools_version}`
@@ -509,10 +526,10 @@
`/usr/libexec/PlistBuddy -c "Print :#{keypath}" "#{path}/Contents/Info.plist"`.chomp
end
def fetch_version
output = `DEVELOPER_DIR='' "#{@path}/Contents/Developer/usr/bin/xcodebuild" -version`
- return '0.0' if output.nil? # ¯\_(ツ)_/¯
+ return '0.0' if output.nil? || output.empty? # ¯\_(ツ)_/¯
output.split("\n").first.split(' ')[1]
end
end
class Xcode