awshucks 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +4 -0
- data/LICENSE +19 -0
- data/README +32 -0
- data/Rakefile +14 -0
- data/TODO +143 -0
- data/bin/awshucks +10 -0
- data/lib/awshucks.rb +29 -0
- data/lib/awshucks/cli.rb +76 -0
- data/lib/awshucks/command.rb +98 -0
- data/lib/awshucks/commands.rb +3 -0
- data/lib/awshucks/commands/backup.rb +59 -0
- data/lib/awshucks/commands/backups.rb +25 -0
- data/lib/awshucks/commands/help.rb +22 -0
- data/lib/awshucks/commands/list.rb +39 -0
- data/lib/awshucks/commands/new_config.rb +36 -0
- data/lib/awshucks/commands/reset_metadata_cache.rb +38 -0
- data/lib/awshucks/commands/restore.rb +54 -0
- data/lib/awshucks/config.rb +83 -0
- data/lib/awshucks/ext.rb +23 -0
- data/lib/awshucks/file_info.rb +23 -0
- data/lib/awshucks/file_store.rb +111 -0
- data/lib/awshucks/gemspec.rb +48 -0
- data/lib/awshucks/scanner.rb +58 -0
- data/lib/awshucks/specification.rb +128 -0
- data/lib/awshucks/version.rb +18 -0
- data/resources/awshucks.yml +21 -0
- data/spec/awshucks_spec.rb +7 -0
- data/spec/cli_spec.rb +130 -0
- data/spec/command_spec.rb +111 -0
- data/spec/commands/backup_spec.rb +164 -0
- data/spec/commands/backups_spec.rb +41 -0
- data/spec/commands/help_spec.rb +42 -0
- data/spec/commands/list_spec.rb +77 -0
- data/spec/commands/new_config_spec.rb +102 -0
- data/spec/commands/reset_metadata_cache_spec.rb +93 -0
- data/spec/commands/restore_spec.rb +219 -0
- data/spec/config_spec.rb +152 -0
- data/spec/ext_spec.rb +28 -0
- data/spec/file_info_spec.rb +45 -0
- data/spec/file_store_spec.rb +352 -0
- data/spec/scanner_spec.rb +106 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/specification_spec.rb +41 -0
- metadata +121 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'awshucks/specification'
|
3
|
+
require 'awshucks/version'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
# The Gem Specification plus some extras for awshucks.
|
7
|
+
module Awshucks
|
8
|
+
SPEC = Awshucks::Specification.new do |spec|
|
9
|
+
spec.name = "awshucks"
|
10
|
+
spec.version = Awshucks::VERSION
|
11
|
+
spec.rubyforge_project = "awshucks"
|
12
|
+
spec.author = "Nathan Witmer"
|
13
|
+
spec.email = "nathan-ruby@otherward.net"
|
14
|
+
spec.homepage = "http://awshucks.rubyforge.org/"
|
15
|
+
|
16
|
+
spec.summary = "A Summary of awshucks."
|
17
|
+
spec.description = <<-DESC
|
18
|
+
TODO: A longer more detailed description of awshucks.
|
19
|
+
DESC
|
20
|
+
|
21
|
+
spec.extra_rdoc_files = FileList["[A-Z]*"]
|
22
|
+
spec.has_rdoc = true
|
23
|
+
spec.rdoc_main = "README"
|
24
|
+
spec.rdoc_options = [ "--line-numbers" , "--inline-source" ]
|
25
|
+
|
26
|
+
spec.test_files = FileList["spec/**/*.rb", "test/**/*.rb"]
|
27
|
+
spec.executable = spec.name
|
28
|
+
spec.files = spec.test_files + spec.extra_rdoc_files +
|
29
|
+
FileList["lib/**/*.rb", "resources/**/*"]
|
30
|
+
|
31
|
+
# add dependencies
|
32
|
+
# spec.add_dependency("somegem", ">= 0.4.2")
|
33
|
+
spec.add_dependency("aws-s3", ">= 0.4.0")
|
34
|
+
# spec.add_dependency("main", ">= 0.2.0")
|
35
|
+
|
36
|
+
spec.platform = Gem::Platform::RUBY
|
37
|
+
|
38
|
+
spec.local_rdoc_dir = "doc/rdoc"
|
39
|
+
spec.remote_rdoc_dir = "#{spec.name}/rdoc"
|
40
|
+
spec.local_coverage_dir = "doc/coverage"
|
41
|
+
spec.remote_coverage_dir= "#{spec.name}/coverage"
|
42
|
+
|
43
|
+
spec.remote_site_dir = "#{spec.name}/"
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Awshucks
|
2
|
+
|
3
|
+
class Scanner
|
4
|
+
|
5
|
+
def self.each_file(dir, ignore = [])
|
6
|
+
new(dir, ignore).each_file {|entry| yield entry }
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(dir, ignore = [])
|
10
|
+
@base_dir, @ignored = dir, ignore
|
11
|
+
end
|
12
|
+
|
13
|
+
# yields FileInfo object for each non-ignored file in the specified directory
|
14
|
+
def each_file
|
15
|
+
directory_stack << ''
|
16
|
+
while dir = directory_stack.pop
|
17
|
+
scan_directory(dir) { |entry| yield entry }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#######
|
22
|
+
private
|
23
|
+
#######
|
24
|
+
|
25
|
+
attr_reader :base_dir
|
26
|
+
attr_reader :ignored
|
27
|
+
|
28
|
+
def scan_directory(dir_name)
|
29
|
+
Dir.open(File.join(base_dir, dir_name)) do |dir|
|
30
|
+
while entry = dir.read
|
31
|
+
next if entry == '.' || entry == '..' || ignored?(entry)
|
32
|
+
|
33
|
+
stat = File.lstat(File.join(base_dir, dir_name, entry))
|
34
|
+
next if stat.symlink?
|
35
|
+
|
36
|
+
relative_path = File.join(dir_name, entry)
|
37
|
+
|
38
|
+
if stat.directory?
|
39
|
+
directory_stack << relative_path
|
40
|
+
else
|
41
|
+
# strip off the leading / in the relative path
|
42
|
+
yield FileInfo.new(relative_path[1..-1], File.join(base_dir, relative_path), stat)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def directory_stack
|
49
|
+
@directory_stack ||= []
|
50
|
+
end
|
51
|
+
|
52
|
+
def ignored?(filename)
|
53
|
+
ignored.any? {|ignore| File.fnmatch(ignore, filename) }
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubygems/specification'
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
module Awshucks
|
6
|
+
# Add some additional items to Gem::Specification
|
7
|
+
# A Awshucks::Specification adds additional pieces of information the
|
8
|
+
# typical gem specification
|
9
|
+
class Specification
|
10
|
+
|
11
|
+
RUBYFORGE_ROOT = "/var/www/gforge-projects/"
|
12
|
+
|
13
|
+
# user that accesses remote site
|
14
|
+
attr_accessor :remote_user
|
15
|
+
|
16
|
+
# remote host, default 'rubyforge.org'
|
17
|
+
attr_accessor :remote_host
|
18
|
+
|
19
|
+
# name the rdoc main
|
20
|
+
attr_accessor :rdoc_main
|
21
|
+
|
22
|
+
# local directory in development holding the generated rdoc
|
23
|
+
# default 'doc'
|
24
|
+
attr_accessor :local_rdoc_dir
|
25
|
+
|
26
|
+
# remote directory for storing rdoc, default 'doc'
|
27
|
+
attr_accessor :remote_rdoc_dir
|
28
|
+
|
29
|
+
# local directory for coverage report
|
30
|
+
attr_accessor :local_coverage_dir
|
31
|
+
|
32
|
+
# remote directory for storing coverage reports
|
33
|
+
# This defaults to 'coverage'
|
34
|
+
attr_accessor :remote_coverage_dir
|
35
|
+
|
36
|
+
# local directory for generated website, default +site/public+
|
37
|
+
attr_accessor :local_site_dir
|
38
|
+
|
39
|
+
# remote directory relative to +remote_root+ for the website.
|
40
|
+
# website.
|
41
|
+
attr_accessor :remote_site_dir
|
42
|
+
|
43
|
+
# is a .tgz to be created?, default 'true'
|
44
|
+
attr_accessor :need_tar
|
45
|
+
|
46
|
+
# is a .zip to be created, default 'true'
|
47
|
+
attr_accessor :need_zip
|
48
|
+
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
@remote_user = nil
|
52
|
+
@remote_host = "rubyforge.org"
|
53
|
+
|
54
|
+
@rdoc_main = "README"
|
55
|
+
@local_rdoc_dir = "doc"
|
56
|
+
@remote_rdoc_dir = "doc"
|
57
|
+
@local_coverage_dir = "coverage"
|
58
|
+
@remote_coverage_dir = "coverage"
|
59
|
+
@local_site_dir = "site/public"
|
60
|
+
@remote_site_dir = "."
|
61
|
+
|
62
|
+
@need_tar = true
|
63
|
+
@need_zip = true
|
64
|
+
|
65
|
+
@spec = Gem::Specification.new
|
66
|
+
|
67
|
+
yield self if block_given?
|
68
|
+
|
69
|
+
# update rdoc options to take care of the rdoc_main if it is
|
70
|
+
# there, and add a default title if one is not given
|
71
|
+
if not @spec.rdoc_options.include?("--main") then
|
72
|
+
@spec.rdoc_options.concat(["--main", rdoc_main])
|
73
|
+
end
|
74
|
+
|
75
|
+
if not @spec.rdoc_options.include?("--title") then
|
76
|
+
@spec.rdoc_options.concat(["--title","'#{name} -- #{summary}'"])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# if this gets set then it overwrites what would be the
|
81
|
+
# rubyforge default. If rubyforge project is not set then use
|
82
|
+
# name. If rubyforge project and name are set, but they are
|
83
|
+
# different then assume that name is a subproject of the
|
84
|
+
# rubyforge project
|
85
|
+
def remote_root
|
86
|
+
if rubyforge_project.nil? or
|
87
|
+
rubyforge_project == name then
|
88
|
+
return RUBYFORGE_ROOT + "#{name}/"
|
89
|
+
else
|
90
|
+
return RUBYFORGE_ROOT + "#{rubyforge_project}/#{name}/"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# rdoc files is the same as what would be generated during gem
|
95
|
+
# installation. That is, everything in the require paths plus
|
96
|
+
# the rdoc_extra_files
|
97
|
+
#
|
98
|
+
def rdoc_files
|
99
|
+
flist = extra_rdoc_files.dup
|
100
|
+
@spec.require_paths.each do |rp|
|
101
|
+
flist << FileList["#{rp}/**/*.rb"]
|
102
|
+
end
|
103
|
+
flist.flatten.uniq
|
104
|
+
end
|
105
|
+
|
106
|
+
# calculate the remote directories
|
107
|
+
def remote_root_location
|
108
|
+
"#{remote_user}@#{remote_host}:#{remote_root}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def remote_rdoc_location
|
112
|
+
remote_root_location + @remote_rdoc_dir
|
113
|
+
end
|
114
|
+
|
115
|
+
def remote_coverage_location
|
116
|
+
remote_root_location + @remote_coverage_dir
|
117
|
+
end
|
118
|
+
|
119
|
+
def remote_site_location
|
120
|
+
remote_root_location + @remote_site_dir
|
121
|
+
end
|
122
|
+
|
123
|
+
# we delegate any other calls to spec
|
124
|
+
def method_missing(method_id,*params,&block)
|
125
|
+
@spec.send method_id, *params, &block
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
# awshucks-generated config file
|
3
|
+
# The default filename is awshucks.yml, but can be overridden.
|
4
|
+
|
5
|
+
# Amazon S3 configuration
|
6
|
+
access_key_id: insert your access key here
|
7
|
+
secret_access_key: insert your secret access key here
|
8
|
+
|
9
|
+
# This is where awshucks will store all of your backed-up files.
|
10
|
+
bucket: bucket name
|
11
|
+
|
12
|
+
# Backup location configurations. Add as many of them as you like.
|
13
|
+
# Currently the only required key is location.
|
14
|
+
|
15
|
+
# For example (replace these with your own):
|
16
|
+
|
17
|
+
photos:
|
18
|
+
location: "~/pictures"
|
19
|
+
|
20
|
+
email:
|
21
|
+
location: "~/mail"
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),"spec_helper.rb")
|
2
|
+
|
3
|
+
describe Awshucks::CLI, '#execute' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@cli = Awshucks::CLI.new
|
7
|
+
@cmd = mock('pretend command')
|
8
|
+
@cmd.stub!(:command).and_return('pretend')
|
9
|
+
@old_stdout, $stdout = $stdout, StringIO.new
|
10
|
+
@old_stderr, $stderr = $stderr, StringIO.new
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
$stdout = @old_stdout
|
15
|
+
$stderr = @old_stderr
|
16
|
+
end
|
17
|
+
|
18
|
+
it "fails with a help message with empty arguments" do
|
19
|
+
@cli.execute([])
|
20
|
+
$stdout.string.should include("--help")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "loads the configuration from awshucks.yml in the current working directory by default" do
|
24
|
+
config = mock('config')
|
25
|
+
Awshucks::Config.should_receive(:new).with('awshucks.yml').and_return(config)
|
26
|
+
config.stub!(:help_message=)
|
27
|
+
Dir.chdir(dummy_fs_path) do
|
28
|
+
@cli.execute([])
|
29
|
+
@cli.send(:config) # lazily loaded, so force it
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "assigns the main help method to the config object as a way to piggyback it for commands" do
|
34
|
+
config = mock('config')
|
35
|
+
Awshucks::Config.should_receive(:new).with('awshucks.yml').and_return(config)
|
36
|
+
config.should_receive(:help_message=).with(/-h, --help/)
|
37
|
+
Dir.chdir(dummy_fs_path) do
|
38
|
+
@cli.execute([])
|
39
|
+
@cli.send(:config) # lazily loaded, so force it
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "runs the specified subcommand if a command is provided" do
|
44
|
+
@cmd.should_receive(:execute)
|
45
|
+
Awshucks::Command.should_receive(:commands).at_least(1).times.and_return({'pretend' => @cmd})
|
46
|
+
@cli.execute(['pretend'])
|
47
|
+
end
|
48
|
+
|
49
|
+
it "prints an error and exit if a specified subcommand is not found" do
|
50
|
+
Awshucks::Command.should_receive(:parse_and_execute).and_raise(Awshucks::UnknownCommandError.new('pretend'))
|
51
|
+
lambda { @cli.execute(['pretend']) }.should raise_error(SystemExit)
|
52
|
+
$stderr.string.should =~ /could not find.*pretend/i
|
53
|
+
end
|
54
|
+
|
55
|
+
it "prints an error and exit if a subcommand raises an error" do
|
56
|
+
Awshucks::Command.should_receive(:parse_and_execute).and_raise(Awshucks::CommandError.new('pretend error'))
|
57
|
+
lambda { @cli.execute(['pretend']) }.should raise_error(SystemExit)
|
58
|
+
$stderr.string.should =~ /pretend error/
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Awshucks::CLI, '#execute with no command-line arguments provided' do
|
64
|
+
|
65
|
+
before(:each) do
|
66
|
+
@old_stdout, $stdout = $stdout, StringIO.new
|
67
|
+
@cli = Awshucks::CLI.new
|
68
|
+
@cli.execute([])
|
69
|
+
end
|
70
|
+
|
71
|
+
after(:each) do
|
72
|
+
$stdout = @old_stdout
|
73
|
+
end
|
74
|
+
|
75
|
+
it "prints out a help message to stdout" do
|
76
|
+
$stdout.string.should =~ /-h, --help/
|
77
|
+
end
|
78
|
+
|
79
|
+
it "prints out a list of available commands" do
|
80
|
+
$stdout.string.should =~ / help/
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe Awshucks::CLI, '#execute with the -h argument' do
|
86
|
+
|
87
|
+
before(:each) do
|
88
|
+
@old_stdout, $stdout = $stdout, StringIO.new
|
89
|
+
@cli = Awshucks::CLI.new
|
90
|
+
@cli.execute(%w(-h))
|
91
|
+
end
|
92
|
+
|
93
|
+
after(:each) do
|
94
|
+
$stdout = @old_stdout
|
95
|
+
end
|
96
|
+
|
97
|
+
it "prints out a help message to stdout" do
|
98
|
+
$stdout.string.should =~ /-h, --help/
|
99
|
+
end
|
100
|
+
|
101
|
+
it "includes the version string" do
|
102
|
+
$stdout.string.should include("version #{Awshucks::VERSION}")
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe Awshucks::CLI, '#execute with the -c argument' do
|
108
|
+
|
109
|
+
before(:each) do
|
110
|
+
@cli = Awshucks::CLI.new
|
111
|
+
end
|
112
|
+
|
113
|
+
it "executes the given command with the specified config" do
|
114
|
+
config = mock('config')
|
115
|
+
Awshucks::Config.should_receive(:new).with('asdf.yml').and_return(config)
|
116
|
+
config.stub!(:help_message=)
|
117
|
+
Awshucks::Command.should_receive(:parse_and_execute)
|
118
|
+
@cli.execute(['-c', 'asdf.yml', 'command'])
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe Awshucks::CLI, '.execute' do
|
124
|
+
it "instantiates the CLI and calls execute with ARGV" do
|
125
|
+
@cli = mock('cli')
|
126
|
+
Awshucks::CLI.should_receive(:new).and_return(@cli)
|
127
|
+
@cli.should_receive(:execute).with(ARGV)
|
128
|
+
Awshucks::CLI.execute
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),"spec_helper.rb")
|
2
|
+
|
3
|
+
describe Awshucks::Command, '.commands' do
|
4
|
+
|
5
|
+
it "should return a list of commands stored at the class level" do
|
6
|
+
Awshucks::Command.commands.should be_kind_of(Hash)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have the standard commands loaded via the inherited callback" do
|
10
|
+
Awshucks::Command.commands['help'].should == Awshucks::HelpCommand
|
11
|
+
Awshucks::Command.commands['backup'].should == Awshucks::BackupCommand
|
12
|
+
Awshucks::Command.commands['backups'].should == Awshucks::BackupsCommand
|
13
|
+
Awshucks::Command.commands['list'].should == Awshucks::ListCommand
|
14
|
+
Awshucks::Command.commands['new_config'].should == Awshucks::NewConfigCommand
|
15
|
+
Awshucks::Command.commands['reset_metadata_cache'].should == Awshucks::ResetMetadataCacheCommand
|
16
|
+
Awshucks::Command.commands['restore'].should == Awshucks::RestoreCommand
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Awshucks::Command, '.parse_and_execute' do
|
22
|
+
|
23
|
+
before(:each) do
|
24
|
+
@cmd = mock('command')
|
25
|
+
@config = mock('config')
|
26
|
+
Awshucks::Command.commands['mock'] = @cmd
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should call execute on the command matching the first argument" do
|
30
|
+
@cmd.should_receive(:execute)
|
31
|
+
Awshucks::Command.parse_and_execute(['mock'], @config)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should strip the first argument from the arguments passed in when calling execute" do
|
35
|
+
@cmd.should_receive(:execute).with(['arg', 'arg2'], @config)
|
36
|
+
Awshucks::Command.parse_and_execute(['mock', 'arg', 'arg2'], @config)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should raise an unknown command error if the command isn't one that's registered" do
|
40
|
+
lambda { Awshucks::Command.parse_and_execute(['blahblah'], nil) }.should raise_error(Awshucks::UnknownCommandError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe Awshucks::Command, '.execute' do
|
45
|
+
it "should instantiate and call execute on the command class" do
|
46
|
+
class MockCommand < Awshucks::Command
|
47
|
+
end
|
48
|
+
|
49
|
+
@mock = mock('dummy command instance')
|
50
|
+
MockCommand.should_receive(:new).and_return(@mock)
|
51
|
+
@mock.should_receive(:execute)
|
52
|
+
|
53
|
+
MockCommand.execute(nil, nil)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe Awshucks::Command, '.option_string, when no custom options are defined' do
|
58
|
+
|
59
|
+
before(:each) do
|
60
|
+
class DummyCommand < Awshucks::Command
|
61
|
+
self.command = 'command name'
|
62
|
+
self.usage = 'usage string'
|
63
|
+
self.description = 'description'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should include usage in the option parser string" do
|
68
|
+
DummyCommand.option_string.should include('usage string')
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should include description in the option parser string" do
|
72
|
+
DummyCommand.option_string.should include('description')
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should state 'no options' in option parser string" do
|
76
|
+
DummyCommand.option_string.should include('No options')
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe Awshucks::Command, '.option_string, with custom options defined' do
|
82
|
+
|
83
|
+
before(:each) do
|
84
|
+
class DummyCommand < Awshucks::Command
|
85
|
+
self.command = 'command name'
|
86
|
+
self.usage = 'usage string'
|
87
|
+
self.description = 'description'
|
88
|
+
def custom_options(opts)
|
89
|
+
opts.on('-v', "be verbose")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should include custom options in option parser string if a block was used" do
|
95
|
+
DummyCommand.option_string.should include('Options:')
|
96
|
+
DummyCommand.option_string.should include('be verbose')
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
describe Awshucks::Command, '#parsed_options' do
|
102
|
+
it "should return an OpenStruct by default for use in option definitions" do
|
103
|
+
Awshucks::Command.new.send(:parsed_options).should be_instance_of(OpenStruct)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe Awshucks::Command, '#execute' do
|
108
|
+
it "raises an exception since it's meant to be an abstract method" do
|
109
|
+
lambda {Awshucks::Command.new.execute(nil, nil) }.should raise_error(Awshucks::CommandError)
|
110
|
+
end
|
111
|
+
end
|