~ubuntu-branches/ubuntu/precise/rake/precise

« back to all changes in this revision

Viewing changes to lib/rake.rb

  • Committer: Bazaar Package Importer
  • Author(s): Adam Majer
  • Date: 2008-01-28 11:42:11 UTC
  • mfrom: (1.1.5 upstream) (2.1.2 lenny)
  • Revision ID: james.westby@ubuntu.com-20080128114211-8l1wcx1k9s6oa8s6
Tags: 0.8.1-3
Apply upstream patch (SVN r632) correcting one of the unit
tests. The old unit test depends on the file system ordering
while the new ones just check for consistency. File order is
unimportant. (closes: #462817)

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
#--
4
4
 
5
 
# Copyright (c) 2003, 2004, 2005, 2006 Jim Weirich
 
5
# Copyright (c) 2003, 2004, 2005, 2006, 2007  Jim Weirich
6
6
#
7
7
# Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
# of this software and associated documentation files (the "Software"), to
24
24
#++
25
25
#
26
26
# = Rake -- Ruby Make
27
 
#      
 
27
#
28
28
# This is the main file for the Rake application.  Normally it is referenced
29
29
# as a library via a require statement, but it can be distributed
30
30
# independently as an application.
31
31
 
32
 
RAKEVERSION = '0.7.3'
 
32
RAKEVERSION = '0.8.1'
33
33
 
34
34
require 'rbconfig'
35
 
require 'ftools'
36
35
require 'getoptlong'
37
36
require 'fileutils'
38
37
require 'singleton'
43
42
# Rake extensions to Module.
44
43
#
45
44
class Module
46
 
 
47
45
  # Check for an existing method in the current class before extending.  IF
48
46
  # the method already exists, then a warning is printed and the extension is
49
47
  # not added.  Otherwise the block is yielded and any definitions in the
60
58
  #   end
61
59
  #
62
60
  def rake_extension(method)
63
 
    if instance_methods.include?(method)
 
61
    if instance_methods.include?(method.to_s) || instance_methods.include?(method.to_sym)
64
62
      $stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists"
65
63
    else
66
64
      yield
67
65
    end
68
66
  end
69
 
end
 
67
end # module Module
70
68
 
71
69
 
72
70
######################################################################
103
101
    # front end (left hand side) if +n+ is positive.  Include |+n+|
104
102
    # directories from the back end (right hand side) if +n+ is negative.
105
103
    def pathmap_partial(n)
106
 
      target = File.dirname(self)
107
 
      dirs = target.pathmap_explode
108
 
      if n > 0
109
 
        File.join(dirs[0...n])
110
 
      elsif n < 0
111
 
        partial = dirs[n..-1]
112
 
        if partial.nil? || partial.empty?
113
 
          target
 
104
      dirs = File.dirname(self).pathmap_explode
 
105
      partial_dirs =
 
106
        if n > 0
 
107
          dirs[0...n]
 
108
        elsif n < 0
 
109
          dirs.reverse[0...-n].reverse
114
110
        else
115
 
          File.join(partial)
 
111
          "."
116
112
        end
117
 
      else
118
 
        "."
119
 
      end
 
113
      File.join(partial_dirs)
120
114
    end
121
115
    protected :pathmap_partial
122
 
 
 
116
      
123
117
    # Preform the pathmap replacement operations on the given path. The
124
118
    # patterns take the form 'pat1,rep1;pat2,rep2...'.
125
119
    def pathmap_replace(patterns, &block)
143
137
    # controls the details of the mapping.  The following special patterns are
144
138
    # recognized:
145
139
    #
146
 
    # * <b>%p</b> -- The complete path.   
 
140
    # * <b>%p</b> -- The complete path.
147
141
    # * <b>%f</b> -- The base file name of the path, with its file extension,
148
142
    #   but without any directories.
149
143
    # * <b>%n</b> -- The file name of the path without its file extension.
178
172
    # excluded from both the pattern and replacement text (let's keep parsing
179
173
    # reasonable).
180
174
    #
181
 
    # For example: 
 
175
    # For example:
182
176
    #
183
177
    #    "src/org/onestepback/proj/A.java".pathmap("%{^src,bin}X.class")
184
 
    #  
 
178
    #
185
179
    # returns:
186
180
    #
187
181
    #    "bin/org/onestepback/proj/A.class"
213
207
        when '%x'
214
208
          result << $1 if self =~ /[^\/](\.[^.]+)$/
215
209
        when '%X'
216
 
          if self =~ /^(.+[^\/])(\.[^.]+)$/
 
210
          if self =~ /^(.*[^\/])(\.[^.]+)$/
217
211
            result << $1
218
212
          else
219
213
            result << self
240
234
      result
241
235
    end
242
236
  end
243
 
end
 
237
end # class String
244
238
 
245
239
##############################################################################
246
240
module Rake
283
277
    end
284
278
    alias dup clone
285
279
  end
286
 
end
 
280
 
 
281
  ####################################################################
 
282
  # TaskAguments manage the arguments passed to a task.
 
283
  #
 
284
  class TaskArguments
 
285
    include Enumerable
 
286
 
 
287
    attr_reader :names
 
288
 
 
289
    def initialize(names, values, parent=nil)
 
290
      @names = names
 
291
      @parent = parent
 
292
      @hash = {}
 
293
      names.each_with_index { |name, i|
 
294
        @hash[name.to_sym] = values[i]
 
295
      }
 
296
    end
 
297
 
 
298
    # Create a new argument scope using the prerequisite argument
 
299
    # names.
 
300
    def new_scope(names)
 
301
      values = names.collect { |n| self[n] }
 
302
      self.class.new(names, values, self)
 
303
    end
 
304
 
 
305
    # Find an argument value by name or index.
 
306
    def [](index)
 
307
      lookup(index.to_sym)
 
308
    end
 
309
 
 
310
    def each(&block)
 
311
      @hash.each(&block)
 
312
    end
 
313
 
 
314
    def method_missing(sym, *args, &block)
 
315
      lookup(sym.to_sym)
 
316
    end
 
317
 
 
318
    def to_hash
 
319
      @hash
 
320
    end
 
321
 
 
322
    def to_s
 
323
      @hash.inspect
 
324
    end
 
325
 
 
326
    def inspect
 
327
      to_s
 
328
    end
 
329
    
 
330
    protected
 
331
    
 
332
    def lookup(name)
 
333
      if @hash.has_key?(name)
 
334
        @hash[name]
 
335
      elsif ENV.has_key?(name.to_s)
 
336
        ENV[name.to_s]
 
337
      elsif ENV.has_key?(name.to_s.upcase)
 
338
        ENV[name.to_s.upcase]
 
339
      elsif @parent
 
340
        @parent.lookup(name)
 
341
      end
 
342
    end
 
343
  end
 
344
 
 
345
  ####################################################################
 
346
  # InvocationChain tracks the chain of task invocations to detect
 
347
  # circular dependencies.
 
348
  class InvocationChain
 
349
    def initialize(value, tail)
 
350
      @value = value
 
351
      @tail = tail
 
352
    end
 
353
 
 
354
    def member?(obj)
 
355
      @value == obj || @tail.member?(obj)
 
356
    end
 
357
 
 
358
    def append(value)
 
359
      if member?(value)
 
360
        fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}"
 
