directory_watcher 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.2.0 / 2009-04-12
2
+
3
+ * 2 minor enhancements
4
+ - added an option to persist state to a file [Benjamin Thomas]
5
+ - the option to run the directory watcher scanner manually
6
+
1
7
  == 1.1.2 / 2008-12-14
2
8
 
3
9
  * 1 minor bugfix
data/Rakefile CHANGED
@@ -3,7 +3,8 @@ begin
3
3
  require 'bones'
4
4
  Bones.setup
5
5
  rescue LoadError
6
- load 'tasks/setup.rb'
6
+ begin; load 'tasks/setup.rb'
7
+ rescue LoadError; abort '### please install the "bones" gem ###'; end
7
8
  end
8
9
 
9
10
  ensure_in_path 'lib'
@@ -18,6 +19,7 @@ PROJ.email = 'tim.pease@gmail.com'
18
19
  PROJ.url = 'http://codeforpeople.rubyforge.org/directory_watcher'
19
20
  PROJ.version = DirectoryWatcher::VERSION
20
21
  PROJ.rubyforge.name = 'codeforpeople'
22
+ PROJ.ignore_file = '.gitignore'
21
23
 
22
24
  PROJ.rdoc.remote_dir = 'directory_watcher'
23
25
  PROJ.spec.opts << '--color'
@@ -5,6 +5,7 @@
5
5
  #
6
6
 
7
7
  require 'observer'
8
+ require 'yaml'
8
9
 
9
10
  # == Synopsis
10
11
  #
@@ -132,6 +133,40 @@ require 'observer'
132
133
  # gets # when the user hits "enter" the script will terminate
133
134
  # dw.stop
134
135
  #
136
+ # === Persisting State
137
+ #
138
+ # A directory watcher can be configured to persist its current state to a
139
+ # file when it is stopped and to load state from that same file when it
140
+ # starts. Setting the +persist+ value to a filename will enable this
141
+ # feature.
142
+ #
143
+ # require 'directory_watcher'
144
+ #
145
+ # dw = DirectoryWatcher.new '.', :glob => '**/*.rb'
146
+ # dw.interval = 5.0
147
+ # dw.persist = "dw_state.yml"
148
+ # dw.add_observer {|*args| args.each {|event| puts event}}
149
+ #
150
+ # dw.start # loads state from dw_state.yml
151
+ # gets # when the user hits "enter" the script will terminate
152
+ # dw.stop # stores state to dw_state.yml
153
+ #
154
+ # === Running Once
155
+ #
156
+ # Instead of using the built in run loop, the directory watcher can be run
157
+ # one or many times using the +run_once+ method. The state of the directory
158
+ # watcher can be loaded and dumped if so desired.
159
+ #
160
+ # dw = DirectoryWatcher.new '.', :glob => '**/*.rb'
161
+ # dw.persist = "dw_state.yml"
162
+ # dw.add_observer {|*args| args.each {|event| puts event}}
163
+ #
164
+ # dw.load! # loads state from dw_state.yml
165
+ # dw.run_once
166
+ # sleep 5.0
167
+ # dw.run_once
168
+ # dw.persist! # stores state to dw_state.yml
169
+ #
135
170
  # == Contact
136
171
  #
137
172
  # A lot of discussion happens about Ruby in general on the ruby-talk
@@ -150,7 +185,7 @@ require 'observer'
150
185
  #
151
186
  class DirectoryWatcher
152
187
 
153
- VERSION = '1.1.2' # :nodoc:
188
+ VERSION = '1.2.0' # :nodoc:
154
189
 
155
190
  # An +Event+ structure contains the _type_ of the event and the file _path_
156
191
  # to which the event pertains. The type can be one of the following:
@@ -161,11 +196,19 @@ class DirectoryWatcher
161
196
  # :removed => file has been removed from the directory
162
197
  # :stable => file has stabilized since being added or modified
163
198
  #
164
- Event = Struct.new :type, :path
199
+ Event = Struct.new(:type, :path) do
200
+ def to_s( ) "#{type} '#{path}'" end
201
+ end
165
202
 
