rake 0.9.2 → 13.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.rdoc +43 -0
  3. data/Gemfile +10 -0
  4. data/History.rdoc +2386 -0
  5. data/MIT-LICENSE +1 -1
  6. data/README.rdoc +64 -109
  7. data/Rakefile +22 -386
  8. data/bin/bundle +105 -0
  9. data/bin/console +7 -0
  10. data/bin/rake +20 -23
  11. data/bin/rdoc +29 -0
  12. data/bin/rubocop +29 -0
  13. data/bin/setup +6 -0
  14. data/doc/command_line_usage.rdoc +65 -21
  15. data/doc/glossary.rdoc +40 -49
  16. data/doc/jamis.rb +1 -0
  17. data/doc/rake.1 +156 -0
  18. data/doc/rakefile.rdoc +127 -62
  19. data/exe/rake +27 -0
  20. data/lib/rake.rb +37 -31
  21. data/lib/rake/application.rb +507 -272
  22. data/lib/rake/backtrace.rb +24 -0
  23. data/lib/rake/clean.rb +55 -8
  24. data/lib/rake/cloneable.rb +11 -19
  25. data/lib/rake/cpu_counter.rb +107 -0
  26. data/lib/rake/default_loader.rb +5 -0
  27. data/lib/rake/dsl_definition.rb +74 -46
  28. data/lib/rake/early_time.rb +5 -1
  29. data/lib/rake/ext/core.rb +5 -6
  30. data/lib/rake/ext/string.rb +61 -52
  31. data/lib/rake/file_creation_task.rb +4 -3
  32. data/lib/rake/file_list.rb +81 -49
  33. data/lib/rake/file_task.rb +15 -8
  34. data/lib/rake/file_utils.rb +69 -47
  35. data/lib/rake/file_utils_ext.rb +18 -26
  36. data/lib/rake/invocation_chain.rb +25 -19
  37. data/lib/rake/invocation_exception_mixin.rb +1 -0
  38. data/lib/rake/late_time.rb +18 -0
  39. data/lib/rake/linked_list.rb +112 -0
  40. data/lib/rake/loaders/makefile.rb +23 -9
  41. data/lib/rake/multi_task.rb +4 -6
  42. data/lib/rake/name_space.rb +36 -23
  43. data/lib/rake/packagetask.rb +71 -34
  44. data/lib/rake/phony.rb +16 -0
  45. data/lib/rake/private_reader.rb +21 -0
  46. data/lib/rake/promise.rb +100 -0
  47. data/lib/rake/pseudo_status.rb +8 -2
  48. data/lib/rake/rake_module.rb +41 -3
  49. data/lib/rake/rake_test_loader.rb +21 -7
  50. data/lib/rake/rule_recursion_overflow_error.rb +2 -2
  51. data/lib/rake/scope.rb +43 -0
  52. data/lib/rake/task.rb +186 -79
  53. data/lib/rake/task_argument_error.rb +1 -0
  54. data/lib/rake/task_arguments.rb +50 -15
  55. data/lib/rake/task_manager.rb +89 -65
  56. data/lib/rake/tasklib.rb +2 -12
  57. data/lib/rake/testtask.rb +61 -63
  58. data/lib/rake/thread_history_display.rb +49 -0
  59. data/lib/rake/thread_pool.rb +163 -0
  60. data/lib/rake/trace_output.rb +23 -0
  61. data/lib/rake/version.rb +7 -7
  62. data/lib/rake/win32.rb +14 -18
  63. data/rake.gemspec +43 -0
  64. metadata +82 -221
  65. data/.gemtest +0 -0
  66. data/CHANGES +0 -509
  67. data/RRR +0 -9
  68. data/TODO +0 -20
  69. data/doc/rake.1.gz +0 -0
  70. data/doc/release_notes/rake-0.4.14.rdoc +0 -23
  71. data/doc/release_notes/rake-0.4.15.rdoc +0 -35
  72. data/doc/release_notes/rake-0.5.0.rdoc +0 -53
  73. data/doc/release_notes/rake-0.5.3.rdoc +0 -78
  74. data/doc/release_notes/rake-0.5.4.rdoc +0 -46
  75. data/doc/release_notes/rake-0.6.0.rdoc +0 -141
  76. data/doc/release_notes/rake-0.7.0.rdoc +0 -119
  77. data/doc/release_notes/rake-0.7.1.rdoc +0 -59
  78. data/doc/release_notes/rake-0.7.2.rdoc +0 -121
  79. data/doc/release_notes/rake-0.7.3.rdoc +0 -47
  80. data/doc/release_notes/rake-0.8.0.rdoc +0 -114
  81. data/doc/release_notes/rake-0.8.2.rdoc +0 -165
  82. data/doc/release_notes/rake-0.8.3.rdoc +0 -112
  83. data/doc/release_notes/rake-0.8.4.rdoc +0 -147
  84. data/doc/release_notes/rake-0.8.5.rdoc +0 -53
  85. data/doc/release_notes/rake-0.8.6.rdoc +0 -55
  86. data/doc/release_notes/rake-0.8.7.rdoc +0 -55
  87. data/doc/release_notes/rake-0.9.0.rdoc +0 -112
  88. data/doc/release_notes/rake-0.9.1.rdoc +0 -52
  89. data/doc/release_notes/rake-0.9.2.rdoc +0 -49
  90. data/install.rb +0 -90
  91. data/lib/rake/alt_system.rb +0 -109
  92. data/lib/rake/classic_namespace.rb +0 -9
  93. data/lib/rake/contrib/compositepublisher.rb +0 -21
  94. data/lib/rake/contrib/ftptools.rb +0 -150
  95. data/lib/rake/contrib/publisher.rb +0 -69
  96. data/lib/rake/contrib/rubyforgepublisher.rb +0 -16
  97. data/lib/rake/contrib/sshpublisher.rb +0 -45
  98. data/lib/rake/contrib/sys.rb +0 -191
  99. data/lib/rake/ext/module.rb +0 -39
  100. data/lib/rake/ext/time.rb +0 -14
  101. data/lib/rake/gempackagetask.rb +0 -13
  102. data/lib/rake/pathmap.rb +0 -1
  103. data/lib/rake/rdoctask.rb +0 -230
  104. data/lib/rake/ruby182_test_unit_fix.rb +0 -25
  105. data/lib/rake/runtest.rb +0 -21
  106. data/test/check_expansion.rb +0 -5
  107. data/test/check_no_expansion.rb +0 -5
  108. data/test/data/access/Rakefile +0 -35
  109. data/test/data/chains/Rakefile +0 -15
  110. data/test/data/comments/Rakefile +0 -18
  111. data/test/data/default/Rakefile +0 -17
  112. data/test/data/deprecated_import/Rakefile +0 -1
  113. data/test/data/dryrun/Rakefile +0 -22
  114. data/test/data/extra/Rakefile +0 -1
  115. data/test/data/file_creation_task/Rakefile +0 -31
  116. data/test/data/imports/Rakefile +0 -19
  117. data/test/data/imports/deps.mf +0 -1
  118. data/test/data/multidesc/Rakefile +0 -15
  119. data/test/data/namespace/Rakefile +0 -64
  120. data/test/data/rakelib/test1.rb +0 -4
  121. data/test/data/rbext/rakefile.rb +0 -3
  122. data/test/data/sample.mf +0 -14
  123. data/test/data/statusreturn/Rakefile +0 -6
  124. data/test/data/unittest/Rakefile +0 -1
  125. data/test/data/verbose/Rakefile +0 -34
  126. data/test/file_creation.rb +0 -34
  127. data/test/helper.rb +0 -44
  128. data/test/in_environment.rb +0 -35
  129. data/test/reqfile.rb +0 -3
  130. data/test/reqfile2.rb +0 -3
  131. data/test/shellcommand.rb +0 -3
  132. data/test/test_rake.rb +0 -38
  133. data/test/test_rake_application.rb +0 -364
  134. data/test/test_rake_application_options.rb +0 -382
  135. data/test/test_rake_clean.rb +0 -12
  136. data/test/test_rake_definitions.rb +0 -80
  137. data/test/test_rake_directory_task.rb +0 -55
  138. data/test/test_rake_dsl.rb +0 -73
  139. data/test/test_rake_early_time.rb +0 -31
  140. data/test/test_rake_extension.rb +0 -59
  141. data/test/test_rake_file_creation_task.rb +0 -62
  142. data/test/test_rake_file_list.rb +0 -633
  143. data/test/test_rake_file_list_path_map.rb +0 -8
  144. data/test/test_rake_file_task.rb +0 -104
  145. data/test/test_rake_file_utils.rb +0 -252
  146. data/test/test_rake_ftp_file.rb +0 -59
  147. data/test/test_rake_functional.rb +0 -468
  148. data/test/test_rake_invocation_chain.rb +0 -52
  149. data/test/test_rake_makefile_loader.rb +0 -23
  150. data/test/test_rake_multi_task.rb +0 -51
  151. data/test/test_rake_name_space.rb +0 -43
  152. data/test/test_rake_package_task.rb +0 -78
  153. data/test/test_rake_path_map.rb +0 -157
  154. data/test/test_rake_path_map_explode.rb +0 -31
  155. data/test/test_rake_path_map_partial.rb +0 -18
  156. data/test/test_rake_pseudo_status.rb +0 -20
  157. data/test/test_rake_rdoc_task.rb +0 -81
  158. data/test/test_rake_require.rb +0 -35
  159. data/test/test_rake_rules.rb +0 -346
  160. data/test/test_rake_task.rb +0 -271
  161. data/test/test_rake_task_argument_parsing.rb +0 -116
  162. data/test/test_rake_task_arguments.rb +0 -86
  163. data/test/test_rake_task_lib.rb +0 -9
  164. data/test/test_rake_task_manager.rb +0 -145
  165. data/test/test_rake_task_manager_argument_resolution.rb +0 -36
  166. data/test/test_rake_task_with_arguments.rb +0 -162
  167. data/test/test_rake_test_task.rb +0 -122
  168. data/test/test_rake_top_level_functions.rb +0 -76
  169. data/test/test_rake_win32.rb +0 -83
  170. data/test/test_sys.rb +0 -20