361
      end
 
362
      self.class.new(value, self)
 
363
    end
 
364
 
 
365
    def to_s
 
366
      "#{prefix}#{@value}"
 
367
    end
 
368
 
 
369
    def self.append(value, chain)
 
370
      chain.append(value)
 
371
    end
 
372
 
 
373
    private
 
374
 
 
375
    def prefix
 
376
      "#{@tail.to_s} => "
 
377
    end
 
378
 
 
379
    class EmptyInvocationChain
 
380
      def member?(obj)
 
381
        false
 
382
      end
 
383
      def append(value)
 
384
        InvocationChain.new(value, self)
 
385
      end
 
386
      def to_s
 
387
        "TOP"
 
388
      end
 
389
    end
 
390
 
 
391
    EMPTY = EmptyInvocationChain.new
 
392
 
 
393
  end # class InvocationChain
 
394
 
 
395
end # module Rake
287
396
 
288
397
module Rake
289
398
 
302
411
 
303
412
    # Application owning this task.
304
413
    attr_accessor :application
305
 
    
306
 
    # Comment for this task.
307
 
    attr_accessor :comment
308
 
    
 
414
 
 
415
    # Comment for this task.  Restricted to a single line of no more than 50
 
416
    # characters.
 
417
    attr_reader :comment
 
418
 
 
419
    # Full text of the (possibly multi-line) comment.
 
420
    attr_reader :full_comment
 
421
 
309
422
    # Array of nested namespaces names used for task lookup by this task.
310
423
    attr_reader :scope
311
424
 
313
426
    def to_s
314
427
      name
315
428
    end
316
 
    
 
429
 
 
430
    def inspect
 
431
      "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>"
 
432
    end
 
433
 
317
434
    # List of sources for task.
318
435
    attr_writer :sources
319
436
    def sources
324
441
    def source
325
442
      @sources.first if defined?(@sources)
326
443
    end
327
 
    
 
444
 
328
445
    # Create a task named +task_name+ with no actions or prerequisites. Use
329
446
    # +enhance+ to add actions and prerequisites.
330
447
    def initialize(task_name, app)
332
449
      @prerequisites = FileList[]
333
450
      @actions = []
334
451
      @already_invoked = false
 
452
      @full_comment = nil
335
453
      @comment = nil
336
454
      @lock = Mutex.new
337
455
      @application = app
338
456
      @scope = app.current_scope
 
457
      @arg_names = nil
339
458
    end
340
 
    
 
459
 
341
460
    # Enhance a task with prerequisites or actions.  Returns self.
342
461
    def enhance(deps=nil, &block)
343
462
      @prerequisites |= deps if deps
344
463
      @actions << block if block_given?
345
464
      self
346
465
    end
347
 
    
 
466
 
348
467
    # Name of the task, including any namespace qualifiers.
349
468
    def name
350
469
      @name.to_s
351
470
    end
352
 
    
 
471
 
 
472
    # Name of task with argument list description.
 
473
    def name_with_args # :nodoc:
 
474
      if arg_description
 
475
        "#{name}#{arg_description}"
 
476
      else
 
477
        name
 
478
      end
 
479
    end
 
480
 
 
481
    # Argument description (nil if none).
 
482
    def arg_description # :nodoc:
 
483
      @arg_names ? "[#{(arg_names || []).join(',')}]" : nil
 
484
    end
 
485
 
 
486
    # Name of arguments for this task.
 
487
    def arg_names
 
488
      @arg_names || []
 
489
    end
 
490
 
353
491
    # Invoke the task if it is needed.  Prerequites are invoked first.
354
 
    def invoke
 
492
    def invoke(*args)
 
493
      task_args = TaskArguments.new(arg_names, args)
 
494
      invoke_with_call_chain(task_args, InvocationChain::EMPTY)
 
495
    end
 
496
 
 
497
    # Same as invoke, but explicitly pass a call chain to detect
 
498
    # circular dependencies.
 
499
    def invoke_with_call_chain(task_args, invocation_chain)
 
500
      new_chain = InvocationChain.append(self, invocation_chain)
355
501
      @lock.synchronize do
356
502
        if application.options.trace
357
503
          puts "** Invoke #{name} #{format_trace_flags}"
358
504
        end
359
505
        return if @already_invoked
360
506
        @already_invoked = true
361
 
        invoke_prerequisites
362
 
        execute if needed?
 
507
        invoke_prerequisites(task_args, new_chain)
 
508
        execute(task_args) if needed?
363
509
      end
364
510
    end
 
511
    protected :invoke_with_call_chain
365
512
 
366
513
    # Invoke all the prerequisites of a task.
367
 
    def invoke_prerequisites
 
514
    def invoke_prerequisites(task_args, invocation_chain)