166
203
  # :stopdoc:
167
- class Event
168
- def to_s( ) "#{type} '#{path}'" end
204
+ # A persistable file stat structure used internally by the directory
205
+ # watcher.
206
+ #
207
+ FileStat = Struct.new(:mtime, :size, :stable) do
208
+ def <=>( other )
209
+ return unless other.is_a? ::DirectoryWatcher::FileStat
210
+ self.mtime <=> other.mtime
211
+ end
169
212
  end
170
213
  # :startdoc:
171
214
 
@@ -186,6 +229,9 @@ class DirectoryWatcher
186
229
  # round of file added events that would normally
187
230
  # be generated (glob pattern must also be
188
231
  # specified otherwise odd things will happen)
232
+ # :persist => file the state will be persisted to and restored
233
+ # from the file when the directory watcher is
234
+ # stopped and started (respectively)
189
235
  #
190
236
  # The default glob pattern will scan all files in the configured directory.
191
237
  # Setting the :stable option to +nil+ will prevent stable events from being
@@ -205,6 +251,7 @@ class DirectoryWatcher
205
251
  self.glob = opts[:glob] || '*'
206
252
  self.interval = opts[:interval] || 30
207
253
  self.stable = opts[:stable] || nil
254
+ self.persist = opts[:persist]
208
255
 
209
256
  @files = (opts[:pre_load] ? scan_files : Hash.new)
210
257
  @events = []
@@ -279,9 +326,6 @@ class DirectoryWatcher
279
326
  end
280
327
  attr_reader :glob
281
328
 
282
- # call-seq:
283
- # interval = 30.0
284
- #
285
329
  # Sets the directory scan interval. The directory will be scanned every
286
330
  # _interval_ seconds for changes to files matching the glob pattern.
287
331
  # Raises +ArgumentError+ if the interval is zero or negative.
@@ -293,9 +337,6 @@ class DirectoryWatcher
293
337
  end
294
338
  attr_reader :interval
295
339
 
296
- # call-seq:
297
- # stable = 2
298
- #
299
340
  # Sets the number of intervals a file must remain unchanged before it is
300
341
  # considered "stable". When this condition is met, a stable event is
301
342
  # generated for the file. If stable is set to +nil+ then stable events
@@ -328,9 +369,35 @@ class DirectoryWatcher
328
369
  end
329
370
  attr_reader :stable
330
371
 
331
- # call-seq:
332
- # running?
372
+ # Sets the name of the file to which the directory watcher state will be
373
+ # persisted when it is stopped. Setting the persist filename to +nil+ will
374
+ # disable this feature.
333
375
  #
376
+ def persist=( filename )
377
+ @persist = filename ? filename.to_s : nil
378
+ end
379
+ attr_reader :persist
380
+
381
+ # Write the current state of the directory watcher to the persist file.
382
+ # This method will do nothing if the directory watcher is running or if
383
+ # the persist file is not configured.
384
+ #
385
+ def persist!
386
+ return if running?
387
+ File.open(@persist, 'w') {|fd| fd.write YAML.dump(@files)} if @persist
388
+ self
389
+ end
390
+
391
+ # Loads the state of the directory watcher from the persist file. This
392
+ # method will do nothing if the directory watcher is running or if the
393
+ # persist file is not configured.
394
+ #
395
+ def load!
396
+ return if running?
397
+ @files = YAML.load_file(@persist) if @persist and test(?f, @persist)
398
+ self
399
+ end
400
+
334
401
  # Returns +true+ if the directory watcher is currently running. Returns
335
402
  # +false+ if this is not the case.
336
403
  #
@@ -338,23 +405,18 @@ class DirectoryWatcher
338
405
  !@thread.nil?
339
406
  end
340
407
 
341
- # call-seq:
342
- # start
343
- #
344
408
  # Start the directory watcher scanning thread. If the directory watcher is
345
409
  # already running, this method will return without taking any action.
