Skip to content

Commit

Permalink
Parse hdiutil output (fixes xcpretty#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcljx committed Nov 5, 2015
1 parent ce348b0 commit 7ea94a4
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 31 deletions.
25 changes: 20 additions & 5 deletions lib/xcode/install.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'fileutils'
require 'pathname'
require 'rexml/document'
require 'spaceship'
require 'json'
require 'rubygems/version'
Expand Down Expand Up @@ -69,16 +70,16 @@ def installed_versions
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
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
Expand Down Expand Up @@ -266,6 +267,20 @@ def verify_integrity(path)
puts `/usr/sbin/spctl --assess --verbose=4 --type execute #{path}`
$?.exitstatus == 0
end

def hdiutil(*args)
result = IO.popen(['hdiutil', *args]).read
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
Expand Down Expand Up @@ -327,7 +342,7 @@ def install

def prepare_package
puts 'Mounting DMG'
mount_location = `hdiutil mount -nobrowse -noverify #{dmg_path}`.scan(%r{/Volumes.*\n}).first.chomp
mount_location = mount(dmg_path)
puts 'Expanding pkg'
expanded_pkg_path = CACHE_DIR + identifier
FileUtils.rm_rf(expanded_pkg_path)
Expand Down
31 changes: 31 additions & 0 deletions spec/fixtures/hdiutil.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<plist version="1.0">
<dict>
<key>system-entities</key>
<array>
<dict>
<key>content-hint</key>
<string>GUID_partition_scheme</string>
<key>dev-entry</key>
<string>/dev/disk2</string>
<key>potentially-mountable</key>
<false/>
<key>unmapped-content-hint</key>
<string>GUID_partition_scheme</string>
</dict>
<dict>
<key>content-hint</key>
<string>Apple_HFS</string>
<key>dev-entry</key>
<string>/dev/disk2s1</string>
<key>mount-point</key>
<string>/Volumes/XcodeME</string>
<key>potentially-mountable</key>
<true/>
<key>unmapped-content-hint</key>
<string>48465300-0000-11AA-AA11-00306543ECAC</string>
<key>volume-kind</key>
<string>hfs</string>
</dict>
</array>
</dict>
</plist>
62 changes: 36 additions & 26 deletions spec/install_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,47 @@

module XcodeInstall
describe Command::Install do
before do
Installer.any_instance.stubs(:exists).returns(true)
Installer.any_instance.stubs(:installed).returns([])
fixture = Pathname.new('spec/fixtures/xcode_63.json').read
xcode = Xcode.new(JSON.parse(fixture))
Installer.any_instance.stubs(:seedlist).returns([xcode])
end
describe "when invoked" do
before do
Installer.any_instance.stubs(:exists).returns(true)
Installer.any_instance.stubs(:installed).returns([])
fixture = Pathname.new('spec/fixtures/xcode_63.json').read
xcode = Xcode.new(JSON.parse(fixture))
Installer.any_instance.stubs(:seedlist).returns([xcode])
end

it 'downloads and installs' do
Installer.any_instance.expects(:download).with('6.3', true, nil).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
Command::Install.run(['6.3'])
end
it 'downloads and installs' do
Installer.any_instance.expects(:download).with('6.3', true, nil).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
Command::Install.run(['6.3'])
end

it 'downloads and installs with custom HTTP URL' do
url = 'http://yolo.com/xcode.dmg'
Installer.any_instance.expects(:download).with('6.3', true, url).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
Command::Install.run(['6.3', "--url=#{url}"])
end
it 'downloads and installs with custom HTTP URL' do
url = 'http://yolo.com/xcode.dmg'
Installer.any_instance.expects(:download).with('6.3', true, url).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
Command::Install.run(['6.3', "--url=#{url}"])
end

it 'downloads and installs and does not switch if --no-switch given' do
Installer.any_instance.expects(:download).with('6.3', true, nil).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', false, true)
Command::Install.run(['6.3', '--no-switch'])
end

it 'downloads and installs and does not switch if --no-switch given' do
Installer.any_instance.expects(:download).with('6.3', true, nil).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', false, true)
Command::Install.run(['6.3', '--no-switch'])
it 'downloads without progress if switch --no-progress is given' do
Installer.any_instance.expects(:download).with('6.3', false, nil).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
Command::Install.run(['6.3', '--no-progress'])
end
end

it 'downloads without progress if switch --no-progress is given' do
Installer.any_instance.expects(:download).with('6.3', false, nil).returns('/some/path')
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
Command::Install.run(['6.3', '--no-progress'])
it 'parses hdiutil output' do
installer = Installer.new
fixture = Pathname.new('spec/fixtures/hdiutil.plist').read
installer.expects(:hdiutil).with('mount', '-plist', '-nobrowse', '-noverify', '/some/path').returns(fixture)
location = installer.send(:mount, Pathname.new('/some/path'))
location.should == '/Volumes/XcodeME'
end
end
end

0 comments on commit 7ea94a4

Please sign in to comment.