rake 10.0.0.beta.2 → 13.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) 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 +1 -1
  10. data/README.rdoc +57 -101
  11. data/Rakefile +22 -354
  12. data/bin/bundle +105 -0
  13. data/bin/console +7 -0
  14. data/bin/rake +19 -27
  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 +30 -18
  19. data/doc/glossary.rdoc +40 -49
  20. data/doc/jamis.rb +1 -0
  21. data/doc/rake.1 +156 -0
  22. data/doc/rakefile.rdoc +127 -62
  23. data/exe/rake +27 -0
  24. data/lib/rake.rb +35 -34
  25. data/lib/rake/application.rb +355 -188
  26. data/lib/rake/backtrace.rb +14 -7
  27. data/lib/rake/clean.rb +54 -8
  28. data/lib/rake/cloneable.rb +5 -4
  29. data/lib/rake/cpu_counter.rb +107 -0
  30. data/lib/rake/default_loader.rb +5 -0
  31. data/lib/rake/dsl_definition.rb +58 -19
  32. data/lib/rake/early_time.rb +5 -1
  33. data/lib/rake/ext/core.rb +5 -6
  34. data/lib/rake/ext/string.rb +61 -52
  35. data/lib/rake/file_creation_task.rb +4 -3
  36. data/lib/rake/file_list.rb +81 -49
  37. data/lib/rake/file_task.rb +15 -8
  38. data/lib/rake/file_utils.rb +63 -43
  39. data/lib/rake/file_utils_ext.rb +10 -22
  40. data/lib/rake/invocation_chain.rb +25 -19
  41. data/lib/rake/invocation_exception_mixin.rb +1 -0
  42. data/lib/rake/late_time.rb +18 -0
  43. data/lib/rake/linked_list.rb +112 -0
  44. data/lib/rake/loaders/makefile.rb +23 -9
  45. data/lib/rake/multi_task.rb +2 -1
  46. data/lib/rake/name_space.rb +36 -23
  47. data/lib/rake/packagetask.rb +71 -34
  48. data/lib/rake/phony.rb +6 -3
  49. data/lib/rake/private_reader.rb +21 -0
  50. data/lib/rake/promise.rb +100 -0
  51. data/lib/rake/pseudo_status.rb +8 -2
  52. data/lib/rake/rake_module.rb +34 -11
  53. data/lib/rake/rake_test_loader.rb +18 -13
  54. data/lib/rake/rule_recursion_overflow_error.rb +2 -2
  55. data/lib/rake/scope.rb +43 -0
  56. data/lib/rake/task.rb +166 -82
  57. data/lib/rake/task_argument_error.rb +1 -0
  58. data/lib/rake/task_arguments.rb +45 -14
  59. data/lib/rake/task_manager.rb +82 -50
  60. data/lib/rake/tasklib.rb +2 -12
  61. data/lib/rake/testtask.rb +68 -39
  62. data/lib/rake/thread_history_display.rb +10 -6
  63. data/lib/rake/thread_pool.rb +60 -86
  64. data/lib/rake/trace_output.rb +23 -0
  65. data/lib/rake/version.rb +6 -8
  66. data/lib/rake/win32.rb +14 -18
  67. data/rake.gemspec +36 -0
  68. metadata +64 -166
  69. data/.gemtest +0 -0
  70. data/CHANGES +0 -526
  71. data/TODO +0 -21
  72. data/doc/rake.1.gz +0 -0
  73. data/doc/release_notes/rake-0.4.14.rdoc +0 -23
  74. data/doc/release_notes/rake-0.4.15.rdoc +0 -35
  75. data/doc/release_notes/rake-0.5.0.rdoc +0 -53
  76. data/doc/release_notes/rake-0.5.3.rdoc +0 -78
  77. data/doc/release_notes/rake-0.5.4.rdoc +0 -46
  78. data/doc/release_notes/rake-0.6.0.rdoc +0 -141
  79. data/doc/release_notes/rake-0.7.0.rdoc +0 -119
  80. data/doc/release_notes/rake-0.7.1.rdoc +0 -59
  81. data/doc/release_notes/rake-0.7.2.rdoc +0 -121
  82. data/doc/release_notes/rake-0.7.3.rdoc +0 -47
  83. data/doc/release_notes/rake-0.8.0.rdoc +0 -114
  84. data/doc/release_notes/rake-0.8.2.rdoc +0 -165
  85. data/doc/release_notes/rake-0.8.3.rdoc +0 -112
  86. data/doc/release_notes/rake-0.8.4.rdoc +0 -147
  87. data/doc/release_notes/rake-0.8.5.rdoc +0 -53
  88. data/doc/release_notes/rake-0.8.6.rdoc +0 -55
  89. data/doc/release_notes/rake-0.8.7.rdoc +0 -55
  90. data/doc/release_notes/rake-0.9.0.rdoc +0 -112
  91. data/doc/release_notes/rake-0.9.1.rdoc +0 -52
  92. data/doc/release_notes/rake-0.9.2.2.rdoc +0 -55
  93. data/doc/release_notes/rake-0.9.2.rdoc +0 -49
  94. data/doc/release_notes/rake-0.9.3.rdoc +0 -102
  95. data/doc/release_notes/rake-10.0.0.rdoc +0 -178
  96. data/install.rb +0 -90
  97. data/lib/rake/alt_system.rb +0 -109
  98. data/lib/rake/contrib/compositepublisher.rb +0 -21
  99. data/lib/rake/contrib/ftptools.rb +0 -151
  100. data/lib/rake/contrib/publisher.rb +0 -73
  101. data/lib/rake/contrib/rubyforgepublisher.rb +0 -16
  102. data/lib/rake/contrib/sshpublisher.rb +0 -50
  103. data/lib/rake/ext/module.rb +0 -0
  104. data/lib/rake/ext/time.rb +0 -14
  105. data/lib/rake/pathmap.rb +0 -1
  106. data/lib/rake/ruby182_test_unit_fix.rb +0 -25
  107. data/lib/rake/runtest.rb +0 -21
  108. data/test/file_creation.rb +0 -34
  109. data/test/helper.rb +0 -522
  110. data/test/test_rake.rb +0 -40
  111. data/test/test_rake_application.rb +0 -484
  112. data/test/test_rake_application_options.rb +0 -427
  113. data/test/test_rake_backtrace.rb +0 -67
  114. data/test/test_rake_clean.rb +0 -14
  115. data/test/test_rake_definitions.rb +0 -80
  116. data/test/test_rake_directory_task.rb +0 -57
  117. data/test/test_rake_dsl.rb +0 -40
  118. data/test/test_rake_early_time.rb +0 -31
  119. data/test/test_rake_extension.rb +0 -59
  120. data/test/test_rake_file_creation_task.rb +0 -56
  121. data/test/test_rake_file_list.rb +0 -628
  122. data/test/test_rake_file_list_path_map.rb +0 -8
  123. data/test/test_rake_file_task.rb +0 -122
  124. data/test/test_rake_file_utils.rb +0 -305
  125. data/test/test_rake_ftp_file.rb +0 -59
  126. data/test/test_rake_functional.rb +0 -472
  127. data/test/test_rake_invocation_chain.rb +0 -52
  128. data/test/test_rake_makefile_loader.rb +0 -44
  129. data/test/test_rake_multi_task.rb +0 -59
  130. data/test/test_rake_name_space.rb +0 -43
  131. data/test/test_rake_package_task.rb +0 -79
  132. data/test/test_rake_path_map.rb +0 -157
  133. data/test/test_rake_path_map_explode.rb +0 -34
  134. data/test/test_rake_path_map_partial.rb +0 -18
  135. data/test/test_rake_pseudo_status.rb +0 -21
  136. data/test/test_rake_rake_test_loader.rb +0 -21
  137. data/test/test_rake_reduce_compat.rb +0 -30
  138. data/test/test_rake_require.rb +0 -40
  139. data/test/test_rake_rules.rb +0 -327
  140. data/test/test_rake_task.rb +0 -316
  141. data/test/test_rake_task_argument_parsing.rb +0 -103
  142. data/test/test_rake_task_arguments.rb +0 -88
  143. data/test/test_rake_task_lib.rb +0 -9
  144. data/test/test_rake_task_manager.rb +0 -157
  145. data/test/test_rake_task_manager_argument_resolution.rb +0 -19
  146. data/test/test_rake_task_with_arguments.rb +0 -162
  147. data/test/test_rake_test_task.rb +0 -120
  148. data/test/test_rake_thread_pool.rb +0 -146
  149. data/test/test_rake_top_level_functions.rb +0 -71
  150. data/test/test_rake_win32.rb +0 -72
  151. data/test/test_thread_history_display.rb +0 -91
