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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38c99ca643c947821f164f389981a9958424ede39ba1aeea5ba956265291d0ff
4
- data.tar.gz: bc09955bf615924204cad88a4a7b840826633184b6830207cb1193e71f132346
3
+ metadata.gz: 0c7830e5e5d0a88f9ecc26668684d1f14c5f8a4a0144268d52d9099fb6443db1
4
+ data.tar.gz: adbfab80da9e0a617fccd0f3afd7908009274e4ea88a407b0b95bdf921fad00d
5
5
  SHA512:
6
- metadata.gz: a91f53242d38998a7b2ab739050379b07108697c488f9dc69120e8538c6ee1299a66cc07ea203bca54aa76341d8c817f107af365cbaa669f6c365704ca780757
7
- data.tar.gz: 2918aa0f4ecea9affba5a6d531a7fa7cfd89ae2186ae30f033efda40e9480a91157afe4d20879591e7e8013a92a19adea79284dcc8cbc966737d6b6624080f7f
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.1.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/jleeothon/eksek.svg)](https://travis-ci.org/jleeothon/eksek)
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
- This returns an `EksekResult` object providing the following methods:
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' { 'This goes to stdin.' }
69
+ eksek 'echo Hello'
70
+ kapture 'echo Hello'
71
+
82
72
  # With Eksekuter
83
- Eksekuter.new('echo Hello').run { 'This goes to stdin.' }
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).run(&block)
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
- # rubocop:disable Metrics/ParameterLists
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
- @success = success
14
- @stdout = stdout
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, :stdout, :stderr
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
- @success
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
- def initialize *args, **opts
10
- @env = args[0].is_a?(Hash) ? args.shift : {}
11
- @env = @env.each_with_object({}) { |(k, v), o| o[k.to_s] = v }
12
- @cmd = args.size == 1 ? args.first : args
13
- @opts = opts
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
- def run &block
17
- spawn_process
18
- write_and_close_stdin(&block)
19
- wait
20
- read_and_close_stdout_stderr
21
- assemble_result
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
- private
25
-
26
- attr_reader(
27
- :cmd,
28
- :env,
29
- :err_str,
30
- :opts,
31
- :out_str,
32
- :process_status,
33
- :stdin,
34
- :wait_thr,
35
- )
36
-
37
- def stdout
38
- @stdout ||= StringIO.new('', 'r')
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
- def spawn_process
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 wait
60
- @process_status = wait_thr.value
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 read_and_close_stdout_stderr
64
- streams = [stdout, stderr]
65
- @out_str, @err_str = streams.map(&:read).map(&:chomp)
66
- streams.each(&:close)
67
- nil
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
- process_status.success?,
76
- out_str,
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.1.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: 2018-04-01 00:00:00.000000000 Z
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: '0'
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: '0'
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