remote-session 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ module Remote
2
+
3
+ class Session
4
+
5
+ class SendFile
6
+
7
+ attr_accessor :local_path
8
+ attr_accessor :remote_path
9
+ attr_accessor :chunk_size
10
+
11
+ def initialize( local_path, remote_path )
12
+ @local_path = local_path
13
+ @remote_path = remote_path
14
+ @chunk_size = 1024
15
+ @file = nil
16
+ end
17
+
18
+ def open?
19
+ ! @file.nil?
20
+ end
21
+
22
+ def eof?
23
+ return true if ! open?
24
+ @file.eof?
25
+ end
26
+
27
+ def read
28
+ open if ! open?
29
+
30
+ @file.read( @chunk_size )
31
+ end
32
+
33
+ def close
34
+ return if ! open?
35
+ @file.close
36
+ @file = nil
37
+ end
38
+
39
+ def open
40
+ close if open?
41
+ @file = File.open( @local_path, 'r' )
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
@@ -1,5 +1,6 @@
1
1
  module Remote
2
2
  class Session
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
6
+
@@ -1,6 +1,8 @@
1
+ require 'remote/session/send_file'
1
2
  require 'remote/session/version'
2
3
  require 'net/sftp'
3
4
  require 'net/ssh'
5
+ require 'base64'
4
6
 
5
7
  module Remote
6
8
  class Session
@@ -41,15 +43,15 @@ module Remote
41
43
  puts @session.exec!( command )
42
44
  end
43
45
 
44
- def sudo( command )
46
+ def sudo( commands )
45
47
  raise "Session is closed" if @session.nil?
48
+ commands = [ *commands ]
46
49
 
47
- puts "@#{ @host }: sudo #{ command }"
48
50
  @session.open_channel do |ch|
49
51
  ch.request_pty do |ch, success|
50
52
  raise "Could not obtain pty" if ! success
51
53
 
52
- channel_exec ch, command
54
+ channel_exec ch, commands
53
55
  end
54
56
  end
55
57
  @session.loop
@@ -60,22 +62,10 @@ module Remote
60
62
  @session = nil
61
63
  end
62
64
 
63
- def sudo_put( remote_path, &block )
64
- temp_path = "/tmp/remote-session.#{ Time.now.to_f }"
65
- run "mkdir #{ temp_path }"
66
- run "chmod 0700 #{ temp_path }"
67
-
68
- temp_file = File.join( temp_path, File.basename( remote_path ) )
69
- put temp_file, &block
70
-
71
- sudo "cp -f #{ temp_file } #{ remote_path }"
72
- run "rm -rf #{ temp_path }"
73
- end
74
-
75
65
  def put( remote_path, &block )
76
66
  sftp = Net::SFTP::Session.new( @session ).connect!
77
67
  sftp.file.open( remote_path, 'w' ) do |f|
78
- f.puts block.call
68
+ f.write block.call
79
69
  end
80
70
  sftp.close_channel
81
71
  end
@@ -94,29 +84,70 @@ module Remote
94
84
  @session = Net::SSH.start( @host, @username, ssh_options )
95
85
  end
96
86
 
97
- def channel_exec( ch, command )
98
- ch.exec "sudo -p '#{ SUDO_PROMPT }' #{ command }" do |ch, success|
99
- raise "Could not execute sudo command: #{ command }" if ! success
100
-
101
- ch.on_data do | ch, data |
102
- if data =~ Regexp.new( SUDO_PROMPT )
103
- ch.send_data "#{ @sudo_password }\n"
104
- else
105
- prompt_matched = false
106
- @prompts.each_pair do | prompt, send |
107
- if data =~ Regexp.new( prompt )
108
- ch.send_data "#{ send }\n"
109
- prompt_matched = true
110
- end
111
- end
112
- puts data if ! prompt_matched
113
- end
114
- end
87
+ def channel_exec( ch, commands )
88
+ ch[ :commands ] = commands
89
+
90
+ ch.exec "sudo -k -p '#{ SUDO_PROMPT }' su -" do |ch, success|
91
+ raise "Could not execute sudo su command" if ! success
92
+
93
+ ch.on_data( &method( :on_data ) )
115
94
 
116
95
  ch.on_extended_data do |ch, type, data|
