rake 11.3.0 → 13.0.1
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.
- checksums.yaml +5 -5
- data/.github/workflows/macos.yml +22 -0
- data/.github/workflows/ubuntu-rvm.yml +28 -0
- data/.github/workflows/ubuntu.yml +20 -0
- data/.github/workflows/windows.yml +20 -0
- data/CONTRIBUTING.rdoc +11 -4
- data/Gemfile +8 -1
- data/History.rdoc +171 -37
- data/README.rdoc +9 -11
- data/Rakefile +21 -13
- data/bin/bundle +105 -0
- data/bin/rake +29 -0
- data/bin/rdoc +29 -0
- data/bin/rubocop +29 -0
- data/doc/jamis.rb +1 -0
- data/doc/rake.1 +139 -124
- data/doc/rakefile.rdoc +2 -4
- data/exe/rake +1 -1
- data/lib/rake/application.rb +119 -79
- data/lib/rake/backtrace.rb +3 -2
- data/lib/rake/clean.rb +7 -5
- data/lib/rake/cloneable.rb +1 -0
- data/lib/rake/cpu_counter.rb +3 -2
- data/lib/rake/default_loader.rb +1 -0
- data/lib/rake/dsl_definition.rb +5 -4
- data/lib/rake/early_time.rb +1 -0
- data/lib/rake/ext/core.rb +1 -0
- data/lib/rake/ext/string.rb +22 -21
- data/lib/rake/file_creation_task.rb +4 -3
- data/lib/rake/file_list.rb +13 -14
- data/lib/rake/file_task.rb +12 -4
- data/lib/rake/file_utils.rb +17 -22
- data/lib/rake/file_utils_ext.rb +8 -18
- data/lib/rake/invocation_chain.rb +1 -0
- data/lib/rake/invocation_exception_mixin.rb +1 -0
- data/lib/rake/late_time.rb +2 -1
- data/lib/rake/linked_list.rb +1 -0
- data/lib/rake/loaders/makefile.rb +5 -4
- data/lib/rake/multi_task.rb +2 -1
- data/lib/rake/name_space.rb +1 -1
- data/lib/rake/packagetask.rb +28 -16
- data/lib/rake/phony.rb +2 -1
- data/lib/rake/private_reader.rb +1 -0
- data/lib/rake/promise.rb +13 -12
- data/lib/rake/pseudo_status.rb +1 -0
- data/lib/rake/rake_module.rb +30 -1
- data/lib/rake/rake_test_loader.rb +18 -12
- data/lib/rake/rule_recursion_overflow_error.rb +2 -1
- data/lib/rake/scope.rb +3 -2
- data/lib/rake/task.rb +70 -27
- data/lib/rake/task_argument_error.rb +1 -0
- data/lib/rake/task_arguments.rb +10 -4
- data/lib/rake/task_manager.rb +54 -39
- data/lib/rake/tasklib.rb +2 -1
- data/lib/rake/testtask.rb +28 -16
- data/lib/rake/thread_history_display.rb +4 -3
- data/lib/rake/thread_pool.rb +15 -14
- data/lib/rake/trace_output.rb +1 -0
- data/lib/rake/version.rb +3 -2
- data/lib/rake/win32.rb +9 -8
- data/lib/rake.rb +34 -33
- data/rake.gemspec +22 -9
- metadata +25 -108
- data/.gitignore +0 -14
- data/.rubocop.yml +0 -18
- data/.travis.yml +0 -28
- data/appveyor.yml +0 -22
- data/doc/release_notes/README.md +0 -4
- data/doc/release_notes/rake-0.4.14.rdoc +0 -23
- data/doc/release_notes/rake-0.4.15.rdoc +0 -35
- data/doc/release_notes/rake-0.5.0.rdoc +0 -53
- data/doc/release_notes/rake-0.5.3.rdoc +0 -78
- data/doc/release_notes/rake-0.5.4.rdoc +0 -46
- data/doc/release_notes/rake-0.6.0.rdoc +0 -141
- data/doc/release_notes/rake-0.7.0.rdoc +0 -119
- data/doc/release_notes/rake-0.7.1.rdoc +0 -59
- data/doc/release_notes/rake-0.7.2.rdoc +0 -121
- data/doc/release_notes/rake-0.7.3.rdoc +0 -47
- data/doc/release_notes/rake-0.8.0.rdoc +0 -114
- data/doc/release_notes/rake-0.8.2.rdoc +0 -165
- data/doc/release_notes/rake-0.8.3.rdoc +0 -112
- data/doc/release_notes/rake-0.8.4.rdoc +0 -147
- data/doc/release_notes/rake-0.8.5.rdoc +0 -53
- data/doc/release_notes/rake-0.8.6.rdoc +0 -37
- data/doc/release_notes/rake-0.8.7.rdoc +0 -55
- data/doc/release_notes/rake-0.9.0.rdoc +0 -112
- data/doc/release_notes/rake-0.9.1.rdoc +0 -52
- data/doc/release_notes/rake-0.9.2.2.rdoc +0 -55
- data/doc/release_notes/rake-0.9.2.rdoc +0 -49
- data/doc/release_notes/rake-0.9.3.rdoc +0 -102
- data/doc/release_notes/rake-0.9.4.rdoc +0 -60
- data/doc/release_notes/rake-0.9.5.rdoc +0 -55
- data/doc/release_notes/rake-0.9.6.rdoc +0 -64
- data/doc/release_notes/rake-10.0.0.rdoc +0 -178
- data/doc/release_notes/rake-10.0.1.rdoc +0 -58
- data/doc/release_notes/rake-10.0.2.rdoc +0 -53
- data/doc/release_notes/rake-10.0.3.rdoc +0 -191
- data/doc/release_notes/rake-10.1.0.rdoc +0 -61
- data/lib/rake/contrib/compositepublisher.rb +0 -21
- data/lib/rake/contrib/ftptools.rb +0 -137
- data/lib/rake/contrib/sshpublisher.rb +0 -60
- data/lib/rake/ext/pathname.rb +0 -25
data/lib/rake/file_utils_ext.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "rake/file_utils"
|
|
2
3
|
|
|
3
4
|
module Rake
|
|
4
5
|
#
|
|
@@ -22,19 +23,18 @@ module Rake
|
|
|
22
23
|
opts = FileUtils.options_of name
|
|
23
24
|
default_options = []
|
|
24
25
|
if opts.include?("verbose")
|
|
25
|
-
default_options <<
|
|
26
|
+
default_options << "verbose: FileUtilsExt.verbose_flag"
|
|
26
27
|
end
|
|
27
28
|
if opts.include?("noop")
|
|
28
|
-
default_options <<
|
|
29
|
+
default_options << "noop: FileUtilsExt.nowrite_flag"
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
next if default_options.empty?
|
|
32
33
|
module_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
33
|
-
def #{name}(
|
|
34
|
-
super(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
), &block)
|
|
34
|
+
def #{name}(*args, **options, &block)
|
|
35
|
+
super(*args,
|
|
36
|
+
#{default_options.join(', ')},
|
|
37
|
+
**options, &block)
|
|
38
38
|
end
|
|
39
39
|
EOS
|
|
40
40
|
end
|
|
@@ -112,16 +112,6 @@ module Rake
|
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
-
# Merge the given options with the default values.
|
|
116
|
-
def rake_merge_option(args, defaults)
|
|
117
|
-
if Hash === args.last
|
|
118
|
-
defaults.update(args.last)
|
|
119
|
-
args.pop
|
|
120
|
-
end
|
|
121
|
-
args.push defaults
|
|
122
|
-
args
|
|
123
|
-
end
|
|
124
|
-
|
|
125
115
|
# Send the message to the default rake output (which is $stderr).
|
|
126
116
|
def rake_output_message(message)
|
|
127
117
|
$stderr.puts(message)
|
data/lib/rake/late_time.rb
CHANGED
data/lib/rake/linked_list.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Rake
|
|
2
3
|
|
|
3
4
|
# Makefile loader to be used with the import file loader. Use this to
|
|
@@ -24,7 +25,7 @@ module Rake
|
|
|
24
25
|
lines = File.read fn
|
|
25
26
|
lines.gsub!(/\\ /, SPACE_MARK)
|
|
26
27
|
lines.gsub!(/#[^\n]*\n/m, "")
|
|
27
|
-
lines.gsub!(/\\\n/,
|
|
28
|
+
lines.gsub!(/\\\n/, " ")
|
|
28
29
|
lines.each_line do |line|
|
|
29
30
|
process_line(line)
|
|
30
31
|
end
|
|
@@ -34,7 +35,7 @@ module Rake
|
|
|
34
35
|
|
|
35
36
|
# Process one logical line of makefile data.
|
|
36
37
|
def process_line(line) # :nodoc:
|
|
37
|
-
file_tasks, args = line.split(
|
|
38
|
+
file_tasks, args = line.split(":", 2)
|
|
38
39
|
return if args.nil?
|
|
39
40
|
dependents = args.split.map { |d| respace(d) }
|
|
40
41
|
file_tasks.scan(/\S+/) do |file_task|
|
|
@@ -44,10 +45,10 @@ module Rake
|
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
def respace(str) # :nodoc:
|
|
47
|
-
str.tr SPACE_MARK,
|
|
48
|
+
str.tr SPACE_MARK, " "
|
|
48
49
|
end
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
# Install the handler
|
|
52
|
-
Rake.application.add_loader(
|
|
53
|
+
Rake.application.add_loader("mf", MakefileLoader.new)
|
|
53
54
|
end
|
data/lib/rake/multi_task.rb
CHANGED
|
@@ -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
|
data/lib/rake/name_space.rb
CHANGED
data/lib/rake/packagetask.rb
CHANGED
|
@@ -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
|
|
5
|
-
require
|
|
5
|
+
require "rake"
|
|
6
|
+
require "rake/tasklib"
|
|
6
7
|
|
|
7
8
|
module Rake
|
|
8
9
|
|
|
@@ -78,6 +79,9 @@ module Rake
|
|
|
78
79
|
# Zip command for zipped archives. The default is 'zip'.
|
|
79
80
|
attr_accessor :zip_command
|
|
80
81
|
|
|
82
|
+
# True if parent directory should be omited (default is false)
|
|
83
|
+
attr_accessor :without_parent_dir
|
|
84
|
+
|
|
81
85
|
# Create a Package Task with the given name and version. Use +:noversion+
|
|
82
86
|
# as the version to build a package without a version or to provide a
|
|
83
87
|
# fully-versioned package name.
|
|
@@ -93,14 +97,15 @@ module Rake
|
|
|
93
97
|
@name = name
|
|
94
98
|
@version = version
|
|
95
99
|
@package_files = Rake::FileList.new
|
|
96
|
-
@package_dir =
|
|
100
|
+
@package_dir = "pkg"
|
|
97
101
|
@need_tar = false
|
|
98
102
|
@need_tar_gz = false
|
|
99
103
|
@need_tar_bz2 = false
|
|
100
104
|
@need_tar_xz = false
|
|
101
105
|
@need_zip = false
|
|
102
|
-
@tar_command =
|
|
103
|
-
@zip_command =
|
|
106
|
+
@tar_command = "tar"
|
|
107
|
+
@zip_command = "zip"
|
|
108
|
+
@without_parent_dir = false
|
|
104
109
|
end
|
|
105
110
|
|
|
106
111
|
# Create the tasks defined by this task library.
|
|
@@ -112,39 +117,37 @@ module Rake
|
|
|
112
117
|
task :package
|
|
113
118
|
|
|
114
119
|
desc "Force a rebuild of the package files"
|
|
115
|
-
task :
|
|
120
|
+
task repackage: [:clobber_package, :package]
|
|
116
121
|
|
|
117
122
|
desc "Remove package products"
|
|
118
123
|
task :clobber_package do
|
|
119
124
|
rm_r package_dir rescue nil
|
|
120
125
|
end
|
|
121
126
|
|
|
122
|
-
task :
|
|
127
|
+
task clobber: [:clobber_package]
|
|
123
128
|
|
|
124
129
|
[
|
|
125
130
|
[need_tar, tgz_file, "z"],
|
|
126
131
|
[need_tar_gz, tar_gz_file, "z"],
|
|
127
132
|
[need_tar_bz2, tar_bz2_file, "j"],
|
|
128
133
|
[need_tar_xz, tar_xz_file, "J"]
|
|
129
|
-
].each do |
|
|
134
|
+
].each do |need, file, flag|
|
|
130
135
|
if need
|
|
131
|
-
task :
|
|
136
|
+
task package: ["#{package_dir}/#{file}"]
|
|
132
137
|
file "#{package_dir}/#{file}" =>
|
|
133
138
|
[package_dir_path] + package_files do
|
|
134
|
-
chdir(
|
|
135
|
-
|
|
136
|
-
end
|
|
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
|
|
137
141
|
end
|
|
138
142
|
end
|
|
139
143
|
end
|
|
140
144
|
|
|
141
145
|
if need_zip
|
|
142
|
-
task :
|
|
146
|
+
task package: ["#{package_dir}/#{zip_file}"]
|
|
143
147
|
file "#{package_dir}/#{zip_file}" =>
|
|
144
148
|
[package_dir_path] + package_files do
|
|
145
|
-
chdir(
|
|
146
|
-
|
|
147
|
-
end
|
|
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
|
|
148
151
|
end
|
|
149
152
|
end
|
|
150
153
|
|
|
@@ -205,6 +208,15 @@ module Rake
|
|
|
205
208
|
def zip_file
|
|
206
209
|
"#{package_name}.zip"
|
|
207
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
|
|
208
220
|
end
|
|
209
221
|
|
|
210
222
|
end
|
data/lib/rake/phony.rb
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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
|
|
8
|
+
require "rake"
|
|
8
9
|
|
|
9
10
|
task :phony
|
|
10
11
|
|
data/lib/rake/private_reader.rb
CHANGED
data/lib/rake/promise.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Rake
|
|
2
3
|
|
|
3
4
|
# A Promise object represents a promise to do work (a chore) in the
|
|
@@ -27,11 +28,11 @@ module Rake
|
|
|
27
28
|
# synchronously. We will wait.
|
|
28
29
|
def value
|
|
29
30
|
unless complete?
|
|
30
|
-
stat :sleeping_on, :
|
|
31
|
+
stat :sleeping_on, item_id: object_id
|
|
31
32
|
@mutex.synchronize do
|
|
32
|
-
stat :has_lock_on, :
|
|
33
|
+
stat :has_lock_on, item_id: object_id
|
|
33
34
|
chore
|
|
34
|
-
stat :releasing_lock_on, :
|
|
35
|
+
stat :releasing_lock_on, item_id: object_id
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
38
|
error? ? raise(@error) : @result
|
|
@@ -39,14 +40,14 @@ module Rake
|
|
|
39
40
|
|
|
40
41
|
# If no one else is working this promise, go ahead and do the chore.
|
|
41
42
|
def work
|
|
42
|
-
stat :attempting_lock_on, :
|
|
43
|
+
stat :attempting_lock_on, item_id: object_id
|
|
43
44
|
if @mutex.try_lock
|
|
44
|
-
stat :has_lock_on, :
|
|
45
|
+
stat :has_lock_on, item_id: object_id
|
|
45
46
|
chore
|
|
46
|
-
stat :releasing_lock_on, :
|
|
47
|
+
stat :releasing_lock_on, item_id: object_id
|
|
47
48
|
@mutex.unlock
|
|
48
49
|
else
|
|
49
|
-
stat :bailed_on, :
|
|
50
|
+
stat :bailed_on, item_id: object_id
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
@@ -55,27 +56,27 @@ module Rake
|
|
|
55
56
|
# Perform the chore promised
|
|
56
57
|
def chore
|
|
57
58
|
if complete?
|
|
58
|
-
stat :found_completed, :
|
|
59
|
+
stat :found_completed, item_id: object_id
|
|
59
60
|
return
|
|
60
61
|
end
|
|
61
|
-
stat :will_execute, :
|
|
62
|
+
stat :will_execute, item_id: object_id
|
|
62
63
|
begin
|
|
63
64
|
@result = @block.call(*@args)
|
|
64
65
|
rescue Exception => e
|
|
65
66
|
@error = e
|
|
66
67
|
end
|
|
67
|
-
stat :did_execute, :
|
|
68
|
+
stat :did_execute, item_id: object_id
|
|
68
69
|
discard
|
|
69
70
|
end
|
|
70
71
|
|
|
71
72
|
# Do we have a result for the promise
|
|
72
73
|
def result?
|
|
73
|
-
|
|
74
|
+
!@result.equal?(NOT_SET)
|
|
74
75
|
end
|
|
75
76
|
|
|
76
77
|
# Did the promise throw an error
|
|
77
78
|
def error?
|
|
78
|
-
|
|
79
|
+
!@error.equal?(NOT_SET)
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
# Are we done with the promise
|
data/lib/rake/pseudo_status.rb
CHANGED
data/lib/rake/rake_module.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "rake/application"
|
|
2
3
|
|
|
3
4
|
module Rake
|
|
4
5
|
|
|
@@ -33,6 +34,34 @@ module Rake
|
|
|
33
34
|
application.options.rakelib ||= []
|
|
34
35
|
application.options.rakelib.concat(files)
|
|
35
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
|
|
36
65
|
end
|
|
37
66
|
|
|
38
67
|
end
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "rake"
|
|
2
3
|
|
|
3
4
|
# Load the test files from the command line.
|
|
4
5
|
argv = ARGV.select do |argument|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
false
|
|
16
|
+
else
|
|
17
|
+
require File.expand_path argument
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
false
|
|
20
|
+
end
|
|
21
|
+
rescue LoadError => e
|
|
22
|
+
raise unless e.path
|
|
23
|
+
abort "\nFile does not exist: #{e.path}\n\n"
|
|
18
24
|
end
|
|
19
25
|
end
|
|
20
26
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Rake
|
|
2
3
|
|
|
3
4
|
# Error indicating a recursion overflow error in task selection.
|
|
@@ -12,7 +13,7 @@ module Rake
|
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def message
|
|
15
|
-
super + ": [" + @targets.reverse.join(
|
|
16
|
+
super + ": [" + @targets.reverse.join(" => ") + "]"
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
|
data/lib/rake/scope.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Rake
|
|
2
3
|
class Scope < LinkedList # :nodoc: all
|
|
3
4
|
|
|
4
5
|
# Path for the scope.
|
|
5
6
|
def path
|
|
6
|
-
map
|
|
7
|
+
map(&:to_s).reverse.join(":")
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
# Path for the scope + the named path.
|
|
@@ -15,7 +16,7 @@ module Rake
|
|
|
15
16
|
# this trim beyond the toplevel scope.
|
|
16
17
|
def trim(n)
|
|
17
18
|
result = self
|
|
18
|
-
while n > 0 && !
|
|
19
|
+
while n > 0 && !result.empty?
|
|
19
20
|
result = result.tail
|
|
20
21
|
n -= 1
|
|
21
22
|
end
|