net-ssh-shell 0.1.0 → 0.2.0

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,4 @@
1
+ *.swp
2
+ pkg
3
+ doc
4
+ Gemfile.lock
@@ -0,0 +1,10 @@
1
+ ## 0.2.0 (unreleased)
2
+
3
+ - Loosen regex on `on_stdout` [GH-1]
4
+ - Capture stderr from shell. This won't capture the stderr of the processes
5
+ running. Instead it will just capture any error output from the shell process.
6
+ - Ability to specify the default process class to use for `Shell#execute`
7
+
8
+ ## 0.1.0 (October 24, 2010)
9
+
10
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "net-ssh-shell", :path => '.'
@@ -41,12 +41,12 @@ If you want to use any of the Rake tasks, you'll need:
41
41
  * Echoe (for the Rakefile)
42
42
 
43
43
  == INSTALL:
44
- This gem is not yet on rubygems , so you have to install it from this source
44
+
45
+ This gem is available from RubyGems, so you can install it using the "gem" command:
45
46
 
46
47
  * gem install net-ssh-shell
47
- ERROR: could not find gem net-ssh-shell locally or in a repository
48
48
 
49
- Therefor you need to build the gem yourself:
49
+ If you'd like to build the gem for yourself from source:
50
50
  * git clone http://github.com/jedi4ever/net-ssh-shell.git
51
51
  * cd net-ssh-shell
52
52
  * gem install echoe
data/Rakefile CHANGED
@@ -1,28 +1,3 @@
1
- require './lib/net/ssh/shell/version'
2
-
3
- begin
4
- require 'echoe'
5
- rescue LoadError
6
- abort "You'll need to have `echoe' installed to use Net::SSH::Shell's Rakefile"
7
- end
8
-
9
- version = Net::SSH::Shell::Version::STRING.dup
10
- if ENV['SNAPSHOT'].to_i == 1
11
- version << "." << Time.now.utc.strftime("%Y%m%d%H%M%S")
12
- end
13
-
14
- Echoe.new('net-ssh-shell', version) do |p|
15
- p.changelog = "CHANGELOG.rdoc"
16
-
17
- p.author = "Jamis Buck"
18
- p.email = "jamis@jamisbuck.org"
19
- p.summary = "A simple library to aid with stateful shell interactions"
20
- p.url = "http://net-ssh.rubyforge.org/shell"
21
-
22
- p.dependencies = ["net-ssh >=2.0.9"]
23
-
24
- p.need_zip = true
25
- p.include_rakefile = true
26
-
27
- p.rdoc_pattern = /^(lib|README.rdoc|CHANGELOG.rdoc)/
28
- end
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ Bundler::GemHelper.install_tasks
@@ -11,6 +11,7 @@ module Net
11
11
  attr_reader :state
12
12
  attr_reader :shell
13
13
  attr_reader :processes
14
+ attr_accessor :default_process_class
14
15
 
15
16
  def initialize(session, shell=:default)
16
17
  @session = session
@@ -18,6 +19,8 @@ module Net
18
19
  @state = :closed
19
20
  @processes = []
20
21
  @when_open = []
22
+ @on_process_run = nil
23
+ @default_process_class = Net::SSH::Shell::Process
21
24
  open
22
25
  end
23
26
 
@@ -26,6 +29,7 @@ module Net
26
29
  @state = :opening
27
30
  @channel = session.open_channel(&method(:open_succeeded))
28
31
  @channel.on_open_failed(&method(:open_failed))
32
+ @channel.on_request('exit-status', &method(:on_exit_status))
29
33
  end
30
34
  when_open(&callback) if callback
31
35
  self
@@ -60,11 +64,23 @@ module Net
60
64
  !open? && !closed?
61
65
  end
62
66
 
63
- def execute(command, klass=Net::SSH::Shell::Process, &callback)
64
- process = klass.new(self, command, callback)
65
- process.run if processes.empty?
67
+ def on_process_run(&callback)
68
+ @on_process_run = callback
69
+ end
70
+
71
+ def execute(command, *args, &callback)
72
+ # The class is an optional second argument.
73
+ klass = default_process_class
74
+ klass = args.shift if args.first.is_a?(Class)
75
+
76
+ # The properties are expected to be the next argument.
77
+ props = {}
78
+ props = args.shift if args.first.is_a?(Hash)
79
+
80
+ process = klass.new(self, command, props, callback)
66
81
  processes << process