368
515
      @prerequisites.each { |n|
369
 
        application[n, @scope].invoke
 
516
        prereq = application[n, @scope]
 
517
        prereq_args = task_args.new_scope(prereq.arg_names)
 
518
        prereq.invoke_with_call_chain(prereq_args, invocation_chain)
370
519
      }
371
520
    end
372
521
 
378
527
      flags.empty? ? "" : "(" + flags.join(", ") + ")"
379
528
    end
380
529
    private :format_trace_flags
381
 
    
 
530
 
382
531
    # Execute the actions associated with this task.
383
 
    def execute
 
532
    def execute(args)
384
533
      if application.options.dryrun
385
534
        puts "** Execute (dry run) #{name}"
386
535
        return
389
538
        puts "** Execute #{name}"
390
539
      end
391
540
      application.enhance_with_matching_rule(name) if @actions.empty?
392
 
      @actions.each { |act| result = act.call(self) }
 
541
      @actions.each do |act|
 
542
        case act.arity
 
543
        when 1
 
544
          act.call(self)
 
545
        else
 
546
          act.call(self, args)
 
547
        end
 
548
      end
393
549
    end
394
 
    
 
550
 
395
551
    # Is this task needed?
396
552
    def needed?
397
553
      true
398
554
    end
399
 
    
 
555
 
400
556
    # Timestamp for this task.  Basic tasks return the current time for their
401
557
    # time stamp.  Other tasks can be more sophisticated.
402
558
    def timestamp
403
559
      @prerequisites.collect { |p| application[p].timestamp }.max || Time.now
404
560
    end
405
 
    
 
561
 
 
562
    # Add a description to the task.  The description can consist of an option
 
563
    # argument list (enclosed brackets) and an optional comment.
 
564
    def add_description(description)
 
565
      return if ! description
 
566
      comment = description.strip
 
567
      add_comment(comment) if comment && ! comment.empty?
 
568
    end
 
569
 
 
570
    # Writing to the comment attribute is the same as adding a description.
 
571
    def comment=(description)
 
572
      add_description(description)
 
573
    end
 
574
 
406
575
    # Add a comment to the task.  If a comment alread exists, separate
407
576
    # the new comment with " / ".
408
577
    def add_comment(comment)
409
 
      return if ! comment
410
 
      if @comment 
411
 
        @comment << " / "
412
 
      else
413
 
        @comment = ''
414
 
      end
415
 
      @comment << comment
416
 
    end
417
 
    
 
578
      if @full_comment
 
579
        @full_comment << " / "
 
580
      else
 
581
        @full_comment = ''
 
582
      end
 
583
      @full_comment << comment
 
584
      if @full_comment =~ /\A([^.]+?\.)( |$)/
 
585
        @comment = $1
 
586
      else
 
587
        @comment = @full_comment
 
588
      end
 
589
    end
 
590
    private :add_comment
 
591
 
 
592
    # Set the names of the arguments for this task. +args+ should be
 
593
    # an array of symbols, one for each argument name.
 
594
    def set_arg_names(args)
 
595
      @arg_names = args.map { |a| a.to_sym }
 
596
    end
 
597
 
418
598
    # Return a string describing the internal state of a task.  Useful for
419
599
    # debugging.
420
600
    def investigation
421
601
      result = "------------------------------\n"
422
 
      result << "Investigating #{name}\n" 
 
602
      result << "Investigating #{name}\n"
423
603
      result << "class: #{self.class}\n"
424
604
      result <<  "task needed: #{needed?}\n"
425
605
      result <<  "timestamp: #{timestamp}\n"
434
614
      result << "................................\n\n"
435
615
      return result
436
616
    end
437
 
    
 
617
 
438
618
    # ----------------------------------------------------------------
439
619
    # Rake Module Methods
440
 
    #    
 
620
    #
441
621
    class << self
442
 
      
 
622
 
443
623
      # Clear the task list.  This cause rake to immediately forget all the
444
624
      # tasks that have been assigned.  (Normally used in the unit tests.)
445
625
      def clear
446
626
        Rake.application.clear
447
627
      end
448
 
      
 
628
 
449
629
      # List of all defined tasks.
450
630
      def tasks
451
631
        Rake.application.tasks
452
632
      end
453
 
      
 
633
 
454
634
      # Return a task with the given name.  If the task is not currently
455
635
      # known, try to synthesize one from the defined rules.  If no rules are
456
636
      # found, but an existing file matches the task name, assume it is a file
458
638
      def [](task_name)
459
639
        Rake.application[task_name]
460
640
      end
461
 
      
 
641
 
462
642
      # TRUE if the task name is already defined.
463
643
      def task_defined?(task_name)
464
644
        Rake.application.lookup(task_name) != nil
465
645
      end
466
 
      
 
646
 
467
647
      # Define a task given +args+ and an option block.  If a rule with the
468
648
      # given name already exists, the prerequisites and actions are added to
469
649
      # the existing task.  Returns the defined task.
470
 
      def define_task(args, &block)
471
 
        Rake.application.define_task(self, args, &block)
 
650
      def define_task(*args, &block)
 
651
        Rake.application.define_task(self, *args, &block)
472
652
      end
473
 
      
474
 
      # Define a rule for synthesizing tasks.  
475
 
      def create_rule(args, &block)
476
 
        Rake.application.create_rule(args, &block)
 
653
 
 
654
      # Define a rule for synthesizing tasks.
 
655
      def create_rule(*args, &block)
 
656
        Rake.application.create_rule(*args, &block)
477
657
      end
478
658
 
479
659
      # Apply the scope to the task name according to the rules for
483
663
        (scope + [task_name]).join(':')
484
664
      end
485
665
 
486
 
    end
487
 
  end
488
 
  
489
 
  
 
666
    end # class << Rake::Task
 
667
  end # class Rake::Task
 
668
 
 
669
 
490
670
  # #########################################################################
491
671
  # A FileTask is a task that includes time based dependencies.  If any of a
492
672
  # FileTask's prerequisites have a timestamp that is later than the file
494
674
  # supplied actions).
495
675
  #
496
676
  class FileTask < Task
497
 
    
 
677
 
498
678
    # Is this file task needed?  Yes if it doesn't exist, or if its time stamp
