piperun 0.1.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 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