@@ -1,8 +1,9 @@
1
- require 'rake/task.rb'
2
- require 'rake/early_time'
1
+ # frozen_string_literal: true
2
+ require "rake/task"
3
+ require "rake/early_time"
3
4
 
4
5
  module Rake
5
- # #########################################################################
6
+
6
7
  # A FileTask is a task that includes time based dependencies. If any of a
7
8
  # FileTask's prerequisites have a timestamp that is later than the file
8
9
  # represented by this task, then the file must be rebuilt (using the
@@ -13,7 +14,7 @@ module Rake
13
14
  # Is this file task needed? Yes if it doesn't exist, or if its time stamp
14
15
  # is out of date.
15
16
  def needed?
16
- ! File.exist?(name) || out_of_date?(timestamp)
17
+ !File.exist?(name) || out_of_date?(timestamp) || @application.options.build_all
17
18
  end
18
19
 
19
20
  # Time stamp for file task.
@@ -21,7 +22,7 @@ module Rake
21
22
  if File.exist?(name)
22
23
  File.mtime(name.to_s)
23
24
  else
24
- Rake::EARLY
25
+ Rake::LATE
25
26
  end
26
27
  end
27
28
 
@@ -29,7 +30,14 @@ module Rake
29
30
 
30
31
  # Are there any prerequisites with a later time than the given time stamp?
