rake-pipeline-fork 0.8.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.
Files changed (75) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +12 -0
  5. data/.yardopts +2 -0
  6. data/GETTING_STARTED.md +268 -0
  7. data/Gemfile +14 -0
  8. data/LICENSE +20 -0
  9. data/README.markdown +11 -0
  10. data/README.yard +178 -0
  11. data/Rakefile +21 -0
  12. data/bin/rakep +4 -0
  13. data/examples/copying_files.md +12 -0
  14. data/examples/minifying_files.md +37 -0
  15. data/examples/modifying_pipelines.md +67 -0
  16. data/examples/multiple_pipelines.md +77 -0
  17. data/lib/generators/rake/pipeline/install/install_generator.rb +70 -0
  18. data/lib/rake-pipeline.rb +462 -0
  19. data/lib/rake-pipeline/cli.rb +56 -0
  20. data/lib/rake-pipeline/dsl.rb +9 -0
  21. data/lib/rake-pipeline/dsl/pipeline_dsl.rb +246 -0
  22. data/lib/rake-pipeline/dsl/project_dsl.rb +108 -0
  23. data/lib/rake-pipeline/dynamic_file_task.rb +194 -0
  24. data/lib/rake-pipeline/error.rb +17 -0
  25. data/lib/rake-pipeline/file_wrapper.rb +182 -0
  26. data/lib/rake-pipeline/filter.rb +249 -0
  27. data/lib/rake-pipeline/filters.rb +4 -0
  28. data/lib/rake-pipeline/filters/concat_filter.rb +63 -0
  29. data/lib/rake-pipeline/filters/gsub_filter.rb +56 -0
  30. data/lib/rake-pipeline/filters/ordering_concat_filter.rb +38 -0
  31. data/lib/rake-pipeline/filters/pipeline_finalizing_filter.rb +21 -0
  32. data/lib/rake-pipeline/graph.rb +178 -0
  33. data/lib/rake-pipeline/manifest.rb +86 -0
  34. data/lib/rake-pipeline/manifest_entry.rb +34 -0
  35. data/lib/rake-pipeline/matcher.rb +141 -0
  36. data/lib/rake-pipeline/middleware.rb +72 -0
  37. data/lib/rake-pipeline/precompile.rake +8 -0
  38. data/lib/rake-pipeline/project.rb +335 -0
  39. data/lib/rake-pipeline/rails_plugin.rb +10 -0
  40. data/lib/rake-pipeline/railtie.rb +34 -0
  41. data/lib/rake-pipeline/reject_matcher.rb +29 -0
  42. data/lib/rake-pipeline/server.rb +15 -0
  43. data/lib/rake-pipeline/sorted_pipeline.rb +19 -0
  44. data/lib/rake-pipeline/version.rb +6 -0
  45. data/rails/init.rb +2 -0
  46. data/rake-pipeline.gemspec +24 -0
  47. data/spec/cli_spec.rb +71 -0
  48. data/spec/concat_filter_spec.rb +37 -0
  49. data/spec/dsl/pipeline_dsl_spec.rb +165 -0
  50. data/spec/dsl/project_dsl_spec.rb +41 -0
  51. data/spec/dynamic_file_task_spec.rb +119 -0
  52. data/spec/encoding_spec.rb +106 -0
  53. data/spec/file_wrapper_spec.rb +132 -0
  54. data/spec/filter_spec.rb +332 -0
  55. data/spec/graph_spec.rb +56 -0
  56. data/spec/gsub_filter_spec.rb +87 -0
  57. data/spec/manifest_entry_spec.rb +46 -0
  58. data/spec/manifest_spec.rb +67 -0
  59. data/spec/matcher_spec.rb +141 -0
  60. data/spec/middleware_spec.rb +199 -0
  61. data/spec/ordering_concat_filter_spec.rb +42 -0
  62. data/spec/pipeline_spec.rb +232 -0
  63. data/spec/project_spec.rb +295 -0
  64. data/spec/rake_acceptance_spec.rb +738 -0
  65. data/spec/rake_tasks_spec.rb +21 -0
  66. data/spec/reject_matcher_spec.rb +31 -0
  67. data/spec/sorted_pipeline_spec.rb +27 -0
  68. data/spec/spec_helper.rb +38 -0
  69. data/spec/support/spec_helpers/file_utils.rb +35 -0
  70. data/spec/support/spec_helpers/filters.rb +37 -0
  71. data/spec/support/spec_helpers/input_helpers.rb +23 -0
  72. data/spec/support/spec_helpers/memory_file_wrapper.rb +31 -0
  73. data/spec/support/spec_helpers/memory_manifest.rb +19 -0
  74. data/tools/perfs +101 -0
  75. metadata +215 -0
