rake-pipeline 0.5.0 → 0.7.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.
- data/.travis.yml +12 -0
- data/Gemfile +1 -0
- data/README.markdown +1 -1
- data/README.yard +61 -32
- data/Rakefile +9 -0
- data/bin/rakep +1 -24
- data/lib/generators/rake/pipeline/install/install_generator.rb +70 -0
- data/lib/rake-pipeline.rb +117 -53
- data/lib/rake-pipeline/cli.rb +56 -0
- data/lib/rake-pipeline/dsl.rb +3 -140
- data/lib/rake-pipeline/dsl/pipeline_dsl.rb +168 -0
- data/lib/rake-pipeline/dsl/project_dsl.rb +108 -0
- data/lib/rake-pipeline/dynamic_file_task.rb +188 -0
- data/lib/rake-pipeline/file_wrapper.rb +1 -1
- data/lib/rake-pipeline/filter.rb +45 -15
- data/lib/rake-pipeline/filters.rb +3 -1
- data/lib/rake-pipeline/filters/{concat.rb → concat_filter.rb} +0 -0
- data/lib/rake-pipeline/filters/ordering_concat_filter.rb +38 -0
- data/lib/rake-pipeline/filters/pipeline_finalizing_filter.rb +19 -0
- data/lib/rake-pipeline/graph.rb +178 -0
- data/lib/rake-pipeline/manifest.rb +63 -0
- data/lib/rake-pipeline/manifest_entry.rb +34 -0
- data/lib/rake-pipeline/matcher.rb +65 -30
- data/lib/rake-pipeline/middleware.rb +15 -12
- data/lib/rake-pipeline/precompile.rake +8 -0
- data/lib/rake-pipeline/project.rb +280 -0
- data/lib/rake-pipeline/railtie.rb +16 -1
- data/lib/rake-pipeline/server.rb +15 -0
- data/lib/rake-pipeline/version.rb +2 -2
- data/rake-pipeline.gemspec +2 -0
- data/spec/cli_spec.rb +71 -0
- data/spec/concat_filter_spec.rb +1 -27
- data/spec/{dsl_spec.rb → dsl/pipeline_dsl_spec.rb} +32 -18
- data/spec/dsl/project_dsl_spec.rb +41 -0
- data/spec/dynamic_file_task_spec.rb +111 -0
- data/spec/encoding_spec.rb +6 -8
- data/spec/file_wrapper_spec.rb +19 -2
- data/spec/filter_spec.rb +120 -22
- data/spec/graph_spec.rb +56 -0
- data/spec/manifest_entry_spec.rb +51 -0
- data/spec/manifest_spec.rb +67 -0
- data/spec/matcher_spec.rb +35 -2
- data/spec/middleware_spec.rb +123 -75
- data/spec/ordering_concat_filter_spec.rb +39 -0
- data/spec/pipeline_spec.rb +95 -34
- data/spec/project_spec.rb +293 -0
- data/spec/rake_acceptance_spec.rb +307 -67
- data/spec/rake_tasks_spec.rb +21 -0
- data/spec/spec_helper.rb +11 -48
- data/spec/support/spec_helpers/file_utils.rb +35 -0
- data/spec/support/spec_helpers/filters.rb +16 -0
- data/spec/support/spec_helpers/input_helpers.rb +23 -0
- data/spec/support/spec_helpers/memory_file_wrapper.rb +31 -0
- data/tools/perfs +107 -0
- metadata +100 -12
@@ -2,14 +2,29 @@ require "rake-pipeline/middleware"
|
|
2
2
|
|
3
3
|
module Rake
|
4
4
|
class Pipeline
|
5
|
+
# Use Rake::Pipeline inside of Rails 3.x. To use, simply add
|
6
|
+
# Rake::Pipeline to your +Gemfile+:
|
7
|
+
#
|
8
|
+
# !!!ruby
|
9
|
+
# gem 'rake-pipeline'
|
10
|
+
#
|
11
|
+
# Then, activate it in development mode. In config/development.rb:
|
12
|
+
#
|
13
|
+
# !!!ruby
|
14
|
+
# config.rake_pipeline_enabled = true
|
15
|
+
#
|
5
16
|
class Railtie < ::Rails::Railtie
|
6
17
|
config.rake_pipeline_enabled = false
|
7
18
|
config.rake_pipeline_assetfile = 'Assetfile'
|
8
19
|
|
20
|
+
rake_tasks do
|
21
|
+
load "rake-pipeline/precompile.rake"
|
22
|
+
end
|
23
|
+
|
9
24
|
initializer "rake-pipeline.assetfile" do |app|
|
10
25
|
if config.rake_pipeline_enabled
|
11
26
|
assetfile = File.join(Rails.root, config.rake_pipeline_assetfile)
|
12
|
-
config.app_middleware.
|
27
|
+
config.app_middleware.insert ActionDispatch::Static, Rake::Pipeline::Middleware, assetfile
|
13
28
|
end
|
14
29
|
end
|
15
30
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "rake-pipeline/middleware"
|
2
|
+
require "rack/server"
|
3
|
+
|
4
|
+
module Rake
|
5
|
+
class Pipeline
|
6
|
+
class Server < Rack::Server
|
7
|
+
def app
|
8
|
+
not_found = proc { [404, { "Content-Type" => "text/plain" }, ["not found"]] }
|
9
|
+
config = "Assetfile"
|
10
|
+
|
11
|
+
Middleware.new(not_found, config)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/rake-pipeline.gemspec
CHANGED
@@ -16,6 +16,8 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Rake::Pipeline::VERSION
|
17
17
|
|
18
18
|
gem.add_dependency "rake", "~> 0.9.0"
|
19
|
+
gem.add_dependency "thor"
|
20
|
+
gem.add_dependency "json"
|
19
21
|
|
20
22
|
gem.add_development_dependency "rspec"
|
21
23
|
gem.add_development_dependency "rack-test"
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
describe "Rake::Pipeline::CLI" do
|
2
|
+
attr_reader :project, :pipeline
|
3
|
+
|
4
|
+
before do
|
5
|
+
@project = Rake::Pipeline::Project.new
|
6
|
+
@project.stub(:clean)
|
7
|
+
@project.stub(:invoke)
|
8
|
+
@project.stub(:output_files).and_return([])
|
9
|
+
Rake::Pipeline::Project.stub(:new).and_return(@project)
|
10
|
+
end
|
11
|
+
|
12
|
+
def rakep(*args)
|
13
|
+
Rake::Pipeline::CLI.start(args)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "build" do
|
17
|
+
context "with no arguments" do
|
18
|
+
it "invokes a project" do
|
19
|
+
project.should_receive :invoke
|
20
|
+
rakep "build"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "cleans up the tmpdir" do
|
24
|
+
project.should_receive :cleanup_tmpdir
|
25
|
+
rakep "build"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with a --pretend argument" do
|
30
|
+
it "doesn't invoke a project" do
|
31
|
+
project.should_not_receive :invoke
|
32
|
+
rakep "build", "--pretend"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with a --clean argument" do
|
37
|
+
it "cleans a project" do
|
38
|
+
project.should_receive :clean
|
39
|
+
rakep "build", "--clean"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "invokes a project" do
|
43
|
+
project.should_receive :invoke
|
44
|
+
rakep "build", "--clean"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "clean" do
|
50
|
+
context "with no arguments" do
|
51
|
+
it "cleans a project" do
|
52
|
+
project.should_receive :clean
|
53
|
+
rakep "clean"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "server" do
|
59
|
+
let(:server) { double "server" }
|
60
|
+
|
61
|
+
before do
|
62
|
+
require 'rake-pipeline/server'
|
63
|
+
Rake::Pipeline::Server.stub(:new).and_return(server)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "starts a Rake::Pipeline::Server" do
|
67
|
+
server.should_receive :start
|
68
|
+
rakep "server"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/concat_filter_spec.rb
CHANGED
@@ -1,31 +1,5 @@
|
|
1
1
|
describe "ConcatFilter" do
|
2
|
-
|
3
|
-
@@files = {}
|
4
|
-
|
5
|
-
def self.files
|
6
|
-
@@files
|
7
|
-
end
|
8
|
-
|
9
|
-
def with_encoding(new_encoding)
|
10
|
-
self.class.new(root, path, new_encoding, body)
|
11
|
-
end
|
12
|
-
|
13
|
-
def fullpath
|
14
|
-
File.join(root, path)
|
15
|
-
end
|
16
|
-
|
17
|
-
def create
|
18
|
-
@@files[fullpath] = self
|
19
|
-
self.body = ""
|
20
|
-
yield
|
21
|
-
end
|
22
|
-
|
23
|
-
alias read body
|
24
|
-
|
25
|
-
def write(contents)
|
26
|
-
self.body << contents
|
27
|
-
end
|
28
|
-
end
|
2
|
+
MemoryFileWrapper = Rake::Pipeline::SpecHelpers::MemoryFileWrapper
|
29
3
|
|
30
4
|
let(:input_files) {
|
31
5
|
[
|
@@ -1,11 +1,11 @@
|
|
1
|
-
describe "Rake::Pipeline::
|
1
|
+
describe "Rake::Pipeline::PipelineDSL" do
|
2
2
|
ConcatFilter = Rake::Pipeline::SpecHelpers::Filters::ConcatFilter
|
3
3
|
|
4
4
|
let(:pipeline) { Rake::Pipeline.new }
|
5
|
-
let(:dsl) { Rake::Pipeline::DSL.new(pipeline) }
|
5
|
+
let(:dsl) { Rake::Pipeline::DSL::PipelineDSL.new(pipeline) }
|
6
6
|
|
7
|
-
|
8
|
-
pipeline.
|
7
|
+
def filter
|
8
|
+
pipeline.filters.last
|
9
9
|
end
|
10
10
|
|
11
11
|
it "accepts a pipeline in its constructor" do
|
@@ -13,19 +13,19 @@ describe "Rake::Pipeline::DSL" do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "#input" do
|
16
|
-
it "
|
16
|
+
it "adds an input to the pipeline" do
|
17
17
|
dsl.input "/app"
|
18
|
-
pipeline.
|
18
|
+
pipeline.inputs["/app"].should == '**/*'
|
19
19
|
end
|
20
20
|
|
21
|
-
it "configures the
|
21
|
+
it "configures the input's glob" do
|
22
22
|
dsl.input "/app", "*.js"
|
23
|
-
pipeline.
|
23
|
+
pipeline.inputs['/app'].should == "*.js"
|
24
24
|
end
|
25
25
|
|
26
|
-
it "defaults
|
26
|
+
it "defaults input's glob to **/*" do
|
27
27
|
dsl.input "/app"
|
28
|
-
pipeline.
|
28
|
+
pipeline.inputs['/app'].should == "**/*"
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -35,13 +35,13 @@ describe "Rake::Pipeline::DSL" do
|
|
35
35
|
pipeline.filters.should be_empty
|
36
36
|
dsl.filter ConcatFilter
|
37
37
|
pipeline.filters.should_not be_empty
|
38
|
-
|
38
|
+
filter.should be_kind_of(ConcatFilter)
|
39
39
|
end
|
40
40
|
|
41
41
|
it "takes a block to configure the filter's output file names" do
|
42
42
|
generator = proc { |input| "main.js" }
|
43
43
|
dsl.filter(ConcatFilter, &generator)
|
44
|
-
|
44
|
+
filter.output_name_generator.should == generator
|
45
45
|
end
|
46
46
|
|
47
47
|
it "passes any extra arguments to the filter's constructor" do
|
@@ -53,7 +53,7 @@ describe "Rake::Pipeline::DSL" do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
dsl.filter filter_class, "foo", "bar"
|
56
|
-
|
56
|
+
filter.args.should == %w(foo bar)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
@@ -66,7 +66,7 @@ describe "Rake::Pipeline::DSL" do
|
|
66
66
|
|
67
67
|
it "adds the new matcher to the pipeline's filters" do
|
68
68
|
matcher = dsl.match("*.glob") {}
|
69
|
-
|
69
|
+
filter.should == matcher
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -77,10 +77,24 @@ describe "Rake::Pipeline::DSL" do
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
describe "#
|
81
|
-
it "
|
82
|
-
dsl.
|
83
|
-
|
80
|
+
describe "#concat" do
|
81
|
+
it "creates a ConcatFilter" do
|
82
|
+
dsl.concat "octopus"
|
83
|
+
filter.should be_kind_of(Rake::Pipeline::ConcatFilter)
|
84
|
+
end
|
85
|
+
|
86
|
+
context "passed an Array first argument" do
|
87
|
+
it "creates an OrderingConcatFilter" do
|
88
|
+
dsl.concat ["octopus"]
|
89
|
+
filter.should be_kind_of(Rake::Pipeline::OrderingConcatFilter)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#copy" do
|
95
|
+
it "creates a ConcatFilter" do
|
96
|
+
dsl.copy
|
97
|
+
filter.should be_kind_of(Rake::Pipeline::ConcatFilter)
|
84
98
|
end
|
85
99
|
end
|
86
100
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
describe "Rake::Pipeline::ProjectDSL" do
|
2
|
+
ConcatFilter = Rake::Pipeline::SpecHelpers::Filters::ConcatFilter
|
3
|
+
|
4
|
+
let(:project) { Rake::Pipeline::Project.new }
|
5
|
+
let(:dsl) { Rake::Pipeline::DSL::ProjectDSL.new(project) }
|
6
|
+
|
7
|
+
it "accepts a project in its constructor" do
|
8
|
+
dsl.project.should == project
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#output" do
|
12
|
+
it "configures the project's default_output_root" do
|
13
|
+
dsl.output "/path/to/output"
|
14
|
+
project.default_output_root.should == "/path/to/output"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#tmpdir" do
|
19
|
+
it "sets the project's tmpdir" do
|
20
|
+
dsl.tmpdir "/path/to/tmpdir"
|
21
|
+
project.tmpdir.should == "/path/to/tmpdir"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#input" do
|
26
|
+
it "uses Project#build_pipeline to add a new pipeline to the project" do
|
27
|
+
project.should_receive(:build_pipeline)
|
28
|
+
dsl.input("app") {}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#map" do
|
33
|
+
it "saves the block in a hash on the project" do
|
34
|
+
project.maps.keys.size.should == 0
|
35
|
+
run_me = lambda { }
|
36
|
+
dsl.map("foo", &run_me)
|
37
|
+
dsl.project.maps["foo"].should == run_me
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rake::Pipeline::DynamicFileTask do
|
4
|
+
let(:invoked_tasks) { [] }
|
5
|
+
|
6
|
+
def define_task(deps, klass=Rake::Pipeline::DynamicFileTask, &task_proc)
|
7
|
+
task_proc ||= proc do |task|
|
8
|
+
touch(task.name)
|
9
|
+
invoked_tasks << task
|
10
|
+
end
|
11
|
+
|
12
|
+
klass.define_task(deps, &task_proc)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:task) { define_task('output') }
|
16
|
+
|
17
|
+
before do
|
18
|
+
# Make sure date conversions happen in UTC, not local time
|
19
|
+
ENV['TZ'] = 'UTC'
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
# Clean out all defined tasks after each test runs
|
24
|
+
Rake.application = Rake::Application.new
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#dynamic" do
|
28
|
+
it "saves a block that can be called later with #invoke_dynamic_block" do
|
29
|
+
block = proc {}
|
30
|
+
task.dynamic(&block)
|
31
|
+
block.should_receive(:call).with(task)
|
32
|
+
task.invoke_dynamic_block
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns the task" do
|
36
|
+
(task.dynamic {}).should eq(task)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#invoke" do
|
41
|
+
let(:static) { define_task('static', Rake::FileTask) }
|
42
|
+
let!(:dynamic) { define_task('dynamic', Rake::FileTask) }
|
43
|
+
let!(:dynamic_task) { define_task('output' => static).dynamic { ['dynamic'] } }
|
44
|
+
|
45
|
+
it "invokes the task's static and dynamic prerequisites" do
|
46
|
+
dynamic_task.invoke
|
47
|
+
invoked_tasks.should include(static)
|
48
|
+
invoked_tasks.should include(dynamic)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "adds dynamic dependencies to its manifest entry" do
|
52
|
+
dynamic_task.invoke
|
53
|
+
dynamic_task.manifest_entry.deps.should == {
|
54
|
+
'dynamic' => File.mtime('dynamic')
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
it "adds the current task's mtime to its manifest entry" do
|
59
|
+
dynamic_task.invoke
|
60
|
+
dynamic_task.manifest_entry.mtime.should == File.mtime('output')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#needed?" do
|
65
|
+
it "is true if the task has no previous manifest entry" do
|
66
|
+
task.last_manifest_entry.should be_nil
|
67
|
+
task.should be_needed
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#dynamic_prerequisites" do
|
72
|
+
def make_file(name, mtime=nil)
|
73
|
+
touch(name)
|
74
|
+
if mtime
|
75
|
+
File.utime(mtime, mtime, name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it "returns an empty array if the task has no dynamic block" do
|
80
|
+
task.dynamic_prerequisites.should == []
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns the result of invoking the dynamic block" do
|
84
|
+
task.dynamic { %w[blinky] }
|
85
|
+
task.dynamic_prerequisites.should == %w[blinky]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "filters the task itself from the list" do
|
89
|
+
task.dynamic { %w[output blinky] }
|
90
|
+
task.dynamic_prerequisites.should == %w[blinky]
|
91
|
+
end
|
92
|
+
|
93
|
+
it "loads dependency information from the manifest first" do
|
94
|
+
time = Time.utc(2000)
|
95
|
+
%w[blinky output].each { |f| make_file f, time }
|
96
|
+
|
97
|
+
manifest_entry = Rake::Pipeline::ManifestEntry.from_hash({
|
98
|
+
"deps" => {
|
99
|
+
"blinky" => "2000-01-01 00:00:00 +0000"
|
100
|
+
},
|
101
|
+
"mtime" => "2000-01-01 00:00:00 +0000"
|
102
|
+
})
|
103
|
+
|
104
|
+
task.dynamic { %w[] }
|
105
|
+
task.stub(:last_manifest_entry) { manifest_entry }
|
106
|
+
task.should_not_receive(:invoke_dynamic_block)
|
107
|
+
task.dynamic_prerequisites.should == %w[blinky]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
data/spec/encoding_spec.rb
CHANGED
@@ -57,11 +57,10 @@ if "".respond_to?(:encode)
|
|
57
57
|
create_files
|
58
58
|
|
59
59
|
@pipeline = Rake::Pipeline.build do
|
60
|
-
tmpdir "temporary"
|
61
|
-
input tmp, "app/javascripts/*.js"
|
62
|
-
filter Filters::ConcatFilter, "javascripts/application.js"
|
63
|
-
filter Filters::StripAssertsFilter
|
64
60
|
output "public"
|
61
|
+
input "#{tmp}/app/javascripts/", "*.js"
|
62
|
+
concat "javascripts/application.js"
|
63
|
+
filter Filters::StripAssertsFilter
|
65
64
|
end
|
66
65
|
end
|
67
66
|
|
@@ -86,11 +85,10 @@ if "".respond_to?(:encode)
|
|
86
85
|
let(:encoding) { "EUC-JP" }
|
87
86
|
|
88
87
|
it "does not raise an exception" do
|
89
|
-
|
90
|
-
tmpdir "temporary"
|
91
|
-
input tmp, "app/javascripts/*.js"
|
92
|
-
filter Filters::ConcatFilter, "javascripts/application.js"
|
88
|
+
pipeline = Rake::Pipeline.build do
|
93
89
|
output "public"
|
90
|
+
input "#{tmp}/app/javascripts/", "*.js"
|
91
|
+
concat "javascripts/application.js"
|
94
92
|
end
|
95
93
|
|
96
94
|
pipeline.invoke
|