117
- raise "Error #{ data } while performing command: #{ command }"
96
+ $stderr.puts data
97
+ end
98
+ end
99
+ end
100
+
101
+ def on_data( ch, data )
102
+ if data =~ Regexp.new( SUDO_PROMPT )
103
+ ch.send_data "#{ @sudo_password }\n"
104
+ return
105
+ end
106
+
107
+ @prompts.each_pair do | prompt, send |
108
+ if data =~ Regexp.new( prompt )
109
+ ch.send_data "#{ send }\n"
110
+ return
118
111
  end
119
112
  end
113
+
114
+ $stdout.write( data )
115
+
116
+ if ch[ :commands ].size == 0
117
+ ch.send_data "exit\n"
118
+ return
119
+ end
120
+
121
+ command = ch[ :commands ].shift
122
+ if command.is_a?( Remote::Session::SendFile )
123
+ send_file_chunk( ch, command )
124
+ else
125
+ ch.send_data "#{command}\n"
126
+ end
127
+ end
128
+
129
+ def send_file_chunk( ch, send_file )
130
+ if send_file.open?
131
+ operator = '>>'
132
+ else
133
+ send_file.open
134
+ operator = '>'
135
+ end
136
+
137
+ chunk =
138
+ if ! send_file.eof?
139
+ Base64.encode64( send_file.read )
140
+ else
141
+ # Handle empty files
142
+ ''
143
+ end
144
+ ch.send_data "echo -n '#{ chunk }' | base64 -d #{ operator } #{ send_file.remote_path }\n"
145
+
146
+ if send_file.eof?
147
+ send_file.close
148
+ else
149
+ ch[ :commands ].unshift send_file
150
+ end
120
151
  end
121
152
 
122
153
  end
@@ -0,0 +1,110 @@
1
+ # encoding: utf-8
2
+ load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
3
+
4
+ describe Remote::Session::SendFile do
5
+
6
+ context '#initialize' do
7
+
8
+ it 'should require two parameters'do
9
+ expect do
10
+ Remote::Session::SendFile.new( 'foo' )
11
+ end.to raise_error( ArgumentError, 'wrong number of arguments (1 for 2)' )
12
+ end
13
+
14
+ end
15
+
16
+ context 'attributes' do
17
+ subject { Remote::Session::SendFile.new( 'foo', 'bar' ) }
18
+
19
+ specify( 'local_path' ) { subject.local_path.should == 'foo' }
20
+ specify( 'remote_path' ) { subject.remote_path.should == 'bar' }
21
+ specify( 'chunk_size' ) { subject.chunk_size.should == 1024 }
22
+ end
23
+
24
+ context 'instance_methods' do
25
+ subject { Remote::Session::SendFile.new( '/local/path', '/remote/path' ) }
26
+
27
+ context '#open?' do
28
+ specify { subject.open?.should be_false }
29
+ end
30
+
31
+ context '#eof?' do
32
+ specify { subject.eof?.should be_true }
33
+
34
+ it 'should delegate to the file' do
35
+ @file = stub( 'file' )
36
+ File.stub!( :open ).with( '/local/path', 'r' ).and_return( @file )
37
+ @file.should_receive( :eof? ).and_return( false )
38
+
39
+ subject.open
40
+
41
+ subject.eof?.should be_false
42
+ end
43
+ end
44
+
45
+ context '#close' do
46
+
47
+ before :each do
48
+ @file = stub( 'file' )
49
+ end
50
+
51
+ it 'should close the file' do
52
+ File.stub!( :open ).with( '/local/path', 'r' ).and_return( @file )
53
+
54
+ subject.open
55
+
56
+ @file.should_receive( :close )
57
+
58
+ subject.close
59
+ end
60
+
61
+ it 'should do nothing is the file is not open' do
62
+ File.should_not_receive( :open )
63
+ @file.should_not_receive( :close )
64
+
65
+ subject.close
66
+ end
67
+
68
+ end
69
+
70
+ context '#read' do
71
+
72
+ before :each do
73
+ @file = stub( 'file' )
74
+ File.stub!( :open ).with( '/local/path', 'r' ).and_return( @file )
75
+ end
76
+
77
+ it 'should open the file' do
78
+ @file.stub!( :read ).and_return( 'aaa' )
79
+
80
+ File.should_receive( :open ).with( '/local/path', 'r' ).and_return( @file )
81
+
82
+ subject.read
83
+ end
84
+
85
+ it 'should fail, if the local file does non exist' do
86
+ File.stub!( :open ).and_raise( 'Stubbed error' )
87
+
88
+ expect do
89
+ subject.read
90
+ end.to raise_error
91
+ end
92
+
93
+ it 'should read chunks' do
94
+ @file.should_receive( :read ).and_return( 'stuff' )
95
+
96
+ subject.read.should == 'stuff'
97
+ end
98
+
99
+ it 'should read chunk_size bytes at a time' do
100
+ @file.should_receive( :read ).with( 1024 ).and_return( 'x' * 1024 )
101
+
102
+ subject.read.should == 'x' * 1024
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
@@ -1,8 +1,32 @@
1
1
  # encoding: utf-8