@@ -1,17 +1,31 @@
1
+ # frozen_string_literal: true
1
2
  module Rake
2
3
 
3
- # Makefile loader to be used with the import file loader.
4
+ # Makefile loader to be used with the import file loader. Use this to
5
+ # import dependencies from make dependency tools:
6
+ #
7
+ # require 'rake/loaders/makefile'
8
+ #
9
+ # file ".depends.mf" => [SRC_LIST] do |t|
10
+ # sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}"
11
+ # end
12
+ #
13
+ # import ".depends.mf"
14
+ #
15
+ # See {Importing Dependencies}[link:doc/rakefile_rdoc.html#label-Importing+Dependencies]
16
+ # for further details.
17
+
4
18
  class MakefileLoader
5
19
  include Rake::DSL
6
20
 
7
- SPACE_MARK = "\0"
21
+ SPACE_MARK = "\0" # :nodoc:
8
22
 
9
23
  # Load the makefile dependencies in +fn+.
10
- def load(fn)
24
+ def load(fn) # :nodoc:
11
25
  lines = File.read fn
12
26
  lines.gsub!(/\\ /, SPACE_MARK)
13
27
  lines.gsub!(/#[^\n]*\n/m, "")
14
- lines.gsub!(/\\\n/, ' ')
28
+ lines.gsub!(/\\\n/, " ")
15
29
  lines.each_line do |line|
16
30
  process_line(line)
17
31
  end
@@ -20,8 +34,8 @@ module Rake
20
34
  private
21
35
 
22
36
  # Process one logical line of makefile data.
23
- def process_line(line)
24
- file_tasks, args = line.split(':', 2)
37
+ def process_line(line) # :nodoc:
38
+ file_tasks, args = line.split(":", 2)
25
39
  return if args.nil?
26
40
  dependents = args.split.map { |d| respace(d) }
27
41
  file_tasks.scan(/\S+/) do |file_task|
@@ -30,11 +44,11 @@ module Rake
30
44
  end
31
45
  end
32
46
 
33
- def respace(str)
34
- str.tr SPACE_MARK, ' '
47
+ def respace(str) # :nodoc:
48
+ str.tr SPACE_MARK, " "
35
49
  end
36
50
  end
37
51
 
38
52
  # Install the handler
39
- Rake.application.add_loader('mf', MakefileLoader.new)
53
+ Rake.application.add_loader("mf", MakefileLoader.new)
40
54
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Rake
2
3
 
3
4
  # Same as a regular task, but the immediate prerequisites are done in
@@ -5,9 +6,9 @@ module Rake
5
6
  #
6
7
  class MultiTask < Task
7
8
  private
9
+
8
10
  def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
9
11
  invoke_prerequisites_concurrently(task_args, invocation_chain)
10
12
  end
11
13
  end
12
-
13
14
  end
@@ -1,25 +1,38 @@
1
- module Rake
2
-
3
- # The NameSpace class will lookup task names in the the scope
4
- # defined by a +namespace+ command.
5
- #
6
- class NameSpace
7
-
8
- # Create a namespace lookup object using the given task manager
9
- # and the list of scopes.
10
- def initialize(task_manager, scope_list)
11
- @task_manager = task_manager
12
- @scope = scope_list.dup
13
- end
14
-
15
- # Lookup a task named +name+ in the namespace.
16
- def [](name)
17
- @task_manager.lookup(name, @scope)
18
- end
19
-
20
- # Return the list of tasks defined in this and nested namespaces.
21
- def tasks
22
- @task_manager.tasks_in_scope(@scope)
23
- end
1
+ # frozen_string_literal: true
2
+ ##
3
+ # The NameSpace class will lookup task names in the scope defined by a
4
+ # +namespace+ command.
5
+
6
+ class Rake::NameSpace
7
+
8
+ ##
9
+ # Create a namespace lookup object using the given task manager
10
+ # and the list of scopes.
11
+
12
+ def initialize(task_manager, scope_list)
13
+ @task_manager = task_manager
14
+ @scope = scope_list.dup
24
15
  end
16
+
17
+ ##
18
+ # Lookup a task named +name+ in the namespace.
19
+
20
+ def [](name)
21
+ @task_manager.lookup(name, @scope)
22
+ end
23
+
24
+ ##
25
+ # The scope of the namespace (a LinkedList)
26
+
27
+ def scope
28
+ @scope.dup
29
+ end
30
+
31
+ ##
32
+ # Return the list of tasks defined in this and nested namespaces.
33
+
34
+ def tasks
35
+ @task_manager.tasks_in_scope(@scope)
36
+ end
37
+
25
38
  end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  # Define a package task library to aid in the definition of
2
3
  # redistributable package files.
3
4
 
4
- require 'rake'
5
- require 'rake/tasklib'
5
+ require "rake"
6
+ require "rake/tasklib"
6
7
 
7
8
  module Rake
8
9
 
@@ -11,27 +12,27 @@ module Rake
11
12
  #
12
13
  # The PackageTask will create the following targets:
13
14
  #
14
- # [<b>:package</b>]
15
+ # +:package+ ::
15
16
  # Create all the requested package files.
16
17
  #
17
- # [<b>:clobber_package</b>]
18
+ # +:clobber_package+ ::
18
19
  # Delete all the package files. This target is automatically
19
20
  # added to the main clobber target.
20
21
  #
21
- # [<b>:repackage</b>]
22
+ # +:repackage+ ::
22
23
  # Rebuild the package files from scratch, even if they are not out
23
24
  # of date.
24
25
  #
25
- # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tgz"</b>]
26
+ # <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tgz"</tt> ::
26
27
  # Create a gzipped tar package (if <em>need_tar</em> is true).
27
28
  #
28
- # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.gz"</b>]
29
+ # <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.gz"</tt> ::
29
30
  # Create a gzipped tar package (if <em>need_tar_gz</em> is true).
30
31
  #
31
- # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.bz2"</b>]
32
+ # <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.bz2"</tt> ::
32
33
  # Create a bzip2'd tar package (if <em>need_tar_bz2</em> is true).
33
34
  #
34
- # [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.zip"</b>]
35
+ # <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.zip"</tt> ::
35
36
  # Create a zip package archive (if <em>need_zip</em> is true).
36
37
  #
37
38
  # Example:
@@ -51,15 +52,21 @@ module Rake
51
52
  # Directory used to store the package files (default is 'pkg').
52
53
  attr_accessor :package_dir
53
54
 
54
- # True if a gzipped tar file (tgz) should be produced (default is false).
55
+ # True if a gzipped tar file (tgz) should be produced (default is
56
+ # false).
55
57
  attr_accessor :need_tar
56
58
 
57
- # True if a gzipped tar file (tar.gz) should be produced (default is false).
59
+ # True if a gzipped tar file (tar.gz) should be produced (default
60
+ # is false).
58
61
  attr_accessor :need_tar_gz
59
62
 
60
- # True if a bzip2'd tar file (tar.bz2) should be produced (default is false).
63
+ # True if a bzip2'd tar file (tar.bz2) should be produced (default
64
+ # is false).
61
65
  attr_accessor :need_tar_bz2
62
66
 
67
+ # True if a xz'd tar file (tar.xz) should be produced (default is false)
68
+ attr_accessor :need_tar_xz
69
+
63
70
  # True if a zip file should be produced (default is false)
64
71
  attr_accessor :need_zip
65
72
 
@@ -72,6 +79,9 @@ module Rake
72
79
  # Zip command for zipped archives. The default is 'zip'.
73
80
  attr_accessor :zip_command
74
81
 
82
+ # True if parent directory should be omited (default is false)
83
+ attr_accessor :without_parent_dir
84
+
75
85
  # Create a Package Task with the given name and version. Use +:noversion+
76
86
  # as the version to build a package without a version or to provide a
77
87
  # fully-versioned package name.
@@ -87,13 +97,15 @@ module Rake
87
97
  @name = name
88
98
  @version = version
89
99
  @package_files = Rake::FileList.new
90
- @package_dir = 'pkg'
100
+ @package_dir = "pkg"
91
101
  @need_tar = false
92
102
  @need_tar_gz = false
93
103
  @need_tar_bz2 = false
104
+ @need_tar_xz = false
94
105
  @need_zip = false
95
- @tar_command = 'tar'
96
- @zip_command = 'zip'
106
+ @tar_command = "tar"
107
+ @zip_command = "zip"
108
+ @without_parent_dir = false
97
109
  end
98
110
 
99
111
  # Create the tasks defined by this task library.
@@ -105,47 +117,45 @@ module Rake
105
117
  task :package
106
118
 
107
119
  desc "Force a rebuild of the package files"
108
- task :repackage => [:clobber_package, :package]
120
+ task repackage: [:clobber_package, :package]
109
121
 
110
122
  desc "Remove package products"
111
123
  task :clobber_package do
112
124
  rm_r package_dir rescue nil
113
125
  end
114
126
 
115
- task :clobber => [:clobber_package]
127
+ task clobber: [:clobber_package]
116
128
 
117
129
  [
118
130
  [need_tar, tgz_file, "z"],
119
131
  [need_tar_gz, tar_gz_file, "z"],
120
- [need_tar_bz2, tar_bz2_file, "j"]
121
- ].each do |(need, file, flag)|
132
+ [need_tar_bz2, tar_bz2_file, "j"],
133
+ [need_tar_xz, tar_xz_file, "J"]
134
+ ].each do |need, file, flag|
122
135
  if need
