autobuild 1.17.0 → 1.21.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +107 -0
  3. data/.travis.yml +3 -2
  4. data/Gemfile +2 -1
  5. data/Rakefile +1 -4
  6. data/autobuild.gemspec +18 -13
  7. data/bin/autobuild +4 -3
  8. data/lib/autobuild.rb +4 -5
  9. data/lib/autobuild/build_logfile.rb +6 -4
  10. data/lib/autobuild/config.rb +104 -41
  11. data/lib/autobuild/configurable.rb +32 -18
  12. data/lib/autobuild/environment.rb +126 -120
  13. data/lib/autobuild/exceptions.rb +48 -31
  14. data/lib/autobuild/import/archive.rb +134 -82
  15. data/lib/autobuild/import/cvs.rb +28 -24
  16. data/lib/autobuild/import/darcs.rb +13 -16
  17. data/lib/autobuild/import/git-lfs.rb +37 -30
  18. data/lib/autobuild/import/git.rb +246 -182
  19. data/lib/autobuild/import/hg.rb +23 -18
  20. data/lib/autobuild/import/svn.rb +48 -29
  21. data/lib/autobuild/importer.rb +534 -499
  22. data/lib/autobuild/mail_reporter.rb +77 -77
  23. data/lib/autobuild/package.rb +200 -122
  24. data/lib/autobuild/packages/autotools.rb +47 -42
  25. data/lib/autobuild/packages/cmake.rb +77 -65
  26. data/lib/autobuild/packages/dummy.rb +9 -8
  27. data/lib/autobuild/packages/genom.rb +1 -1
  28. data/lib/autobuild/packages/gnumake.rb +74 -31
  29. data/lib/autobuild/packages/import.rb +2 -6
  30. data/lib/autobuild/packages/orogen.rb +32 -31
  31. data/lib/autobuild/packages/pkgconfig.rb +2 -2
  32. data/lib/autobuild/packages/python.rb +12 -8
  33. data/lib/autobuild/packages/ruby.rb +22 -17
  34. data/lib/autobuild/parallel.rb +50 -46
  35. data/lib/autobuild/pkgconfig.rb +25 -13
  36. data/lib/autobuild/progress_display.rb +149 -64
  37. data/lib/autobuild/rake_task_extension.rb +12 -7
  38. data/lib/autobuild/reporting.rb +51 -26
  39. data/lib/autobuild/subcommand.rb +72 -65
  40. data/lib/autobuild/test.rb +9 -7
  41. data/lib/autobuild/test_utility.rb +12 -10
  42. data/lib/autobuild/timestamps.rb +28 -23
  43. data/lib/autobuild/tools.rb +17 -16
  44. data/lib/autobuild/utility.rb +67 -23
  45. data/lib/autobuild/version.rb +1 -1
  46. metadata +53 -37
@@ -44,7 +44,7 @@ def setup
44
44
  @temp_dirs = Array.new
45
45
 
46
46
  @tempdir = make_tmpdir
47
- FileUtils.mkdir_p(@tempdir, :mode => 0700)
47
+ FileUtils.mkdir_p(@tempdir, mode: 0o700)
48
48
  Autobuild.logdir = "#{tempdir}/log"
49
49
  FileUtils.mkdir_p Autobuild.logdir
50
50
  Autobuild.silent = true
@@ -57,6 +57,7 @@ def teardown
57
57
 
58
58
  Autobuild::Package.clear
59
59
  Rake::Task.clear
60
+ Autobuild.reset_gnumake_detection
60
61
 
61
62
  @temp_dirs.each do |dir|
62
63
  FileUtils.rm_rf dir
@@ -75,20 +76,21 @@ def data_dir
75
76
  attr_reader :tempdir
76
77
 
77
78
  def build_config(bind, template)
78
- eval "basedir = '#{self.tempdir}'", bind
79
- ryml = File.open(File.join(data_dir, "#{template}.ryml")) { |f| f.readlines }.join('')
79
+ bind.local_variable_set(:basedir, tempdir.to_s)
80
+ ryml = File.open(File.join(data_dir, "#{template}.ryml"), &:readlines)
81
+ .join('')
80
82
  result = ERB.new(ryml).result(bind)