2
2
  load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
3
3
 
4
+ module SpecOutputCapture
5
+
6
+ def expect_output
7
+ stdout = []
8
+ @rs.stub!( :puts ) do | s |
9
+ stdout << "{ s }\n"
10
+ end
11
+ $stdout.stub!( :write ) do | s |
12
+ stdout << s
13
+ end
14
+ stderr = []
15
+ $stderr.stub!( :write ) do | s |
16
+ stderr << s
17
+ end
18
+
19
+ yield
20
+
21
+ [ stdout, stderr ]
22
+ end
23
+
24
+ end
25
+
4
26
  describe Remote::Session do
5
27
 
28
+ include SpecOutputCapture
29
+
6
30
  TEST_HOST = 'host.example.com'
7
31
 
8
32
  context 'initialization' do
@@ -125,6 +149,17 @@ describe Remote::Session do
125
149
 
126
150
  context '#sudo' do
127
151
 
152
+ before :each do
153
+ @ch = stub( 'channel' )
154
+ @commands = {}
155
+ @ch.stub!( :[]= ) do | k, v |
156
+ @commands[ k ] = v
157
+ end
158
+ @ch.stub!( :[] ) do | k |
159
+ @commands[ k ]
160
+ end
161
+ end
162
+
128
163
  subject { Remote::Session.new( TEST_HOST ) }
129
164
 
130
165
  it 'should fail, if the session is closed' do
@@ -136,28 +171,17 @@ describe Remote::Session do
136
171
  end.to raise_error( RuntimeError, 'Session is closed' )
137
172
  end
138
173
 
139
- it 'should print the command to stdout' do
140
- @ssh.stub!( :open_channel => nil )
141
- @ssh.stub!( :loop => nil )
142
-
143
- subject.should_receive( :puts ).with( "@#{TEST_HOST}: sudo pwd" )
144
-
145
- subject.sudo( 'pwd' )
146
- end
147
-
148
- it 'should run the command' do
174
+ it 'should run the su command' do
149
175
  subject.stub!( :puts )
150
176
 
151
177
  @ssh.should_receive( :open_channel ) do |&open_channel_block|
152
- @channel = stub( 'channel' )
153
-
154
- @channel.should_receive( :request_pty ) do |&request_pty_block|
155
- request_pty_block.call( @channel, true )
178
+ @ch.should_receive( :request_pty ) do |&request_pty_block|
179
+ request_pty_block.call( @ch, true )
156
180
  end
157
181
 
158
- @channel.should_receive( :exec ).with( "sudo -p 'sudo_prompt' pwd" )
182
+ @ch.should_receive( :exec ).with( "sudo -k -p 'sudo_prompt' su -" )
159
183
 
160
- open_channel_block.call @channel
184
+ open_channel_block.call @ch
161
185
  end
162
186
  @ssh.should_receive( :loop )
163
187
 
@@ -171,7 +195,6 @@ describe Remote::Session do
171
195
  @rs.stub!( :puts )
172
196
 
173
197
  @ssh.stub!( :loop => nil )
174
- @ch = stub( 'channel' )
175
198
  @ssh.stub!( :open_channel ) do |&block|
176
199
  block.call @ch
177
200
  end
@@ -195,23 +218,51 @@ describe Remote::Session do
195
218
  end
196
219
  end
197
220
 
198
- it 'should fail if the command fails' do
221
+ it 'should fail if the sudo command fails' do
199
222
  @ch.stub!( :exec ) do |&block|
200
223
  expect do
201
224
  block.call( @ch, false )
202
- end.to raise_error( RuntimeError, 'Could not execute sudo command: pwd' )
225
+ end.to raise_error( RuntimeError, 'Could not execute sudo su command' )
203
226
  end
204
227
 
205
228
  @rs.sudo( 'pwd' )
206
229
  end
207
230
 
208
231
  context 'in exec' do
232
+
209
233
  before :each do
210
234
  @ch.stub!( :exec ) do |&block|
