arduino_ci 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8bc68a43b822ba3c0456a181772f22d0aabd5a3d068e4012da71a25c073b85d1
4
- data.tar.gz: ca27e600b1c0768a5a2e69b0bde17cd6d985d3a99b9c963fc50b8d3675780e3e
3
+ metadata.gz: 28e1e4179be7a5d17d57b16b02f3eb75a41f6bb9506c8d034c14d2f077d09c48
4
+ data.tar.gz: b60ab526bb91b353379aa7f3d4a3ab8ec3f8fa18442369e0197c098487ed53a0
5
5
  SHA512:
6
- metadata.gz: 990cab7ac8de31536d3287d4bad8853f3a0710d89f49511cc54176be2a6ac4e725814bde7dcd9aaa3b6ce5dff47522a6294d802f3b53dacb921c6eb8a4702c7c
7
- data.tar.gz: d6eb5c03d83ea50cf1ee361360ede6869481f65123667604f0ef5309611c493717e706d04893a2a55786249acf509b08eeef31ff149d1c411cb4a787e59ddb52
6
+ metadata.gz: 7b9b69ee987e14970104cbf6c6e41f846b714d40536af43d5cc1b21e5811bb75f12172de94a21340277cc830654f97a5a8cb4c5e954f5c2358e515a39ac9c871
7
+ data.tar.gz: 360e1c2b48e9f706a90275356363802c6534968e0d96c29d5f7a825a1f0c73df2d2526d680bf103909544508506c1e0a7effec59a722f1788b171184d0bbd332
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- # ArduinoCI Ruby gem (`arduino_ci`) [![Gem Version](https://badge.fury.io/rb/arduino_ci.svg)](https://rubygems.org/gems/arduino_ci) [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/0.1.13)
2
+ # ArduinoCI Ruby gem (`arduino_ci`) [![Gem Version](https://badge.fury.io/rb/arduino_ci.svg)](https://rubygems.org/gems/arduino_ci) [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/0.1.14)
3
3
 
