rake 13.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/macos.yml +22 -0
  3. data/.github/workflows/ubuntu-rvm.yml +28 -0
  4. data/.github/workflows/ubuntu.yml +20 -0
  5. data/.github/workflows/windows.yml +20 -0
  6. data/CONTRIBUTING.rdoc +43 -0
  7. data/Gemfile +10 -0
  8. data/History.rdoc +2359 -0
  9. data/MIT-LICENSE +21 -0
  10. data/README.rdoc +155 -0
  11. data/Rakefile +41 -0
  12. data/bin/bundle +105 -0
  13. data/bin/console +7 -0
  14. data/bin/rake +29 -0
  15. data/bin/rdoc +29 -0
  16. data/bin/rubocop +29 -0
  17. data/bin/setup +6 -0
  18. data/doc/command_line_usage.rdoc +158 -0
  19. data/doc/example/Rakefile1 +38 -0
  20. data/doc/example/Rakefile2 +35 -0
  21. data/doc/example/a.c +6 -0
  22. data/doc/example/b.c +6 -0
  23. data/doc/example/main.c +11 -0
  24. data/doc/glossary.rdoc +42 -0
  25. data/doc/jamis.rb +592 -0
  26. data/doc/proto_rake.rdoc +127 -0
  27. data/doc/rake.1 +156 -0
  28. data/doc/rakefile.rdoc +622 -0
  29. data/doc/rational.rdoc +151 -0
  30. data/exe/rake +27 -0
  31. data/lib/rake.rb +71 -0
  32. data/lib/rake/application.rb +824 -0
  33. data/lib/rake/backtrace.rb +24 -0
  34. data/lib/rake/clean.rb +78 -0
  35. data/lib/rake/cloneable.rb +17 -0
  36. data/lib/rake/cpu_counter.rb +107 -0
  37. data/lib/rake/default_loader.rb +15 -0
  38. data/lib/rake/dsl_definition.rb +195 -0
  39. data/lib/rake/early_time.rb +22 -0
  40. data/lib/rake/ext/core.rb +26 -0
  41. data/lib/rake/ext/string.rb +176 -0
  42. data/lib/rake/file_creation_task.rb +25 -0
  43. data/lib/rake/file_list.rb +435 -0
  44. data/lib/rake/file_task.rb +54 -0
  45. data/lib/rake/file_utils.rb +134 -0
  46. data/lib/rake/file_utils_ext.rb +134 -0
  47. data/lib/rake/invocation_chain.rb +57 -0
  48. data/lib/rake/invocation_exception_mixin.rb +17 -0
  49. data/lib/rake/late_time.rb +18 -0
  50. data/lib/rake/linked_list.rb +112 -0
  51. data/lib/rake/loaders/makefile.rb +54 -0
  52. data/lib/rake/multi_task.rb +14 -0
  53. data/lib/rake/name_space.rb +38 -0
  54. data/lib/rake/packagetask.rb +222 -0
  55. data/lib/rake/phony.rb +16 -0
  56. data/lib/rake/private_reader.rb +21 -0
  57. data/lib/rake/promise.rb +100 -0
  58. data/lib/rake/pseudo_status.rb +30 -0
  59. data/lib/rake/rake_module.rb +67 -0
  60. data/lib/rake/rake_test_loader.rb +27 -0
  61. data/lib/rake/rule_recursion_overflow_error.rb +20 -0
  62. data/lib/rake/scope.rb +43 -0
  63. data/lib/rake/task.rb +433 -0
  64. data/lib/rake/task_argument_error.rb +8 -0
  65. data/lib/rake/task_arguments.rb +109 -0
  66. data/lib/rake/task_manager.rb +328 -0
  67. data/lib/rake/tasklib.rb +12 -0
  68. data/lib/rake/testtask.rb +224 -0
  69. data/lib/rake/thread_history_display.rb +49 -0
  70. data/lib/rake/thread_pool.rb +163 -0
  71. data/lib/rake/trace_output.rb +23 -0
  72. data/lib/rake/version.rb +10 -0
  73. data/lib/rake/win32.rb +51 -0
  74. data/rake.gemspec +36 -0
  75. metadata +132 -0
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+ require "rake"
3
+ require "rake/tasklib"
4
+
5
+ module Rake
6
+
7
+ # Create a task that runs a set of tests.
8
+ #
9
+ # Example:
10
+ # require "rake/testtask"
11
+ #
12
+ # Rake::TestTask.new do |t|
13
+ # t.libs << "test"
14
+ # t.test_files = FileList['test/test*.rb']
15
+ # t.verbose = true
16
+ # end
17
+ #
18
+ # If rake is invoked with a "TEST=filename" command line option,
19
+ # then the list of test files will be overridden to include only the
20
+ # filename specified on the command line. This provides an easy way
21
+ # to run just one test.
22
+ #
23
+ # If rake is invoked with a "TESTOPTS=options" command line option,
24
+ # then the given options are passed to the test process after a
25
+ # '--'. This allows Test::Unit options to be passed to the test
26
+ # suite.
27
+ #
28
+ # Examples:
29
+ #
30
+ # rake test # run tests normally
31
+ # rake test TEST=just_one_file.rb # run just one test file.
32
+ # rake test TESTOPTS="-v" # run in verbose mode
33
+ # rake test TESTOPTS="--runner=fox" # use the fox test runner
34
+ #
35
+ class TestTask < TaskLib
36
+
37
+ # Name of test task. (default is :test)
38
+ attr_accessor :name
39
+
40
+ # List of directories added to $LOAD_PATH before running the
41
+ # tests. (default is 'lib')
42
+ attr_accessor :libs
43
+
44
+ # True if verbose test output desired. (default is false)
45
+ attr_accessor :verbose
46
+
47
+ # Test options passed to the test suite. An explicit
48
+ # TESTOPTS=opts on the command line will override this. (default
49
+ # is NONE)
50
+ attr_accessor :options
51
+
52
+ # Request that the tests be run with the warning flag set.
53
+ # E.g. warning=true implies "ruby -w" used to run the tests.
54
+ # (default is true)
55
+ attr_accessor :warning
56
+
57
+ # Glob pattern to match test files. (default is 'test/test*.rb')
58
+ attr_accessor :pattern
59
+
60
+ # Style of test loader to use. Options are:
61
+ #
62
+ # * :rake -- Rake provided test loading script (default).
63
+ # * :testrb -- Ruby provided test loading script.
64
+ # * :direct -- Load tests using command line loader.
65
+ #
66
+ attr_accessor :loader
67
+
68
+ # Array of command line options to pass to ruby when running test loader.
69
+ attr_accessor :ruby_opts
70
+
71
+ # Description of the test task. (default is 'Run tests')
72
+ attr_accessor :description
73
+
74
+ # Task prerequisites.
75
+ attr_accessor :deps
76
+
77
+ # Explicitly define the list of test files to be included in a
78
+ # test. +list+ is expected to be an array of file names (a
79
+ # FileList is acceptable). If both +pattern+ and +test_files+ are
80
+ # used, then the list of test files is the union of the two.
81
+ def test_files=(list)
82
+ @test_files = list
83
+ end
84
+
85
+ # Create a testing task.
86
+ def initialize(name=:test)
87
+ @name = name
88
+ @libs = ["lib"]
89
+ @pattern = nil
90
+ @options = nil
91
+ @test_files = nil
92
+ @verbose = false
93
+ @warning = true
94
+ @loader = :rake
95
+ @ruby_opts = []
96
+ @description = "Run tests" + (@name == :test ? "" : " for #{@name}")
97
+ @deps = []
98
+ if @name.is_a?(Hash)
99
+ @deps = @name.values.first
100
+ @name = @name.keys.first
101
+ end
102
+ yield self if block_given?
103
+ @pattern = "test/test*.rb" if @pattern.nil? && @test_files.nil?
104
+ define
105
+ end
106
+
107
+ # Create the tasks defined by this task lib.
108
+ def define
109
+ desc @description
110
+ task @name => Array(deps) do
111
+ FileUtilsExt.verbose(@verbose) do
112
+ puts "Use TESTOPTS=\"--verbose\" to pass --verbose" \
113
+ ", etc. to runners." if ARGV.include? "--verbose"
114
+ args =
115
+ "#{ruby_opts_string} #{run_code} " +
116
+ "#{file_list_string} #{option_list}"
117
+ ruby args do |ok, status|
118
+ if !ok && status.respond_to?(:signaled?) && status.signaled?
119
+ raise SignalException.new(status.termsig)
120
+ elsif !ok
121
+ status = "Command failed with status (#{status.exitstatus})"
122
+ details = ": [ruby #{args}]"
123
+ message =
124
+ if Rake.application.options.trace or @verbose
125
+ status + details
126
+ else
127
+ status
128
+ end
129
+
130
+ fail message
131
+ end
132
+ end
133
+ end
134
+ end
135
+ self
136
+ end
137
+
138
+ def option_list # :nodoc:
139
+ (ENV["TESTOPTS"] ||
140
+ ENV["TESTOPT"] ||
141
+ ENV["TEST_OPTS"] ||
142
+ ENV["TEST_OPT"] ||
143
+ @options ||
144
+ "")
145
+ end
146
+
147
+ def ruby_opts_string # :nodoc:
148
+ opts = @ruby_opts.dup
149
+ opts.unshift("-I\"#{lib_path}\"") unless @libs.empty?
150
+ opts.unshift("-w") if @warning
151
+ opts.join(" ")
152
+ end
153
+
154
+ def lib_path # :nodoc:
155
+ @libs.join(File::PATH_SEPARATOR)
156
+ end
157
+
158
+ def file_list_string # :nodoc:
159
+ file_list.map { |fn| "\"#{fn}\"" }.join(" ")
160
+ end
161
+
162
+ def file_list # :nodoc:
163
+ if ENV["TEST"]
164
+ FileList[ENV["TEST"]]
165
+ else
166
+ result = []
167
+ result += @test_files.to_a if @test_files
168
+ result += FileList[@pattern].to_a if @pattern
169
+ result
170
+ end
171
+ end
172
+
173
+ def ruby_version # :nodoc:
174
+ RUBY_VERSION
175
+ end
176
+
177
+ def run_code # :nodoc:
178
+ case @loader
179
+ when :direct
180
+ "-e \"ARGV.each{|f| require f}\""
181
+ when :testrb
182
+ "-S testrb"
183
+ when :rake
184
+ "#{rake_include_arg} \"#{rake_loader}\""
185
+ end
186
+ end
187
+
188
+ def rake_loader # :nodoc:
189
+ find_file("rake/rake_test_loader") or
190
+ fail "unable to find rake test loader"
191
+ end
192
+
193
+ def find_file(fn) # :nodoc:
194
+ $LOAD_PATH.each do |path|
195
+ file_path = File.join(path, "#{fn}.rb")
196
+ return file_path if File.exist? file_path
197
+ end
198
+ nil
199
+ end
200
+
201
+ def rake_include_arg # :nodoc:
202
+ spec = Gem.loaded_specs["rake"]
203
+ if spec.respond_to?(:default_gem?) && spec.default_gem?
204
+ ""
205
+ else
206
+ "-I\"#{rake_lib_dir}\""
207
+ end
208
+ end
209
+
210
+ def rake_lib_dir # :nodoc:
211
+ find_dir("rake") or
212
+ fail "unable to find rake lib"
213
+ end
214
+
215
+ def find_dir(fn) # :nodoc:
216
+ $LOAD_PATH.each do |path|
217
+ file_path = File.join(path, "#{fn}.rb")
218
+ return path if File.exist? file_path
219
+ end
220
+ nil
221
+ end
222
+
223
+ end
224
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ require "rake/private_reader"
3
+
4
+ module Rake
5
+
6
+ class ThreadHistoryDisplay # :nodoc: all
7
+ include Rake::PrivateReader
8
+
9
+ private_reader :stats, :items, :threads
10
+
11
+ def initialize(stats)
12
+ @stats = stats
13
+ @items = { _seq_: 1 }
14
+ @threads = { _seq_: "A" }
15
+ end
16
+
17
+ def show
18
+ puts "Job History:"
19
+ stats.each do |stat|
20
+ stat[:data] ||= {}
21
+ rename(stat, :thread, threads)
22
+ rename(stat[:data], :item_id, items)
23
+ rename(stat[:data], :new_thread, threads)
24
+ rename(stat[:data], :deleted_thread, threads)
25
+ printf("%8d %2s %-20s %s\n",
26
+ (stat[:time] * 1_000_000).round,
27
+ stat[:thread],
28
+ stat[:event],
29
+ stat[:data].map do |k, v| "#{k}:#{v}" end.join(" "))
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def rename(hash, key, renames)
36
+ if hash && hash[key]
37
+ original = hash[key]
38
+ value = renames[original]
39
+ unless value
40
+ value = renames[:_seq_]
41
+ renames[:_seq_] = renames[:_seq_].succ
42
+ renames[original] = value
43
+ end
44
+ hash[key] = value
45
+ end
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+ require "set"
3
+
4
+ require "rake/promise"
5
+
6
+ module Rake
7
+
8
+ class ThreadPool # :nodoc: all
9
+
10
+ # Creates a ThreadPool object. The +thread_count+ parameter is the size
11
+ # of the pool.
12
+ def initialize(thread_count)
13
+ @max_active_threads = [thread_count, 0].max
14
+ @threads = Set.new
15
+ @threads_mon = Monitor.new
16
+ @queue = Queue.new
17
+ @join_cond = @threads_mon.new_cond
18
+
19
+ @history_start_time = nil
20
+ @history = []
21
+ @history_mon = Monitor.new
22
+ @total_threads_in_play = 0
23
+ end
24
+
25
+ # Creates a future executed by the +ThreadPool+.
26
+ #
27
+ # The args are passed to the block when executing (similarly to
28
+ # Thread#new) The return value is an object representing
29
+ # a future which has been created and added to the queue in the
30
+ # pool. Sending #value to the object will sleep the
31
+ # current thread until the future is finished and will return the
32
+ # result (or raise an exception thrown from the future)
33
+ def future(*args, &block)
34
+ promise = Promise.new(args, &block)
35
+ promise.recorder = lambda { |*stats| stat(*stats) }
36
+
37
+ @queue.enq promise
38
+ stat :queued, item_id: promise.object_id
39
+ start_thread
40
+ promise
41
+ end
42
+
43
+ # Waits until the queue of futures is empty and all threads have exited.
44
+ def join
45
+ @threads_mon.synchronize do
46
+ begin
47
+ stat :joining
48
+ @join_cond.wait unless @threads.empty?
49
+ stat :joined
50
+ rescue Exception => e
51
+ stat :joined
52
+ $stderr.puts e
53
+ $stderr.print "Queue contains #{@queue.size} items. " +
54
+ "Thread pool contains #{@threads.count} threads\n"
55
+ $stderr.print "Current Thread #{Thread.current} status = " +
56
+ "#{Thread.current.status}\n"
57
+ $stderr.puts e.backtrace.join("\n")
58
+ @threads.each do |t|
59
+ $stderr.print "Thread #{t} status = #{t.status}\n"
60
+ $stderr.puts t.backtrace.join("\n")
61
+ end
62
+ raise e
63
+ end
64
+ end
65
+ end
66
+
67
+ # Enable the gathering of history events.
68
+ def gather_history #:nodoc:
69
+ @history_start_time = Time.now if @history_start_time.nil?
70
+ end
71
+
72
+ # Return a array of history events for the thread pool.
73
+ #
74
+ # History gathering must be enabled to be able to see the events
75
+ # (see #gather_history). Best to call this when the job is
76
+ # complete (i.e. after ThreadPool#join is called).
77
+ def history # :nodoc:
78
+ @history_mon.synchronize { @history.dup }.
79
+ sort_by { |i| i[:time] }.
80
+ each { |i| i[:time] -= @history_start_time }
81
+ end
82
+
83
+ # Return a hash of always collected statistics for the thread pool.
84
+ def statistics # :nodoc:
85
+ {
86
+ total_threads_in_play: @total_threads_in_play,
87
+ max_active_threads: @max_active_threads,
88
+ }
89
+ end
90
+
91
+ private
92
+
93
+ # processes one item on the queue. Returns true if there was an
94
+ # item to process, false if there was no item
95
+ def process_queue_item #:nodoc:
96
+ return false if @queue.empty?
97
+
98
+ # Even though we just asked if the queue was empty, it
99
+ # still could have had an item which by this statement
100
+ # is now gone. For this reason we pass true to Queue#deq
101
+ # because we will sleep indefinitely if it is empty.
102
+ promise = @queue.deq(true)
103
+ stat :dequeued, item_id: promise.object_id
104
+ promise.work
105
+ return true
106
+
107
+ rescue ThreadError # this means the queue is empty
108
+ false
109
+ end
110
+
111
+ def safe_thread_count
112
+ @threads_mon.synchronize do
113
+ @threads.count
114
+ end
115
+ end
116
+
117
+ def start_thread # :nodoc:
118
+ @threads_mon.synchronize do
119
+ next unless @threads.count < @max_active_threads
120
+
121
+ t = Thread.new do
122
+ begin
123
+ while safe_thread_count <= @max_active_threads
124
+ break unless process_queue_item
125
+ end
126
+ ensure
127
+ @threads_mon.synchronize do
128
+ @threads.delete Thread.current
129
+ stat :ended, thread_count: @threads.count
130
+ @join_cond.broadcast if @threads.empty?
131
+ end
132
+ end
133
+ end
134
+
135
+ @threads << t
136
+ stat(
137
+ :spawned,
138
+ new_thread: t.object_id,
139
+ thread_count: @threads.count)
140
+ @total_threads_in_play = @threads.count if
141
+ @threads.count > @total_threads_in_play
142
+ end
143
+ end
144
+
145
+ def stat(event, data=nil) # :nodoc:
146
+ return if @history_start_time.nil?
147
+ info = {
148
+ event: event,
149
+ data: data,
150
+ time: Time.now,
151
+ thread: Thread.current.object_id,
152
+ }
153
+ @history_mon.synchronize { @history << info }
154
+ end
155
+
156
+ # for testing only
157
+
158
+ def __queue__ # :nodoc:
159
+ @queue
160
+ end
161
+ end
162
+
163
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+ module TraceOutput # :nodoc: all
4
+
5
+ # Write trace output to output stream +out+.
6
+ #
7
+ # The write is done as a single IO call (to print) to lessen the
8
+ # chance that the trace output is interrupted by other tasks also
9
+ # producing output.
10
+ def trace_on(out, *strings)
11
+ sep = $\ || "\n"
12
+ if strings.empty?
13
+ output = sep
14
+ else
15
+ output = strings.map { |s|
16
+ next if s.nil?
17
+ s.end_with?(sep) ? s : s + sep
18
+ }.join
19
+ end
20
+ out.print(output)
21
+ end
22
+ end
23
+ end