remote-session 0.0.2 → 0.0.3

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.
@@ -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