autobuild 1.17.0 → 1.21.0

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