nutshell 1.0.0 → 1.0.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/.gemtest +0 -0
- data/History.txt +6 -0
- data/README.txt +3 -3
- data/Rakefile +1 -0
- data/lib/nutshell.rb +29 -2
- data/lib/nutshell/remote_shell.rb +3 -3
- data/lib/nutshell/shell.rb +30 -8
- data/test/test_helper.rb +1 -1
- data/test/test_shell.rb +2 -2
- metadata +99 -73
data/.gemtest
ADDED
File without changes
|
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Nutshell
|
2
2
|
|
3
|
-
* http://
|
3
|
+
* http://yaks.me/nutshell
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
@@ -43,7 +43,7 @@ A light weight ssh client that wraps the ssh and rsync commands.
|
|
43
43
|
|
44
44
|
* highline gem
|
45
45
|
|
46
|
-
* Unix based OS
|
46
|
+
* Unix based OS with ssh and rsync
|
47
47
|
|
48
48
|
== INSTALL:
|
49
49
|
|
@@ -53,7 +53,7 @@ A light weight ssh client that wraps the ssh and rsync commands.
|
|
53
53
|
|
54
54
|
(The MIT License)
|
55
55
|
|
56
|
-
Copyright (c) 2010
|
56
|
+
Copyright (c) 2010 Jeremie Castagna
|
57
57
|
|
58
58
|
Permission is hereby granted, free of charge, to any person obtaining
|
59
59
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
data/lib/nutshell.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'open4'
|
3
3
|
require 'highline'
|
4
|
+
require 'termios'
|
4
5
|
|
5
6
|
require 'fileutils'
|
6
7
|
require 'tmpdir'
|
@@ -8,7 +9,7 @@ require 'tmpdir'
|
|
8
9
|
|
9
10
|
module Nutshell
|
10
11
|
|
11
|
-
VERSION = "1.0.
|
12
|
+
VERSION = "1.0.1"
|
12
13
|
|
13
14
|
##
|
14
15
|
# Temp directory used by various nutshell classes
|
@@ -21,22 +22,48 @@ module Nutshell
|
|
21
22
|
class CmdError < Exception; end
|
22
23
|
class ConnectionError < Exception; end
|
23
24
|
|
25
|
+
DEFAULT_CONFIG = {
|
26
|
+
:timeout => 300,
|
27
|
+
:interactive => true,
|
28
|
+
:tty_state_freq => 0.1
|
29
|
+
}
|
30
|
+
|
31
|
+
##
|
32
|
+
# Set the config.
|
24
33
|
|
25
34
|
def self.config
|
26
|
-
@config ||=
|
35
|
+
@config ||= DEFAULT_CONFIG.dup
|
27
36
|
end
|
28
37
|
|
29
38
|
|
39
|
+
##
|
40
|
+
# How long to wait with no data coming in before timing out.
|
41
|
+
# Reads config[:timeout].
|
42
|
+
|
30
43
|
def self.timeout
|
31
44
|
config[:timeout]
|
32
45
|
end
|
33
46
|
|
34
47
|
|
48
|
+
##
|
49
|
+
# Defines if process should fail when user interaction is required.
|
50
|
+
# Defaults to true. Reads config[:interactive].
|
51
|
+
|
35
52
|
def self.interactive?
|
36
53
|
config[:interactive]
|
37
54
|
end
|
38
55
|
|
39
56
|
|
57
|
+
##
|
58
|
+
# How often to check the state of the tty in seconds.
|
59
|
+
# Used for detecting prompts.
|
60
|
+
# Defaults to 0.1. Reads config[:tty_state_freq].
|
61
|
+
|
62
|
+
def self.tty_state_freq
|
63
|
+
config[:tty_state_freq]
|
64
|
+
end
|
65
|
+
|
66
|
+
|
40
67
|
require 'nutshell/shell'
|
41
68
|
require 'nutshell/remote_shell'
|
42
69
|
end
|
@@ -60,7 +60,7 @@ module Nutshell
|
|
60
60
|
|
61
61
|
@user ||= options[:user]
|
62
62
|
|
63
|
-
@rsync_flags = ["-
|
63
|
+
@rsync_flags = ["-azrP"]
|
64
64
|
@rsync_flags.concat [*options[:rsync_flags]] if options[:rsync_flags]
|
65
65
|
|
66
66
|
@ssh_flags = [
|
@@ -107,7 +107,7 @@ module Nutshell
|
|
107
107
|
raise TimeoutError if timed_out?(start_time, LOGIN_TIMEOUT)
|
108
108
|
end
|
109
109
|
|
110
|
-
unless connected?
|
110
|
+
unless ready && connected?
|
111
111
|
disconnect
|
112
112
|
host_info = [@user, @host].compact.join("@")
|
113
113
|
raise ConnectionError, "Can't connect to #{host_info}"
|
@@ -165,7 +165,7 @@ module Nutshell
|
|
165
165
|
# Checks if the given file exists
|
166
166
|
|
167
167
|
def file? filepath
|
168
|
-
|
168
|
+
self.system "test -f #{filepath}"
|
169
169
|
end
|
170
170
|
|
171
171
|
|
data/lib/nutshell/shell.rb
CHANGED
@@ -10,8 +10,22 @@ module Nutshell
|
|
10
10
|
LOCAL_USER = `whoami`.chomp
|
11
11
|
LOCAL_HOST = `hostname`.chomp
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# The message to match in stderr to determine logging in has failed.
|
16
|
+
# Defaults to:
|
17
|
+
# /^Sorry, try again./
|
18
|
+
attr_accessor :sudo_failed_matcher
|
19
|
+
|
20
|
+
# The message to match in stderr to determine a password is required.
|
21
|
+
# Defaults to:
|
22
|
+
# /^Password:/
|
23
|
+
attr_accessor :sudo_prompt_matcher
|
24
|
+
end
|
25
|
+
|
26
|
+
self.sudo_failed_matcher = /^Sorry, try again./
|
27
|
+
self.sudo_prompt_matcher = /^Password:/
|
28
|
+
|
15
29
|
|
16
30
|
attr_reader :user, :host, :password, :input, :output, :mutex
|
17
31
|
attr_accessor :env, :sudo, :timeout
|
@@ -69,6 +83,14 @@ module Nutshell
|
|
69
83
|
end
|
70
84
|
|
71
85
|
|
86
|
+
##
|
87
|
+
# Prompt the user to make a choice.
|
88
|
+
|
89
|
+
def choose(&block)
|
90
|
+
sync{ @input.choose(&block) }
|
91
|
+
end
|
92
|
+
|
93
|
+
|
72
94
|
##
|
73
95
|
# Close the output IO. (Required by the Logger class)
|
74
96
|
|
@@ -206,7 +228,7 @@ module Nutshell
|
|
206
228
|
# Build an sh -c command
|
207
229
|
|
208
230
|
def sh_cmd cmd
|
209
|
-
["sh", "-c", quote_cmd(cmd)]
|
231
|
+
["sh", "-i", "-c", quote_cmd(cmd)]
|
210
232
|
end
|
211
233
|
|
212
234
|
|
@@ -258,7 +280,7 @@ module Nutshell
|
|
258
280
|
##
|
259
281
|
# Returns true if command was run successfully, otherwise returns false.
|
260
282
|
|
261
|
-
def
|
283
|
+
def system cmd, options=nil
|
262
284
|
call(cmd, options) && true rescue false
|
263
285
|
end
|
264
286
|
|
@@ -339,6 +361,8 @@ module Nutshell
|
|
339
361
|
inn.sync = true
|
340
362
|
log_methods = {out => :debug, err => :error}
|
341
363
|
|
364
|
+
status = nil
|
365
|
+
|
342
366
|
result, status = process_streams(pid, out, err) do |stream, data|
|
343
367
|
stream_name = :out if stream == out
|
344
368
|
stream_name = :err if stream == err
|
@@ -352,9 +376,7 @@ module Nutshell
|
|
352
376
|
|
353
377
|
|
354
378
|
if password_required?(stream_name, data) then
|
355
|
-
|
356
379
|
kill_process(pid) unless Nutshell.interactive?
|
357
|
-
|
358
380
|
send_password_to_stream(inn, data)
|
359
381
|
end
|
360
382
|
end
|
@@ -379,12 +401,12 @@ module Nutshell
|
|
379
401
|
|
380
402
|
|
381
403
|
def password_required? stream_name, data
|
382
|
-
stream_name == :err && data =~
|
404
|
+
stream_name == :err && data =~ Shell.sudo_prompt_matcher
|
383
405
|
end
|
384
406
|
|
385
407
|
|
386
408
|
def send_password_to_stream inn, data
|
387
|
-
prompt_for_password if data =~
|
409
|
+
prompt_for_password if data =~ Shell.sudo_failed_matcher
|
388
410
|
inn.puts @password || prompt_for_password
|
389
411
|
end
|
390
412
|
|
data/test/test_helper.rb
CHANGED
@@ -80,7 +80,7 @@ def assert_rsync from, to, ds=@remote_shell, sudo=false
|
|
80
80
|
"--rsync-path='#{ path }' "
|
81
81
|
end
|
82
82
|
|
83
|
-
rsync_cmd = "rsync -
|
83
|
+
rsync_cmd = "rsync -azrP #{rsync_path}-e \"ssh #{ds.ssh_flags.join(' ')}\""
|
84
84
|
|
85
85
|
error_msg = "No such command in remote_shell log [#{ds.host}]\n#{rsync_cmd}"
|
86
86
|
error_msg << "#{from.inspect} #{to.inspect}"
|
data/test/test_shell.rb
CHANGED
@@ -24,13 +24,13 @@ class TestShell < Test::Unit::TestCase
|
|
24
24
|
|
25
25
|
def test_ask
|
26
26
|
@shell.ask "input something!"
|
27
|
-
|
27
|
+
assert_equal 1, @shell.input.method_call_count(:ask)
|
28
28
|
end
|
29
29
|
|
30
30
|
|
31
31
|
def test_close
|
32
32
|
@shell.close
|
33
|
-
|
33
|
+
assert_equal 1, @shell.output.method_call_count(:close)
|
34
34
|
end
|
35
35
|
|
36
36
|
|
metadata
CHANGED
@@ -1,76 +1,106 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: nutshell
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 1
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
version: 1.0.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Jeremie Castagna
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-07-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: open4
|
22
|
-
|
23
|
-
|
24
|
-
requirements:
|
25
|
-
- -
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
segments:
|
28
|
-
- 1
|
29
|
-
- 0
|
30
|
-
- 1
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
31
21
|
version: 1.0.1
|
32
22
|
type: :runtime
|
33
|
-
|
34
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.0.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
35
31
|
name: highline
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.5.1
|
38
|
+
type: :runtime
|
36
39
|
prerelease: false
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
- 1
|
43
|
-
- 5
|
44
|
-
- 1
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
45
|
version: 1.5.1
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: ruby-termios
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.6
|
46
54
|
type: :runtime
|
47
|
-
version_requirements: *id002
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: hoe
|
50
55
|
prerelease: false
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.6
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rdoc
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3.10'
|
60
70
|
type: :development
|
61
|
-
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.10'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: hoe
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '3.0'
|
86
|
+
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: '3.0'
|
62
94
|
description: A light weight ssh client that wraps the ssh and rsync commands.
|
63
|
-
email:
|
95
|
+
email:
|
64
96
|
- yaksnrainbows@gmail.com
|
65
97
|
executables: []
|
66
|
-
|
67
98
|
extensions: []
|
68
|
-
|
69
|
-
extra_rdoc_files:
|
99
|
+
extra_rdoc_files:
|
70
100
|
- History.txt
|
71
101
|
- Manifest.txt
|
72
102
|
- README.txt
|
73
|
-
files:
|
103
|
+
files:
|
74
104
|
- History.txt
|
75
105
|
- Manifest.txt
|
76
106
|
- README.txt
|
@@ -83,38 +113,34 @@ files:
|
|
83
113
|
- test/test_helper.rb
|
84
114
|
- test/test_remote_shell.rb
|
85
115
|
- test/test_shell.rb
|
86
|
-
|
87
|
-
homepage: http://
|
116
|
+
- .gemtest
|
117
|
+
homepage: http://yaks.me/nutshell
|
88
118
|
licenses: []
|
89
|
-
|
90
119
|
post_install_message:
|
91
|
-
rdoc_options:
|
120
|
+
rdoc_options:
|
92
121
|
- --main
|
93
122
|
- README.txt
|
94
|
-
require_paths:
|
123
|
+
require_paths:
|
95
124
|
- lib
|
96
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
requirements:
|
105
|
-
- -
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
|
108
|
-
- 0
|
109
|
-
version: "0"
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ! '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
110
137
|
requirements: []
|
111
|
-
|
112
138
|
rubyforge_project: nutshell
|
113
|
-
rubygems_version: 1.
|
139
|
+
rubygems_version: 1.8.23
|
114
140
|
signing_key:
|
115
141
|
specification_version: 3
|
116
142
|
summary: A light weight ssh client that wraps the ssh and rsync commands.
|
117
|
-
test_files:
|
143
|
+
test_files:
|
118
144
|
- test/test_helper.rb
|
119
145
|
- test/test_remote_shell.rb
|
120
146
|
- test/test_shell.rb
|