autobuild 1.19.0 → 1.20.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2db3dc0a2d21505b88966e48b4019800e42f39e4a44cbd113a874a4aefad8dc8
4
- data.tar.gz: 3f19bf595f8c258899f1cfd3636257e9c58bd0ca02680a1e205d12d645cb9354
3
+ metadata.gz: 3b347c81cc5ac09e4f967df3dd5f53bca82fb3ba2a1a4a2e76b1b2d20ba19869
4
+ data.tar.gz: 6eaa54db5306f069ce5e9809b708df1bb4c5def84dc1553c953a3e38319cbf26
5
5
  SHA512:
6
- metadata.gz: ac1af6ad08365cda04b28c52e8283fdaf2b4f56ae0b320961fb8600c7126e242c7e83569d8ac8f6722b441efc5f10d18b90a576a76efee1dc53c9c442327562f
7
- data.tar.gz: e716f6c428ea5c6384465697abd8124a9e6aa739ab78025129beec71dd4ec14630e81804f0109a6707575713e69d86fbcd2d16fea4031cff1953ae6ff702fcf9
6
+ metadata.gz: ccefa69f82809031debaeee77adde985c2de4d88c738e9b439cf7e839bc511f2f4c757486625f88a91541d97c16566217a544831c35924ea76cae98920d9f59d
7
+ data.tar.gz: 9f4b9b5c38e9072104dc052c630ca7a49a915331526cdbc624d2ef725eef44987b97b97667ebcafead9afb145fcbb3cee5a921f699aed101ec99efd611c28352
@@ -33,4 +33,5 @@ Gem::Specification.new do |s|
33
33
  s.add_development_dependency "flexmock", '~> 2.0', ">= 2.0.0"
34
34
  s.add_development_dependency "minitest", "~> 5.0", ">= 5.0"
35
35
  s.add_development_dependency "simplecov"
36
+ s.add_development_dependency "timecop"
36
37
  end
@@ -352,7 +352,20 @@ def self.apply(packages, buildname = "autobuild", phases = [], options = Hash.ne
352
352
  invoker = Autobuild::RakeTaskParallelism.new(options[:parallel])
353
353
  Autobuild.parallel_task_manager = invoker
354
354
  phases.each do |phase|
355
- invoker.invoke_parallel([Rake::Task["#{buildname}-#{phase}"]])
355
+ package_tasks = packages.each_with_object({}) do |pkg_name, h|
356
+ h["#{pkg_name}-#{phase}"] = true
357
+ end
358
+ callback =
359
+ if block_given?
360
+ proc do |task|
361
+ yield(task.package, phase) if package_tasks[task.name]
362
+ end
363
+ else
364
+ proc { }
365
+ end
366
+
367
+ invoker.invoke_parallel([Rake::Task["#{buildname}-#{phase}"]],
368
+ completion_callback: callback)
356
369
  end
357
370
  ensure
358
371
  Autobuild.parallel_task_manager = nil
@@ -109,6 +109,7 @@ def prepare
109
109
 
110
110
  stamps = dependencies.map { |pkg| Autobuild::Package[pkg].installstamp }
111
111
  file configurestamp => stamps do
112
+ @install_invoked = true
112
113
  isolate_errors do
113
114
  ensure_dependencies_installed
114
115
  configure
@@ -118,6 +119,7 @@ def prepare
118
119
  task "#{name}-prepare" => configurestamp
119
120
 
120
121
  file buildstamp => [srcdir, configurestamp] do
122
+ @install_invoked = true
121
123
  isolate_errors do
122
124
  ensure_dependencies_installed
123
125
  build
@@ -132,7 +134,7 @@ def prepare
132
134
  def configure
133
135
  if File.exist?(builddir) && !File.directory?(builddir)
134
136
  raise ConfigException.new(self, 'configure'),
135
- "#{builddir} already exists but is not a directory"
137
+ "#{builddir} already exists but is not a directory"
136
138
  end
137
139
 
138
140
  FileUtils.mkdir_p builddir unless File.directory?(builddir)
@@ -1199,7 +1199,8 @@ def checkout(package, _options = Hash.new)
1199
1199
  repository, package.importdir, retry: true)
