autobuild 1.17.0 → 1.18.0
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 +4 -4
- data/.rubocop.yml +107 -0
- data/Gemfile +2 -1
- data/Rakefile +1 -4
- data/autobuild.gemspec +14 -11
- data/bin/autobuild +4 -3
- data/lib/autobuild.rb +4 -5
- data/lib/autobuild/build_logfile.rb +6 -4
- data/lib/autobuild/config.rb +90 -40
- data/lib/autobuild/configurable.rb +30 -18
- data/lib/autobuild/environment.rb +126 -120
- data/lib/autobuild/exceptions.rb +48 -31
- data/lib/autobuild/import/archive.rb +134 -82
- data/lib/autobuild/import/cvs.rb +28 -24
- data/lib/autobuild/import/darcs.rb +13 -16
- data/lib/autobuild/import/git-lfs.rb +37 -30
- data/lib/autobuild/import/git.rb +231 -179
- data/lib/autobuild/import/hg.rb +23 -18
- data/lib/autobuild/import/svn.rb +48 -29
- data/lib/autobuild/importer.rb +530 -499
- data/lib/autobuild/mail_reporter.rb +77 -77
- data/lib/autobuild/package.rb +171 -101
- data/lib/autobuild/packages/autotools.rb +47 -42
- data/lib/autobuild/packages/cmake.rb +71 -65
- data/lib/autobuild/packages/dummy.rb +9 -8
- data/lib/autobuild/packages/genom.rb +1 -1
- data/lib/autobuild/packages/gnumake.rb +19 -13
- data/lib/autobuild/packages/import.rb +2 -6
- data/lib/autobuild/packages/orogen.rb +32 -31
- data/lib/autobuild/packages/pkgconfig.rb +2 -2
- data/lib/autobuild/packages/python.rb +7 -2
- data/lib/autobuild/packages/ruby.rb +22 -17
- data/lib/autobuild/parallel.rb +35 -39
- data/lib/autobuild/pkgconfig.rb +25 -13
- data/lib/autobuild/progress_display.rb +23 -23
- data/lib/autobuild/rake_task_extension.rb +6 -6
- data/lib/autobuild/reporting.rb +38 -26
- data/lib/autobuild/subcommand.rb +72 -65
- data/lib/autobuild/test.rb +8 -7
- data/lib/autobuild/test_utility.rb +10 -9
- data/lib/autobuild/timestamps.rb +28 -23
- data/lib/autobuild/tools.rb +17 -16
- data/lib/autobuild/utility.rb +16 -18
- data/lib/autobuild/version.rb +1 -1
- metadata +39 -38
@@ -8,100 +8,100 @@
|
|
8
8
|
|
9
9
|
## Report by mail
|
10
10
|
if Autobuild::HAS_RMAIL
|
11
|
-
module Autobuild
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
module Autobuild
|
12
|
+
class MailReporter < Reporter
|
13
|
+
def default_mail
|
14
|
+
Etc.endpwent
|
15
|
+
uname = while (pwent = Etc.getpwent)
|
16
|
+
break pwent.name if pwent.uid == Process.uid
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
"#{pwent.name}@#{Socket.gethostname}"
|
21
|
-
end
|
22
|
-
|
23
|
-
attr_reader :from_email, :to_email, :smtp_hostname, :smtp_port, :subject, :only_errors
|
24
|
-
def initialize(config)
|
25
|
-
@from_email = (config[:from] || default_mail)
|
26
|
-
@to_email = (config[:to] || default_mail)
|
27
|
-
@subject = (config[:subject] || "Build %result% on #{Socket.gethostname} at %time%")
|
28
|
-
@only_errors = config[:only_errors]
|
29
|
-
@smtp_hostname = (config[:smtp] || "localhost" )
|
30
|
-
@smtp_port = Integer(config[:port] || Socket.getservbyname('smtp'))
|
31
|
-
end
|
19
|
+
raise "FATAL: cannot find a user with uid=#{Process.uid}" unless uname
|
32
20
|
|
33
|
-
|
34
|
-
if error.mail?
|
35
|
-
send_mail("failed", error.to_s)
|
21
|
+
"#{pwent.name}@#{Socket.gethostname}"
|
36
22
|
end
|
37
|
-
end
|
38
23
|
|
39
|
-
|
40
|
-
|
41
|
-
|
24
|
+
attr_reader :from_email, :to_email, :smtp_hostname, :smtp_port,
|
25
|
+
:subject, :only_errors
|
26
|
+
def initialize(config)
|
27
|
+
@from_email = (config[:from] || default_mail)
|
28
|
+
@to_email = (config[:to] || default_mail)
|
29
|
+
@subject =
|
30
|
+
config[:subject] ||
|
31
|
+
"Build %result% on #{Socket.gethostname} at %time%"
|
32
|
+
@only_errors = config[:only_errors]
|
33
|
+
@smtp_hostname = (config[:smtp] || "localhost")
|
34
|
+
@smtp_port = Integer(config[:port] || Socket.getservbyname('smtp'))
|
42
35
|
end
|
43
|
-
end
|
44
36
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
mail.header.from = from_email
|
49
|
-
mail.header.subject = subject.
|
50
|
-
gsub('%result%', result).
|
51
|
-
gsub('%time%', Time.now.to_s).
|
52
|
-
gsub('%hostname%', Socket.gethostname)
|
53
|
-
|
54
|
-
part = RMail::Message.new
|
55
|
-
part.header.set('Content-Type', 'text/plain')
|
56
|
-
part.body = body
|
57
|
-
mail.add_part(part)
|
37
|
+
def error(error)
|
38
|
+
send_mail("failed", error.to_s) if error.mail?
|
39
|
+
end
|
58
40
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
41
|
+
def success
|
42
|
+
unless only_errors
|
43
|
+
send_mail("success", Autobuild.post_success_message || "")
|
44
|
+
end
|
63
45
|
end
|
64
46
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
47
|
+
def send_mail(result, body = "")
|
48
|
+
mail = RMail::Message.new
|
49
|
+
mail.header.date = Time.now
|
50
|
+
mail.header.from = from_email
|
51
|
+
mail.header.subject = subject.
|
52
|
+
gsub('%result%', result).
|
53
|
+
gsub('%time%', Time.now.to_s).
|
54
|
+
gsub('%hostname%', Socket.gethostname)
|
55
|
+
|
56
|
+
part = RMail::Message.new
|
57
|
+
part.header.set('Content-Type', 'text/plain')
|
58
|
+
part.body = body
|
59
|
+
mail.add_part(part)
|
60
|
+
|
61
|
+
# Attach log files
|
62
|
+
Reporting.each_log do |file|
|
63
|
+
name = file[Autobuild.logdir.size..-1]
|
64
|
+
mail.add_file(name, file)
|
71
65
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
66
|
+
|
67
|
+
# Send the mails
|
68
|
+
if smtp_hostname =~ %r{/} && File.directory?(File.dirname(smtp_hostname))
|
69
|
+
File.open(smtp_hostname, 'w') do |io|
|
70
|
+
io.puts "From: #{from_email}"
|
71
|
+
io.puts "To: #{to_email.join(' ')}"
|
72
|
+
io.write RMail::Serialize.write('', mail)
|
73
|
+
end
|
74
|
+
puts "saved notification email in #{smtp_hostname}"
|
75
|
+
else
|
76
|
+
smtp = Net::SMTP.new(smtp_hostname, smtp_port)
|
77
|
+
smtp.start do
|
78
|
+
to_email.each do |email|
|
79
|
+
mail.header.to = email
|
80
|
+
smtp.send_mail(RMail::Serialize.write('', mail),
|
81
|
+
from_email, email)
|
82
|
+
end
|
79
83
|
end
|
80
|
-
}
|
81
84
|
|
82
|
-
|
83
|
-
|
85
|
+
# Notify the sending
|
86
|
+
puts "sent notification mail to #{to_email} with source #{from_email}"
|
87
|
+
end
|
84
88
|
end
|
85
89
|
end
|
86
90
|
end
|
87
|
-
end
|
88
91
|
|
89
|
-
module RMail
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
92
|
+
module RMail
|
93
|
+
class Message
|
94
|
+
## Attachs a file to a message
|
95
|
+
def add_file(name, path, content_type = 'text/plain')
|
96
|
+
part = RMail::Message.new
|
97
|
+
part.header.set('Content-Type', content_type)
|
98
|
+
part.header.set('Content-Disposition', 'attachment', 'filename' => name)
|
99
|
+
part.body = ''
|
100
|
+
File.open(path) do |file|
|
101
|
+
part.body << file.readlines.join("")
|
102
|
+
end
|
103
|
+
add_part(part)
|
99
104
|
end
|
100
|
-
self.add_part(part)
|
101
105
|
end
|
102
106
|
end
|
103
107
|
end
|
104
|
-
end # if Autobuild::HAS_RMAIL
|
105
|
-
|
106
|
-
|
107
|
-
|
data/lib/autobuild/package.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Autobuild
|
2
|
-
TARGETS = %w
|
2
|
+
TARGETS = %w[import prepare build].freeze
|
3
3
|
|
4
4
|
class << self
|
5
5
|
attr_accessor :ignore_errors
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
# Basic block for the autobuilder
|
9
9
|
#
|
10
10
|
# The build is done in three phases:
|
@@ -43,14 +43,18 @@ class Package
|
|
43
43
|
# The set of utilities attached to this package
|
44
44
|
# @return [{String=>Utility}]
|
45
45
|
attr_reader :utilities
|
46
|
+
|
46
47
|
# Whether {#apply_post_install} has been called
|
47
|
-
def applied_post_install
|
48
|
-
|
48
|
+
def applied_post_install?
|
49
|
+
@applied_post_install
|
50
|
+
end
|
51
|
+
|
49
52
|
# Sets importer object for this package. Defined for backwards compatibility.
|
50
53
|
# Use the #importer attribute instead
|
51
54
|
def import=(value)
|
52
55
|
@importer = value
|
53
56
|
end
|
57
|
+
|
54
58
|
# Sets an importer object for this package
|
55
59
|
attr_accessor :importer
|
56
60
|
|
@@ -74,11 +78,20 @@ def add_stat(phase, duration)
|
|
74
78
|
end
|
75
79
|
|
76
80
|
# Absolute path to the source directory. See #srcdir=
|
77
|
-
def srcdir
|
81
|
+
def srcdir
|
82
|
+
File.expand_path(@srcdir || name, Autobuild.srcdir)
|
83
|
+
end
|
84
|
+
|
78
85
|
# Absolute path to the import directory. See #importdir=
|
79
|
-
def importdir
|
86
|
+
def importdir
|
87
|
+
File.expand_path(@importdir || srcdir, Autobuild.srcdir)
|
88
|
+
end
|
89
|
+
|
80
90
|
# Absolute path to the installation directory. See #prefix=
|
81
|
-
def prefix
|
91
|
+
def prefix
|
92
|
+
File.expand_path(@prefix || '', Autobuild.prefix)
|
93
|
+
end
|
94
|
+
|
82
95
|
# Absolute path to the log directory for this package. See #logdir=
|
83
96
|
def logdir
|
84
97
|
if @logdir
|
@@ -115,17 +128,19 @@ def update?
|
|
115
128
|
# Returns true if this package has already been updated. It will not be
|
116
129
|
# true if the importer has been called while Autobuild.do_update was
|
117
130
|
# false.
|
118
|
-
def updated
|
131
|
+
def updated?
|
132
|
+
@updated
|
133
|
+
end
|
119
134
|
|
120
135
|
def initialize(spec = Hash.new)
|
121
136
|
@srcdir = @importdir = @logdir = @prefix = nil
|
122
137
|
@updated = false
|
123
138
|
@update = nil
|
124
139
|
@failed = nil
|
125
|
-
@dependencies
|
126
|
-
@provides
|
140
|
+
@dependencies = Array.new
|
141
|
+
@provides = Array.new
|
142
|
+
@statistics = Hash.new
|
127
143
|
@parallel_build_level = nil
|
128
|
-
@statistics = Hash.new
|
129
144
|
@failures = Array.new
|
130
145
|
@post_install_blocks = Array.new
|
131
146
|
@applied_post_install = false
|
@@ -139,19 +154,23 @@ def initialize(spec = Hash.new)
|
|
139
154
|
if Hash === spec
|
140
155
|
name, depends = spec.to_a.first
|
141
156
|
else
|
142
|
-
name
|
157
|
+
name = spec
|
158
|
+
depends = nil
|
143
159
|
end
|
144
160
|
|
145
161
|
name = name.to_s
|
146
162
|
@name = name
|
147
|
-
|
163
|
+
if Autobuild::Package[name]
|
164
|
+
raise ConfigException, "package #{name} is already defined"
|
165
|
+
end
|
166
|
+
|
148
167
|
@@packages[name] = self
|
149
168
|
|
150
169
|
# Call the config block (if any)
|
151
170
|
yield(self) if block_given?
|
152
171
|
|
153
|
-
|
154
|
-
|
172
|
+
doc_utility.source_dir ||= 'doc'
|
173
|
+
doc_utility.target_dir ||= name
|
155
174
|
|
156
175
|
# Define the default tasks
|
157
176
|
task "#{name}-import" do
|
@@ -174,12 +193,10 @@ def initialize(spec = Hash.new)
|
|
174
193
|
Rake::Task["#{name}-import"].invoke
|
175
194
|
Rake::Task["#{name}-prepare"].invoke
|
176
195
|
Rake::Task["#{name}-build"].invoke
|
177
|
-
if has_doc? && Autobuild.do_doc
|
178
|
-
Rake::Task["#{name}-doc"].invoke
|
179
|
-
end
|
196
|
+
Rake::Task["#{name}-doc"].invoke if has_doc? && Autobuild.do_doc
|
180
197
|
end
|
181
198
|
task :default => name
|
182
|
-
|
199
|
+
|
183
200
|
# The dependencies will be declared in the import phase, so save
|
184
201
|
# them there for now
|
185
202
|
@spec_dependencies = depends
|
@@ -217,7 +234,10 @@ def built?
|
|
217
234
|
def to_s
|
218
235
|
"#<#{self.class} name=#{name}>"
|
219
236
|
end
|
220
|
-
|
237
|
+
|
238
|
+
def inspect
|
239
|
+
to_s
|
240
|
+
end
|
221
241
|
|
222
242
|
# @api private
|
223
243
|
#
|
@@ -226,8 +246,8 @@ def inspect; to_s end
|
|
226
246
|
#
|
227
247
|
# @param [EnvOp] op
|
228
248
|
# @return [void]
|
229
|
-
def add_env_op(
|
230
|
-
env <<
|
249
|
+
def add_env_op(envop)
|
250
|
+
env << envop
|
231
251
|
end
|
232
252
|
|
233
253
|
# Add value(s) to a list-based environment variable
|
@@ -300,11 +320,15 @@ class IncompatibleEnvironment < ConfigException; end
|
|
300
320
|
def apply_env(env, set = Hash.new, ops = Array.new)
|
301
321
|
self.env.each do |env_op|
|
302
322
|
next if ops.last == env_op
|
323
|
+
|
303
324
|
if env_op.type == :set
|
304
|
-
if last = set[env_op.name]
|
325
|
+
if (last = set[env_op.name])
|
305
326
|
last_pkg, last_values = *last
|
306
327
|
if last_values != env_op.values
|
307
|
-
raise IncompatibleEnvironment, "trying to reset
|
328
|
+
raise IncompatibleEnvironment, "trying to reset "\
|
329
|
+
"#{env_op.name} to #{env_op.values} in #{name} "\
|
330
|
+
"but this conflicts with #{last_pkg.name} "\
|
331
|
+
"already setting it to #{last_values}"
|
308
332
|
end
|
309
333
|
else
|
310
334
|
set[env_op.name] = [self, env_op.values]
|
@@ -356,9 +380,7 @@ def resolved_env(root = Autobuild.env)
|
|
356
380
|
# target files so that all the build phases of this package gets
|
357
381
|
# retriggered. However, it should not clean the build products.
|
358
382
|
def prepare_for_forced_build
|
359
|
-
if File.exist?(installstamp)
|
360
|
-
FileUtils.rm_f installstamp
|
361
|
-
end
|
383
|
+
FileUtils.rm_f installstamp if File.exist?(installstamp)
|
362
384
|
end
|
363
385
|
|
364
386
|
# Called when the user asked for a full rebuild. It should delete the
|
@@ -366,9 +388,7 @@ def prepare_for_forced_build
|
|
366
388
|
def prepare_for_rebuild
|
367
389
|
prepare_for_forced_build
|
368
390
|
|
369
|
-
if File.exist?(installstamp)
|
370
|
-
FileUtils.rm_f installstamp
|
371
|
-
end
|
391
|
+
FileUtils.rm_f installstamp if File.exist?(installstamp)
|
372
392
|
end
|
373
393
|
|
374
394
|
# Returns true if one of the operations applied on this package failed
|
@@ -388,18 +408,18 @@ def failed?
|
|
388
408
|
# will subsequently be a noop. I.e. if +build+ fails, +install+ will do
|
389
409
|
# nothing.
|
390
410
|
def isolate_errors(options = Hash.new)
|
391
|
-
|
392
|
-
options = Hash[mark_as_failed: true]
|
393
|
-
end
|
411
|
+
options = Hash[mark_as_failed: true] unless options.kind_of?(Hash)
|
394
412
|
options = validate_options options,
|
395
413
|
mark_as_failed: true,
|
396
414
|
ignore_errors: Autobuild.ignore_errors
|
397
415
|
|
398
416
|
# Don't do anything if we already have failed
|
399
417
|
if failed?
|
400
|
-
|
401
|
-
raise AlreadyFailedError, "attempting to do an operation
|
418
|
+
unless options[:ignore_errors]
|
419
|
+
raise AlreadyFailedError, "attempting to do an operation "\
|
420
|
+
"on a failed package"
|
402
421
|
end
|
422
|
+
|
403
423
|
return
|
404
424
|
end
|
405
425
|
|
@@ -413,18 +433,12 @@ def isolate_errors(options = Hash.new)
|
|
413
433
|
raise
|
414
434
|
rescue ::Exception => e
|
415
435
|
@failures << e
|
416
|
-
if options[:mark_as_failed]
|
417
|
-
@failed = true
|
418
|
-
end
|
436
|
+
@failed = true if options[:mark_as_failed]
|
419
437
|
|
420
438
|
if options[:ignore_errors]
|
421
439
|
lines = e.to_s.split("\n")
|
422
|
-
if lines.empty?
|
423
|
-
|
424
|
-
end
|
425
|
-
if lines.empty?
|
426
|
-
lines = ["unknown error"]
|
427
|
-
end
|
440
|
+
lines = e.message.split("\n") if lines.empty?
|
441
|
+
lines = ["unknown error"] if lines.empty?
|
428
442
|
message(lines.shift, :red, :bold)
|
429
443
|
lines.each do |line|
|
430
444
|
message(line)
|
@@ -434,9 +448,7 @@ def isolate_errors(options = Hash.new)
|
|
434
448
|
raise
|
435
449
|
end
|
436
450
|
ensure
|
437
|
-
if toplevel
|
438
|
-
Thread.current[:isolate_errors] = false
|
439
|
-
end
|
451
|
+
Thread.current[:isolate_errors] = false if toplevel
|
440
452
|
end
|
441
453
|
end
|
442
454
|
|
@@ -445,9 +457,7 @@ def isolate_errors(options = Hash.new)
|
|
445
457
|
#
|
446
458
|
# (see Importer#import)
|
447
459
|
def import(options = Hash.new)
|
448
|
-
|
449
|
-
options = Hash[only_local: options]
|
450
|
-
end
|
460
|
+
options = Hash[only_local: options] unless options.respond_to?(:to_hash)
|
451
461
|
|
452
462
|
if @importer
|
453
463
|
result = @importer.import(self, options)
|
@@ -478,7 +488,8 @@ def prepare
|
|
478
488
|
end
|
479
489
|
|
480
490
|
def process_formatting_string(msg, *prefix_style)
|
481
|
-
prefix
|
491
|
+
prefix = []
|
492
|
+
suffix = []
|
482
493
|
msg.split(" ").each do |token|
|
483
494
|
if token =~ /%s/
|
484
495
|
suffix << token.gsub(/%s/, name)
|
@@ -492,7 +503,8 @@ def process_formatting_string(msg, *prefix_style)
|
|
492
503
|
elsif prefix_style.empty?
|
493
504
|
return (prefix + suffix).join(" ")
|
494
505
|
else
|
495
|
-
|
506
|
+
colorized_prefix = Autobuild.color(prefix.join(" "), *prefix_style)
|
507
|
+
return [colorized_prefix, *suffix].join(" ")
|
496
508
|
end
|
497
509
|
end
|
498
510
|
|
@@ -511,17 +523,13 @@ def error(error_string)
|
|
511
523
|
# Display a progress message. %s in the string is replaced by the
|
512
524
|
# package name
|
513
525
|
def message(*args)
|
514
|
-
|
515
|
-
args[0] = " #{process_formatting_string(args[0])}"
|
516
|
-
end
|
526
|
+
args[0] = " #{process_formatting_string(args[0])}" unless args.empty?
|
517
527
|
Autobuild.message(*args)
|
518
528
|
end
|
519
529
|
|
520
530
|
def progress_start(*args, done_message: nil, **raw_options, &block)
|
521
531
|
args[0] = process_formatting_string(args[0], :bold)
|
522
|
-
if done_message
|
523
|
-
done_message = process_formatting_string(done_message)
|
524
|
-
end
|
532
|
+
done_message = process_formatting_string(done_message) if done_message
|
525
533
|
Autobuild.progress_start(self, *args,
|
526
534
|
done_message: done_message, **raw_options, &block)
|
527
535
|
end
|
@@ -559,13 +567,14 @@ def install
|
|
559
567
|
end
|
560
568
|
|
561
569
|
def run(*args, &block)
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
570
|
+
options =
|
571
|
+
if args.last.kind_of?(Hash)
|
572
|
+
args.pop
|
573
|
+
else
|
574
|
+
Hash.new
|
575
|
+
end
|
567
576
|
options[:env] = options.delete(:resolved_env) ||
|
568
|
-
|
577
|
+
(options[:env] || Hash.new).merge(resolved_env)
|
569
578
|
Autobuild::Subprocess.run(self, *args, options, &block)
|
570
579
|
end
|
571
580
|
|
@@ -596,17 +605,49 @@ def task(*args, &block)
|
|
596
605
|
task
|
597
606
|
end
|
598
607
|
|
599
|
-
def doc_dir=(value)
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
def
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
def
|
608
|
-
|
609
|
-
|
608
|
+
def doc_dir=(value)
|
609
|
+
doc_utility.source_dir = value
|
610
|
+
end
|
611
|
+
|
612
|
+
def doc_dir
|
613
|
+
doc_utility.source_dir
|
614
|
+
end
|
615
|
+
|
616
|
+
def doc_target_dir=(value)
|
617
|
+
doc_utility.target_dir = value
|
618
|
+
end
|
619
|
+
|
620
|
+
def doc_target_dir
|
621
|
+
doc_utility.target_dir
|
622
|
+
end
|
623
|
+
|
624
|
+
def doc_task(&block)
|
625
|
+
doc_utility.task(&block)
|
626
|
+
end
|
627
|
+
|
628
|
+
def generates_doc?
|
629
|
+
doc_utility.enabled?
|
630
|
+
end
|
631
|
+
|
632
|
+
def enable_doc
|
633
|
+
doc_utility.enabled = true
|
634
|
+
end
|
635
|
+
|
636
|
+
def disable_doc
|
637
|
+
doc_utility.enabled = false
|
638
|
+
end
|
639
|
+
|
640
|
+
def install_doc
|
641
|
+
doc_utility.install
|
642
|
+
end
|
643
|
+
|
644
|
+
def doc_disabled
|
645
|
+
doc_utility.disabled
|
646
|
+
end
|
647
|
+
|
648
|
+
def has_doc?
|
649
|
+
doc_utility.has_task?
|
650
|
+
end
|
610
651
|
|
611
652
|
def post_install(*args, &block)
|
612
653
|
if args.empty?
|
@@ -618,11 +659,35 @@ def post_install(*args, &block)
|
|
618
659
|
end
|
619
660
|
end
|
620
661
|
|
662
|
+
# Returns a unique hash representing a state of the package and
|
663
|
+
# its dependencies, if any dependency can't calculate its own
|
664
|
+
# fingerprint the result will be nil
|
665
|
+
# @return [String]
|
666
|
+
def fingerprint(recursive: true, memo: {})
|
667
|
+
self_fingerprint = importer.fingerprint(self)
|
668
|
+
return unless self_fingerprint
|
669
|
+
|
670
|
+
memo[name] = self_fingerprint
|
671
|
+
return self_fingerprint if !recursive || dependencies.empty?
|
672
|
+
|
673
|
+
dependency_fingerprints = dependencies.sort.map do |pkg_name|
|
674
|
+
pkg = Autobuild::Package[pkg_name]
|
675
|
+
unless (fingerprint = memo[pkg.name])
|
676
|
+
fingerprint = pkg.fingerprint(recursive: true, memo: memo)
|
677
|
+
return unless fingerprint
|
678
|
+
memo[pkg.name] = fingerprint
|
679
|
+
end
|
680
|
+
fingerprint
|
681
|
+
end
|
682
|
+
|
683
|
+
Digest::SHA1.hexdigest(self_fingerprint + dependency_fingerprints.join(""))
|
684
|
+
end
|
685
|
+
|
621
686
|
# Returns the name of all the packages +self+ depends on
|
622
687
|
def all_dependencies(result = Set.new)
|
623
688
|
dependencies.each do |pkg_name|
|
624
689
|
pkg = Autobuild::Package[pkg_name]
|
625
|
-
|
690
|
+
unless result.include?(pkg.name)
|
626
691
|
result << pkg.name
|
627
692
|
pkg.all_dependencies(result)
|
628
693
|
end
|
@@ -642,18 +707,21 @@ def depends_on?(package_name)
|
|
642
707
|
def depends_on(*packages)
|
643
708
|
packages.each do |p|
|
644
709
|
p = p.name if p.respond_to?(:name)
|
645
|
-
|
710
|
+
unless p.respond_to?(:to_str)
|
711
|
+
raise ArgumentError, "#{p.inspect} should be a string"
|
712
|
+
end
|
713
|
+
|
646
714
|
p = p.to_str
|
647
715
|
next if p == name
|
648
|
-
|
649
|
-
|
716
|
+
|
717
|
+
unless (pkg = Package[p])
|
718
|
+
raise ConfigException.new(self), "package #{p}, "\
|
719
|
+
"listed as a dependency of #{name}, is not defined"
|
650
720
|
end
|
651
721
|
|
652
722
|
next if @dependencies.include?(pkg.name)
|
653
723
|
|
654
|
-
if Autobuild.verbose
|
655
|
-
Autobuild.message "#{name} depends on #{pkg.name}"
|
656
|
-
end
|
724
|
+
Autobuild.message "#{name} depends on #{pkg.name}" if Autobuild.verbose
|
657
725
|
|
658
726
|
task "#{name}-import" => "#{pkg.name}-import"
|
659
727
|
task "#{name}-prepare" => "#{pkg.name}-prepare"
|
@@ -666,16 +734,17 @@ def depends_on(*packages)
|
|
666
734
|
# listed in +packages+ are aliases for this package.
|
667
735
|
def provides(*packages)
|
668
736
|
packages.each do |p|
|
669
|
-
|
737
|
+
unless p.respond_to?(:to_str)
|
738
|
+
raise ArgumentError, "#{p.inspect} should be a string"
|
739
|
+
end
|
740
|
+
|
670
741
|
p = p.to_str
|
671
742
|
next if p == name
|
672
743
|
next if @provides.include?(name)
|
673
744
|
|
674
|
-
@@provides[p] = self
|
745
|
+
@@provides[p] = self
|
675
746
|
|
676
|
-
if Autobuild.verbose
|
677
|
-
Autobuild.message "#{name} provides #{p}"
|
678
|
-
end
|
747
|
+
Autobuild.message "#{name} provides #{p}" if Autobuild.verbose
|
679
748
|
|
680
749
|
task p => name
|
681
750
|
task "#{p}-import" => "#{name}-import"
|
@@ -688,13 +757,11 @@ def provides(*packages)
|
|
688
757
|
# Iterates on all available packages
|
689
758
|
# if with_provides is true, includes the list
|
690
759
|
# of package aliases
|
691
|
-
def self.each(with_provides = false, &
|
692
|
-
|
693
|
-
return enum_for(:each, with_provides)
|
694
|
-
end
|
760
|
+
def self.each(with_provides = false, &block)
|
761
|
+
return enum_for(:each, with_provides) unless block
|
695
762
|
|
696
|
-
@@packages.each(&
|
697
|
-
@@provides.each(&
|
763
|
+
@@packages.each(&block)
|
764
|
+
@@provides.each(&block) if with_provides
|
698
765
|
end
|
699
766
|
|
700
767
|
# Gets a package from its name
|
@@ -719,7 +786,7 @@ def parallel_build_level=(value)
|
|
719
786
|
end
|
720
787
|
|
721
788
|
# Returns the level of parallelism authorized during the build for this
|
722
|
-
# particular package. If not set, defaults to the system-wide option
|
789
|
+
# particular package. If not set, defaults to the system-wide option
|
723
790
|
# (Autobuild.parallel_build_level and Autobuild.parallel_build_level=).
|
724
791
|
#
|
725
792
|
# The default value is the number of CPUs on this system.
|
@@ -740,7 +807,6 @@ def working_directory
|
|
740
807
|
def in_dir(directory)
|
741
808
|
@in_dir_stack << directory
|
742
809
|
yield
|
743
|
-
|
744
810
|
ensure
|
745
811
|
@in_dir_stack.pop
|
746
812
|
end
|
@@ -768,21 +834,26 @@ def disable(phases = Autobuild.all_phases)
|
|
768
834
|
end
|
769
835
|
|
770
836
|
def utility(utility_name)
|
771
|
-
utilities[utility_name] ||= Autobuild.create_utility(utility_name, self)
|
837
|
+
utilities[utility_name.to_s] ||= Autobuild.create_utility(utility_name, self)
|
772
838
|
end
|
773
839
|
|
840
|
+
def respond_to_missing?(name, _include_all)
|
841
|
+
utilities.key?(name.to_s)
|
842
|
+
end
|
774
843
|
|
775
|
-
def method_missing(
|
776
|
-
case
|
844
|
+
def method_missing(name, *args, &block)
|
845
|
+
case name.to_s
|
777
846
|
when /(\w+)_utility$/
|
778
847
|
utility_name = $1
|
779
|
-
|
848
|
+
|
849
|
+
unless args.empty?
|
780
850
|
raise ArgumentError, "expected 0 arguments and got #{args.size}"
|
781
851
|
end
|
852
|
+
|
782
853
|
begin
|
783
854
|
return utility(utility_name)
|
784
855
|
rescue ArgumentError => e
|
785
|
-
raise NoMethodError.new(
|
856
|
+
raise NoMethodError.new(name), e.message, e.backtrace
|
786
857
|
end
|
787
858
|
end
|
788
859
|
super
|
@@ -797,4 +868,3 @@ def self.package_set(spec)
|
|
797
868
|
end
|
798
869
|
end
|
799
870
|
end
|
800
|
-
|