dmg 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/dmg.gemspec +5 -1
- data/features/dmg.feature +14 -0
- data/features/support/env.rb +23 -0
- data/lib/dmg.rb +47 -3
- data/lib/dmg/cli.rb +22 -12
- data/lib/dmg/output_helpers.rb +54 -0
- data/lib/dmg/pkg.rb +69 -24
- data/lib/dmg/pkgs.yml +12 -20
- data/lib/dmg/source.rb +66 -0
- data/lib/dmg/version.rb +1 -1
- data/spec/data/pkgs_1.yml +22 -0
- data/spec/data/pkgs_2.yml +24 -0
- data/spec/lib/pkg_spec.rb +106 -0
- data/spec/lib/sources_spec.rb +40 -0
- data/spec/spec_helper.rb +16 -0
- metadata +65 -9
data/Gemfile
CHANGED
data/dmg.gemspec
CHANGED
@@ -8,12 +8,16 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Philippe Creux"]
|
10
10
|
s.email = ["pcreux@gmail.com"]
|
11
|
-
s.homepage = ""
|
11
|
+
s.homepage = "https://github.com/versapay/dmg"
|
12
12
|
s.summary = %q{Install popular applications provided as dmgs from the command line}
|
13
13
|
s.description = %q{It's like apt-get for Mac}
|
14
14
|
|
15
15
|
s.default_executable = %q{dmg}
|
16
16
|
|
17
|
+
s.add_development_dependency 'rspec'
|
18
|
+
s.add_development_dependency 'cucumber'
|
19
|
+
s.add_development_dependency 'aruba'
|
20
|
+
|
17
21
|
s.files = `git ls-files`.split("\n")
|
18
22
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
23
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: dmg
|
2
|
+
|
3
|
+
In order to install dmgs via the command line
|
4
|
+
As a Mac user
|
5
|
+
I want to type dmg install chrome and it should just work!
|
6
|
+
|
7
|
+
Scenario: Run dmg for the first time
|
8
|
+
When I run "dmg list"
|
9
|
+
Then the output should contain "chrome"
|
10
|
+
Then the file ".dmg/sources.yml" should contain:
|
11
|
+
"""
|
12
|
+
- https://github.com/pcreux/dmg-pkgs/raw/master/pkgs.yml
|
13
|
+
"""
|
14
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
Bundler.require
|
5
|
+
|
6
|
+
require 'aruba/cucumber'
|
7
|
+
|
8
|
+
# Following from 'aruba/cucumber'
|
9
|
+
Before do
|
10
|
+
@__aruba_original_paths = (ENV['PATH'] || '').split(File::PATH_SEPARATOR)
|
11
|
+
ENV['PATH'] = ([File.expand_path('bin')] + @__aruba_original_paths).join(File::PATH_SEPARATOR)
|
12
|
+
ENV['DMG_HOME'] = File.join(File.dirname(__FILE__), '..', '..', 'tmp', 'aruba')
|
13
|
+
end
|
14
|
+
|
15
|
+
After do
|
16
|
+
ENV['PATH'] = @__aruba_original_paths.join(File::PATH_SEPARATOR)
|
17
|
+
end
|
18
|
+
# End of following from 'aruba/cucumber'
|
19
|
+
|
20
|
+
Then /^the file "([^"]*)" should contain:$/ do |file, exact_content|
|
21
|
+
check_file_content(file, exact_content, true)
|
22
|
+
end
|
23
|
+
|
data/lib/dmg.rb
CHANGED
@@ -1,7 +1,51 @@
|
|
1
|
-
module DMG; end
|
2
|
-
|
3
1
|
require 'yaml'
|
4
2
|
|
5
|
-
|
3
|
+
module DMG
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def home_dir
|
7
|
+
ENV['DMG_HOME'] || ENV['HOME']
|
8
|
+
end
|
9
|
+
|
10
|
+
def config_dir
|
11
|
+
File.join(home_dir, '.dmg')
|
12
|
+
end
|
13
|
+
|
14
|
+
def sources_file
|
15
|
+
File.join(config_dir, 'sources.yml')
|
16
|
+
end
|
17
|
+
|
18
|
+
def combined_pkgs_file
|
19
|
+
File.join(config_dir, 'pkgs.yml')
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_configuration
|
23
|
+
['https://github.com/pcreux/dmg-pkgs/raw/master/pkgs.yml']
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup!
|
27
|
+
create_dmg_directory_if_needed
|
28
|
+
generate_default_source_file_if_needed
|
29
|
+
download_sources
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_dmg_directory_if_needed
|
33
|
+
unless File.directory?(config_dir)
|
34
|
+
Dir::mkdir(config_dir)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def generate_default_source_file_if_needed
|
39
|
+
unless File.exists? sources_file
|
40
|
+
File.open(sources_file, 'w') { |f| f.write default_configuration.to_yaml }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def download_sources
|
45
|
+
DMG::Source.download_and_combine
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
%w{errors output_helpers source pkg cli}.each do |file|
|
6
50
|
require File.dirname(__FILE__) + "/dmg/#{file}"
|
7
51
|
end
|
data/lib/dmg/cli.rb
CHANGED
@@ -1,16 +1,26 @@
|
|
1
1
|
class DMG::CLI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
DMG
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
class << self
|
3
|
+
include OutputHelpers
|
4
|
+
|
5
|
+
def run!
|
6
|
+
|
7
|
+
DMG.setup!
|
8
|
+
|
9
|
+
case ARGV[0]
|
10
|
+
when "install"
|
11
|
+
DMG::Pkg.install(ARGV[1..-1])
|
12
|
+
when "list"
|
13
|
+
puts DMG::Pkg.list
|
14
|
+
else
|
15
|
+
puts <<-EOF
|
16
|
+
Usage:
|
17
|
+
dmg install PACKAGE
|
18
|
+
dmg list
|
19
|
+
EOF
|
20
|
+
end
|
21
|
+
|
22
|
+
rescue DMG::DMGError => e
|
23
|
+
alert(e.message)
|
14
24
|
end
|
15
25
|
end
|
16
26
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module OutputHelpers
|
2
|
+
def info(text)
|
3
|
+
puts Output.green(text)
|
4
|
+
end
|
5
|
+
|
6
|
+
def debug(text)
|
7
|
+
puts Output.grey(text)
|
8
|
+
end
|
9
|
+
|
10
|
+
def alert(text)
|
11
|
+
puts Output.red(text)
|
12
|
+
end
|
13
|
+
|
14
|
+
module Output
|
15
|
+
|
16
|
+
extend self
|
17
|
+
|
18
|
+
def color(text, color_code)
|
19
|
+
"#{color_code}#{text}\e[0m"
|
20
|
+
end
|
21
|
+
|
22
|
+
def bold(text)
|
23
|
+
color(text, "\e[1m")
|
24
|
+
end
|
25
|
+
|
26
|
+
def white(text)
|
27
|
+
color(text, "\e[37m")
|
28
|
+
end
|
29
|
+
|
30
|
+
def green(text)
|
31
|
+
color(text, "\e[32m")
|
32
|
+
end
|
33
|
+
|
34
|
+
def red(text)
|
35
|
+
color(text, "\e[31m")
|
36
|
+
end
|
37
|
+
|
38
|
+
def magenta(text)
|
39
|
+
color(text, "\e[35m")
|
40
|
+
end
|
41
|
+
|
42
|
+
def yellow(text)
|
43
|
+
color(text, "\e[33m")
|
44
|
+
end
|
45
|
+
|
46
|
+
def blue(text)
|
47
|
+
color(text, "\e[34m")
|
48
|
+
end
|
49
|
+
|
50
|
+
def grey(text)
|
51
|
+
color(text, "\e[90m")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/dmg/pkg.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module DMG
|
2
2
|
class Pkg
|
3
3
|
def self.list
|
4
|
-
|
4
|
+
all.map(&:name).sort
|
5
5
|
end
|
6
6
|
|
7
7
|
def self.install(pkg_names)
|
@@ -9,53 +9,98 @@ module DMG
|
|
9
9
|
pkgs.each(&:install!)
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.
|
13
|
-
|
14
|
-
|
15
|
-
pkgs = YAML.load_file(File.dirname(__FILE__) + '/pkgs.yml')
|
16
|
-
pkgs.each do |key, values|
|
17
|
-
@@all << Pkg.new({'name' => key}.merge(values))
|
18
|
-
end
|
12
|
+
def self.find!(pkg_name)
|
13
|
+
pkg = all.select { |pkg| pkg.name == pkg_name }.first
|
14
|
+
raise PackageNotFound, "Can't find a package called '#{pkg_name}'" unless pkg
|
19
15
|
|
20
|
-
|
16
|
+
pkg
|
21
17
|
end
|
22
18
|
|
23
|
-
attr_reader :name, :package, :url, :volume_dir
|
19
|
+
attr_reader :name, :package, :url, :volume_dir, :mpkg
|
24
20
|
|
25
21
|
def initialize(args)
|
26
22
|
@name = args['name']
|
27
23
|
@package = args['package']
|
28
24
|
@url = args['url']
|
29
25
|
@volume_dir = args['volume_dir'] || @package
|
26
|
+
@mpkg = args['mpkg']
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def self.all
|
32
|
+
return @@all if defined?(@@all)
|
33
|
+
@@all = []
|
34
|
+
hash_from_yaml.each do |key, values|
|
35
|
+
@@all << Pkg.new({'name' => key}.merge(values))
|
36
|
+
end
|
37
|
+
|
38
|
+
@@all
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.hash_from_yaml
|
42
|
+
YAML.load_file(File.dirname(__FILE__) + '/pkgs.yml')
|
30
43
|
end
|
31
44
|
|
45
|
+
include OutputHelpers
|
46
|
+
|
32
47
|
def install!
|
33
|
-
|
34
|
-
|
48
|
+
if downloaded?
|
49
|
+
info "#{name} already downloaded in #{dmg_file}"
|
50
|
+
else
|
51
|
+
download
|
52
|
+
end
|
35
53
|
|
36
|
-
|
37
|
-
|
38
|
-
|
54
|
+
mount unless mounted?
|
55
|
+
if mpkg
|
56
|
+
open_mpkg
|
57
|
+
info "I've just launched #{name} installer!"
|
58
|
+
info ""
|
59
|
+
info "Don't forget to unmount the volume once done. Just run the following command:"
|
60
|
+
info " hdiutil detach '/Volumes/#{volume_dir}'"
|
61
|
+
info ""
|
62
|
+
else
|
63
|
+
copy_app
|
64
|
+
info "#{name} is now installed!"
|
39
65
|
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def dmg_file
|
69
|
+
"#{ENV['HOME']}/Downloads/#{package}.dmg"
|
70
|
+
end
|
71
|
+
|
72
|
+
def destination
|
73
|
+
'/Applications'
|
74
|
+
end
|
75
|
+
|
76
|
+
def mounted?
|
77
|
+
!!`hdiutil info`[/image-path.*#{dmg_file}/]
|
78
|
+
end
|
79
|
+
|
80
|
+
def download
|
81
|
+
run_cmd "curl -L #{url} -o '#{dmg_file}'"
|
82
|
+
end
|
40
83
|
|
41
|
-
|
84
|
+
def mount
|
42
85
|
run_cmd "hdid '#{dmg_file}'"
|
86
|
+
end
|
87
|
+
|
88
|
+
def open_mpkg
|
89
|
+
run_cmd "open /Volumes/#{volume_dir}/#{mpkg}.mpkg"
|
90
|
+
end
|
91
|
+
|
92
|
+
def copy_app
|
43
93
|
run_cmd "sudo cp -fr '/Volumes/#{volume_dir}/#{package}.app' '#{destination}'"
|
44
94
|
run_cmd "hdiutil detach '/Volumes/#{volume_dir}'"
|
45
95
|
run_cmd "sudo chmod 755 '#{destination}/#{package}.app/Contents/MacOS/#{package}'"
|
46
96
|
end
|
47
97
|
|
48
|
-
|
49
|
-
|
50
|
-
def self.find!(pkg_name)
|
51
|
-
pkg = all.select { |pkg| pkg.name == pkg_name }.first
|
52
|
-
raise PackageNotFound, "Can't find a package called '#{pkg_name}'" unless pkg
|
53
|
-
|
54
|
-
pkg
|
98
|
+
def downloaded?
|
99
|
+
File.exist?(dmg_file)
|
55
100
|
end
|
56
101
|
|
57
102
|
def run_cmd(cmd)
|
58
|
-
|
103
|
+
debug cmd
|
59
104
|
raise DMGError, "Failed to run a command" unless system(cmd)
|
60
105
|
end
|
61
106
|
end
|
data/lib/dmg/pkgs.yml
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# Does not work because of a broken symlink in the dmg
|
2
|
+
#dropbox:
|
3
|
+
# package: Dropbox
|
4
|
+
# volume_dir: Dropbox Installer
|
5
|
+
# url: "http://www.dropbox.com/download?plat=mac"
|
5
6
|
|
6
7
|
chrome:
|
7
8
|
package: Google Chrome
|
@@ -11,25 +12,16 @@ skype:
|
|
11
12
|
package: Skype
|
12
13
|
url: http://www.skype.com/go/getskype-macosx.dmg
|
13
14
|
|
14
|
-
steam:
|
15
|
-
package: Steam
|
16
|
-
url: http://cdn.store.steampowered.com/public/client/installer/steam.dmg
|
17
|
-
|
18
|
-
macirssi:
|
19
|
-
package: MacIrssi
|
20
|
-
url: http://www.sysctl.co.uk/projects/macirssi/downloads/MacIrssi-0.8.6.6.dmg
|
21
|
-
|
22
15
|
picasa:
|
23
16
|
package: Picasa
|
24
17
|
volume_dir: Picasa 3.8.9
|
25
18
|
url: http://dl.google.com/photos/picasamac38.dmg
|
26
19
|
|
27
|
-
|
28
|
-
package:
|
29
|
-
|
30
|
-
|
20
|
+
virtualbox:
|
21
|
+
package: VirtualBox
|
22
|
+
url: http://download.virtualbox.org/virtualbox/4.0.4/VirtualBox-4.0.4-70112-OSX.dmg
|
23
|
+
mpkg: VirtualBox
|
31
24
|
|
32
|
-
|
33
|
-
package:
|
34
|
-
url: http://
|
35
|
-
|
25
|
+
launchbar:
|
26
|
+
package: LaunchBar
|
27
|
+
url: http://www.obdev.at/downloads/launchbar/LaunchBar-5.0.4.dmg
|
data/lib/dmg/source.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module DMG
|
5
|
+
class Source
|
6
|
+
class << self
|
7
|
+
def download_and_combine
|
8
|
+
combine(Source.all)
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def combine(sources)
|
14
|
+
combined_pkgs_hash = {}
|
15
|
+
|
16
|
+
sources.each do |source|
|
17
|
+
combined_pkgs_hash.merge!(source.pkgs_hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
File.open(DMG::combined_pkgs_file, 'w') { |f| f.write(combined_pkgs_hash.to_yaml) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def all
|
24
|
+
YAML.load_file(DMG::sources_file).map do |path_or_url|
|
25
|
+
Source.new(path_or_url)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end # class << self
|
29
|
+
|
30
|
+
attr_reader :pkgs_hash
|
31
|
+
|
32
|
+
def initialize(path_or_url)
|
33
|
+
@pkgs_hash = YAML.load(get(path_or_url))
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return content from path or url
|
37
|
+
def get(path_or_url)
|
38
|
+
case path_or_url
|
39
|
+
when /^http(s):\/\//
|
40
|
+
get_file(path_or_url)
|
41
|
+
else
|
42
|
+
read_file(path_or_url)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
# Get file content from a url
|
49
|
+
def get_file(url)
|
50
|
+
uri = URI.parse(url)
|
51
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
52
|
+
http.use_ssl = true if uri.port == 443
|
53
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
54
|
+
|
55
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
56
|
+
|
57
|
+
response = http.request(request)
|
58
|
+
response.body
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return file content from a path
|
62
|
+
def read_file(path)
|
63
|
+
File.read(path)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/dmg/version.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Does not work because of a broken symlink in the dmg
|
2
|
+
#dropbox:
|
3
|
+
# package: Dropbox
|
4
|
+
# volume_dir: Dropbox Installer
|
5
|
+
# url: "http://www.dropbox.com/download?plat=mac"
|
6
|
+
|
7
|
+
chrome:
|
8
|
+
package: Google Chrome
|
9
|
+
url: "https://dl-ssl.google.com/chrome/mac/stable/GGRM/googlechrome.dmg"
|
10
|
+
|
11
|
+
skype:
|
12
|
+
package: Skype
|
13
|
+
url: http://www.skype.com/go/getskype-macosx.dmg
|
14
|
+
|
15
|
+
picasa:
|
16
|
+
package: Picasa
|
17
|
+
volume_dir: Picasa 3.8.9
|
18
|
+
url: http://dl.google.com/photos/picasamac38.dmg
|
19
|
+
|
20
|
+
launchbar:
|
21
|
+
package: LaunchBar
|
22
|
+
url: http://www.obdev.at/downloads/launchbar/LaunchBar-5.0.4.dmg
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Does not work because of a broken symlink in the dmg
|
2
|
+
#dropbox:
|
3
|
+
# package: Dropbox
|
4
|
+
# volume_dir: Dropbox Installer
|
5
|
+
# url: "http://www.dropbox.com/download?plat=mac"
|
6
|
+
|
7
|
+
chrome:
|
8
|
+
package: Google Chrome
|
9
|
+
url: "https://dl-ssl.google.com/chrome/mac/stable/GGRM/googlechrome.dmg"
|
10
|
+
|
11
|
+
skype:
|
12
|
+
package: Skype
|
13
|
+
url: http://www.skype.com/go/getskype-macosx.dmg
|
14
|
+
|
15
|
+
picasa:
|
16
|
+
package: Picasa
|
17
|
+
volume_dir: Picasa 3.8.9
|
18
|
+
url: http://dl.google.com/photos/picasamac38.dmg
|
19
|
+
|
20
|
+
virtualbox:
|
21
|
+
package: VirtualBox
|
22
|
+
url: http://download.virtualbox.org/virtualbox/4.0.4/VirtualBox-4.0.4-70112-OSX.dmg
|
23
|
+
mpkg: VirtualBox
|
24
|
+
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DMG::Pkg do
|
4
|
+
before do
|
5
|
+
DMG::Pkg.stub!(:hash_from_yaml) do
|
6
|
+
{
|
7
|
+
"launchbar"=> {"url"=>"http://example.com/launchbar.dmg", "package"=>"LaunchBar"},
|
8
|
+
"virtualbox"=> {"url"=> "http://example.com/virtualbox.dmg", "package"=>"VirtualBox", "mpkg"=>"VirtualBox"},
|
9
|
+
"picasa"=> {"url"=>"http://example.com/picasa.dmg", "package"=>"Picasa", "volume_dir"=>"Picasa 3.8.9"}
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
DMG::Pkg.stub!(:install!)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "##all" do
|
17
|
+
subject { DMG::Pkg.all }
|
18
|
+
|
19
|
+
it "should return an array of DMG::Pkg" do
|
20
|
+
subject.should have(3).items
|
21
|
+
subject.each do |pkg|
|
22
|
+
pkg.should be_a(DMG::Pkg)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "one of the packages" do
|
27
|
+
subject { DMG::Pkg.all.select { |p| p.name == "launchbar" }.first }
|
28
|
+
its(:name) { should == "launchbar" }
|
29
|
+
its(:url) { should == "http://example.com/launchbar.dmg" }
|
30
|
+
its(:package) { should == "LaunchBar"}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "##list" do
|
35
|
+
subject { DMG::Pkg.list }
|
36
|
+
|
37
|
+
it "should return an array of packages names" do
|
38
|
+
subject.should be_an(Array)
|
39
|
+
subject.first.should be_a(String)
|
40
|
+
subject.sort.should == subject
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "##install" do
|
45
|
+
let(:launchbar) { DMG::Pkg.find!("launchbar") }
|
46
|
+
let(:picasa) { DMG::Pkg.find!("picasa") }
|
47
|
+
let(:virtualbox) { DMG::Pkg.find!("virtualbox") }
|
48
|
+
|
49
|
+
context "all the packages passed in exist" do
|
50
|
+
it "should call install on the packages with a name matching the ones passed in" do
|
51
|
+
launchbar.should_receive :install!
|
52
|
+
picasa.should_receive :install!
|
53
|
+
virtualbox.should_not_receive :install!
|
54
|
+
|
55
|
+
DMG::Pkg.install(%w(launchbar picasa))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "one of the package does not exist" do
|
60
|
+
it "should raise PackageNotFound" do
|
61
|
+
expect { DMG::Pkg.install(%w(launchbar coffeemaker)) }.should raise_error(DMG::PackageNotFound)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not install any package" do
|
65
|
+
launchbar.should_not_receive :install!
|
66
|
+
DMG::Pkg.install(%w(launchbar coffeemaker)) rescue nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#initialize" do
|
72
|
+
context %{when passing in { "name" => "launchbar", "url" => "http://example.com/launchbar.dmg", "package" => "LaunchBar"} } do
|
73
|
+
subject { DMG::Pkg.new({ "name" => "launchbar", "url" => "http://example.com/launchbar.dmg", "package" => "LaunchBar"}) }
|
74
|
+
|
75
|
+
its(:name) { should == "launchbar" }
|
76
|
+
its(:package) { should == "LaunchBar" }
|
77
|
+
its(:url) { should == "http://example.com/launchbar.dmg" }
|
78
|
+
its(:volume_dir) { should == "LaunchBar" }
|
79
|
+
its(:mpkg) { should be_nil }
|
80
|
+
end
|
81
|
+
|
82
|
+
context %{when passing in { "package" => "LaunchBar", "volume_dir" => "LaunchBarDMG", "mpkg" => "install.mpkg"} } do
|
83
|
+
subject { DMG::Pkg.new({ "package" => "LaunchBar", "volume_dir" => "LaunchBarDMG", "mpkg" => "install.mpkg"}) }
|
84
|
+
|
85
|
+
its(:package) { should == "LaunchBar" }
|
86
|
+
its(:volume_dir) { should == "LaunchBarDMG" }
|
87
|
+
its(:mpkg) { should == "install.mpkg" }
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when the name, package or url is missing" do
|
91
|
+
it "should raise an exception"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#install! (protected)" do
|
96
|
+
# This method runs a bunch of system commands that can only be
|
97
|
+
# tested in integration tests only
|
98
|
+
# We should refactor it as it contains a few switches:
|
99
|
+
context "when dmg not installed yet"
|
100
|
+
context "when dmg already installed"
|
101
|
+
context "when dmg not downloaded yet"
|
102
|
+
context "when dmg already downloaded"
|
103
|
+
context "when dmg has a mpkg"
|
104
|
+
context "when dmg does not have a mpkg"
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DMG::Source do
|
4
|
+
|
5
|
+
let(:pkgs_1_path) { File.join(File.dirname(__FILE__), '..', 'data', 'pkgs_1.yml') }
|
6
|
+
let(:pkgs_2_path) { File.join(File.dirname(__FILE__), '..', 'data', 'pkgs_2.yml') }
|
7
|
+
let(:pkgs_1_url) { 'https://github.com/versapay/dmg/raw/master/spec/data/pkgs_1.yml' }
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
context "when given a path to a yaml file" do
|
11
|
+
subject { DMG::Source.new(pkgs_1_path) }
|
12
|
+
|
13
|
+
its(:pkgs_hash) { should == YAML.load_file(pkgs_1_path) }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when given a url" do
|
17
|
+
subject { DMG::Source.new(pkgs_1_url) }
|
18
|
+
|
19
|
+
its(:pkgs_hash) { should == YAML.load_file(pkgs_1_path) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#download_and_combine" do
|
24
|
+
before do
|
25
|
+
File.open(DMG.sources_file, 'w') { |f| f.write [pkgs_1_path, pkgs_2_path].to_yaml }
|
26
|
+
DMG::Source.download_and_combine
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "generated combined packages file" do
|
30
|
+
let(:combined_pkgs) { YAML.load_file(DMG.combined_pkgs_file) }
|
31
|
+
|
32
|
+
subject { combined_pkgs }
|
33
|
+
|
34
|
+
it { should include("launchbar") } # in pkgs_1.yml only
|
35
|
+
it { should include("virtualbox") } # in pkgs_2.yml only
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "bundler"
|
6
|
+
Bundler.load
|
7
|
+
|
8
|
+
require 'rspec'
|
9
|
+
require 'dmg'
|
10
|
+
|
11
|
+
Rspec.configure do |config|
|
12
|
+
config.mock_with :rspec
|
13
|
+
end
|
14
|
+
|
15
|
+
ENV['DMG_HOME'] = File.join(File.dirname(__FILE__), '..', 'tmp', 'aruba')
|
16
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dmg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Philippe Creux
|
@@ -15,10 +15,51 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-05-02 00:00:00 -07:00
|
19
19
|
default_executable: dmg
|
20
|
-
dependencies:
|
21
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: cucumber
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: aruba
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
22
63
|
description: It's like apt-get for Mac
|
23
64
|
email:
|
24
65
|
- pcreux@gmail.com
|
@@ -35,14 +76,23 @@ files:
|
|
35
76
|
- Rakefile
|
36
77
|
- bin/dmg
|
37
78
|
- dmg.gemspec
|
79
|
+
- features/dmg.feature
|
80
|
+
- features/support/env.rb
|
38
81
|
- lib/dmg.rb
|
39
82
|
- lib/dmg/cli.rb
|
40
83
|
- lib/dmg/errors.rb
|
84
|
+
- lib/dmg/output_helpers.rb
|
41
85
|
- lib/dmg/pkg.rb
|
42
86
|
- lib/dmg/pkgs.yml
|
87
|
+
- lib/dmg/source.rb
|
43
88
|
- lib/dmg/version.rb
|
89
|
+
- spec/data/pkgs_1.yml
|
90
|
+
- spec/data/pkgs_2.yml
|
91
|
+
- spec/lib/pkg_spec.rb
|
92
|
+
- spec/lib/sources_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
44
94
|
has_rdoc: true
|
45
|
-
homepage:
|
95
|
+
homepage: https://github.com/versapay/dmg
|
46
96
|
licenses: []
|
47
97
|
|
48
98
|
post_install_message:
|
@@ -75,5 +125,11 @@ rubygems_version: 1.3.7
|
|
75
125
|
signing_key:
|
76
126
|
specification_version: 3
|
77
127
|
summary: Install popular applications provided as dmgs from the command line
|
78
|
-
test_files:
|
79
|
-
|
128
|
+
test_files:
|
129
|
+
- features/dmg.feature
|
130
|
+
- features/support/env.rb
|
131
|
+
- spec/data/pkgs_1.yml
|
132
|
+
- spec/data/pkgs_2.yml
|
133
|
+
- spec/lib/pkg_spec.rb
|
134
|
+
- spec/lib/sources_spec.rb
|
135
|
+
- spec/spec_helper.rb
|