1200
1200
 
1201
1201
  update_remotes_configuration(package)
1202
- update(package, only_local: !remote_branch.start_with?("refs/"), reset: true)
1202
+ update(package, only_local: !remote_branch.start_with?("refs/"),
1203
+ reset: :force)
1203
1204
  run_git(package, "submodule", "update", '--init') if with_submodules?
1204
1205
  end
1205
1206
 
@@ -107,7 +107,11 @@ def self.cache_dirs(type)
107
107
  # @return [Array<String>,nil]
108
108
  # @see .cache_dirs
109
109
  def self.default_cache_dirs
110
- [@default_cache_dirs] if @default_cache_dirs ||= ENV['AUTOBUILD_CACHE_DIR']
110
+ if @default_cache_dirs
111
+ @default_cache_dirs
112
+ elsif (from_env = ENV['AUTOBUILD_CACHE_DIR'])
113
+ @default_cache_dirs = [from_env]
114
+ end
111
115
  end
112
116
 
113
117
  # Sets the cache directory for a given importer type
@@ -663,6 +663,10 @@ def post_install(*args, &block)
663
663
  end
664
664
  end
665
665
 
666
+ def self_fingerprint
667
+ importer.fingerprint(self)
668
+ end
669
+
666
670
  # Returns a unique hash representing a state of the package and
667
671
  # its dependencies, if any dependency can't calculate its own
668
672
  # fingerprint the result will be nil
@@ -670,9 +674,13 @@ def post_install(*args, &block)
670
674
  def fingerprint(recursive: true, memo: {})
671
675
  return memo[name] if memo.key?(name)
672
676
 
673
- self_fingerprint = importer.fingerprint(self)
677
+ self_fingerprint = self.self_fingerprint
674
678
  return unless self_fingerprint
675
- return self_fingerprint if !recursive || dependencies.empty?
679
+ if dependencies.empty?
680
+ return (memo[name] = self_fingerprint)
681
+ elsif !recursive
682
+ return self_fingerprint
683
+ end
676
684
 
677
685
  dependency_fingerprints = dependencies.sort.map do |pkg_name|
678
686
  pkg = Autobuild::Package[pkg_name]
@@ -542,5 +542,11 @@ def delete_obsolete_files
542
542
  message "%s: removed #{counter} obsolete files from prefix (cmake)"
543
543
  end
544
544
  end
545
+
546
+ def self_fingerprint
547
+ return unless (base = super)
548
+ all_defines = self.class.defines.merge(self.defines).sort_by(&:first)
549
+ Digest::SHA1.hexdigest(base + all_defines.join(""))
550
+ end
545
551
  end
546
552
  end
@@ -83,8 +83,9 @@ class ProcessingState
83
83
  attr_reader :queue
84
84
  attr_reader :priorities
85
85
 
86
- def initialize(reverse_dependencies)
86
+ def initialize(reverse_dependencies, completion_callback: proc { })
87
87
  @reverse_dependencies = reverse_dependencies
88
+ @completion_callback = completion_callback
88
89
  @processed = Set.new
89
90
  @active_tasks = Set.new
90
91
  @priorities = Hash.new
@@ -143,6 +144,8 @@ def process_finished_task(task)
143
144
  push(candidate, priorities[task])
144
145
  end
145
146
  end
147
+
148
+ @completion_callback.call(task)
146
149
  end
147
150
 
148
151
  def trivial_task?(task)
@@ -153,7 +156,7 @@ def trivial_task?(task)
153
156
 
154
157
  # Invokes the provided tasks. Unlike the rake code, this is a toplevel
155
158
  # algorithm that does not use recursion
156
- def invoke_parallel(required_tasks)
159
+ def invoke_parallel(required_tasks, completion_callback: proc { })
157
160
  tasks = Set.new
158
161
  reverse_dependencies = Hash.new { |h, k| h[k] = Set.new }
159
162
  required_tasks.each do |t|
@@ -162,7 +165,8 @@ def invoke_parallel(required_tasks)
162
165
  # The queue is the set of tasks for which all prerequisites have
163
166
  # been successfully executed (or where not needed). I.e. it is the
164
167
  # set of tasks that can be queued for execution.