31
32
  def out_of_date?(stamp)
32
- @prerequisites.any? { |n| application[n, @scope].timestamp > stamp}
33
+ all_prerequisite_tasks.any? { |prereq|
34
+ prereq_task = application[prereq, @scope]
35
+ if prereq_task.instance_of?(Rake::FileTask)
36
+ prereq_task.timestamp > stamp || @application.options.build_all
37
+ else
38
+ prereq_task.timestamp > stamp
39
+ end
40
+ }
33
41
  end
34
42
 
35
43
  # ----------------------------------------------------------------
@@ -39,9 +47,8 @@ module Rake
39
47
  # Apply the scope to the task name according to the rules for this kind
40
48
  # of task. File based tasks ignore the scope when creating the name.
41
49
  def scope_name(scope, task_name)
42
- task_name
50
+ Rake.from_pathname(task_name)
43
51
  end
44
52
  end
45
53
  end
46
54
  end
47
-
@@ -1,32 +1,41 @@
1
- require 'rbconfig'
2
- require 'fileutils'
1
+ # frozen_string_literal: true
2
+ require "rbconfig"
3
+ require "fileutils"
3
4
 
4
- # ###########################################################################
5
+ #--
5
6
  # This a FileUtils extension that defines several additional commands to be
6
7
  # added to the FileUtils utility functions.
