From 6361928083d01906ab9d8782b6533b4ed7c834a0 Mon Sep 17 00:00:00 2001 From: hsbt Date: Tue, 15 Jul 2014 03:07:37 +0000 Subject: * lib/rake.rb, lib/rake/*.rb: Upgrade to rake-10.3.2 [fix GH-668] * test/rake/*.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46818 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 + lib/rake.rb | 7 +- lib/rake/alt_system.rb | 8 +- lib/rake/application.rb | 175 ++++++++++++++++--------- lib/rake/backtrace.rb | 5 +- lib/rake/clean.rb | 23 +++- lib/rake/cloneable.rb | 6 +- lib/rake/contrib/ftptools.rb | 8 +- lib/rake/contrib/publisher.rb | 16 ++- lib/rake/contrib/rubyforgepublisher.rb | 4 +- lib/rake/contrib/sshpublisher.rb | 23 +++- lib/rake/contrib/sys.rb | 2 + lib/rake/cpu_counter.rb | 109 ++++++++++++++++ lib/rake/default_loader.rb | 4 + lib/rake/dsl_definition.rb | 77 ++++++++--- lib/rake/early_time.rb | 5 +- lib/rake/ext/core.rb | 7 +- lib/rake/ext/module.rb | 1 + lib/rake/ext/string.rb | 63 +++++---- lib/rake/ext/time.rb | 2 +- lib/rake/file_list.rb | 14 +- lib/rake/file_task.rb | 4 +- lib/rake/file_utils.rb | 20 ++- lib/rake/gempackagetask.rb | 4 +- lib/rake/invocation_chain.rb | 1 - lib/rake/lib/.document | 1 - lib/rake/lib/project.rake | 21 --- lib/rake/linked_list.rb | 2 +- lib/rake/name_space.rb | 59 +++++---- lib/rake/packagetask.rb | 30 +++-- lib/rake/pathmap.rb | 2 + lib/rake/pseudo_status.rb | 4 +- lib/rake/rake_module.rb | 11 +- lib/rake/rdoctask.rb | 2 + lib/rake/ruby182_test_unit_fix.rb | 2 + lib/rake/runtest.rb | 7 +- lib/rake/scope.rb | 2 +- lib/rake/task.rb | 23 ++-- lib/rake/task_arguments.rb | 29 +++-- lib/rake/task_manager.rb | 29 +++-- lib/rake/tasklib.rb | 2 + lib/rake/testtask.rb | 29 +++-- lib/rake/thread_pool.rb | 23 ++-- lib/rake/trace_output.rb | 2 +- lib/rake/version.rb | 2 - lib/rake/win32.rb | 2 +- test/rake/support/rakefile_definitions.rb | 34 +++++ test/rake/test_rake_application.rb | 186 ++++++++++++++++++++++----- test/rake/test_rake_application_options.rb | 17 ++- test/rake/test_rake_backtrace.rb | 6 + test/rake/test_rake_clean.rb | 15 ++- test/rake/test_rake_cpu_counter.rb | 50 +++++++ test/rake/test_rake_directory_task.rb | 6 + test/rake/test_rake_file_task.rb | 64 +++++++++ test/rake/test_rake_functional.rb | 18 ++- test/rake/test_rake_name_space.rb | 14 ++ test/rake/test_rake_path_map.rb | 4 +- test/rake/test_rake_rules.rb | 26 ++++ test/rake/test_rake_task.rb | 16 +++ test/rake/test_rake_task_argument_parsing.rb | 6 + test/rake/test_rake_task_arguments.rb | 6 + test/rake/test_rake_task_manager.rb | 20 +++ test/rake/test_rake_test_task.rb | 24 +++- 63 files changed, 1080 insertions(+), 310 deletions(-) create mode 100644 lib/rake/cpu_counter.rb delete mode 100644 lib/rake/lib/.document delete mode 100644 lib/rake/lib/project.rake create mode 100644 test/rake/test_rake_cpu_counter.rb diff --git a/ChangeLog b/ChangeLog index a98f046d37..f28be45888 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Tue Jul 15 12:00:03 2014 SHIBATA Hiroshi + + * lib/rake.rb, lib/rake/*.rb: Upgrade to rake-10.3.2 + [fix GH-668] + * test/rake/*.rb: ditto. + Mon Jul 14 19:14:51 2014 Masaki Suketa * ext/win32ole/win32ole.c: modify WIN32OLE class document and diff --git a/lib/rake.rb b/lib/rake.rb index 531cfc82b8..47cce17064 100644 --- a/lib/rake.rb +++ b/lib/rake.rb @@ -1,5 +1,4 @@ #-- - # Copyright 2003-2010 by Jim Weirich (jim.weirich@gmail.com) # # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -21,9 +20,14 @@ # IN THE SOFTWARE. #++ +module Rake + VERSION = '10.3.2' +end + require 'rake/version' # :stopdoc: +# TODO: Remove in Rake 11 RAKEVERSION = Rake::VERSION # :startdoc: @@ -41,6 +45,7 @@ require 'rake/ext/time' require 'rake/win32' require 'rake/linked_list' +require 'rake/cpu_counter' require 'rake/scope' require 'rake/task_argument_error' require 'rake/rule_recursion_overflow_error' diff --git a/lib/rake/alt_system.rb b/lib/rake/alt_system.rb index a42597bf09..aa7b7791b6 100644 --- a/lib/rake/alt_system.rb +++ b/lib/rake/alt_system.rb @@ -24,11 +24,13 @@ require 'rbconfig' -# +## # Alternate implementations of system() and backticks `` on Windows # for ruby-1.8 and earlier. -# -module Rake::AltSystem +#-- +# TODO: Remove in Rake 11 + +module Rake::AltSystem # :nodoc: all WINDOWS = RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw|[Ww]indows)! diff --git a/lib/rake/application.rb b/lib/rake/application.rb index b76244b7a3..795b4685d4 100644 --- a/lib/rake/application.rb +++ b/lib/rake/application.rb @@ -12,10 +12,10 @@ module Rake CommandLineOptionError = Class.new(StandardError) - ###################################################################### + ## # Rake main application object. When invoking +rake+ from the # command line, a Rake::Application object is created and run. - # + class Application include TaskManager include TraceOutput @@ -84,7 +84,7 @@ module Rake standard_exception_handling do @name = app_name handle_options - collect_tasks + collect_command_line_tasks end end @@ -117,8 +117,8 @@ module Rake thread_pool.join if options.job_stats stats = thread_pool.statistics - puts "Maximum active threads: #{stats[:max_active_threads]}" - puts "Total threads in play: #{stats[:total_threads_in_play]}" + puts "Maximum active threads: #{stats[:max_active_threads]} + main" + puts "Total threads in play: #{stats[:total_threads_in_play]} + main" end ThreadHistoryDisplay.new(thread_pool.history).show if options.job_stats == :history @@ -138,30 +138,41 @@ module Rake # Return the thread pool used for multithreaded processing. def thread_pool # :nodoc: - @thread_pool ||= ThreadPool.new(options.thread_pool_size || FIXNUM_MAX) + @thread_pool ||= ThreadPool.new(options.thread_pool_size || Rake.suggested_thread_count-1) end - # private ---------------------------------------------------------------- + # internal ---------------------------------------------------------------- - def invoke_task(task_string) + # Invokes a task with arguments that are extracted from +task_string+ + def invoke_task(task_string) # :nodoc: name, args = parse_task_string(task_string) t = self[name] t.invoke(*args) end - def parse_task_string(string) - if string =~ /^([^\[]+)(\[(.*)\])$/ - name = $1 - args = $3.split(/\s*,\s*/) - else - name = string - args = [] - end - [name, args] + def parse_task_string(string) # :nodoc: + /^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s + + name = $1 + remaining_args = $2 + + return string, [] unless name + return name, [] if remaining_args.empty? + + args = [] + + begin + /((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args + + remaining_args = $2 + args << $1.gsub(/\\(.)/, '\1') + end while remaining_args + + return name, args end # Provide standard exception handling for the given block. - def standard_exception_handling + def standard_exception_handling # :nodoc: yield rescue SystemExit # Exit silently with current status @@ -177,22 +188,47 @@ module Rake # Exit the program because of an unhandle exception. # (may be overridden by subclasses) - def exit_because_of_exception(ex) + def exit_because_of_exception(ex) # :nodoc: exit(false) end # Display the error message that caused the exception. - def display_error_message(ex) + def display_error_message(ex) # :nodoc: trace "#{name} aborted!" - trace ex.message + display_exception_details(ex) + trace "Tasks: #{ex.chain}" if has_chain?(ex) + trace "(See full trace by running task with --trace)" unless + options.backtrace + end + + def display_exception_details(ex) # :nodoc: + seen = Thread.current[:rake_display_exception_details_seen] ||= [] + return if seen.include? ex + seen << ex + + display_exception_message_details(ex) + display_exception_backtrace(ex) + display_exception_details(ex.cause) if has_cause?(ex) + end + + def has_cause?(ex) # :nodoc: + ex.respond_to?(:cause) && ex.cause + end + + def display_exception_message_details(ex) # :nodoc: + if ex.instance_of?(RuntimeError) + trace ex.message + else + trace "#{ex.class.name}: #{ex.message}" + end + end + + def display_exception_backtrace(ex) # :nodoc: if options.backtrace trace ex.backtrace.join("\n") else trace Backtrace.collapse(ex.backtrace).join("\n") end - trace "Tasks: #{ex.chain}" if has_chain?(ex) - trace "(See full trace by running task with --trace)" unless - options.backtrace end # Warn about deprecated usage. @@ -200,7 +236,7 @@ module Rake # Example: # Rake.application.deprecate("import", "Rake.import", caller.first) # - def deprecate(old_usage, new_usage, call_site) + def deprecate(old_usage, new_usage, call_site) # :nodoc: unless options.ignore_deprecate $stderr.puts "WARNING: '#{old_usage}' is deprecated. " + "Please use '#{new_usage}' instead.\n" + @@ -209,14 +245,14 @@ module Rake end # Does the exception have a task invocation chain? - def has_chain?(exception) + def has_chain?(exception) # :nodoc: exception.respond_to?(:chain) && exception.chain end private :has_chain? # True if one of the files in RAKEFILES is in the current directory. # If a match is found, it is copied into @rakefile. - def have_rakefile + def have_rakefile # :nodoc: @rakefiles.each do |fn| if File.exist?(fn) others = FileList.glob(fn, File::FNM_CASEFOLD) @@ -229,23 +265,23 @@ module Rake end # True if we are outputting to TTY, false otherwise - def tty_output? + def tty_output? # :nodoc: @tty_output end # Override the detected TTY output state (mostly for testing) - def tty_output=(tty_output_state) + def tty_output=(tty_output_state) # :nodoc: @tty_output = tty_output_state end # We will truncate output if we are outputting to a TTY or if we've been # given an explicit column width to honor - def truncate_output? + def truncate_output? # :nodoc: tty_output? || @terminal_columns.nonzero? end # Display the tasks and comments. - def display_tasks_and_comments + def display_tasks_and_comments # :nodoc: displayable_tasks = tasks.select { |t| (options.show_all_tasks || t.comment) && t.name =~ options.show_task_pattern @@ -284,7 +320,7 @@ module Rake end end - def terminal_width + def terminal_width # :nodoc: if @terminal_columns.nonzero? result = @terminal_columns else @@ -296,28 +332,28 @@ module Rake end # Calculate the dynamic width of the - def dynamic_width + def dynamic_width # :nodoc: @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) end - def dynamic_width_stty + def dynamic_width_stty # :nodoc: %x{stty size 2>/dev/null}.split[1].to_i end - def dynamic_width_tput + def dynamic_width_tput # :nodoc: %x{tput cols 2>/dev/null}.to_i end - def unix? + def unix? # :nodoc: RbConfig::CONFIG['host_os'] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i end - def windows? + def windows? # :nodoc: Win32.windows? end - def truncate(string, width) + def truncate(string, width) # :nodoc: if string.nil? "" elsif string.length <= width @@ -328,19 +364,19 @@ module Rake end # Display the tasks and prerequisites - def display_prerequisites + def display_prerequisites # :nodoc: tasks.each do |t| puts "#{name} #{t.name}" t.prerequisites.each { |pre| puts " #{pre}" } end end - def trace(*strings) + def trace(*strings) # :nodoc: options.trace_output ||= $stderr trace_on(options.trace_output, *strings) end - def sort_options(options) + def sort_options(options) # :nodoc: options.sort_by { |opt| opt.select { |o| o =~ /^-/ }.map { |o| o.downcase }.sort.reverse } @@ -349,11 +385,11 @@ module Rake # A list of all the standard options used in rake, suitable for # passing to OptionParser. - def standard_rake_options + def standard_rake_options # :nodoc: sort_options( [ ['--all', '-A', - "Show all tasks, even uncommented ones", + "Show all tasks, even uncommented ones (in combination with -T or -D)", lambda { |value| options.show_all_tasks = value } @@ -365,6 +401,12 @@ module Rake select_trace_output(options, 'backtrace', value) } ], + ['--build-all', '-B', + "Build all prerequisites, including those which are up-to-date.", + lambda { |value| + options.build_all = true + } + ], ['--comments', "Show commented tasks only", lambda { |value| @@ -407,9 +449,17 @@ module Rake ], ['--jobs', '-j [NUMBER]', "Specifies the maximum number of tasks to execute in parallel. " + - "(default is 2)", + "(default is number of CPU cores + 4)", lambda { |value| - options.thread_pool_size = [(value || 2).to_i, 2].max + if value.nil? || value == '' + value = FIXNUM_MAX + elsif value =~ /^\d+$/ + value = value.to_i + else + value = Rake.suggested_thread_count + end + value = 1 if value < 1 + options.thread_pool_size = value - 1 } ], ['--job-stats [LEVEL]', @@ -443,8 +493,8 @@ module Rake "Do not log messages to standard output.", lambda { |value| Rake.verbose(false) } ], - ['--rakefile', '-f [FILE]', - "Use FILE as the rakefile.", + ['--rakefile', '-f [FILENAME]', + "Use FILENAME as the rakefile to search for.", lambda { |value| value ||= '' @rakefiles.clear @@ -545,14 +595,14 @@ module Rake ]) end - def select_tasks_to_show(options, show_tasks, value) + def select_tasks_to_show(options, show_tasks, value) # :nodoc: options.show_tasks = show_tasks options.show_task_pattern = Regexp.new(value || '') Rake::TaskManager.record_task_metadata = true end private :select_tasks_to_show - def select_trace_output(options, trace_option, value) + def select_trace_output(options, trace_option, value) # :nodoc: value = value.strip unless value.nil? case value when 'stdout' @@ -567,7 +617,7 @@ module Rake private :select_trace_output # Read and handle the command line options. - def handle_options + def handle_options # :nodoc: options.rakelib = ['rakelib'] options.trace_output = $stderr @@ -588,7 +638,7 @@ module Rake # Similar to the regular Ruby +require+ command, but will check # for *.rake files in addition to *.rb files. - def rake_require(file_name, paths=$LOAD_PATH, loaded=$") + def rake_require(file_name, paths=$LOAD_PATH, loaded=$") # :nodoc: fn = file_name + ".rake" return false if loaded.include?(fn) paths.each do |path| @@ -602,7 +652,7 @@ module Rake fail LoadError, "Can't find #{file_name}" end - def find_rakefile_location + def find_rakefile_location # :nodoc: here = Dir.pwd until (fn = have_rakefile) Dir.chdir("..") @@ -614,7 +664,7 @@ module Rake Dir.chdir(Rake.original_dir) end - def print_rakefile_directory(location) + def print_rakefile_directory(location) # :nodoc: $stderr.puts "(in #{Dir.pwd})" unless options.silent or original_dir == location end @@ -645,13 +695,13 @@ module Rake load_imports end - def glob(path, &block) + def glob(path, &block) # :nodoc: FileList.glob(path.gsub("\\", '/')).each(&block) end private :glob # The directory path containing the system wide rakefiles. - def system_dir + def system_dir # :nodoc: @system_dir ||= begin if ENV['RAKE_SYSTEM'] @@ -677,7 +727,7 @@ module Rake # Collect the list of tasks on the command line. If no tasks are # given, return a list containing only the default task. # Environmental assignments are processed at this time as well. - def collect_tasks + def collect_command_line_tasks # :nodoc: @top_level_tasks = [] ARGV.each do |arg| if arg =~ /^(\w+)=(.*)$/m @@ -691,28 +741,33 @@ module Rake # Default task name ("default"). # (May be overridden by subclasses) - def default_task_name + def default_task_name # :nodoc: "default" end # Add a file to the list of files to be imported. - def add_import(fn) + def add_import(fn) # :nodoc: @pending_imports << fn end # Load the pending list of imported files. - def load_imports + def load_imports # :nodoc: while fn = @pending_imports.shift next if @imported.member?(fn) fn_task = lookup(fn) and fn_task.invoke ext = File.extname(fn) loader = @loaders[ext] || @default_loader loader.load(fn) + if fn_task = lookup(fn) and fn_task.needed? + fn_task.reenable + fn_task.invoke + loader.load(fn) + end @imported << fn end end - def rakefile_location(backtrace=caller) + def rakefile_location(backtrace=caller) # :nodoc: backtrace.map { |t| t[/([^:]+):/, 1] } re = /^#{@rakefile}$/ diff --git a/lib/rake/backtrace.rb b/lib/rake/backtrace.rb index 9b2ba6157f..439255d78b 100644 --- a/lib/rake/backtrace.rb +++ b/lib/rake/backtrace.rb @@ -1,5 +1,5 @@ module Rake - module Backtrace + module Backtrace # :nodoc: all SYS_KEYS = RbConfig::CONFIG.keys.grep(/(prefix|libdir)/) SYS_PATHS = RbConfig::CONFIG.values_at(*SYS_KEYS).uniq + [ File.join(File.dirname(__FILE__), "..") ] @@ -9,6 +9,9 @@ module Rake map { |f| File.expand_path(f) }. reject { |s| s.nil? || s =~ /^ *$/ } SUPPRESSED_PATHS_RE = SUPPRESSED_PATHS.map { |f| Regexp.quote(f) }.join("|") + SUPPRESSED_PATHS_RE << "|^org\\/jruby\\/\\w+\\.java" if + Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' + SUPPRESS_PATTERN = %r!(\A(#{SUPPRESSED_PATHS_RE})|bin/rake:\d+)!i def self.collapse(backtrace) diff --git a/lib/rake/clean.rb b/lib/rake/clean.rb index 8001ce569a..a49cd44167 100644 --- a/lib/rake/clean.rb +++ b/lib/rake/clean.rb @@ -31,9 +31,30 @@ module Rake begin rm_r file_name, opts rescue StandardError => ex - puts "Failed to remove #{file_name}: #{ex}" + puts "Failed to remove #{file_name}: #{ex}" unless file_already_gone?(file_name) end end + + def file_already_gone?(file_name) + return false if File.exist?(file_name) + + path = file_name + prev = nil + + while path = File.dirname(path) + return false if cant_be_deleted?(path) + break if [prev, "."].include?(path) + prev = path + end + true + end + private_class_method :file_already_gone? + + def cant_be_deleted?(path_name) + File.exist?(path_name) && + (!File.readable?(path_name) || !File.executable?(path_name)) + end + private_class_method :cant_be_deleted? end end diff --git a/lib/rake/cloneable.rb b/lib/rake/cloneable.rb index ac67471232..cd19cd3733 100644 --- a/lib/rake/cloneable.rb +++ b/lib/rake/cloneable.rb @@ -1,8 +1,8 @@ module Rake - # ########################################################################## + ## # Mixin for creating easily cloned objects. - # - module Cloneable + + module Cloneable # :nodoc: # The hook that invoked by 'clone' and 'dup' methods. def initialize_copy(source) super diff --git a/lib/rake/contrib/ftptools.rb b/lib/rake/contrib/ftptools.rb index 0dd50fdc8d..b178523bc6 100644 --- a/lib/rake/contrib/ftptools.rb +++ b/lib/rake/contrib/ftptools.rb @@ -9,9 +9,7 @@ require 'rake/file_list' module Rake # :nodoc: - #################################################################### - # Note: Not released for general use. - class FtpFile + class FtpFile # :nodoc: all attr_reader :name, :size, :owner, :group, :time def self.date @@ -68,9 +66,9 @@ module Rake # :nodoc: end end - #################################################################### + ## # Manage the uploading of files to an FTP account. - class FtpUploader + class FtpUploader # :nodoc: # Log uploads to standard output when true. attr_accessor :verbose diff --git a/lib/rake/contrib/publisher.rb b/lib/rake/contrib/publisher.rb index 8b11edb59c..f4ee1abf86 100644 --- a/lib/rake/contrib/publisher.rb +++ b/lib/rake/contrib/publisher.rb @@ -14,8 +14,10 @@ HostInfo = Struct.new(:name, :webdir, :pkgdir) # :startdoc: +# TODO: Move to contrib/sshpublisher +#-- # Manage several publishers as a single entity. -class CompositePublisher +class CompositePublisher # :nodoc: def initialize @publishers = [] end @@ -31,9 +33,11 @@ class CompositePublisher end end +# TODO: Remove in Rake 11, duplicated +#-- # Publish an entire directory to an existing remote directory using # SSH. -class SshDirPublisher +class SshDirPublisher # :nodoc: all def initialize(host, remote_dir, local_dir) @host = host @remote_dir = remote_dir @@ -45,8 +49,10 @@ class SshDirPublisher end end +# TODO: Remove in Rake 11, duplicated +#-- # Publish an entire directory to a fresh remote directory using SSH. -class SshFreshDirPublisher < SshDirPublisher +class SshFreshDirPublisher < SshDirPublisher # :nodoc: all def upload run %{ssh #{@host} rm -rf #{@remote_dir}} rescue nil run %{ssh #{@host} mkdir #{@remote_dir}} @@ -54,8 +60,10 @@ class SshFreshDirPublisher < SshDirPublisher end end +# TODO: Remove in Rake 11, duplicated +#-- # Publish a list of files to an existing remote directory. -class SshFilePublisher +class SshFilePublisher # :nodoc: all # Create a publisher using the give host information. def initialize(host, remote_dir, local_dir, *files) @host = host diff --git a/lib/rake/contrib/rubyforgepublisher.rb b/lib/rake/contrib/rubyforgepublisher.rb index a4b96936c8..00889ad7b9 100644 --- a/lib/rake/contrib/rubyforgepublisher.rb +++ b/lib/rake/contrib/rubyforgepublisher.rb @@ -1,8 +1,10 @@ +# TODO: Remove in Rake 11 + require 'rake/contrib/sshpublisher' module Rake - class RubyForgePublisher < SshDirPublisher + class RubyForgePublisher < SshDirPublisher # :nodoc: all attr_reader :project, :proj_id, :user def initialize(projname, user) diff --git a/lib/rake/contrib/sshpublisher.rb b/lib/rake/contrib/sshpublisher.rb index bd6adc127e..64f577017c 100644 --- a/lib/rake/contrib/sshpublisher.rb +++ b/lib/rake/contrib/sshpublisher.rb @@ -8,22 +8,30 @@ module Rake class SshDirPublisher include Rake::DSL + # Creates an SSH publisher which will scp all files in +local_dir+ to + # +remote_dir+ on +host+ + def initialize(host, remote_dir, local_dir) @host = host @remote_dir = remote_dir @local_dir = local_dir end + # Uploads the files + def upload - sh %{scp -rq #{@local_dir}/* #{@host}:#{@remote_dir}} + sh "scp", "-rq", "#{@local_dir}/*", "#{@host}:#{@remote_dir}" end end # Publish an entire directory to a fresh remote directory using SSH. class SshFreshDirPublisher < SshDirPublisher + + # Uploads the files after removing the existing remote directory. + def upload - sh %{ssh #{@host} rm -rf #{@remote_dir}} rescue nil - sh %{ssh #{@host} mkdir #{@remote_dir}} + sh "ssh", @host, "rm", "-rf", @remote_dir rescue nil + sh "ssh", @host, "mkdir", @remote_dir super end end @@ -32,7 +40,9 @@ module Rake class SshFilePublisher include Rake::DSL - # Create a publisher using the give host information. + # Creates an SSH publisher which will scp all +files+ in +local_dir+ to + # +remote_dir+ on +host+. + def initialize(host, remote_dir, local_dir, *files) @host = host @remote_dir = remote_dir @@ -40,10 +50,11 @@ module Rake @files = files end - # Upload the local directory to the remote directory. + # Uploads the files + def upload @files.each do |fn| - sh %{scp -q #{@local_dir}/#{fn} #{@host}:#{@remote_dir}} + sh "scp", "-q", "#{@local_dir}/#{fn}", "#{@host}:#{@remote_dir}" end end end diff --git a/lib/rake/contrib/sys.rb b/lib/rake/contrib/sys.rb index a3a9f69e25..8d4c735434 100644 --- a/lib/rake/contrib/sys.rb +++ b/lib/rake/contrib/sys.rb @@ -1,2 +1,4 @@ +# TODO: Remove in Rake 11 + fail "ERROR: 'rake/contrib/sys' is obsolete and no longer supported. " + "Use 'FileUtils' instead." diff --git a/lib/rake/cpu_counter.rb b/lib/rake/cpu_counter.rb new file mode 100644 index 0000000000..c05b69b7a7 --- /dev/null +++ b/lib/rake/cpu_counter.rb @@ -0,0 +1,109 @@ +require 'rbconfig' + +# TODO: replace with IO.popen using array-style arguments in Rake 11 +require 'open3' + +module Rake + + # Based on a script at: + # http://stackoverflow.com/questions/891537/ruby-detect-number-of-cpus-installed + class CpuCounter # :nodoc: all + def self.count + new.count_with_default + end + + def count_with_default(default=4) + count || default + rescue StandardError + default + end + + def count + if defined?(Java::Java) + count_via_java_runtime + else + case RbConfig::CONFIG['host_os'] + when /darwin9/ + count_via_hwprefs_cpu_count + when /darwin/ + count_via_hwprefs_thread_count || count_via_sysctl + when /linux/ + count_via_cpuinfo + when /bsd/ + count_via_sysctl + when /mswin|mingw/ + count_via_win32 + else + # Try everything + count_via_win32 || + count_via_sysctl || + count_via_hwprefs_thread_count || + count_via_hwprefs_cpu_count + end + end + end + + def count_via_java_runtime + Java::Java.lang.Runtime.getRuntime.availableProcessors + rescue StandardError + nil + end + + def count_via_win32 + require 'win32ole' + wmi = WIN32OLE.connect("winmgmts://") + cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # TODO count hyper-threaded in this + cpu.to_enum.first.NumberOfCores + rescue StandardError, LoadError + nil + end + + def count_via_cpuinfo + open('/proc/cpuinfo') { |f| f.readlines }.grep(/processor/).size + rescue StandardError + nil + end + + def count_via_hwprefs_thread_count + run 'hwprefs', 'thread_count' + end + + def count_via_hwprefs_cpu_count + run 'hwprefs', 'cpu_count' + end + + def count_via_sysctl + run 'sysctl', '-n', 'hw.ncpu' + end + + def run(command, *args) + cmd = resolve_command(command) + if cmd + Open3.popen3 cmd, *args do |inn, out, err,| + inn.close + err.read + out.read.to_i + end + else + nil + end + end + + def resolve_command(command) + look_for_command("/usr/sbin", command) || + look_for_command("/sbin", command) || + in_path_command(command) + end + + def look_for_command(dir, command) + path = File.join(dir, command) + File.exist?(path) ? path : nil + end + + def in_path_command(command) + Open3.popen3 'which', command do |_, out,| + out.eof? ? nil : command + end + end + end +end diff --git a/lib/rake/default_loader.rb b/lib/rake/default_loader.rb index 5dd3c05617..6154408f44 100644 --- a/lib/rake/default_loader.rb +++ b/lib/rake/default_loader.rb @@ -2,6 +2,10 @@ module Rake # Default Rakefile loader used by +import+. class DefaultLoader + + ## + # Loads a rakefile into the current application from +fn+ + def load(fn) Rake.load_rakefile(File.expand_path(fn)) end diff --git a/lib/rake/dsl_definition.rb b/lib/rake/dsl_definition.rb index b24a821386..28e9631c3c 100644 --- a/lib/rake/dsl_definition.rb +++ b/lib/rake/dsl_definition.rb @@ -6,6 +6,9 @@ module Rake ## # DSL is a module that provides #task, #desc, #namespace, etc. Use this # when you'd like to use rake outside the top level scope. + # + # For a Rakefile you run from the comamnd line this module is automatically + # included. module DSL @@ -21,14 +24,45 @@ module Rake private - # Declare a basic task. + # :call-seq: + # task task_name + # task task_name: dependencies + # task task_name, arguments => dependencies + # task task_name, argument[, argument ...], :needs: dependencies # - # Example: - # task :clobber => [:clean] do + # Declare a basic task. The +task_name+ is always the first argument. If + # the task name contains a ":" it is defined in that namespace. + # + # The +dependencies+ may be a single task name or an Array of task names. + # The +argument+ (a single name) or +arguments+ (an Array of names) define + # the arguments provided to the task. + # + # The task, argument and dependency names may be either symbols or + # strings. + # + # A task with a single dependency: + # + # task clobber: %w[clean] do # rm_rf "html" # end # - def task(*args, &block) + # A task with an argument and a dependency: + # + # task :package, [:version] => :test do |t, args| + # # ... + # end + # + # To invoke this task from the command line: + # + # $ rake package[1.2.3] + # + # Alternate definition: + # + # task :package, :version, needs: :test do |t, args| + # # ... + # end + # + def task(*args, &block) # :doc: Rake::Task.define_task(*args, &block) end @@ -45,7 +79,7 @@ module Rake # end # end # - def file(*args, &block) + def file(*args, &block) # :doc: Rake::FileTask.define_task(*args, &block) end @@ -61,7 +95,7 @@ module Rake # Example: # directory "testdata/doc" # - def directory(*args, &block) + def directory(*args, &block) # :doc: result = file_create(*args, &block) dir, _ = *Rake.application.resolve_args(args) Rake.each_dir_parent(dir) do |d| @@ -78,9 +112,9 @@ module Rake # about it) # # Example: - # multitask :deploy => [:deploy_gem, :deploy_rdoc] + # multitask deploy: %w[deploy_gem deploy_rdoc] # - def multitask(*args, &block) + def multitask(*args, &block) # :doc: Rake::MultiTask.define_task(*args, &block) end @@ -88,14 +122,22 @@ module Rake # block. Returns a NameSpace object that can be used to lookup # tasks defined in the namespace. # - # E.g. + # Example: # # ns = namespace "nested" do + # # the "nested:run" task # task :run # end # task_run = ns[:run] # find :run in the given namespace. # - def namespace(name=nil, &block) + # Tasks can also be defined in a namespace by using a ":" in the task + # name: + # + # task "nested:test" do + # # ... + # end + # + def namespace(name=nil, &block) # :doc: name = name.to_s if name.kind_of?(Symbol) name = name.to_str if name.respond_to?(:to_str) unless name.kind_of?(String) || name.nil? @@ -108,23 +150,22 @@ module Rake # # Example: # rule '.o' => '.c' do |t| - # sh %{cc -o #{t.name} #{t.source}} + # sh 'cc', '-o', t.name, t.source # end # - def rule(*args, &block) + def rule(*args, &block) # :doc: Rake::Task.create_rule(*args, &block) end - # Describe the next rake task. - # Duplicate descriptions are discarded. + # Describes the next rake task. Duplicate descriptions are discarded. # # Example: # desc "Run the Unit Tests" - # task :test => [:build] - # runtests + # task test: [:build] + # # ... run tests # end # - def desc(description) + def desc(description) # :doc: Rake.application.last_description = description end @@ -142,7 +183,7 @@ module Rake # Example: # import ".depend", "my_rules" # - def import(*fns) + def import(*fns) # :doc: fns.each do |fn| Rake.application.add_import(fn) end diff --git a/lib/rake/early_time.rb b/lib/rake/early_time.rb index 8c0e7d3339..abcb1872b5 100644 --- a/lib/rake/early_time.rb +++ b/lib/rake/early_time.rb @@ -5,11 +5,14 @@ module Rake include Comparable include Singleton + ## + # The EarlyTime always comes before +other+! + def <=>(other) -1 end - def to_s + def to_s # :nodoc: "" end end diff --git a/lib/rake/ext/core.rb b/lib/rake/ext/core.rb index c924c7eaba..7575df15a9 100644 --- a/lib/rake/ext/core.rb +++ b/lib/rake/ext/core.rb @@ -1,8 +1,5 @@ -###################################################################### -# Core extension library -# class Module - # Check for an existing method in the current class before extending. IF + # Check for an existing method in the current class before extending. If # the method already exists, then a warning is printed and the extension is # not added. Otherwise the block is yielded and any definitions in the # block will take effect. @@ -17,7 +14,7 @@ class Module # end # end # - def rake_extension(method) + def rake_extension(method) # :nodoc: if method_defined?(method) $stderr.puts "WARNING: Possible conflict with Rake extension: " + "#{self}##{method} already exists" diff --git a/lib/rake/ext/module.rb b/lib/rake/ext/module.rb index 8b13789179..3ee155ff6c 100644 --- a/lib/rake/ext/module.rb +++ b/lib/rake/ext/module.rb @@ -1 +1,2 @@ +# TODO: remove in Rake 11 diff --git a/lib/rake/ext/string.rb b/lib/rake/ext/string.rb index 07ef167f82..34ee328f72 100644 --- a/lib/rake/ext/string.rb +++ b/lib/rake/ext/string.rb @@ -1,8 +1,5 @@ require 'rake/ext/core' -###################################################################### -# Rake extension methods for String. -# class String rake_extension("ext") do @@ -11,6 +8,8 @@ class String # is not given, or is the empty string, remove any existing extension. # # +ext+ is a user added method for the String class. + # + # This String extension comes from Rake def ext(newext='') return self.dup if ['.', '..'].include? self newext = (newext =~ /^\./) ? newext : ("." + newext) if newext != '' @@ -20,6 +19,8 @@ class String rake_extension("pathmap") do # Explode a path into individual components. Used by +pathmap+. + # + # This String extension comes from Rake def pathmap_explode head, tail = File.split(self) return [self] if head == self @@ -32,6 +33,8 @@ class String # Extract a partial path from the path. Include +n+ directories from the # front end (left hand side) if +n+ is positive. Include |+n+| # directories from the back end (right hand side) if +n+ is negative. + # + # This String extension comes from Rake def pathmap_partial(n) dirs = File.dirname(self).pathmap_explode partial_dirs = @@ -48,6 +51,8 @@ class String # Preform the pathmap replacement operations on the given path. The # patterns take the form 'pat1,rep1;pat2,rep2...'. + # + # This String extension comes from Rake def pathmap_replace(patterns, &block) result = self patterns.split(';').each do |pair| @@ -69,35 +74,36 @@ class String # controls the details of the mapping. The following special patterns are # recognized: # - # * %p -- The complete path. - # * %f -- The base file name of the path, with its file extension, - # but without any directories. - # * %n -- The file name of the path without its file extension. - # * %d -- The directory list of the path. - # * %x -- The file extension of the path. An empty string if there - # is no extension. - # * %X -- Everything *but* the file extension. - # * %s -- The alternate file separator if defined, otherwise use - # the standard file separator. - # * %% -- A percent sign. - # - # The %d specifier can also have a numeric prefix (e.g. '%2d'). If the - # number is positive, only return (up to) +n+ directories in the path, - # starting from the left hand side. If +n+ is negative, return (up to) - # |+n+| directories from the right hand side of the path. + # %p :: The complete path. + # %f :: The base file name of the path, with its file extension, + # but without any directories. + # %n :: The file name of the path without its file extension. + # %d :: The directory list of the path. + # %x :: The file extension of the path. An empty string if there + # is no extension. + # %X :: Everything *but* the file extension. + # %s :: The alternate file separator if defined, otherwise use # + # the standard file separator. + # %% :: A percent sign. + # + # The %d specifier can also have a numeric prefix (e.g. '%2d'). + # If the number is positive, only return (up to) +n+ directories in the + # path, starting from the left hand side. If +n+ is negative, return (up + # to) +n+ directories from the right hand side of the path. # # Examples: # # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b' # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d' # - # Also the %d, %p, %f, %n, %x, and %X operators can take a - # pattern/replacement argument to perform simple string substitutions on a - # particular part of the path. The pattern and replacement are separated - # by a comma and are enclosed by curly braces. The replacement spec comes - # after the % character but before the operator letter. (e.g. - # "%{old,new}d"). Multiple replacement specs should be separated by - # semi-colons (e.g. "%{old,new;src,bin}d"). + # Also the %d, %p, %f, %n, + # %x, and %X operators can take a pattern/replacement + # argument to perform simple string substitutions on a particular part of + # the path. The pattern and replacement are separated by a comma and are + # enclosed by curly braces. The replacement spec comes after the % + # character but before the operator letter. (e.g. "%{old,new}d"). + # Multiple replacement specs should be separated by semi-colons (e.g. + # "%{old,new;src,bin}d"). # # Regular expressions may be used for the pattern, and back refs may be # used in the replacement text. Curly braces, commas and semi-colons are @@ -106,11 +112,11 @@ class String # # For example: # - # "src/org/onestepback/proj/A.java".pathmap("%{^src,bin}X.class") + # "src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class") # # returns: # - # "bin/org/onestepback/proj/A.class" + # "class/org/onestepback/proj/A.class" # # If the replacement text is '*', then a block may be provided to perform # some arbitrary calculation for the replacement. @@ -125,6 +131,7 @@ class String # # "/path/to/file.txt" # + # This String extension comes from Rake def pathmap(spec=nil, &block) return self if spec.nil? result = '' diff --git a/lib/rake/ext/time.rb b/lib/rake/ext/time.rb index ea8b037e39..c058649b7e 100644 --- a/lib/rake/ext/time.rb +++ b/lib/rake/ext/time.rb @@ -3,7 +3,7 @@ require 'rake/early_time' -class Time +class Time # :nodoc: all alias rake_original_time_compare :<=> def <=>(other) if Rake::EarlyTime === other diff --git a/lib/rake/file_list.rb b/lib/rake/file_list.rb index f32b8c62a4..b01dbbb341 100644 --- a/lib/rake/file_list.rb +++ b/lib/rake/file_list.rb @@ -2,10 +2,10 @@ require 'rake/cloneable' require 'rake/file_utils_ext' require 'rake/pathmap' -###################################################################### + module Rake - # ######################################################################### + ## # A FileList is essentially an array with a few helper methods defined to # make file manipulation a bit easier. # @@ -156,7 +156,6 @@ module Rake self end - # Clear all the exclude patterns so that we exclude nothing. def clear_exclude @exclude_patterns = [] @@ -164,7 +163,7 @@ module Rake self end - # Define equality. + # A FileList is equal through array equality. def ==(array) to_ary == array end @@ -208,7 +207,7 @@ module Rake self end - def resolve_add(fn) + def resolve_add(fn) # :nodoc: case fn when %r{[*?\[\{]} add_matching(fn) @@ -218,7 +217,7 @@ module Rake end private :resolve_add - def resolve_exclude + def resolve_exclude # :nodoc: reject! { |fn| excluded_from_list?(fn) } self end @@ -276,7 +275,6 @@ module Rake collect { |fn| fn.ext(newext) } end - # Grep each of the files in the filelist using the given pattern. If a # block is given, call the block on each matching line, passing the file # name, line number, and the matching line of text. If no block is given, @@ -377,7 +375,7 @@ module Rake proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) } ] - def import(array) + def import(array) # :nodoc: @items = array self end diff --git a/lib/rake/file_task.rb b/lib/rake/file_task.rb index 3e717c24b7..03e26d967b 100644 --- a/lib/rake/file_task.rb +++ b/lib/rake/file_task.rb @@ -2,7 +2,7 @@ require 'rake/task.rb' require 'rake/early_time' module Rake - # ######################################################################### + # A FileTask is a task that includes time based dependencies. If any of a # FileTask's prerequisites have a timestamp that is later than the file # represented by this task, then the file must be rebuilt (using the @@ -13,7 +13,7 @@ module Rake # Is this file task needed? Yes if it doesn't exist, or if its time stamp # is out of date. def needed? - ! File.exist?(name) || out_of_date?(timestamp) + ! File.exist?(name) || out_of_date?(timestamp) || @application.options.build_all end # Time stamp for file task. diff --git a/lib/rake/file_utils.rb b/lib/rake/file_utils.rb index 0f7f459d87..27f4e2e1d1 100644 --- a/lib/rake/file_utils.rb +++ b/lib/rake/file_utils.rb @@ -14,12 +14,24 @@ module FileUtils OPT_TABLE['sh'] = %w(noop verbose) OPT_TABLE['ruby'] = %w(noop verbose) - # Run the system command +cmd+. If multiple arguments are given the command - # is not run with the shell (same semantics as Kernel::exec and + # Run the system command +cmd+. If multiple arguments are given the command + # is run directly (without the shell, same semantics as Kernel::exec and # Kernel::system). # - # Example: - # sh %{ls -ltr} + # It is recommended you use the multiple argument form over interpolating + # user input for both usability and security reasons. With the multiple + # argument form you can easily process files with spaces or other shell + # reserved characters in them. With the multiple argument form your rake + # tasks are not vulnerable to users providing an argument like + # ; rm # -rf /. + # + # If a block is given, upon command completion the block is called with an + # OK flag (true on a zero exit status) and a Process::Status object. + # Without a block a RuntimeError is raised when the command exits non-zero. + # + # Examples: + # + # sh 'ls -ltr' # # sh 'ls', 'file with spaces' # diff --git a/lib/rake/gempackagetask.rb b/lib/rake/gempackagetask.rb index 4ace0a6f0e..16e7ce042b 100644 --- a/lib/rake/gempackagetask.rb +++ b/lib/rake/gempackagetask.rb @@ -1,2 +1,4 @@ +# TODO: Remove in Rake 11 + fail "ERROR: 'rake/gempackagetask' is obsolete and no longer supported. " + - "Use 'rubygems/packagetask' instead." + "Use 'rubygems/package_task' instead." diff --git a/lib/rake/invocation_chain.rb b/lib/rake/invocation_chain.rb index dae9a35915..690435169a 100644 --- a/lib/rake/invocation_chain.rb +++ b/lib/rake/invocation_chain.rb @@ -1,6 +1,5 @@ module Rake - #################################################################### # InvocationChain tracks the chain of task invocations to detect # circular dependencies. class InvocationChain < LinkedList diff --git a/lib/rake/lib/.document b/lib/rake/lib/.document deleted file mode 100644 index 098e64716e..0000000000 --- a/lib/rake/lib/.document +++ /dev/null @@ -1 +0,0 @@ -# Ignore project.rake diff --git a/lib/rake/lib/project.rake b/lib/rake/lib/project.rake deleted file mode 100644 index a5497328a7..0000000000 --- a/lib/rake/lib/project.rake +++ /dev/null @@ -1,21 +0,0 @@ -task "create:project" => ["lib", "test", "Rakefile"] - -directory "lib" -directory "test" - -file "Rakefile" do - File.open("Rakefile", "w") do |out| - out.puts %{# -*- ruby -*- - -require 'rake/clean' -require 'rake/testtask' - -task :default => :test - -Rake::TestTask.new do |t| - t.verbose = false - t.test_files = FileList['test/test_*.rb'] -end -} - end -end diff --git a/lib/rake/linked_list.rb b/lib/rake/linked_list.rb index 7369e83ac3..b5ab797808 100644 --- a/lib/rake/linked_list.rb +++ b/lib/rake/linked_list.rb @@ -13,7 +13,7 @@ module Rake end # Polymorphically add a new element to the head of a list. The - # type of head node will be the same list type has the tail. + # type of head node will be the same list type as the tail. def conj(item) self.class.cons(item, self) end diff --git a/lib/rake/name_space.rb b/lib/rake/name_space.rb index e1cc0940b8..58f911e434 100644 --- a/lib/rake/name_space.rb +++ b/lib/rake/name_space.rb @@ -1,25 +1,38 @@ -module Rake - - # The NameSpace class will lookup task names in the the scope - # defined by a +namespace+ command. - # - class NameSpace - - # Create a namespace lookup object using the given task manager - # and the list of scopes. - def initialize(task_manager, scope_list) - @task_manager = task_manager - @scope = scope_list.dup - end - - # Lookup a task named +name+ in the namespace. - def [](name) - @task_manager.lookup(name, @scope) - end - - # Return the list of tasks defined in this and nested namespaces. - def tasks - @task_manager.tasks_in_scope(@scope) - end +## +# The NameSpace class will lookup task names in the scope defined by a +# +namespace+ command. + +class Rake::NameSpace + + ## + # Create a namespace lookup object using the given task manager + # and the list of scopes. + + def initialize(task_manager, scope_list) + @task_manager = task_manager + @scope = scope_list.dup + end + + ## + # Lookup a task named +name+ in the namespace. + + def [](name) + @task_manager.lookup(name, @scope) + end + + ## + # The scope of the namespace (a LinkedList) + + def scope + @scope.dup end + + ## + # Return the list of tasks defined in this and nested namespaces. + + def tasks + @task_manager.tasks_in_scope(@scope) + end + end + diff --git a/lib/rake/packagetask.rb b/lib/rake/packagetask.rb index 029caa6d49..e862952c05 100644 --- a/lib/rake/packagetask.rb +++ b/lib/rake/packagetask.rb @@ -11,27 +11,27 @@ module Rake # # The PackageTask will create the following targets: # - # [:package] + # +:package+ :: # Create all the requested package files. # - # [:clobber_package] + # +:clobber_package+ :: # Delete all the package files. This target is automatically # added to the main clobber target. # - # [:repackage] + # +:repackage+ :: # Rebuild the package files from scratch, even if they are not out # of date. # - # ["package_dir/name-version.tgz"] + # "package_dir/name-version.tgz" :: # Create a gzipped tar package (if need_tar is true). # - # ["package_dir/name-version.tar.gz"] + # "package_dir/name-version.tar.gz" :: # Create a gzipped tar package (if need_tar_gz is true). # - # ["package_dir/name-version.tar.bz2"] + # "package_dir/name-version.tar.bz2" :: # Create a bzip2'd tar package (if need_tar_bz2 is true). # - # ["package_dir/name-version.zip"] + # "package_dir/name-version.zip" :: # Create a zip package archive (if need_zip is true). # # Example: @@ -127,7 +127,7 @@ module Rake file "#{package_dir}/#{file}" => [package_dir_path] + package_files do chdir(package_dir) do - sh %{#{@tar_command} #{flag}cvf #{file} #{package_name}} + sh @tar_command, "#{flag}cvf", file, package_name end end end @@ -138,7 +138,7 @@ module Rake file "#{package_dir}/#{zip_file}" => [package_dir_path] + package_files do chdir(package_dir) do - sh %{#{@zip_command} -r #{zip_file} #{package_name}} + sh @zip_command, "-r", zip_file, package_name end end end @@ -162,26 +162,38 @@ module Rake self end + # The name of this package + def package_name @version ? "#{@name}-#{@version}" : @name end + # The directory this package will be built in + def package_dir_path "#{package_dir}/#{package_name}" end + # The package name with .tgz added + def tgz_file "#{package_name}.tgz" end + # The package name with .tar.gz added + def tar_gz_file "#{package_name}.tar.gz" end + # The package name with .tar.bz2 added + def tar_bz2_file "#{package_name}.tar.bz2" end + # The package name with .zip added + def zip_file "#{package_name}.zip" end diff --git a/lib/rake/pathmap.rb b/lib/rake/pathmap.rb index 2275724341..9a840cda29 100644 --- a/lib/rake/pathmap.rb +++ b/lib/rake/pathmap.rb @@ -1 +1,3 @@ +# TODO: Remove in Rake 11 + require 'rake/ext/string' diff --git a/lib/rake/pseudo_status.rb b/lib/rake/pseudo_status.rb index 09d5c88c7e..16e1903bd6 100644 --- a/lib/rake/pseudo_status.rb +++ b/lib/rake/pseudo_status.rb @@ -1,8 +1,8 @@ module Rake - #################################################################### + ## # Exit status class for times the system just gives us a nil. - class PseudoStatus + class PseudoStatus # :nodoc: all attr_reader :exitstatus def initialize(code=0) diff --git a/lib/rake/rake_module.rb b/lib/rake/rake_module.rb index fcf5800064..3692753434 100644 --- a/lib/rake/rake_module.rb +++ b/lib/rake/rake_module.rb @@ -2,8 +2,6 @@ require 'rake/application' module Rake - # Rake module singleton methods. - # class << self # Current Rake Application def application @@ -15,6 +13,11 @@ module Rake @application = app end + def suggested_thread_count # :nodoc: + @cpu_count ||= Rake::CpuCounter.count + @cpu_count + 4 + end + # Return the original directory where the Rake application was started. def original_dir application.original_dir @@ -28,9 +31,7 @@ module Rake # Add files to the rakelib list def add_rakelib(*files) application.options.rakelib ||= [] - files.each do |file| - application.options.rakelib << file - end + application.options.rakelib.concat(files) end end diff --git a/lib/rake/rdoctask.rb b/lib/rake/rdoctask.rb index 50b7e269d5..8d7df4f12b 100644 --- a/lib/rake/rdoctask.rb +++ b/lib/rake/rdoctask.rb @@ -1,2 +1,4 @@ +# TODO: Remove in Rake 11 + fail "ERROR: 'rake/rdoctask' is obsolete and no longer supported. " + "Use 'rdoc/task' (available in RDoc 2.4.2+) instead." diff --git a/lib/rake/ruby182_test_unit_fix.rb b/lib/rake/ruby182_test_unit_fix.rb index e47feeb09c..40b30a6fde 100644 --- a/lib/rake/ruby182_test_unit_fix.rb +++ b/lib/rake/ruby182_test_unit_fix.rb @@ -1,3 +1,5 @@ +# TODO: Remove in rake 11 + # Local Rake override to fix bug in Ruby 0.8.2 module Test # :nodoc: # Local Rake override to fix bug in Ruby 0.8.2 diff --git a/lib/rake/runtest.rb b/lib/rake/runtest.rb index 3f01b28cad..4774b0e262 100644 --- a/lib/rake/runtest.rb +++ b/lib/rake/runtest.rb @@ -5,7 +5,12 @@ require 'rake/file_list' module Rake include Test::Unit::Assertions - def run_tests(pattern='test/test*.rb', log_enabled=false) + ## + # Deprecated way of running tests in process, but only for Test::Unit. + #-- + # TODO: Remove in rake 11 + + def run_tests(pattern='test/test*.rb', log_enabled=false) # :nodoc: FileList.glob(pattern).each do |fn| $stderr.puts fn if log_enabled begin diff --git a/lib/rake/scope.rb b/lib/rake/scope.rb index 33e1c08e7b..dbefcea465 100644 --- a/lib/rake/scope.rb +++ b/lib/rake/scope.rb @@ -1,5 +1,5 @@ module Rake - class Scope < LinkedList + class Scope < LinkedList # :nodoc: all # Path for the scope. def path diff --git a/lib/rake/task.rb b/lib/rake/task.rb index 5e4dd64d4e..9bcf725523 100644 --- a/lib/rake/task.rb +++ b/lib/rake/task.rb @@ -2,7 +2,7 @@ require 'rake/invocation_exception_mixin' module Rake - # ######################################################################### + ## # A Task is the basic unit of work in a Rakefile. Tasks have associated # actions (possibly more than one) and a list of prerequisites. When # invoked, a task will first ensure that all of its prerequisites have an @@ -34,14 +34,18 @@ module Rake name end - def inspect + def inspect # :nodoc: "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>" end # List of sources for task. attr_writer :sources def sources - @sources ||= [] + if defined?(@sources) + @sources + else + prerequisites + end end # List of prerequisite tasks @@ -49,7 +53,7 @@ module Rake prerequisites.map { |pre| lookup_prerequisite(pre) } end - def lookup_prerequisite(prerequisite_name) + def lookup_prerequisite(prerequisite_name) # :nodoc: application[prerequisite_name, @scope] end private :lookup_prerequisite @@ -63,7 +67,7 @@ module Rake seen.values end - def collect_prerequisites(seen) + def collect_prerequisites(seen) # :nodoc: prerequisite_tasks.each do |pre| next if seen[pre.name] seen[pre.name] = pre @@ -74,7 +78,7 @@ module Rake # First source from a rule (nil if no sources) def source - @sources.first if defined?(@sources) + sources.first end # Create a task named +task_name+ with no actions or prerequisites. Use @@ -180,7 +184,7 @@ module Rake end protected :invoke_with_call_chain - def add_chain_to(exception, new_chain) + def add_chain_to(exception, new_chain) # :nodoc: exception.extend(InvocationExceptionMixin) unless exception.respond_to?(:chain) exception.chain = new_chain if exception.chain.nil? @@ -257,11 +261,12 @@ module Rake add_comment(comment) if comment && ! comment.empty? end - def comment=(comment) + def comment=(comment) # :nodoc: add_comment(comment) end - def add_comment(comment) + def add_comment(comment) # :nodoc: + return if comment.nil? @comments << comment unless @comments.include?(comment) end private :add_comment diff --git a/lib/rake/task_arguments.rb b/lib/rake/task_arguments.rb index 0094682579..fc0d657274 100644 --- a/lib/rake/task_arguments.rb +++ b/lib/rake/task_arguments.rb @@ -1,16 +1,16 @@ module Rake - #################################################################### + ## # TaskArguments manage the arguments passed to a task. # class TaskArguments include Enumerable + # Argument names attr_reader :names - # Create a TaskArgument object with a list of named arguments - # (given by :names) and a set of associated values (given by - # :values). :parent is the parent argument object. + # Create a TaskArgument object with a list of argument +names+ and a set + # of associated +values+. +parent+ is the parent argument object. def initialize(names, values, parent=nil) @names = names @parent = parent @@ -21,12 +21,12 @@ module Rake } end - # Retrive the complete array of sequential values + # Retrieve the complete array of sequential values def to_a @values.dup end - # Retrive the list of values not associated with named arguments + # Retrieve the list of values not associated with named arguments def extras @values[@names.length..-1] || [] end @@ -50,33 +50,42 @@ module Rake @hash = defaults.merge(@hash) end + # Enumerates the arguments and their values def each(&block) @hash.each(&block) end + # Extracts the argument values at +keys+ def values_at(*keys) keys.map { |k| lookup(k) } end + # Returns the value of the given argument via method_missing def method_missing(sym, *args) lookup(sym.to_sym) end + # Returns a Hash of arguments and their values def to_hash @hash end - def to_s + def to_s # :nodoc: @hash.inspect end - def inspect + def inspect # :nodoc: to_s end + # Returns true if +key+ is one of the arguments + def has_key?(key) + @hash.has_key?(key) + end + protected - def lookup(name) + def lookup(name) # :nodoc: if @hash.has_key?(name) @hash[name] elsif @parent @@ -85,5 +94,5 @@ module Rake end end - EMPTY_TASK_ARGS = TaskArguments.new([], []) + EMPTY_TASK_ARGS = TaskArguments.new([], []) # :nodoc: end diff --git a/lib/rake/task_manager.rb b/lib/rake/task_manager.rb index 06c243a7b2..af53e3f586 100644 --- a/lib/rake/task_manager.rb +++ b/lib/rake/task_manager.rb @@ -4,9 +4,12 @@ module Rake module TaskManager # Track the last comment made in the Rakefile. attr_accessor :last_description - alias :last_comment :last_description # Backwards compatibility - def initialize + # TODO: Remove in Rake 11 + + alias :last_comment :last_description # :nodoc: Backwards compatibility + + def initialize # :nodoc: super @tasks = Hash.new @rules = Array.new @@ -14,14 +17,22 @@ module Rake @last_description = nil end - def create_rule(*args, &block) + def create_rule(*args, &block) # :nodoc: pattern, args, deps = resolve_args(args) pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern @rules << [pattern, args, deps, block] end - def define_task(task_class, *args, &block) + def define_task(task_class, *args, &block) # :nodoc: task_name, arg_names, deps = resolve_args(args) + + original_scope = @scope + if String === task_name and + not task_class.ancestors.include? Rake::FileTask then + task_name, *definition_scope = *(task_name.split(":").reverse) + @scope = Scope.make(*(definition_scope + @scope.to_a)) + end + task_name = task_class.scope_name(@scope, task_name) deps = [deps] unless deps.respond_to?(:to_ary) deps = deps.map { |d| d.to_s } @@ -32,6 +43,8 @@ module Rake task.add_description(get_description(task)) end task.enhance(deps, &block) + ensure + @scope = original_scope end # Lookup a task. Return an existing task if found, otherwise @@ -49,7 +62,7 @@ module Rake fail "Don't know how to build task '#{task_name}'" end - def synthesize_file_task(task_name) + def synthesize_file_task(task_name) # :nodoc: return nil unless File.exist?(task_name) define_task(Rake::FileTask, task_name) end @@ -226,7 +239,7 @@ module Rake "_anon_#{@seed}" end - def trace_rule(level, message) + def trace_rule(level, message) # :nodoc: options.trace_output.puts "#{" " * level}#{message}" if Rake.application.options.trace_rules end @@ -265,7 +278,7 @@ module Rake task_name.ext(ext) when String ext - when Proc + when Proc, Method if ext.arity == 1 ext.call(task_name) else @@ -289,7 +302,7 @@ module Rake end class << self - attr_accessor :record_task_metadata + attr_accessor :record_task_metadata # :nodoc: TaskManager.record_task_metadata = false end end diff --git a/lib/rake/tasklib.rb b/lib/rake/tasklib.rb index 48d27df9ed..6203d9402b 100644 --- a/lib/rake/tasklib.rb +++ b/lib/rake/tasklib.rb @@ -14,6 +14,8 @@ module Rake # libraries depend on this so I can't remove it without breaking # other people's code. So for now it stays for backwards # compatibility. BUT DON'T USE IT. + #-- + # TODO: Remove in Rake 11 def paste(a, b) # :nodoc: (a.to_s + b.to_s).intern end diff --git a/lib/rake/testtask.rb b/lib/rake/testtask.rb index c693dd2626..2daa589634 100644 --- a/lib/rake/testtask.rb +++ b/lib/rake/testtask.rb @@ -1,5 +1,3 @@ -# Define a task library for running unit tests. - require 'rake' require 'rake/tasklib' @@ -67,6 +65,9 @@ module Rake # Array of commandline options to pass to ruby when running test loader. attr_accessor :ruby_opts + # Description of the test task. (default is 'Run tests') + attr_accessor :description + # Explicitly define the list of test files to be included in a # test. +list+ is expected to be an array of file names (a # FileList is acceptable). If both +pattern+ and +test_files+ are @@ -86,6 +87,7 @@ module Rake @warning = false @loader = :rake @ruby_opts = [] + @description = "Run tests" + (@name == :test ? "" : " for #{@name}") yield self if block_given? @pattern = 'test/test*.rb' if @pattern.nil? && @test_files.nil? define @@ -93,7 +95,7 @@ module Rake # Create the tasks defined by this task lib. def define - desc "Run tests" + (@name == :test ? "" : " for #{@name}") + desc @description task @name do FileUtilsExt.verbose(@verbose) do args = @@ -121,18 +123,18 @@ module Rake "") end - def ruby_opts_string + def ruby_opts_string # :nodoc: opts = @ruby_opts.dup opts.unshift("-I\"#{lib_path}\"") unless @libs.empty? opts.unshift("-w") if @warning opts.join(" ") end - def lib_path + def lib_path # :nodoc: @libs.join(File::PATH_SEPARATOR) end - def file_list_string + def file_list_string # :nodoc: file_list.map { |fn| "\"#{fn}\"" }.join(' ') end @@ -156,18 +158,18 @@ module Rake end || '' end - def ruby_version + def ruby_version # :nodoc: RUBY_VERSION end - def run_code + def run_code # :nodoc: case @loader when :direct "-e \"ARGV.each{|f| require f}\"" when :testrb "-S testrb #{fix}" when :rake - "-I\"#{rake_lib_dir}\" \"#{rake_loader}\"" + "#{rake_include_arg} \"#{rake_loader}\"" end end @@ -184,6 +186,15 @@ module Rake nil end + def rake_include_arg # :nodoc: + spec = Gem.loaded_specs['rake'] + if spec.respond_to?(:default_gem?) && spec.default_gem? + "" + else + "-I\"#{rake_lib_dir}\"" + end + end + def rake_lib_dir # :nodoc: find_dir('rake') or fail "unable to find rake lib" diff --git a/lib/rake/thread_pool.rb b/lib/rake/thread_pool.rb index 44bc7483e4..d2ac6e7ac2 100644 --- a/lib/rake/thread_pool.rb +++ b/lib/rake/thread_pool.rb @@ -5,10 +5,10 @@ require 'rake/promise' module Rake - class ThreadPool # :nodoc: all + class ThreadPool # :nodoc: all - # Creates a ThreadPool object. - # The parameter is the size of the pool. + # Creates a ThreadPool object. The +thread_count+ parameter is the size + # of the pool. def initialize(thread_count) @max_active_threads = [thread_count, 0].max @threads = Set.new @@ -25,9 +25,9 @@ module Rake # Creates a future executed by the +ThreadPool+. # # The args are passed to the block when executing (similarly to - # Thread#new) The return value is an object representing + # Thread#new) The return value is an object representing # a future which has been created and added to the queue in the - # pool. Sending #value to the object will sleep the + # pool. Sending #value to the object will sleep the # current thread until the future is finished and will return the # result (or raise an exception thrown from the future) def future(*args, &block) @@ -109,13 +109,19 @@ module Rake false end + def safe_thread_count + @threads_mon.synchronize do + @threads.count + end + end + def start_thread # :nodoc: @threads_mon.synchronize do next unless @threads.count < @max_active_threads t = Thread.new do begin - while @threads.count <= @max_active_threads + while safe_thread_count <= @max_active_threads break unless process_queue_item end ensure @@ -126,6 +132,7 @@ module Rake end end end + @threads << t stat( :spawned, @@ -152,10 +159,6 @@ module Rake def __queue__ # :nodoc: @queue end - - def __threads__ # :nodoc: - @threads.dup - end end end diff --git a/lib/rake/trace_output.rb b/lib/rake/trace_output.rb index 1cd19451ca..396096d4df 100644 --- a/lib/rake/trace_output.rb +++ b/lib/rake/trace_output.rb @@ -1,5 +1,5 @@ module Rake - module TraceOutput + module TraceOutput # :nodoc: all # Write trace output to output stream +out+. # diff --git a/lib/rake/version.rb b/lib/rake/version.rb index 05c934d785..b9b1b2d485 100644 --- a/lib/rake/version.rb +++ b/lib/rake/version.rb @@ -1,6 +1,4 @@ module Rake - VERSION = '10.1.0' - module Version # :nodoc: all MAJOR, MINOR, BUILD, *OTHER = Rake::VERSION.split '.' diff --git a/lib/rake/win32.rb b/lib/rake/win32.rb index edb33938b4..6b4873da2c 100644 --- a/lib/rake/win32.rb +++ b/lib/rake/win32.rb @@ -4,7 +4,7 @@ module Rake # Win 32 interface methods for Rake. Windows specific functionality # will be placed here to collect that knowledge in one spot. - module Win32 + module Win32 # :nodoc: all # Error indicating a problem in locating the home directory on a # Win32 system. diff --git a/test/rake/support/rakefile_definitions.rb b/test/rake/support/rakefile_definitions.rb index 5cc2ae1293..d4311425f1 100644 --- a/test/rake/support/rakefile_definitions.rb +++ b/test/rake/support/rakefile_definitions.rb @@ -41,6 +41,16 @@ end ACCESS end + def rakefile_test_task + rakefile <<-RAKEFILE + require "rake/testtask" + + Rake::TestTask.new(:unit) do |t| + t.description = "custom test task description" + end + RAKEFILE + end + def rakefile_chains rakefile <<-DEFAULT task :default => "play.app" @@ -217,6 +227,30 @@ default: other end end + def rakefile_regenerate_imports + rakefile <<-REGENERATE_IMPORTS +task :default + +task :regenerate do + open("deps", "w") do |f| + f << <<-CONTENT +file "deps" => :regenerate +puts "REGENERATED" + CONTENT + end +end + +import "deps" + REGENERATE_IMPORTS + + open "deps", "w" do |f| + f << <<-CONTENT +file "deps" => :regenerate +puts "INITIAL" + CONTENT + end + end + def rakefile_multidesc rakefile <<-MULTIDESC task :b diff --git a/test/rake/test_rake_application.rb b/test/rake/test_rake_application.rb index aa5ed39f80..1532be1c9b 100644 --- a/test/rake/test_rake_application.rb +++ b/test/rake/test_rake_application.rb @@ -9,6 +9,79 @@ class TestRakeApplication < Rake::TestCase @app.options.rakelib = [] end + def setup_command_line(*options) + ARGV.clear + options.each do |option| + ARGV << option + end + end + + def test_display_exception_details + begin + raise 'test' + rescue => ex + end + + out, err = capture_io do + @app.display_error_message ex + end + + assert_empty out + + assert_match 'rake aborted!', err + assert_match __method__.to_s, err + end + + def test_display_exception_details_cause + skip 'Exception#cause not implemented' unless + Exception.method_defined? :cause + + begin + raise 'cause a' + rescue + begin + raise 'cause b' + rescue => ex + end + end + + out, err = capture_io do + @app.display_error_message ex + end + + assert_empty out + + assert_match 'cause a', err + assert_match 'cause b', err + end + + def test_display_exception_details_cause_loop + skip 'Exception#cause not implemented' unless + Exception.method_defined? :cause + + begin + begin + raise 'cause a' + rescue => a + begin + raise 'cause b' + rescue + raise a + end + end + rescue => ex + end + + out, err = capture_io do + @app.display_error_message ex + end + + assert_empty out + + assert_match 'cause a', err + assert_match 'cause b', err + end + def test_display_tasks @app.options.show_tasks = :tasks @app.options.show_task_pattern = // @@ -193,6 +266,7 @@ class TestRakeApplication < Rake::TestCase end def test_load_rakefile_not_found + ARGV.clear Dir.chdir @tempdir ENV['RAKE_SYSTEM'] = 'not_exist' @@ -201,8 +275,11 @@ class TestRakeApplication < Rake::TestCase options.silent = true end + ex = assert_raises(RuntimeError) do - @app.instance_eval do raw_load_rakefile end + @app.instance_eval do + raw_load_rakefile + end end assert_match(/no rakefile found/i, ex.message) @@ -295,8 +372,7 @@ class TestRakeApplication < Rake::TestCase assert !@app.options.trace valid_option = '--trace' - ARGV.clear - ARGV << valid_option + setup_command_line(valid_option) @app.handle_options @@ -305,8 +381,7 @@ class TestRakeApplication < Rake::TestCase end def test_handle_options_trace_default_is_stderr - ARGV.clear - ARGV << "--trace" + setup_command_line("--trace") @app.handle_options @@ -315,8 +390,7 @@ class TestRakeApplication < Rake::TestCase end def test_handle_options_trace_overrides_to_stdout - ARGV.clear - ARGV << "--trace=stdout" + setup_command_line("--trace=stdout") @app.handle_options @@ -327,8 +401,7 @@ class TestRakeApplication < Rake::TestCase def test_handle_options_trace_does_not_eat_following_task_names assert !@app.options.trace - ARGV.clear - ARGV << "--trace" << "sometask" + setup_command_line("--trace", "sometask") @app.handle_options assert ARGV.include?("sometask") @@ -359,8 +432,7 @@ class TestRakeApplication < Rake::TestCase def test_display_task_run ran = false - ARGV.clear - ARGV << '-f' << '-s' << '--tasks' << '--rakelib=""' + setup_command_line('-f', '-s', '--tasks', '--rakelib=""') @app.last_description = "COMMENT" @app.define_task(Rake::Task, "default") out, = capture_io { @app.run } @@ -372,8 +444,7 @@ class TestRakeApplication < Rake::TestCase def test_display_prereqs ran = false - ARGV.clear - ARGV << '-f' << '-s' << '--prereqs' << '--rakelib=""' + setup_command_line('-f', '-s', '--prereqs', '--rakelib=""') @app.last_description = "COMMENT" t = @app.define_task(Rake::Task, "default") t.enhance([:a, :b]) @@ -389,44 +460,99 @@ class TestRakeApplication < Rake::TestCase def test_bad_run @app.intern(Rake::Task, "default").enhance { fail } - ARGV.clear - ARGV << '-f' << '-s' << '--rakelib=""' - assert_raises(SystemExit) { - _, err = capture_io { @app.run } - assert_match(/see full trace/, err) + setup_command_line('-f', '-s', '--rakelib=""') + _, err = capture_io { + assert_raises(SystemExit){ @app.run } } + assert_match(/see full trace/i, err) ensure ARGV.clear end def test_bad_run_with_trace @app.intern(Rake::Task, "default").enhance { fail } - ARGV.clear - ARGV << '-f' << '-s' << '-t' - assert_raises(SystemExit) { - _, err = capture_io { @app.run } - refute_match(/see full trace/, err) + setup_command_line('-f', '-s', '-t') + _, err = capture_io { + assert_raises(SystemExit) { @app.run } } + refute_match(/see full trace/i, err) ensure ARGV.clear end def test_bad_run_with_backtrace @app.intern(Rake::Task, "default").enhance { fail } + setup_command_line('-f', '-s', '--backtrace') + _, err = capture_io { + assert_raises(SystemExit) { + @app.run + } + } + refute_match(/see full trace/, err) + ensure ARGV.clear - ARGV << '-f' << '-s' << '--backtrace' - assert_raises(SystemExit) { - _, err = capture_io { @app.run } - refute_match(/see full trace/, err) + end + + CustomError = Class.new(RuntimeError) + + def test_bad_run_includes_exception_name + @app.intern(Rake::Task, "default").enhance { + raise CustomError, "intentional" + } + setup_command_line('-f', '-s') + _, err = capture_io { + assert_raises(SystemExit) { + @app.run + } } + assert_match(/CustomError: intentional/, err) + end + + def test_rake_error_excludes_exception_name + @app.intern(Rake::Task, "default").enhance { + fail "intentional" + } + setup_command_line('-f', '-s') + _, err = capture_io { + assert_raises(SystemExit) { + @app.run + } + } + refute_match(/RuntimeError/, err) + assert_match(/intentional/, err) + end + + def cause_supported? + ex = StandardError.new + ex.respond_to?(:cause) + end + + def test_printing_original_exception_cause + custom_error = Class.new(StandardError) + @app.intern(Rake::Task, "default").enhance { + begin + raise custom_error, "Original Error" + rescue custom_error + raise custom_error, "Secondary Error" + end + } + setup_command_line('-f', '-s') + _ ,err = capture_io { + assert_raises(SystemExit) { + @app.run + } + } + if cause_supported? + assert_match(/Original Error/, err) + end + assert_match(/Secondary Error/, err) ensure ARGV.clear end def test_run_with_bad_options @app.intern(Rake::Task, "default").enhance { fail } - ARGV.clear - ARGV << '-f' << '-s' << '--xyzzy' + setup_command_line('-f', '-s', '--xyzzy') assert_raises(SystemExit) { capture_io { @app.run } } @@ -500,14 +626,12 @@ class TestRakeApplication < Rake::TestCase loader.instance_variable_set :@load_called, false def loader.load arg - raise 'called more than once' if @load_called raise ArgumentError, arg unless arg == 'x.dummy' @load_called = true end loader.instance_variable_set :@make_dummy_called, false def loader.make_dummy - raise 'called more than once' if @make_dummy_called @make_dummy_called = true end diff --git a/test/rake/test_rake_application_options.rb b/test/rake/test_rake_application_options.rb index b3220b8a97..a9ae4d9c00 100644 --- a/test/rake/test_rake_application_options.rb +++ b/test/rake/test_rake_application_options.rb @@ -111,14 +111,23 @@ class TestRakeApplicationOptions < Rake::TestCase end def test_jobs + flags([]) do |opts| + assert_nil opts.thread_pool_size + end + flags(['--jobs', '0'], ['-j', '0']) do |opts| + assert_equal 0, opts.thread_pool_size + end + flags(['--jobs', '1'], ['-j', '1']) do |opts| + assert_equal 0, opts.thread_pool_size + end flags(['--jobs', '4'], ['-j', '4']) do |opts| - assert_equal 4, opts.thread_pool_size + assert_equal 3, opts.thread_pool_size end flags(['--jobs', 'asdas'], ['-j', 'asdas']) do |opts| - assert_equal 2, opts.thread_pool_size + assert_equal Rake.suggested_thread_count-1, opts.thread_pool_size end flags('--jobs', '-j') do |opts| - assert_equal 2, opts.thread_pool_size + assert opts.thread_pool_size > 1_000_000, "thread pool size should be huge (was #{opts.thread_pool_size})" end end @@ -449,7 +458,7 @@ class TestRakeApplicationOptions < Rake::TestCase end @app.instance_eval do handle_options - collect_tasks + collect_command_line_tasks end @tasks = @app.top_level_tasks @app.options diff --git a/test/rake/test_rake_backtrace.rb b/test/rake/test_rake_backtrace.rb index 8db3b5ab54..a60f251cc9 100644 --- a/test/rake/test_rake_backtrace.rb +++ b/test/rake/test_rake_backtrace.rb @@ -12,6 +12,9 @@ class TestBacktraceSuppression < Rake::TestCase def test_system_dir_suppressed path = RbConfig::CONFIG['rubylibprefix'] + skip if path.nil? + path = File.expand_path path + paths = [path + ":12"] actual = Rake::Backtrace.collapse(paths) @@ -21,6 +24,9 @@ class TestBacktraceSuppression < Rake::TestCase def test_near_system_dir_isnt_suppressed path = RbConfig::CONFIG['rubylibprefix'] + skip if path.nil? + path = File.expand_path path + paths = [" " + path + ":12"] actual = Rake::Backtrace.collapse(paths) diff --git a/test/rake/test_rake_clean.rb b/test/rake/test_rake_clean.rb index 5e38950d38..0bce7bc0b1 100644 --- a/test/rake/test_rake_clean.rb +++ b/test/rake/test_rake_clean.rb @@ -15,7 +15,7 @@ class TestRakeClean < Rake::TestCase file_name = create_undeletable_file out, _ = capture_io do - Rake::Cleaner.cleanup(file_name, verbose: false) + Rake::Cleaner.cleanup(file_name, :verbose => false) end assert_match(/failed to remove/i, out) @@ -23,6 +23,15 @@ class TestRakeClean < Rake::TestCase remove_undeletable_file end + def test_cleanup_ignores_missing_files + file_name = File.join(@tempdir, "missing_directory", "no_such_file") + + out, _ = capture_io do + Rake::Cleaner.cleanup(file_name, :verbose => false) + end + refute_match(/failed to remove/i, out) + end + private def create_undeletable_file @@ -46,7 +55,7 @@ class TestRakeClean < Rake::TestCase file_name = File.join(dir_name, "deleteme") FileUtils.chmod(0777, dir_name) FileUtils.chmod(0777, file_name) - Rake::Cleaner.cleanup(file_name, verbose: false) - Rake::Cleaner.cleanup(dir_name, verbose: false) + Rake::Cleaner.cleanup(file_name, :verbose => false) + Rake::Cleaner.cleanup(dir_name, :verbose => false) end end diff --git a/test/rake/test_rake_cpu_counter.rb b/test/rake/test_rake_cpu_counter.rb new file mode 100644 index 0000000000..ccf21d8ba6 --- /dev/null +++ b/test/rake/test_rake_cpu_counter.rb @@ -0,0 +1,50 @@ +require File.expand_path('../helper', __FILE__) + +class TestRakeCpuCounter < Rake::TestCase + + def setup + super + + @cpu_counter = Rake::CpuCounter.new + end + + def test_count_via_win32 + if Rake::Win32.windows? then + assert_kind_of Numeric, @cpu_counter.count_via_win32 + else + assert_nil @cpu_counter.count_via_win32 + end + end + + def test_in_path_command + with_ruby_in_path do |ruby| + assert_equal ruby, @cpu_counter.in_path_command(ruby) + end + rescue Errno::ENOENT => e + raise unless e.message =~ /\bwhich\b/ + + skip 'cannot find which for this test' + end + + def test_run + with_ruby_in_path do |ruby| + assert_equal 7, @cpu_counter.run(ruby, '-e', 'puts 3 + 4') + end + end + + def with_ruby_in_path + ruby = File.basename Gem.ruby + ruby_dir = File.dirname Gem.ruby + + begin + orig_path, ENV['PATH'] = + ENV['PATH'], [ruby_dir, *ENV['PATH']].join(File::PATH_SEPARATOR) + + yield ruby + ensure + ENV['PATH'] = orig_path + end + end + +end + diff --git a/test/rake/test_rake_directory_task.rb b/test/rake/test_rake_directory_task.rb index 8ae7537b50..c8275e6d10 100644 --- a/test/rake/test_rake_directory_task.rb +++ b/test/rake/test_rake_directory_task.rb @@ -25,6 +25,12 @@ class TestRakeDirectoryTask < Rake::TestCase refute File.exist?("a/b/c") end + def test_directory_colon + directory "a:b" + + assert_equal FileCreationTask, Task['a:b'].class + end unless Rake::Win32.windows? + if Rake::Win32.windows? def test_directory_win32 desc "WIN32 DESC" diff --git a/test/rake/test_rake_file_task.rb b/test/rake/test_rake_file_task.rb index fa3241b78b..ae828c9ba1 100644 --- a/test/rake/test_rake_file_task.rb +++ b/test/rake/test_rake_file_task.rb @@ -98,6 +98,70 @@ class TestRakeFileTask < Rake::TestCase assert @ran end + def test_needed_eh_build_all + create_file 'a' + + file 'a' + + a_task = Task['a'] + + refute a_task.needed? + + Rake.application.options.build_all = true + + assert a_task.needed? + ensure + delete_file 'a' + end + + def test_needed_eh_dependency + create_file 'a', Time.now + create_file 'b', Time.now - 60 + + create_file 'c', Time.now + create_file 'd', Time.now - 60 + + file 'b' => 'a' + + b_task = Task['b'] + + assert b_task.needed? + + file 'c' => 'd' + + c_task = Task['c'] + + refute c_task.needed? + ensure + delete_file 'old' + delete_file 'new' + end + + def test_needed_eh_exists + name = "dummy" + file name + + ftask = Task[name] + + assert ftask.needed? + + create_file name + + refute ftask.needed? + ensure + delete_file name + end + + def test_source_is_first_prerequisite + t = file :f => ["preqA", "preqB"] + assert_equal "preqA", t.source + end + + def test_sources_is_all_prerequisites + t = file :f => ["preqA", "preqB"] + assert_equal ["preqA", "preqB"], t.sources + end + # I have currently disabled this test. I'm not convinced that # deleting the file target on failure is always the proper thing to # do. I'm willing to hear input on this topic. diff --git a/test/rake/test_rake_functional.rb b/test/rake/test_rake_functional.rb index f2ce2f78f0..bf7ba92f75 100644 --- a/test/rake/test_rake_functional.rb +++ b/test/rake/test_rake_functional.rb @@ -268,6 +268,14 @@ class TestRakeFunctional < Rake::TestCase assert_match(/^FIRST$\s+^DYNAMIC$\s+^STATIC$\s+^OTHER$/, @out) end + def test_regenerate_imports + rakefile_regenerate_imports + + rake + + assert_match(/^INITIAL\s+^REGENERATED$/, @out) + end + def test_rules_chaining_to_file_task rakefile_chains @@ -368,6 +376,14 @@ class TestRakeFunctional < Rake::TestCase assert_match(/^PREPARE\nSCOPEDEP$/m, @out) end + def test_test_task_descriptions + rakefile_test_task + + rake "-T" + + assert_match(/custom test task description/, @out) + end + def test_comment_before_task_acts_like_desc rakefile_comments @@ -414,7 +430,7 @@ class TestRakeFunctional < Rake::TestCase end def can_detect_signals? - system "ruby -e 'Process.kill \"TERM\", $$'" + system RUBY, '-e', 'Process.kill "TERM", $$' status = $? if @verbose puts " SIG status = #{$?.inspect}" diff --git a/test/rake/test_rake_name_space.rb b/test/rake/test_rake_name_space.rb index 3ab977d013..d35e70e175 100644 --- a/test/rake/test_rake_name_space.rb +++ b/test/rake/test_rake_name_space.rb @@ -40,4 +40,18 @@ class TestRakeNameSpace < Rake::TestCase ns.tasks.map { |tsk| tsk.name } assert_equal ["n:nn:z"], nns.tasks.map { |t| t.name } end + + def test_scope + mgr = TM.new + + scope = Rake::LinkedList.new 'b' + scope = scope.conj 'a' + + ns = Rake::NameSpace.new mgr, scope + + assert_equal scope, ns.scope + + refute_same scope, ns.scope + end + end diff --git a/test/rake/test_rake_path_map.rb b/test/rake/test_rake_path_map.rb index b76a9491f9..038ba1f9a7 100644 --- a/test/rake/test_rake_path_map.rb +++ b/test/rake/test_rake_path_map.rb @@ -156,8 +156,8 @@ class TestRakePathMap < Rake::TestCase "src/org/onstepback/proj/A.java".pathmap("%{src,bin}d/%n.class")) assert_equal( "src_work/bin/org/onstepback/proj/A.class", - "src_work/src/org/onstepback/proj/A.java" - .pathmap('%{\bsrc\b,bin}X.class')) + "src_work/src/org/onstepback/proj/A.java". + pathmap('%{\bsrc\b,bin}X.class')) assert_equal( ".depends.bak", ".depends".pathmap("%X.bak")) diff --git a/test/rake/test_rake_rules.rb b/test/rake/test_rake_rules.rb index 376b99889c..ece75e5d9e 100644 --- a/test/rake/test_rake_rules.rb +++ b/test/rake/test_rake_rules.rb @@ -359,4 +359,30 @@ class TestRakeRules < Rake::TestCase Task[OBJFILE].invoke('arg') end + def test_rule_with_method_prereq + create_file(".foo") + obj = Object.new + def obj.find_prereq + ".foo" + end + rule '.o' => obj.method(:find_prereq) do |t| + @runs << "#{t.name} - #{t.source}" + end + Task[OBJFILE].invoke + assert_equal ["#{OBJFILE} - .foo"], @runs + end + + def test_rule_with_one_arg_method_prereq + create_file(SRCFILE) + obj = Object.new + def obj.find_prereq(task_name) + task_name.ext(".c") + end + rule '.o' => obj.method(:find_prereq) do |t| + @runs << "#{t.name} - #{t.source}" + end + Task[OBJFILE].invoke + assert_equal ["#{OBJFILE} - abc.c"], @runs + end + end diff --git a/test/rake/test_rake_task.rb b/test/rake/test_rake_task.rb index ed5f1b1e11..d7f14efcdb 100644 --- a/test/rake/test_rake_task.rb +++ b/test/rake/test_rake_task.rb @@ -333,6 +333,17 @@ class TestRakeTask < Rake::TestCase assert_equal "Revision 1.2.3", t.comment end + def test_comments_do_not_set + t = task(:t, :name, :rev) + assert_equal nil, t.comment + end + + def test_comments_is_nil + t = task(:t, :name, :rev) + t.comment = nil + assert_equal nil, t.comment + end + def test_extended_comments desc %{ This is a comment. @@ -374,4 +385,9 @@ class TestRakeTask < Rake::TestCase task(:t) assert_equal "line one / line two", t.comment end + + def test_source_is_first_prerequisite + t = task :t => ["preqA", "preqB"] + assert_equal "preqA", t.source + end end diff --git a/test/rake/test_rake_task_argument_parsing.rb b/test/rake/test_rake_task_argument_parsing.rb index 9b99991de9..0294a9fb2c 100644 --- a/test/rake/test_rake_task_argument_parsing.rb +++ b/test/rake/test_rake_task_argument_parsing.rb @@ -43,6 +43,12 @@ class TestRakeTaskArgumentParsing < Rake::TestCase assert_equal ["a one ana", "two"], args end + def test_can_handle_commas_in_args + name, args = @app.parse_task_string("name[one, two, three_a\\, three_b, four]") + assert_equal "name", name + assert_equal ["one", "two", "three_a, three_b", "four"], args + end + def test_terminal_width_using_env app = Rake::Application.new app.terminal_columns = 1234 diff --git a/test/rake/test_rake_task_arguments.rb b/test/rake/test_rake_task_arguments.rb index 061178e23e..369ecf6e5c 100644 --- a/test/rake/test_rake_task_arguments.rb +++ b/test/rake/test_rake_task_arguments.rb @@ -19,6 +19,12 @@ class TestRakeTaskArguments < Rake::TestCase assert_equal({:a => :one, :b => :two, :c => :three}, ta.to_hash) end + def test_has_key + ta = Rake::TaskArguments.new([:a], [:one]) + assert(ta.has_key?(:a)) + refute(ta.has_key?(:b)) + end + def test_to_s ta = Rake::TaskArguments.new([:a, :b, :c], [1, 2, 3]) assert_equal ta.to_hash.inspect, ta.to_s diff --git a/test/rake/test_rake_task_manager.rb b/test/rake/test_rake_task_manager.rb index 5ec4c0e65c..c2730b67e2 100644 --- a/test/rake/test_rake_task_manager.rb +++ b/test/rake/test_rake_task_manager.rb @@ -40,6 +40,23 @@ class TestRakeTaskManager < Rake::TestCase assert_equal ["x:t"], @tm.tasks.map { |t| t.name } end + def test_define_namespaced_task + t = @tm.define_task(Rake::Task, 'n:a:m:e:t') + assert_equal Rake::Scope.make("e", "m", "a", "n"), t.scope + assert_equal "n:a:m:e:t", t.name + assert_equal @tm, t.application + end + + def test_define_namespace_in_namespace + t = nil + @tm.in_namespace("n") do + t = @tm.define_task(Rake::Task, 'a:m:e:t') + end + assert_equal Rake::Scope.make("e", "m", "a", "n"), t.scope + assert_equal "n:a:m:e:t", t.name + assert_equal @tm, t.application + end + def test_anonymous_namespace anon_ns = @tm.in_namespace(nil) do t = @tm.define_task(Rake::Task, :t) @@ -89,6 +106,7 @@ class TestRakeTaskManager < Rake::TestCase @tm.in_namespace("a") do aa = @tm.define_task(Rake::Task, :aa) mid_z = @tm.define_task(Rake::Task, :z) + ns_d = @tm.define_task(Rake::Task, "n:t") @tm.in_namespace("b") do bb = @tm.define_task(Rake::Task, :bb) bot_z = @tm.define_task(Rake::Task, :z) @@ -116,6 +134,8 @@ class TestRakeTaskManager < Rake::TestCase assert_equal top_z, @tm["^z"] assert_equal top_z, @tm["^^z"] # Over the top assert_equal top_z, @tm["rake:z"] + assert_equal ns_d, @tm["n:t"] + assert_equal ns_d, @tm["a:n:t"] end assert_equal Rake::Scope.make, @tm.current_scope diff --git a/test/rake/test_rake_test_task.rb b/test/rake/test_rake_test_task.rb index 637accc291..9b500dc044 100644 --- a/test/rake/test_rake_test_task.rb +++ b/test/rake/test_rake_test_task.rb @@ -16,11 +16,13 @@ class TestRakeTestTask < Rake::TestCase def test_initialize_override tt = Rake::TestTask.new(:example) do |t| + t.description = "Run example tests" t.libs = ['src', 'ext'] t.pattern = 'test/tc_*.rb' t.verbose = true end refute_nil tt + assert_equal "Run example tests", tt.description assert_equal :example, tt.name assert_equal ['src', 'ext'], tt.libs assert_equal 'test/tc_*.rb', tt.pattern @@ -81,11 +83,31 @@ class TestRakeTestTask < Rake::TestCase end def test_run_code_rake + spec = Gem::Specification.new 'rake', 0 + spec.loaded_from = File.join Gem::Specification.dirs.last, 'rake-0.gemspec' + rake, Gem.loaded_specs['rake'] = Gem.loaded_specs['rake'], spec + + test_task = Rake::TestTask.new do |t| + t.loader = :rake + end + + assert_match(/\A-I".*?" ".*?"\Z/, test_task.run_code) + ensure + Gem.loaded_specs['rake'] = rake + end + + def test_run_code_rake_default_gem + default_spec = Gem::Specification.new 'rake', 0 + default_spec.loaded_from = File.join Gem::Specification.default_specifications_dir, 'rake-0.gemspec' + rake, Gem.loaded_specs['rake'] = Gem.loaded_specs['rake'], default_spec + test_task = Rake::TestTask.new do |t| t.loader = :rake end - assert_match(/-I".*?" ".*?"/, test_task.run_code) + assert_match(/\A ".*?"\Z/, test_task.run_code) + ensure + Gem.loaded_specs['rake'] = rake end def test_run_code_testrb_ruby_1_8_2 -- cgit v1.2.3