81
83
 
82
84
  yml = File.join(tempdir, "#{template}.yml")
83
85
  File.open(yml, 'w+') { |f| f.write(result) }
84
-
85
- return yml
86
+
87
+ yml
86
88
  end
87
89
 
88
90
  def untar(file)
89
91
  file = File.expand_path(file, data_dir)
90
- dir = self.tempdir
91
- Dir.chdir(dir) do
92
+ dir = tempdir
93
+ Dir.chdir(dir) do
92
94
  system("tar xf #{file}")
93
95
  end
94
96
 
@@ -29,16 +29,14 @@ def coverage_enabled?
29
29
  end
30
30
 
31
31
  def coverage_available?
32
- !!@coverage_source_dir
32
+ @coverage_source_dir
33
33
  end
34
34
 
35
35
  # Controls whether code coverage should be measured
36
36
  #
37
37
  # @param [Boolean,nil] flag enable or disable code coverage. If set to
38
38
  # nil, will use the default from {TestUtility.coverage?}
39
- def coverage_enabled=(flag)
40
- @coverage_enabled = flag
41
- end
39
+ attr_writer :coverage_enabled
42
40
 
43
41
  # Where the code coverage will be generated
44
42
  #
@@ -75,7 +73,8 @@ def coverage_source_dir
75
73
  def coverage_target_dir
76
74
  if @coverage_target_dir
77
75
  File.expand_path(@coverage_target_dir, package.prefix)
78
- else File.join(target_dir, 'coverage')
76
+ elsif (target_dir = self.target_dir)
77
+ File.join(target_dir, 'coverage')
79
78
  end
80
79
  end
81
80
 
@@ -85,21 +84,24 @@ def install
85
84
  if !coverage_enabled?
86
85
  return
87
86
  elsif !coverage_available?
88
- package.warn "%s: #coverage_source_dir not set on #test_utility, skipping installation of the code coverage results"
87
+ package.warn "%s: #coverage_source_dir not set on #test_utility, "\
88
+ "skipping installation of the code coverage results"
89
89
  end
90
90
 
91
91
  coverage_target_dir = self.coverage_target_dir
92
92
  coverage_source_dir = self.coverage_source_dir
93
93
  if "#{coverage_source_dir}/".start_with?("#{source_dir}/")
94
- raise ArgumentError, "#coverage_source_dir cannot be a subdirectory of #source_dir in #{package.name}"
94
+ raise ArgumentError, "#coverage_source_dir cannot be a subdirectory "\
95
+ "of #source_dir in #{package.name}"
95
96
  elsif target_dir == coverage_target_dir
96
- raise ArgumentError, "#coverage_target_dir cannot be the same than of #target_dir in #{package.name}"
97
+ raise ArgumentError, "#coverage_target_dir cannot be the same than of "\
98
+ "#target_dir in #{package.name}"
97
99
  end
98
100
 
99
101
  FileUtils.mkdir_p File.dirname(coverage_target_dir)
100
102
  FileUtils.cp_r coverage_source_dir, coverage_target_dir
101
- package.message "%s: copied test coverage results for #{package.name} from #{coverage_source_dir} to #{coverage_target_dir}"
103
+ package.message "%s: copied test coverage results for #{package.name} from "\
104
+ "#{coverage_source_dir} to #{coverage_target_dir}"
102
105
  end
103
106
  end
104
107
  end
105
-
@@ -1,5 +1,5 @@
1
1
  module Autobuild
2
- STAMPFILE = "autobuild-stamp"
2
+ STAMPFILE = "autobuild-stamp".freeze
3
3
 
4
4
  class << self
5
5
  # The set of global ignores for SourceTreeTask
@@ -15,17 +15,18 @@ class << self
15
15
  # The matching paths will not be considered when looking if a source tree
16
16
  # has been updated or not.
17
17
  def self.ignore(path)
18
- if path.kind_of?(Regexp)
19
- ignored_files << path
20
- else
21
- ignored_files << Regexp.new("^#{Regexp.quote(path)}")
22
- end
18
+ ignored_files <<
19
+ if path.kind_of?(Regexp)
20
+ path
21
+ else
22
+ Regexp.new("^#{Regexp.quote(path)}")
23
+ end
23
24
  end