67
- return process
82
+ run_next_process if processes.length == 1
83
+ process
68
84
  end
69
85
 
70
86
  def subshell(command, &callback)
@@ -72,9 +88,9 @@ module Net
72
88
  end
73
89
 
74
90
  def execute!(command, &callback)
75
- execute(command, &callback)
91
+ process = execute(command, &callback)
76
92
  wait!
77
- return process
93
+ process
78
94
  end
79
95
 
80
96
  def busy?
@@ -92,7 +108,7 @@ module Net
92
108
  def child_finished(child)
93
109
  channel.on_close(&method(:on_channel_close)) if !channel.nil?
94
110
  processes.delete(child)
95
- processes.first.run if processes.any?
111
+ run_next_process
96
112
  end
97
113
 
98
114
  def separator
@@ -109,41 +125,55 @@ module Net
109
125
 
110
126
  private
111
127
 
112
- def open_succeeded(channel)
113
- @state = :pty
114
- channel.on_close(&method(:on_channel_close))
115
- channel.request_pty(:modes => { Net::SSH::Connection::Term::ECHO => 0 }, &method(:pty_requested))
128
+ def run_next_process
129
+ if processes.any?
130
+ process = processes.first
131
+ @on_process_run.call(self, process) if @on_process_run
132
+ process.run
116
133
  end
134
+ end
117
135
 
118
- def open_failed(channel, code, description)
119
- @state = :closed
120
- raise "could not open channel for process manager (#{description}, ##{code})"
121
- end
136
+ def open_succeeded(channel)
137
+ @state = :pty
138
+ channel.on_close(&method(:on_channel_close))
139
+ channel.request_pty(:modes => { Net::SSH::Connection::Term::ECHO => 0 }, &method(:pty_requested))
140
+ end
141
+
142
+ def open_failed(channel, code, description)
143
+ @state = :closed
144
+ raise "could not open channel for process manager (#{description}, ##{code})"
145
+ end
122
146
 
123
- def pty_requested(channel, success)
124
- @state = :shell
125
- raise "could not request pty for process manager" unless success
126
- if shell == :default
127
- channel.send_channel_request("shell", &method(:shell_requested))
128
- else
129
- channel.exec(shell, &method(:shell_requested))
130
- end
147
+ def on_exit_status(channel, data)
148
+ unless data.read_long == 0
149
+ raise "the shell exited unexpectedly"
131
150
  end
151
+ end
132
152
 
133
- def shell_requested(channel, success)
134
- @state = :initializing
135
- raise "could not request shell for process manager" unless success
136
- channel.on_data(&method(:look_for_initialization_done))
137
- channel.send_data "export PS1=; echo #{separator} $?\n"
153
+ def pty_requested(channel, success)
154
+ @state = :shell
155
+ raise "could not request pty for process manager" unless success
156
+ if shell == :default
157
+ channel.send_channel_request("shell", &method(:shell_requested))
158
+ else
159
+ channel.exec(shell, &method(:shell_requested))
138
160
  end
161
+ end
162
+
163
+ def shell_requested(channel, success)
164
+ @state = :initializing
165
+ raise "could not request shell for process manager" unless success
166
+ channel.on_data(&method(:look_for_initialization_done))
167
+ channel.send_data "export PS1=; echo #{separator} $?\n"
168
+ end
139
169
 
140
- def look_for_initialization_done(channel, data)
141
- if data.include?(separator)
142
- @state = :open
143
- @when_open.each { |callback| callback.call(self) }
144
- @when_open.clear
145
- end
170
+ def look_for_initialization_done(channel, data)
171
+ if data.include?(separator)
172
+ @state = :open
173
+ @when_open.each { |callback| callback.call(self) }
174
+ @when_open.clear
146
175
  end
176
+ end
147
177
  end
148
178
  end
149
179
  end
@@ -155,6 +185,6 @@ class Net::SSH::Connection::Session
155
185
  def shell(*args)
