rake 12.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.rdoc +43 -0
  3. data/Gemfile +3 -0
  4. data/History.rdoc +2344 -0
  5. data/MIT-LICENSE +21 -0
  6. data/README.rdoc +156 -0
  7. data/Rakefile +41 -0
  8. data/azure-pipelines.yml +11 -0
  9. data/bin/bundle +105 -0
  10. data/bin/console +7 -0
  11. data/bin/rake +29 -0
  12. data/bin/rdoc +29 -0
  13. data/bin/rubocop +29 -0
  14. data/bin/setup +6 -0
  15. data/doc/command_line_usage.rdoc +158 -0
  16. data/doc/example/Rakefile1 +38 -0
  17. data/doc/example/Rakefile2 +35 -0
  18. data/doc/example/a.c +6 -0
  19. data/doc/example/b.c +6 -0
  20. data/doc/example/main.c +11 -0
  21. data/doc/glossary.rdoc +42 -0
  22. data/doc/jamis.rb +592 -0
  23. data/doc/proto_rake.rdoc +127 -0
  24. data/doc/rake.1 +156 -0
  25. data/doc/rakefile.rdoc +622 -0
  26. data/doc/rational.rdoc +151 -0
  27. data/exe/rake +27 -0
  28. data/lib/rake.rb +71 -0
  29. data/lib/rake/application.rb +824 -0
  30. data/lib/rake/backtrace.rb +24 -0
  31. data/lib/rake/clean.rb +78 -0
  32. data/lib/rake/cloneable.rb +17 -0
  33. data/lib/rake/cpu_counter.rb +107 -0
  34. data/lib/rake/default_loader.rb +15 -0
  35. data/lib/rake/dsl_definition.rb +195 -0
  36. data/lib/rake/early_time.rb +22 -0
  37. data/lib/rake/ext/core.rb +26 -0
  38. data/lib/rake/ext/string.rb +176 -0
  39. data/lib/rake/file_creation_task.rb +25 -0
  40. data/lib/rake/file_list.rb +435 -0
  41. data/lib/rake/file_task.rb +54 -0
  42. data/lib/rake/file_utils.rb +137 -0
  43. data/lib/rake/file_utils_ext.rb +145 -0
  44. data/lib/rake/invocation_chain.rb +57 -0
  45. data/lib/rake/invocation_exception_mixin.rb +17 -0
  46. data/lib/rake/late_time.rb +18 -0
  47. data/lib/rake/linked_list.rb +112 -0
  48. data/lib/rake/loaders/makefile.rb +54 -0
  49. data/lib/rake/multi_task.rb +14 -0
  50. data/lib/rake/name_space.rb +38 -0
  51. data/lib/rake/packagetask.rb +207 -0
  52. data/lib/rake/phony.rb +16 -0
  53. data/lib/rake/private_reader.rb +21 -0
  54. data/lib/rake/promise.rb +100 -0
  55. data/lib/rake/pseudo_status.rb +30 -0
  56. data/lib/rake/rake_module.rb +67 -0
  57. data/lib/rake/rake_test_loader.rb +27 -0
  58. data/lib/rake/rule_recursion_overflow_error.rb +20 -0
  59. data/lib/rake/scope.rb +43 -0
  60. data/lib/rake/task.rb +413 -0
  61. data/lib/rake/task_argument_error.rb +8 -0
  62. data/lib/rake/task_arguments.rb +109 -0
  63. data/lib/rake/task_manager.rb +324 -0
  64. data/lib/rake/tasklib.rb +12 -0
  65. data/lib/rake/testtask.rb +224 -0
  66. data/lib/rake/thread_history_display.rb +49 -0
  67. data/lib/rake/thread_pool.rb +163 -0
  68. data/lib/rake/trace_output.rb +23 -0
  69. data/lib/rake/version.rb +10 -0
  70. data/lib/rake/win32.rb +51 -0
  71. data/rake.gemspec +42 -0
  72. metadata +199 -0
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+
4
+ ##
5
+ # Exit status class for times the system just gives us a nil.
6
+ class PseudoStatus # :nodoc: all
7
+ attr_reader :exitstatus
8
+
9
+ def initialize(code=0)
10
+ @exitstatus = code
11
+ end
12
+
13
+ def to_i
14
+ @exitstatus << 8
15
+ end
16
+
17
+ def >>(n)
18
+ to_i >> n
19
+ end
20
+
21
+ def stopped?
22
+ false
23
+ end
24
+
25
+ def exited?
26
+ true
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ require "rake/application"
3
+
4
+ module Rake
5
+
6
+ class << self
7
+ # Current Rake Application
8
+ def application
9
+ @application ||= Rake::Application.new
10
+ end
11
+
12
+ # Set the current Rake application object.
13
+ def application=(app)
14
+ @application = app
15
+ end
16
+
17
+ def suggested_thread_count # :nodoc:
18
+ @cpu_count ||= Rake::CpuCounter.count
19
+ @cpu_count + 4
20
+ end
21
+
22
+ # Return the original directory where the Rake application was started.
23
+ def original_dir
24
+ application.original_dir
25
+ end
26
+
27
+ # Load a rakefile.
28
+ def load_rakefile(path)
29
+ load(path)
30
+ end
31
+
32
+ # Add files to the rakelib list
33
+ def add_rakelib(*files)
34
+ application.options.rakelib ||= []
35
+ application.options.rakelib.concat(files)
36
+ end
37
+
38
+ # Make +block_application+ the default rake application inside a block so
39
+ # you can load rakefiles into a different application.
40
+ #
41
+ # This is useful when you want to run rake tasks inside a library without
42
+ # running rake in a sub-shell.
43
+ #
44
+ # Example:
45
+ #
46
+ # Dir.chdir 'other/directory'
47
+ #
48
+ # other_rake = Rake.with_application do |rake|
49
+ # rake.load_rakefile
50
+ # end
51
+ #
52
+ # puts other_rake.tasks
53
+
54
+ def with_application(block_application = Rake::Application.new)
55
+ orig_application = Rake.application
56
+
57
+ Rake.application = block_application
58
+
59
+ yield block_application
60
+
61
+ block_application
62
+ ensure
63
+ Rake.application = orig_application
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ require "rake"
3
+
4
+ # Load the test files from the command line.
5
+ argv = ARGV.select do |argument|
6
+ begin
7
+ case argument
8
+ when /^-/ then
9
+ argument
10
+ when /\*/ then
11
+ FileList[argument].to_a.each do |file|
12
+ require File.expand_path file
13
+ end
14
+
15
+ false
16
+ else
17
+ require File.expand_path argument
18
+
19
+ false
20
+ end
21
+ rescue LoadError => e
22
+ raise unless e.path
23
+ abort "\nFile does not exist: #{e.path}\n\n"
24
+ end
25
+ end
26
+
27
+ ARGV.replace argv
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+
4
+ # Error indicating a recursion overflow error in task selection.
5
+ class RuleRecursionOverflowError < StandardError
6
+ def initialize(*args)
7
+ super
8
+ @targets = []
9
+ end
10
+
11
+ def add_target(target)
12
+ @targets << target
13
+ end
14
+
15
+ def message
16
+ super + ": [" + @targets.reverse.join(" => ") + "]"
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+ class Scope < LinkedList # :nodoc: all
4
+
5
+ # Path for the scope.
6
+ def path
7
+ map(&:to_s).reverse.join(":")
8
+ end
9
+
10
+ # Path for the scope + the named path.
11
+ def path_with_task_name(task_name)
12
+ "#{path}:#{task_name}"
13
+ end
14
+
15
+ # Trim +n+ innermost scope levels from the scope. In no case will
16
+ # this trim beyond the toplevel scope.
17
+ def trim(n)
18
+ result = self
19
+ while n > 0 && !result.empty?
20
+ result = result.tail
21
+ n -= 1
22
+ end
23
+ result
24
+ end
25
+
26
+ # Scope lists always end with an EmptyScope object. See Null
27
+ # Object Pattern)
28
+ class EmptyScope < EmptyLinkedList
29
+ @parent = Scope
30
+
31
+ def path
32
+ ""
33
+ end
34
+
35
+ def path_with_task_name(task_name)
36
+ task_name
37
+ end
38
+ end
39
+
40
+ # Singleton null object for an empty scope.
41
+ EMPTY = EmptyScope.new
42
+ end
43
+ end
@@ -0,0 +1,413 @@
1
+ # frozen_string_literal: true
2
+ require "rake/invocation_exception_mixin"
3
+
4
+ module Rake
5
+
6
+ ##
7
+ # A Task is the basic unit of work in a Rakefile. Tasks have associated
8
+ # actions (possibly more than one) and a list of prerequisites. When
9
+ # invoked, a task will first ensure that all of its prerequisites have an
10
+ # opportunity to run and then it will execute its own actions.
11
+ #
12
+ # Tasks are not usually created directly using the new method, but rather
13
+ # use the +file+ and +task+ convenience methods.
14
+ #
15
+ class Task
16
+ # List of prerequisites for a task.
17
+ attr_reader :prerequisites
18
+ alias prereqs prerequisites
19
+
20
+ # List of actions attached to a task.
21
+ attr_reader :actions
22
+
23
+ # Application owning this task.
24
+ attr_accessor :application
25
+
26
+ # Array of nested namespaces names used for task lookup by this task.
27
+ attr_reader :scope
28
+
29
+ # File/Line locations of each of the task definitions for this
30
+ # task (only valid if the task was defined with the detect
31
+ # location option set).
32
+ attr_reader :locations
33
+
34
+ # Has this task already been invoked? Already invoked tasks
35
+ # will be skipped unless you reenable them.
36
+ attr_reader :already_invoked
37
+
38
+ # Return task name
39
+ def to_s
40
+ name
41
+ end
42
+
43
+ def inspect # :nodoc:
44
+ "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>"
45
+ end
46
+
47
+ # List of sources for task.
48
+ attr_writer :sources
49
+ def sources
50
+ if defined?(@sources)
51
+ @sources
52
+ else
53
+ prerequisites
54
+ end
55
+ end
56
+
57
+ # List of prerequisite tasks
58
+ def prerequisite_tasks
59
+ prerequisites.map { |pre| lookup_prerequisite(pre) }
60
+ end
61
+
62
+ def lookup_prerequisite(prerequisite_name) # :nodoc:
63
+ scoped_prerequisite_task = application[prerequisite_name, @scope]
64
+ if scoped_prerequisite_task == self
65
+ unscoped_prerequisite_task = application[prerequisite_name]
66
+ end
67
+ unscoped_prerequisite_task || scoped_prerequisite_task
68
+ end
69
+ private :lookup_prerequisite
70
+
71
+ # List of all unique prerequisite tasks including prerequisite tasks'
72
+ # prerequisites.
73
+ # Includes self when cyclic dependencies are found.
74
+ def all_prerequisite_tasks
75
+ seen = {}
76
+ collect_prerequisites(seen)
77
+ seen.values
78
+ end
79
+
80
+ def collect_prerequisites(seen) # :nodoc:
81
+ prerequisite_tasks.each do |pre|
82
+ next if seen[pre.name]
83
+ seen[pre.name] = pre
84
+ pre.collect_prerequisites(seen)
85
+ end
86
+ end
87
+ protected :collect_prerequisites
88
+
89
+ # First source from a rule (nil if no sources)
90
+ def source
91
+ sources.first
92
+ end
93
+
94
+ # Create a task named +task_name+ with no actions or prerequisites. Use
95
+ # +enhance+ to add actions and prerequisites.
96
+ def initialize(task_name, app)
97
+ @name = task_name.to_s
98
+ @prerequisites = []
99
+ @actions = []
100
+ @already_invoked = false
101
+ @comments = []
102
+ @lock = Monitor.new
103
+ @application = app
104
+ @scope = app.current_scope
105
+ @arg_names = nil
106
+ @locations = []
107
+ @invocation_exception = nil
108
+ end
109
+
110
+ # Enhance a task with prerequisites or actions. Returns self.
111
+ def enhance(deps=nil, &block)
112
+ @prerequisites |= deps if deps
113
+ @actions << block if block_given?
114
+ self
115
+ end
116
+
117
+ # Name of the task, including any namespace qualifiers.
118
+ def name
119
+ @name.to_s
120
+ end
121
+
122
+ # Name of task with argument list description.
123
+ def name_with_args # :nodoc:
124
+ if arg_description
125
+ "#{name}#{arg_description}"
126
+ else
127
+ name
128
+ end
129
+ end
130
+
131
+ # Argument description (nil if none).
132
+ def arg_description # :nodoc:
133
+ @arg_names ? "[#{arg_names.join(',')}]" : nil
134
+ end
135
+
136
+ # Name of arguments for this task.
137
+ def arg_names
138
+ @arg_names || []
139
+ end
140
+
141
+ # Reenable the task, allowing its tasks to be executed if the task
142
+ # is invoked again.
143
+ def reenable
144
+ @already_invoked = false
145
+ end
146
+
147
+ # Clear the existing prerequisites, actions, comments, and arguments of a rake task.
148
+ def clear
149
+ clear_prerequisites
150
+ clear_actions
151
+ clear_comments
152
+ clear_args
153
+ self
154
+ end
155
+
156
+ # Clear the existing prerequisites of a rake task.
157
+ def clear_prerequisites
158
+ prerequisites.clear
159
+ self
160
+ end
161
+
162
+ # Clear the existing actions on a rake task.
163
+ def clear_actions
164
+ actions.clear
165
+ self
166
+ end
167
+
168
+ # Clear the existing comments on a rake task.
169
+ def clear_comments
170
+ @comments = []
171
+ self
172
+ end
173
+
174
+ # Clear the existing arguments on a rake task.
175
+ def clear_args
176
+ @arg_names = nil
177
+ self
178
+ end
179
+
180
+ # Invoke the task if it is needed. Prerequisites are invoked first.
181
+ def invoke(*args)
182
+ task_args = TaskArguments.new(arg_names, args)
183
+ invoke_with_call_chain(task_args, InvocationChain::EMPTY)
184
+ end
185
+
186
+ # Same as invoke, but explicitly pass a call chain to detect
187
+ # circular dependencies.
188
+ #
189
+ # If multiple tasks depend on this
190
+ # one in parallel, they will all fail if the first execution of
191
+ # this task fails.
192
+ def invoke_with_call_chain(task_args, invocation_chain)
193
+ new_chain = Rake::InvocationChain.append(self, invocation_chain)
194
+ @lock.synchronize do
195
+ begin
196
+ if application.options.trace
197
+ application.trace "** Invoke #{name} #{format_trace_flags}"
198
+ end
199
+
200
+ if @already_invoked
201
+ if @invocation_exception
202
+ if application.options.trace
203
+ application.trace "** Previous invocation of #{name} failed #{format_trace_flags}"
204
+ end
205
+ raise @invocation_exception
206
+ else
207
+ return
208
+ end
209
+ end
210
+
211
+ @already_invoked = true
212
+
213
+ invoke_prerequisites(task_args, new_chain)
214
+ execute(task_args) if needed?
215
+ rescue Exception => ex
216
+ add_chain_to(ex, new_chain)
217
+ @invocation_exception = ex
218
+ raise ex
219
+ end
220
+ end
221
+ end
222
+ protected :invoke_with_call_chain
223
+
224
+ def add_chain_to(exception, new_chain) # :nodoc:
225
+ exception.extend(InvocationExceptionMixin) unless
226
+ exception.respond_to?(:chain)
227
+ exception.chain = new_chain if exception.chain.nil?
228
+ end
229
+ private :add_chain_to
230
+
231
+ # Invoke all the prerequisites of a task.
232
+ def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
233
+ if application.options.always_multitask
234
+ invoke_prerequisites_concurrently(task_args, invocation_chain)
235
+ else
236
+ prerequisite_tasks.each { |p|
237
+ prereq_args = task_args.new_scope(p.arg_names)
238
+ p.invoke_with_call_chain(prereq_args, invocation_chain)
239
+ }
240
+ end
241
+ end
242
+
243
+ # Invoke all the prerequisites of a task in parallel.
244
+ def invoke_prerequisites_concurrently(task_args, invocation_chain)# :nodoc:
245
+ futures = prerequisite_tasks.map do |p|
246
+ prereq_args = task_args.new_scope(p.arg_names)
247
+ application.thread_pool.future(p) do |r|
248
+ r.invoke_with_call_chain(prereq_args, invocation_chain)
249
+ end
250
+ end
251
+ # Iterate in reverse to improve performance related to thread waiting and switching
252
+ futures.reverse_each(&:value)
253
+ end
254
+
255
+ # Format the trace flags for display.
256
+ def format_trace_flags
257
+ flags = []
258
+ flags << "first_time" unless @already_invoked
259
+ flags << "not_needed" unless needed?
260
+ flags.empty? ? "" : "(" + flags.join(", ") + ")"
261
+ end
262
+ private :format_trace_flags
263
+
264
+ # Execute the actions associated with this task.
265
+ def execute(args=nil)
266
+ args ||= EMPTY_TASK_ARGS
267
+ if application.options.dryrun
268
+ application.trace "** Execute (dry run) #{name}"
269
+ return
270
+ end
271
+ application.trace "** Execute #{name}" if application.options.trace
272
+ application.enhance_with_matching_rule(name) if @actions.empty?
273
+ @actions.each { |act| act.call(self, args) }
274
+ end
275
+
276
+ # Is this task needed?
277
+ def needed?
278
+ true
279
+ end
280
+
281
+ # Timestamp for this task. Basic tasks return the current time for their
282
+ # time stamp. Other tasks can be more sophisticated.
283
+ def timestamp
284
+ Time.now
285
+ end
286
+
287
+ # Add a description to the task. The description can consist of an option
288
+ # argument list (enclosed brackets) and an optional comment.
289
+ def add_description(description)
290
+ return unless description
291
+ comment = description.strip
292
+ add_comment(comment) if comment && !comment.empty?
293
+ end
294
+
295
+ def comment=(comment) # :nodoc:
296
+ add_comment(comment)
297
+ end
298
+
299
+ def add_comment(comment) # :nodoc:
300
+ return if comment.nil?
301
+ @comments << comment unless @comments.include?(comment)
302
+ end
303
+ private :add_comment
304
+
305
+ # Full collection of comments. Multiple comments are separated by
306
+ # newlines.
307
+ def full_comment
308
+ transform_comments("\n")
309
+ end
310
+
311
+ # First line (or sentence) of all comments. Multiple comments are
312
+ # separated by a "/".
313
+ def comment
314
+ transform_comments(" / ") { |c| first_sentence(c) }
315
+ end
316
+
317
+ # Transform the list of comments as specified by the block and
318
+ # join with the separator.
319
+ def transform_comments(separator, &block)
320
+ if @comments.empty?
321
+ nil
322
+ else
323
+ block ||= lambda { |c| c }
324
+ @comments.map(&block).join(separator)
325
+ end
326
+ end
327
+ private :transform_comments
328
+
329
+ # Get the first sentence in a string. The sentence is terminated
330
+ # by the first period, exclamation mark, or the end of the line.
331
+ # Decimal points do not count as periods.
332
+ def first_sentence(string)
333
+ string.split(/(?<=\w)(\.|!)[ \t]|(\.$|!)|\n/).first
334
+ end
335
+ private :first_sentence
336
+
337
+ # Set the names of the arguments for this task. +args+ should be
338
+ # an array of symbols, one for each argument name.
339
+ def set_arg_names(args)
340
+ @arg_names = args.map(&:to_sym)
341
+ end
342
+
343
+ # Return a string describing the internal state of a task. Useful for
344
+ # debugging.
345
+ def investigation
346
+ result = "------------------------------\n".dup
347
+ result << "Investigating #{name}\n"
348
+ result << "class: #{self.class}\n"
349
+ result << "task needed: #{needed?}\n"
350
+ result << "timestamp: #{timestamp}\n"
351
+ result << "pre-requisites: \n"
352
+ prereqs = prerequisite_tasks
353
+ prereqs.sort! { |a, b| a.timestamp <=> b.timestamp }
354
+ prereqs.each do |p|
355
+ result << "--#{p.name} (#{p.timestamp})\n"
356
+ end
357
+ latest_prereq = prerequisite_tasks.map(&:timestamp).max
358
+ result << "latest-prerequisite time: #{latest_prereq}\n"
359
+ result << "................................\n\n"
360
+ return result
361
+ end
362
+
363
+ # ----------------------------------------------------------------
364
+ # Rake Module Methods
365
+ #
366
+ class << self
367
+
368
+ # Clear the task list. This cause rake to immediately forget all the
369
+ # tasks that have been assigned. (Normally used in the unit tests.)
370
+ def clear
371
+ Rake.application.clear
372
+ end
373
+
374
+ # List of all defined tasks.
375
+ def tasks
376
+ Rake.application.tasks
377
+ end
378
+
379
+ # Return a task with the given name. If the task is not currently
380
+ # known, try to synthesize one from the defined rules. If no rules are
381
+ # found, but an existing file matches the task name, assume it is a file
382
+ # task with no dependencies or actions.
383
+ def [](task_name)
384
+ Rake.application[task_name]
385
+ end
386
+
387
+ # TRUE if the task name is already defined.
388
+ def task_defined?(task_name)
389
+ Rake.application.lookup(task_name) != nil
390
+ end
391
+
392
+ # Define a task given +args+ and an option block. If a rule with the
393
+ # given name already exists, the prerequisites and actions are added to
394
+ # the existing task. Returns the defined task.
395
+ def define_task(*args, &block)
396
+ Rake.application.define_task(self, *args, &block)
397
+ end
398
+
399
+ # Define a rule for synthesizing tasks.
400
+ def create_rule(*args, &block)
401
+ Rake.application.create_rule(*args, &block)
402
+ end
403
+
404
+ # Apply the scope to the task name according to the rules for
405
+ # this kind of task. Generic tasks will accept the scope as
406
+ # part of the name.
407
+ def scope_name(scope, task_name)
408
+ scope.path_with_task_name(task_name)
409
+ end
410
+
411
+ end # class << Rake::Task
412
+ end # class Rake::Task
413
+ end