211
235
  block.call( @ch, true )
212
236
  end
213
237
  @ch.stub!( :on_extended_data => nil )
214
238
  @ch.stub!( :send_data )
239
+ $stdout.stub!( :write => nil )
240
+ end
241
+
242
+ it 'should print the command to stdout' do
243
+ @ch.stub!( :on_data ) do |&block|
244
+ block.call( @ch, 'the_prompt' )
245
+ end
246
+
247
+ @ch.should_receive( :send_data ).with( "pwd\n" )
248
+
249
+ subject.sudo( 'pwd' )
250
+ end
251
+
252
+ it 'should run multiple commands' do
253
+ @ch.stub!( :on_data ) do |&block|
254
+ block.call( @ch, 'the_prompt' )
255
+ block.call( @ch, 'the_prompt' )
256
+ block.call( @ch, 'the_prompt' )
257
+ block.call( @ch, 'the_prompt' )
258
+ end
259
+
260
+ sent = []
261
+ @ch.stub!( :send_data ) { | s | sent << s }
262
+
263
+ subject.sudo( [ 'pwd', 'cd /etc', 'ls' ] )
264
+
265
+ sent.should == [ "pwd\n", "cd /etc\n", "ls\n", "exit\n" ]
215
266
  end
216
267
 
217
268
  it 'should output returning data' do
@@ -219,15 +270,99 @@ describe Remote::Session do
219
270
  block.call( @ch, 'some_data' )
220
271
  end
221
272
 
222
- @rs.should_receive( :puts ).with( 'some_data' )
273
+ expect_output do
274
+ @rs.sudo( 'pwd' )
275
+ end.should == [ [ 'some_data' ], [] ]
276
+ end
277
+
278
+ context 'sending files' do
279
+
280
+ before :each do
281
+ @sf = stub( 'Remote::Session::SendFile instance', :open => nil, :close => nil )
282
+ end
283
+
284
+ it 'should copy files' do
285
+ @ch.stub!( :on_data ) do |&block|
286
+ block.call( @ch, 'root_prompt#' )
287
+ block.call( @ch, 'root_prompt#' )
288
+ block.call( @ch, 'root_prompt#' )
289
+ end
290
+
291
+ @sf.should_receive( :is_a? ).with( Remote::Session::SendFile ).twice.and_return( true )
292
+ @sf.should_receive( :remote_path ).twice.and_return( '/remote/path' )
293
+
294
+ chunk = 0
295
+ open = false
296
+ @sf.should_receive( :open ) do
297
+ chunk = 1
298
+ open = true
299
+ end
300
+
301
+ @sf.stub!( :open? ) do
302
+ open
303
+ end
304
+
305
+ @sf.stub!( :eof? ) do
306
+ case chunk
307
+ when 0
308
+ true
309
+ when 1, 2
310
+ false
311
+ else
312
+ true
313
+ end
314
+ end
315
+
316
+ data = [ nil, 'first_chunk', 'second_chunk' ]
317
+ @sf.should_receive( :read ).twice do
318
+ d = data[ chunk ]
319
+ chunk += 1
320
+ d
321
+ end
322
+
323
+ sent = []
324
+ @ch.stub!( :send_data ) { | d | sent << d }
325
+
326
+ @rs.sudo( @sf )
327
+
328
+ sent.should == [
329
+ "echo -n 'Zmlyc3RfY2h1bms=\n' | base64 -d > /remote/path\n",
330
+ "echo -n 'c2Vjb25kX2NodW5r\n' | base64 -d >> /remote/path\n",
331
+ "exit\n"
332
+ ]
333
+ end
334
+
335
+ it 'should copy empty files' do
336
+ @ch.stub!( :on_data ) do |&block|
337
+ block.call( @ch, 'root_prompt#' )
338
+ block.call( @ch, 'root_prompt#' )
339
+ end
340
+
341
+ @sf.stub!( :is_a? ).with( Remote::Session::SendFile ).and_return( true )
342
+ @sf.stub!( :open? => false )
343
+ @sf.stub!( :remote_path ).and_return( '/remote/path' )
344
+ @sf.stub!( :eof? => true )
345
+
346
+ sent = []
347
+ @ch.stub!( :send_data ) { | d | sent << d }
348
+
223
349
 
224
- @rs.sudo( 'pwd' )
350
+ @rs.sudo( @sf )
351
+
352
+ sent.should == [
353
+ "echo -n '' | base64 -d > /remote/path\n",
354
+ "exit\n"
355
+ ]
356
+ end
357
+
225
358
  end
