arduino_ci 0.1.9 → 0.1.10

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.
@@ -0,0 +1,219 @@
1
+ DOWNLOAD_ATTEMPTS = 3
2
+
3
+ module ArduinoCI
4
+
5
+ # Manage the OS-specific download & install of Arduino
6
+ class ArduinoDownloader
7
+
8
+ def initialize(desired_ide_version)
9
+ @desired_ide_version = desired_ide_version
10
+ end
11
+
12
+ # Provide guidelines to the implementer of this class
13
+ <<<<<<< HEAD
14
+ def must_implement(method)
15
+ raise NoMethodError("#{self.class.name} failed to implement ArduinoDownloader.#{method}")
16
+ =======
17
+ def self.must_implement(method)
18
+ raise NotImplementedError, "#{self.class.name} failed to implement ArduinoDownloader.#{method}"
19
+ >>>>>>> Refactor force_install code in preparation for windows CI
20
+ end
21
+
22
+ # Make any preparations or run any checks prior to making changes
23
+ # @return [string] Error message, or nil if success
24
+ def prepare
25
+ nil
26
+ end
27
+
28
+ # The autolocated executable of the installation
29
+ #
30
+ # @return [string] or nil
31
+ <<<<<<< HEAD
32
+ def self.autolocation
33
+ =======
34
+ def self.autolocated_executable
35
+ >>>>>>> Refactor force_install code in preparation for windows CI
36
+ # Arbitrarily, I'm going to pick the force installed location first
37
+ # if it exists. I'm not sure why we would have both, but if we did
38
+ # a force install then let's make sure we actually use it.
39
+ locations = [self.force_installed_executable, self.existing_executable]
40
+ locations.each do |loc|
41
+ next if loc.nil?
42
+ next unless File.exist? loc
43
+ return loc
44
+ end
45
+ nil
46
+ end
47
+
48
+ <<<<<<< HEAD
49
+ # The executable Arduino file in an existing installation, or nil
50
+ # @return [string]
51
+ def self.existing_executable
52
+ must_implement(__method__)
53
+ =======
54
+ # The autolocated directory of the installation
55
+ #
56
+ # @return [string] or nil
57
+ def self.autolocated_installation
58
+ # Arbitrarily, I'm going to pick the force installed location first
59
+ # if it exists. I'm not sure why we would have both, but if we did
60
+ # a force install then let's make sure we actually use it.
61
+ locations = [self.force_install_location, self.existing_installation]
62
+ locations.each do |loc|
63
+ next if loc.nil?
64
+ next unless File.exist? loc
65
+ return loc
66
+ end
67
+ nil
68
+ end
69
+
70
+ # The path to the directory of an existing installation, or nil
71
+ # @return [string]
72
+ def self.existing_installation
73
+ self.must_implement(__method__)
74
+ end
75
+
76
+ # The executable Arduino file in an existing installation, or nil
77
+ # @return [string]
78
+ def self.existing_executable
79
+ self.must_implement(__method__)
80
+ >>>>>>> Refactor force_install code in preparation for windows CI
81
+ end
82
+
83
+ # The executable Arduino file in a forced installation, or nil
84
+ # @return [string]
85
+ def self.force_installed_executable
86
+ <<<<<<< HEAD
87
+ must_implement(__method__)
88
+ =======
89
+ self.must_implement(__method__)
90
+ >>>>>>> Refactor force_install code in preparation for windows CI
91
+ end
92
+
93
+ # The technology that will be used to complete the download
94
+ # (for logging purposes)
95
+ # @return [string]
96
+ def downloader
97
+ <<<<<<< HEAD
98
+ must_implement(__method__)
99
+ =======
100
+ self.class.must_implement(__method__)
101
+ >>>>>>> Refactor force_install code in preparation for windows CI
102
+ end
103
+
104
+ # The technology that will be used to extract the download
105
+ # (for logging purposes)
106
+ # @return [string]
107
+ def extracter
108
+ <<<<<<< HEAD
109
+ must_implement(__method__)
110
+ =======
111
+ self.class.must_implement(__method__)
112
+ >>>>>>> Refactor force_install code in preparation for windows CI
113
+ end
114
+
115
+ # The URL of the desired IDE package (zip/tar/etc) for this platform
116
+ # @return [string]
117
+ def package_url
118
+ "https://downloads.arduino.cc/#{package_file}"
119
+ end
120
+
121
+ # The local file (dir) name of the desired IDE package (zip/tar/etc)
122
+ # @return [string]
123
+ def package_file
124
+ <<<<<<< HEAD
125
+ must_implement(__method__)
126
+ =======
127
+ self.class.must_implement(__method__)
128
+ >>>>>>> Refactor force_install code in preparation for windows CI
129
+ end
130
+
131
+ # The local filename of the extracted IDE package (zip/tar/etc)
132
+ # @return [string]
133
+ def extracted_file
134
+ <<<<<<< HEAD
135
+ must_implement(__method__)
136
+ =======
137
+ self.class.must_implement(__method__)
138
+ >>>>>>> Refactor force_install code in preparation for windows CI
139
+ end
140
+
141
+ # @return [String] The location where a forced install will go
142
+ def self.force_install_location
143
+ File.join(ENV['HOME'], 'arduino_ci_ide')
144
+ end
145
+
146
+ # Download the package_url to package_file, and maybe print a line of dots......
147
+ # @return [bool] whether successful
148
+ def download
149
+ <<<<<<< HEAD
150
+ must_implement(__method__)
151
+ =======
152
+ self.class.must_implement(__method__)
153
+ >>>>>>> Refactor force_install code in preparation for windows CI
154
+ end
155
+
156
+ # Extract the package_file to extracted_file
157
+ # @return [bool] whether successful
158
+ def extract
159
+ <<<<<<< HEAD
160
+ must_implement(__method__)
161
+ =======
162
+ self.class.must_implement(__method__)
163
+ >>>>>>> Refactor force_install code in preparation for windows CI
164
+ end
165
+
166
+ # Move the extracted package file from extracted_file to the force_install_location
167
+ # @return [bool] whether successful
168
+ def install
169
+ <<<<<<< HEAD
170
+ must_implement(__method__)
171
+ =======
172
+ self.class.must_implement(__method__)
173
+ >>>>>>> Refactor force_install code in preparation for windows CI
174
+ end
175
+
176
+ # Forcibly install Arduino on linux from the web
177
+ # @return [bool] Whether the command succeeded
178
+ def execute
179
+ error_preparing = prepare
180
+ unless error_preparing.nil?
181
+ puts "Arduino force-install failed preparation: #{error_preparing}"
182
+ return false
183
+ end
184
+
185
+ attempts = 0
186
+
187
+ loop do
188
+ if File.exist? package_file
189
+ puts "Arduino package seems to have been downloaded already" if attempts.zero?
190
+ break
191
+ elsif attempts >= DOWNLOAD_ATTEMPTS
192
+ break puts "After #{DOWNLOAD_ATTEMPTS} attempts, failed to download #{package_url}"
193
+ else
194
+ puts "Attempting to download Arduino package with #{downloader}"
195
+ download
196
+ end
197
+ attempts += 1
198
+ end
199
+
200
+ if File.exist? extracted_file
201
+ puts "Arduino package seems to have been extracted already"
202
+ elsif File.exist? package_file
203
+ puts "Extracting archive with #{extracter}"
204
+ extract
205
+ end
206
+
207
+ if File.exist? self.class.force_install_location
208
+ puts "Arduino package seems to have been installed already"
209
+ elsif File.exist? extracted_file
210
+ install
211
+ else
212
+ puts "Arduino force-install failed"
213
+ end
214
+
215
+ File.exist? self.class.force_install_location
216
+ end
217
+
218
+ end
219
+ end
@@ -0,0 +1,86 @@
1
+ require "arduino_ci/arduino_downloader"
2
+
3
+ USE_BUILDER = false
4
+
5
+ module ArduinoCI
6
+
7
+ # Manage the linux download & install of Arduino
8
+ class ArduinoDownloaderLinux < ArduinoDownloader
9
+
10
+ # The local filename of the desired IDE package (zip/tar/etc)
11
+ # @return [string]
12
+ def package_file
13
+ "#{extracted_file}-linux64.tar.xz"
14
+ end
15
+
16
+ # Make any preparations or run any checks prior to making changes
17
+ # @return [string] Error message, or nil if success
18
+ def prepare
19
+ reqs = [extracter]
20
+ reqs.each do |req|
21
+ return "#{req} does not appear to be installed!" unless Host.which(req)
22
+ end
23
+ nil
24
+ end
25
+
26
+ # The technology that will be used to extract the download
27
+ # (for logging purposes)
28
+ # @return [string]
29
+ def extracter
30
+ "tar"
31
+ end
32
+
33
+ # Extract the package_file to extracted_file
34
+ # @return [bool] whether successful
35
+ def extract
36
+ system(extracter, "xf", package_file)
37
+ end
38
+
39
+ # The local file (dir) name of the extracted IDE package (zip/tar/etc)
40
+ # @return [string]
41
+ def extracted_file
42
+ "arduino-#{@desired_ide_version}"
43
+ end
44
+
45
+ # The path to the directory of an existing installation, or nil
46
+ # @return [string]
47
+ def self.existing_installation
48
+ exe = self.existing_executable
49
+ return nil if exe.nil?
50
+ File.dirname(exe) # it's not really this
51
+ # but for this platform it doesn't really matter
52
+ end
53
+
54
+ # The executable Arduino file in an existing installation, or nil
55
+ # @return [string]
56
+ def self.existing_executable
57
+ if USE_BUILDER
58
+ # builder_name = "arduino-builder"
59
+ # cli_place = Host.which(builder_name)
60
+ # unless cli_place.nil?
61
+ # ret = ArduinoCmdLinuxBuilder.new
62
+ # ret.base_cmd = [cli_place]
63
+ # return ret
64
+ # end
65
+ end
66
+ Host.which("arduino")
67
+ end
68
+
69
+ # The executable Arduino file in a forced installation, or nil
70
+ # @return [string]
71
+ def self.force_installed_executable
72
+ if USE_BUILDER
73
+ # forced_builder = File.join(ArduinoCmdLinuxBuilder.force_install_location, builder_name)
74
+ # if File.exist?(forced_builder)
75
+ # ret = ArduinoCmdLinuxBuilder.new
76
+ # ret.base_cmd = [forced_builder]
77
+ # return ret
78
+ # end
79
+ end
80
+ forced_arduino = File.join(self.force_install_location, "arduino")
81
+ return forced_arduino if File.exist? forced_arduino
82
+ nil
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,79 @@
1
+ require "arduino_ci/arduino_downloader_posix"
2
+
3
+ USE_BUILDER = false
4
+
5
+ module ArduinoCI
6
+
7
+ # Manage the linux download & install of Arduino
8
+ class ArduinoDownloaderLinux < ArduinoDownloaderPosix
9
+
10
+ # The local filename of the desired IDE package (zip/tar/etc)
11
+ # @return [string]
12
+ def package_file
13
+ "#{extracted_file}-linux64.tar.xz"
14
+ end
15
+
16
+ # The technology that will be used to extract the download
17
+ # (for logging purposes)
18
+ # @return [string]
19
+ def extracter
20
+ "tar"
21
+ end
22
+
23
+ # Extract the package_file to extracted_file
24
+ # @return [bool] whether successful
25
+ def extract
26
+ system(extracter, "xf", package_file)
27
+ end
28
+
29
+ # The local file (dir) name of the extracted IDE package (zip/tar/etc)
30
+ # @return [string]
31
+ def extracted_file
32
+ "arduino-#{@desired_ide_version}"
33
+ end
34
+
35
+ <<<<<<< HEAD
36
+ =======
37
+ # The path to the directory of an existing installation, or nil
38
+ # @return [string]
39
+ def self.existing_installation
40
+ exe = self.existing_executable
41
+ return nil if exe.nil?
42
+ File.dirname(exe) # it's not really this
43
+ # but for this platform it doesn't really matter
44
+ end
45
+
46
+ >>>>>>> Refactor force_install code in preparation for windows CI
47
+ # The executable Arduino file in an existing installation, or nil
48
+ # @return [string]
49
+ def self.existing_executable
50
+ if USE_BUILDER
51
+ # builder_name = "arduino-builder"
52
+ # cli_place = Host.which(builder_name)
53
+ # unless cli_place.nil?
54
+ # ret = ArduinoCmdLinuxBuilder.new
55
+ # ret.base_cmd = [cli_place]
56
+ # return ret
57
+ # end
58
+ end
59
+ Host.which("arduino")
60
+ end
61
+
62
+ # The executable Arduino file in a forced installation, or nil
63
+ # @return [string]
64
+ def self.force_installed_executable
65
+ if USE_BUILDER
66
+ # forced_builder = File.join(ArduinoCmdLinuxBuilder.force_install_location, builder_name)
67
+ # if File.exist?(forced_builder)
68
+ # ret = ArduinoCmdLinuxBuilder.new
69
+ # ret.base_cmd = [forced_builder]
70
+ # return ret
71
+ # end
72
+ end
73
+ forced_arduino = File.join(self.force_install_location, "arduino")
74
+ return forced_arduino if File.exist? forced_arduino
75
+ nil
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,66 @@
1
+ require "arduino_ci/arduino_downloader"
2
+
3
+ module ArduinoCI
4
+
5
+ # Manage the OSX download & install of Arduino
6
+ class ArduinoDownloaderOSX < ArduinoDownloader
7
+
8
+ # The local filename of the desired IDE package (zip/tar/etc)
9
+ # @return [string]
10
+ def package_file
11
+ "arduino-#{@desired_ide_version}-macosx.zip"
12
+ end
13
+
14
+ # The local file (dir) name of the extracted IDE package (zip/tar/etc)
15
+ # @return [string]
16
+ def extracted_file
17
+ "Arduino.app"
18
+ end
19
+
20
+ # @return [String] The location where a forced install will go
21
+ def self.force_install_location
22
+ # include the .app extension
23
+ File.join(ENV['HOME'], 'Arduino.app')
24
+ end
25
+
26
+ # An existing Arduino directory in one of the given directories, or nil
27
+ # @param Array<string> a list of places to look
28
+ # @return [string]
29
+ def self.find_existing_arduino_dir(paths)
30
+ paths.each do |path|
31
+ return path if File.exist? path
32
+ end
33
+ nil
34
+ end
35
+
36
+ # An existing Arduino file in one of the given directories, or nil
37
+ # @param Array<string> a list of places to look for the executable
38
+ # @return [string]
39
+ def self.find_existing_arduino_exe(paths)
40
+ paths.each do |path|
41
+ exe = File.join(path, "MacOS", "Arduino")
42
+ return exe if File.exist? exe
43
+ end
44
+ nil
45
+ end
46
+
47
+ # The path to the directory of an existing installation, or nil
48
+ # @return [string]
49
+ def self.existing_installation
50
+ self.find_existing_arduino_dir(["/Applications/Arduino.app"])
51
+ end
52
+
53
+ # The executable Arduino file in an existing installation, or nil
54
+ # @return [string]
55
+ def self.existing_executable
56
+ self.find_existing_arduino_exe(["/Applications/Arduino.app"])
57
+ end
58
+
59
+ # The executable Arduino file in a forced installation, or nil
60
+ # @return [string]
61
+ def self.force_installed_executable
62
+ self.find_existing_arduino_exe([self.force_install_location])
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,88 @@
1
+ require "arduino_ci/arduino_downloader_posix"
2
+
3
+ module ArduinoCI
4
+
5
+ # Manage the OSX download & install of Arduino
6
+ class ArduinoDownloaderOSX < ArduinoDownloaderPosix
7
+
8
+ # The local filename of the desired IDE package (zip/tar/etc)
9
+ # @return [string]
10
+ def package_file
11
+ <<<<<<< HEAD
12
+ "#arduino-#{@desired_ide_version}-macosx.zip"
13
+ =======
14
+ "arduino-#{@desired_ide_version}-macosx.zip"
15
+ >>>>>>> Refactor force_install code in preparation for windows CI
16
+ end
17
+
18
+ # The technology that will be used to extract the download
19
+ # (for logging purposes)
20
+ # @return [string]
21
+ def extracter
22
+ "unzip"
23
+ end
24
+
25
+ # Extract the package_file to extracted_file
26
+ # @return [bool] whether successful
27
+ def extract
28
+ system(extracter, package_file)
29
+ end
30
+
31
+ # The local file (dir) name of the extracted IDE package (zip/tar/etc)
32
+ # @return [string]
33
+ def extracted_file
34
+ "Arduino.app"
35
+ end
36
+
37
+ <<<<<<< HEAD
38
+ # The an existing Arduino file in one of the given directories, or nil
39
+ =======
40
+ # An existing Arduino directory in one of the given directories, or nil
41
+ # @param Array<string> a list of places to look
42
+ # @return [string]
43
+ def self.find_existing_arduino_dir(paths)
44
+ paths.each do |path|
45
+ return path if File.exist? path
46
+ end
47
+ nil
48
+ end
49
+
50
+ # An existing Arduino file in one of the given directories, or nil
51
+ >>>>>>> Refactor force_install code in preparation for windows CI
52
+ # @param Array<string> a list of places to look for the executable
53
+ # @return [string]
54
+ def self.find_existing_arduino_exe(paths)
55
+ paths.each do |path|
56
+ <<<<<<< HEAD
57
+ exe = File.join(path, "Arduino")
58
+ =======
59
+ exe = File.join(path, "MacOS", "Arduino")
60
+ >>>>>>> Refactor force_install code in preparation for windows CI
61
+ return exe if File.exist? exe
62
+ end
63
+ nil
64
+ end
65
+
66
+ <<<<<<< HEAD
67
+ =======
68
+ # The path to the directory of an existing installation, or nil
69
+ # @return [string]
70
+ def self.existing_installation
71
+ self.find_existing_arduino_dir(["/Applications/Arduino.app/Contents"])
72
+ end
73
+
74
+ >>>>>>> Refactor force_install code in preparation for windows CI
75
+ # The executable Arduino file in an existing installation, or nil
76
+ # @return [string]
77
+ def self.existing_executable
78
+ self.find_existing_arduino_exe(["/Applications/Arduino.app/Contents"])
79
+ end
80
+
81
+ # The executable Arduino file in a forced installation, or nil
82
+ # @return [string]
83
+ def self.force_installed_executable
84
+ self.find_existing_arduino_exe([File.join(self.force_install_location, "Contents")])
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,101 @@
1
+ require 'base64'
2
+ require 'shellwords' # fingers crossed this works on win32
3
+ require 'win32/registry'
4
+ require "arduino_ci/arduino_downloader"
5
+ require "fileutils"
6
+
7
+ module ArduinoCI
8
+
9
+ # Manage the POSIX download & install of Arduino
10
+ class ArduinoDownloaderWindows < ArduinoDownloader
11
+
12
+ # Make any preparations or run any checks prior to making changes
13
+ # @return [string] Error message, or nil if success
14
+ def prepare
15
+ nil
16
+ end
17
+
18
+ # The technology that will be used to complete the download
19
+ # (for logging purposes)
20
+ # @return [string]
21
+ def downloader
22
+ "open-uri"
23
+ end
24
+
25
+ # Download the package_url to package_file
26
+ # @return [bool] whether successful
27
+ def download
28
+ # Turned off ssl verification
29
+ # This should be acceptable because it won't happen on a user's machine, just CI
30
+ open(URI.parse(package_url), ssl_verify_mode: 0) do |url|
31
+ File.open(package_file, 'wb') { |file| file.write(url.read) }
32
+ end
33
+ end
34
+
35
+ # Move the extracted package file from extracted_file to the force_install_location
36
+ # @return [bool] whether successful
37
+ def install
38
+ # Move only the content of the directory
39
+ FileUtils.mv extracted_file, self.class.force_install_location
40
+ end
41
+
42
+ # The local filename of the desired IDE package (zip/tar/etc)
43
+ # @return [string]
44
+ def package_file
45
+ "#{extracted_file}-windows.zip"
46
+ end
47
+
48
+ # The technology that will be used to extract the download
49
+ # (for logging purposes)
50
+ # @return [string]
51
+ def extracter
52
+ "Expand-Archive"
53
+ end
54
+
55
+ # Extract the package_file to extracted_file
56
+ # @return [bool] whether successful
57
+ def extract
58
+ Zip::File.open(package_file) do |zip|
59
+ zip.each do |file|
60
+ file.extract(file.name)
61
+ end
62
+ end
63
+ end
64
+
65
+ # The local file (dir) name of the extracted IDE package (zip/tar/etc)
66
+ # @return [string]
67
+ def extracted_file
68
+ "arduino-#{@desired_ide_version}"
69
+ end
70
+
71
+ # The path to the directory of an existing installation, or nil
72
+ # @return [string]
73
+ def self.existing_installation
74
+ exe = self.existing_executable
75
+ return nil if exe.nil?
76
+ File.dirname(exe)
77
+ end
78
+
79
+ # The executable Arduino file in an existing installation, or nil
80
+ # @return [string]
81
+ def self.existing_executable
82
+ arduino_reg = 'SOFTWARE\WOW6432Node\Arduino'
83
+ Win32::Registry::HKEY_LOCAL_MACHINE.open(arduino_reg) do |reg|
84
+ path = reg.read_s('Install_Dir')
85
+ exe = File.join(path, "arduino_debug.exe")
86
+ return exe if File.exist? exe
87
+ end
88
+ rescue
89
+ nil
90
+ end
91
+
92
+ # The executable Arduino file in a forced installation, or nil
93
+ # @return [string]
94
+ def self.force_installed_executable
95
+ exe = File.join(self.force_install_location, "arduino_debug.exe")
96
+ return nil if exe.nil?
97
+ exe
98
+ end
99
+
100
+ end
101
+ end