165
- state = ProcessingState.new(reverse_dependencies)
168
+ state = ProcessingState.new(reverse_dependencies,
169
+ completion_callback: completion_callback)
166
170
  tasks.each do |t|
167
171
  state.push(t) if state.ready?(t)
168
172
  end
@@ -9,16 +9,61 @@ def initialize(io, color: ::Autobuild.method(:color))
9
9
 
10
10
  @silent = false
11
11
  @color = color
12
- @progress_enabled = true
13
12
  @display_lock = Mutex.new
13
+
14
+ @next_progress_display = Time.at(0)
15
+ @progress_mode = :single_line
16
+ @progress_period = 0.1
17
+ end
18
+
19
+ # Set the minimum time between two progress messages
20
+ #
21
+ # @see period
22
+ def progress_period=(period)
23
+ @progress_period = Float(period)
14
24
  end
15
25
 
16
- attr_writer :silent
26
+ # Minimum time between two progress displays
27
+ #
28
+ # This does not affect normal messages
29
+ #
30
+ # @return [Float]
31
+ attr_reader :progress_period
32
+
33
+ # Valid progress modes
34
+ #
35
+ # @see progress_mode=
36
+ PROGRESS_MODES = %I[single_line newline off]
37
+
38
+ # Sets how progress messages will be displayed
39
+ #
40
+ # @param [String] the new mode. Can be either 'single_line', where a
41
+ # progress message replaces the last one, 'newline' which displays
42
+ # each on a new line or 'off' to disable progress messages altogether
43
+ def progress_mode=(mode)
44
+ mode = mode.to_sym
45
+ unless PROGRESS_MODES.include?(mode)
46
+ raise ArgumentError,
47
+ "#{mode} is not a valid mode, expected one of "\
48
+ "#{PROGRESS_MODES.join(", ")}"
49
+ end
50
+ @progress_mode = mode
51
+ end
52
+
53
+ # Return the current display mode
54
+ #
55
+ # @return [Symbol]
56
+ # @see mode=
57
+ attr_reader :progress_mode
17
58
 
18
59
  def silent?
19
60
  @silent
20
61
  end
21
62
 
63
+ def silent=(flag)
64
+ @silent = flag
65
+ end
66
+
22
67
  def silent
23
68
  silent = @silent
24
69
  @silent = true
@@ -27,10 +72,14 @@ def silent
27
72
  @silent = silent
28
73
  end
29
74
 
30
- attr_writer :progress_enabled
75
+ # @deprecated use progress_mode= instead
76
+ def progress_enabled=(flag)
77
+ self.progress_mode = flag ? :single_line : :off
78
+ end
31
79
 
80
+ # Whether progress messages will be displayed at all
32
81
  def progress_enabled?
33
- !@silent && @progress_enabled
82
+ !@silent && (@progress_mode != :off)
34
83
  end
35
84
 
36
85
  def message(message, *args, io: @io, force: false)
@@ -39,8 +88,11 @@ def message(message, *args, io: @io, force: false)
39
88
  io = args.pop if args.last.respond_to?(:to_io)
40
89
 
41
90
  @display_lock.synchronize do
42
- io.print "#{@cursor.column(1)}#{@cursor.clear_screen_down}"\
43
- "#{@color.call(message, *args)}\n"
91
+ if @progress_mode == :single_line
92
+ io.print @cursor.clear_screen_down
93
+ end
94
+ io.puts @color.call(message, *args)
95
+
44
96
  io.flush if @io != io
45
97
  display_progress
46
98
  @io.flush
@@ -54,7 +106,7 @@ def progress_start(key, *args, done_message: nil)
54
106
  @progress_messages << [key, formatted_message]
55
107
  if progress_enabled?
56
108
  @display_lock.synchronize do
57
- display_progress
109
+ display_progress(consider_period: false)
58
110
  end
59
111
  else
60
112
  message " #{formatted_message}"
@@ -113,32 +165,38 @@ def progress_done(key, display_last = true, message: nil)
113
165
  end
114
166
  end
115
167
 
116
- def display_progress
168
+ def display_progress(consider_period: true)
117
169
  return unless progress_enabled?