226
359
 
227
360
  context 'with password prompt' do
228
361
  before :each do
362
+ $stdout.stub( :write )
229
363
  @ch.stub!( :on_data ) do |&block|
230
364
  block.call( @ch, 'sudo_prompt' )
365
+ block.call( @ch, 'root#' )
231
366
  end
232
367
  end
233
368
 
@@ -238,21 +373,18 @@ describe Remote::Session do
238
373
  end
239
374
 
240
375
  it 'should not echo the standard prompt' do
241
- output = []
242
- @rs.stub!( :puts ) do | s |
243
- output << s
244
- end
245
-
246
- @rs.sudo( 'pwd' )
247
-
248
- output.should == ["@#{TEST_HOST}: sudo pwd"]
376
+ expect_output do
377
+ @rs.sudo( 'pwd' )
378
+ end.should == [ [ 'root#' ], [] ]
249
379
  end
250
380
  end
251
381
 
252
382
  context 'with user-supplied prompt' do
253
383
  before :each do
384
+ $stdout.stub( :write )
254
385
  @ch.stub!( :on_data ) do |&block|
255
386
  block.call( @ch, 'Here is my prompt:' )
387
+ block.call( @ch, 'root#' )
256
388
  end
257
389
  end
258
390
 
@@ -264,29 +396,25 @@ describe Remote::Session do
264
396
  end
265
397
 
266
398
  it 'should not echo the prompt' do
267
- output = []
268
- @rs.stub!( :puts ) do | s |
269
- output << s
270
- end
271
399
  @rs.prompts[ 'my prompt' ] = 'this data'
272
400
 
273
- @rs.sudo( 'pwd' )
274
-
275
- output.should == ["@#{TEST_HOST}: sudo pwd"]
401
+ expect_output do
402
+ @rs.sudo( 'pwd' )
403
+ end.should == [ [ 'root#' ], [] ]
276
404
  end
277
405
 
278
406
  end
279
407
 
280
- it 'should fail if error data is received' do
408
+ it 'should send error data to stdout' do
281
409
  @ch.stub!( :on_data )
282
410
 
283
411
  @ch.stub!( :on_extended_data ) do |&block|
284
412
  block.call @ch, 'foo', 'It failed'
285
413
  end
286
414
 
287
- expect do
415
+ expect_output do
288
416
  @rs.sudo( 'pwd' )
289
- end.to raise_error( RuntimeError, 'Error It failed while performing command: pwd' )
417
+ end.should == [ [], [ "It failed", "\n" ] ]
290
418
  end
291
419
 
292
420
  end
@@ -297,6 +425,46 @@ describe Remote::Session do
297
425
 
298
426
  end
299
427
 
428
+ context '#put' do
429
+
430
+ before :each do
431
+ @file2 = stub( 'file2' )
432
+ @file1 = stub( 'file1', :open => lambda { |&block| block.call @file2 } )
433
+ @sftp2 = stub( 'Net::SFTP::Session instance', :file => @file1,
434
+ :close_channel => nil )
435
+ @sftp1 = stub( 'Net::SFTP::Session instance', :connect! => @sftp2 )
436
+ Net::SFTP::Session.stub!( :new => @sftp1 )
437
+ end
438
+
439
+ subject { Remote::Session.new( TEST_HOST ) }
440
+
441
+ it 'creates an SFTP session' do
442
+ Net::SFTP::Session.should_receive( :new ).and_return( @sftp1 )
443
+ @sftp1.should_receive( :connect! ).once.and_return( @sftp2 )
444
+
445
+ subject.put( '/path' ) {}
446
+ end
447
+
448
+ it 'opens the file' do
449
+ @file1.should_receive( :open ) do | *args, &block |
450
+ args.should == ["/path", "w"]
451
+ end
452
+
453
+ subject.put( '/path' ) { 'content' }
454
+ end
455
+
456
+ it 'writes the data to the file' do
457
+ @file1.stub!( :open ) do | *args, &block |
458
+ block.call @file2
459
+ end
460
+
461
+ @file2.should_receive( :write ).with( 'content' )
462
+
463
+ subject.put( '/path' ) { 'content' }
464
+ end
465
+
466
+ end
467
+
300
468
  end
301
469
 
302
470
  end
metadata CHANGED
@@ -1,107 +1,108 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: remote-session
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Joe Yates
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-05-18 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-05-20 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ prerelease: false
15
22
  name: rake
