pvc 0.0.1 → 0.0.2

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.
data/.gitignore CHANGED
@@ -1,2 +1,6 @@
1
1
  .DS_Store
2
2
  *.sw*
3
+ pkg/*
4
+ *.gem
5
+ TODO.md
6
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile.lock CHANGED
@@ -2,11 +2,15 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  pvc (0.0.1)
5
+ childprocess
5
6
 
6
7
  GEM
7
8
  remote: http://rubygems.org/
8
9
  specs:
10
+ childprocess (0.3.6)
11
+ ffi (~> 1.0, >= 1.0.6)
9
12
  diff-lcs (1.1.3)
13
+ ffi (1.3.1)
10
14
  rspec (2.12.0)
11
15
  rspec-core (~> 2.12.0)
12
16
  rspec-expectations (~> 2.12.0)
data/README.md CHANGED
@@ -7,9 +7,6 @@ Pipe between processes as easily as in the shell
7
7
  # run the specs
8
8
  bundle exec rspec spec
9
9
 
10
- # run the simulation interactively (see description below)
11
- ./bin/gorobo
12
-
13
10
  ## Install it as a RubyGem
14
11
 
15
12
  This code is packaged as a Gem. If you like, you can build and install it by running:
@@ -17,8 +14,41 @@ This code is packaged as a Gem. If you like, you can build and install it by run
17
14
  gem build pvc.gemspec
18
15
  gem install pvc-*.gem
19
16
 
20
- ## Description
17
+ ## Synopsis - implemented
18
+
19
+ # Run a single process
20
+ PVC.new("echo hello").run
21
+
22
+ # Or pipe from one process to another
23
+ PVC.new("echo hello").to("tr h H").run
24
+
25
+ # Get individual or several outputs from the final result
26
+ PVC.new("echo hello && ls doesnotexist").run.stdout # => "hello\n"
27
+ PVC.new("echo hello && ls doesnotexist").run.stderr # => "ls: doesnotexist: No such file or directory\n"
28
+ PVC.new("echo hello && ls doesnotexist").run.stdboth # => "hello\nls: doesnotexist: No such file or directory\n"
29
+ PVC.new("echo hello && ls doesnotexist").run.code # => 1
30
+ stderr, code = PVC.new("echo hello && ls doesnotexist").run.get(:stderr, :code) # => ["ls: doesnotexist: No such file or directory\n", 1]
31
+
32
+ # Input a string into stdin
33
+ PVC.new.input("one\ntwo\nthree\n").to("sort -r").run.stdout # => "two\nthree\none\n"
34
+
35
+ # Process intermediate results with Ruby
36
+ PVC.new("cat some.log").to { |i,o| i.each_line { |line| o.puts line if line.match(/ERROR/) } }.to("tail -n10").run
37
+
38
+ # Mix stderr and stdin at some point in a pipeline
39
+ PVC.new("echo hello && ls doesnotexist").with_err.to("wc -l").run.stdout # => " 2\n"
40
+
41
+ # Pass on only stderr at some point in a pipeline
42
+ PVC.new("echo hello && ls doesnotexist").only_err.to("wc -l").run.stdout # => " 1\n"
43
+
44
+ # Insert one pipeline into another
45
+ upcase_unique_pipeline = PVC.new("tr a-z A-Z").to("uniq")
46
+ PVC.new.input("hello\nHeLlO\nworld\nWoRlD\n").to(upcase_unique_pipeline).to("sort -r").run.stdout # => "WORLD\nHELLO"
47
+
48
+ ## Synopsis - unimplemented
21
49
 
50
+ # Kill run if it does not finish in time (miliseconds)
51
+ PVC.new("sleep 2").run(:timeout => 1000)
22
52
 
23
53
  ## Compatibility
24
54
 
@@ -0,0 +1,43 @@
1
+ module PVC
2
+ class BlockPiece
3
+
4
+ class Runner
5
+
6
+ def initialize(&block)
7
+ @block = block
8
+ @read, @write = IO.pipe
9
+ @read.close_on_exec = true
10
+ @write.close_on_exec = true
11
+ end
12
+
13
+ def stdin
14
+ @write
15
+ end
16
+
17
+ def start(following_piece)
18
+ @return = nil
19
+ @thread = Thread.new do
20
+ @return = @block.call(@read, following_piece.stdin)
21
+ end
22
+ end
23
+
24
+ def finish
25
+ @write.close
26
+ @thread.join
27
+ @read.close
28
+ end
29
+
30
+ attr_reader :return
31
+ end
32
+
33
+ def initialize(&block)
34
+ @block = block
35
+ end
36
+
37
+ def runner
38
+ Runner.new(&@block)
39
+ end
40
+
41
+ end
42
+ end
43
+
@@ -0,0 +1,37 @@
1
+ module PVC
2
+ class InputPiece
3
+
4
+ class Runner
5
+ def initialize(input)
6
+ @input = input
7
+ @read, @write = IO.pipe
8
+ @read.close_on_exec = true
9
+ @write.close_on_exec = true
10
+ end
11
+
12
+ def stdin
13
+ @write
14
+ end
15
+
16
+ def start(following_piece)
17
+ following_piece.stdin.write(@input)
18
+ following_piece.stdin.flush
19
+ end
20
+
21
+ def finish
22
+ @write.close
23
+ @read.close
24
+ end
25
+ end
26
+
27
+ def initialize(input)
28
+ @input = input
29
+ end
30
+
31
+ def runner
32
+ Runner.new(@input)
33
+ end
34
+
35
+ end
36
+ end
37
+
@@ -0,0 +1,32 @@
1
+ module PVC
2
+ class NullPiece
3
+
4
+ class Runner
5
+ def initialize
6
+ @read, @write = IO.pipe
7
+ @read.close_on_exec = true
8
+ @write.close_on_exec = true
9
+ end
10
+
11
+ def stdin
12
+ @write
13
+ end
14
+
15
+ def start(following=nil)
16
+ # do nothing
17
+ end
18
+
19
+ def finish
20
+ @write.close
21
+ @read.close
22
+ end
23
+
24
+ end
25
+
26
+ def runner
27
+ Runner.new
28
+ end
29
+
30
+ end
31
+ end
32
+
@@ -0,0 +1,44 @@
1
+ module PVC
2
+ class OnlyErrPiece
3
+
4
+ class Runner
5
+ def initialize
6
+ @stdread, @stdwrite = IO.pipe
7
+ @errread, @errwrite = IO.pipe
8
+ @stdread.close_on_exec = true
9
+ @stdwrite.close_on_exec = true
10
+ @errread.close_on_exec = true
11
+ @errwrite.close_on_exec = true
12
+ end
13
+
14
+ def stdin
15
+ @stdwrite
16
+ end
17
+
18
+ def errin
19
+ @errwrite
20
+ end
21
+
22
+ def start(following_piece)
23
+ @errthread = Thread.new do
24
+ @errread.each_line { |line| following_piece.stdin.puts line }
25
+ end
26
+ end
27
+
28
+ def finish
29
+ @stdwrite.close
30
+ @errwrite.close
31
+ @errthread.join
32
+ @stdread.close
33
+ @errread.close
34
+ end
35
+
36
+ end
37
+
38
+ def runner
39
+ Runner.new
40
+ end
41
+
42
+ end
43
+ end
44
+
@@ -0,0 +1,74 @@
1
+ require "childprocess"
2
+
3
+ require "pvc/block_piece"
4
+ require "pvc/null_piece"
5
+ require "pvc/process_piece"
6
+ require "pvc/with_err_piece"
7
+ require "pvc/only_err_piece"
8
+ require "pvc/result_piece"
9
+ require "pvc/input_piece"
10
+ require "pvc/result"
11
+
12
+ module PVC
13
+ class Pipeline
14
+
15
+ def initialize(*args, &block)
16
+ @pieces = []
17
+ if args.length > 0 || block_given?
18
+ self.to(*args, &block)
19
+ end
20
+ end
21
+
22
+ def to(*args, &block)
23
+ if block_given?
24
+ @pieces << BlockPiece.new(&block)
25
+ elsif args.length == 1 && args.first.respond_to?(:pieces)
26
+ args.first.pieces.each { |piece| @pieces << piece }
27
+ else
28
+ @pieces << ProcessPiece.new(*args)
29
+ end
30
+ self
31
+ end
32
+
33
+ def input(input)
34
+ @pieces << InputPiece.new(input)
35
+ self
36
+ end
37
+
38
+ def with_err
39
+ @pieces << WithErrPiece.new
40
+ self
41
+ end
42
+
43
+ def only_err
44
+ @pieces << OnlyErrPiece.new
45
+ self
46
+ end
47
+
48
+ def run
49
+ runners = ([NullPiece.new] + @pieces + [ResultPiece.new]).map(&:runner)
50
+
51
+ runners.zip(runners[1..-1]).reverse.each do |current, following|
52
+ current.start(following)
53
+ end
54
+
55
+ runners.each do |current|
56
+ current.finish
57
+ end
58
+
59
+ Result.new(
60
+ :stdout => runners.last.stdout,
61
+ :stderr => runners.last.stderr,
62
+ :stdboth => runners.last.stdboth,
63
+ :codes => runners.inject([]) { |codes, runner| codes << runner.code if runner.respond_to?(:code); codes },
64
+ :returns => runners.inject([]) { |returns, runner| returns << runner.return if runner.respond_to?(:return); returns }
65
+ )
66
+ end
67
+
68
+ protected
69
+
70
+ attr_reader :pieces
71
+
72
+ end
73
+ end
74
+
@@ -0,0 +1,41 @@
1
+ module PVC
2
+ class ProcessPiece
3
+
4
+ class Runner
5
+ def initialize(*args)
6
+ @args = args
7
+ @process = ChildProcess.build(*args)
8
+ end
9
+
10
+ def stdin
11
+ @process.io.stdin
12
+ end
13
+
14
+ def start(following_piece)
15
+ @process.duplex = true
16
+ @process.io.stdout = following_piece.stdin
17
+ @process.io.stderr = following_piece.errin if following_piece.respond_to?(:errin)
18
+ @process.start
19
+ end
20
+
21
+ def finish
22
+ @process.io.stdin.close
23
+ @process.wait
24
+ end
25
+
26
+ def code
27
+ @process.exit_code
28
+ end
29
+ end
30
+
31
+ def initialize(args)
32
+ @args = args
33
+ end
34
+
35
+ def runner
36
+ Runner.new(@args)
37
+ end
38
+
39
+ end
40
+ end
41
+
data/lib/pvc/result.rb ADDED
@@ -0,0 +1,32 @@
1
+ module PVC
2
+ class Result
3
+
4
+ attr_reader :stdout
5
+ attr_reader :stderr
6
+ attr_reader :stdboth
7
+
8
+ def initialize(args)
9
+ @stdout = args[:stdout]
10
+ @stderr = args[:stderr]
11
+ @stdboth = args[:stdboth]
12
+ @returns = args[:returns]
13
+ @codes = args[:codes]
14
+ end
15
+
16
+ def return
17
+ @returns.last
18
+ end
19
+
20
+ def code
21
+ @codes.last
22
+ end
23
+
24
+ def get(*requested_outputs)
25
+ allowed_outputs = [:stdout, :stderr, :stdboth, :return, :code]
26
+ raise "No such output to get!" unless (requested_outputs-allowed_outputs)==[]
27
+ requested_outputs.map { |output_kind| self.send(output_kind) }
28
+ end
29
+
30
+ end
31
+ end
32
+
@@ -0,0 +1,69 @@
1
+ module PVC
2
+ class ResultPiece
3
+
4
+ class Runner
5
+ def initialize
6
+ @stdread, @stdwrite = IO.pipe
7
+ @errread, @errwrite = IO.pipe
8
+ @stdread.close_on_exec = true
9
+ @stdwrite.close_on_exec = true
10
+ @errread.close_on_exec = true
11
+ @errwrite.close_on_exec = true
12
+ @stdout = []
13
+ @stderr = []
14
+ @stdboth = []
15
+ end
16
+
17
+ def stdin
18
+ @stdwrite
19
+ end
20
+
21
+ def errin
22
+ @errwrite
23
+ end
24
+
25
+ def start(following=nil)
26
+ @stdthread = Thread.new do
27
+ @stdread.each_line do |line|
28
+ @stdout << line
29
+ @stdboth << line
30
+ end
31
+ end
32
+ @errthread = Thread.new do
33
+ @errread.each_line do |line|
34
+ @stderr << line
35
+ @stdboth << line
36
+ end
37
+ end
38
+ end
39
+
40
+ def finish
41
+ @stdwrite.close
42
+ @errwrite.close
43
+ @stdthread.join
44
+ @errthread.join
45
+ @stdread.close
46
+ @errread.close
47
+ end
48
+
49
+ def stdout
50
+ @stdout.join("")
51
+ end
52
+
53
+ def stderr
54
+ @stderr.join("")
55
+ end
56
+
57
+ def stdboth
58
+ @stdboth.join("")
59
+ end
60
+
61
+ end
62
+
63
+ def runner
64
+ Runner.new
65
+ end
66
+
67
+ end
68
+ end
69
+
data/lib/pvc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module PVC
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,48 @@
1
+ module PVC
2
+ class WithErrPiece
3
+
4
+ class Runner
5
+ def initialize
6
+ @stdread, @stdwrite = IO.pipe
7
+ @errread, @errwrite = IO.pipe
8
+ @stdread.close_on_exec = true
9
+ @stdwrite.close_on_exec = true
10
+ @errread.close_on_exec = true
11
+ @errwrite.close_on_exec = true
12
+ end
13
+
14
+ def stdin
15
+ @stdwrite
16
+ end
17
+
18
+ def errin
19
+ @errwrite
20
+ end
21
+
22
+ def start(following_piece)
23
+ @stdthread = Thread.new do
24
+ @stdread.each_line { |line| following_piece.stdin.puts line }
25
+ end
26
+ @errthread = Thread.new do
27
+ @errread.each_line { |line| following_piece.stdin.puts line }
28
+ end
29
+ end
30
+
31
+ def finish
32
+ @stdwrite.close
33
+ @errwrite.close
34
+ @stdthread.join
35
+ @errthread.join
36
+ @stdread.close
37
+ @errread.close
38
+ end
39
+
40
+ end
41
+
42
+ def runner
43
+ Runner.new
44
+ end
45
+
46
+ end
47
+ end
48
+
data/lib/pvc.rb CHANGED
@@ -0,0 +1,12 @@
1
+ require "childprocess"
2
+
3
+ require "pvc/pipeline"
4
+
5
+ module PVC
6
+
7
+ def self.new(*args, &block)
8
+ Pipeline.new(*args, &block)
9
+ end
10
+
11
+ end
12
+
data/pvc.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.version = PVC::VERSION
8
8
  s.authors = ["Chris Berkhout"]
9
9
  s.email = ["chrisberkhout@gmail.com"]
10
- s.homepage = "http://chrisberkhout.com"
10
+ s.homepage = "http://github.com/chrisberkhout/pvc"
11
11
  s.summary = %q{Easy piping between processes}
12
12
 
13
13
  s.rubyforge_project = "pvc"
@@ -17,7 +17,8 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- # specify any dependencies here; for example:
20
+ s.add_runtime_dependency "childprocess"
21
+
21
22
  s.add_development_dependency "rspec"
22
23
 
23
24
  s.required_ruby_version = '>= 1.9.0'
@@ -0,0 +1,109 @@
1
+ require "pvc"
2
+
3
+ describe "pvc" do
4
+
5
+ describe "(synopsis tests)" do
6
+
7
+ it "should run a single process" do
8
+ PVC.new("echo hello").run.stdout.should == "hello\n"
9
+ end
10
+
11
+ it "should pipe from one process to another" do
12
+ PVC.new("echo hello").to("tr h H").run.stdout.should == "Hello\n"
13
+ end
14
+
15
+ it "should let you get stdout" do
16
+ PVC.new("echo hello && ls doesnotexist").run.stdout.should == "hello\n"
17
+ end
18
+
19
+ it "should let you get stderr" do
20
+ PVC.new("echo hello && ls doesnotexist").run.stderr.should == "ls: doesnotexist: No such file or directory\n"
21
+ end
22
+
23
+ it "should let you get stdout and stderr together" do
24
+ PVC.new("echo hello && ls doesnotexist").run.stdboth.should == "hello\nls: doesnotexist: No such file or directory\n"
25
+ end
26
+
27
+ it "should let you get the exit code of the last process" do
28
+ PVC.new("echo hello").run.code.should == 0
29
+ PVC.new("echo hello && ls doesnotexist").run.code.should == 1
30
+ end
31
+
32
+ it "should let you get several outputs from the final result" do
33
+ PVC.new("echo hello && ls doesnotexist").run.get(:stderr, :code).should == ["ls: doesnotexist: No such file or directory\n", 1]
34
+ end
35
+
36
+ it "should let you input into the stdin" do
37
+ PVC.new.input("one\ntwo\nthree\n").to("sort -r").run.stdout.should == "two\nthree\none\n"
38
+ end
39
+
40
+ it "should let you process intermediate results with Ruby" do
41
+ PVC.new.input("one\ntwo\nthree\n").to do |i,o|
42
+ i.each_line { |line| o.puts line if line.match(/^t/) }
43
+ end.to("cat").run.stdout.should == "two\nthree\n"
44
+ end
45
+
46
+ it "should let you mix stderr and stdin at some point in a pipeline" do
47
+ PVC.new("echo hello && ls doesnotexist").with_err.to("wc -l").run.stdout.should == " 2\n"
48
+ end
49
+
50
+ it "should let you pass on only stderr at some point in a pipeline" do
51
+ PVC.new("echo hello && ls doesnotexist").only_err.to("wc -l").run.stdout.should == " 1\n"
52
+ end
53
+
54
+ it "should let you insert one pipeline into another" do
55
+ upcase_unique_pipeline = PVC.new("tr a-z A-Z").to("uniq")
56
+ string = "hello\nHeLlO\nworld\nWoRlD\n"
57
+ PVC.new.input(string).to(upcase_unique_pipeline).to("sort -r").run.stdout.should == "WORLD\nHELLO\n"
58
+ end
59
+
60
+ end
61
+
62
+ describe "(original manual tests)" do
63
+
64
+ let(:log) { [] }
65
+
66
+ it "should work with 2 shell commands and a block" do
67
+ PVC.new.
68
+ to("echo BBB && echo AAA").
69
+ to("sort").
70
+ to do |input, output|
71
+ input.each_line { |line| log << line.chomp }
72
+ end.run
73
+
74
+ log.should == %w{AAA BBB}
75
+ end
76
+
77
+ it "should work with sevearal blocks" do
78
+ PVC.new.
79
+ to("echo BBB && echo AAA").
80
+ to("sort").
81
+ to do |input, output|
82
+ input.each_line { |line| output.write line }
83
+ end.
84
+ to do |input, output|
85
+ input.each_line { |line| log << line.chomp }
86
+ end.run
87
+
88
+ log.should == %w{AAA BBB}
89
+ end
90
+
91
+ it "should work with sevearal blocks separated by a shell command" do
92
+ PVC.new.
93
+ to("echo BBB && echo AAA").
94
+ to("sort").
95
+ to do |input, output|
96
+ input.each_line { |line| output.write line }
97
+ end.
98
+ to("cat").
99
+ to do |input, output|
100
+ input.each_line { |line| log << line.chomp }
101
+ end.run
102
+
103
+ log.should == %w{AAA BBB}
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
@@ -0,0 +1,64 @@
1
+ require "childprocess"
2
+
3
+ describe "pipe io" do
4
+
5
+ def fork_childprocess
6
+ ChildProcess.unix?.should == true && ChildProcess.posix_spawn?.should == false # to ensure this does fork+exec
7
+ process = ChildProcess.build("cat")
8
+ process.duplex = true # to make stdin available on start
9
+ process.start
10
+ yield if block_given?
11
+ process.io.stdin.close
12
+ process.wait
13
+ end
14
+
15
+ # see also the example at: http://rubydoc.info/stdlib/core/1.9.3/IO.pipe
16
+
17
+ it "will not show EOF on close if a fork has an open copy of the file handle" do
18
+ read, write = IO.pipe
19
+ fork_childprocess do
20
+ write.close
21
+ expect { read.read_nonblock(1) }.to raise_error(Errno::EAGAIN) # not yet EOF
22
+ end
23
+ end
24
+
25
+ it "should show EOF on close if the fork has closed its copy of the file handle (by exiting)" do
26
+ read, write = IO.pipe
27
+ fork_childprocess
28
+ write.close
29
+ expect { read.read_nonblock(1) }.to raise_error(EOFError)
30
+ end
31
+
32
+ it "should show EOF on close if the fork has closed its copy of the file handle (by closing on exec)" do
33
+ read, write = IO.pipe
34
+ write.close_on_exec = true
35
+ fork_childprocess do
36
+ write.close
37
+ expect { read.read_nonblock(1) }.to raise_error(EOFError)
38
+ end
39
+ end
40
+
41
+ it "should not close everywhere if closed in a fork" do
42
+ read, write = IO.pipe
43
+ read.close_on_exec = true
44
+ write.close_on_exec = true
45
+ fork_childprocess do
46
+ read.closed?.should be_false
47
+ end
48
+ end
49
+
50
+ it "should get a final unterminated line via #each_line" do
51
+ read, write = IO.pipe
52
+ lines_read = []
53
+ thread = Thread.new do
54
+ read.each_line { |line| lines_read << line }
55
+ end
56
+ write.puts "terminated line"
57
+ write.print "unterminated line"
58
+ write.close
59
+ thread.join
60
+ lines_read.should == ["terminated line\n", "unterminated line"]
61
+ end
62
+
63
+ end
64
+
data/spec/spec_helper.rb CHANGED
@@ -0,0 +1,18 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
18
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pvc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-26 00:00:00.000000000 Z
12
+ date: 2013-02-11 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: childprocess
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rspec
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -35,15 +51,27 @@ extensions: []
35
51
  extra_rdoc_files: []
36
52
  files:
37
53
  - .gitignore
54
+ - .rspec
38
55
  - Gemfile
39
56
  - Gemfile.lock
40
57
  - README.md
41
58
  - Rakefile
42
59
  - lib/pvc.rb
60
+ - lib/pvc/block_piece.rb
61
+ - lib/pvc/input_piece.rb
62
+ - lib/pvc/null_piece.rb
63
+ - lib/pvc/only_err_piece.rb
64
+ - lib/pvc/pipeline.rb
65
+ - lib/pvc/process_piece.rb
66
+ - lib/pvc/result.rb
67
+ - lib/pvc/result_piece.rb
43
68
  - lib/pvc/version.rb
69
+ - lib/pvc/with_err_piece.rb
44
70
  - pvc.gemspec
71
+ - spec/pvc/integration_spec.rb
72
+ - spec/ruby/pipe_io_spec.rb
45
73
  - spec/spec_helper.rb
46
- homepage: http://chrisberkhout.com
74
+ homepage: http://github.com/chrisberkhout/pvc
47
75
  licenses: []
48
76
  post_install_message:
49
77
  rdoc_options: []
@@ -68,5 +96,7 @@ signing_key:
68
96
  specification_version: 3
69
97
  summary: Easy piping between processes
70
98
  test_files:
99
+ - spec/pvc/integration_spec.rb
100
+ - spec/ruby/pipe_io_spec.rb
71
101
  - spec/spec_helper.rb
72
102
  has_rdoc: