class ArduinoCI::ArduinoDownloader

Manage the OS-specific download & install of Arduino

Public Class Methods

autolocated_executable() click to toggle source

The autolocated executable of the installation

@return [Pathname] or nil

# File lib/arduino_ci/arduino_downloader.rb, line 35
def self.autolocated_executable
  # Arbitrarily, I'm going to pick the force installed location first
  # if it exists.  I'm not sure why we would have both, but if we did
  # a force install then let's make sure we actually use it.
  locations = [self.force_installed_executable, self.existing_executable]
  locations.find { |loc| !loc.nil? && File.exist?(loc) }
end
downloader() click to toggle source

The technology that will be used to complete the download (for logging purposes) @return [string]

# File lib/arduino_ci/arduino_downloader.rb, line 70
def self.downloader
  "open-uri"
end
existing_executable() click to toggle source

The executable Arduino file in an existing installation, or nil @return [Pathname]

# File lib/arduino_ci/arduino_downloader.rb, line 45
def self.existing_executable
  self.must_implement(__method__)
end
extract(_package_file) click to toggle source

Extract the package_file to extracted_file @return [bool] whether successful

# File lib/arduino_ci/arduino_downloader.rb, line 83
def self.extract(_package_file)
  self.must_implement(__method__)
end
extracted_file() click to toggle source

The local filename of the extracted IDE package (zip/tar/etc) @return [string]

# File lib/arduino_ci/arduino_downloader.rb, line 57
def self.extracted_file
  self.must_implement(__method__)
end
extracter() click to toggle source

The technology that will be used to extract the download (for logging purposes) @return [string]

# File lib/arduino_ci/arduino_downloader.rb, line 77
def self.extracter
  self.must_implement(__method__)
end
force_installed_executable() click to toggle source

The executable Arduino file in a forced installation, or nil @return [Pathname]

# File lib/arduino_ci/arduino_downloader.rb, line 63
def self.force_installed_executable
  Pathname.new(ENV['HOME']) + self.extracted_file
end
must_implement(method) click to toggle source

Provide guidelines to the implementer of this class

# File lib/arduino_ci/arduino_downloader.rb, line 22
def self.must_implement(method)
  raise NotImplementedError, "#{self.class.name} failed to implement ArduinoDownloader.#{method}"
end
new(desired_version, output = $stdout) click to toggle source

@param desired_version [string] Version string e.g. 1.8.7 @param output [IO] $stdout, $stderr, File.new(/dev/null, 'w'), etc. where console output will be sent

# File lib/arduino_ci/arduino_downloader.rb, line 16
def initialize(desired_version, output = $stdout)
  @desired_version = desired_version
  @output = output
end

Public Instance Methods

download() click to toggle source

Download the package_url to package_file @return [bool] whether successful

# File lib/arduino_ci/arduino_downloader.rb, line 95
def download
  # Turned off ssl verification
  # This should be acceptable because it won't happen on a user's machine, just CI

  # define a progress-bar printer
  chunk_size = 1024 * 1024 * 1024
  total_size = 0
  dots = 0
  dot_printer = lambda do |size|
    total_size += size
    needed_dots = (total_size / chunk_size).to_i
    unprinted_dots = needed_dots - dots
    @output.print("." * unprinted_dots) if unprinted_dots.positive?
    dots = needed_dots
  end

  open(package_url, ssl_verify_mode: 0, progress_proc: dot_printer) do |url|
    File.open(package_file, 'wb') { |file| file.write(url.read) }
  end
rescue Net::OpenTimeout, Net::ReadTimeout, OpenURI::HTTPError, URI::InvalidURIError => e
  @output.puts "\nArduino force-install failed downloading #{package_url}: #{e}"
end
execute() click to toggle source

Forcibly install Arduino on linux from the web @return [bool] Whether the command succeeded

# File lib/arduino_ci/arduino_downloader.rb, line 126
def execute
  error_preparing = prepare
  unless error_preparing.nil?
    @output.puts "Arduino force-install failed preparation: #{error_preparing}"
    return false
  end

  arduino_package = "Arduino #{@desired_version} package"
  attempts = 0

  loop do
    if File.exist?(package_file)
      @output.puts "#{arduino_package} seems to have been downloaded already at #{package_file}" if attempts.zero?
      break
    elsif attempts >= DOWNLOAD_ATTEMPTS
      break @output.puts "After #{DOWNLOAD_ATTEMPTS} attempts, failed to download #{package_url}"
    else
      @output.print "Attempting to download #{arduino_package} with #{self.class.downloader}"
      download
      @output.puts
    end
    attempts += 1
  end

  if File.exist?(self.class.extracted_file)
    @output.puts "#{arduino_package} seems to have been extracted already at #{self.class.extracted_file}"
  elsif File.exist?(package_file)
    @output.print "Extracting archive with #{self.class.extracter}"
    self.class.extract(package_file)
    @output.puts
  end

  if File.exist?(self.class.force_installed_executable)
    @output.puts "#{arduino_package} seems to have been installed already at #{self.class.force_installed_executable}"
  elsif File.exist?(self.class.extracted_file)
    install
  else
    @output.puts "Could not find extracted archive (tried #{self.class.extracted_file})"
  end

  File.exist?(self.class.force_installed_executable)
end
install() click to toggle source

Move the extracted package file from extracted_file to the force_installed_executable @return [bool] whether successful

# File lib/arduino_ci/arduino_downloader.rb, line 120
def install
  FileUtils.mv self.class.extracted_file.to_s, self.class.force_installed_executable.to_s
end
package_file() click to toggle source

The local file (dir) name of the desired IDE package (zip/tar/etc) @return [string]

# File lib/arduino_ci/arduino_downloader.rb, line 51
def package_file
  self.class.must_implement(__method__)
end
package_url() click to toggle source

The URL of the desired IDE package (zip/tar/etc) for this platform @return [string]

# File lib/arduino_ci/arduino_downloader.rb, line 89
def package_url
  "https://github.com/arduino/arduino-cli/releases/download/#{@desired_version}/#{package_file}"
end
prepare() click to toggle source

Make any preparations or run any checks prior to making changes @return [string] Error message, or nil if success

# File lib/arduino_ci/arduino_downloader.rb, line 28
def prepare
  nil
end