346
410
  #
347
411
  def start
348
412
  return if running?
349
413
 
414
+ load!
350
415
  @stop = false
351
- @thread = Thread.new(self) {|dw| dw.__send__ :run}
416
+ @thread = Thread.new(self) {|dw| dw.__send__ :run_loop}
352
417
  self
353
418
  end
354
419
 
355
- # call-seq:
356
- # stop
357
- #
358
420
  # Stop the directory watcher scanning thread. If the directory watcher is
359
421
  # already stopped, this method will return without taking any action.
360
422
  #
@@ -364,8 +426,10 @@ class DirectoryWatcher
364
426
  @stop = true
365
427
  @thread.wakeup if @thread.status == 'sleep'
366
428
  @thread.join
367
- @thread = nil
368
429
  self
430
+ ensure
431
+ @thread = nil
432
+ persist!
369
433
  end
370
434
 
371
435
  # call-seq:
@@ -382,6 +446,7 @@ class DirectoryWatcher
382
446
  was_running = running?
383
447
 
384
448
  stop if was_running
449
+ File.delete(@persist) if @persist and test(?f, @persist)
385
450
  @files = (pre_load ? scan_files : Hash.new)
386
451
  start if was_running
387
452
  end
@@ -402,12 +467,28 @@ class DirectoryWatcher
402
467
  @thread.join limit
403
468
  end
404
469
 
470
+ # Performs exactly one scan of the directory for file changes and notifies
471
+ # the observers.
472
+ #
473
+ # This method wil not persist file changes if that options is configured.
474
+ # The user must call persist! explicitly when using the run_once method.
475
+ #
476
+ def run_once
477
+ files = scan_files
478
+ keys = [files.keys, @files.keys] # current files, previous files
479
+
480
+ find_added(files, *keys)
481
+ find_modified(files, *keys)
482
+ find_removed(*keys)
483
+
484
+ notify_observers
485
+ @files = files # store the current file list for the next iteration
486
+ self
487
+ end
488
+
405
489
 
406
490
  private
407
491
 
408
- # call-seq:
409
- # scan_files
410
- #
411
492
  # Using the configured glob pattern, scan the directory for all files and
412
493
  # return a hash with the filenames as keys and +File::Stat+ objects as the
413
494
  # values. The +File::Stat+ objects contain the mtime and size of the file.
@@ -419,35 +500,24 @@ class DirectoryWatcher
419
500
  begin
420
501
  stat = File.stat fn
421
502
  next unless stat.file?
422
- files[fn] = stat
503
+ files[fn] = DirectoryWatcher::FileStat.new(stat.mtime, stat.size)
423
504
  rescue SystemCallError; end
424
505
  end
425
506
  end
426
507
  files
427
508
  end
428
509
 
429
- # call-seq:
430
- # run
431
- #
432
510
  # Calling this method will enter the directory watcher's run loop. The
433
511
  # calling thread will not return until the +stop+ method is called.
434
512
  #
435
513
  # The run loop is responsible for scanning the directory for file changes,
436
514
  # and then dispatching events to registered listeners.
437
515
  #
438
- def run
516
+ def run_loop
439
517
  until @stop
440
518
  start = Time.now.to_f
441
519
 
442
- files = scan_files
443
- keys = [files.keys, @files.keys] # current files, previous files
444
-
445
- find_added(files, *keys)
446
- find_modified(files, *keys)
447
- find_removed(*keys)
448
-
449
- notify_observers
450
- @files = files # store the current file list for the next iteration
520
+ run_once
451
521
 
452
522
  nap_time = @interval - (Time.now.to_f - start)
453
523
  sleep nap_time if nap_time > 0
@@ -516,9 +586,6 @@ class DirectoryWatcher
516
586
  self
517
587
  end
518
588
 
519
- # call-seq:
520
- # notify_observers
521
- #
522
589
  # If there are queued files events, then invoke the update method of each
523
590
  # registered observer in turn passing the list of file events to each.
524
591
  # The file events array is cleared at the end of this method call.