170
+ return if consider_period && (@next_progress_display > Time.now)
118
171
 
119
- formatted = format_grouped_messages(@progress_messages.map(&:last),
120
- indent: " ")
121
- @io.print @cursor.clear_screen_down
122
- @io.print formatted.join("\n")
123
- if formatted.size > 1
124
- @io.print "#{@cursor.up(formatted.size - 1)}#{@cursor.column(0)}"
172
+ formatted = format_grouped_messages(
173
+ @progress_messages.map(&:last),
174
+ indent: " "
175
+ )
176
+ if @progress_mode == :newline
177
+ @io.print formatted.join("\n")
178
+ @io.print "\n"
125
179
  else
180
+ @io.print @cursor.clear_screen_down
181
+ @io.print formatted.join("\n")
182
+ @io.print @cursor.up(formatted.size - 1) if formatted.size > 1
126
183
  @io.print @cursor.column(0)
127
184
  end
128
185
  @io.flush
186
+ @next_progress_display = Time.now + @progress_period
129
187
  end
130
188
 
131
189
  def find_common_prefix(msg, other_msg)
132
- msg = msg.split(" ")
133
- other_msg = other_msg.split(" ")
190
+ msg = msg.split(' ')
191
+ other_msg = other_msg.split(' ')
134
192
  msg.each_with_index do |token, idx|
135
193
  if other_msg[idx] != token
136
194
  prefix = msg[0..(idx - 1)].join(" ")
137
- prefix << " " unless prefix.empty?
195
+ prefix << ' ' unless prefix.empty?
138
196
  return prefix
139
197
  end
140
198
  end
141
- msg.join(" ")
199
+ msg.join(' ')
142
200
  end
143
201
 
144
202
  def group_messages(messages)
@@ -47,10 +47,19 @@ def self.progress_display_enabled?
47
47
  @display.progress_enabled?
48
48
  end
49
49
 
50
+ # @deprecated use {progress_display_mode=} instead
50
51
  def self.progress_display_enabled=(value)
51
52
  @display.progress_enabled = value
52
53
  end
53
54
 
55
+ def self.progress_display_mode=(value)
56
+ @display.progress_mode = value
57
+ end
58
+
59
+ def self.progress_display_period=(value)
60
+ @display.progress_period = value
61
+ end
62
+
54
63
  def self.message(*args, **options)
55
64
  @display.message(*args, **options)
56
65
  end
@@ -104,16 +104,18 @@ def task(&block)
104
104
  def call_task_block
105
105
  @invoked = true
106
106
 
107
- yield if block_given?
108
- @success = true
107
+ begin
108
+ yield if block_given?
109
+ @success = true
110
+ rescue StandardError => e
111
+ install if install_on_error? && !@installed && target_dir
112
+ raise
113
+ end
109
114
 
110
115
  # Allow the user to install manually in the task
111
116
  # block
112
117
  install if !@installed && target_dir
113
- rescue Interrupt
114
- raise
115
- rescue ::Exception => e
116
- install if install_on_error? && !@installed && target_dir
118
+ rescue StandardError => e
117
119
  @success = false
118
120
 
119
121
  if Autobuild.send("pass_#{name}_errors")
@@ -1,3 +1,3 @@
1
1
  module Autobuild
2
- VERSION = "1.19.0".freeze unless defined? Autobuild::VERSION
2
+ VERSION = "1.20.0".freeze unless defined? Autobuild::VERSION
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: autobuild
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.0
4
+ version: 1.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Joyeux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-03 00:00:00.000000000 Z
11
+ date: 2020-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pastel
@@ -180,6 +180,20 @@ dependencies:
180
180
  - - ">="
181
181
  - !ruby/object:Gem::Version
182
182
  version: '0'
183
+ - !ruby/object:Gem::Dependency
184
+ name: timecop
185
+ requirement: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ type: :development
191
+ prerelease: false
192
+ version_requirements: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
183
197
  description: Collection of classes to handle build systems (CMake, autotools, ...)
184
198
  and import mechanisms (tarballs, CVS, SVN, git, ...). It also offers a Rake integration
185
199
  to import and build such software packages. It is the backbone of the autoproj (http://rock-robotics.org/autoproj)