arduino_ci 0.1.9 → 0.1.10

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