@@ -0,0 +1,42 @@
1
+ describe "OrderingConcatFilter" do
2
+ MemoryFileWrapper ||= Rake::Pipeline::SpecHelpers::MemoryFileWrapper
3
+ MemoryManifest ||= Rake::Pipeline::SpecHelpers::MemoryManifest
4
+
5
+ let(:input_files) {
6
+ [
7
+ MemoryFileWrapper.new("/path/to/input", "first.txt", "UTF-8", "FIRST"),
8
+ MemoryFileWrapper.new("/path/to/input", "second.txt", "UTF-8", "SECOND"),
9
+ MemoryFileWrapper.new("/path/to/input", "last.txt", "UTF-8", "LAST")
10
+ ]
11
+ }
12
+
13
+ let(:output_files) {
14
+ [
15
+ MemoryFileWrapper.new("/path/to/output", "all.txt", "BINARY")
16
+ ]
17
+ }
18
+
19
+ let(:output_file) {
20
+ MemoryFileWrapper.files["/path/to/output/all.txt"]
21
+ }
22
+
23
+ def make_filter(ordering)
24
+ filter = Rake::Pipeline::OrderingConcatFilter.new(ordering, "all.txt")
25
+ filter.manifest = MemoryManifest.new
26
+ filter.last_manifest = MemoryManifest.new
27
+ filter.file_wrapper_class = MemoryFileWrapper
28
+ filter.input_files = input_files
29
+ filter.output_root = "/path/to/output"
30
+ filter.rake_application = Rake::Application.new
31
+ filter.generate_rake_tasks.each(&:invoke)
32
+ filter
33
+ end
34
+
35
+ it "generates output" do
36
+ filter = make_filter(["first.txt", "second.txt"])
37
+
38
+ filter.output_files.should == output_files
39
+ output_file.body.should == "FIRSTSECONDLAST"
40
+ output_file.encoding.should == "BINARY"
41
+ end
42
+ end
@@ -0,0 +1,232 @@
1
+ describe "Rake::Pipeline" do
2
+ ConcatFilter ||= Rake::Pipeline::SpecHelpers::Filters::ConcatFilter
3
+ StripAssertsFilter ||= Rake::Pipeline::SpecHelpers::Filters::StripAssertsFilter
4
+
5
+ let(:project) { Rake::Pipeline::Project.new }
6
+ let(:pipeline) { Rake::Pipeline.new :project => project }
7
+
8
+ it "accepts a input root" do
9
+ pipeline.add_input "app/assets"
10
+ pipeline.inputs["app/assets"].should == '**/*'
11
+ end
12
+
13
+ it "raises an exception on #relative_input_files if input_files are not provided" do
14
+ lambda { pipeline.input_files }.should raise_error(Rake::Pipeline::Error)
15
+ end
16
+
17
+ it "accepts a temporary directory" do
18
+ pipeline.tmpdir = "tmp"
19
+ pipeline.tmpdir.should == File.expand_path("tmp")
20
+ end
21
+
22
+ it "accepts an output directory" do
23
+ pipeline.output_root = "public"
24
+ pipeline.output_root.should == File.expand_path("public")
25
+ end
26
+
27
+ it "accepts a rake application" do
28
+ app = Rake::Application.new
29
+ pipeline.rake_application = app
30
+ pipeline.rake_application.should == app
31
+ end
32
+
33
+ it "defaults the rake application to Rake.application" do
34
+ pipeline.rake_application.should == Rake.application
35
+ end
36
+
37
+ describe ".build" do
38
+ it "evaluates a block against a new Pipeline" do
39
+ pipeline = Rake::Pipeline.build do
40
+ output "octopus"
41
+ end
42
+ pipeline.should be_kind_of(Rake::Pipeline)
43
+ pipeline.output_root.should == File.expand_path("octopus")
44
+ end
45
+ end
46
+
47
+ describe "#build" do
48
+ it "evaluates a block against an existing Pipeline" do
49
+ pipeline = Rake::Pipeline.new
50
+ pipeline.output_root = "octopus"
51
+
52
+ pipeline.build do
53
+ output "squid"
54
+ end
55
+ pipeline.output_root.should == File.expand_path("squid")
56
+ end
57
+ end
58
+
59
+ describe "the constructor" do
60
+ it "accepts an :inputs option" do
61
+ pipeline = Rake::Pipeline.new(:inputs => {"app/assets" => "**/*"})
62
+ pipeline.inputs.should == {"app/assets" => "**/*"}
63
+ end
64
+
65
+ it "accepts a :tmpdir option" do
66
+ pipeline = Rake::Pipeline.new(:tmpdir => "tmp")
67
+ pipeline.tmpdir.should == "tmp"
68
+ end
69
+
70
+ it "accepts an :output_root option" do
71
+ pipeline = Rake::Pipeline.new(:output_root => "public")
72
+ pipeline.output_root.should == File.expand_path("public")
73
+ end
74
+
75
+ it "accepts a :rake_application option" do
76
+ app = Rake::Application.new
77
+ pipeline = Rake::Pipeline.new(:rake_application => app)
78
+ pipeline.rake_application.should == app
79
+ end
80
+ end
81
+
82
+ describe "adding filters" do
83
+ let(:filter) { ConcatFilter.new }
84
+
85
+ it "can have filters added to it" do
86
+ pipeline.add_filter filter
87
+ end
88
+
89
+ it "sets an added filter's rake_application" do
90
+ app = Rake::Application.new
91
+ pipeline.rake_application = app
92
+ pipeline.add_filter filter
93
+ filter.rake_application.should == app
94
+ end
95
+
96
+ it "sets an added filter's pipeline" do
97
+ pipeline.add_filter filter
98
+ filter.pipeline.should == pipeline
99
+ end
100
+ end
101
+
102
+ describe "#copy" do
103
+ it "should copy state" do
104
+ copy = pipeline.copy
105
+ copy.inputs.should == pipeline.inputs
106
+ copy.tmpdir.should == pipeline.tmpdir
107
+ copy.rake_application.should == pipeline.rake_application
108
+ copy.project.should == pipeline.project
109
+ end
110
+ end
111
+
112
+ shared_examples_for "when working with input" do
113
+ include Rake::Pipeline::SpecHelpers::InputHelpers
114
+
115
+ let(:files) do
116
+ %w(javascripts/jquery.js javascripts/sproutcore.js).map do |filename|
117
+ input_file(filename)
118
+ end
119
+ end
120
+
121
+ def setup_roots
122
+ pipeline.add_input "app/assets"
123
+ end
124
+
125
+ before do
126
+ Rake.application = Rake::Application.new
127
+ create_files(files)
128
+ setup_roots
129
+ setup_input(pipeline)
130
+ pipeline.output_root = "public"
131
+ end
132
+
133
+ it "accepts a list of relative input files" do
134
+ pipeline.input_files.should == files
135
+ end
136
+
137
+ it "configures the filters with outputs and inputs with #rake_tasks" do
138
+ concat = ConcatFilter.new
139
+ concat.output_name_generator = proc { |input| "javascripts/application.js" }
140
+
141
+ strip_asserts = StripAssertsFilter.new
142
+ strip_asserts.output_name_generator = proc { |input| input }
143
+
144
+ pipeline.add_filters concat, strip_asserts
145
+ pipeline.setup
146
+
147
+ concat.input_files.should == pipeline.input_files
148
+ strip_asserts.input_files.each { |file| file.root.should == concat.output_root }
149
+
150
+ strip_asserts.input_files.should == [input_file("javascripts/application.js", concat.output_root)]
151
+ strip_asserts.output_root.should == File.expand_path(pipeline.output_root)
152
+ end
153
+
154
+ describe "generating rake tasks" do
155
+ tasks = nil
156
+
157
+ before do
158
+ concat = ConcatFilter.new
159
+ concat.output_name_generator = proc { |input| "javascripts/application.js" }
160
+ pipeline.add_filter concat
161
+ end
162
+
163
+ it "generates rake tasks in Rake.application" do
164
+ pipeline.setup
165
+ tasks = pipeline.rake_tasks
166
+
167
+ tasks.size.should == 1
168
+ task = tasks[0]
169
+ task.name.should == File.join(pipeline.output_root, "javascripts/application.js")
170
+
171
+ deps = task.prerequisites
172
+ deps.size.should == 2
173
+
174
+ root = File.expand_path(pipeline.inputs.keys.first)
175
+
176
+ deps[0].should == File.join(root, "javascripts/jquery.js")
177
+ deps[1].should == File.join(root, "javascripts/sproutcore.js")
178
+
179
+ Rake.application.tasks.size.should == 3
180
+ end
181
+
182
+ it "generates rake tasks is an alternate Rake::Application" do
183
+ app = Rake::Application.new
184
+ pipeline.rake_application = app
185
+ pipeline.setup
186
+ tasks = pipeline.rake_tasks
187
+
188
+ Rake.application.tasks.size.should == 0
189
+ end
190
+ end
191
+ end
192
+
193
+ describe "when using multiple input roots" do
194
+ it_behaves_like "when working with input"
195
+
196
+ def setup_roots
197
+ pipeline.add_input File.join(tmp, 'tmp1', "app/assets"), '**/*.js'
198
+ pipeline.add_input File.join(tmp, 'tmp2', "app/assets"), '**/*.css'
199
+ end
200
+
201
+ def setup_input(pipeline)
202
+ end
203
+
204
+ let(:files) do
205
+ f = []
206
+
207
+ %w(javascripts/jquery.js javascripts/sproutcore.js).map do |filename|
208
+ f << input_file(filename, File.join(tmp, 'tmp1', "app/assets"))
209
+ end
210
+
211
+ %w(stylesheets/jquery.css stylesheets/sproutcore.css).map do |filename|
212
+ f << input_file(filename, File.join(tmp, 'tmp2', "app/assets"))
213
+ end
214
+
215
+ f
216
+ end
217
+ end
218
+
219
+ describe "using an array for input files" do
220
+ it_behaves_like "when working with input"
221
+
222
+ def setup_input(pipeline)
223
+ Dir.chdir("app/assets") do
224
+ files = Dir["javascripts/**/*.js"].sort
225
+ wrappers = files.map do |file|
226
+ Rake::Pipeline::FileWrapper.new(File.join(tmp, "app/assets"), file)
227
+ end
228
+ pipeline.input_files = wrappers
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,295 @@
1
+ describe "Rake::Pipeline::Project" do
2
+ include Rake::Pipeline::SpecHelpers::InputHelpers
3
+
4
+ ASSETFILE_SOURCE = <<-HERE.gsub(/^ {4}/, '')
5
+ require "#{tmp}/../support/spec_helpers/filters"
6
+ tmpdir "tmp"
7
+ output "public"
8
+
9
+ input "app/assets" do
10
+ match "*.js" do
11
+ concat "javascripts/application.js"
12
+ filter Rake::Pipeline::SpecHelpers::Filters::StripAssertsFilter
13
+ end
14
+ end
15
+ HERE
16
+
17
+ MODIFIED_ASSETFILE_SOURCE = <<-HERE.gsub(/^ {4}/, '')
18
+ require "#{tmp}/../support/spec_helpers/filters"
19
+ tmpdir "tmp"
20
+ output "public"
21
+
22
+ input "app/assets" do
23
+ match "*.js" do
24
+ concat "javascripts/app.js"
25
+ filter Rake::Pipeline::SpecHelpers::Filters::StripAssertsFilter
26
+ end
27
+ end
28
+ HERE
29
+
30
+ BAD_ASSETFILE_SOURCE = <<-HERE.gsub(/^ {4}/, '')
31
+ require "#{tmp}/../support/spec_helpers/filters"
32
+ tmpdir "tmp"
33
+ output "public"
34
+
35
+ input "app/assets" do
36
+ method_not_in_dsl_on_line_6
37
+ end
38
+ HERE
39
+
40
+ let(:assetfile_path) { File.join(tmp, "Assetfile") }
41
+
42
+ def assetfile_digest
43
+ (Digest::SHA1.new << File.read(assetfile_path)).to_s
44
+ end
45
+
46
+ let(:unmatched_file) { input_file("junk.txt") }
47
+
48
+ let(:input_files) do
49
+ [input_file("jquery.js"), input_file("ember.js"), unmatched_file]
50
+ end
51
+
52
+ let(:output_files) do
53
+ [output_file("javascripts/application.js")]
54
+ end
55
+
56
+ let(:old_tmpdir) do
57
+ File.join(tmp, "tmp", "rake-pipeline-ad7a83894789")
58
+ end
59
+
60
+ let(:digested_tmpdir) do
61
+ File.join(tmp, "tmp", "rake-pipeline-#{assetfile_digest}")
62
+ end
63
+
64
+ attr_reader :project
65
+
66
+ before do
67
+ File.open(assetfile_path, 'w') { |file| file.write(ASSETFILE_SOURCE) }
68
+ create_files(input_files)
69
+ @project = Rake::Pipeline::Project.new(assetfile_path)
70
+ mkdir_p(old_tmpdir)
71
+ end
72
+
73
+ it "has an assetfile_path" do
74
+ project.assetfile_path.should == assetfile_path
75
+ end
76
+
77
+ it "has an assetfile_digest" do
78
+ project.assetfile_digest.should == assetfile_digest
79
+ end
80
+
81
+ it "has a pipeline" do
82
+ project.should have(1).pipelines
83
+ end
84
+
85
+ describe "constructor" do
86
+ it "creates pipelines from an Assetfile given an Assetfile path" do
87
+ project = Rake::Pipeline::Project.new(assetfile_path)
88
+ project.maps.should == {}
89
+ pipeline = project.pipelines.last
90
+ pipeline.inputs.should == { "app/assets" => "**/*" }
91
+ pipeline.output_root.should == File.join(tmp, "public")
92
+ end
93
+
94
+ it "wraps an existing pipeline" do
95
+ pipeline = Rake::Pipeline::Project.class_eval("build do\n#{File.read(assetfile_path)}\nend", assetfile_path, 1)
96
+ project = Rake::Pipeline::Project.new(pipeline)
97
+ project.pipelines.last.should == pipeline
98
+ end
99
+ end
100
+
101
+ describe "#invoke" do
102
+ def modify_assetfile
103
+ File.open(assetfile_path, 'w') do |file|
104
+ file.write(MODIFIED_ASSETFILE_SOURCE)
105
+ end
106
+ end
107
+
108
+ it "creates output files" do
109
+ output_files.each { |file| file.should_not exist }
110
+ project.invoke
111
+ output_files.each { |file| file.should exist }
112
+ end
113
+
114
+ it "writes temp files to a subdirectory of the tmp dir named after the assetfile digest" do
115
+ project.invoke
116
+ File.exist?(digested_tmpdir).should be_true
117
+ end
118
+
119
+ it "updates the manifest" do
120
+ project.last_manifest.should_receive(:read_manifest)
121
+ project.manifest.should_receive(:write_manifest)
122
+ project.invoke
123
+ end
124
+
125
+ it "rebuilds its pipeline when the Assetfile changes" do
126
+ project.invoke
127
+ original_pipeline = project.pipelines.last
128
+ original_assetfile_digest = assetfile_digest
129
+
130
+ modify_assetfile
131
+ project.invoke
132
+ assetfile_digest.should_not == original_assetfile_digest
133
+ project.pipelines.last.should_not == original_pipeline
134
+ end
135
+ end
136
+
137
+ describe "invalid Assetfile" do
138
+ before do
139
+ File.open(assetfile_path, 'w') { |file| file.write(BAD_ASSETFILE_SOURCE) }
140
+ end
141
+
142
+ it "should raise error with assetfile path on correct line number" do
143
+ lambda {
144
+ Rake::Pipeline::Project.new(assetfile_path)
145
+ }.should raise_error {|error| error.backtrace[0].should match(/Assetfile:6/) }
146
+ end
147
+ end
148
+
149
+ describe "#cleanup_tmpdir" do
150
+ it "cleans old rake-pipeline-* dirs out of the pipeline's tmp dir" do
151
+ File.exist?(old_tmpdir).should be_true
152
+ project.cleanup_tmpdir
153
+ File.exist?(old_tmpdir).should be_false
154
+ end
155
+
156
+ it "leaves the current assetfile-digest tmp dir alone" do
157
+ project.invoke
158
+ File.exist?(digested_tmpdir).should be_true
159
+ project.cleanup_tmpdir
160
+ File.exist?(digested_tmpdir).should be_true
161
+ end
162
+ end
163
+
164
+ describe "#clean" do
165
+ def rakep_tmpdirs
166
+ Dir["#{tmp}/tmp/rake-pipeline-*"]
167
+ end
168
+
169
+ it "cleans all rake-pipeline-* dirs out of the pipeline's tmp dir" do
170
+ project.invoke
171
+ rakep_tmpdirs.should_not be_empty
172
+ project.clean
173
+ rakep_tmpdirs.should be_empty
174
+ end
175
+
176
+ it "removes the pipeline's output files" do
177
+ project.invoke
178
+ output_files.each { |f| f.should exist }
179
+ project.clean
180
+ output_files.each { |f| f.should_not exist }
181
+ end
182
+
183
+ it "leaves the pipeline's unmatched input files alone" do
184
+ project.invoke
185
+ project.clean
186
+ unmatched_file.should exist
187
+ end
188
+ end
189
+
190
+ describe ".add_to_digest" do
191
+ after do
192
+ Rake::Pipeline::Project.digest_additions = []
193
+ end
194
+
195
+ it "appends a string to the generated tmp dir name" do
196
+ Rake::Pipeline::Project.add_to_digest("octopus")
197
+
198
+ File.basename(project.digested_tmpdir).should ==
199
+ "rake-pipeline-#{assetfile_digest}-octopus"
200
+ end
201
+
202
+ it "can be called multiple times" do
203
+ Rake::Pipeline::Project.add_to_digest("a")
204
+ Rake::Pipeline::Project.add_to_digest("b")
205
+
206
+ File.basename(project.digested_tmpdir).should ==
207
+ "rake-pipeline-#{assetfile_digest}-a-b"
208
+ end
209
+ end
210
+
211
+ describe "#build_pipeline" do
212
+ let(:inputs) { {"foo" => "**/*"} }
213
+
214
+ it "returns a pipeline" do
215
+ pipeline = project.build_pipeline(inputs) {}
216
+ pipeline.should be_kind_of(Rake::Pipeline)
217
+ end
218
+
219
+ it "adds the pipeline to the list of pipelines" do
220
+ pipeline = project.build_pipeline(inputs) {}
221
+ project.pipelines.last.should == pipeline
222
+ end
223
+
224
+ it "configures the pipeline with the pipeline DSL" do
225
+ pipeline = project.build_pipeline(inputs) do
226
+ output "bar"
227
+ end
228
+
229
+ pipeline.output_root.should == File.expand_path("bar")
230
+ end
231
+
232
+ it "sets the pipeline's tmpdir to a digest tmpdir" do
233
+ pipeline = project.build_pipeline(inputs) {}
234
+ pipeline.tmpdir.should == project.digested_tmpdir
235
+ end
236
+
237
+ it "sets the pipeline's output_root to the default_output_root" do
238
+ pipeline = project.build_pipeline(inputs) {}
239
+ pipeline.output_root.should == project.default_output_root
240
+ end
241
+
242
+ it "sets the pipeline's project to itself" do
243
+ pipeline = project.build_pipeline(inputs) {}
244
+ pipeline.project.should == project
245
+ end
246
+
247
+ it "creates a pipeline with a given set of inputs" do
248
+ pipeline = project.build_pipeline(inputs) {}
249
+ pipeline.inputs.should == inputs
250
+ end
251
+
252
+ it "can be called with a single path input" do
253
+ pipeline = project.build_pipeline("/path") {}
254
+ pipeline.inputs.should == {"/path" => "**/*"}
255
+ end
256
+
257
+ it "can be called with a path and a glob" do
258
+ pipeline = project.build_pipeline("/path", "*.js") {}
259
+ pipeline.inputs.should == {"/path" => "*.js"}
260
+ end
261
+
262
+ it "can be called with an array of paths" do
263
+ pipeline = project.build_pipeline(["path1", "path2"]) {}
264
+ pipeline.inputs.should have_key("path1")
265
+ pipeline.inputs.should have_key("path2")
266
+ end
267
+
268
+ it "can be called with a hash of path => glob pairs" do
269
+ pipeline = project.build_pipeline({"/path" => "*.css"}) {}
270
+ pipeline.inputs.should == {"/path" => "*.css"}
271
+ end
272
+ end
273
+
274
+ describe "#obsolete_tmpdirs" do
275
+ it "includes tmp directories that don't match the current digest" do
276
+ project.obsolete_tmpdirs.should include(old_tmpdir)
277
+ end
278
+ end
279
+
280
+ describe "#files_to_clean" do
281
+ it "includes a project's output files" do
282
+ output_files.each do |file|
283
+ project.files_to_clean.should include(file.fullpath)
284
+ end
285
+ end
286
+
287
+ it "includes a project's temporary directory" do
288
+ project.files_to_clean.should include(digested_tmpdir)
289
+ end
290
+
291
+ it "includes any old digest tmp dirs" do
292
+ project.files_to_clean.should include(old_tmpdir)
293
+ end
294
+ end
295
+ end