16
- requirement: !ruby/object:Gem::Requirement
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 49
29
+ segments:
30
+ - 0
31
+ - 8
32
+ - 7
21
33
  version: 0.8.7
34
+ requirement: *id001
22
35
  type: :runtime
36
+ - !ruby/object:Gem::Dependency
23
37
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: 0.8.7
30
- - !ruby/object:Gem::Dependency
31
38
  name: net-sftp
32
- requirement: !ruby/object:Gem::Requirement
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
33
40
  none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ requirement: *id002
38
49
  type: :runtime
50
+ - !ruby/object:Gem::Dependency
39
51
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- - !ruby/object:Gem::Dependency
47
52
  name: net-ssh
48
- requirement: !ruby/object:Gem::Requirement
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
49
54
  none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirement: *id003
54
63
  type: :runtime
64
+ - !ruby/object:Gem::Dependency
55
65
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
63
66
  name: rspec
64
- requirement: !ruby/object:Gem::Requirement
67
+ version_requirements: &id004 !ruby/object:Gem::Requirement
65
68
  none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 2
75
+ - 3
76
+ - 0
69
77
  version: 2.3.0
78
+ requirement: *id004
70
79
  type: :development
80
+ - !ruby/object:Gem::Dependency
71
81
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: 2.3.0
78
- - !ruby/object:Gem::Dependency
79
- name: simplecov
80
- requirement: !ruby/object:Gem::Requirement
82
+ name: rcov
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
81
84
  none: false
82
- requirements:
83
- - - ! '>='
84
- - !ruby/object:Gem::Version
85
- version: '0'
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirement: *id005
86
93
  type: :development
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
94
- description: ! 'This gem uses Net::SSH to create a connection and allow command execution
95
- over it.
96
-
97
- Run commands as the logged on user, or via sudo as any permitetd user (defaults
98
- to root).'
99
- email:
94
+ description: |-
95
+ This gem uses Net::SSH to create a connection and allow command execution over it.
96
+ Run commands as the logged on user, or via sudo as any permitetd user (defaults to root).
97
+ email:
100
98
  - joe.g.yates@gmail.com
101
99
  executables: []
100
+
102
101
  extensions: []
102
+
103
103
  extra_rdoc_files: []
104
- files:
104
+
105
+ files:
105
106
  - .gitignore
106
107
  - .travis.yml
107
108
  - Gemfile
@@ -109,42 +110,48 @@ files:
109
110
  - README.md
110
111
  - Rakefile
111
112
  - lib/remote/session.rb
113
+ - lib/remote/session/send_file.rb
112
114
  - lib/remote/session/version.rb
113
115
  - remote-session.gemspec
114
116
  - spec/gather_rspec_coverage.rb
115
117
  - spec/spec_helper.rb
118
+ - spec/unit/send_file_spec.rb
116
119
  - spec/unit/session_spec.rb
117
- homepage: ''
120
+ homepage: ""
118
121
  licenses: []
122
+
119
123
  post_install_message:
120
124
  rdoc_options: []
121
- require_paths:
125
+
126
+ require_paths:
122
127
  - lib
123
- required_ruby_version: !ruby/object:Gem::Requirement
128
+ required_ruby_version: !ruby/object:Gem::Requirement
124
129
  none: false
125
- requirements:
126
- - - ! '>='
127
- - !ruby/object:Gem::Version
128
- version: '0'
129
- segments:
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ hash: 3
134
+ segments:
130
135
  - 0
131
- hash: 2675303135346864190
132
- required_rubygems_version: !ruby/object:Gem::Requirement
136
+ version: "0"
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
138
  none: false
134
- requirements:
135
- - - ! '>='
136
- - !ruby/object:Gem::Version
137
- version: '0'
138
- segments:
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ hash: 3
143
+ segments:
139
144
  - 0
140
- hash: 2675303135346864190
145
+ version: "0"
141
146
  requirements: []
147
+
142
148
  rubyforge_project: nowarning
143
149
  rubygems_version: 1.8.24
144
150
  signing_key:
145
151
  specification_version: 3
146
152
  summary: Run user commands, and sudo, commands over an SSH connection
147
- test_files:
153
+ test_files:
148
154
  - spec/gather_rspec_coverage.rb
149
155
  - spec/spec_helper.rb
156
+ - spec/unit/send_file_spec.rb
150
157
  - spec/unit/session_spec.rb