7
- #
8
8
  module FileUtils
9
9
  # Path to the currently running Ruby program
10
- RUBY = File.join(
11
- RbConfig::CONFIG['bindir'],
12
- RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']).
10
+ RUBY = ENV["RUBY"] || File.join(
11
+ RbConfig::CONFIG["bindir"],
12
+ RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]).
13
13
  sub(/.*\s.*/m, '"\&"')
14
14
 
15
- OPT_TABLE['sh'] = %w(noop verbose)
16
- OPT_TABLE['ruby'] = %w(noop verbose)
17
-
18
- # Run the system command +cmd+. If multiple arguments are given the command
19
- # is not run with the shell (same semantics as Kernel::exec and
15
+ # Run the system command +cmd+. If multiple arguments are given the command
16
+ # is run directly (without the shell, same semantics as Kernel::exec and
20
17
  # Kernel::system).
21
18
  #
22
- # Example:
23
- # sh %{ls -ltr}
19
+ # It is recommended you use the multiple argument form over interpolating
20
+ # user input for both usability and security reasons. With the multiple
21
+ # argument form you can easily process files with spaces or other shell
22
+ # reserved characters in them. With the multiple argument form your rake
23
+ # tasks are not vulnerable to users providing an argument like
24
+ # <code>; rm # -rf /</code>.
25
+ #
26
+ # If a block is given, upon command completion the block is called with an
27
+ # OK flag (true on a zero exit status) and a Process::Status object.
28
+ # Without a block a RuntimeError is raised when the command exits non-zero.
29
+ #
30
+ # Examples:
31
+ #
32
+ # sh 'ls -ltr'
24
33
  #
25
34
  # sh 'ls', 'file with spaces'
26
35
  #
27
36
  # # check exit status after command runs
28
37
  # sh %{grep pattern file} do |ok, res|
29
- # if ! ok
38
+ # if !ok
30
39
  # puts "pattern not found (status = #{res.exitstatus})"
31
40
  # end
32
41
  # end
@@ -34,50 +43,65 @@ module FileUtils
34
43
  def sh(*cmd, &block)
35
44
  options = (Hash === cmd.last) ? cmd.pop : {}
36
45
  shell_runner = block_given? ? block : create_shell_runner(cmd)
46
+
37
47
  set_verbose_option(options)
38
- options[:noop] ||= Rake::FileUtilsExt.nowrite_flag
39
- Rake.rake_check_options options, :noop, :verbose
40
- Rake.rake_output_message cmd.join(" ") if options[:verbose]
41
- unless options[:noop]
42
- res = rake_system(*cmd)
48
+ verbose = options.delete :verbose
49
+ noop = options.delete(:noop) || Rake::FileUtilsExt.nowrite_flag
50
+
51
+ Rake.rake_output_message sh_show_command cmd if verbose
52
+
53
+ unless noop
54
+ res = (Hash === cmd.last) ? system(*cmd) : system(*cmd, options)
43
55
  status = $?
44
- status = PseudoStatus.new(1) if !res && status.nil?
56
+ status = Rake::PseudoStatus.new(1) if !res && status.nil?
45
57
  shell_runner.call(res, status)
46
58
  end
47
59
  end
48
60
 
