autobuild 1.17.0 → 1.18.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|