@@ -534,11 +601,4 @@ class DirectoryWatcher
534
601
 
535
602
  end # class DirectoryWatcher
536
603
 
537
- # :stopdoc:
538
- # We need to add a 'stable' attribute to the File::Stat object
539
- class File::Stat
540
- attr_accessor :stable
541
- end
542
- # :startdoc:
543
-
544
604
  # EOF
data/tasks/gem.rake CHANGED
@@ -37,8 +37,6 @@ class GemPackageTask < Rake::PackageTask
37
37
  local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
38
38
  if !test(?e, local_setup)
39
39
  Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
40
- gem_spec.files = (gem_spec.files +
41
- bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
42
40
  end
43
41
  end
44
42
 
@@ -63,6 +61,10 @@ class GemPackageTask < Rake::PackageTask
63
61
 
64
62
  file package_dir_path => bones_files do
65
63
  mkdir_p package_dir rescue nil
64
+
65
+ gem_spec.files = (gem_spec.files +
66
+ bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
67
+
66
68
  bones_files.each do |fn|
67
69
  base_fn = File.join('tasks', File.basename(fn))
68
70
  f = File.join(package_dir_path, base_fn)
@@ -157,6 +159,13 @@ namespace :gem do
157
159
  puts PROJ.gem._spec.to_ruby
158
160
  end
159
161
 
162
+ desc 'Write the gemspec '
163
+ task :spec => 'gem:prereqs' do
164
+ File.open("#{PROJ.name}.gemspec", 'w') do |f|
165
+ f.write PROJ.gem._spec.to_ruby
166
+ end
167
+ end
168
+
160
169
  desc 'Install the gem'
161
170
  task :install => [:clobber, 'gem:package'] do
162
171
  sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
data/tasks/post_load.rake CHANGED
@@ -2,8 +2,8 @@
2
2
  # This file does not define any rake tasks. It is used to load some project
3
3
  # settings if they are not defined by the user.
4
4
 
5
- PROJ.rdoc.exclude << "^#{Regexp.escape(PROJ.manifest_file)}$"
6
5
  PROJ.exclude << ["^#{Regexp.escape(PROJ.ann.file)}$",
6
+ "^#{Regexp.escape(PROJ.ignore_file)}$",
7
7
  "^#{Regexp.escape(PROJ.rdoc.dir)}/",
8
8
  "^#{Regexp.escape(PROJ.rcov.dir)}/"]
9
9
 
@@ -25,12 +25,7 @@ PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
25
25
 
26
26
  PROJ.summary ||= PROJ.description.split('.').first
27
27
 
28
- PROJ.gem.files ||=
29
- if test(?f, PROJ.manifest_file)
30
- files = File.readlines(PROJ.manifest_file).map {|fn| fn.chomp.strip}
31
- files.delete ''
32
- files
33
- else [] end
28
+ PROJ.gem.files ||= manifest
34
29
 
35
30
  PROJ.gem.executables ||= PROJ.gem.files.find_all {|fn| fn =~ %r/^bin/}
36
31
 
data/tasks/rdoc.rake CHANGED
@@ -19,10 +19,11 @@ namespace :doc do
19
19
  end
20
20
  rd.rdoc_files.push(*files)
21
21
 
22
- title = "#{PROJ.name}-#{PROJ.version} Documentation"
23
-
22
+ name = PROJ.name
24
23
  rf_name = PROJ.rubyforge.name
25
- title = "#{rf_name}'s " + title if rf_name.valid? and rf_name != title
24
+
25
+ title = "#{name}-#{PROJ.version} Documentation"
26
+ title = "#{rf_name}'s " + title if rf_name.valid? and rf_name != name
26
27
 
27
28
  rd.options << "-t #{title}"
28
29
  rd.options.concat(rdoc.opts)
data/tasks/setup.rb CHANGED
@@ -4,8 +4,9 @@ require 'rake'
4
4
  require 'rake/clean'
5
5
  require 'fileutils'
6
6
  require 'ostruct'
7
+ require 'find'
7
8
 
8
- class OpenStruct; undef :gem; end
9
+ class OpenStruct; undef :gem if defined? :gem; end
9
10
 
10
11
  # TODO: make my own openstruct type object that includes descriptions
11
12
  # TODO: use the descriptions to output help on the available bones options
@@ -27,8 +28,8 @@ PROJ = OpenStruct.new(
27
28
  :ruby_opts => %w(-w),
28
29
  :libs => [],
29
30
  :history_file => 'History.txt',
30
- :manifest_file => 'Manifest.txt',
31
31
  :readme_file => 'README.txt',
32
+ :ignore_file => '.bnsignore',
32
33
 
33
34
  # Announce
34
35
  :ann => OpenStruct.new(
@@ -123,9 +124,7 @@ import(*rakefiles)
123
124
  %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
124
125
 
125
126
  # Setup some constants
126
- WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WIN32
127
-
128
- DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
127
+ DEV_NULL = File.exist?('/dev/null') ? '/dev/null' : 'NUL:'
129
128
 
130
129
  def quiet( &block )
131
130
  io = [STDOUT.dup, STDERR.dup]
@@ -138,23 +137,17 @@ ensure
138
137
  $stdout, $stderr = STDOUT, STDERR
139
138
  end
140
139
 
141
- DIFF = if WIN32 then 'diff.exe'
142
- else
143
- if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
144
- else 'diff' end
145
- end unless defined? DIFF
140
+ DIFF = if system("gdiff '#{__FILE__}' '#{__FILE__}' > #{DEV_NULL} 2>&1") then 'gdiff'
141
+ else 'diff' end unless defined? DIFF
146
142
 
147
- SUDO = if WIN32 then ''
148
- else
149
- if quiet {system 'which sudo'} then 'sudo'
150
- else '' end
151
- end
143
+ SUDO = if system("which sudo > #{DEV_NULL} 2>&1") then 'sudo'
144
+ else '' end unless defined? SUDO
152
145
 
153
- RCOV = WIN32 ? 'rcov.bat' : 'rcov'
154
- RDOC = WIN32 ? 'rdoc.bat' : 'rdoc'
155
- GEM = WIN32 ? 'gem.bat' : 'gem'
146
+ RCOV = "#{RUBY} -S rcov"
147
+ RDOC = "#{RUBY} -S rdoc"
148
+ GEM = "#{RUBY} -S gem"
156
149
 
157
- %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
150
+ %w(rcov spec/rake/spectask rubyforge bones facets/ansicode zentest).each do |lib|
158
151
  begin
159
152
  require lib
160
153
  Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
@@ -254,9 +247,29 @@ end
254
247
  # Scans the current working directory and creates a list of files that are
255
248
  # candidates to be in the manifest.
256
249
  #
257
- def manifest_files
250
+ def manifest
258
251
  files = []
259
- exclude = Regexp.new(PROJ.exclude.join('|'))
252
+ exclude = PROJ.exclude.dup
253
+ comment = %r/^\s*#/
254
+
255
+ # process the ignore file and add the items there to the exclude list
256
+ if test(?f, PROJ.ignore_file)
257
+ ary = []
258
+ File.readlines(PROJ.ignore_file).each do |line|
259
+ next if line =~ comment
260
+ line.chomp!
261
+ line.strip!
262
+ next if line.nil? or line.empty?
263
+
264
+ glob = line =~ %r/\*\./ ? File.join('**', line) : line
265
+ Dir.glob(glob).each {|fn| ary << "^#{Regexp.escape(fn)}"}
266
+ end
267
+ exclude.concat ary
268
+ end
269
+
270
+ # generate a regular expression from the exclude list
271
+ exclude = Regexp.new(exclude.join('|'))
272
+
260
273
  Find.find '.' do |path|
261
274
  path.sub! %r/^(\.\/|\/)/o, ''
262
275
  next unless test ?f, path
@@ -0,0 +1,36 @@
1
+ if HAVE_ZENTEST
2
+
3
+ # --------------------------------------------------------------------------
4
+ if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
5
+ require 'autotest'
6
+
7
+ namespace :test do
8
+ task :autotest do
9
+ Autotest.run
10
+ end
11
+ end
12
+
13
+ desc "Run the autotest loop"
14
+ task :autotest => 'test:autotest'
15
+
16
+ end # if test
17
+
18
+ # --------------------------------------------------------------------------
19
+ if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
20
+ require 'autotest/rspec'
21
+
22
+ namespace :spec do
23
+ task :autotest do
24
+ load '.autotest' if test(?f, '.autotest')
25
+ Autotest::Rspec.run
26
+ end
27
+ end
28
+
29
+ desc "Run the autotest loop"
30
+ task :autotest => 'spec:autotest'
31
+
32
+ end # if rspec
33
+
34
+ end # if HAVE_ZENTEST
35
+
36
+ # EOF
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: directory_watcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Pease
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-14 00:00:00 -07:00
12
+ date: 2009-04-12 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 2.1.1
23
+ version: 2.5.0
24
24
  version:
25
25
  description: ""
26
26
  email: tim.pease@gmail.com
@@ -33,7 +33,6 @@ extra_rdoc_files:
33
33
  - README.txt
34
34
  files:
35
35
  - History.txt
36
- - Manifest.txt
37
36
  - README.txt
38
37
  - Rakefile
39
38
  - lib/directory_watcher.rb
@@ -41,7 +40,6 @@ files:
41
40
  - tasks/bones.rake
42
41
  - tasks/gem.rake
43
42
  - tasks/git.rake
44
- - tasks/manifest.rake
45
43
  - tasks/notes.rake
46
44
  - tasks/post_load.rake
47
45
  - tasks/rdoc.rake
@@ -50,6 +48,7 @@ files:
50
48
  - tasks/spec.rake
51
49
  - tasks/svn.rake
52
50
  - tasks/test.rake
51
+ - tasks/zentest.rake
53
52
  has_rdoc: true
54
53
  homepage: http://codeforpeople.rubyforge.org/directory_watcher
55
54
  post_install_message:
data/Manifest.txt DELETED
@@ -1,5 +0,0 @@
1
- History.txt
2
- Manifest.txt
3
- README.txt
4
- Rakefile
5
- lib/directory_watcher.rb
data/tasks/manifest.rake DELETED
@@ -1,48 +0,0 @@
1
-
2
- require 'find'
3
-
4
- namespace :manifest do
5
-
6
- desc 'Verify the manifest'
7
- task :check do
8
- fn = PROJ.manifest_file + '.tmp'
9
- files = manifest_files
10
-
11
- File.open(fn, 'w') {|fp| fp.puts files}
12
- lines = %x(#{DIFF} -du #{PROJ.manifest_file} #{fn}).split("\n")
13
- if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
14
- lines.map! do |line|
15
- case line
16
- when %r/^(-{3}|\+{3})/; nil
17
- when %r/^@/; ANSICode.blue line
18
- when %r/^\+/; ANSICode.green line
19
- when %r/^\-/; ANSICode.red line
20
- else line end
21
- end
22
- end
23
- puts lines.compact
24
- rm fn rescue nil
25
- end
26
-
27
- desc 'Create a new manifest'
28
- task :create do
29
- files = manifest_files
30
- unless test(?f, PROJ.manifest_file)
31
- files << PROJ.manifest_file
32
- files.sort!
33
- end
34
- File.open(PROJ.manifest_file, 'w') {|fp| fp.puts files}
35
- end
36
-
37
- task :assert do
38
- files = manifest_files
39
- manifest = File.read(PROJ.manifest_file).split($/)
40
- raise "ERROR: #{PROJ.manifest_file} is out of date" unless files == manifest
41
- end
42
-
43
- end # namespace :manifest
44
-
45
- desc 'Alias to manifest:check'
46
- task :manifest => 'manifest:check'
47
-
48
- # EOF