1
- # typed: true # rubocop:todo Sorbet/StrictSigil
1
+ # typed: strict
2
2
# frozen_string_literal: true
3
3
4
4
require "ipaddr"
@@ -23,13 +23,38 @@ class Service
23
23
PROCESS_TYPE_ADAPTIVE = :adaptive
24
24
25
25
KEEP_ALIVE_KEYS = [ :always , :successful_exit , :crashed , :path ] . freeze
26
+ SOCKET_STRING_REGEX = %r{^([a-z]+)://(.+):([0-9]+)$}i
27
+
28
+ RunParam = T . type_alias { T . nilable ( T . any ( T ::Array [ T . any ( String , Pathname ) ] , String , Pathname ) ) }
29
+ Sockets = T . type_alias { T ::Hash [ Symbol , { host : String , port : String , type : String } ] }
26
30
27
- # sig { params(formula: Formula).void }
31
+ sig { returns ( String ) }
32
+ attr_reader :plist_name , :service_name
33
+
34
+ sig { params ( formula : Formula , block : T . nilable ( T . proc . void ) ) . void }
28
35
def initialize ( formula , &block )
36
+ @cron = T . let ( { } , T ::Hash [ Symbol , T . any ( Integer , String ) ] )
37
+ @environment_variables = T . let ( { } , T ::Hash [ Symbol , String ] )
38
+ @error_log_path = T . let ( nil , T . nilable ( String ) )
29
39
@formula = formula
30
- @run_type = RUN_TYPE_IMMEDIATE
31
- @run_at_load = true
32
- @environment_variables = { }
40
+ @input_path = T . let ( nil , T . nilable ( String ) )
41
+ @interval = T . let ( nil , T . nilable ( Integer ) )
42
+ @keep_alive = T . let ( { } , T ::Hash [ Symbol , T . untyped ] )
43
+ @launch_only_once = T . let ( false , T ::Boolean )
44
+ @log_path = T . let ( nil , T . nilable ( String ) )
45
+ @macos_legacy_timers = T . let ( false , T ::Boolean )
46
+ @plist_name = T . let ( default_plist_name , String )
47
+ @process_type = T . let ( nil , T . nilable ( Symbol ) )
48
+ @require_root = T . let ( false , T ::Boolean )
49
+ @restart_delay = T . let ( nil , T . nilable ( Integer ) )
50
+ @root_dir = T . let ( nil , T . nilable ( String ) )
51
+ @run = T . let ( [ ] , T ::Array [ String ] )
52
+ @run_at_load = T . let ( true , T ::Boolean )
53
+ @run_params = T . let ( nil , T . any ( RunParam , T ::Hash [ Symbol , RunParam ] ) )
54
+ @run_type = T . let ( RUN_TYPE_IMMEDIATE , Symbol )
55
+ @service_name = T . let ( default_service_name , String )
56
+ @sockets = T . let ( { } , Sockets )
57
+ @working_dir = T . let ( nil , T . nilable ( String ) )
33
58
instance_eval ( &block ) if block
34
59
end
35
60
@@ -43,21 +68,11 @@ def default_plist_name
43
68
"homebrew.mxcl.#{ @formula . name } "
44
69
end
45
70
46
- sig { returns ( String ) }
47
- def plist_name
48
- @plist_name ||= default_plist_name
49
- end
50
-
51
71
sig { returns ( String ) }
52
72
def default_service_name
53
73
"homebrew.#{ @formula . name } "
54
74
end
55
75
56
- sig { returns ( String ) }
57
- def service_name
58
- @service_name ||= default_service_name
59
- end
60
-
61
76
sig { params ( macos : T . nilable ( String ) , linux : T . nilable ( String ) ) . void }
62
77
def name ( macos : nil , linux : nil )
63
78
raise TypeError , "Service#name expects at least one String" if [ macos , linux ] . none? ( String )
@@ -68,27 +83,27 @@ def name(macos: nil, linux: nil)
68
83
69
84
sig {
70
85
params (
71
- command : T . nilable ( T . any ( T :: Array [ T . any ( String , Pathname ) ] , String , Pathname ) ) ,
72
- macos : T . nilable ( T . any ( T :: Array [ T . any ( String , Pathname ) ] , String , Pathname ) ) ,
73
- linux : T . nilable ( T . any ( T :: Array [ T . any ( String , Pathname ) ] , String , Pathname ) ) ,
86
+ command : T . nilable ( RunParam ) ,
87
+ macos : T . nilable ( RunParam ) ,
88
+ linux : T . nilable ( RunParam ) ,
74
89
) . returns ( T . nilable ( T ::Array [ T . any ( String , Pathname ) ] ) )
75
90
}
76
91
def run ( command = nil , macos : nil , linux : nil )
77
92
# Save parameters for serialization
78
93
if command
79
94
@run_params = command
80
95
elsif macos || linux
81
- @run_params = { macos :, linux : } . compact
96
+ @run_params = { macos :, linux : } . compact , T . any ( RunParam , T :: Hash [ Symbol , RunParam ] )
82
97
end
83
98
84
99
command ||= on_system_conditional ( macos :, linux :)
85
100
case command
86
101
when nil
87
102
@run
88
103
when String , Pathname
89
- @run = [ command ]
104
+ @run = [ command . to_s ]
90
105
when Array
91
- @run = command
106
+ @run = command . map ( & :to_s )
92
107
end
93
108
end
94
109
@@ -161,12 +176,12 @@ def keep_alive(value = nil)
161
176
end
162
177
end
163
178
164
- sig { params ( value : T . nilable ( T ::Boolean ) ) . returns ( T . nilable ( T ::Boolean ) ) }
179
+ sig { params ( value : T . nilable ( T ::Boolean ) ) . returns ( T ::Boolean ) }
165
180
def require_root ( value = nil )
166
181
case value
167
182
when nil
168
183
@require_root
169
- when true , false
184
+ when TrueClass , FalseClass
170
185
@require_root = value
171
186
end
172
187
end
@@ -183,16 +198,14 @@ def run_at_load(value = nil)
183
198
case value
184
199
when nil
185
200
@run_at_load
186
- when true , false
201
+ when TrueClass , FalseClass
187
202
@run_at_load = value
188
203
end
189
204
end
190
205
191
- SOCKET_STRING_REGEX = %r{^([a-z]+)://(.+):([0-9]+)$}i
192
-
193
206
sig {
194
207
params ( value : T . nilable ( T . any ( String , T ::Hash [ Symbol , String ] ) ) )
195
- . returns ( T . nilable ( T ::Hash [ Symbol , T ::Hash [ Symbol , String ] ] ) )
208
+ . returns ( T ::Hash [ Symbol , T ::Hash [ Symbol , String ] ] )
196
209
}
197
210
def sockets ( value = nil )
198
211
return @sockets if value . nil?
@@ -204,9 +217,11 @@ def sockets(value = nil)
204
217
value
205
218
end . transform_values do |socket_string |
206
219
match = socket_string . match ( SOCKET_STRING_REGEX )
207
- raise TypeError , "Service#sockets a formatted socket definition as <type>://<host>:<port>" if match . blank?
220
+ raise TypeError , "Service#sockets a formatted socket definition as <type>://<host>:<port>" unless match
208
221
209
- type , host , port = match . captures
222
+ type = T . must ( match [ 1 ] )
223
+ host = T . must ( match [ 2 ] )
224
+ port = T . must ( match [ 3 ] )
210
225
211
226
begin
212
227
IPAddr . new ( host )
@@ -222,15 +237,15 @@ def sockets(value = nil)
222
237
# @return [Boolean]
223
238
sig { returns ( T ::Boolean ) }
224
239
def keep_alive?
225
- @keep_alive . present ? && @keep_alive [ :always ] != false
240
+ ! @keep_alive . empty ? && @keep_alive [ :always ] != false
226
241
end
227
242
228
- sig { params ( value : T . nilable ( T ::Boolean ) ) . returns ( T . nilable ( T ::Boolean ) ) }
243
+ sig { params ( value : T . nilable ( T ::Boolean ) ) . returns ( T ::Boolean ) }
229
244
def launch_only_once ( value = nil )
230
245
case value
231
246
when nil
232
247
@launch_only_once
233
- when true , false
248
+ when TrueClass , FalseClass
234
249
@launch_only_once = value
235
250
end
236
251
end
@@ -281,13 +296,13 @@ def interval(value = nil)
281
296
end
282
297
end
283
298
284
- sig { params ( value : T . nilable ( String ) ) . returns ( T . nilable ( Hash ) ) }
299
+ sig { params ( value : T . nilable ( String ) ) . returns ( T :: Hash [ Symbol , T . any ( Integer , String ) ] ) }
285
300
def cron ( value = nil )
286
301
case value
287
302
when nil
288
303
@cron
289
304
when String
290
- @cron = parse_cron ( T . must ( value ) )
305
+ @cron = parse_cron ( value )
291
306
end
292
307
end
293
308
@@ -345,12 +360,12 @@ def environment_variables(variables = {})
345
360
end
346
361
end
347
362
348
- sig { params ( value : T . nilable ( T ::Boolean ) ) . returns ( T . nilable ( T ::Boolean ) ) }
363
+ sig { params ( value : T . nilable ( T ::Boolean ) ) . returns ( T ::Boolean ) }
349
364
def macos_legacy_timers ( value = nil )
350
365
case value
351
366
when nil
352
367
@macos_legacy_timers
353
- when true , false
368
+ when TrueClass , FalseClass
354
369
@macos_legacy_timers = value
355
370
end
356
371
end
@@ -362,14 +377,14 @@ def std_service_path_env
362
377
"#{ HOMEBREW_PREFIX } /bin:#{ HOMEBREW_PREFIX } /sbin:/usr/bin:/bin:/usr/sbin:/sbin"
363
378
end
364
379
365
- sig { returns ( T . nilable ( T ::Array [ String ] ) ) }
380
+ sig { returns ( T ::Array [ String ] ) }
366
381
def command
367
- @run & .map ( &:to_s ) & .map { |arg | arg . start_with? ( "~" ) ? File . expand_path ( arg ) : arg }
382
+ @run . map ( &:to_s ) . map { |arg | arg . start_with? ( "~" ) ? File . expand_path ( arg ) : arg }
368
383
end
369
384
370
385
sig { returns ( T ::Boolean ) }
371
386
def command?
372
- @run . present ?
387
+ ! @run . empty ?
373
388
end
374
389
375
390
# Returns the `String` command to run manually instead of the service.
@@ -379,8 +394,8 @@ def manual_command
379
394
vars = @environment_variables . except ( :PATH )
380
395
. map { |k , v | "#{ k } =\" #{ v } \" " }
381
396
382
- out = vars + T . must ( command ) . map { |arg | Utils ::Shell . sh_quote ( arg ) } if command?
383
- out . join ( " " )
397
+ vars . concat ( command . map { |arg | Utils ::Shell . sh_quote ( arg ) } )
398
+ vars . join ( " " )
384
399
end
385
400
386
401
# Returns a `Boolean` describing if a service is timed.
@@ -425,7 +440,7 @@ def to_plist
425
440
end
426
441
end
427
442
428
- if @sockets . present ?
443
+ unless @sockets . empty ?
429
444
base [ :Sockets ] = { }
430
445
@sockets . each do |name , info |
431
446
base [ :Sockets ] [ name ] = {
@@ -436,7 +451,7 @@ def to_plist
436
451
end
437
452
end
438
453
439
- if @cron . present ? && @run_type == RUN_TYPE_CRON
454
+ if ! @cron . empty ? && @run_type == RUN_TYPE_CRON
440
455
base [ :StartCalendarInterval ] = @cron . reject { |_ , value | value == "*" }
441
456
end
442
457
@@ -456,8 +471,8 @@ def to_plist
456
471
sig { returns ( String ) }
457
472
def to_systemd_unit
458
473
# command needs to be first because it initializes all other values
459
- cmd = command & .map { |arg | Utils ::Service . systemd_quote ( arg ) }
460
- & .join ( " " )
474
+ cmd = command . map { |arg | Utils ::Service . systemd_quote ( arg ) }
475
+ . join ( " " )
461
476
462
477
options = [ ]
463
478
options << "Type=#{ ( @launch_only_once == true ) ? "oneshot" : "simple" } "
@@ -512,7 +527,7 @@ def to_systemd_timer
512
527
end
513
528
514
529
# Prepare the service hash for inclusion in the formula API JSON.
515
- sig { returns ( Hash ) }
530
+ sig { returns ( T :: Hash [ Symbol , T . untyped ] ) }
516
531
def to_hash
517
532
name_params = {
518
533
macos : ( plist_name if plist_name != default_plist_name ) ,
@@ -521,13 +536,13 @@ def to_hash
521
536
522
537
return { name : name_params } . compact_blank if @run_params . blank?
523
538
524
- cron_string = if @cron . present ?
539
+ cron_string = unless @cron . empty ?
525
540
[ :Minute , :Hour , :Day , :Month , :Weekday ]
526
541
. map { |key | @cron [ key ] . to_s }
527
542
. join ( " " )
528
543
end
529
544
530
- sockets_var = if @sockets . present ?
545
+ sockets_var = unless @sockets . empty ?
531
546
@sockets . transform_values { |info | "#{ info [ :type ] } ://#{ info [ :host ] } :#{ info [ :port ] } " }
532
547
. then do |sockets_hash |
533
548
# TODO: Remove this code when all users are running on versions of Homebrew
@@ -565,7 +580,7 @@ def to_hash
565
580
end
566
581
567
582
# Turn the service API hash values back into what is expected by the formula DSL.
568
- sig { params ( api_hash : Hash ) . returns ( Hash ) }
583
+ sig { params ( api_hash : T :: Hash [ String , T . untyped ] ) . returns ( T :: Hash [ Symbol , T . untyped ] ) }
569
584
def self . from_hash ( api_hash )
570
585
hash = { }
571
586
hash [ :name ] = api_hash [ "name" ] . transform_keys ( &:to_sym ) if api_hash . key? ( "name" )
0 commit comments