eksek 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gemspec +2 -3
- data/README.md +17 -26
- data/lib/eksek.rb +9 -1
- data/lib/eksek_result.rb +13 -7
- data/lib/eksekuter.rb +47 -56
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c7830e5e5d0a88f9ecc26668684d1f14c5f8a4a0144268d52d9099fb6443db1
|
4
|
+
data.tar.gz: adbfab80da9e0a617fccd0f3afd7908009274e4ea88a407b0b95bdf921fad00d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfcf19d51d3ee081739ecb55fb6d0572f07e8865953fe6cd90cc910d0bd453990344dc7df6988e2e30a1b7e799f68e70e6909ad59b1350b6a22c730233677c88
|
7
|
+
data.tar.gz: cc6e0f4ccb882adab62d699d7c5b7b5fe010dd6dc4d48c96828a9adf3de1f2e2eb6435261fd23ab1805f8800bc44693d3f4c7bd0f9732f269ba0c1920df81afe
|
data/.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'eksek'
|
3
|
-
s.version = '0.
|
3
|
+
s.version = '0.2.0'
|
4
4
|
s.authors = ['Johnny Lee-Othon', 'Thomas Bretzke']
|
5
5
|
s.homepage = 'https://github.com/taccon/eksek'
|
6
6
|
s.summary = 'A better backticks'
|
@@ -13,6 +13,5 @@ Gem::Specification.new do |s|
|
|
13
13
|
|
14
14
|
s.required_ruby_version = '~> 2.3'
|
15
15
|
s.add_development_dependency 'rspec','~> 3'
|
16
|
-
s.add_development_dependency 'rubocop', '~> 0'
|
17
|
-
s.add_development_dependency 'bundler', '~> 1.0'
|
16
|
+
s.add_development_dependency 'rubocop', '~> 0.49.0'
|
18
17
|
end
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# eksek
|
2
2
|
|
3
|
-
[![Travis](https://img.shields.io/travis/
|
3
|
+
[![Travis](https://img.shields.io/travis/taccon/eksek.svg)](https://travis-ci.org/taccon/eksek)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/github/taccon/eksek/badge.svg?branch=coveralls)](https://coveralls.io/github/taccon/eksek?branch=coveralls)
|
4
5
|
|
5
6
|
`eksek` is a library to run shell commands synchronously and obtain any of the standard output, standard error, and exit code with flexibility.
|
6
7
|
|
@@ -8,17 +9,23 @@
|
|
8
9
|
|
9
10
|
### Basic usage
|
10
11
|
|
11
|
-
Use the `eksek` to execute a command:
|
12
|
+
Use the `eksek` method to execute a command:
|
12
13
|
|
13
14
|
```ruby
|
14
15
|
eksek 'echo Hello'
|
15
16
|
```
|
16
17
|
|
17
|
-
|
18
|
+
or the `kapture` method to execute a command but "capture" the standard output and standard error in a fashion similar to `Kernel#\`` (backticks) or `%x()`.
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
kapture 'echo Hello'
|
22
|
+
```
|
23
|
+
|
24
|
+
These methods return an `EksekResult` object providing the following methods:
|
18
25
|
|
19
26
|
- `exit` returns the exit code.
|
20
|
-
- `stdout` returns the standard output as a string.
|
21
|
-
- `stderr` returns the standard error as a string.
|
27
|
+
- `stdout` returns the standard output as a string if `kapture` was called.
|
28
|
+
- `stderr` returns the standard error as a string if `kapture` was called.
|
22
29
|
- `success?` returns `true` or `false` depending of the exit code (`0` for `true`).
|
23
30
|
- `success!` throws an exception if the command exited with a non-0 code.
|
24
31
|
|
@@ -32,25 +39,6 @@ puts eksek!('echo Hello').stdout # Hello
|
|
32
39
|
puts eksek('echo Hello').success!.stdout
|
33
40
|
```
|
34
41
|
|
35
|
-
### Writing to stdin
|
36
|
-
|
37
|
-
To write into the standard input a block can be used:
|
38
|
-
|
39
|
-
```ruby
|
40
|
-
r = eksek('read A; echo $A') { |stdin| stdin.write "Hello" }
|
41
|
-
r.success!
|
42
|
-
```
|
43
|
-
|
44
|
-
If the block returns a `String` or `IO`, it will be written into the stdio.
|
45
|
-
|
46
|
-
```ruby
|
47
|
-
r = eksek('read A; echo $A') { "Hello" }
|
48
|
-
r.success!
|
49
|
-
|
50
|
-
r = eksek('read A; echo $A') { File.open('myfile.txt') }
|
51
|
-
r.success!
|
52
|
-
```
|
53
|
-
|
54
42
|
### Passing other options
|
55
43
|
|
56
44
|
`eksek` has the same signature as `Process#spawn`. This means that:
|
@@ -78,7 +66,10 @@ In case you prefer an object oriented method, you can also use the `Eksekuter` c
|
|
78
66
|
|
79
67
|
```ruby
|
80
68
|
# With eksek
|
81
|
-
eksek 'echo Hello'
|
69
|
+
eksek 'echo Hello'
|
70
|
+
kapture 'echo Hello'
|
71
|
+
|
82
72
|
# With Eksekuter
|
83
|
-
Eksekuter.new('echo Hello')
|
73
|
+
Eksekuter.new.exec('echo Hello')
|
74
|
+
Eksekuter.new.capture('echo Hello')
|
84
75
|
```
|
data/lib/eksek.rb
CHANGED
@@ -9,10 +9,18 @@ module Kernel
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def eksek *args, **opts, &block
|
12
|
-
Eksekuter.new(*args, **opts
|
12
|
+
Eksekuter.new.exec(*args, **opts, &block)
|
13
13
|
end
|
14
14
|
|
15
15
|
def eksek! *args, **opts, &block
|
16
16
|
eksek(*args, **opts, &block).success!
|
17
17
|
end
|
18
|
+
|
19
|
+
def kapture *args, **opts, &block
|
20
|
+
Eksekuter.new.capture(*args, **opts, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def kapture! *args, **opts, &block
|
24
|
+
kapture(*args, **opts, &block).success!
|
25
|
+
end
|
18
26
|
end
|
data/lib/eksek_result.rb
CHANGED
@@ -5,21 +5,27 @@ require_relative 'eksek_error'
|
|
5
5
|
# Describes a result object to be used for evaluating
|
6
6
|
# return values from a command
|
7
7
|
class EksekResult
|
8
|
-
|
9
|
-
def initialize env, cmd, exit_code, success, stdout, stderr
|
8
|
+
def initialize env, cmd, exit_code, out_stream, err_stream
|
10
9
|
@env = env
|
11
10
|
@cmd = cmd
|
12
11
|
@exit_code = exit_code
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@stderr = stderr
|
12
|
+
@out_stream = out_stream
|
13
|
+
@err_stream = err_stream
|
16
14
|
end
|
17
15
|
# rubocop:enable Metrics/ParameterLists
|
18
16
|
|
19
|
-
attr_reader :exit_code
|
17
|
+
attr_reader :exit_code
|
18
|
+
|
19
|
+
def stdout
|
20
|
+
@stdout ||= @out_stream&.read
|
21
|
+
end
|
22
|
+
|
23
|
+
def stderr
|
24
|
+
@stderr ||= @err_stream&.read
|
25
|
+
end
|
20
26
|
|
21
27
|
def success?
|
22
|
-
@
|
28
|
+
@exit_code.zero?
|
23
29
|
end
|
24
30
|
|
25
31
|
def success!
|
data/lib/eksekuter.rb
CHANGED
@@ -6,75 +6,66 @@ require_relative 'eksek_result'
|
|
6
6
|
|
7
7
|
# Class that command execution is delegated to by Eksek.
|
8
8
|
class Eksekuter
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
9
|
+
# @param {Logger} logger
|
10
|
+
def initialize logger: nil
|
11
|
+
@logger = logger
|
12
|
+
@stdout_buffer = nil
|
13
|
+
@stderr_buffer = nil
|
14
|
+
@stdin_buffer = nil
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
# Wraps around Kernel#spawn so that the return value is an EksekResult.
|
18
|
+
# @return EksekResult
|
19
|
+
def exec *args, **opts
|
20
|
+
env, cmd = split_env_and_cmd(args)
|
21
|
+
params = { env: env, cmd: cmd, opts: opts }
|
22
|
+
process_status = spawn_and_get_status(params)
|
23
|
+
assemble_result(params, process_status)
|
22
24
|
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
:
|
34
|
-
:
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
def stderr
|
42
|
-
@stderr ||= StringIO.new('', 'r')
|
26
|
+
# Like Eksekuter#exec but the :out and :err options are ignored; instead
|
27
|
+
# the output is attached to the EksekResult object returned.
|
28
|
+
# Returns an EksekResult object which getters :stdout and :stderr containing
|
29
|
+
# the corresponding output of the spawned process.
|
30
|
+
# @return EksekResult
|
31
|
+
def capture *args, **opts
|
32
|
+
env, cmd = split_env_and_cmd(args)
|
33
|
+
out_read, out_write = IO.pipe
|
34
|
+
err_read, err_write = IO.pipe
|
35
|
+
opts2 = opts.merge(out: out_write, err: err_write)
|
36
|
+
params = { env: env, cmd: cmd, opts: opts2 }
|
37
|
+
process_status = spawn_and_get_status(params)
|
38
|
+
out_write.close
|
39
|
+
err_write.close
|
40
|
+
assemble_result(params, process_status, out_read, err_read)
|
43
41
|
end
|
44
42
|
|
45
|
-
|
46
|
-
@stdin, @stdout, @stderr, @wait_thr = Open3.popen3(env, *cmd, opts)
|
47
|
-
nil
|
48
|
-
end
|
49
|
-
|
50
|
-
def write_and_close_stdin
|
51
|
-
return if stdin.closed? || !block_given?
|
52
|
-
block_result = yield stdin
|
53
|
-
block_result = StringIO.new(block_result) if block_result.is_a? String
|
54
|
-
IO.copy_stream(block_result, stdin) if block_result.respond_to? :read
|
55
|
-
stdin.close
|
56
|
-
nil
|
57
|
-
end
|
43
|
+
private
|
58
44
|
|
59
|
-
def
|
60
|
-
|
45
|
+
def split_env_and_cmd args
|
46
|
+
cmd_args = args.clone
|
47
|
+
env = cmd_args.first.is_a?(Hash) ? cmd_args.shift : {}
|
48
|
+
env = env.each_with_object({}) { |(k, v), o| o[k.to_s] = v }
|
49
|
+
cmd = cmd_args.size == 1 ? cmd_args.first : cmd_args
|
50
|
+
[env, cmd]
|
61
51
|
end
|
62
52
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
53
|
+
def spawn_and_get_status params
|
54
|
+
env = params.fetch(:env)
|
55
|
+
cmd = params.fetch(:cmd)
|
56
|
+
opts = params.fetch(:opts)
|
57
|
+
pid = spawn(env, *cmd, opts)
|
58
|
+
_, process_status = Process.wait2(pid)
|
59
|
+
process_status
|
68
60
|
end
|
69
61
|
|
70
|
-
def assemble_result
|
62
|
+
def assemble_result params, process_status, out_stream = nil, err_stream = nil
|
71
63
|
EksekResult.new(
|
72
|
-
env,
|
73
|
-
cmd,
|
64
|
+
params.fetch(:env),
|
65
|
+
params.fetch(:cmd),
|
74
66
|
process_status.exitstatus,
|
75
|
-
|
76
|
-
|
77
|
-
err_str,
|
67
|
+
out_stream,
|
68
|
+
err_stream,
|
78
69
|
)
|
79
70
|
end
|
80
71
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eksek
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Johnny Lee-Othon
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-03-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -31,28 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: 0.49.0
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
42
|
-
- !ruby/object:Gem::Dependency
|
43
|
-
name: bundler
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
46
|
-
- - "~>"
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: '1.0'
|
49
|
-
type: :development
|
50
|
-
prerelease: false
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
requirements:
|
53
|
-
- - "~>"
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: '1.0'
|
41
|
+
version: 0.49.0
|
56
42
|
description: 'Execute shell commands and easily get stdout, stderr, exit code, and
|
57
43
|
more
|
58
44
|
|