ng 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,24 +1,43 @@
1
1
  # ng - Pure-Ruby Nailgun client port
2
2
 
3
- Eliminates the need to shell-out when using Nailgun
3
+ Eliminates the need to shell-out to the `ng` binary when using Nailgun, by implementing the Nailgun Protocol in pure Ruby code.
4
+
5
+ This was an experiment, so don't consider it stable.
6
+
7
+ I've noticed that Nailgun doesn't like when its IO buffer fills up, and it will if you don't empty it fast enough. Ruby may not be fast enough to handle this job, so if you're trying to send/receive lots of data, this may not work for you. If you're just sending some signals and getting small return values, it may yet.
4
8
 
5
9
  ## Installation
6
10
 
7
- Add this line to your application's Gemfile:
11
+ $ gem install ng
8
12
 
9
- gem 'ng'
13
+ ## Usage
10
14
 
11
- And then execute:
15
+ ```Ruby
16
+ # instantiate a new client (optional option overrides may be passed in)
17
+ client = Nailgun::Client.new(port: 2114)
12
18
 
13
- $ bundle
19
+ # send this command to the server
20
+ client.run('java.Command', :arg1, 2) # args are splatted on the instance method
14
21
 
15
- Or install it yourself as:
22
+ # shouldn't be strictly necessary to close the socket manually, but it's there if you want it
23
+ client.close!
24
+ ```
16
25
 
17
- $ gem install ng
26
+ A class method is also available:
18
27
 
19
- ## Usage
28
+ ```Ruby
29
+ Nailgun::Client.run('java.Command', [:arg1, 2], port: 2114) # args must be explicitly an array here
30
+ ```
31
+
32
+ Or, if you prefer, there is a block form available, which automatically closes the socket at completion
33
+
34
+ ```Ruby
35
+ Nailgun::Client.new do |client|
36
+
37
+ client.run('java.Command', [:arg1, 2])
20
38
 
21
- TODO: Write usage instructions here
39
+ end
40
+ ```
22
41
 
23
42
  ## Contributing
24
43
 
@@ -5,6 +5,51 @@ require 'timeout'
5
5
 
6
6
  module Nailgun
7
7
  class Client
8
+
9
+ DEFAULTS = {
10
+ hostname: 'localhost',
11
+ port: 2113,
12
+ stdin: nil,
13
+ stdout: STDOUT,
14
+ stderr: STDERR,
15
+ env: ENV,
16
+ dir: Dir.pwd
17
+ }.freeze
18
+
19
+ CHUNK_HEADER_LEN = 5
20
+
21
+ TIMEOUT = 5
22
+
23
+ TimeoutError = Class.new(StandardError)
24
+ SocketFailedError = Class.new(StandardError)
25
+ ConnectFailedError = Class.new(StandardError)
26
+ UnexpectedChunktypeError = Class.new(StandardError)
27
+ ServerExceptionError = Class.new(StandardError)
28
+ ConnectionBrokenError = Class.new(StandardError)
29
+ BadArgumentsError = Class.new(StandardError)
30
+ OtherError = Class.new(StandardError)
31
+
32
+ EXIT_CODE_EXCEPTIONS = {
33
+ 999 => SocketFailedError,
34
+ 998 => ConnectFailedError,
35
+ 997 => UnexpectedChunktypeError,
36
+ 996 => ServerExceptionError,
37
+ 995 => ConnectionBrokenError,
38
+ 994 => BadArgumentsError
39
+ }.freeze
40
+
41
+ CHUNK_TYPES = {
42
+ stdin: '0',
43
+ stdout: '1',
44
+ stderr: '2',
45
+ stdin_eof: '.',
46
+ arg: 'A',
47
+ env: 'E',
48
+ dir: 'D',
49
+ cmd: 'C',
50
+ exit: 'X'
51
+ }.freeze
52
+
8
53
  attr_reader :opts, :socket
9
54
 
10
55
  # Public: Convinience method to instantiate and run the command
@@ -20,10 +65,16 @@ module Nailgun
20
65
 
21
66
  # Public: Initialize a Client.
22
67
  #
23
- # opts = {} - a Hash of options to override the defaults in Nailgun::DEFAULTS
68
+ # opts = {} - a Hash of options to override the defaults in DEFAULTS
24
69
  def initialize(opts = {})
25
- @opts = Nailgun::DEFAULTS.merge(opts)
70
+ @opts = DEFAULTS.merge(opts)
26
71
  @socket = TCPSocket.new(*@opts.values_at(:hostname, :port))
72
+
73
+ if block_given?
74
+ yield self
75
+ @socket.close
76
+ return nil
77
+ end
27
78
  end
28
79
 
29
80
  # Public: Run a command on the Client instance
@@ -54,6 +105,11 @@ module Nailgun
54
105
  end
55
106
  }
56
107
  end
108
+
109
+ # Public: Explicitly close the TCPSocket
110
+ def close!
111
+ socket.close
112
+ end
57
113
 
58
114
  private
59
115
 
@@ -113,7 +169,7 @@ module Nailgun
113
169
 
114
170
  # Private: get the next chunk from the socket, and then determine what to do with it.
115
171
  def receive_chunk
116
- Timeout.timeout(Nailgun::TIMEOUT, Nailgun::TimeoutError) do
172
+ Timeout.timeout(TIMEOUT, TimeoutError) do
117
173
  length, type = receive_header
118
174
  if length > 0
