1
1
require 'fileutils'
2
2
require 'arduino_ci/display_manager'
3
- require 'arduino_ci/arduino_installation'
4
3
5
4
module ArduinoCI
6
5
7
6
# Wrap the Arduino executable. This requires, in some cases, a faked display.
8
7
class ArduinoCmd
9
8
10
- class << self
11
- protected :new
12
-
13
- # @return [ArduinoCmd] A command object with a best guess (or nil) for the installation
14
- def autolocate
15
- new ( ArduinoInstallation . autolocate )
16
- end
17
-
18
- # @return [ArduinoCmd] A command object, installing Arduino if necessary
19
- def autolocate!
20
- new ( ArduinoInstallation . autolocate! )
21
- end
22
-
9
+ # Enable a shortcut syntax for command line flags
10
+ # @param name [String] What the flag will be called (prefixed with 'flag_')
11
+ # @return [void]
12
+ # @macro [attach] flag
13
+ # @!attribute [r] flag_$1
14
+ # @return String $2 the text of the command line flag
15
+ def self . flag ( name , text = nil )
16
+ text = "(flag #{ name } not defined)" if text . nil?
17
+ self . class_eval ( "def flag_#{ name } ;\" #{ text } \" ;end" )
23
18
end
24
19
25
20
attr_accessor :installation
26
- attr_reader :prefs_response_time
21
+ attr_accessor :base_cmd
22
+
27
23
attr_reader :library_is_indexed
28
24
29
- # @param installation [ArduinoInstallation] the location of the Arduino program installation
30
- def initialize ( installation )
31
- @display_mgr = DisplayManager ::instance
32
- @installation = installation
33
- @prefs_response_time = nil
25
+ # set the command line flags (undefined for now).
26
+ # These vary between gui/cli
27
+ flag :get_pref
28
+ flag :set_pref
29
+ flag :save_prefs
30
+ flag :use_board
31
+ flag :install_boards
32
+ flag :install_library
33
+ flag :verify
34
+
35
+ def initialize
34
36
@prefs_cache = nil
35
37
@library_is_indexed = false
36
38
end
37
39
38
- def _parse_pref_string ( arduino_output )
40
+ def parse_pref_string ( arduino_output )
39
41
lines = arduino_output . split ( "\n " ) . select { |l | l . include? "=" }
40
42
ret = lines . each_with_object ( { } ) do |e , acc |
41
43
parts = e . split ( "=" , 2 )
@@ -45,26 +47,21 @@ def _parse_pref_string(arduino_output)
45
47
ret
46
48
end
47
49
48
- # fetch preferences to a hash
49
- def _prefs
50
- resp = nil
51
- if @installation . requires_x
52
- @display_mgr . with_display do
53
- start = Time . now
54
- resp = run_and_capture ( "--get-pref" )
55
- @prefs_response_time = Time . now - start
56
- end
57
- else
58
- start = Time . now
59
- resp = run_and_capture ( "--get-pref" )
60
- @prefs_response_time = Time . now - start
61
- end
50
+ def _lib_dir
51
+ "<lib dir not defined>"
52
+ end
53
+
54
+ # fetch preferences to a string
55
+ def _prefs_raw
56
+ resp = run_and_capture ( flag_get_pref )
62
57
return nil unless resp [ :success ]
63
- _parse_pref_string ( resp [ :out ] )
58
+ resp [ :out ]
64
59
end
65
60
66
61
def prefs
67
- @prefs_cache = _prefs if @prefs_cache . nil?
62
+ prefs_raw = _prefs_raw if @prefs_cache . nil?
63
+ return nil if prefs_raw . nil?
64
+ @prefs_cache = parse_pref_string ( prefs_raw )
68
65
@prefs_cache . clone
69
66
end
70
67
@@ -74,42 +71,25 @@ def get_pref(key)
74
71
data [ key ]
75
72
end
76
73
77
- # set a preference key/value pair
74
+ # underlying preference-setter.
75
+ # @return [bool] whether the command succeeded
76
+ def _set_pref ( key , value )
77
+ run_and_capture ( flag_set_pref , "#{ key } =#{ value } " , flag_save_prefs ) [ :success ]
78
+ end
79
+
80
+ # set a preference key/value pair, and update the cache.
78
81
# @param key [String] the preference key
79
82
# @param value [String] the preference value
80
83
# @return [bool] whether the command succeeded
81
84
def set_pref ( key , value )
82
- success = run_with_gui_guess ( " about preferences" , "--pref" , " #{ key } = #{ value } " , "--save-prefs" )
85
+ success = _set_pref ( key , value )
83
86
@prefs_cache [ key ] = value if success
84
87
success
85
88
end
86
89
87
90
# run the arduino command
88
91
def run ( *args , **kwargs )
89
- full_args = @installation . base_cmd + args
90
- if @installation . requires_x
91
- @display_mgr . run ( *full_args , **kwargs )
92
- else
93
- Host . run ( *full_args , **kwargs )
94
- end
95
- end
96
-
97
- def run_with_gui_guess ( message , *args , **kwargs )
98
- # On Travis CI, we get an error message in the GUI instead of on STDERR
99
- # so, assume that if we don't get a rapid reply that things are not installed
100
-
101
- # if we don't need X, we can skip this whole thing
102
- return run_and_capture ( *args , **kwargs ) [ :success ] unless @installation . requires_x
103
-
104
- prefs if @prefs_response_time . nil?
105
- x3 = @prefs_response_time * 3
106
- Timeout . timeout ( x3 ) do
107
- result = run_and_capture ( *args , **kwargs )
108
- result [ :success ]
109
- end
110
- rescue Timeout ::Error
111
- puts "No response in #{ x3 } seconds. Assuming graphical modal error message#{ message } ."
112
- false
92
+ raise "Ian needs to implement this in a subclass #{ args } #{ kwargs } "
113
93
end
114
94
115
95
# run a command and capture its output
@@ -140,30 +120,29 @@ def run_wrap(*args, **kwargs)
140
120
# we do this by just selecting a board.
141
121
# the arduino binary will error if unrecognized and do a successful no-op if it's installed
142
122
def board_installed? ( boardname )
143
- run_with_gui_guess ( " about board not installed" , "--board" , boardname )
123
+ run_and_capture ( flag_use_board , boardname ) [ :success ]
144
124
end
145
125
146
126
# install a board by name
147
127
# @param name [String] the board name
148
128
# @return [bool] whether the command succeeded
149
129
def install_board ( boardname )
150
130
# TODO: find out why IO.pipe fails but File::NULL succeeds :(
151
- run_and_capture ( "--install-boards" , boardname , out : File ::NULL ) [ :success ]
131
+ run_and_capture ( flag_install_boards , boardname , out : File ::NULL ) [ :success ]
152
132
end
153
133
154
134
# install a library by name
155
135
# @param name [String] the library name
156
136
# @return [bool] whether the command succeeded
157
137
def install_library ( library_name )
158
- result = run_and_capture ( "--install-library" , library_name )
138
+ result = run_and_capture ( flag_install_library , library_name )
159
139
@library_is_indexed = true if result [ :success ]
160
140
result [ :success ]
161
141
end
162
142
163
143
# generate the (very likely) path of a library given its name
164
144
def library_path ( library_name )
165
- sketchbook = get_pref ( "sketchbook.path" )
166
- File . join ( sketchbook , library_name )
145
+ File . join ( @lib_dir , library_name )
167
146
end
168
147
169
148
# update the library index
@@ -175,7 +154,7 @@ def update_library_index
175
154
176
155
# use a particular board for compilation
177
156
def use_board ( boardname )
178
- run_with_gui_guess ( " about board not installed" , "--board" , boardname , "--save-prefs" )
157
+ run_and_capture ( flag_use_board , boardname , flag_save_prefs ) [ :success ]
179
158
end
180
159
181
160
# use a particular board for compilation, installing it if necessary
@@ -197,25 +176,25 @@ def verify_sketch(path)
197
176
puts "Can't verify nonexistent Sketch at '#{ path } '!"
198
177
return false
199
178
end
200
- run ( "--verify" , path , err : :out )
179
+ run ( flag_verify , path , err : :out )
201
180
end
202
181
203
182
# ensure that the given library is installed, or symlinked as appropriate
204
183
# return the path of the prepared library, or nil
205
- def install_local_library ( library_path )
206
- library_name = File . basename ( library_path )
207
- destination_path = File . join ( @installation . lib_dir , library_name )
184
+ def install_local_library ( path )
185
+ library_name = File . basename ( path )
186
+ destination_path = library_path ( library_name )
208
187
209
188
# things get weird if the sketchbook contains the library.
210
189
# check that first
211
190
if File . exist? destination_path
212
191
uhoh = "There is already a library '#{ library_name } ' in the library directory"
213
- return destination_path if destination_path == library_path
192
+ return destination_path if destination_path == path
214
193
215
194
# maybe it's a symlink? that would be OK
216
195
if File . symlink? ( destination_path )
217
- return destination_path if File . readlink ( destination_path ) == library_path
218
- puts "#{ uhoh } and it's not symlinked to #{ library_path } "
196
+ return destination_path if File . readlink ( destination_path ) == path
197
+ puts "#{ uhoh } and it's not symlinked to #{ path } "
219
198
return nil
220
199
end
221
200
@@ -224,7 +203,7 @@ def install_local_library(library_path)
224
203
end
225
204
226
205
# install the library
227
- FileUtils . ln_s ( library_path , destination_path )
206
+ FileUtils . ln_s ( path , destination_path )
228
207
destination_path
229
208
end
230
209
0 commit comments