24
25
 
25
26
  def self.tree_timestamp(path, *exclude)
26
27
  # Exclude autobuild timestamps
27
- exclude << (/#{Regexp.quote(STAMPFILE)}$/)
28
- exclude << (/\.autobuild-patches$/)
28
+ exclude << /#{Regexp.quote(STAMPFILE)}$/
29
+ exclude << /\.autobuild-patches$/
29
30
 
30
31
  Autobuild.message "getting tree timestamp for #{path}" if Autobuild.debug
31
32
  latest = Time.at(0)
@@ -33,13 +34,15 @@ def self.tree_timestamp(path, *exclude)
33
34
 
34
35
  Find.find(path) do |p|
35
36
  Find.prune if File.basename(p) =~ /^\./
36
- exclude.each do |pattern|
37
+ exclude.each do |pattern|
37
38
  if pattern === p
38
- Autobuild.message " excluding #{p} because of #{pattern}" if Autobuild.debug
39
+ if Autobuild.debug
40
+ Autobuild.message " excluding #{p} because of #{pattern}"
41
+ end
39
42
  Find.prune
40
43
  end
41
44
  end
42
- next if !File.file?(p)
45
+ next unless File.file?(p)
43
46
 
44
47
  p_time = File.mtime(p)
45
48
  if latest < p_time
@@ -49,7 +52,7 @@ def self.tree_timestamp(path, *exclude)
49
52
  end
50
53
 
51
54
  Autobuild.message " newest file: #{latest_file} at #{latest}" if Autobuild.debug
52
- return latest_file, latest
55
+ [latest_file, latest]
53
56
  end
54
57
 
55
58
  class SourceTreeTask < Rake::Task
@@ -62,26 +65,28 @@ def initialize(*args, &block)
62
65
  @exclude = Autobuild.ignored_files.dup
63
66
  super
64
67
  end
65
-
68
+
66
69
  def timestamp
67
- if @newest_time
68
- return @newest_time
69
- end
70
+ return @newest_time if @newest_time
70
71
 
71
72
  @newest_file, @newest_time =
72
- Autobuild.tree_timestamp(name, %r#(?:^|/)(?:CVS|_darcs|\.svn)$#, *@exclude)
73
+ Autobuild.tree_timestamp(name,
74
+ %r{(?:^|/)(?:CVS|_darcs|\.svn)$}, *@exclude)
73
75
  @newest_time
74
76
  end
75
77
  end
76
78
  def self.source_tree(path, &block)
77
79
  task = SourceTreeTask.define_task(path)
78
- block.call(task) unless !block
80
+ block&.call(task)
79
81
  task
80
82
  end
81
-
83
+
82
84
  def self.get_stamp(stampfile)
83
- return Time.at(0) if !File.exist?(stampfile)
84
- return File.mtime(stampfile)
85
+ if File.exist?(stampfile)
86
+ File.mtime(stampfile)
87
+ else
88
+ Time.at(0)
89
+ end
85
90
  end
86
91
 
87
92
  def self.hires_modification_time?
@@ -103,9 +108,10 @@ def self.touch_stamp(stampfile)
103
108
  elsif !File.exist?(dir)
104
109
  FileUtils.mkdir_p dir
105
110
  end
111
+
106
112
  FileUtils.touch(stampfile)
107
113
 
108
- if !hires_modification_time?
114
+ unless hires_modification_time?
109
115
  # File modification times on most Unix filesystems have a granularity of
110
116
  # one second, so we (unfortunately) have to sleep 1s to make sure that
111
117
  # time comparisons will work as expected.
@@ -113,4 +119,3 @@ def self.touch_stamp(stampfile)
113
119
  end
114
120
  end
115
121
  end
116
-
@@ -2,7 +2,7 @@ module Autobuild
2
2
  class << self
3
3
  # Configure the programs used by different packages
4
4
  attr_reader :programs
5
- # A cache of entries in programs to their resolved full path
5
+ # A cache of entries in programs to their resolved full path
6
6
  #
7
7
  # @return [{String=>[String,String,String]}] the triplet (full path,
8
8
  # tool name, value of ENV['PATH']). The last two values are used to
@@ -13,7 +13,7 @@ class << self
13
13
 
14
14
  # Get a given program, using its name as default value. For
15
15
  # instance
16
- # tool('automake')
16
+ # tool('automake')
17
17
  # will return 'automake' unless the autobuild script defined
18
18
  # another automake program in Autobuild.programs by doing
19
19
  # Autobuild.programs['automake'] = 'automake1.9'
@@ -30,29 +30,30 @@ def find_in_path(file, envvar = 'PATH')
30
30
  def tool_in_path(name, env: self.env)
31
31
  path, path_name, path_env = programs_in_path[name]
32
32
  current = tool(name)
33
- env_PATH = env.resolved_env['PATH']
34
- if (path_env != env_PATH) || (path_name != current)
33
+ env_path = env.resolved_env['PATH']
34
+ if (path_env != env_path) || (path_name != current)
35
35
  # Delete the current entry given that it is invalid
36
36
  programs_in_path.delete(name)
37
- if current[0, 1] == "/"
38
- # This is already a full path
39
- path = current
40
- else
41
- path = env.find_executable_in_path(current)
37
+ path =
38
+ if current[0, 1] == "/"
39
+ # This is already a full path
40
+ current
41
+ else
42
+ env.find_executable_in_path(current)
43
+ end
44
+
45
+ unless path
46
+ raise ArgumentError, "tool #{name}, set to #{current}, "\
47
+ "can not be found in PATH=#{env_path}"
42
48
  end
43
49
 
44
- if !path
45
- raise ArgumentError, "tool #{name}, set to #{current}, can not be found in PATH=#{env_PATH}"
46
- end
47
-
48
- programs_in_path[name] = [path, current, env_PATH]
50
+ programs_in_path[name] = [path, current, env_path]
49
51
  end
50
52
 
51
- return path
53
+ path
52
54
  end
53
55
  end
54
56
 
55
57
  @programs = Hash.new
56
58
  @programs_in_path = Hash.new
57
59
  end
58
-
@@ -28,7 +28,12 @@ def initialize(name, package, install_on_error: false)
28
28
  @source_ref_dir = nil
29
29
  @source_dir = nil
30
30
  @target_dir = nil
31
- @install_on_error = !!install_on_error
31
+ @install_on_error = install_on_error
32
+
33
+ @no_results = false
34
+ @invoked = false
35
+ @success = false
36
+ @installed = false
32
37
  end
33
38
 
34
39
  # Directory in which the utility will generate some files The
@@ -43,9 +48,7 @@ def initialize(name, package, install_on_error: false)
43
48
  # Absolute path to where this utulity should output its results. Returns nil if
44
49
  # {source_dir} has not been set.
45
50
  def source_dir
46
- if @source_dir
47
- File.expand_path(@source_dir, source_ref_dir || package.srcdir)
48
- end
51
+ File.expand_path(@source_dir, source_ref_dir || package.srcdir) if @source_dir
49
52
  end
50
53
 
51
54
  # Directory in which the utility would install some files.
@@ -56,13 +59,32 @@ def source_dir
56
59
  # not install anything
57
60
  attr_writer :target_dir
58
61
 
62
+ # Controls whether this utility generates results or not
63
+ #
64
+ # By default, Autobuild assumes that utilities generate report or
65
+ # artifact files, that are saved in {#target_dir}. Set this flag to
66
+ # true to disable this behavior, in which case the only report will
67
+ # be the console output during run
68
+ #
69
+ # @see no_results?
70
+ attr_writer :no_results
71
+
72
+ # Whether this utility generates results or not
73
+ #
74
+ # @see no_results=
75
+ def no_results?
76
+ @no_results
77
+ end
78
+
59
79
  # Absolute path to where the utility product files have to be installed.
60
80
  # Returns nil if {target_dir} is not set.
61
81
  #
62
82
  # @return [String,nil]
63
83
  def target_dir
64
84
  if @target_dir
65
- File.expand_path(@target_dir, File.expand_path(Autobuild.send("#{name}_prefix") || name, package.prefix))
85
+ utility_prefix = Autobuild.send("#{name}_prefix") || name
86
+ File.expand_path(@target_dir,
87
+ File.expand_path(utility_prefix, package.prefix))
66
88
  else
67
89
  File.join(package.logdir, "#{name}-results", package.name)
68
90
  end
@@ -79,6 +101,7 @@ def target_dir
79
101
  # @return [Rake::Task]
80
102
  def task(&block)
81
103
  return if @task
104
+
82
105
  @task = package.task task_name do
83
106
  # This flag allows to disable this utility's task
84
107
  # once {task} has been called
@@ -92,25 +115,26 @@ def task(&block)
92
115
  end
93
116
  end
94
117
 
95
- package.task name => task_name
118
+ package.task name => task_name
96
119
  @task
97
120
  end
98
121
 
99
122
  def call_task_block
100
- yield if block_given?
123
+ @invoked = true
101
124
 
102
- # Allow the user to install manually in the task
103
- # block
104
- if !@installed && target_dir
105
- install
125
+ begin
126
+ yield if block_given?
127
+ @success = true
128
+ rescue StandardError => e
129
+ install if install_on_error? && !@installed && !no_results?
130
+ raise
106
131
  end
107
132
 
108
- rescue Interrupt
109
- raise
110
- rescue ::Exception => e
111
- if install_on_error? && !@installed && target_dir
112
- install
113
- end
133
+ # Allow the user to install manually in the task
134
+ # block
135
+ install if !@installed && !no_results?
136
+ rescue StandardError => e
137
+ @success = false
114
138
 
115
139
  if Autobuild.send("pass_#{name}_errors")
116
140
  raise
@@ -132,7 +156,7 @@ def call_task_block
132
156
  #
133
157
  # @return [Boolean]
134
158
  def available?
135
- @available && (source_dir && @task)
159
+ @available && @task && (no_results? || source_dir)
136
160
  end
137
161
 
138
162
  # True if this utility should be executed
@@ -154,8 +178,10 @@ def enabled?
154
178
  attr_writer :enabled
155
179
 
156
180
  def install
157
- if !File.directory?(source_dir)
158
- raise "#{source_dir} was expected to be a directory, but it is not. Check the package's #{name} generation. The generated #{name} products should be in #{source_dir}"
181
+ unless File.directory?(source_dir)
182
+ raise "#{source_dir} was expected to be a directory, but it is not. "\
183
+ "Check the package's #{name} generation. "\
184
+ "The generated #{name} products should be in #{source_dir}"
159
185
  end
160
186
 
161
187
  target_dir = self.target_dir
@@ -163,11 +189,30 @@ def install
163
189
  FileUtils.rm_rf target_dir
164
190
  FileUtils.mkdir_p File.dirname(target_dir)
165
191
  FileUtils.cp_r source_dir, target_dir
166
- Autoproj.message " copied #{name} results for #{package.name} from #{source_dir} to #{target_dir}"
192
+ Autoproj.message " copied #{name} results for #{package.name} "\
193
+ "from #{source_dir} to #{target_dir}"
167
194
 
168
195
  @installed = true
169
196
  end
170
197
 
198
+ # True if the utility has been invoked
199
+ def invoked?
200
+ @invoked
201
+ end
202
+
203
+ # True if the utility has been successful
204
+ #
205
+ # Combine with {#invoked?} to determine whether 'false' means 'not run'
206
+ # or 'failed'
207
+ def success?
208
+ @success
209
+ end
210
+
211
+ # True if the utility's results have been installed
212
+ def installed?
213
+ @installed
214
+ end
215
+
171
216
  # Can be called in the block given to {task} to announce that the
172
217
  # utility is to be disabled for that package. This is mainly used
173
218
  # when a runtime check is necessary to know if a package can run
@@ -188,8 +233,7 @@ def task_name
188
233
  #
189
234
  # @return [Boolean]
190
235
  def has_task?
191
- !!Rake.application.lookup(task_name)
236
+ Rake.application.lookup(task_name)
192
237
  end
193
238
  end
194
239
  end
195
-
@@ -1,3 +1,3 @@
1
1
  module Autobuild
2
- VERSION = "1.17.0" unless defined? Autobuild::VERSION
2
+ VERSION = "1.21.0".freeze unless defined? Autobuild::VERSION
3
3
  end