4
4
  You want your Arduino library to be automatically built and tested every time someone contributes code to your project on GitHub, but the Arduino IDE lacks the ability to run unit tests. [Arduino CI](https://github.com/ianfixes/arduino_ci) provides that ability.
5
5
 
@@ -4,6 +4,7 @@ require 'set'
4
4
  require 'pathname'
5
5
 
6
6
  WIDTH = 80
7
+ FIND_FILES_INDENT = 4
7
8
 
8
9
  @failure_count = 0
9
10
  @passfail = proc { |result| result ? "✓" : "✗" }
@@ -23,6 +24,10 @@ def terminate(final = nil)
23
24
  end
24
25
 
25
26
  # make a nice status line for an action and react to the action
27
+ # TODO / note to self: inform_multline is tougher to write
28
+ # without altering the signature because it only leaves space
29
+ # for the checkmark _after_ the multiline, it doesn't know how
30
+ # to make that conditionally the body
26
31
  def perform_action(message, multiline, mark_fn, on_fail_msg, tally_on_fail, abort_on_fail)
27
32
  line = "#{message}... "
28
33
  endline = "...#{message} "
@@ -83,9 +88,36 @@ def assured_platform(purpose, name, config)
83
88
  platform_definition
84
89
  end
85
90
 
91
+ # Return true if the file (or one of the dirs containing it) is hidden
92
+ def file_is_hidden_somewhere?(path)
93
+ # this is clunkly but pre-2.2-ish ruby doesn't return ascend as an enumerator
94
+ path.ascend do |part|
95
+ return true if part.basename.to_s.start_with? "."
96
+ end
97
+ false
98
+ end
99
+
100
+ # print out some files
101
+ def display_files(pathname)
102
+ # `find` doesn't follow symlinks, so we should instead
103
+ realpath = pathname.symlink? ? pathname.readlink : pathname
104
+
105
+ # suppress directories and dotfile-based things
106
+ all_files = realpath.find.select(&:file?)
107
+ non_hidden = all_files.reject { |path| file_is_hidden_somewhere?(path) }
108
+
109
+ # print files with an indent
110
+ margin = " " * FIND_FILES_INDENT
111
+ non_hidden.each { |p| puts "#{margin}#{p}" }
112
+ end
113
+
86
114
  # initialize command and config
87
115
  config = ArduinoCI::CIConfig.default.from_project_library
88
116
  @arduino_cmd = ArduinoCI::ArduinoInstallation.autolocate!
117
+ inform("Located Arduino binary") { @arduino_cmd.binary_path.to_s }
118
+
119
+ # index the existing libraries
120
+ attempt("Indexing libraries") { @arduino_cmd.index_libraries } unless @arduino_cmd.libraries_indexed
89
121
 
90
122
  # initialize library under test
91
123
  installed_library_path = attempt("Installing library under test") do
@@ -95,10 +127,11 @@ if installed_library_path.exist?
95
127
  inform("Library installed at") { installed_library_path.to_s }
96
128
  else
97
129
  assure_multiline("Library installed successfully") do
130
+ # print out the contents of the deepest directory we actually find
98
131
  @arduino_cmd.lib_dir.ascend do |path_part|
99
132
  next unless path_part.exist?
100
133
 
101
- break puts path_part.find.to_a.to_s
134
+ break display_files(path_part)
102
135
  end
103
136
  false
104
137
  end
@@ -120,26 +153,54 @@ compilers.each do |gcc_binary|
120
153
  inform("libasan availability for #{gcc_binary}") { cpp_library.libasan?(gcc_binary) }
121
154
  end
122
155
 
123
- # gather up all required boards so we can install them up front.
156
+ # Ensure platforms exist for unit test, and save their info in all_platform_info keyed by name
157
+ all_platform_info = {}
158
+ config.platforms_to_unittest.each { |p| all_platform_info[p] = assured_platform("unittest", p, config) }
159
+
160
+ # gather up all required boards for compilation so we can install them up front.
124
161
  # start with the "platforms to unittest" and add the examples
125
162
  # while we're doing that, get the aux libraries as well
126
- all_platforms = {}
163
+ example_platform_info = {}
164
+ board_package_url = {}
127
165
  aux_libraries = Set.new(config.aux_libraries_for_unittest + config.aux_libraries_for_build)
128
166
  # while collecting the platforms, ensure they're defined
129
- config.platforms_to_unittest.each { |p| all_platforms[p] = assured_platform("unittest", p, config) }
130
167
  library_examples.each do |path|
131
168
  ovr_config = config.from_example(path)
132
- ovr_config.platforms_to_build.each { |p| all_platforms[p] = assured_platform("library example", p, config) }
169
+ ovr_config.platforms_to_build.each do |platform|
170
+ # assure the platform if we haven't already
171
+ next if example_platform_info.key?(platform)
172
+
173
+ platform_info = assured_platform("library example", platform, config)
174
+ next if platform_info.nil?
175
+
176
+ example_platform_info[platform] = all_platform_info[platform] = platform_info
177
+ package = platform_info[:package]
178
+ board_package_url[package] = ovr_config.package_url(package)
179
+ end
133
180
  aux_libraries.merge(ovr_config.aux_libraries_for_build)
134
181
  end
135
182
 
136
183
  # with all platform info, we can extract unique packages and their urls
137
184
  # do that, set the URLs, and download the packages
138
- all_packages = all_platforms.values.map { |v| v[:package] }.uniq.reject(&:nil?)
139
- all_urls = all_packages.map { |p| config.package_url(p) }.uniq.reject(&:nil?)
185
+ all_packages = all_platform_info.values.map { |v| v[:package] }.uniq.reject(&:nil?)
186
+
187
+ # inform about builtin packages
188
+ all_packages.select { |p| config.package_builtin?(p) }.each do |p|
189
+ inform("Using built-in board package") { p }
190
+ end
191
+
192
+ # make sure any non-builtin package has a URL defined
193
+ all_packages.reject { |p| config.package_builtin?(p) }.each do |p|
194
+ assure("Board package #{p} has a defined URL") { board_package_url[p] }
195
+ end
196
+
197
+ # set up all the board manager URLs.
198
+ # we can safely reject nils now, they would be for the builtins
199
+ all_urls = all_packages.map { |p| board_package_url[p] }.uniq.reject(&:nil?)
200
+
140
201
  unless all_urls.empty?
141
202
  assure("Setting board manager URLs") do
142
- @arduino_cmd.set_pref("boardsmanager.additional.urls", all_urls.join(","))
203
+ @arduino_cmd.board_manager_urls = all_urls
143
204
  end
144
205
  end
145
206
 
@@ -161,19 +222,21 @@ end
161
222
  last_board = nil
162
223
  if !cpp_library.tests_dir.exist?
163
224
  inform_multiline("Skipping unit tests; no tests dir at #{cpp_library.tests_dir}") do
164
- puts cpp_library.tests_dir.parent.find.to_a.to_s
225
+ puts " In case that's an error, this is what was found in the library:"
226
+ display_files(cpp_library.tests_dir.parent)
165
227
  true
166
228
  end
167
229
  elsif cpp_library.test_files.empty?
168
230
  inform_multiline("Skipping unit tests; no test files were found in #{cpp_library.tests_dir}") do
169
- puts cpp_library.tests_dir.find.to_a.to_s
231
+ puts " In case that's an error, this is what was found in the tests directory:"
232
+ display_files(cpp_library.tests_dir)
170
233
  true
171
234
  end
172
235
  elsif config.platforms_to_unittest.empty?
173
236
  inform("Skipping unit tests") { "no platforms were requested" }
174
237
  else
175
238
  config.platforms_to_unittest.each do |p|
176
- board = all_platforms[p][:board]
239
+ board = all_platform_info[p][:board]
177
240
  assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
178
241
  last_board = board
179
242
  cpp_library.test_files.each do |unittest_path|
@@ -202,7 +265,7 @@ end
202
265
 
203
266
  if library_examples.empty?
204
267
  inform_multiline("Skipping libraries; no examples found in #{installed_library_path}") do
205
- puts installed_library_path.find.to_a.to_s
268
+ display_files(installed_library_path)
206
269
  end
207
270
  else
208
271
  attempt("Setting compiler warning level") { @arduino_cmd.set_pref("compiler.warning_level", "all") }
@@ -218,7 +281,7 @@ else
218
281
  end
219
282
 
220
283
  examples_by_platform.each do |platform, example_paths|
221
- board = all_platforms[platform][:board]
284
+ board = all_platform_info[platform][:board]
222
285
  assure("Switching to board for #{platform} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
223
286
  last_board = board
224
287
 
@@ -4,6 +4,7 @@ require 'set'
4
4
  require 'pathname'
5
5
 
6
6
  WIDTH = 80
7
+ FIND_FILES_INDENT = 4
7
8
 
8
9
  @failure_count = 0
9
10
  @passfail = proc { |result| result ? "✓" : "✗" }
@@ -23,7 +24,7 @@ def terminate(final = nil)
23
24
  end
24
25
 
25
26
  # make a nice status line for an action and react to the action
26
- def perform_action(message, multiline, mark_fn, on_fail_msg, abort_on_fail)
27
+ def perform_action(message, multiline, mark_fn, on_fail_msg, tally_on_fail, abort_on_fail)
27
28
  line = "#{message}... "
28
29
  endline = "...#{message} "
29
30
  if multiline
@@ -31,14 +32,15 @@ def perform_action(message, multiline, mark_fn, on_fail_msg, abort_on_fail)
31
32
  else
32
33
  print line
33
34
  end
35
+ STDOUT.flush
34
36
  result = yield
35
37
  mark = mark_fn.nil? ? "" : mark_fn.call(result)
36
38
  # if multline, put checkmark at full width
37
39
  print endline if multiline
38
- puts mark.rjust(WIDTH - line.length, " ")
40
+ puts mark.to_s.rjust(WIDTH - line.length, " ")
39
41
  unless result
40
42
  puts on_fail_msg unless on_fail_msg.nil?
41
- @failure_count += 1
43
+ @failure_count += 1 if tally_on_fail
42
44
  # print out error messaging here if we've captured it
43
45
  terminate if abort_on_fail
44
46
  end
@@ -47,29 +49,30 @@ end
47
49
 
48
50
  # Make a nice status for something that defers any failure code until script exit
49
51
  def attempt(message, &block)
50
- perform_action(message, false, @passfail, nil, false, &block)
52
+ perform_action(message, false, @passfail, nil, true, false, &block)
51
53
  end
52
54
 
53
55
  # Make a nice status for something that defers any failure code until script exit
54
56
  def attempt_multiline(message, &block)
55
- perform_action(message, true, @passfail, nil, false, &block)
57
+ perform_action(message, true, @passfail, nil, true, false, &block)
56
58
  end
57
59
 
58
60
  # Make a nice status for something that kills the script immediately on failure
61
+ FAILED_ASSURANCE_MESSAGE = "This may indicate a problem with ArduinoCI, or your configuration".freeze
59
62
  def assure(message, &block)
60
- perform_action(message, false, @passfail, "This may indicate a problem with ArduinoCI, or your configuration", true, &block)
63
+ perform_action(message, false, @passfail, FAILED_ASSURANCE_MESSAGE, true, true, &block)
64
+ end
65
+
66
+ def assure_multiline(message, &block)
67
+ perform_action(message, true, @passfail, FAILED_ASSURANCE_MESSAGE, true, true, &block)
61
68
  end
62
69
 
63
70
  def inform(message, &block)
64
- perform_action(message, false, proc { |x| x }, nil, false, &block)
71
+ perform_action(message, false, proc { |x| x }, nil, false, false, &block)
65
72
  end
66
73
 
67
74
  def inform_multiline(message, &block)
68
- <<<<<<< HEAD
69
- perform_action(message, true, nil, nil, false, &block)
70
- =======
71
- perform_action(message, true, proc { }, nil, false, &block)
72
- >>>>>>> 30d4a9f... Show file tree when unittests or examples aren't found
75
+ perform_action(message, true, nil, nil, false, false, &block)
73
76
  end
74
77
 
75
78
  # Assure that a platform exists and return its definition
@@ -81,15 +84,51 @@ def assured_platform(purpose, name, config)
81
84
  platform_definition
82
85
  end
83
86
 
87
+ # print out some files
88
+ def display_files(pathname)
89
+ # `find` doesn't follow symlinks, so we should instead
90
+ realpath = pathname.symlink? ? pathname.readlink : pathname
91
+
92
+ # suppress directories and dotfile-based things
93
+ all_files = realpath.find.select(&:file?)
94
+ non_hidden = all_files.reject do |path|
95
+ <<<<<<< HEAD
96
+ path.ascend.any? { |part| part.basename.to_s.start_with? "." }
97
+ =======
98
+ path.ascend do |path_part|
99
+ next true if path_part.basename.to_s.start_with? "."
100
+ end
101
+ false
102
+ >>>>>>> 0f4e679... don't redundantly report assured platforms
103
+ end
104
+
105
+ # print files with an indent
106
+ margin = " " * FIND_FILES_INDENT
107
+ non_hidden.each { |p| puts "#{margin}#{p}" }
108
+ end
109
+
84
110
  # initialize command and config
85
111
  config = ArduinoCI::CIConfig.default.from_project_library
86
112
  @arduino_cmd = ArduinoCI::ArduinoInstallation.autolocate!
87
113
 
88
114
  # initialize library under test
89
- installed_library_path = assure("Installing library under test") { @arduino_cmd.install_local_library(".") }
115
+ installed_library_path = attempt("Installing library under test") do
116
+ @arduino_cmd.install_local_library(Pathname.new("."))
117
+ end
118
+ if installed_library_path.exist?
119
+ inform("Library installed at") { installed_library_path.to_s }
120
+ else
121
+ assure_multiline("Library installed successfully") do
122
+ @arduino_cmd.lib_dir.ascend do |path_part|
123
+ next unless path_part.exist?
124
+
125
+ break display_files(path_part)
126
+ end
127
+ false
128
+ end
129
+ end
90
130
  library_examples = @arduino_cmd.library_examples(installed_library_path)
91
131
  cpp_library = ArduinoCI::CppLibrary.new(installed_library_path, @arduino_cmd.lib_dir)
92
- inform("Library installed at") { installed_library_path.to_s }
93
132
 
94
133
  # check GCC
95
134
  compilers = config.compilers_to_use
@@ -102,6 +141,7 @@ compilers.each do |gcc_binary|
102
141
  puts version.split("\n").map { |l| " #{l}" }.join("\n")
103
142
  version
104
143
  end
144
+ inform("libasan availability for #{gcc_binary}") { cpp_library.libasan?(gcc_binary) }
105
145
  end
106
146
 
107
147
  # gather up all required boards so we can install them up front.
@@ -111,9 +151,13 @@ all_platforms = {}
111
151
  aux_libraries = Set.new(config.aux_libraries_for_unittest + config.aux_libraries_for_build)
112
152
  # while collecting the platforms, ensure they're defined
113
153
  config.platforms_to_unittest.each { |p| all_platforms[p] = assured_platform("unittest", p, config) }
154
+ example_platforms = {}
114
155
  library_examples.each do |path|
115
156
  ovr_config = config.from_example(path)
116
- ovr_config.platforms_to_build.each { |p| all_platforms[p] = assured_platform("library example", p, config) }
157
+ ovr_config.platforms_to_build.each do |p|
158
+ # assure the platform if we haven't already
159
+ example_platforms[p] = all_platforms[p] = assured_platform("library example", p, config) unless example_platforms.key?(p)
160
+ end
117
161
  aux_libraries.merge(ovr_config.aux_libraries_for_build)
118
162
  end
119
163
 
@@ -145,12 +189,12 @@ end
145
189
  last_board = nil
146
190
  if !cpp_library.tests_dir.exist?
147
191
  inform_multiline("Skipping unit tests; no tests dir at #{cpp_library.tests_dir}") do
148
- puts cpp_library.tests_dir.find.to_a.to_s
192
+ display_files(cpp_library.tests_dir.parent)
149
193
  true
150
194
  end
151
195
  elsif cpp_library.test_files.empty?
152
196
  inform_multiline("Skipping unit tests; no test files were found in #{cpp_library.tests_dir}") do
153
- puts cpp_library.tests_dir.find.to_a.to_s
197
+ display_files(cpp_library.tests_dir)
154
198
  true
155
199
  end
156
200
  elsif config.platforms_to_unittest.empty?
@@ -158,7 +202,6 @@ elsif config.platforms_to_unittest.empty?
158
202
  else
159
203
  config.platforms_to_unittest.each do |p|
160
204
  board = all_platforms[p][:board]
161
- last_board = "arduino:avr:pro:cpu=16MHzatmega328"
162
205
  assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
163
206
  last_board = board
164
207
  cpp_library.test_files.each do |unittest_path|
@@ -187,18 +230,27 @@ end
187
230
 
188
231
  if library_examples.empty?
189
232
  inform_multiline("Skipping libraries; no examples found in #{installed_library_path}") do
190
- puts installed_library_path.find.to_a.to_s
233
+ display_files(installed_library_path)
191
234
  end
192
235
  else
193
236
  attempt("Setting compiler warning level") { @arduino_cmd.set_pref("compiler.warning_level", "all") }
194
237
 
195
- # unlike previous, iterate examples / boards
196
- library_examples.each do |example_path|
238
+ # switching boards takes time, so iterate board first
239
+ # _then_ whichever examples match it
240
+ examples_by_platform = library_examples.each_with_object({}) do |example_path, acc|
197
241
  ovr_config = config.from_example(example_path)
198
242
  ovr_config.platforms_to_build.each do |p|
199
- board = all_platforms[p][:board]
200
- assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
201
- last_board = board
243
+ acc[p] = [] unless acc.key?(p)
244
+ acc[p] << example_path
245
+ end
246
+ end
247
+
248
+ examples_by_platform.each do |platform, example_paths|
249
+ board = all_platforms[platform][:board]
250
+ assure("Switching to board for #{platform} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
251
+ last_board = board
252
+
253
+ example_paths.each do |example_path|
202
254
  example_name = File.basename(example_path)
203
255
  attempt("Verifying #{example_name}") do
204
256
  ret = @arduino_cmd.verify_sketch(example_path)
@@ -1,6 +1,9 @@
1
1
  require 'fileutils'
2
2
  require 'pathname'
3
3
 
4
+ # workaround for https://github.com/arduino/Arduino/issues/3535
5
+ WORKAROUND_LIB = "USBHost".freeze
6
+
4
7
  module ArduinoCI
5
8
 
6
9
  # Wrap the Arduino executable. This requires, in some cases, a faked display.
@@ -18,12 +21,16 @@ module ArduinoCI
18
21
  self.class_eval("def flag_#{name};\"#{text}\";end", __FILE__, __LINE__)
19
22
  end
20
23
 
21
- # the path to the Arduino executable
22
- # @return [String]
24
+ # the array of command components to launch the Arduino executable
25
+ # @return [Array<String>]
23
26
  attr_accessor :base_cmd
24
27
 
28
+ # the actual path to the executable on this platform
29
+ # @return [Pathname]
30
+ attr_accessor :binary_path
31
+
25
32
  # part of a workaround for https://github.com/arduino/Arduino/issues/3535
26
- attr_reader :library_is_indexed
33
+ attr_reader :libraries_indexed
27
34
 
28
35
  # @return [String] STDOUT of the most recently-run command
29
36
  attr_reader :last_out
@@ -47,7 +54,7 @@ module ArduinoCI
47
54
  def initialize
48
55
  @prefs_cache = {}
49
56
  @prefs_fetched = false
50
- @library_is_indexed = false
57
+ @libraries_indexed = false
51
58
  @last_out = ""
52
59
  @last_err = ""
53
60
  @last_msg = ""
@@ -145,11 +152,19 @@ module ArduinoCI
145
152
  ret
146
153
  end
147
154
 
148
- # run a command and don't capture its output, but use the same signature
149
- # @return [Hash] {:out => String, :err => String, :success => bool}
150
- def run_wrap(*args, **kwargs)
151
- success = run(*args, **kwargs)
152
- { out: "NOPE, use run_and_capture", err: "NOPE, use run_and_capture", success: success }
155
+ # Board manager URLs
156
+ # @return [Array<String>] The additional URLs used by the board manager
157
+ def board_manager_urls
158
+ url_list = get_pref("boardsmanager.additional.urls")
159
+ return [] if url_list.nil?
160
+
161
+ url_list.split(",")
162
+ end
163
+
164
+ # Set board manager URLs
165
+ # @return [Array<String>] The additional URLs used by the board manager
166
+ def board_manager_urls=(all_urls)
167
+ set_pref("boardsmanager.additional.urls", all_urls.join(","))
153
168
  end
154
169
 
155
170
  # check whether a board is installed
@@ -174,21 +189,29 @@ module ArduinoCI
174
189
  # install a library by name
175
190
  # @param name [String] the library name
176
191
  # @return [bool] whether the command succeeded
177
- def install_library(library_name)
178
- # workaround for https://github.com/arduino/Arduino/issues/3535
179
- # use a dummy library name but keep open the possiblity that said library
180
- # might be selected by choice for installation
181
- workaround_lib = "USBHost"
182
- unless @library_is_indexed || workaround_lib == library_name
183
- @library_is_indexed = run_and_capture(flag_install_library, workaround_lib)
184
- end
192
+ def _install_library(library_name)
193
+ success = run_and_capture(flag_install_library, library_name)[:success]
185
194
 
186
- # actual installation
187
- result = run_and_capture(flag_install_library, library_name)
195
+ @libraries_indexed = (@libraries_indexed || success) if library_name == WORKAROUND_LIB
196
+ success
197
+ end
198
+
199
+ # index the set of libraries by installing a dummy library
200
+ # related to WORKAROUND_LIB and https://github.com/arduino/Arduino/issues/3535
201
+ # TODO: unclear if this is still necessary
202
+ def index_libraries
203
+ return true if @libraries_indexed
204
+
205
+ _install_library(WORKAROUND_LIB)
206
+ @libraries_indexed
207
+ end
188
208
 
189
- # update flag if necessary
190
- @library_is_indexed = (@library_is_indexed || result[:success]) if library_name == workaround_lib
191
- result[:success]
209
+ # install a library by name
210
+ # @param name [String] the library name
211
+ # @return [bool] whether the command succeeded
212
+ def install_library(library_name)
213
+ index_libraries
214
+ _install_library(library_name)
192
215
  end
193
216
 
194
217
  # generate the (very likely) path of a library given its name
@@ -5,9 +5,6 @@ module ArduinoCI
5
5
 
6
6
  # Implementation of Arduino linux IDE commands
7
7
  class ArduinoCmdLinux < ArduinoCmd
8
-
9
- attr_reader :prefs_response_time
10
-
11
8
  flag :get_pref, "--get-pref"
12
9
  flag :set_pref, "--pref"
13
10
  flag :save_prefs, "--save-prefs"
@@ -15,61 +12,6 @@ module ArduinoCI
15
12
  flag :install_boards, "--install-boards"
16
13
  flag :install_library, "--install-library"
17
14
  flag :verify, "--verify"
18
-
19
- def initialize
20
- super
21
- @prefs_response_time = nil
22
- end
23
-
24
- # fetch preferences in their raw form
25
- # @return [String] Preferences as a set of lines
26
- def _prefs_raw
27
- start = Time.now
28
- resp = run_and_capture(flag_get_pref)
29
- @prefs_response_time = Time.now - start
30
- return nil unless resp[:success]
31
-
32
- resp[:out]
33
- end
34
-
35
- def run_with_gui_guess(message, *args, **kwargs)
36
- # On Travis CI, we get an error message in the GUI instead of on STDERR
37
- # so, assume that if we don't get a rapid reply that things are not installed
38
-
39
- prefs if @prefs_response_time.nil?
40
- x3 = @prefs_response_time * 3
41
- Timeout.timeout(x3) do
42
- result = run_and_capture(*args, **kwargs)
43
- result[:success]
44
- end
45
- rescue Timeout::Error
46
- puts "No response in #{x3} seconds. Assuming graphical modal error message#{message}."
47
- false
48
- end
49
-
50
- # underlying preference-setter.
51
- # @param key [String] the preference key
52
- # @param value [String] the preference value
53
- # @return [bool] whether the command succeeded
54
- def _set_pref(key, value)
55
- run_with_gui_guess(" about preferences", flag_set_pref, "#{key}=#{value}", flag_save_prefs)
56
- end
57
-
58
- # check whether a board is installed
59
- # we do this by just selecting a board.
60
- # the arduino binary will error if unrecognized and do a successful no-op if it's installed
61
- # @param boardname [String] The name of the board
62
- # @return [bool]
63
- def board_installed?(boardname)
64
- run_with_gui_guess(" about board not installed", flag_use_board, boardname)
65
- end
66
-
67
- # use a particular board for compilation
68
- # @param boardname [String] The name of the board
69
- def use_board(boardname)
70
- run_with_gui_guess(" about board not installed", flag_use_board, boardname, flag_save_prefs)
71
- end
72
-
73
15
  end
74
16
 
75
17
  end
@@ -1,3 +1,4 @@
1
+ require 'pathname'
1
2
  require "arduino_ci/host"
2
3
  require "arduino_ci/arduino_cmd_osx"
3
4
  require "arduino_ci/arduino_cmd_linux"
@@ -32,12 +33,14 @@ module ArduinoCI
32
33
 
33
34
  ret = ArduinoCmdLinux.new
34
35
  ret.base_cmd = [loc]
36
+ ret.binary_path = Pathname.new(loc)
35
37
  when :windows then
36
38
  loc = ArduinoDownloaderWindows.autolocated_executable
37
39
  return nil if loc.nil?
38
40
 
39
41
  ret = ArduinoCmdWindows.new
40
42
  ret.base_cmd = [loc]
43
+ ret.binary_path = Pathname.new(loc)
41
44
  end
42
45
  ret
43
46
  end
@@ -75,10 +78,11 @@ module ArduinoCI
75
78
  # don't want to see is a java error.
76
79
  args = launcher + ["--bogus-option"]
77
80
  result = Host.run_and_capture(*args)
78
- if result[:err].include? "Error: unknown option: --bogus-option"
79
- ret.base_cmd = launcher
80
- return ret
81
- end
81
+ next unless result[:err].include? "Error: unknown option: --bogus-option"
82
+
83
+ ret.base_cmd = launcher
84
+ ret.binary_path = Pathname.new(osx_root)
85
+ return ret
82
86
  end
83
87
  nil
84
88
  end
@@ -191,6 +191,13 @@ module ArduinoCI
191
191
  deep_clone(defn)
192
192
  end
193
193
 
194
+ # Whether a package is built-in to arduino
195
+ # @param package [String] the package name (e.g. "arduino:avr")
196
+ # @return [bool]
197
+ def package_builtin?(package)
198
+ package.start_with?("arduino:")
199
+ end
200
+
194
201
  # the URL that gives the download info for a given package (a JSON file).
195
202
  # this is NOT where the package comes from.
196
203
  # @param package [String] the package name (e.g. "arduino:avr")
@@ -50,16 +50,32 @@ module ArduinoCI
50
50
  #
51
51
  # This assumes the vendor bundle will be at `vendor/bundle` and not some other location
52
52
  # @param path [Pathname] The path to check
53
- # @return [Array<Pathname>] The paths of the found files
53
+ # @return [bool]
54
54
  def vendor_bundle?(path)
55
55
  # TODO: look for Gemfile, look for .bundle/config and get BUNDLE_PATH from there?
56
56
  base = @base_dir + "vendor"
57
57
  return false unless base.exist?
58
58
 
59
- real = base.realpath
60
- path.ascend do |path_part|
61
- return true if path_part == base
62
- return true if path_part == real
59
+ vendor_bundle_aliases = [base, base.realpath]
60
+
61
+ # we could do this but some rubies don't return an enumerator for ascend
62
+ # path.ascend.any? { |part| vendor_bundle_aliases.include?(part) }
63
+ path.ascend do |part|
64
+ return true if vendor_bundle_aliases.include?(part)
65
+ end
66
+ false
67
+ end
68
+
69
+ # Guess whether a file is part of the tests/ dir (indicating library compilation should ignore it).
70
+ #
71
+ # @param path [Pathname] The path to check
72
+ # @return [bool]
73
+ def in_tests_dir?(path)
74
+ tests_dir_aliases = [tests_dir, tests_dir.realpath]
75
+ # we could do this but some rubies don't return an enumerator for ascend
76
+ # path.ascend.any? { |part| tests_dir_aliases.include?(part) }
77
+ path.ascend do |part|
78
+ return true if tests_dir_aliases.include?(part)
63
79
  end
64
80
  false
65
81
  end
@@ -98,16 +114,7 @@ module ArduinoCI
98
114
  # CPP files that are part of the project library under test
99
115
  # @return [Array<Pathname>]
100
116
  def cpp_files
101
- real_tests_dir = tests_dir.realpath
102
- cpp_files_in(@base_dir).reject do |p|
103
- next true if p.ascend do |path_part|
104
- break true if path_part == tests_dir
105
- break true if path_part == real_tests_dir
106
- break true if vendor_bundle?(p)
107
- end
108
-
109
- false
110
- end
117
+ cpp_files_in(@base_dir).reject { |p| vendor_bundle?(p) || in_tests_dir?(p) }
111
118
  end
112
119
 
113
120
  # CPP files that are part of the arduino mock library we're providing
@@ -1,3 +1,3 @@
1
1
  module ArduinoCI
2
- VERSION = "0.1.13".freeze
2
+ VERSION = "0.1.14".freeze
3
3
  end
data/misc/default.yml CHANGED
@@ -3,15 +3,21 @@
3
3
  # https://en.wikipedia.org/wiki/List_of_Arduino_boards_and_compatible_systems
4
4
 
5
5
  packages:
6
+ # arduino:xxx are builtin, we don't need to include them here
6
7
  esp8266:esp8266:
7
8
  url: http://arduino.esp8266.com/stable/package_esp8266com_index.json
8
9
  adafruit:avr:
9
10
  url: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
11
+ adafruit:samd:
12
+ url: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
13
+ esp32:esp32:
14
+ url: https://dl.espressif.com/dl/package_esp32_index.json
10
15
 
11
16
  platforms:
17
+
12
18
  uno:
13
19
  board: arduino:avr:uno
14
- package: ~
20
+ package: arduino:avr
15
21
  gcc:
16
22
  features:
17
23
  defines:
@@ -37,6 +43,14 @@ platforms:
37
43
  - ARDUINO_SAMD_ZERO
38
44
  warnings:
39
45
  flags:
46
+ esp32:
47
+ board: esp32:esp32:featheresp32:FlashFreq=80
48
+ package: esp32:esp32
49
+ gcc:
50
+ features:
51
+ defines:
52
+ warnings:
53
+ flags:
40
54
  esp8266:
41
55
  board: esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80
42
56
  package: esp8266:esp8266
@@ -47,7 +61,7 @@ platforms:
47
61
  flags:
48
62
  leonardo:
49
63
  board: arduino:avr:leonardo
50
- package: ~
64
+ package: arduino:avr
51
65
  gcc:
52
66
  features:
53
67
  defines:
@@ -70,6 +84,39 @@ platforms:
70
84
  defines:
71
85
  warnings:
72
86
  flags:
87
+ m4:
88
+ board: adafruit:samd:adafruit_metro_m4
89
+ package: adafruit:samd
90
+ gcc:
91
+ features:
92
+ defines:
93
+ warnings:
94
+ flags:
95
+ mega2560:
96
+ board: arduino:avr:mega:cpu=atmega2560
97
+ package: arduino:avr
98
+ gcc:
99
+ features:
100
+ defines:
101
+ warnings:
102
+ flags:
103
+ cplayClassic:
104
+ board: arduino:avr:circuitplay32u4cat
105
+ package: arduino:avr
106
+ gcc:
107
+ features:
108
+ defines:
109
+ warnings:
110
+ flags:
111
+ cplayExpress:
112
+ board: arduino:samd:adafruit_circuitplayground_m0
113
+ package: arduino:samd
114
+ gcc:
115
+ features:
116
+ defines:
117
+ warnings:
118
+ flags:
119
+
73
120
 
74
121
  compile:
75
122
  libraries: ~
@@ -78,6 +125,10 @@ compile:
78
125
  - due
79
126
  - zero
80
127
  - leonardo
128
+ - m4
129
+ - esp32
130
+ - esp8266
131
+ - mega2560
81
132
 
82
133
  unittest:
83
134
  compilers:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arduino_ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Katz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-19 00:00:00.000000000 Z
11
+ date: 2018-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: os