komenda 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.
- checksums.yaml +4 -4
- data/README.md +36 -3
- data/lib/komenda.rb +15 -7
- data/lib/komenda/process.rb +109 -0
- data/lib/komenda/process_builder.rb +31 -0
- metadata +18 -4
- data/lib/komenda/definition.rb +0 -20
- data/lib/komenda/runner.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88de98a8e1d12b4b613978ba42a78e239e4a37d5
|
4
|
+
data.tar.gz: 0bf5019ac2520a5c51290d7b80a897c3c32ae86c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ecef5f25f1866b5fe846489b26db3e6e4682a87e74d3b7a2a4adabe19ce80d886cd0239e4d6a828ac132b3d89b1cfa51b83b6a2e067d2ceb5626205997e6f24
|
7
|
+
data.tar.gz: b0af38deff1bb138effcda501f5c3c87b2f12ceba21d82b251ecf333347e4a76e8f344e206f44cdf26fb3e1a0cfdd50f6476ad37303ed93462b656e6e3073d4c
|
data/README.md
CHANGED
@@ -6,14 +6,14 @@ Usage
|
|
6
6
|
-----
|
7
7
|
Run a command:
|
8
8
|
```ruby
|
9
|
-
Komenda.run(
|
9
|
+
Komenda.run('date')
|
10
10
|
```
|
11
11
|
|
12
12
|
The `run()` method will block until the sub process finished.
|
13
13
|
|
14
14
|
It will expose the output and exit status as a `Komenda::Result` value:
|
15
15
|
```ruby
|
16
|
-
result = Komenda.run(
|
16
|
+
result = Komenda.run('date')
|
17
17
|
result.stdout # => "Tue Nov 26 14:45:03 EST 2013\n"
|
18
18
|
result.stderr # => ""
|
19
19
|
result.output # => "Tue Nov 26 14:45:03 EST 2013\n" (combined stdout + stderr)
|
@@ -21,9 +21,42 @@ result.status # => 0
|
|
21
21
|
result.success? # => true
|
22
22
|
result.pid # => 32157
|
23
23
|
```
|
24
|
+
The program and its arguments can be passed as an array:
|
25
|
+
```ruby
|
26
|
+
result = Komenda.run(['echo', '-n', 'hello'])
|
27
|
+
result.output # => "hello"
|
28
|
+
```
|
24
29
|
|
25
30
|
The `run()` method has a second argument `options`, which expects these keys:
|
26
31
|
- **`env`** (Hash): The environment variables to use. Defaults to the current process' environment.
|
32
|
+
- **`cwd`** (String): Directory to change to before running the process. Defaults to `nil`.
|
33
|
+
|
34
|
+
### Advanced usage
|
35
|
+
The `create()` method creates a `Process` which can be `start()`ed (in a Thread) and then `wait_for()`ed until finished.
|
36
|
+
```ruby
|
37
|
+
process = Komenda.create('date')
|
38
|
+
thread = process.start
|
39
|
+
result = process.wait_for
|
40
|
+
```
|
41
|
+
|
42
|
+
To start a process and wait for it to finish, call the process' `run()` method:
|
43
|
+
```
|
44
|
+
process = Komenda.create('date')
|
45
|
+
result = process.run
|
46
|
+
```
|
47
|
+
|
48
|
+
Event callbacks can be registered with `Process.on()`, for example for when output is written.
|
49
|
+
```ruby
|
50
|
+
process = Komenda.create('date')
|
51
|
+
process.on(:stdout) { |output| puts "STDOUT: #{output}" }
|
52
|
+
result = process.wait_for
|
53
|
+
```
|
54
|
+
The following events are emitted:
|
55
|
+
- **`.on(:stdout) { |output| }`**: When data is available on STDOUT.
|
56
|
+
- **`.on(:stderr) { |output| }`**: When data is available on STDERR.
|
57
|
+
- **`.on(:output) { |output| }`**: When data is available on STDOUT or STDERR.
|
58
|
+
- **`.on(:exit) { |result| }`**: When the process finishes.
|
59
|
+
- **`.on(:error) { |exception| }`**: When process execution fails (e.g. executable file cannot be found).
|
27
60
|
|
28
61
|
Development
|
29
62
|
-----------
|
@@ -41,4 +74,4 @@ TODO
|
|
41
74
|
----
|
42
75
|
Add options for:
|
43
76
|
- Passing STDIN
|
44
|
-
- Making `run()` fail when exit status is not
|
77
|
+
- Making `run()` fail when exit status is not '0'
|
data/lib/komenda.rb
CHANGED
@@ -1,18 +1,26 @@
|
|
1
1
|
require 'open3'
|
2
|
+
require 'event_emitter'
|
2
3
|
|
3
|
-
require 'komenda/
|
4
|
-
require 'komenda/
|
4
|
+
require 'komenda/process_builder'
|
5
|
+
require 'komenda/process'
|
5
6
|
require 'komenda/result'
|
6
7
|
|
7
8
|
module Komenda
|
8
9
|
|
9
|
-
# @param [String]
|
10
|
+
# @param [String] command
|
11
|
+
# @param [Hash] options
|
12
|
+
# @return [Komenda::Process]
|
13
|
+
def self.create(command, options = {})
|
14
|
+
process_builder = Komenda::ProcessBuilder.new(command, options)
|
15
|
+
process_builder.create
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param [String] command
|
10
19
|
# @param [Hash] options
|
11
20
|
# @return [Komenda::Result]
|
12
|
-
def self.run(
|
13
|
-
|
14
|
-
|
15
|
-
runner.run(definition)
|
21
|
+
def self.run(command, options = {})
|
22
|
+
process_builder = Komenda::ProcessBuilder.new(command, options)
|
23
|
+
process_builder.create.run
|
16
24
|
end
|
17
25
|
|
18
26
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Komenda
|
2
|
+
class Process
|
3
|
+
|
4
|
+
attr_reader :output
|
5
|
+
|
6
|
+
include EventEmitter
|
7
|
+
|
8
|
+
# @param [ProcessBuilder] process_builder
|
9
|
+
def initialize(process_builder)
|
10
|
+
@process_builder = process_builder
|
11
|
+
@output = {:stdout => '', :stderr => '', :combined => ''}
|
12
|
+
@exit_status = nil
|
13
|
+
@thread = nil
|
14
|
+
|
15
|
+
on(:stdout) { |data| @output[:stdout] += data }
|
16
|
+
on(:stderr) { |data| @output[:stderr] += data }
|
17
|
+
on(:output) { |data| @output[:combined] += data }
|
18
|
+
process_builder.events.each do |event|
|
19
|
+
on(event[:type], &event[:listener])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Thread]
|
24
|
+
def start
|
25
|
+
raise 'Already started' if is_started?
|
26
|
+
@thread = Thread.new { run_process(@process_builder) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Komenda::Result]
|
30
|
+
def wait_for
|
31
|
+
raise 'Process not started' unless is_started?
|
32
|
+
@thread.join
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Komenda::Result]
|
37
|
+
def run
|
38
|
+
start unless is_started?
|
39
|
+
wait_for
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [TrueClass, FalseClass]
|
43
|
+
def running?
|
44
|
+
raise 'Process not started' unless is_started?
|
45
|
+
@thread.alive?
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Komenda::Result]
|
49
|
+
def result
|
50
|
+
raise 'Process not started' unless is_started?
|
51
|
+
raise 'Process not finished' unless is_finished?
|
52
|
+
Komenda::Result.new(@output, @exit_status)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# @return [TrueClass, FalseClass]
|
58
|
+
def is_started?
|
59
|
+
!@thread.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [TrueClass, FalseClass]
|
63
|
+
def is_finished?
|
64
|
+
!@exit_status.nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [ProcessBuilder] process_builder
|
68
|
+
def run_process(process_builder)
|
69
|
+
begin
|
70
|
+
if process_builder.cwd.nil?
|
71
|
+
run_popen3(process_builder)
|
72
|
+
else
|
73
|
+
Dir.chdir(process_builder.cwd) { run_popen3(process_builder) }
|
74
|
+
end
|
75
|
+
rescue Exception => exception
|
76
|
+
emit(:error, exception)
|
77
|
+
raise exception
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param [ProcessBuilder] process_builder
|
82
|
+
def run_popen3(process_builder)
|
83
|
+
Open3.popen3(process_builder.env, *process_builder.command) do |stdin, stdout, stderr, wait_thr|
|
84
|
+
stdin.close
|
85
|
+
|
86
|
+
streams_read_open = [stdout, stderr]
|
87
|
+
begin
|
88
|
+
streams_read_available, _, _ = IO.select(streams_read_open)
|
89
|
+
|
90
|
+
streams_read_available.each do |stream|
|
91
|
+
if stream.eof?
|
92
|
+
stream.close
|
93
|
+
streams_read_open.delete(stream)
|
94
|
+
else
|
95
|
+
data = stream.readpartial(4096)
|
96
|
+
emit(:stdout, data) if stdout === stream
|
97
|
+
emit(:stderr, data) if stderr === stream
|
98
|
+
emit(:output, data)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end until streams_read_open.empty?
|
102
|
+
|
103
|
+
@exit_status = wait_thr.value
|
104
|
+
emit(:exit, result)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Komenda
|
2
|
+
class ProcessBuilder
|
3
|
+
|
4
|
+
attr_reader :command
|
5
|
+
attr_reader :env
|
6
|
+
attr_reader :cwd
|
7
|
+
attr_reader :events
|
8
|
+
|
9
|
+
# @param [String, String[]] command
|
10
|
+
# @param [Hash] options
|
11
|
+
def initialize(command, options = {})
|
12
|
+
defaults = {
|
13
|
+
:env => ENV.to_hash,
|
14
|
+
:cwd => nil,
|
15
|
+
:events => {},
|
16
|
+
}
|
17
|
+
options = defaults.merge(options)
|
18
|
+
|
19
|
+
@command = command.is_a?(Array) ? command.map { |v| String(v) } : String(command)
|
20
|
+
@env = Hash[options[:env].to_hash.map { |k, v| [String(k), String(v)] }]
|
21
|
+
@cwd = options[:cwd].nil? ? nil : String(options[:cwd])
|
22
|
+
@events = Hash[options[:events].to_hash.map { |k, v| [k.to_sym, v.to_proc] }]
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Komenda::Process]
|
26
|
+
def create
|
27
|
+
Komenda::Process.new(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: komenda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cargo Media
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-11-
|
12
|
+
date: 2015-11-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -53,6 +53,20 @@ dependencies:
|
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '2.0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: event_emitter
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0.2'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.2'
|
56
70
|
description: Convenience wrapper around `Open3` to run shell commands in Ruby.
|
57
71
|
email: hello@cargomedia.ch
|
58
72
|
executables: []
|
@@ -62,9 +76,9 @@ files:
|
|
62
76
|
- LICENSE
|
63
77
|
- README.md
|
64
78
|
- lib/komenda.rb
|
65
|
-
- lib/komenda/
|
79
|
+
- lib/komenda/process.rb
|
80
|
+
- lib/komenda/process_builder.rb
|
66
81
|
- lib/komenda/result.rb
|
67
|
-
- lib/komenda/runner.rb
|
68
82
|
homepage: https://github.com/cargomedia/komenda
|
69
83
|
licenses:
|
70
84
|
- MIT
|
data/lib/komenda/definition.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Komenda
|
2
|
-
class Definition
|
3
|
-
|
4
|
-
attr_reader :cmd
|
5
|
-
attr_reader :env
|
6
|
-
|
7
|
-
# @param [String] cmd
|
8
|
-
# @param [Hash] options
|
9
|
-
def initialize(cmd, options = {})
|
10
|
-
defaults = {
|
11
|
-
:env => ENV.to_hash,
|
12
|
-
}
|
13
|
-
options = defaults.merge(options)
|
14
|
-
|
15
|
-
@cmd = String(cmd)
|
16
|
-
@env = Hash[options[:env].to_hash.map { |k, v| [String(k), String(v)] }]
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
data/lib/komenda/runner.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
module Komenda
|
2
|
-
class Runner
|
3
|
-
|
4
|
-
# @param [Komenda::Definition] definition
|
5
|
-
# @return [Komenda::Result]
|
6
|
-
def run(definition)
|
7
|
-
output = {:stdout => '', :stderr => '', :combined => ''}
|
8
|
-
status = nil
|
9
|
-
|
10
|
-
Open3.popen3(definition.env, definition.cmd) do |stdin, stdout, stderr, wait_thr|
|
11
|
-
stdin.close
|
12
|
-
|
13
|
-
streams_read_open = [stdout, stderr]
|
14
|
-
begin
|
15
|
-
streams_read_available, _, _ = IO.select(streams_read_open)
|
16
|
-
|
17
|
-
streams_read_available.each do |stream|
|
18
|
-
if stream.eof?
|
19
|
-
stream.close
|
20
|
-
streams_read_open.delete(stream)
|
21
|
-
else
|
22
|
-
data = stream.readpartial(4096)
|
23
|
-
output[:stdout] += data if stdout === stream
|
24
|
-
output[:stderr] += data if stderr === stream
|
25
|
-
output[:combined] += data
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end until streams_read_open.empty?
|
29
|
-
|
30
|
-
status = wait_thr.value
|
31
|
-
end
|
32
|
-
|
33
|
-
Komenda::Result.new(output, status)
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|