156
186
  shell = Net::SSH::Shell.new(self, *args)
157
187
  yield shell if block_given?
158
- return shell
188
+ shell
159
189
  end
160
190
  end
@@ -1,5 +1,4 @@
1
1
  module Net; module SSH; class Shell
2
-
3
2
  class Process
4
3
  attr_reader :state
5
4
  attr_reader :command
@@ -8,12 +7,13 @@ module Net; module SSH; class Shell
8
7
  attr_reader :exit_status
9
8
  attr_reader :properties
10
9
 
11
- def initialize(manager, command, callback)
10
+ def initialize(manager, command, properties, callback)
12
11
  @command = command
13
12
  @manager = manager
14
13
  @callback = callback
15
- @properties = {}
16
- @on_output = Proc.new { |p, data| print(data) }
14
+ @properties = properties
15
+ @on_output = nil
16
+ @on_error_output = nil
17
17
  @on_finish = nil
18
18
  @state = :new
19
19
  end
@@ -36,14 +36,16 @@ module Net; module SSH; class Shell
36
36
  manager.open do
37
37
  state = :running
38
38
  manager.channel.on_data(&method(:on_stdout))
39
- @master_onclose = manager.channel.on_close(&method(:on_close))
39
+ manager.channel.on_extended_data(&method(:on_stderr))
40
+ manager.channel.on_close(&method(:on_close))
41
+
42
+ callback.call(self) if callback
40
43
 
41
44
  cmd = command.dup
42
45
  cmd << ";" if cmd !~ /[;&]$/
43
46
  cmd << " DONTEVERUSETHIS=$?; echo #{manager.separator} $DONTEVERUSETHIS; echo \"exit $DONTEVERUSETHIS\"|sh"
44
47
 
45
48
  send_data(cmd + "\n")
46
- callback.call(self) if callback
47
49
  end
48
50
  end
49
51
 
@@ -75,38 +77,44 @@ module Net; module SSH; class Shell
75
77
  @on_output = callback
76
78
  end
77
79
 
80
+ def on_error_output(&callback)
81
+ @on_error_output = callback
82
+ end
83
+
78
84
  def on_finish(&callback)
79
85
  @on_finish = callback
80
86
  end
81
87
 
82
- private
88
+ protected
83
89
 
84
- def output!(data)
85
- return unless @on_output
86
- @on_output.call(self, data)
87
- end
90
+ def output!(data)
91
+ @on_output.call(self, data) if @on_output
92
+ end
88
93
 
89
- def on_stdout(ch, data)
90
- if data.strip =~ /^#{manager.separator} (\d+)$/
91
- before = $`
92
- output!(before) unless before.empty?
93
- finished!($1)
94
- else
95
- output!(data)
96
- end
94
+ def on_stdout(ch, data)
95
+ if data.strip =~ /#{manager.separator} (\d+)$/
96
+ before = $`
97
+ output!(before) unless before.empty?
98
+ finished!($1)
99
+ else
100
+ output!(data)
97
101
  end
102
+ end
98
103
 
99
- def on_close(ch)
100
- manager.on_channel_close(ch)
101
- finished!(-1)
102
- end
104
+ def on_stderr(ch, type, data)
105
+ @on_error_output.call(self, data) if @on_error_output
106
+ end
103
107
 
104
- def finished!(status)
105
- @state = :finished
106
- @exit_status = status.to_i
107
- @on_finish.call(self) if @on_finish
108
- manager.child_finished(self)
109
- end
110
- end
108
+ def on_close(ch)
109
+ manager.on_channel_close(ch)
110
+ finished!(-1)
111
+ end
111
112
 
113
+ def finished!(status)
114
+ @state = :finished
115
+ @exit_status = status.to_i
116
+ @on_finish.call(self) if @on_finish
117
+ manager.child_finished(self)
118
+ end
119
+ end
112
120
  end; end; end
@@ -1,23 +1,21 @@
1
1
  require 'net/ssh/shell/process'
2
2
 
3
3
  module Net; module SSH; class Shell
4
-
5
4
  class Subshell < Process
6
- private
5
+ protected
7
6
 
