rake 10.1.1 → 10.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rake might be problematic. Click here for more details.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/.rubocop.yml +27 -0
- data/.togglerc +7 -0
- data/Gemfile +5 -0
- data/{CHANGES → History.rdoc} +84 -54
- data/Manifest.txt +161 -0
- data/README.rdoc +9 -10
- data/Rakefile +34 -337
- data/doc/command_line_usage.rdoc +16 -10
- data/doc/rake.1.gz +0 -0
- data/doc/rakefile.rdoc +72 -36
- data/doc/release_notes/rake-0.5.3.rdoc +1 -1
- data/doc/release_notes/rake-0.5.4.rdoc +1 -1
- data/doc/release_notes/rake-0.8.6.rdoc +1 -19
- data/doc/release_notes/rake-0.9.2.2.rdoc +2 -2
- data/doc/release_notes/rake-0.9.4.rdoc +0 -50
- data/doc/release_notes/rake-0.9.5.rdoc +0 -59
- data/doc/release_notes/rake-0.9.6.rdoc +0 -63
- data/doc/release_notes/rake-10.0.1.rdoc +2 -131
- data/doc/release_notes/rake-10.0.2.rdoc +2 -140
- data/doc/release_notes/rake-10.1.0.rdoc +2 -2
- data/lib/rake.rb +6 -1
- data/lib/rake/alt_system.rb +5 -3
- data/lib/rake/application.rb +102 -60
- data/lib/rake/backtrace.rb +1 -1
- data/lib/rake/cloneable.rb +3 -3
- data/lib/rake/contrib/.document +0 -0
- data/lib/rake/contrib/ftptools.rb +3 -5
- data/lib/rake/contrib/publisher.rb +12 -4
- data/lib/rake/contrib/rubyforgepublisher.rb +3 -1
- data/lib/rake/contrib/sshpublisher.rb +13 -2
- data/lib/rake/contrib/sys.rb +2 -0
- data/lib/rake/cpu_counter.rb +104 -0
- data/lib/rake/default_loader.rb +4 -0
- data/lib/rake/dsl_definition.rb +58 -17
- data/lib/rake/early_time.rb +4 -1
- data/lib/rake/ext/core.rb +2 -5
- data/lib/rake/ext/module.rb +1 -0
- data/lib/rake/ext/string.rb +35 -28
- data/lib/rake/ext/time.rb +1 -1
- data/lib/rake/file_list.rb +7 -9
- data/lib/rake/file_task.rb +1 -1
- data/lib/rake/gempackagetask.rb +3 -1
- data/lib/rake/invocation_chain.rb +0 -1
- data/lib/rake/linked_list.rb +1 -1
- data/lib/rake/packagetask.rb +19 -7
- data/lib/rake/pathmap.rb +2 -0
- data/lib/rake/pseudo_status.rb +2 -2
- data/lib/rake/rake_module.rb +6 -5
- data/lib/rake/rdoctask.rb +2 -0
- data/lib/rake/ruby182_test_unit_fix.rb +2 -0
- data/lib/rake/runtest.rb +6 -1
- data/lib/rake/scope.rb +1 -1
- data/lib/rake/task.rb +14 -9
- data/lib/rake/task_arguments.rb +19 -10
- data/lib/rake/task_manager.rb +20 -8
- data/lib/rake/tasklib.rb +2 -0
- data/lib/rake/testtask.rb +20 -9
- data/lib/rake/thread_pool.rb +13 -10
- data/lib/rake/trace_output.rb +1 -1
- data/lib/rake/version.rb +0 -2
- data/lib/rake/win32.rb +1 -1
- data/rakelib/publish.rake +20 -0
- data/rakelib/test_times.rake +25 -0
- data/test/helper.rb +6 -7
- data/test/support/rakefile_definitions.rb +34 -0
- data/test/test_rake_application.rb +89 -31
- data/test/test_rake_application_options.rb +13 -4
- data/test/test_rake_backtrace.rb +6 -2
- data/test/test_rake_clean.rb +3 -3
- data/test/test_rake_cpu_counter.rb +42 -0
- data/test/test_rake_file_task.rb +10 -0
- data/test/test_rake_functional.rb +17 -1
- data/test/test_rake_path_map.rb +2 -2
- data/test/test_rake_rules.rb +26 -0
- data/test/test_rake_task.rb +16 -0
- data/test/test_rake_task_argument_parsing.rb +6 -0
- data/test/test_rake_task_arguments.rb +6 -0
- data/test/test_rake_task_manager.rb +20 -0
- data/test/test_rake_test_task.rb +23 -1
- metadata +196 -72
- metadata.gz.sig +0 -0
- data/TODO +0 -21
- data/install.rb +0 -80
data/lib/rake/ext/module.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
# TODO: remove in Rake 11
|
data/lib/rake/ext/string.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
require 'rake/ext/core'
|
2
2
|
|
3
|
-
######################################################################
|
4
|
-
# Rake extension methods for String.
|
5
|
-
#
|
6
3
|
class String
|
7
4
|
|
8
5
|
rake_extension("ext") do
|
@@ -11,6 +8,8 @@ class String
|
|
11
8
|
# is not given, or is the empty string, remove any existing extension.
|
12
9
|
#
|
13
10
|
# +ext+ is a user added method for the String class.
|
11
|
+
#
|
12
|
+
# This String extension comes from Rake
|
14
13
|
def ext(newext='')
|
15
14
|
return self.dup if ['.', '..'].include? self
|
16
15
|
newext = (newext =~ /^\./) ? newext : ("." + newext) if newext != ''
|
@@ -20,6 +19,8 @@ class String
|
|
20
19
|
|
21
20
|
rake_extension("pathmap") do
|
22
21
|
# Explode a path into individual components. Used by +pathmap+.
|
22
|
+
#
|
23
|
+
# This String extension comes from Rake
|
23
24
|
def pathmap_explode
|
24
25
|
head, tail = File.split(self)
|
25
26
|
return [self] if head == self
|
@@ -32,6 +33,8 @@ class String
|
|
32
33
|
# Extract a partial path from the path. Include +n+ directories from the
|
33
34
|
# front end (left hand side) if +n+ is positive. Include |+n+|
|
34
35
|
# directories from the back end (right hand side) if +n+ is negative.
|
36
|
+
#
|
37
|
+
# This String extension comes from Rake
|
35
38
|
def pathmap_partial(n)
|
36
39
|
dirs = File.dirname(self).pathmap_explode
|
37
40
|
partial_dirs =
|
@@ -48,6 +51,8 @@ class String
|
|
48
51
|
|
49
52
|
# Preform the pathmap replacement operations on the given path. The
|
50
53
|
# patterns take the form 'pat1,rep1;pat2,rep2...'.
|
54
|
+
#
|
55
|
+
# This String extension comes from Rake
|
51
56
|
def pathmap_replace(patterns, &block)
|
52
57
|
result = self
|
53
58
|
patterns.split(';').each do |pair|
|
@@ -69,35 +74,36 @@ class String
|
|
69
74
|
# controls the details of the mapping. The following special patterns are
|
70
75
|
# recognized:
|
71
76
|
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
# The
|
85
|
-
# number is positive, only return (up to) +n+ directories in the
|
86
|
-
# starting from the left hand side. If +n+ is negative, return (up
|
87
|
-
#
|
77
|
+
# <tt>%p</tt> :: The complete path.
|
78
|
+
# <tt>%f</tt> :: The base file name of the path, with its file extension,
|
79
|
+
# but without any directories.
|
80
|
+
# <tt>%n</tt> :: The file name of the path without its file extension.
|
81
|
+
# <tt>%d</tt> :: The directory list of the path.
|
82
|
+
# <tt>%x</tt> :: The file extension of the path. An empty string if there
|
83
|
+
# is no extension.
|
84
|
+
# <tt>%X</tt> :: Everything *but* the file extension.
|
85
|
+
# <tt>%s</tt> :: The alternate file separator if defined, otherwise use #
|
86
|
+
# the standard file separator.
|
87
|
+
# <tt>%%</tt> :: A percent sign.
|
88
|
+
#
|
89
|
+
# The <tt>%d</tt> specifier can also have a numeric prefix (e.g. '%2d').
|
90
|
+
# If the number is positive, only return (up to) +n+ directories in the
|
91
|
+
# path, starting from the left hand side. If +n+ is negative, return (up
|
92
|
+
# to) +n+ directories from the right hand side of the path.
|
88
93
|
#
|
89
94
|
# Examples:
|
90
95
|
#
|
91
96
|
# 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
|
92
97
|
# 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
|
93
98
|
#
|
94
|
-
# Also the
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
# "%{old,new}d").
|
100
|
-
# semi-colons (e.g.
|
99
|
+
# Also the <tt>%d</tt>, <tt>%p</tt>, <tt>%f</tt>, <tt>%n</tt>,
|
100
|
+
# <tt>%x</tt>, and <tt>%X</tt> operators can take a pattern/replacement
|
101
|
+
# argument to perform simple string substitutions on a particular part of
|
102
|
+
# the path. The pattern and replacement are separated by a comma and are
|
103
|
+
# enclosed by curly braces. The replacement spec comes after the %
|
104
|
+
# character but before the operator letter. (e.g. "%{old,new}d").
|
105
|
+
# Multiple replacement specs should be separated by semi-colons (e.g.
|
106
|
+
# "%{old,new;src,bin}d").
|
101
107
|
#
|
102
108
|
# Regular expressions may be used for the pattern, and back refs may be
|
103
109
|
# used in the replacement text. Curly braces, commas and semi-colons are
|
@@ -106,11 +112,11 @@ class String
|
|
106
112
|
#
|
107
113
|
# For example:
|
108
114
|
#
|
109
|
-
# "src/org/onestepback/proj/A.java".pathmap("%{^src,
|
115
|
+
# "src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class")
|
110
116
|
#
|
111
117
|
# returns:
|
112
118
|
#
|
113
|
-
# "
|
119
|
+
# "class/org/onestepback/proj/A.class"
|
114
120
|
#
|
115
121
|
# If the replacement text is '*', then a block may be provided to perform
|
116
122
|
# some arbitrary calculation for the replacement.
|
@@ -125,6 +131,7 @@ class String
|
|
125
131
|
#
|
126
132
|
# "/path/to/file.txt"
|
127
133
|
#
|
134
|
+
# This String extension comes from Rake
|
128
135
|
def pathmap(spec=nil, &block)
|
129
136
|
return self if spec.nil?
|
130
137
|
result = ''
|
data/lib/rake/ext/time.rb
CHANGED
data/lib/rake/file_list.rb
CHANGED
@@ -2,10 +2,10 @@ require 'rake/cloneable'
|
|
2
2
|
require 'rake/file_utils_ext'
|
3
3
|
require 'rake/pathmap'
|
4
4
|
|
5
|
-
|
5
|
+
|
6
6
|
module Rake
|
7
7
|
|
8
|
-
|
8
|
+
##
|
9
9
|
# A FileList is essentially an array with a few helper methods defined to
|
10
10
|
# make file manipulation a bit easier.
|
11
11
|
#
|
@@ -156,7 +156,6 @@ module Rake
|
|
156
156
|
self
|
157
157
|
end
|
158
158
|
|
159
|
-
|
160
159
|
# Clear all the exclude patterns so that we exclude nothing.
|
161
160
|
def clear_exclude
|
162
161
|
@exclude_patterns = []
|
@@ -164,7 +163,7 @@ module Rake
|
|
164
163
|
self
|
165
164
|
end
|
166
165
|
|
167
|
-
#
|
166
|
+
# A FileList is equal through array equality.
|
168
167
|
def ==(array)
|
169
168
|
to_ary == array
|
170
169
|
end
|
@@ -208,7 +207,7 @@ module Rake
|
|
208
207
|
self
|
209
208
|
end
|
210
209
|
|
211
|
-
def resolve_add(fn)
|
210
|
+
def resolve_add(fn) # :nodoc:
|
212
211
|
case fn
|
213
212
|
when %r{[*?\[\{]}
|
214
213
|
add_matching(fn)
|
@@ -218,7 +217,7 @@ module Rake
|
|
218
217
|
end
|
219
218
|
private :resolve_add
|
220
219
|
|
221
|
-
def resolve_exclude
|
220
|
+
def resolve_exclude # :nodoc:
|
222
221
|
reject! { |fn| excluded_from_list?(fn) }
|
223
222
|
self
|
224
223
|
end
|
@@ -276,7 +275,6 @@ module Rake
|
|
276
275
|
collect { |fn| fn.ext(newext) }
|
277
276
|
end
|
278
277
|
|
279
|
-
|
280
278
|
# Grep each of the files in the filelist using the given pattern. If a
|
281
279
|
# block is given, call the block on each matching line, passing the file
|
282
280
|
# name, line number, and the matching line of text. If no block is given,
|
@@ -377,7 +375,7 @@ module Rake
|
|
377
375
|
proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
|
378
376
|
]
|
379
377
|
|
380
|
-
def import(array)
|
378
|
+
def import(array) # :nodoc:
|
381
379
|
@items = array
|
382
380
|
self
|
383
381
|
end
|
@@ -391,7 +389,7 @@ module Rake
|
|
391
389
|
end
|
392
390
|
|
393
391
|
# Get a sorted list of files matching the pattern. This method
|
394
|
-
# should be
|
392
|
+
# should be preferred to Dir[pattern] and Dir.glob(pattern) because
|
395
393
|
# the files returned are guaranteed to be sorted.
|
396
394
|
def glob(pattern, *args)
|
397
395
|
Dir.glob(pattern, *args).sort
|
data/lib/rake/file_task.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rake/task.rb'
|
|
2
2
|
require 'rake/early_time'
|
3
3
|
|
4
4
|
module Rake
|
5
|
-
|
5
|
+
|
6
6
|
# A FileTask is a task that includes time based dependencies. If any of a
|
7
7
|
# FileTask's prerequisites have a timestamp that is later than the file
|
8
8
|
# represented by this task, then the file must be rebuilt (using the
|
data/lib/rake/gempackagetask.rb
CHANGED
data/lib/rake/linked_list.rb
CHANGED
@@ -80,7 +80,7 @@ module Rake
|
|
80
80
|
#
|
81
81
|
# When inheriting from the LinkedList class, you should implement
|
82
82
|
# a type specific Empty class as well. Make sure you set the class
|
83
|
-
# instance variable @parent to the
|
83
|
+
# instance variable @parent to the associated list class (this
|
84
84
|
# allows conj, cons and make to work polymorphically).
|
85
85
|
class EmptyLinkedList < LinkedList
|
86
86
|
@parent = LinkedList
|
data/lib/rake/packagetask.rb
CHANGED
@@ -11,27 +11,27 @@ module Rake
|
|
11
11
|
#
|
12
12
|
# The PackageTask will create the following targets:
|
13
13
|
#
|
14
|
-
#
|
14
|
+
# +:package+ ::
|
15
15
|
# Create all the requested package files.
|
16
16
|
#
|
17
|
-
#
|
17
|
+
# +:clobber_package+ ::
|
18
18
|
# Delete all the package files. This target is automatically
|
19
19
|
# added to the main clobber target.
|
20
20
|
#
|
21
|
-
#
|
21
|
+
# +:repackage+ ::
|
22
22
|
# Rebuild the package files from scratch, even if they are not out
|
23
23
|
# of date.
|
24
24
|
#
|
25
|
-
#
|
25
|
+
# <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tgz"</tt> ::
|
26
26
|
# Create a gzipped tar package (if <em>need_tar</em> is true).
|
27
27
|
#
|
28
|
-
#
|
28
|
+
# <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.gz"</tt> ::
|
29
29
|
# Create a gzipped tar package (if <em>need_tar_gz</em> is true).
|
30
30
|
#
|
31
|
-
#
|
31
|
+
# <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.tar.bz2"</tt> ::
|
32
32
|
# Create a bzip2'd tar package (if <em>need_tar_bz2</em> is true).
|
33
33
|
#
|
34
|
-
#
|
34
|
+
# <tt>"<em>package_dir</em>/<em>name</em>-<em>version</em>.zip"</tt> ::
|
35
35
|
# Create a zip package archive (if <em>need_zip</em> is true).
|
36
36
|
#
|
37
37
|
# Example:
|
@@ -162,26 +162,38 @@ module Rake
|
|
162
162
|
self
|
163
163
|
end
|
164
164
|
|
165
|
+
# The name of this package
|
166
|
+
|
165
167
|
def package_name
|
166
168
|
@version ? "#{@name}-#{@version}" : @name
|
167
169
|
end
|
168
170
|
|
171
|
+
# The directory this package will be built in
|
172
|
+
|
169
173
|
def package_dir_path
|
170
174
|
"#{package_dir}/#{package_name}"
|
171
175
|
end
|
172
176
|
|
177
|
+
# The package name with .tgz added
|
178
|
+
|
173
179
|
def tgz_file
|
174
180
|
"#{package_name}.tgz"
|
175
181
|
end
|
176
182
|
|
183
|
+
# The package name with .tar.gz added
|
184
|
+
|
177
185
|
def tar_gz_file
|
178
186
|
"#{package_name}.tar.gz"
|
179
187
|
end
|
180
188
|
|
189
|
+
# The package name with .tar.bz2 added
|
190
|
+
|
181
191
|
def tar_bz2_file
|
182
192
|
"#{package_name}.tar.bz2"
|
183
193
|
end
|
184
194
|
|
195
|
+
# The package name with .zip added
|
196
|
+
|
185
197
|
def zip_file
|
186
198
|
"#{package_name}.zip"
|
187
199
|
end
|
data/lib/rake/pathmap.rb
CHANGED
data/lib/rake/pseudo_status.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Rake
|
2
2
|
|
3
|
-
|
3
|
+
##
|
4
4
|
# Exit status class for times the system just gives us a nil.
|
5
|
-
class PseudoStatus
|
5
|
+
class PseudoStatus # :nodoc: all
|
6
6
|
attr_reader :exitstatus
|
7
7
|
|
8
8
|
def initialize(code=0)
|
data/lib/rake/rake_module.rb
CHANGED
@@ -2,8 +2,6 @@ require 'rake/application'
|
|
2
2
|
|
3
3
|
module Rake
|
4
4
|
|
5
|
-
# Rake module singleton methods.
|
6
|
-
#
|
7
5
|
class << self
|
8
6
|
# Current Rake Application
|
9
7
|
def application
|
@@ -15,6 +13,11 @@ module Rake
|
|
15
13
|
@application = app
|
16
14
|
end
|
17
15
|
|
16
|
+
def suggested_thread_count # :nodoc:
|
17
|
+
@cpu_count ||= Rake::CpuCounter.count
|
18
|
+
@cpu_count + 4
|
19
|
+
end
|
20
|
+
|
18
21
|
# Return the original directory where the Rake application was started.
|
19
22
|
def original_dir
|
20
23
|
application.original_dir
|
@@ -28,9 +31,7 @@ module Rake
|
|
28
31
|
# Add files to the rakelib list
|
29
32
|
def add_rakelib(*files)
|
30
33
|
application.options.rakelib ||= []
|
31
|
-
files
|
32
|
-
application.options.rakelib << file
|
33
|
-
end
|
34
|
+
application.options.rakelib.concat(files)
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
data/lib/rake/rdoctask.rb
CHANGED
data/lib/rake/runtest.rb
CHANGED
@@ -5,7 +5,12 @@ require 'rake/file_list'
|
|
5
5
|
module Rake
|
6
6
|
include Test::Unit::Assertions
|
7
7
|
|
8
|
-
|
8
|
+
##
|
9
|
+
# Deprecated way of running tests in process, but only for Test::Unit.
|
10
|
+
#--
|
11
|
+
# TODO: Remove in rake 11
|
12
|
+
|
13
|
+
def run_tests(pattern='test/test*.rb', log_enabled=false) # :nodoc:
|
9
14
|
FileList.glob(pattern).each do |fn|
|
10
15
|
$stderr.puts fn if log_enabled
|
11
16
|
begin
|
data/lib/rake/scope.rb
CHANGED
data/lib/rake/task.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rake/invocation_exception_mixin'
|
|
2
2
|
|
3
3
|
module Rake
|
4
4
|
|
5
|
-
|
5
|
+
##
|
6
6
|
# A Task is the basic unit of work in a Rakefile. Tasks have associated
|
7
7
|
# actions (possibly more than one) and a list of prerequisites. When
|
8
8
|
# invoked, a task will first ensure that all of its prerequisites have an
|
@@ -34,14 +34,18 @@ module Rake
|
|
34
34
|
name
|
35
35
|
end
|
36
36
|
|
37
|
-
def inspect
|
37
|
+
def inspect # :nodoc:
|
38
38
|
"<#{self.class} #{name} => [#{prerequisites.join(', ')}]>"
|
39
39
|
end
|
40
40
|
|
41
41
|
# List of sources for task.
|
42
42
|
attr_writer :sources
|
43
43
|
def sources
|
44
|
-
@sources
|
44
|
+
if defined?(@sources)
|
45
|
+
@sources
|
46
|
+
else
|
47
|
+
prerequisites
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
# List of prerequisite tasks
|
@@ -49,7 +53,7 @@ module Rake
|
|
49
53
|
prerequisites.map { |pre| lookup_prerequisite(pre) }
|
50
54
|
end
|
51
55
|
|
52
|
-
def lookup_prerequisite(prerequisite_name)
|
56
|
+
def lookup_prerequisite(prerequisite_name) # :nodoc:
|
53
57
|
application[prerequisite_name, @scope]
|
54
58
|
end
|
55
59
|
private :lookup_prerequisite
|
@@ -63,7 +67,7 @@ module Rake
|
|
63
67
|
seen.values
|
64
68
|
end
|
65
69
|
|
66
|
-
def collect_prerequisites(seen)
|
70
|
+
def collect_prerequisites(seen) # :nodoc:
|
67
71
|
prerequisite_tasks.each do |pre|
|
68
72
|
next if seen[pre.name]
|
69
73
|
seen[pre.name] = pre
|
@@ -74,7 +78,7 @@ module Rake
|
|
74
78
|
|
75
79
|
# First source from a rule (nil if no sources)
|
76
80
|
def source
|
77
|
-
|
81
|
+
sources.first
|
78
82
|
end
|
79
83
|
|
80
84
|
# Create a task named +task_name+ with no actions or prerequisites. Use
|
@@ -180,7 +184,7 @@ module Rake
|
|
180
184
|
end
|
181
185
|
protected :invoke_with_call_chain
|
182
186
|
|
183
|
-
def add_chain_to(exception, new_chain)
|
187
|
+
def add_chain_to(exception, new_chain) # :nodoc:
|
184
188
|
exception.extend(InvocationExceptionMixin) unless
|
185
189
|
exception.respond_to?(:chain)
|
186
190
|
exception.chain = new_chain if exception.chain.nil?
|
@@ -257,11 +261,12 @@ module Rake
|
|
257
261
|
add_comment(comment) if comment && ! comment.empty?
|
258
262
|
end
|
259
263
|
|
260
|
-
def comment=(comment)
|
264
|
+
def comment=(comment) # :nodoc:
|
261
265
|
add_comment(comment)
|
262
266
|
end
|
263
267
|
|
264
|
-
def add_comment(comment)
|
268
|
+
def add_comment(comment) # :nodoc:
|
269
|
+
return if comment.nil?
|
265
270
|
@comments << comment unless @comments.include?(comment)
|
266
271
|
end
|
267
272
|
private :add_comment
|