adamwiggins-rush 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +87 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/bin/rush +13 -0
- data/bin/rushd +7 -0
- data/lib/rush/access.rb +130 -0
- data/lib/rush/array_ext.rb +19 -0
- data/lib/rush/box.rb +112 -0
- data/lib/rush/commands.rb +55 -0
- data/lib/rush/config.rb +154 -0
- data/lib/rush/dir.rb +160 -0
- data/lib/rush/embeddable_shell.rb +26 -0
- data/lib/rush/entry.rb +185 -0
- data/lib/rush/exceptions.rb +31 -0
- data/lib/rush/file.rb +85 -0
- data/lib/rush/find_by.rb +39 -0
- data/lib/rush/fixnum_ext.rb +18 -0
- data/lib/rush/head_tail.rb +11 -0
- data/lib/rush/local.rb +402 -0
- data/lib/rush/process.rb +59 -0
- data/lib/rush/process_set.rb +62 -0
- data/lib/rush/remote.rb +156 -0
- data/lib/rush/search_results.rb +58 -0
- data/lib/rush/server.rb +117 -0
- data/lib/rush/shell.rb +187 -0
- data/lib/rush/ssh_tunnel.rb +122 -0
- data/lib/rush/string_ext.rb +3 -0
- data/lib/rush.rb +87 -0
- data/spec/access_spec.rb +134 -0
- data/spec/array_ext_spec.rb +15 -0
- data/spec/base.rb +24 -0
- data/spec/box_spec.rb +64 -0
- data/spec/commands_spec.rb +47 -0
- data/spec/config_spec.rb +108 -0
- data/spec/dir_spec.rb +164 -0
- data/spec/embeddable_shell_spec.rb +17 -0
- data/spec/entry_spec.rb +133 -0
- data/spec/file_spec.rb +83 -0
- data/spec/find_by_spec.rb +58 -0
- data/spec/fixnum_ext_spec.rb +19 -0
- data/spec/local_spec.rb +352 -0
- data/spec/process_set_spec.rb +50 -0
- data/spec/process_spec.rb +73 -0
- data/spec/remote_spec.rb +140 -0
- data/spec/rush_spec.rb +28 -0
- data/spec/search_results_spec.rb +44 -0
- data/spec/shell_spec.rb +23 -0
- data/spec/ssh_tunnel_spec.rb +122 -0
- data/spec/string_ext_spec.rb +23 -0
- metadata +141 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Array do
|
4
|
+
it "mixes commands into array" do
|
5
|
+
[ 1,2,3 ].entries.should == [ 1, 2, 3 ]
|
6
|
+
end
|
7
|
+
|
8
|
+
it "can call head" do
|
9
|
+
[ 1,2,3 ].head(1).should == [ 1 ]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "can call tail" do
|
13
|
+
[ 1,2,3 ].tail(1).should == [ 3 ]
|
14
|
+
end
|
15
|
+
end
|
data/spec/base.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
5
|
+
require 'rush'
|
6
|
+
|
7
|
+
def mock_config(&block)
|
8
|
+
mock_config_start
|
9
|
+
block.call(config)
|
10
|
+
mock_config_end
|
11
|
+
end
|
12
|
+
|
13
|
+
def mock_config_sandbox_dir
|
14
|
+
"/tmp/fake_config.#{Process.pid}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def mock_config_start
|
18
|
+
mock_config_cleanup
|
19
|
+
Rush::Config.new(mock_config_sandbox_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def mock_config_cleanup
|
23
|
+
FileUtils.rm_rf(mock_config_sandbox_dir)
|
24
|
+
end
|
data/spec/box_spec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Rush::Box do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@box = Rush::Box.new('localhost')
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
system "rm -rf #{@sandbox_dir}"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "looks up entries with [] syntax" do
|
16
|
+
@box['/'].should == Rush::Dir.new('/', @box)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "looks up processes" do
|
20
|
+
@box.connection.should_receive(:processes).and_return([ { :pid => 123 } ])
|
21
|
+
@box.processes.should == [ Rush::Process.new({ :pid => 123 }, @box) ]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "executes bash commands" do
|
25
|
+
@box.connection.should_receive(:bash).with('cmd', nil, false).and_return('output')
|
26
|
+
@box.bash('cmd').should == 'output'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "executes bash commands with an optional user" do
|
30
|
+
@box.connection.should_receive(:bash).with('cmd', 'user', false)
|
31
|
+
@box.bash('cmd', :user => 'user')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "executes bash commands in the background, returning a Rush::Process" do
|
35
|
+
@box.connection.should_receive(:bash).with('cmd', nil, true).and_return(123)
|
36
|
+
@box.stub!(:processes).and_return([ mock('ps', :pid => 123) ])
|
37
|
+
@box.bash('cmd', :background => true).pid.should == 123
|
38
|
+
end
|
39
|
+
|
40
|
+
it "builds a script of environment variables to prefix the bash command" do
|
41
|
+
@box.command_with_environment('cmd', { :a => 'b' }).should == "export a='b'\ncmd"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "sets the environment variables from the provided hash" do
|
45
|
+
@box.connection.stub!(:bash)
|
46
|
+
@box.should_receive(:command_with_environment).with('cmd', { 1 => 2 })
|
47
|
+
@box.bash('cmd', :env => { 1 => 2 })
|
48
|
+
end
|
49
|
+
|
50
|
+
it "checks the connection to determine if it is alive" do
|
51
|
+
@box.connection.should_receive(:alive?).and_return(true)
|
52
|
+
@box.should be_alive
|
53
|
+
end
|
54
|
+
|
55
|
+
it "establish_connection to set up the connection manually" do
|
56
|
+
@box.connection.should_receive(:ensure_tunnel)
|
57
|
+
@box.establish_connection
|
58
|
+
end
|
59
|
+
|
60
|
+
it "establish_connection can take a hash of options" do
|
61
|
+
@box.connection.should_receive(:ensure_tunnel).with(:timeout => :infinite)
|
62
|
+
@box.establish_connection(:timeout => :infinite)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Rush::Commands do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@filename = "test_file"
|
9
|
+
system "echo thing_to_find > #{@sandbox_dir}/#{@filename}"
|
10
|
+
system "echo dont_find_me > #{@sandbox_dir}/some_other_file"
|
11
|
+
|
12
|
+
@dir = Rush::Dir.new(@sandbox_dir)
|
13
|
+
@array = @dir.files
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
system "rm -rf #{@sandbox_dir}"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "searches a list of files" do
|
21
|
+
results = @dir.files.search(/thing_to_find/)
|
22
|
+
results.should be_kind_of(Rush::SearchResults)
|
23
|
+
results.entries.should == [ @dir[@filename] ]
|
24
|
+
results.lines.should == [ "thing_to_find" ]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "searches a dir" do
|
28
|
+
@dir.search(/thing_to_find/).entries.should == [ @dir[@filename] ]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "searchs a dir's nested files" do
|
32
|
+
@dir.create_dir('sub').create_file('file').write('nested')
|
33
|
+
@dir['**'].search(/nested/).entries.should == [ @dir['sub/file'] ]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "search and replace contents on all files in the glob" do
|
37
|
+
@dir['1'].create.write('xax')
|
38
|
+
@dir['2'].create.write('-a-')
|
39
|
+
@dir.replace_contents!(/a/, 'b')
|
40
|
+
@dir['1'].contents.should == "xbx"
|
41
|
+
@dir['2'].contents.should == "-b-"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "counts lines of the contained files" do
|
45
|
+
@dir.files.line_count.should == 2
|
46
|
+
end
|
47
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Rush::Config do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_config_spec.#{Process.pid}"
|
6
|
+
system "rm -rf #{@sandbox_dir}"
|
7
|
+
@config = Rush::Config.new(@sandbox_dir)
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
system "rm -rf #{@sandbox_dir}"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "creates the dir" do
|
15
|
+
File.directory?(@sandbox_dir).should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can access the history file" do
|
19
|
+
@config.history_file.class.should == Rush::File
|
20
|
+
end
|
21
|
+
|
22
|
+
it "saves the shell command history" do
|
23
|
+
@config.save_history(%w(1 2 3))
|
24
|
+
@config.history_file.contents.should == "1\n2\n3\n"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "loads the shell command history" do
|
28
|
+
@config.save_history(%w(1 2 3))
|
29
|
+
@config.load_history.should == %w(1 2 3)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "loads a blank history if no history file" do
|
33
|
+
@config.load_history.should == []
|
34
|
+
end
|
35
|
+
|
36
|
+
it "loads the env file" do
|
37
|
+
@config.env_file.write('abc')
|
38
|
+
@config.load_env.should == 'abc'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "loads nothing if env file does not exist" do
|
42
|
+
@config.load_env.should == ""
|
43
|
+
end
|
44
|
+
|
45
|
+
it "loads the commands file" do
|
46
|
+
@config.commands_file.write('abc')
|
47
|
+
@config.load_commands.should == 'abc'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "loads nothing if commands file does not exist" do
|
51
|
+
@config.load_commands.should == ""
|
52
|
+
end
|
53
|
+
|
54
|
+
it "loads usernames and password for rushd" do
|
55
|
+
system "echo 1:2 > #{@sandbox_dir}/passwords"
|
56
|
+
system "echo a:b >> #{@sandbox_dir}/passwords"
|
57
|
+
@config.passwords.should == { '1' => '2', 'a' => 'b' }
|
58
|
+
end
|
59
|
+
|
60
|
+
it "loads blank hash if no passwords file" do
|
61
|
+
@config.passwords.should == { }
|
62
|
+
end
|
63
|
+
|
64
|
+
it "loads credentials for client connecting to server" do
|
65
|
+
system "echo user:pass > #{@sandbox_dir}/credentials"
|
66
|
+
@config.credentials_user.should == 'user'
|
67
|
+
@config.credentials_password.should == 'pass'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "loads list of ssh tunnels" do
|
71
|
+
system "echo host.example.com:123 > #{@sandbox_dir}/tunnels"
|
72
|
+
@config.tunnels.should == { 'host.example.com' => 123 }
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns an empty hash if tunnels file is blank" do
|
76
|
+
@config.tunnels.should == { }
|
77
|
+
end
|
78
|
+
|
79
|
+
it "saves a list of ssh tunnels" do
|
80
|
+
@config.save_tunnels({ 'my.example.com' => 4000 })
|
81
|
+
@config.tunnels_file.contents.should == "my.example.com:4000\n"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "ensure_credentials_exist doesn't do anything if credentials already exist" do
|
85
|
+
@config.credentials_file.write "dummy"
|
86
|
+
@config.should_receive(:generate_credentials).exactly(0).times
|
87
|
+
@config.ensure_credentials_exist
|
88
|
+
end
|
89
|
+
|
90
|
+
it "ensure_credentials_exist generates credentials file if they don't exist" do
|
91
|
+
@config.should_receive(:generate_credentials)
|
92
|
+
@config.ensure_credentials_exist
|
93
|
+
end
|
94
|
+
|
95
|
+
it "secret_characters returns valid characters for username or password" do
|
96
|
+
@config.secret_characters.should be_kind_of(Array)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "generate_secret products a random string for use in username and password" do
|
100
|
+
@config.should_receive(:secret_characters).and_return(%w(a))
|
101
|
+
@config.generate_secret(2, 2).should == "aa"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "generate_credentials saves credentials" do
|
105
|
+
@config.generate_credentials
|
106
|
+
@config.credentials_file.contents.should match(/^.+:.+$/)
|
107
|
+
end
|
108
|
+
end
|
data/spec/dir_spec.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Rush::Dir do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@dirname = "#{@sandbox_dir}/test_dir/"
|
9
|
+
system "mkdir -p #{@dirname}"
|
10
|
+
|
11
|
+
@dir = Rush::Dir.new(@dirname)
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
system "rm -rf #{@sandbox_dir}"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "is a child of Rush::Entry" do
|
19
|
+
@dir.should be_kind_of(Rush::Entry)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can create itself, returning itself" do
|
23
|
+
system "rm -rf #{@sandbox_dir}"
|
24
|
+
@dir.create.should == @dir
|
25
|
+
File.directory?(@dir.full_path).should be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can create a new file" do
|
29
|
+
newfile = @dir.create_file('one.txt')
|
30
|
+
newfile.name.should == 'one.txt'
|
31
|
+
newfile.parent.should == @dir
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can create a new subdir" do
|
35
|
+
newfile = @dir['two/'].create
|
36
|
+
newfile.name.should == 'two'
|
37
|
+
newfile.parent.should == @dir
|
38
|
+
end
|
39
|
+
|
40
|
+
it "find_by_name finds a single entry in the contents" do
|
41
|
+
file = @dir.create_file('one.rb')
|
42
|
+
@dir.find_by_name('one.rb').should == file
|
43
|
+
end
|
44
|
+
|
45
|
+
it "find_by_glob finds a list of entries by wildcard" do
|
46
|
+
file1 = @dir.create_file('one.rb')
|
47
|
+
file2 = @dir.create_file('two.txt')
|
48
|
+
@dir.find_by_glob('*.rb').should == [ file1 ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "lists files" do
|
52
|
+
@dir.create_file('a')
|
53
|
+
@dir.files.should == [ Rush::File.new("#{@dirname}/a") ]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "lists dirs" do
|
57
|
+
system "mkdir -p #{@dir.full_path}/b"
|
58
|
+
@dir.dirs.should == [ Rush::Dir.new("#{@dirname}/b") ]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "lists combined files and dirs" do
|
62
|
+
@dir['c'].create
|
63
|
+
@dir['d/'].create
|
64
|
+
@dir.contents.size.should == 2
|
65
|
+
end
|
66
|
+
|
67
|
+
it "fetches the entry_tree of all contents recursively" do
|
68
|
+
@dir['a/'].create['b/'].create['c'].create
|
69
|
+
@dir.entries_tree.should == @dir.make_entries(%w(a/ a/b/ a/b/c))
|
70
|
+
end
|
71
|
+
|
72
|
+
it "maps [] to find_by_name" do
|
73
|
+
@dir.should_receive(:find_by_name).once
|
74
|
+
@dir['one']
|
75
|
+
end
|
76
|
+
|
77
|
+
it "maps [] with a wildcard character to find_by_glob" do
|
78
|
+
@dir.should_receive(:find_by_glob).once
|
79
|
+
@dir['*']
|
80
|
+
end
|
81
|
+
|
82
|
+
it "can use symbols or strings for [] access" do
|
83
|
+
@dir.should_receive(:find_by_name).once.with('subdir')
|
84
|
+
@dir[:subdir]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "[] can return a file that has yet to be created" do
|
88
|
+
@dir['not_yet'].class.should == Rush::File
|
89
|
+
end
|
90
|
+
|
91
|
+
it "makes a list of entries from an array of filenames" do
|
92
|
+
@dir['a'].create
|
93
|
+
@dir['b/c/'].create
|
94
|
+
@dir.make_entries(%w(a b/c)).should == [ @dir['a'], @dir['b/c'] ]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "lists flattened files from all nested subdirectories" do
|
98
|
+
@dir['1'].create
|
99
|
+
@dir['2/3/'].create['4'].create
|
100
|
+
@dir['a/b/c/'].create['d'].create
|
101
|
+
@dir.files_flattened.should == @dir.make_entries(%w(1 2/3/4 a/b/c/d))
|
102
|
+
end
|
103
|
+
|
104
|
+
it "lists flattened dirs from all nested subdirectories" do
|
105
|
+
@dir.create_dir('1/2')
|
106
|
+
@dir.dirs_flattened.should == @dir.make_entries(%w(1/ 1/2/))
|
107
|
+
end
|
108
|
+
|
109
|
+
it "** as a shortcut to flattened_files" do
|
110
|
+
@dir['**'].should == @dir.files_flattened
|
111
|
+
end
|
112
|
+
|
113
|
+
it "**/ as a shortcut to flattened_files + regular globbing" do
|
114
|
+
@dir.create_file('1.rb')
|
115
|
+
@dir.create_file('ignore.txt')
|
116
|
+
@dir.create_dir('2').create_file('3.rb')
|
117
|
+
@dir.create_dir('a/b').create_file('c.rb')
|
118
|
+
@dir['**/*.rb'].should == @dir.make_entries(%w(1.rb 2/3.rb a/b/c.rb))
|
119
|
+
end
|
120
|
+
|
121
|
+
it "lists nonhidden files" do
|
122
|
+
@dir.create_file('show')
|
123
|
+
@dir.create_file('.dont_show')
|
124
|
+
@dir.nonhidden_files.should == @dir.make_entries(%(show))
|
125
|
+
end
|
126
|
+
|
127
|
+
it "lists nonhidden dirs" do
|
128
|
+
@dir.create_dir('show')
|
129
|
+
@dir.create_dir('.dont_show')
|
130
|
+
@dir.nonhidden_dirs.should == @dir.make_entries(%(show/))
|
131
|
+
end
|
132
|
+
|
133
|
+
if !RUBY_PLATFORM.match(/darwin/) # doesn't work on OS X 'cause du switches are different
|
134
|
+
it "knows its size in bytes, which includes its contents recursively" do
|
135
|
+
@dir.create_file('a').write('1234')
|
136
|
+
@dir.size.should be(4096 + 4)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it "can destroy itself when empty" do
|
141
|
+
@dir.destroy
|
142
|
+
end
|
143
|
+
|
144
|
+
it "can destroy itself when not empty" do
|
145
|
+
@dir.create_dir('a').create_file('b').write('c')
|
146
|
+
@dir.destroy
|
147
|
+
end
|
148
|
+
|
149
|
+
it "can run a bash command within itself" do
|
150
|
+
system "echo test > #{@dir.full_path}/file"
|
151
|
+
@dir.bash("cat file").should == "test\n"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "can run bash within directories with spaces" do
|
155
|
+
@dir.create_dir('with space').create_file('file').write('test')
|
156
|
+
@dir["with space/"].bash("cat file").should == "test"
|
157
|
+
end
|
158
|
+
|
159
|
+
it "passes bash options (e.g., :user) through to the box bash command" do
|
160
|
+
@dir.should_receive(:bash).with('cmd', :opt1 => 1, :opt2 => 2)
|
161
|
+
@dir.bash('cmd', :opt1 => 1, :opt2 => 2)
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Rush::EmbeddableShell do
|
4
|
+
before do
|
5
|
+
@shell = Rush::EmbeddableShell.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should execute unknown methods against a Rush::Shell instance" do
|
9
|
+
@shell.root.class.should == Rush::Dir
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should executes a block as if it were inside the shell" do
|
13
|
+
@shell.execute_in_shell {
|
14
|
+
root.class.should == Rush::Dir
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
data/spec/entry_spec.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Rush::Entry do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}/"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@filename = "#{@sandbox_dir}/test_file"
|
9
|
+
system "touch #{@filename}"
|
10
|
+
|
11
|
+
@entry = Rush::Entry.new(@filename)
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
system "rm -rf #{@sandbox_dir}"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "knows its name" do
|
19
|
+
@entry.name.should == File.basename(@filename)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "knows its parent dir" do
|
23
|
+
@entry.parent.should be_kind_of(Rush::Dir)
|
24
|
+
@entry.parent.name.should == File.basename(@sandbox_dir)
|
25
|
+
@entry.parent.full_path.should == @sandbox_dir
|
26
|
+
end
|
27
|
+
|
28
|
+
it "cleans its pathname" do
|
29
|
+
Rush::Entry.new('/a//b//c').full_path.should == '/a/b/c'
|
30
|
+
Rush::Entry.new('/1/2/../3').full_path.should == '/1/3'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "knows its changed_at time" do
|
34
|
+
@entry.changed_at.should == File.stat(@filename).ctime
|
35
|
+
end
|
36
|
+
|
37
|
+
it "knows its last_modified time" do
|
38
|
+
@entry.last_modified.should == File.stat(@filename).mtime
|
39
|
+
end
|
40
|
+
|
41
|
+
it "knows its last_accessed time" do
|
42
|
+
@entry.last_accessed.should == File.stat(@filename).atime
|
43
|
+
end
|
44
|
+
|
45
|
+
it "considers itself equal to other instances with the same full path" do
|
46
|
+
Rush::Entry.new('/not/the/same').should_not == @entry
|
47
|
+
Rush::Entry.new(@entry.full_path).should == @entry
|
48
|
+
end
|
49
|
+
|
50
|
+
it "can rename itself" do
|
51
|
+
new_file = "test2"
|
52
|
+
|
53
|
+
@entry.rename(new_file)
|
54
|
+
|
55
|
+
File.exists?(@filename).should be_false
|
56
|
+
File.exists?("#{@sandbox_dir}/#{new_file}").should be_true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "rename returns the renamed file" do
|
60
|
+
@entry.rename('file2').should == @entry.parent['file2']
|
61
|
+
end
|
62
|
+
|
63
|
+
it "can't rename itself if another file already exists with that name" do
|
64
|
+
new_file = "test3"
|
65
|
+
system "touch #{@sandbox_dir}/#{new_file}"
|
66
|
+
|
67
|
+
lambda { @entry.rename(new_file) }.should raise_error(Rush::NameAlreadyExists, /#{new_file}/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "can't rename itself to something with a slash in it" do
|
71
|
+
lambda { @entry.rename('has/slash') }.should raise_error(Rush::NameCannotContainSlash, /slash/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can duplicate itself within the directory" do
|
75
|
+
@entry.duplicate('newfile').should == Rush::File.new("#{@sandbox_dir}/newfile")
|
76
|
+
end
|
77
|
+
|
78
|
+
it "can move itself to another dir" do
|
79
|
+
newdir = "#{@sandbox_dir}/newdir"
|
80
|
+
system "mkdir -p #{newdir}"
|
81
|
+
|
82
|
+
dst = Rush::Dir.new(newdir)
|
83
|
+
@entry.move_to(dst)
|
84
|
+
|
85
|
+
File.exists?(@filename).should be_false
|
86
|
+
File.exists?("#{newdir}/#{@entry.name}").should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "can copy itself to another directory" do
|
90
|
+
newdir = "#{@sandbox_dir}/newdir"
|
91
|
+
system "mkdir -p #{newdir}"
|
92
|
+
|
93
|
+
dst = Rush::Dir.new(newdir)
|
94
|
+
@copied_dir = @entry.copy_to(dst)
|
95
|
+
|
96
|
+
File.exists?(@filename).should be_true
|
97
|
+
File.exists?("#{newdir}/#{@entry.name}").should be_true
|
98
|
+
|
99
|
+
@copied_dir.full_path.should == "#{@sandbox_dir}newdir/#{@entry.name}"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "considers dotfiles to be hidden" do
|
103
|
+
Rush::Entry.new("#{@sandbox_dir}/show").should_not be_hidden
|
104
|
+
Rush::Entry.new("#{@sandbox_dir}/.dont_show").should be_hidden
|
105
|
+
end
|
106
|
+
|
107
|
+
it "is considered equal to entries with the same full path and on the same box" do
|
108
|
+
same = Rush::Entry.new(@entry.full_path, @entry.box)
|
109
|
+
@entry.should == same
|
110
|
+
end
|
111
|
+
|
112
|
+
it "is considered not equal to entries with the same full path on a different box" do
|
113
|
+
same = Rush::Entry.new(@entry.full_path, Rush::Box.new('dummy'))
|
114
|
+
@entry.should_not == same
|
115
|
+
end
|
116
|
+
|
117
|
+
it "can mimic another entry" do
|
118
|
+
copy = Rush::Entry.new('abc', :dummy)
|
119
|
+
copy.mimic(@entry)
|
120
|
+
copy.path.should == @entry.path
|
121
|
+
end
|
122
|
+
|
123
|
+
it "can update the read access permission" do
|
124
|
+
system "chmod 666 #{@filename}"
|
125
|
+
@entry.access = { :user_can => :read }
|
126
|
+
`ls -l #{@filename}`.should match(/^-r--------/)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "reads the file permissions in the access hash" do
|
130
|
+
system "chmod 640 #{@filename}"
|
131
|
+
@entry.access.should == { :user_can_read => true, :user_can_write => true, :group_can_read => true }
|
132
|
+
end
|
133
|
+
end
|
data/spec/file_spec.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe Rush::File do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@filename = "#{@sandbox_dir}/test_file"
|
9
|
+
@contents = "1234"
|
10
|
+
system "echo #{@contents} > #{@filename}"
|
11
|
+
@contents += "\n"
|
12
|
+
|
13
|
+
@file = Rush::File.new(@filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
system "rm -rf #{@sandbox_dir}"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "is a child of Rush::Entry" do
|
21
|
+
@file.should be_kind_of(Rush::Entry)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is not a dir" do
|
25
|
+
@file.should_not be_dir
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can create itself as a blank file, and return itself" do
|
29
|
+
create_me = Rush::File.new("#{@sandbox_dir}/create_me")
|
30
|
+
create_me.create.should == create_me
|
31
|
+
File.exists?("#{@sandbox_dir}/create_me").should == true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "knows its size in bytes" do
|
35
|
+
@file.size.should == @contents.length
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can read its contents" do
|
39
|
+
@file.contents.should == @contents
|
40
|
+
end
|
41
|
+
|
42
|
+
it "read is an alias for contents" do
|
43
|
+
@file.read.should == @contents
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can write new contents" do
|
47
|
+
@file.write('write test')
|
48
|
+
@file.contents.should == 'write test'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can count the number of lines it contains" do
|
52
|
+
@file.write("1\n2\n3\n")
|
53
|
+
@file.line_count.should == 3
|
54
|
+
end
|
55
|
+
|
56
|
+
it "searches its contents for matching lines" do
|
57
|
+
@file.write("a\n1\nb\n2\n")
|
58
|
+
@file.search(/\d/).should == %w(1 2)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "search returns nil if no lines match" do
|
62
|
+
@file.write("a\nb\nc\n")
|
63
|
+
@file.search(/\d/).should be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it "find-in-file replace" do
|
67
|
+
@file.replace_contents!(/\d/, 'x')
|
68
|
+
@file.contents.should == "xxxx\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "can destroy itself" do
|
72
|
+
@file.destroy
|
73
|
+
::File.exists?(@filename).should be_false
|
74
|
+
end
|
75
|
+
|
76
|
+
it "can fetch contents or blank if doesn't exist" do
|
77
|
+
Rush::File.new('/does/not/exist').contents_or_blank.should == ""
|
78
|
+
end
|
79
|
+
|
80
|
+
it "can fetch lines, or empty if doesn't exist" do
|
81
|
+
Rush::File.new('/does/not/exist').lines_or_empty.should == []
|
82
|
+
end
|
83
|
+
end
|