8
- def on_stdout(ch, data)
9
- if !output!(data)
10
- ch.on_data(&method(:look_for_finalize_initializer))
11
- ch.send_data("export PS1=; echo #{manager.separator} $?\n")
12
- end
7
+ def on_stdout(ch, data)
8
+ if !output!(data)
9
+ ch.on_data(&method(:look_for_finalize_initializer))
10
+ ch.send_data("export PS1=; echo #{manager.separator} $?\n")
13
11
  end
12
+ end
14
13
 
15
- def look_for_finalize_initializer(ch, data)
16
- if data =~ /#{manager.separator} (\d+)/
17
- ch.on_close(&@master_onclose)
18
- finished!($1)
19
- end
14
+ def look_for_finalize_initializer(ch, data)
15
+ if data =~ /#{manager.separator} (\d+)/
16
+ ch.on_close(&@master_onclose)
17
+ finished!($1)
20
18
  end
19
+ end
21
20
  end
22
-
23
- end; end; end
21
+ end; end; end
@@ -1,22 +1,7 @@
1
- require 'net/ssh/version'
2
-
3
- module Net; module SSH; module Shell
4
- # A trivial class for representing the version of this library.
5
- class Version < Net::SSH::Version
6
- # The major component of the library's version
7
- MAJOR = 0
8
-
9
- # The minor component of the library's version
10
- MINOR = 1
11
-
12
- # The tiny component of the library's version
13
- TINY = 0
14
-
15
- # The library's version as a Version instance
16
- CURRENT = new(MAJOR, MINOR, TINY)
17
-
18
- # The library's version as a String instance
19
- STRING = CURRENT.to_s
1
+ module Net
2
+ module SSH
3
+ class Shell
4
+ VERSION = "0.2.0"
5
+ end
20
6
  end
