coque 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/README.md +17 -3
- data/lib/coque/cmd.rb +17 -15
- data/lib/coque/pipeline.rb +1 -2
- data/lib/coque/rb.rb +4 -4
- data/lib/coque/redirectable.rb +5 -35
- data/lib/coque/sh.rb +9 -6
- data/lib/coque/version.rb +1 -1
- data/lib/coque.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c69c98fb67e7afee6ad27390978968a86ebc9bb8
|
4
|
+
data.tar.gz: 09d45720d414295f7c1b4f887702b5439a3cbfb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd2afeb39c8afe1e1681a4fc7934d6116afdcc9616861c9abfe60ebbe86be469bd47af231568a4fc38c2e382cacf3ce0c6402fe5ab8ef232f804b1cbad699539
|
7
|
+
data.tar.gz: 7ee2833b41ecae0a0b9f7deb06d2a678bd2cb0eea1197a9aba826b2b5c2ea0ba5d38d57ec373e3dbe57d27c1ed53d212dc035f3646f2a2c11ee4f7acbac31540
|
data/README.md
CHANGED
@@ -39,7 +39,7 @@ pipeline.run.to_a
|
|
39
39
|
|
40
40
|
Coque can also create "Rb" commands, which integrate Ruby code with streaming, line-wise processing of other commands:
|
41
41
|
|
42
|
-
```
|
42
|
+
```rb
|
43
43
|
c1 = Coque["printf", '"a\nb\nc\n"']
|
44
44
|
c2 = Coque.rb { |line| puts line.upcase }
|
45
45
|
(c1 | c2).run.to_a
|
@@ -48,7 +48,7 @@ c2 = Coque.rb { |line| puts line.upcase }
|
|
48
48
|
|
49
49
|
Rb commands can also take "pre" and "post" blocks
|
50
50
|
|
51
|
-
```
|
51
|
+
```rb
|
52
52
|
dict = Coque["cat", "/usr/share/dict/words"]
|
53
53
|
rb_wc = Coque.rb { @lines += 1 }.pre { @lines = 0 }.post { puts @lines }
|
54
54
|
|
@@ -71,7 +71,7 @@ File.read("/tmp/error.txt")
|
|
71
71
|
# => "cat: /doesntexist.txt: No such file or directory\n"
|
72
72
|
```
|
73
73
|
|
74
|
-
Coque commands can also be derived from a `Coque::Context
|
74
|
+
Coque commands can also be derived from a `Coque::Context`, which enables changing directory, setting environment variables, and unsetting child env:
|
75
75
|
|
76
76
|
```rb
|
77
77
|
c = Coque.context
|
@@ -83,6 +83,20 @@ Coque.context.chdir("/tmp")["pwd"].run.to_a
|
|
83
83
|
|
84
84
|
Coque.context.setenv("my_key": "pizza")["echo", "$my_key"].run.to_a
|
85
85
|
# => ["pizza"]
|
86
|
+
|
87
|
+
ENV["my_key"] = "pizza"
|
88
|
+
Coque["echo", "$my_key"].run.to_a
|
89
|
+
# => ["pizza"]
|
90
|
+
|
91
|
+
Coque.context.disinherit_env["echo", "$my_key"].to_a
|
92
|
+
# => [""]
|
93
|
+
```
|
94
|
+
|
95
|
+
Coque also includes a `Coque.source` helper for feeding Ruby enumerables into shell pipelines:
|
96
|
+
|
97
|
+
```rb
|
98
|
+
(Coque.source(1..500) | Coque["wc", "-l"]).run.to_a
|
99
|
+
# => ["500"]
|
86
100
|
```
|
87
101
|
|
88
102
|
### Streaming Performance
|
data/lib/coque/cmd.rb
CHANGED
@@ -4,12 +4,11 @@ module Coque
|
|
4
4
|
attr_reader :context
|
5
5
|
|
6
6
|
def |(other)
|
7
|
-
verify_redirectable(other)
|
8
7
|
case other
|
9
8
|
when Cmd
|
10
|
-
Pipeline.new([self, other])
|
9
|
+
Pipeline.new([self.clone, other.clone])
|
11
10
|
when Pipeline
|
12
|
-
Pipeline.new([self] + other.commands)
|
11
|
+
Pipeline.new([self.clone] + other.commands)
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
@@ -17,19 +16,22 @@ module Coque
|
|
17
16
|
raise "Not Implemented - Override"
|
18
17
|
end
|
19
18
|
|
20
|
-
def
|
21
|
-
if self.stdin
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
def get_default_fds
|
20
|
+
stdin = if self.stdin
|
21
|
+
self.stdin
|
22
|
+
else
|
23
|
+
inr, inw = IO.pipe
|
24
|
+
inw.close
|
25
|
+
inr
|
26
|
+
end
|
26
27
|
|
27
|
-
if self.stdout
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
stdoutr, stdoutw = if self.stdout
|
29
|
+
[self.stdout, self.stdout]
|
30
|
+
else
|
31
|
+
IO.pipe
|
32
|
+
end
|
33
|
+
|
34
|
+
[stdin, stdoutr, stdoutw]
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
data/lib/coque/pipeline.rb
CHANGED
@@ -16,12 +16,11 @@ module Coque
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def |(other)
|
19
|
-
verify_redirectable(other)
|
20
19
|
case other
|
21
20
|
when Pipeline
|
22
21
|
Pipeline.new(commands + other.commands)
|
23
22
|
when Cmd
|
24
|
-
Pipeline.new(commands + [other])
|
23
|
+
Pipeline.new(commands + [other.clone])
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
data/lib/coque/rb.rb
CHANGED
@@ -32,10 +32,10 @@ module Coque
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def run
|
35
|
-
|
35
|
+
stdin, stdoutr, stdoutw = get_default_fds
|
36
36
|
|
37
37
|
pid = fork do
|
38
|
-
STDOUT.reopen(
|
38
|
+
STDOUT.reopen(stdoutw)
|
39
39
|
Dir.chdir(context.dir)
|
40
40
|
if context.disinherits_env?
|
41
41
|
ENV.clear
|
@@ -47,8 +47,8 @@ module Coque
|
|
47
47
|
stdin.each_line(&@block)
|
48
48
|
@post_block.call if @post_block
|
49
49
|
end
|
50
|
-
|
51
|
-
Result.new(pid,
|
50
|
+
stdoutw.close
|
51
|
+
Result.new(pid, stdoutr)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
data/lib/coque/redirectable.rb
CHANGED
@@ -37,50 +37,20 @@ module Coque
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def stdin_redirected?
|
41
|
-
defined? @stdin
|
42
|
-
end
|
43
|
-
|
44
|
-
def stdout_redirected?
|
45
|
-
defined? @stdout
|
46
|
-
end
|
47
|
-
|
48
|
-
def stderr_redirected?
|
49
|
-
defined? @stderr
|
50
|
-
end
|
51
|
-
|
52
40
|
def stderr=(s)
|
53
|
-
|
54
|
-
raise RedirectionError.new("Can't set stderr of #{self} to #{s}, is already set to #{stderr}")
|
55
|
-
else
|
56
|
-
@stderr = getio(s, "w")
|
57
|
-
end
|
41
|
+
@stderr = getio(s, "w")
|
58
42
|
end
|
59
43
|
|
60
44
|
def stdout=(s)
|
61
|
-
|
62
|
-
raise RedirectionError.new("Can't set stdout of #{self} to #{s}, is already set to #{stdout}")
|
63
|
-
else
|
64
|
-
@stdout = getio(s, "w")
|
65
|
-
end
|
45
|
+
@stdout = getio(s, "w")
|
66
46
|
end
|
67
47
|
|
68
48
|
def stdin=(s)
|
69
|
-
|
70
|
-
raise RedirectionError.new("Can't set stdin of #{self} to #{s}, is already set to #{stdin}")
|
71
|
-
else
|
72
|
-
@stdin = getio(s, "r")
|
73
|
-
end
|
49
|
+
@stdin = getio(s, "r")
|
74
50
|
end
|
75
51
|
|
76
|
-
def
|
77
|
-
|
78
|
-
raise RedirectionError.new("Can't pipe #{self} into #{other} -- #{self}'s STDIN is already redirected")
|
79
|
-
end
|
80
|
-
|
81
|
-
if other.stdin_redirected?
|
82
|
-
raise RedirectionError.new("Can't pipe #{self} into #{other} -- #{other}'s STDIN is already redirected")
|
83
|
-
end
|
52
|
+
def to_a
|
53
|
+
run.to_a
|
84
54
|
end
|
85
55
|
|
86
56
|
private
|
data/lib/coque/sh.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
module Coque
|
2
2
|
class Sh < Cmd
|
3
3
|
attr_reader :args, :context
|
4
|
-
def initialize(context, args)
|
4
|
+
def initialize(context, args, stdin = nil, stdout = nil, stderr = nil)
|
5
5
|
@context = context
|
6
6
|
@args = args
|
7
|
+
self.stdin = stdin if stdin
|
8
|
+
self.stdout = stdout if stdout
|
9
|
+
self.stderr = stderr if stderr
|
7
10
|
end
|
8
11
|
|
9
12
|
def clone
|
10
|
-
self.class.new(context, args)
|
13
|
+
self.class.new(context, args, stdin, stdout, stderr)
|
11
14
|
end
|
12
15
|
|
13
16
|
def to_s
|
@@ -23,9 +26,9 @@ module Coque
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def run
|
26
|
-
|
29
|
+
stdin, stdoutr, stdoutw = get_default_fds
|
27
30
|
opts = {in: stdin, stdin.fileno => stdin.fileno,
|
28
|
-
out:
|
31
|
+
out: stdoutw, stdoutw.fileno => stdoutw.fileno,
|
29
32
|
chdir: context.dir, unsetenv_others: context.disinherits_env?}
|
30
33
|
|
31
34
|
# Redirect err to out: (e.g. for 2>&1)
|
@@ -38,8 +41,8 @@ module Coque
|
|
38
41
|
|
39
42
|
pid = spawn(context.env, args.join(" "), opts.merge(err_opts))
|
40
43
|
|
41
|
-
|
42
|
-
Result.new(pid,
|
44
|
+
stdoutw.close
|
45
|
+
Result.new(pid, stdoutr)
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
data/lib/coque/version.rb
CHANGED
data/lib/coque.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coque
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Horace Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|