49
- def create_shell_runner(cmd)
50
- show_command = cmd.join(" ")
51
- show_command = show_command[0,42] + "..." unless $trace
52
- lambda { |ok, status|
53
- ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
54
- }
61
+ def create_shell_runner(cmd) # :nodoc:
62
+ show_command = sh_show_command cmd
63
+ show_command = show_command[0, 42] + "..." unless $trace
64
+
65
+ lambda do |ok, status|
66
+ ok or
67
+ fail "Command failed with status (#{status.exitstatus}): " +
68
+ "[#{show_command}]"
69
+ end
55
70
  end
56
71
  private :create_shell_runner
57
72
 
58
- def set_verbose_option(options)
59
- if options[:verbose].nil?
60
- options[:verbose] = Rake::FileUtilsExt.verbose_flag.nil? || Rake::FileUtilsExt.verbose_flag
73
+ def sh_show_command(cmd) # :nodoc:
74
+ cmd = cmd.dup
75
+
76
+ if Hash === cmd.first
77
+ env = cmd.first
78
+ env = env.map { |name, value| "#{name}=#{value}" }.join " "
79
+ cmd[0] = env
61
80
  end
81
+
82
+ cmd.join " "
62
83
  end
63
- private :set_verbose_option
84
+ private :sh_show_command
64
85
 
65
- def rake_system(*cmd)
66
- Rake::AltSystem.system(*cmd)
86
+ def set_verbose_option(options) # :nodoc:
87
+ unless options.key? :verbose
88
+ options[:verbose] =
89
+ (Rake::FileUtilsExt.verbose_flag == Rake::FileUtilsExt::DEFAULT) ||
90
+ Rake::FileUtilsExt.verbose_flag
91
+ end
67
92
  end
68
- private :rake_system
93
+ private :set_verbose_option
69
94
 
70
95
  # Run a Ruby interpreter with the given arguments.
71
96
  #
72
97
  # Example:
73
98
  # ruby %{-pe '$_.upcase!' <README}
74
99
  #
75
- def ruby(*args,&block)
76
- options = (Hash === args.last) ? args.pop : {}
77
- if args.length > 1 then
78
- sh(*([RUBY] + args + [options]), &block)
100
+ def ruby(*args, **options, &block)
101
+ if args.length > 1
102
+ sh(RUBY, *args, **options, &block)
79
103
  else
80
- sh("#{RUBY} #{args.first}", options, &block)
104
+ sh("#{RUBY} #{args.first}", **options, &block)
81
105
  end
82
106
  end
83
107
 
@@ -85,17 +109,15 @@ module FileUtils
85
109
 
86
110
  # Attempt to do a normal file link, but fall back to a copy if the link
87
111
  # fails.
88
- def safe_ln(*args)
89
- unless LN_SUPPORTED[0]
90
- cp(*args)
91
- else
112
+ def safe_ln(*args, **options)
113
+ if LN_SUPPORTED[0]
92
114
  begin
93
- ln(*args)
115
+ return options.empty? ? ln(*args) : ln(*args, **options)
94
116
  rescue StandardError, NotImplementedError
95
117
  LN_SUPPORTED[0] = false
96
- cp(*args)
97
118
  end
98
119
  end
120
+ options.empty? ? cp(*args) : cp(*args, **options)
99
121
  end
100
122
 
101
123
  # Split a file path into individual directory names.
@@ -105,8 +127,8 @@ module FileUtils
105
127
  #
106
128
  def split_all(path)
107
129
  head, tail = File.split(path)
108
- return [tail] if head == '.' || tail == '/'
109
- return [head, tail] if head == '/'
130
+ return [tail] if head == "." || tail == "/"
131
+ return [head, tail] if head == "/"
110
132
  return split_all(head) + [tail]
111
133
  end
112
134
  end
@@ -1,4 +1,5 @@
1
- require 'rake/file_utils'
1
+ # frozen_string_literal: true
2
+ require "rake/file_utils"
2
3
 
3
4
  module Rake
4
5
  #
@@ -12,28 +13,28 @@ module Rake
12
13
  class << self
13
14
  attr_accessor :verbose_flag, :nowrite_flag
14
15
  end
15
- FileUtilsExt.verbose_flag = nil
16
- FileUtilsExt.nowrite_flag = false
17
16
 