21
- end; end; end
22
-
7
+ end
@@ -1,33 +1,23 @@
1
- # -*- encoding: utf-8 -*-
1
+ require File.expand_path("../lib/net/ssh/shell/version", __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = %q{net-ssh-shell}
5
- s.version = "0.1.0"
4
+ s.name = "net-ssh-shell"
5
+ s.version = Net::SSH::Shell::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Jamis Buck"]
8
+ s.email = ["jamis@jamisbuck.org"]
9
+ s.homepage = "http://github.com/mitchellh/net-ssh-shell"
10
+ s.summary = "A simple library to aid with stateful shell interactions"
11
+ s.description = "A simple library to aid with stateful shell interactions"
6
12
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Jamis Buck"]
9
- s.date = %q{2010-10-25}
10
- s.description = %q{A simple library to aid with stateful shell interactions}
11
- s.email = %q{jamis@jamisbuck.org}
12
- s.extra_rdoc_files = ["CHANGELOG.rdoc", "lib/net/ssh/shell/process.rb", "lib/net/ssh/shell/subshell.rb", "lib/net/ssh/shell/version.rb", "lib/net/ssh/shell.rb", "README.rdoc"]
13
- s.files = ["CHANGELOG.rdoc", "lib/net/ssh/shell/process.rb", "lib/net/ssh/shell/subshell.rb", "lib/net/ssh/shell/version.rb", "lib/net/ssh/shell.rb", "Rakefile", "README.rdoc", "Manifest", "net-ssh-shell.gemspec"]
14
- s.homepage = %q{http://net-ssh.rubyforge.org/shell}
15
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Net-ssh-shell", "--main", "README.rdoc"]
16
- s.require_paths = ["lib"]
17
- s.rubyforge_project = %q{net-ssh-shell}
18
- s.rubygems_version = %q{1.3.7}
19
- s.summary = %q{A simple library to aid with stateful shell interactions}
13
+ s.required_rubygems_version = ">= 1.3.6"
14
+ s.rubyforge_project = "net-ssh-shell"
20
15
 
21
- if s.respond_to? :specification_version then
22
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
- s.specification_version = 3
16
+ s.add_dependency "net-ssh", "~> 2.1.0"
24
17
 
25
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
- s.add_runtime_dependency(%q<net-ssh>, [">= 2.0.9"])
27
- else
28
- s.add_dependency(%q<net-ssh>, [">= 2.0.9"])
29
- end
30
- else
31
- s.add_dependency(%q<net-ssh>, [">= 2.0.9"])
32
- end
18
+ s.add_development_dependency "rake"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
22
+ s.require_path = 'lib'
33
23
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-ssh-shell
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
4
+ prerelease:
5
+ version: 0.2.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Jamis Buck
@@ -15,60 +10,56 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2010-10-25 00:00:00 +04:00
19
- default_executable:
13
+ date: 2011-06-13 00:00:00 Z
20
14
  dependencies:
21
15
  - !ruby/object:Gem::Dependency
22
16
  name: net-ssh
23
- prerelease: false
24
17
  requirement: &id001 !ruby/object:Gem::Requirement
25
18
  none: false
26
19
  requirements:
27
- - - ">="
20
+ - - ~>
28
21
  - !ruby/object:Gem::Version
29
- hash: 29
30
- segments:
31
- - 2
32
- - 0
33
- - 9
34
- version: 2.0.9
22
+ version: 2.1.0
35
23
  type: :runtime
24
+ prerelease: false
36
25
  version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rake
28
+ requirement: &id002 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *id002
37
37
  description: A simple library to aid with stateful shell interactions
38
- email: jamis@jamisbuck.org
38
+ email:
39
+ - jamis@jamisbuck.org
39
40
  executables: []
40
41
 
41
42
  extensions: []
42
43
 
43
- extra_rdoc_files:
44
- - CHANGELOG.rdoc
45
- - lib/net/ssh/shell/process.rb
46
- - lib/net/ssh/shell/subshell.rb
47
- - lib/net/ssh/shell/version.rb
48
- - lib/net/ssh/shell.rb
49
- - README.rdoc
44
+ extra_rdoc_files: []
45
+
50
46
  files:
51
- - CHANGELOG.rdoc
47
+ - .gitignore
48
+ - CHANGELOG.md
49
+ - Gemfile
50
+ - README.rdoc
51
+ - Rakefile
52
+ - lib/net/ssh/shell.rb
52
53
  - lib/net/ssh/shell/process.rb
53
54
  - lib/net/ssh/shell/subshell.rb
54
55
  - lib/net/ssh/shell/version.rb
55
- - lib/net/ssh/shell.rb
56
- - Rakefile
57
- - README.rdoc
58
- - Manifest
59
56
  - net-ssh-shell.gemspec
60
- has_rdoc: true
61
- homepage: http://net-ssh.rubyforge.org/shell
57
+ homepage: http://github.com/mitchellh/net-ssh-shell
62
58
  licenses: []
63
59
 
64
60
  post_install_message:
65
- rdoc_options:
66
- - --line-numbers
67
- - --inline-source
68
- - --title
69
- - Net-ssh-shell
70
- - --main
71
- - README.rdoc
61
+ rdoc_options: []
62
+
72
63
  require_paths:
73
64
  - lib
74
65
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -76,7 +67,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
76
67
  requirements:
77
68
  - - ">="
78
69
  - !ruby/object:Gem::Version
79
- hash: 3
70
+ hash: -9612031956568265
80
71
  segments:
81
72
  - 0
82
73
  version: "0"
@@ -85,15 +76,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
76
  requirements:
86
77
  - - ">="
87
78
  - !ruby/object:Gem::Version
88
- hash: 11
89
- segments:
90
- - 1
91
- - 2
92
- version: "1.2"
79
+ version: 1.3.6
93
80
  requirements: []
94
81
 
95
82
  rubyforge_project: net-ssh-shell
96
- rubygems_version: 1.3.7
83
+ rubygems_version: 1.8.5
97
84
  signing_key:
98
85
  specification_version: 3
99
86
  summary: A simple library to aid with stateful shell interactions
@@ -1,3 +0,0 @@
1
- === (unreleased)
2
-
3
- * Initial release
data/Manifest DELETED
@@ -1,8 +0,0 @@
1
- CHANGELOG.rdoc
2
- lib/net/ssh/shell/process.rb
3
- lib/net/ssh/shell/subshell.rb
4
- lib/net/ssh/shell/version.rb
5
- lib/net/ssh/shell.rb
6
- Rakefile
7
- README.rdoc
8
- Manifest