piperun 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDFhOTJhOGE1ZTI1OTcxZjliYjcyNmU5ZWEwYjU5MTdiMjNkMzllZQ==
5
+ data.tar.gz: !binary |-
6
+ MGIxOGYzM2NlYTMyN2JiZWIwYjg2NzU2YjEyY2U0MzI2NzExZjViZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OGFhZGE3ZmNhZjlhNWMzZDQ4ODMxOWY0YzA5M2MwOGQ3ZjY3NmY4YmFkN2Iy
10
+ Y2EwZjY4NThiNTljNjY4NzNmNmNjYmFmYWM0NDRmOWE4MDdiYzkwNjU0NTMx
11
+ MTRiZTY2MmZmOGFiNDcwZGNlNTY1OTI2ZTBkZjlmYzNiYzkwNmY=
12
+ data.tar.gz: !binary |-
13
+ Njc5N2UxMzcyMjIxY2MxZmJjODE5M2RjYjIxYjExYjZkMGUwZjRkMmFmZTI0
14
+ MmEwODQwZmY0YmM5MzlhZjU5NjQ2OWY1MWI5OTM4NDI1M2QwMzliYTA3YjEz
15
+ NjY1MjkzMWM3OTZiNjlmNzEwOWZlZGY1Nzc0ZGVkOWZhZDI4YWQ=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format documentation
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in piperun.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Paul Liétar
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Piperun
2
+
3
+ Piperun allows you to process your application's assets in using pipelines seamlessly.
4
+ It is more lightweight than the Rails pipeline, but more appropriate than task runners like Grunt.
5
+
6
+ It takes assets from a source directory, applies a number a filters to transform them,
7
+ and puts the result in a destination directory.
8
+
9
+ Temporary files are automagically managed by Piperun so you do not have to bother about them.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'piperun'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install piperun
24
+
25
+ ## Usage
26
+
27
+ Create a `Pipefile.rb` file at the root of your project, in which are defined one or more pipelines :
28
+
29
+ pipeline 'scripts', 'public/js' do
30
+ match '*.js'
31
+ yui_js
32
+ end
33
+
34
+ # Slightly more complex example
35
+ pipeline 'styles', 'public/css' do
36
+ parallel do # execute two pipelines on the same source files
37
+ run do # take sass and scss files and compile them into css
38
+ match '*.sass', '*.scss'
39
+ sass # sass and scss filters are identical
40
+ end
41
+
42
+ run do # take only css files
43
+ match '*.css'
44
+ end
45
+ end
46
+
47
+ # We now have only css files, either copied from source or compiled from sass
48
+
49
+ yui_css # minify the stylesheets
50
+ end
51
+
52
+ Now run `piperun` in your root directory, and your files will be available in `public/js` and `public/css` !
53
+
54
+ ### Filters
55
+
56
+ The following filters are supported :
57
+ - Copy
58
+ - Match
59
+ - Parallel
60
+ - Tar
61
+ - Gz
62
+ - Sass / Scss
63
+ - Browserify
64
+ - YUI JS and CSS compressors
65
+
66
+ Feel free to make a PR to add some. Check out examples in `lib/piperun/filters/` to see how.
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :build
7
+
data/bin/piperun ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require 'piperun/cli'
6
+
7
+ Piperun::CLI.start
8
+
@@ -0,0 +1,30 @@
1
+ require 'piperun'
2
+ require 'thor'
3
+
4
+ module Piperun
5
+ class CLI < Thor
6
+ #description "Process files with pipelines"
7
+ #version Piperun::VERSION
8
+
9
+ default_task :build
10
+
11
+ desc "build", "Build the project."
12
+ def build
13
+ project = Piperun::Project.load "Pipefile.rb"
14
+ project.run
15
+ end
16
+
17
+ desc "watch", "Watch the project"
18
+ def watch
19
+ project = Piperun::Project.load "Pipefile.rb"
20
+ project.run
21
+ project.watch
22
+
23
+ begin
24
+ Kernel.sleep
25
+ rescue Interrupt
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,32 @@
1
+ module Piperun::Filters
2
+ class BrowserifyFilter < Filter
3
+ def initialize(entry, options = {})
4
+ super()
5
+
6
+ @entry = [*entry]
7
+ @options = {
8
+ output: 'bundle.js',
9
+ debug: false,
10
+ fast: false
11
+ }.merge options
12
+ end
13
+
14
+ def run(src, dst, files)
15
+ entry = @entry.map { |e| File.join(src, e) }
16
+ dstpath = File.join(dst, @options[:output])
17
+ FileUtils::mkdir_p File.dirname(dstpath)
18
+
19
+ argv = ['browserify',
20
+ '-o', dstpath,
21
+ *entry]
22
+ argv += ['--debug'] if @options[:debug]
23
+ argv += ['--fast'] if @options[:fast]
24
+
25
+ pid = Process.spawn(*argv)
26
+ Process.wait(pid)
27
+
28
+ return [@options[:output]]
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,8 @@
1
+ module Piperun::Filters
2
+ class CopyFilter < TransformFilter
3
+ def transform(src, dst)
4
+ FileUtils::copy_file src, dst
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,16 @@
1
+ module Piperun::Filters
2
+ class GzFilter < TransformFilter
3
+ add_extension '.gz'
4
+
5
+ def transform(src, dst)
6
+ Zlib::GzipWriter.open(dst) do |gz|
7
+ gz.write IO.binread(src)
8
+ end
9
+ end
10
+
11
+ def external_dependencies
12
+ ['zlib']
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,14 @@
1
+ module Piperun::Filters
2
+ class MatchFilter < CopyFilter
3
+ def initialize(*args)
4
+ super()
5
+
6
+ @patterns = [*args]
7
+ end
8
+
9
+ def mapping(name)
10
+ name if @patterns.any? { |p| File.fnmatch(p, name) }
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,37 @@
1
+ module Piperun::Filters
2
+ class ParallelFilter < Filter
3
+ attr_reader :pipelines
4
+
5
+ def initialize(&block)
6
+ super()
7
+
8
+ @pipelines = []
9
+
10
+ dsl = DSL.new(self)
11
+ dsl.instance_eval(&block)
12
+ end
13
+
14
+ def add_pipeline(p)
15
+ @pipelines << p
16
+ end
17
+
18
+ def run(src, dst, files)
19
+ outfiles = []
20
+ @pipelines.each do |p|
21
+ outfiles |= Piperun::Pipeline.build(src, dst, &p).run(files)
22
+ end
23
+ return outfiles
24
+ end
25
+
26
+ class DSL
27
+ def initialize(parent)
28
+ @parent = parent
29
+ end
30
+
31
+ def run(&block)
32
+ @parent.add_pipeline(block)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,21 @@
1
+ module Piperun::Filters
2
+ class SassFilter < TransformFilter
3
+ replace_extension '.css'
4
+
5
+ def initialize(options = {})
6
+ super()
7
+
8
+ @options = options
9
+ end
10
+
11
+ def transform(src, dst)
12
+ e = Sass::Engine.for_file src, @options
13
+ File.write dst, e.render
14
+ end
15
+
16
+ def external_dependencies
17
+ ['sass']
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,29 @@
1
+ module Piperun::Filters
2
+ class TarFilter < Filter
3
+ def initialize(output, options = {})
4
+ super()
5
+
6
+ @output = output
7
+ @options = options
8
+ end
9
+
10
+ def run(src, dst, files)
11
+ dstpath = File.join(dst, @output)
12
+ FileUtils::mkdir_p File.dirname(dstpath)
13
+
14
+ File.open(dstpath, 'wb') do |out|
15
+ tar = Archive::Tar::Minitar::Output.new out
16
+ Dir.chdir src do
17
+ files.each { |f| Archive::Tar::Minitar.pack_file(f, tar) }
18
+ end
19
+ end
20
+
21
+ return [@output]
22
+ end
23
+
24
+ def external_dependencies
25
+ ['archive/tar/minitar']
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,47 @@
1
+ module Piperun::Filters
2
+ class TransformFilter < Filter
3
+ def run(src, dst, files)
4
+ outfiles = []
5
+ files.each do |name|
6
+ outname = mapping(name)
7
+ next unless outname
8
+
9
+ srcpath = File.join(src, name)
10
+ dstpath = File.join(dst, outname)
11
+ FileUtils::mkdir_p File.dirname(dstpath)
12
+
13
+ transform(srcpath, dstpath)
14
+
15
+ outfiles << outname
16
+ end
17
+
18
+ return outfiles
19
+ end
20
+
21
+ def mapping(name)
22
+ name
23
+ end
24
+
25
+ #def transform(src, dst)
26
+ #end
27
+
28
+ protected
29
+ def self.replace_extension ext
30
+ self.class_eval <<-EVAL
31
+ def mapping(name)
32
+ "\#{File.join(File.dirname(name), File.basename(name, '.*'))}#{ext}"
33
+ end
34
+ EVAL
35
+ end
36
+
37
+ def self.add_extension ext
38
+ self.class_eval <<-EVAL
39
+ def mapping(name)
40
+ "\#{name}#{ext}"
41
+ end
42
+ EVAL
43
+ end
44
+ end
45
+ end
46
+
47
+
@@ -0,0 +1,20 @@
1
+ module Piperun::Filters
2
+ class YuiCssFilter < TransformFilter
3
+ def initialize(options = {})
4
+ super()
5
+
6
+ @options = options
7
+ end
8
+
9
+ def transform(src, dst)
10
+ c = YUI::CssCompressor.new @options
11
+ File.write dst, c.compress(File.read src)
12
+ end
13
+
14
+ def external_dependencies
15
+ ['yui/compressor']
16
+ end
17
+ end
18
+ end
19
+
20
+
@@ -0,0 +1,19 @@
1
+ module Piperun::Filters
2
+ class YuiJsFilter < TransformFilter
3
+ def initialize(options = {})
4
+ super()
5
+
6
+ @options = options
7
+ end
8
+
9
+ def transform(src, dst)
10
+ c = YUI::JavaScriptCompressor.new @options
11
+ File.write dst, c.compress(File.read src)
12
+ end
13
+
14
+ def external_dependencies
15
+ ['yui/compressor']
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,54 @@
1
+ module Piperun::Filters
2
+ class Filter
3
+ #def run(src, dst, files)
4
+ #end
5
+
6
+ def initialize
7
+ super
8
+
9
+ require_dependencies!
10
+ end
11
+
12
+ protected
13
+ def external_dependencies
14
+ return []
15
+ end
16
+
17
+ private
18
+ def require_dependencies!
19
+ external_dependencies.each do |d|
20
+ begin
21
+ require d
22
+ rescue LoadError => error
23
+ raise error, "#{self.class} requires #{d}, but it is not available"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ require 'piperun/filters/transform_filter'
31
+
32
+ require 'piperun/filters/copy_filter'
33
+ require 'piperun/filters/browserify_filter'
34
+ require 'piperun/filters/match_filter'
35
+ require 'piperun/filters/parallel_filter'
36
+ require 'piperun/filters/sass_filter'
37
+ require 'piperun/filters/tar_filter'
38
+ require 'piperun/filters/gz_filter'
39
+ require 'piperun/filters/yui_css_filter'
40
+ require 'piperun/filters/yui_js_filter'
41
+
42
+ class Piperun::Pipeline::DSL
43
+ add_filter :copy, Piperun::Filters::CopyFilter
44
+ add_filter :browserify, Piperun::Filters::BrowserifyFilter
45
+ add_filter :match, Piperun::Filters::MatchFilter
46
+ add_filter :parallel, Piperun::Filters::ParallelFilter
47
+ add_filter :sass, Piperun::Filters::SassFilter
48
+ add_filter :scss, Piperun::Filters::SassFilter
49
+ add_filter :tar, Piperun::Filters::TarFilter
50
+ add_filter :gz, Piperun::Filters::GzFilter
51
+ add_filter :yui_css, Piperun::Filters::YuiCssFilter
52
+ add_filter :yui_js, Piperun::Filters::YuiJsFilter
53
+ end
54
+
@@ -0,0 +1,80 @@
1
+ require 'tmpdir'
2
+ require 'listen'
3
+
4
+ module Piperun
5
+ class Pipeline
6
+ attr_reader :filters
7
+ def initialize(src, dst)
8
+ @src = File.absolute_path(src)
9
+ @dst = File.absolute_path(dst)
10
+ @filters = []
11
+ end
12
+
13
+ def add_filter(f)
14
+ @filters << f
15
+ end
16
+
17
+ def self.build(src, dst, &block)
18
+ pipe = new(src, dst)
19
+ dsl = DSL.new(pipe)
20
+ dsl.instance_eval(&block)
21
+ pipe
22
+ end
23
+
24
+ class DSL
25
+ def initialize(parent)
26
+ @parent = parent
27
+ end
28
+
29
+ def filter(f)
30
+ @parent.add_filter(f)
31
+ end
32
+
33
+ def self.add_filter(name, f)
34
+ self.class_eval <<-EVAL
35
+ def #{name}(*args, &block)
36
+ self.filter #{f}.new *args, &block
37
+ end
38
+ EVAL
39
+ end
40
+ end
41
+
42
+ def run(files = nil)
43
+ if files == nil
44
+ Dir.chdir @src do
45
+ files = Dir['**/*'].reject {|fn| File.directory?(fn) }
46
+ end
47
+ end
48
+
49
+ src = @src
50
+
51
+ @filters.each do |f|
52
+ begin
53
+ break if files.length == 0
54
+
55
+ if f == @filters.last
56
+ dst = @dst
57
+ FileUtils.mkdir_p dst
58
+ else
59
+ dst = Dir.mktmpdir
60
+ end
61
+
62
+ files = f.run(src, dst, files)
63
+ ensure
64
+ FileUtils.remove_entry_secure src unless src == @src
65
+ end
66
+
67
+ src = dst
68
+ end
69
+
70
+ return files
71
+ end
72
+
73
+ def watch
74
+ Listen.to(@src) do |modified, added, removed|
75
+ run
76
+ end.start
77
+ end
78
+ end
79
+ end
80
+
@@ -0,0 +1,50 @@
1
+ module Piperun
2
+ class Project
3
+ attr_reader :pipelines
4
+
5
+ def initialize
6
+ @pipelines = []
7
+ end
8
+
9
+ def add_pipeline(p)
10
+ @pipelines << p
11
+ end
12
+
13
+ def self.build(&block)
14
+ pipe = new
15
+ dsl = DSL.new(pipe)
16
+ dsl.instance_eval(&block)
17
+ pipe
18
+ end
19
+
20
+ def self.load(filename)
21
+ pipe = new
22
+ dsl = DSL.new(pipe)
23
+ dsl.instance_eval(File.read(filename), filename)
24
+ pipe
25
+ end
26
+
27
+ class DSL
28
+ def initialize(parent)
29
+ @parent = parent
30
+ end
31
+
32
+ def pipeline(src, dst, &block)
33
+ @parent.add_pipeline Pipeline.build(src, dst, &block)
34
+ end
35
+ end
36
+
37
+ def run
38
+ @pipelines.each do |p|
39
+ p.run
40
+ end
41
+ end
42
+
43
+ def watch
44
+ @pipelines.each do |p|
45
+ p.watch
46
+ end
47
+ end
48
+ end
49
+ end
50
+
@@ -0,0 +1,3 @@
1
+ module Piperun
2
+ VERSION = "0.1.0"
3
+ end
data/lib/piperun.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'piperun/version'
2
+
3
+ require 'piperun/project'
4
+ require 'piperun/pipeline'
5
+ require 'piperun/filters'
6
+
7
+ module Piperun
8
+ end
9
+
data/piperun.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'piperun/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "piperun"
8
+ spec.version = Piperun::VERSION
9
+ spec.authors = ["Paul Liétar"]
10
+ spec.email = ["paul@lietar.net"]
11
+ spec.description = %q{Process files using pipelines}
12
+ spec.summary = %q{Piperun}
13
+ spec.homepage = "https://github.com/plietar/piperun"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "listen", "~> 2.0"
22
+ spec.add_runtime_dependency "thor", "~> 0.19"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec", "~> 2.14"
26
+ spec.add_development_dependency "simplecov", "~> 0.9"
27
+ end
data/spec/cli_spec.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'piperun/cli'
2
+
3
+ describe Piperun::CLI do
4
+ let(:project) { Piperun::Project.new }
5
+
6
+ before do
7
+ project.stub(:run)
8
+ project.stub(:watch)
9
+ Piperun::Project.stub(:new).and_return(project)
10
+ Piperun::Project.stub(:build).and_return(project)
11
+ Piperun::Project.stub(:load).and_return(project)
12
+
13
+ Kernel.stub :sleep
14
+ end
15
+
16
+ def piperun(*args)
17
+ Piperun::CLI.start args
18
+ end
19
+
20
+ context 'with no arguments' do
21
+ it 'builds the project' do
22
+ expect(project).to receive(:run)
23
+ piperun
24
+ end
25
+
26
+ it 'doesn\'t watch the project' do
27
+ expect(project).to_not receive(:watch)
28
+ piperun
29
+ end
30
+ end
31
+
32
+ context "with a watch argument" do
33
+ it 'builds the project' do
34
+ expect(project).to receive(:run)
35
+ piperun "watch"
36
+ end
37
+
38
+ it 'watches the project' do
39
+ expect(project).to receive(:watch)
40
+ piperun "watch"
41
+ end
42
+
43
+ it 'sleeps forever' do
44
+ expect(Kernel).to receive(:sleep)
45
+ piperun "watch"
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,136 @@
1
+ require 'piperun'
2
+ require 'pp'
3
+
4
+ describe Piperun::Pipeline do
5
+ class MockFilter
6
+ def run(src, dst, files)
7
+ files
8
+ end
9
+ end
10
+
11
+ let(:input) { tmpdir + 'in' }
12
+ let(:output) { tmpdir + 'out' }
13
+ let(:pipeline) { Piperun::Pipeline.new(input, output) }
14
+ let(:filters) do
15
+ [
16
+ MockFilter.new,
17
+ MockFilter.new,
18
+ MockFilter.new
19
+ ]
20
+ end
21
+
22
+ before do
23
+ filters.each do |f|
24
+ pipeline.add_filter f
25
+ end
26
+
27
+ Dir.mkdir(input)
28
+ end
29
+
30
+ describe '#run' do
31
+ context 'with a file list' do
32
+ it 'creates temporary directories for filters' do
33
+ filters.each do |f|
34
+ expect(f).to receive(:run) do |src, dst, files|
35
+ expect(File.directory?(src)).to be true
36
+ expect(File.directory?(dst)).to be true
37
+
38
+ files
39
+ end
40
+ end
41
+
42
+ pipeline.run ['foo', 'bar']
43
+ end
44
+
45
+ it 'deletes all temporary directories' do
46
+ dirs = []
47
+ filters.each do |f|
48
+ expect(f).to receive(:run) do |src, dst, files|
49
+ dirs << src unless(dirs.include? src or src == input.to_s or src == output.to_s)
50
+ dirs << dst unless(dirs.include? dst or dst == input.to_s or dst == output.to_s)
51
+ end
52
+ end
53
+
54
+ pipeline.run ['foo', 'bar']
55
+
56
+ dirs.each do |d|
57
+ expect(File.directory?(d)).to be false
58
+ end
59
+ end
60
+
61
+ it 'doesn\'t delete source and destination directories' do
62
+ pipeline.run ['foo', 'bar']
63
+
64
+ expect(File.directory?(input)).to be true
65
+ expect(File.directory?(output)).to be true
66
+ end
67
+
68
+ it 'chains the file list' do
69
+ files = [
70
+ ['foo', 'bar'],
71
+ ['hello', 'world'],
72
+ ['foobar'],
73
+ ['blabla']
74
+ ]
75
+ infiles = files[0]
76
+
77
+ filters.each do |f|
78
+ expect(f).to receive(:run).with(anything(), anything(), match_array(files[0])).and_return(files[1])
79
+ files.shift
80
+ end
81
+
82
+ outfiles = pipeline.run infiles
83
+ expect(outfiles).to match_array(files[0])
84
+ end
85
+ end
86
+
87
+ context 'without a file list' do
88
+ it 'uses all files in the source directory' do
89
+ files = ['foo', 'bar/foo']
90
+
91
+ files.each do |f|
92
+ FileUtils.mkdir_p(File.dirname(input + f))
93
+ FileUtils.touch(input + f)
94
+ end
95
+
96
+ filters.each do |f|
97
+ expect(f).to receive(:run).with(anything(), anything(), match_array(files)).and_return(files)
98
+ end
99
+
100
+ pipeline.run
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '#watch' do
106
+ it 'watches the input directory' do
107
+ watcher = double()
108
+ expect(Listen).to receive(:to).with(input.to_s).and_return(watcher)
109
+ expect(watcher).to receive(:start).and_return(true)
110
+
111
+ pipeline.watch
112
+ end
113
+
114
+ context 'when a file is modified' do
115
+ it 'runs the pipeline' do
116
+ watcher = double()
117
+ block = nil
118
+
119
+ expect(Listen).to receive(:to) do |path, &b|
120
+ block = b
121
+ watcher
122
+ end
123
+
124
+ expect(watcher).to receive(:start) do
125
+ expect(block).to_not be_nil
126
+ block.call
127
+ end
128
+
129
+ expect(pipeline).to receive(:run)
130
+
131
+ pipeline.watch
132
+ end
133
+ end
134
+ end
135
+ end
136
+
@@ -0,0 +1,53 @@
1
+ require 'piperun'
2
+
3
+ describe Piperun::Project do
4
+ let(:project) { Piperun::Project.new }
5
+ let(:pipelines) do
6
+ [
7
+ Piperun::Pipeline.new(tmpdir + 'p1/in', tmpdir + 'p1/out'),
8
+ Piperun::Pipeline.new(tmpdir + 'p2/in', tmpdir + 'p2/out'),
9
+ Piperun::Pipeline.new(tmpdir + 'p3/in', tmpdir + 'p3/out')
10
+ ]
11
+ end
12
+
13
+ before do
14
+ pipelines.each do |p|
15
+ project.add_pipeline p
16
+ p.stub(:run)
17
+ p.stub(:watch)
18
+ end
19
+ end
20
+
21
+ describe '#run' do
22
+ it 'runs each pipeline' do
23
+ pipelines.each do |p|
24
+ expect(p).to receive(:run)
25
+ end
26
+ project.run
27
+ end
28
+
29
+ it 'doesn\'t watch the pipelines' do
30
+ pipelines.each do |p|
31
+ expect(p).to_not receive(:watch)
32
+ end
33
+ project.run
34
+ end
35
+ end
36
+
37
+ describe '#watch' do
38
+ it 'doesn\'t run the pipelines' do
39
+ pipelines.each do |p|
40
+ expect(p).to_not receive(:run)
41
+ end
42
+ project.watch
43
+ end
44
+
45
+ it 'watches each pipelines' do
46
+ pipelines.each do |p|
47
+ expect(p).to receive(:watch)
48
+ end
49
+ project.watch
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,21 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter 'spec/'
5
+ end
6
+
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
+ def tmpdir
13
+ @tmpdir ||= Pathname.new(Dir.mktmpdir)
14
+ end
15
+
16
+ config.after(:each) do
17
+ @tmpdir.rmtree if @tmpdir
18
+ @tmpdir = nil
19
+ end
20
+ end
21
+
@@ -0,0 +1,12 @@
1
+ require 'piperun/version'
2
+
3
+ describe 'Piperun::VERSION' do
4
+ it 'is a string' do
5
+ expect(Piperun::VERSION).to be_a(String)
6
+ end
7
+
8
+ it 'looks like a version' do
9
+ expect(Piperun::VERSION).to match(/^\d+\.\d+(\.\d+)?$/)
10
+ end
11
+ end
12
+
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: piperun
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul Liétar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: listen
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.19'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.19'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '2.14'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '2.14'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '0.9'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '0.9'
97
+ description: Process files using pipelines
98
+ email:
99
+ - paul@lietar.net
100
+ executables:
101
+ - piperun
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - .gitignore
106
+ - .rspec
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/piperun
112
+ - lib/piperun.rb
113
+ - lib/piperun/cli.rb
114
+ - lib/piperun/filters.rb
115
+ - lib/piperun/filters/browserify_filter.rb
116
+ - lib/piperun/filters/copy_filter.rb
117
+ - lib/piperun/filters/gz_filter.rb
118
+ - lib/piperun/filters/match_filter.rb
119
+ - lib/piperun/filters/parallel_filter.rb
120
+ - lib/piperun/filters/sass_filter.rb
121
+ - lib/piperun/filters/tar_filter.rb
122
+ - lib/piperun/filters/transform_filter.rb
123
+ - lib/piperun/filters/yui_css_filter.rb
124
+ - lib/piperun/filters/yui_js_filter.rb
125
+ - lib/piperun/pipeline.rb
126
+ - lib/piperun/project.rb
127
+ - lib/piperun/version.rb
128
+ - piperun.gemspec
129
+ - spec/cli_spec.rb
130
+ - spec/pipeline_spec.rb
131
+ - spec/project_spec.rb
132
+ - spec/spec_helper.rb
133
+ - spec/version_spec.rb
134
+ homepage: https://github.com/plietar/piperun
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.2.2
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: Piperun
158
+ test_files:
159
+ - spec/cli_spec.rb
160
+ - spec/pipeline_spec.rb
161
+ - spec/project_spec.rb
162
+ - spec/spec_helper.rb
163
+ - spec/version_spec.rb