18
- $fileutils_verbose = true
19
- $fileutils_nowrite = false
17
+ DEFAULT = Object.new
18
+
19
+ FileUtilsExt.verbose_flag = DEFAULT
20
+ FileUtilsExt.nowrite_flag = false
20
21
 
21
- FileUtils::OPT_TABLE.each do |name, opts|
22
+ FileUtils.commands.each do |name|
23
+ opts = FileUtils.options_of name
22
24
  default_options = []
23
- if opts.include?(:verbose) || opts.include?("verbose")
24
- default_options << ':verbose => FileUtilsExt.verbose_flag'
25
+ if opts.include?("verbose")
26
+ default_options << "verbose: FileUtilsExt.verbose_flag"
25
27
  end
26
- if opts.include?(:noop) || opts.include?("noop")
27
- default_options << ':noop => FileUtilsExt.nowrite_flag'
28
+ if opts.include?("noop")
29
+ default_options << "noop: FileUtilsExt.nowrite_flag"
28
30
  end
29
31
 
30
32
  next if default_options.empty?
31
33
  module_eval(<<-EOS, __FILE__, __LINE__ + 1)
32
- def #{name}( *args, &block )
33
- super(
34
- *rake_merge_option(args,
35
- #{default_options.join(', ')}
36
- ), &block)
34
+ def #{name}(*args, **options, &block)
35
+ super(*args,
36
+ #{default_options.join(', ')},
37
+ **options, &block)
37
38
  end
38
39
  EOS
39
40
  end
@@ -111,16 +112,6 @@ module Rake
111
112
  end
112
113
  end
113
114
 
114
- # Merge the given options with the default values.
115
- def rake_merge_option(args, defaults)
116
- if Hash === args.last
117
- defaults.update(args.last)
118
- args.pop
119
- end
120
- args.push defaults
121
- args
122
- end
123
-
124
115
  # Send the message to the default rake output (which is $stderr).
125
116
  def rake_output_message(message)
126
117
  $stderr.puts(message)
@@ -134,7 +125,8 @@ module Rake
134
125
  optdecl.each do |name|
135
126
  h.delete name
136
127
  end
137
- raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty?
128
+ raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless
129
+ h.empty?
138
130
  end
139
131
 
140
132
  extend self
@@ -1,46 +1,52 @@
1
+ # frozen_string_literal: true
1
2
  module Rake
2
3
 
3
- ####################################################################
4
4
  # InvocationChain tracks the chain of task invocations to detect
5
5
  # circular dependencies.
6
- class InvocationChain
7
- def initialize(value, tail)
8
- @value = value
9
- @tail = tail
10
- end
6
+ class InvocationChain < LinkedList
11
7
 
12
- def member?(obj)
13
- @value == obj || @tail.member?(obj)
8
+ # Is the invocation already in the chain?
9
+ def member?(invocation)
10
+ head == invocation || tail.member?(invocation)
14
11
  end
15
12
 
16
- def append(value)
17
- if member?(value)
18
- fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}"
13
+ # Append an invocation to the chain of invocations. It is an error
14
+ # if the invocation already listed.
15
+ def append(invocation)
16
+ if member?(invocation)
17
+ fail RuntimeError, "Circular dependency detected: #{to_s} => #{invocation}"
19
18
  end
20
- self.class.new(value, self)
19
+ conj(invocation)
21
20
  end
22
21
 
22
+ # Convert to string, ie: TOP => invocation => invocation
23
23
  def to_s
24
- "#{prefix}#{@value}"
24
+ "#{prefix}#{head}"
25
25
  end
26
26
 
27
- def self.append(value, chain)
28
- chain.append(value)
27
+ # Class level append.
28
+ def self.append(invocation, chain)
29
+ chain.append(invocation)
29
30
  end
30
31
 
31
32
  private
32
33
 
33
34
  def prefix
34
- "#{@tail.to_s} => "
35
+ "#{tail} => "
35
36
  end
36
37
 
37
- class EmptyInvocationChain
38
+ # Null object for an empty chain.
39
+ class EmptyInvocationChain < LinkedList::EmptyLinkedList
40
+ @parent = InvocationChain
41
+
38
42
  def member?(obj)