123
- task :package => ["#{package_dir}/#{file}"]
124
- file "#{package_dir}/#{file}" => [package_dir_path] + package_files do
125
- chdir(package_dir) do
126
- sh %{#{@tar_command} #{flag}cvf #{file} #{package_name}}
127
- end
136
+ task package: ["#{package_dir}/#{file}"]
137
+ file "#{package_dir}/#{file}" =>
138
+ [package_dir_path] + package_files do
139
+ chdir(working_dir) { sh @tar_command, "#{flag}cvf", file, target_dir }
140
+ mv "#{package_dir_path}/#{target_dir}", package_dir if without_parent_dir
128
141
  end
129
142
  end
130
143
  end
131
144
 
132
145
  if need_zip
133
- task :package => ["#{package_dir}/#{zip_file}"]
134
- file "#{package_dir}/#{zip_file}" => [package_dir_path] + package_files do
135
- chdir(package_dir) do
136
- sh %{#{@zip_command} -r #{zip_file} #{package_name}}
137
- end
146
+ task package: ["#{package_dir}/#{zip_file}"]
147
+ file "#{package_dir}/#{zip_file}" =>
148
+ [package_dir_path] + package_files do
149
+ chdir(working_dir) { sh @zip_command, "-r", zip_file, target_dir }
150
+ mv "#{package_dir_path}/#{zip_file}", package_dir if without_parent_dir
138
151
  end
139
152
  end
140
153
 
141
- directory package_dir
142
-
143
- file package_dir_path => @package_files do
144
- mkdir_p package_dir rescue nil
154
+ directory package_dir_path => @package_files do
145
155
  @package_files.each do |fn|
146
156
  f = File.join(package_dir_path, fn)
147
157
  fdir = File.dirname(f)
148
- mkdir_p(fdir) if !File.exist?(fdir)
158
+ mkdir_p(fdir) unless File.exist?(fdir)
149
159
  if File.directory?(fn)
150
160
  mkdir_p(f)
151
161
  else
@@ -157,29 +167,56 @@ module Rake
157
167
  self
158
168
  end
159
169
 
170
+ # The name of this package
171
+
160
172
  def package_name
161
173
  @version ? "#{@name}-#{@version}" : @name
162
174
  end
163
175
 
176
+ # The directory this package will be built in
177
+
164
178
  def package_dir_path
165
179
  "#{package_dir}/#{package_name}"
166
180
  end
167
181
 
182
+ # The package name with .tgz added
183
+
168
184
  def tgz_file
169
185
  "#{package_name}.tgz"
170
186
  end
171
187
 
188
+ # The package name with .tar.gz added
189
+
172
190
  def tar_gz_file
173
191
  "#{package_name}.tar.gz"
174
192
  end
175
193
 
194
+ # The package name with .tar.bz2 added
195
+
176
196
  def tar_bz2_file
177
197
  "#{package_name}.tar.bz2"
178
198
  end
179
199
 
200
+ # The package name with .tar.xz added
201
+
202
+ def tar_xz_file
203
+ "#{package_name}.tar.xz"
204
+ end
205
+
206
+ # The package name with .zip added
207
+
180
208
  def zip_file
181
209
  "#{package_name}.zip"
182
210
  end
211
+
212
+ def working_dir
213
+ without_parent_dir ? package_dir_path : package_dir
214
+ end
215
+
216
+ # target directory relative to working_dir
217
+ def target_dir
218
+ without_parent_dir ? "." : package_name
219
+ end
183
220
  end
184
221
 
185
222
  end
@@ -1,13 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  # Defines a :phony task that you can use as a dependency. This allows
2
3
  # file-based tasks to use non-file-based tasks as prerequisites
3
4
  # without forcing them to rebuild.
4
5
  #
5
6
  # See FileTask#out_of_date? and Task#timestamp for more info.
6
7
 
7
- require 'rake'
8
+ require "rake"
8
9
 
9
10
  task :phony
10
11
 
11
- def (Rake::Task[:phony]).timestamp
12
- Time.at 0
12
+ Rake::Task[:phony].tap do |task|
13
+ def task.timestamp # :nodoc:
14
+ Time.at 0
15
+ end
13
16
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+
4
+ # Include PrivateReader to use +private_reader+.
5
+ module PrivateReader # :nodoc: all
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ # Declare a list of private accessors
14
+ def private_reader(*names)
15
+ attr_reader(*names)
16
+ private(*names)
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ module Rake
3
+
4
+ # A Promise object represents a promise to do work (a chore) in the
5
+ # future. The promise is created with a block and a list of
6
+ # arguments for the block. Calling value will return the value of
7
+ # the promised chore.
8
+ #
9
+ # Used by ThreadPool.
10
+ #
11
+ class Promise # :nodoc: all
12
+ NOT_SET = Object.new.freeze # :nodoc:
13
+
14
+ attr_accessor :recorder
15
+
16
+ # Create a promise to do the chore specified by the block.
17
+ def initialize(args, &block)
18
+ @mutex = Mutex.new
19
+ @result = NOT_SET
20
+ @error = NOT_SET
21
+ @args = args
22
+ @block = block
23
+ end
24
+
25
+ # Return the value of this promise.
26
+ #
27
+ # If the promised chore is not yet complete, then do the work
28
+ # synchronously. We will wait.
29
+ def value
30
+ unless complete?
31
+ stat :sleeping_on, item_id: object_id
32
+ @mutex.synchronize do
33
+ stat :has_lock_on, item_id: object_id
34
+ chore
35
+ stat :releasing_lock_on, item_id: object_id
36
+ end
37
+ end
38
+ error? ? raise(@error) : @result
39
+ end
40
+
41
+ # If no one else is working this promise, go ahead and do the chore.
42
+ def work
43
+ stat :attempting_lock_on, item_id: object_id
44
+ if @mutex.try_lock
45
+ stat :has_lock_on, item_id: object_id
46
+ chore
47
+ stat :releasing_lock_on, item_id: object_id
48
+ @mutex.unlock
49
+ else
50
+ stat :bailed_on, item_id: object_id
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # Perform the chore promised
57
+ def chore
58
+ if complete?
59
+ stat :found_completed, item_id: object_id
60
+ return
61
+ end
62
+ stat :will_execute, item_id: object_id
63
+ begin
64
+ @result = @block.call(*@args)
65
+ rescue Exception => e
66
+ @error = e
67
+ end
68
+ stat :did_execute, item_id: object_id
69
+ discard
70
+ end
71
+
72
+ # Do we have a result for the promise
73
+ def result?
74
+ !@result.equal?(NOT_SET)
75
+ end
76
+
77
+ # Did the promise throw an error
78
+ def error?
79
+ !@error.equal?(NOT_SET)
80
+ end
81
+
82
+ # Are we done with the promise
83
+ def complete?
84
+ result? || error?
85
+ end
86
+
87
+ # free up these items for the GC
88
+ def discard
89
+ @args = nil
90
+ @block = nil
91
+ end
92
+
93
+ # Record execution statistics if there is a recorder
94
+ def stat(*args)
95
+ @recorder.call(*args) if @recorder
96
+ end
97
+
98
+ end
99
+
100
+ end