eksek 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.
- 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
|
-
[](https://travis-ci.org/taccon/eksek)
|
4
|
+
[](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
|
|