39
43
  false
40
44
  end
41
- def append(value)
42
- InvocationChain.new(value, self)
45
+
46
+ def append(invocation)
47
+ conj(invocation)
43
48
  end
49
+
44
50
  def to_s
45
51
  "TOP"
46
52
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Rake
2
3
  module InvocationExceptionMixin
3
4
  # Return the invocation chain (list of Rake tasks) that were in
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+ # LateTime is a fake timestamp that occurs _after_ any other time value.
4
+ class LateTime
5
+ include Comparable
6
+ include Singleton
7
+
8
+ def <=>(other)
9
+ 1
10
+ end
11
+
12
+ def to_s
13
+ "<LATE TIME>"
14
+ end
15
+ end
16
+
17
+ LATE = LateTime.instance
18
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+
4
+ # Polylithic linked list structure used to implement several data
5
+ # structures in Rake.
6
+ class LinkedList
7
+ include Enumerable
8
+ attr_reader :head, :tail
9
+
10
+ # Polymorphically add a new element to the head of a list. The
11
+ # type of head node will be the same list type as the tail.
12
+ def conj(item)
13
+ self.class.cons(item, self)
14
+ end
15
+
16
+ # Is the list empty?
17
+ # .make guards against a list being empty making any instantiated LinkedList
18
+ # object not empty by default
19
+ # You should consider overriding this method if you implement your own .make method
20
+ def empty?
21
+ false
22
+ end
23
+
24
+ # Lists are structurally equivalent.
25
+ def ==(other)
26
+ current = self
27
+ while !current.empty? && !other.empty?
28
+ return false if current.head != other.head
29
+ current = current.tail
30
+ other = other.tail
31
+ end
32
+ current.empty? && other.empty?
33
+ end
34
+
35
+ # Convert to string: LL(item, item...)
36
+ def to_s
37
+ items = map(&:to_s).join(", ")
38
+ "LL(#{items})"
39
+ end
40
+
41
+ # Same as +to_s+, but with inspected items.
42
+ def inspect
43
+ items = map(&:inspect).join(", ")
44
+ "LL(#{items})"
45
+ end
46
+
47
+ # For each item in the list.
48
+ def each
49
+ current = self
50
+ while !current.empty?
51
+ yield(current.head)
52
+ current = current.tail
53
+ end
54
+ self
55
+ end
56
+
57
+ # Make a list out of the given arguments. This method is
58
+ # polymorphic
59
+ def self.make(*args)
60
+ # return an EmptyLinkedList if there are no arguments
61
+ return empty if !args || args.empty?
62
+
63
+ # build a LinkedList by starting at the tail and iterating
64
+ # through each argument
65
+ # inject takes an EmptyLinkedList to start
66
+ args.reverse.inject(empty) do |list, item|
67
+ list = cons(item, list)
68
+ list # return the newly created list for each item in the block
69
+ end
70
+ end
71
+
72
+ # Cons a new head onto the tail list.
73
+ def self.cons(head, tail)
74
+ new(head, tail)
75
+ end
76
+
77
+ # The standard empty list class for the given LinkedList class.
78
+ def self.empty
79
+ self::EMPTY
80
+ end
81
+
82
+ protected
83
+
84
+ def initialize(head, tail=EMPTY)
85
+ @head = head
86
+ @tail = tail
87
+ end
88
+
89
+ # Represent an empty list, using the Null Object Pattern.
90
+ #
91
+ # When inheriting from the LinkedList class, you should implement
92
+ # a type specific Empty class as well. Make sure you set the class
93
+ # instance variable @parent to the associated list class (this
94
+ # allows conj, cons and make to work polymorphically).
95
+ class EmptyLinkedList < LinkedList
96
+ @parent = LinkedList
97
+
98
+ def initialize
99
+ end
100
+
101
+ def empty?
102
+ true
103
+ end
104
+
105
+ def self.cons(head, tail)
106
+ @parent.cons(head, tail)
107
+ end
108
+ end
109
+
110
+ EMPTY = EmptyLinkedList.new
111
+ end
112
+ end