499
679
    # is out of date.
500
680
    def needed?
502
682
      return true if out_of_date?(timestamp)
503
683
      false
504
684
    end
505
 
    
 
685
 
506
686
    # Time stamp for file task.
507
687
    def timestamp
508
688
      if File.exist?(name)
529
709
        task_name
530
710
      end
531
711
    end
532
 
  end
533
 
  
 
712
  end # class Rake::FileTask
 
713
 
534
714
  # #########################################################################
535
715
  # A FileCreationTask is a file task that when used as a dependency will be
536
716
  # needed if and only if the file has not been created.  Once created, it is
542
722
    def needed?
543
723
      ! File.exist?(name)
544
724
    end
545
 
    
 
725
 
546
726
    # Time stamp for file creation task.  This time stamp is earlier
547
727
    # than any other time stamp.
548
728
    def timestamp
555
735
  # parallel using Ruby threads.
556
736
  #
557
737
  class MultiTask < Task
558
 
    def invoke_prerequisites
 
738
    def invoke_prerequisites(args, invocation_chain)
559
739
      threads = @prerequisites.collect { |p|
560
 
        Thread.new(p) { |r| application[r].invoke }
 
740
        Thread.new(p) { |r| application[r].invoke_with_call_chain(args, invocation_chain) }
561
741
      }
562
742
      threads.each { |t| t.join }
563
743
    end
564
744
  end
565
 
end
 
745
end # module Rake
566
746
 
567
747
# ###########################################################################
568
748
# Task Definition Functions ...
574
754
#     rm_rf "html"
575
755
#   end
576
756
#
577
 
def task(args, &block)
578
 
  Rake::Task.define_task(args, &block)
 
757
def task(*args, &block)
 
758
  Rake::Task.define_task(*args, &block)
579
759
end
580
760
 
581
761
 
648
828
#    sh %{cc -o #{t.name} #{t.source}}
649
829
#  end
650
830
#
651
 
def rule(args, &block)
652
 
  Rake::Task.create_rule(args, &block)
 
831
def rule(*args, &block)
 
832
  Rake::Task.create_rule(*args, &block)
653
833
end
654
834
 
655
835
# Describe the next rake task.
660
840
#     runtests
661
841
#   end
662
842
#
663
 
def desc(comment)
664
 
  Rake.application.last_comment = comment
 
843
def desc(description)
 
844
  Rake.application.last_description = description
665
845
end
666
846
 
667
847
# Import the partial Rakefiles +fn+.  Imported files are loaded _after_ the
713
893
    options = (Hash === cmd.last) ? cmd.pop : {}
714
894
    unless block_given?
715
895
      show_command = cmd.join(" ")
716
 
      show_command = show_command[0,42] + "..." 
717
 
        # TODO code application logic heref show_command.length > 45
 
896
      show_command = show_command[0,42] + "..."
 
897
      # TODO code application logic heref show_command.length > 45
718
898
      block = lambda { |ok, status|
719
899
        ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
720
900
      }
737
917
    if args.length > 1 then
738
918
      sh(*([RUBY] + args + [options]), &block)
739
919
    else
740
 
      sh("#{RUBY} #{args}", options, &block)
 
920
      sh("#{RUBY} #{args.first}", options, &block)
741
921
    end
742
922
  end
743
 
  
 
923
 
744
924
  LN_SUPPORTED = [true]
745
925
 
746
926
  #  Attempt to do a normal file link, but fall back to a copy if the link
783
963
  end
784
964
  RakeFileUtils.verbose_flag = true
785
965
  RakeFileUtils.nowrite_flag = false
786
 
  
 
966
 
787
967
  $fileutils_verbose = true
788
968
  $fileutils_nowrite = false
789
 
  
 
969
 
790
970
  FileUtils::OPT_TABLE.each do |name, opts|
791
971
    default_options = []
792
972
    if opts.include?('verbose')
807
987
    EOS
808
988
  end
809
989
 
810
 
  # Get/set the verbose flag controlling output from the FileUtils utilities. 
 
990
  # Get/set the verbose flag controlling output from the FileUtils utilities.
811
991
  # If verbose is true, then the utility method is echoed to standard output.
812
992
  #
813
993
  # Examples:
828
1008
    RakeFileUtils.verbose_flag
829
1009
  end
830
1010
 
831
 
  # Get/set the nowrite flag controlling output from the FileUtils utilities. 
 
1011
  # Get/set the nowrite flag controlling output from the FileUtils utilities.
832
1012
  # If verbose is true, then the utility method is echoed to standard output.
833
1013
  #
834
1014
  # Examples:
852
1032
  # Use this function to prevent protentially destructive ruby code from
853
1033
  # running when the :nowrite flag is set.
854
1034
  #
855
 
  # Example: 
 
1035
  # Example:
856
1036
  #
857
1037
  #   when_writing("Building Project") do
858
1038
  #     project.build
943
1123
  # FileList/Array is requested, the pending patterns are resolved into a real
944
1124
  # list of file names.
945
1125
  #
946
 
  class FileList 
 
1126
  class FileList
947
1127
 
948
1128
    include Cloneable
949
1129
 
965
1145
 
966
1146
    # List of array methods (that are not in +Object+) that need to be
967
1147
    # delegated.
968
 
    ARRAY_METHODS = Array.instance_methods - Object.instance_methods
 
1148
    ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
969
1149
 
970
1150
    # List of additional methods that must be delegated.
971
1151
    MUST_DEFINE = %w[to_a inspect]
981
1161
      compact flatten uniq values_at
982
1162
      + - & |
983
1163
    ]
984
 
    
 
1164
 
985
1165
    DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
986
 
    
 
1166
 
987
1167
    # Now do the delegation.
988
1168
    DELEGATING_METHODS.each_with_index do |sym, i|
989
1169
      if SPECIAL_RETURN.include?(sym)
990
1170
        ln = __LINE__+1