119
175
  content = socket.read(length)
@@ -127,7 +183,7 @@ module Nailgun
127
183
  #
128
184
  # Returns [length, type]
129
185
  def receive_header
130
- socket.read(Nailgun::CHUNK_HEADER_LEN).unpack('NA')
186
+ socket.read(CHUNK_HEADER_LEN).unpack('NA')
131
187
  end
132
188
 
133
189
  # Private: Determine what to do with the received chunk
@@ -135,24 +191,24 @@ module Nailgun
135
191
  # type - chunk type
136
192
  # content - chunk content
137
193
  def handle_chunk(type, content)
138
- case t = Nailgun::CHUNK_TYPES.key(type)
194
+ case t = CHUNK_TYPES.key(type)
139
195
  when :stdout, :stderr
140
196
  opts[t].write content
141
197
  when :exit
142
198
  socket.close
143
199
  handle_exit(content.to_i)
144
200
  else
145
- raise Nailgun::UnexpectedChunktypeError.new([type, content].join(?;))
201
+ raise UnexpectedChunktypeError.new([type, content].join(?;))
146
202
  end
147
203
  end
148
204
 
149
205
  def handle_exit(code)
150
206
  if code == 0
151
207
  throw :exit
152
- elsif ex = Nailgun::EXIT_CODE_EXCEPTIONS[code]
208
+ elsif ex = EXIT_CODE_EXCEPTIONS[code]
153
209
  raise ex.new
154
210
  else
155
- raise Nailgun::OtherError.new(code.to_s)
211
+ raise OtherError.new(code.to_s)
156
212
  end
157
213
  end
158
214
 
@@ -2,7 +2,7 @@ module Nailgun
2
2
  class Client
3
3
  class ChunkHeader
4
4
  def initialize(type, content_length)
5
- @type = Nailgun::CHUNK_TYPES[type]
5
+ @type = Client::CHUNK_TYPES[type]
6
6
  @content_length = content_length
7
7
  end
8
8
 
@@ -0,0 +1,5 @@
1
+ module Nailgun
2
+ class Client
3
+ VERSION = '0.0.3'
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'nailgun/client'
2
+ require_relative 'nailgun/client/version'
data/ng.gemspec CHANGED
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/nailgun/version', __FILE__)
2
+ require File.expand_path('../lib/nailgun/client/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ['Ryan Taylor Long']
@@ -13,5 +13,5 @@ Gem::Specification.new do |gem|
13
13
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
14
  gem.name = 'ng'
15
15
  gem.require_paths = ['lib']
16
- gem.version = Nailgun::VERSION
16
+ gem.version = Nailgun::Client::VERSION
17
17
  end
@@ -0,0 +1,7 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gem 'nailgun', github: 'amardaxini/nailgun'
5
+ gem "ng", path: '../'
6
+
7
+ gem 'pry'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ng
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-18 00:00:00.000000000 Z
12
+ date: 2012-11-02 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Pure-Ruby Nailgun client port
15
15
  email:
@@ -23,12 +23,13 @@ files:
23
23
  - LICENSE
24
24
  - README.md
25
25
  - Rakefile
26
- - lib/nailgun.rb
27
26
  - lib/nailgun/client.rb
28
27
  - lib/nailgun/client/chunk.rb
29
28
  - lib/nailgun/client/chunk_header.rb
30
- - lib/nailgun/version.rb
29
+ - lib/nailgun/client/version.rb
30
+ - lib/ng.rb
31
31
  - ng.gemspec
32
+ - test_app/Gemfile
32
33
  homepage: ''
33
34
  licenses: []
34
35
  post_install_message:
@@ -1,49 +0,0 @@
1
- require_relative 'nailgun/version'
2
- require_relative 'nailgun/client'
3
-
4
- module Nailgun
5
-
6
- DEFAULTS = {
7
- hostname: 'localhost',
8
- port: 2113,
9
- stdin: nil,
10
- stdout: STDOUT,
11
- stderr: STDERR,
12
- env: ENV,
13
- dir: Dir.pwd
14
- }.freeze
15
-
16
- CHUNK_HEADER_LEN = 5
17
-
18
- TIMEOUT = 5
19
-
20
- TimeoutError = Class.new(StandardError)
21
- SocketFailedError = Class.new(StandardError)
22
- ConnectFailedError = Class.new(StandardError)
23
- UnexpectedChunktypeError = Class.new(StandardError)
24
- ServerExceptionError = Class.new(StandardError)
25
- ConnectionBrokenError = Class.new(StandardError)
26
- BadArgumentsError = Class.new(StandardError)
27
- OtherError = Class.new(StandardError)
28
-
29
- EXIT_CODE_EXCEPTIONS = {
30
- 999 => SocketFailedError,
31
- 998 => ConnectFailedError,
32
- 997 => UnexpectedChunktypeError,
33
- 996 => ServerExceptionError,
34
- 995 => ConnectionBrokenError,
35
- 994 => BadArgumentsError
36
- }.freeze
37
-
38
- CHUNK_TYPES = {
39
- stdin: '0',
40
- stdout: '1',
41
- stderr: '2',
42
- stdin_eof: '.',
43
- arg: 'A',
44
- env: 'E',
45
- dir: 'D',
46
- cmd: 'C',
47
- exit: 'X'
48
- }.freeze
49
- end
@@ -1,3 +0,0 @@
1
- module Nailgun
2
- VERSION = '0.0.2'
3
- end