991
1171
        class_eval %{
992
1172
          def #{sym}(*args, &block)
993
 
            resolve if @pending
 
1173
            resolve
994
1174
            result = @items.send(:#{sym}, *args, &block)
995
1175
            FileList.new.import(result)
996
1176
          end
999
1179
        ln = __LINE__+1
1000
1180
        class_eval %{
1001
1181
          def #{sym}(*args, &block)
1002
 
            resolve if @pending
 
1182
            resolve
1003
1183
            result = @items.send(:#{sym}, *args, &block)
1004
1184
            result.object_id == @items.object_id ? self : result
1005
1185
          end
1048
1228
      @pending = true
1049
1229
      self
1050
1230
    end
1051
 
    alias :add :include 
1052
 
    
 
1231
    alias :add :include
 
1232
 
1053
1233
    # Register a list of file name patterns that should be excluded from the
1054
1234
    # list.  Patterns may be regular expressions, glob patterns or regular
1055
1235
    # strings.  In addition, a block given to exclude will remove entries that
1072
1252
    #
1073
1253
    def exclude(*patterns, &block)
1074
1254
      patterns.each do |pat|
1075
 
        @exclude_patterns << pat 
 
1255
        @exclude_patterns << pat
1076
1256
      end
1077
1257
      if block_given?
1078
1258
        @exclude_procs << block
1079
 
      end        
 
1259
      end
1080
1260
      resolve_exclude if ! @pending
1081
1261
      self
1082
1262
    end
1083
1263
 
1084
 
    
 
1264
 
1085
1265
    # Clear all the exclude patterns so that we exclude nothing.
1086
1266
    def clear_exclude
1087
1267
      @exclude_patterns = []
1105
1285
    def to_ary
1106
1286
      to_a
1107
1287
    end
1108
 
    
 
1288
 
1109
1289
    # Lie about our class.
1110
1290
    def is_a?(klass)
1111
1291
      klass == Array || super(klass)
1240
1420
                yield fn, count, line
1241
1421
              else
1242
1422
                puts "#{fn}:#{count}:#{line}"
1243
 
              end               
 
1423
              end
1244
1424
            end
1245
1425
          end
1246
1426
        end
1250
1430
    # Return a new file list that only contains file names from the current
1251
1431
    # file list that exist on the file system.
1252
1432
    def existing
1253
 
      select { |fn| File.exists?(fn) }
 
1433
      select { |fn| File.exist?(fn) }
1254
1434
    end
1255
 
    
 
1435
 
1256
1436
    # Modify the current file list so that it contains only file name that
1257
1437
    # exist on the file system.
1258
1438
    def existing!
1259
1439
      resolve
1260
 
      @items = @items.select { |fn| File.exists?(fn) }
 
1440
      @items = @items.select { |fn| File.exist?(fn) }
1261
1441
      self
1262
1442
    end
1263
1443
 
1271
1451
        FileList.new.import(result[1]),
1272
1452
      ]
1273
1453
    end
1274
 
    
 
1454
 
1275
1455
    # Convert a FileList to a string by joining all elements with a space.
1276
1456
    def to_s
1277
 
      resolve if @pending
 
1457
      resolve
1278
1458
      self.join(' ')
1279
1459
    end
1280
1460
 
1301
1481
    DEFAULT_IGNORE_PROCS = [
1302
1482
      proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
1303
1483
    ]
1304
 
    @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
 
1484
#    @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
1305
1485
 
1306
1486
    def import(array)
1307
1487
      @items = array
1315
1495
      def [](*args)
1316
1496
        new(*args)
1317
1497
      end
1318
 
 
1319
 
      # Set the ignore patterns back to the default value.  The default
1320
 
      # patterns will ignore files 
1321
 
      # * containing "CVS" in the file path
1322
 
      # * containing ".svn" in the file path
1323
 
      # * ending with ".bak"
1324
 
      # * ending with "~"
1325
 
      # * named "core"
1326
 
      #
1327
 
      # Note that file names beginning with "." are automatically ignored by
1328
 
      # Ruby's glob patterns and are not specifically listed in the ignore
1329
 
      # patterns.
1330
 
      def select_default_ignore_patterns
1331
 
        @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
1332
 
      end
1333
 
 
1334
 
      # Clear the ignore patterns.  
1335
 
      def clear_ignore_patterns
1336
 
        @exclude_patterns = [ /^$/ ]
1337
 
      end
1338
1498
    end
1339
1499
  end # FileList
1340
1500
end
1352
1512
      end
1353
1513
    end
1354
1514
  end
1355
 
end
 
1515
end # module Rake
1356
1516
 
1357
1517
# Alias FileList to be available at the top level.
1358
1518
FileList = Rake::FileList
1382
1542
  end
1383
1543
 
1384
1544
  EARLY = EarlyTime.instance
1385
 
end
 
1545
end # module Rake
1386
1546
 
1387
1547
# ###########################################################################
1388
1548
# Extensions to time to allow comparisons with an early time class.
1395
1555
    else
1396
1556
      rake_original_time_compare(other)
1397
1557
    end
1398
 
  end     
1399
 
end
 
1558
  end
 
1559
end # class Time
1400
1560
 
1401
1561
module Rake
1402
1562
 
1412
1572
      @task_manager = task_manager
1413
1573
      @scope = scope_list.dup
1414
1574
    end
1415
 
    
 
1575
 
1416
1576
    # Lookup a task named +name+ in the namespace.
1417
1577
    def [](name)
1418
1578
      @task_manager.lookup(name, @scope)
1422
1582
    def tasks
1423
1583
      @task_manager.tasks
1424
1584
    end
1425
 
  end
 
1585
  end # NameSpace
1426
1586
 
1427
1587
 
1428
1588
  ####################################################################
1429
 
  # The TaskManager module is a mixin for managing tasks.  
 
1589
  # The TaskManager module is a mixin for managing tasks.
1430
1590
  module TaskManager
1431
1591
    # Track the last comment made in the Rakefile.
1432
 
    attr_accessor :last_comment
 
1592
    attr_accessor :last_description
 
1593
    alias :last_comment :last_description    # Backwards compatibility
1433
1594
 
1434
1595
    def initialize
1435
1596
      super
1436
1597
      @tasks = Hash.new
1437
1598
      @rules = Array.new
1438
1599
      @scope = Array.new
1439
 
      @last_comment = nil
 
1600
      @last_description = nil
1440
1601
    end
1441
1602
 
1442
 
    def create_rule(args, &block)
1443
 
      pattern, deps = resolve_args(args)
 
1603
    def create_rule(*args, &block)
 
1604
      pattern, arg_names, deps = resolve_args(args)
1444
1605
      pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
1445
1606
      @rules << [pattern, deps, block]
1446
1607
    end
1447
1608
 
1448
 
    def define_task(task_class, args, &block)
1449
 
      task_name, deps = resolve_args(args)
 
1609
    def define_task(task_class, *args, &block)
 
1610
      task_name, arg_names, deps = resolve_args(args)
1450
1611
      task_name = task_class.scope_name(@scope, task_name)
1451
1612
      deps = [deps] unless deps.respond_to?(:to_ary)
1452
1613
      deps = deps.collect {|d| d.to_s }
1453
1614
      task = intern(task_class, task_name)
1454
 
      task.add_comment(@last_comment)
1455
 
      @last_comment = nil
 
1615
      task.set_arg_names(arg_names) unless arg_names.empty?
 
1616
      task.add_description(@last_description)
 
1617
      @last_description = nil
1456
1618
      task.enhance(deps, &block)
1457
1619
      task
1458
1620
    end
1463
1625
      @tasks[task_name.to_s] ||= task_class.new(task_name, self)
1464
1626
    end
1465
1627
 
1466
 
    # Find a matching task for +task_name+.  
 
1628
    # Find a matching task for +task_name+.
1467
1629
    def [](task_name, scopes=nil)
1468
1630
      task_name = task_name.to_s
1469
1631
      self.lookup(task_name, scopes) or
1476
1638
      return nil unless File.exist?(task_name)
1477
1639
      define_task(Rake::FileTask, task_name)
1478
1640
    end
1479
 
    
1480
 
    # Resolve the arguments for a task/rule.
 
1641
 
 
1642
    # Resolve the arguments for a task/rule.  Returns a triplet of
 
1643
    # [task_name, arg_name_list, prerequisites].
1481
1644
    def resolve_args(args)
1482
 
      case args
1483
 
      when Hash
1484
 
        fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1
1485
 
        fail "No Task Name Given" if args.size < 1
1486
 
        task_name = args.keys[0]
1487
 
        deps = args[task_name]
1488
 
        deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps)
1489
 
      else
1490
 
        task_name = args
1491
 
        deps = []
1492
 
      end
1493
 
      [task_name, deps]
 
1645
      task_name = args.shift
 
1646
      arg_names = args #.map { |a| a.to_sym }
 
1647
      needs = []
 
1648
      if task_name.is_a?(Hash)
 
1649
        hash = task_name
 
1650
        task_name = hash.keys[0]
 
1651
        needs = hash[task_name]
 
1652
      end
 
1653
      if arg_names.last.is_a?(Hash)
 
1654
        hash = arg_names.pop
 
1655
        needs = hash[:needs]
 
1656
        fail "Unrecognized keys in task hash: #{hash.keys.inspect}" if hash.size > 1
 
1657
      end
 
1658
      needs = [needs] unless needs.respond_to?(:to_ary)
 
1659
      [task_name, arg_names, needs]
1494
1660
    end
1495
 
    
 
1661
 
1496
1662
    # If a rule can be found that matches the task name, enhance the
1497
1663
    # task with the prerequisites and actions from the rule.  Set the
1498
1664
    # source attribute of the task appropriately for the rule.  Return
1511
1677
      ex.add_target(task_name)
1512
1678
      fail ex
1513
1679
    end
1514
 
    
 
1680
 
1515
1681
    # List of all defined tasks in this application.
1516
1682
    def tasks
1517
1683
      @tasks.values.sort_by { |t| t.name }
1543
1709
      lookup_in_scope(task_name, scopes)
1544
1710
    end
1545
1711
 
1546
 
    # Lookup the task name 
 
1712
    # Lookup the task name
1547
1713
    def lookup_in_scope(name, scope)
1548
1714
      n = scope.size
1549
1715
      while n >= 0
1599
1765
      task.sources = prereqs
1600
1766
      task
1601
1767
    end
1602
 
    
 
1768
 
1603
1769
    # Make a list of sources from the list of file name extensions /
1604
1770
    # translation procs.
1605
1771
    def make_sources(task_name, extensions)
1606
1772
      extensions.collect { |ext|
1607
1773
        case ext
1608
 
        when /^%/
 
1774
        when /%/
1609
1775
          task_name.pathmap(ext)
1610
1776
        when %r{/}
1611
1777
          ext
1614
1780
        when String
1615
1781
          ext
1616
1782
        when Proc
1617
 
          ext.call(task_name)
 
1783
          if ext.arity == 1
 
1784
            ext.call(task_name)
 
1785
          else
 
1786
            ext.call
 
1787
          end
1618
1788
        else
1619
1789
          fail "Don't know how to handle rule dependent: #{ext.inspect}"
1620
1790
        end
1621
1791
      }.flatten
1622
1792
    end
1623
 
    
1624
 
  end
 
1793
 
 
1794
  end # TaskManager
1625
1795
 
1626
1796
  ######################################################################
1627
1797
  # Rake main application object.  When invoking +rake+ from the
1635
1805
 
1636
1806
    # The original directory where rake was invoked.
1637
1807
    attr_reader :original_dir
1638
 
    
 
1808
 
1639
1809
    # Name of the actual rakefile used.
1640
1810
    attr_reader :rakefile
1641
 
    
 
1811
 
1642
1812
    # List of the top level task names (task names from the command line).
1643
1813
    attr_reader :top_level_tasks
1644
1814
 
1645
1815
    DEFAULT_RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze
1646
 
    
 
1816
 
1647
1817
    OPTIONS = [     # :nodoc:
1648
 
      ['--dry-run',  '-n', GetoptLong::NO_ARGUMENT,
1649
 
        "Do a dry run without executing actions."],
1650
 
      ['--help',     '-H', GetoptLong::NO_ARGUMENT,
 
1818
      ['--classic-namespace', '-C', GetoptLong::NO_ARGUMENT,
 
1819
        "Put Task and FileTask in the top level namespace"],
 
1820
      ['--describe',  '-D', GetoptLong::OPTIONAL_ARGUMENT,
 
1821
        "Describe the tasks (matching optional PATTERN), then exit."],
 
1822
      ['--rakefile', '-f', GetoptLong::OPTIONAL_ARGUMENT,
 
1823
        "Use FILE as the rakefile."],
 
1824
      ['--help',     '-h', '-H', GetoptLong::NO_ARGUMENT,
1651
1825
        "Display this help message."],
1652
1826
      ['--libdir',   '-I', GetoptLong::REQUIRED_ARGUMENT,
1653
1827
        "Include LIBDIR in the search path for required modules."],
1654
 
      ['--rakelibdir', '-R', GetoptLong::REQUIRED_ARGUMENT,
1655
 
        "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')"],
 
1828
      ['--dry-run',  '-n', GetoptLong::NO_ARGUMENT,
 
1829
        "Do a dry run without executing actions."],
1656
1830
      ['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
1657
1831
        "Do not search parent directories for the Rakefile."],
1658
1832
      ['--prereqs',  '-P', GetoptLong::NO_ARGUMENT,
1659
1833
        "Display the tasks and dependencies, then exit."],
1660
1834
      ['--quiet',    '-q', GetoptLong::NO_ARGUMENT,
1661
1835
        "Do not log messages to standard output."],
1662
 
      ['--rakefile', '-f', GetoptLong::OPTIONAL_ARGUMENT,
1663
 
        "Use FILE as the rakefile."],
1664
1836
      ['--require',  '-r', GetoptLong::REQUIRED_ARGUMENT,
1665
1837
        "Require MODULE before executing rakefile."],
 
1838
      ['--rakelibdir', '-R', GetoptLong::REQUIRED_ARGUMENT,
 
1839
        "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')"],
1666
1840
      ['--silent',   '-s', GetoptLong::NO_ARGUMENT,
1667
1841
        "Like --quiet, but also suppresses the 'in directory' announcement."],
1668
1842
      ['--tasks',    '-T', GetoptLong::OPTIONAL_ARGUMENT,
1669
1843
        "Display the tasks (matching optional PATTERN) with descriptions, then exit."],
1670
1844
      ['--trace',    '-t', GetoptLong::NO_ARGUMENT,
1671
1845
        "Turn on invoke/execute tracing, enable full backtrace."],
1672
 
      ['--usage',    '-h', GetoptLong::NO_ARGUMENT,
1673
 
        "Display usage."],
1674
1846
      ['--verbose',  '-v', GetoptLong::NO_ARGUMENT,
1675
1847
        "Log message to standard output (default)."],
1676
1848
      ['--version',  '-V', GetoptLong::NO_ARGUMENT,
1677
1849
        "Display the program version."],
1678
 
      ['--classic-namespace', '-C', GetoptLong::NO_ARGUMENT,
1679
 
        "Put Task and FileTask in the top level namespace"],
1680
1850
    ]
1681
 
    
 
1851
 
1682
1852
    # Initialize a Rake::Application object.
1683
1853
    def initialize
1684
1854
      super
1701
1871
    # * Define the tasks (+load_rakefile+).
1702
1872
    # * Run the top level tasks (+run_tasks+).
1703
1873
    #
1704
 
    # If you wish to build a custom rake command, you should call +init+ on your 
 
1874
    # If you wish to build a custom rake command, you should call +init+ on your
1705
1875
    # application.  The define any tasks.  Finally, call +top_level+ to run your top
1706
1876
    # level tasks.
1707
1877
    def run
1726
1896
      standard_exception_handling do
1727
1897
        raw_load_rakefile
1728
1898
      end
1729
 
    end 
 
1899
    end
1730
1900
 
1731
1901
    # Run the top level tasks of a Rake application.
1732
1902
    def top_level
1736
1906
        elsif options.show_prereqs
1737
1907
          display_prerequisites
1738
1908
        else
1739
 
          top_level_tasks.each { |task_name| self[task_name].invoke }
 
1909
          top_level_tasks.each { |task_name| invoke_task(task_name) }
1740
1910
        end
1741
1911
      end
1742
1912
    end
1747
1917
      ext = ".#{ext}" unless ext =~ /^\./
1748
1918
      @loaders[ext] = loader
1749
1919
    end
1750
 
    
 
1920
 
1751
1921
    # Application options from the command line
1752
1922
    def options
1753
1923
      @options ||= OpenStruct.new
1755
1925
 
1756
1926
    # private ----------------------------------------------------------------
1757
1927
 
 
1928
    def invoke_task(task_string)
 
1929
      name, args = parse_task_string(task_string)
 
1930
      t = self[name]
 
1931
      t.invoke(*args)
 
1932
    end
 
1933
 
 
1934
    def parse_task_string(string)
 
1935
      if string =~ /^([^\[]+)(\[(.*)\])$/
 
1936
        name = $1
 
1937
        args = $3.split(/\s*,\s*/)
 
1938
      else
 
1939
        name = string
 
1940
        args = []
 
1941
      end
 
1942
      [name, args]
 
1943
    end
 
1944
 
1758
1945
    # Provide standard execption handling for the given block.
1759
1946
    def standard_exception_handling
1760
1947
      begin
1761
1948
        yield
 
1949
      rescue SystemExit => ex
 
1950
        # Exit silently with current status
 
1951
        exit(ex.status)
1762
1952
      rescue SystemExit, GetoptLong::InvalidOption => ex
1763
1953
        # Exit silently
1764
1954
        exit(1)
1773
1963
          $stderr.puts "(See full trace by running task with --trace)"
1774
1964
        end
1775
1965
        exit(1)
1776
 
      end    
 
1966
      end
1777
1967
    end
1778
 
        
 
1968
 
1779
1969
    # True if one of the files in RAKEFILES is in the current directory.
1780
1970
    # If a match is found, it is copied into @rakefile.
1781
1971
    def have_rakefile
1787
1977
      end
1788
1978
      return false
1789
1979
    end
1790
 
    
1791
 
    # Display the program usage line.
1792
 
    def usage
1793
 
      puts "rake [-f rakefile] {options} targets..."
1794
 
    end
1795
 
    
 
1980
 
1796
1981
    # Display the rake command line help.
1797
1982
    def help
1798
 
      usage
 
1983
      puts "rake [-f rakefile] {options} targets..."
1799
1984
      puts
1800
1985
      puts "Options are ..."
1801
1986
      puts
1809
1994
        printf "      %s\n", desc
1810
1995
      end
1811
1996
    end
1812
 
    
 
1997
 
1813
1998
    # Display the tasks and dependencies.
1814
1999
    def display_tasks_and_comments
1815
2000
      displayable_tasks = tasks.select { |t|
1816
2001
        t.comment && t.name =~ options.show_task_pattern
1817
2002
      }
1818
 
      width = displayable_tasks.collect { |t| t.name.length }.max
1819
 
      displayable_tasks.each do |t|
1820
 
        printf "#{name} %-#{width}s  # %s\n", t.name, t.comment
1821
 
      end
1822
 
    end
1823
 
    
 
2003
      if options.full_description
 
2004
        displayable_tasks.each do |t|
 
2005
          puts "rake #{t.name_with_args}"
 
2006
          t.full_comment.split("\n").each do |line|
 
2007
            puts "    #{line}"
 
2008
          end
 
2009
          puts
 
2010
        end
 
2011
      else
 
2012
        width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
 
2013
        max_column = 80 - name.size - width - 7
 
2014
        displayable_tasks.each do |t|
 
2015
          printf "#{name} %-#{width}s  # %s\n",
 
2016
            t.name_with_args, truncate(t.comment, max_column)
 
2017
        end
 
2018
      end
 
2019
    end
 
2020
 
 
2021
    def truncate(string, width)
 
2022
      if string.length <= width
 
2023
        string
 
2024
      else
 
2025
        string[0, width-3] + "..."
 
2026
      end
 
2027
    end
 
2028
 
1824
2029
    # Display the tasks and prerequisites
1825
2030
    def display_prerequisites
1826
2031
      tasks.each do |t|
1828
2033
        t.prerequisites.each { |pre| puts "    #{pre}" }
1829
2034
      end
1830
2035
    end
1831
 
    
 
2036
 
1832
2037
    # Return a list of the command line options supported by the
1833
2038
    # program.
1834
2039
    def command_line_options
1835
2040
      OPTIONS.collect { |lst| lst[0..-2] }
1836
2041
    end
1837
 
    
 
2042
 
1838
2043
    # Do the option defined by +opt+ and +value+.
1839
2044
    def do_option(opt, value)
1840
2045
      case opt
 
2046
      when '--describe'
 
2047
        options.show_tasks = true
 
2048
        options.show_task_pattern = Regexp.new(value || '.')
 
2049
        options.full_description = true
1841
2050
      when '--dry-run'
1842
2051
        verbose(true)
1843
2052
        nowrite(true)
1875
2084
      when '--tasks'
1876
2085
        options.show_tasks = true
1877
2086
        options.show_task_pattern = Regexp.new(value || '.')
 
2087
        options.full_description = false
1878
2088
      when '--trace'
1879
2089
        options.trace = true
1880
2090
        verbose(true)
1881
 
      when '--usage'
1882
 
        usage
1883
 
        exit
1884
2091
      when '--verbose'
1885
2092
        verbose(true)
1886
2093
      when '--version'
1891
2098
        options.classic_namespace = true
1892
2099
      end
1893
2100
    end
1894
 
    
 
2101
 
1895
2102
    # Read and handle the command line options.
1896
2103
    def handle_options
1897
 
      options.rakelib = 'rakelib'
 
2104
      options.rakelib = ['rakelib']
1898
2105
 
1899
2106
      opts = GetoptLong.new(*command_line_options)
1900
2107
      opts.each { |opt, value| do_option(opt, value) }
1908
2115
        $dryrun = options.dryrun
1909
2116
        $silent = options.silent
1910
2117
      end
 
2118
    rescue NoMethodError => ex
 
2119
      raise GetoptLong::InvalidOption, "While parsing options, error = #{ex.class}:#{ex.message}"
1911
2120
    end
1912
 
    
 
2121
 
1913
2122
    # Similar to the regular Ruby +require+ command, but will check
1914
2123
    # for .rake files in addition to .rb files.
1915
2124
    def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
1943
2152
      end
1944
2153
      load_imports
1945
2154
    end
1946
 
    
 
2155
 
1947
2156
    # Collect the list of tasks on the command line.  If no tasks are
1948
2157
    # given, return a list containing only the default task.
1949
2158
    # Environmental assignments are processed at this time as well.
1958
2167
      end
1959
2168
      @top_level_tasks.push("default") if @top_level_tasks.size == 0
1960
2169
    end
1961
 
    
 
2170
 
1962
2171
    # Add a file to the list of files to be imported.
1963
2172
    def add_import(fn)
1964
2173
      @pending_imports << fn
1965
2174
    end
1966
 
    
 
2175
 
1967
2176
    # Load the pending list of imported files.
1968
2177
    def load_imports
1969
2178
      while fn = @pending_imports.shift
1977
2186
        @imported << fn
1978
2187
      end
1979
2188
    end
1980
 
    
 
2189
 
1981
2190
    # Warn about deprecated use of top level constant names.
1982
2191
    def const_warning(const_name)
1983
2192
      @const_warning ||= false
2004
2213
class Module
2005
2214
  # Rename the original handler to make it available.
2006
2215
  alias :rake_original_const_missing :const_missing
2007
 
  
 
2216
 
2008
2217
  # Check for deprecated uses of top level (i.e. in Object) uses of
2009
2218
  # Rake class names.  If someone tries to reference the constant
2010
2219
  # name, display a warning and return the proper object.  Using the