| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  | # typed: true | 
					
						
							|  |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 19:45:55 -07:00
										 |  |  | require "ipaddr" | 
					
						
							| 
									
										
										
										
											2023-01-13 14:40:03 +01:00
										 |  |  | require "extend/on_system" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  | module Homebrew | 
					
						
							|  |  |  |   # The {Service} class implements the DSL methods used in a formula's | 
					
						
							|  |  |  |   # `service` block and stores related instance variables. Most of these methods | 
					
						
							|  |  |  |   # also return the related instance variable when no argument is provided. | 
					
						
							|  |  |  |   class Service | 
					
						
							| 
									
										
										
										
											2021-04-08 10:06:45 +02:00
										 |  |  |     extend Forwardable | 
					
						
							| 
									
										
										
										
											2023-01-13 14:40:03 +01:00
										 |  |  |     include OnSystem::MacOSAndLinux | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |     RUN_TYPE_IMMEDIATE = :immediate | 
					
						
							|  |  |  |     RUN_TYPE_INTERVAL = :interval | 
					
						
							|  |  |  |     RUN_TYPE_CRON = :cron | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |     PROCESS_TYPE_BACKGROUND = :background | 
					
						
							|  |  |  |     PROCESS_TYPE_STANDARD = :standard | 
					
						
							|  |  |  |     PROCESS_TYPE_INTERACTIVE = :interactive | 
					
						
							|  |  |  |     PROCESS_TYPE_ADAPTIVE = :adaptive | 
					
						
							| 
									
										
										
										
											2021-09-08 21:54:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |     KEEP_ALIVE_KEYS = [:always, :successful_exit, :crashed, :path].freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |     # sig { params(formula: Formula).void } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:06:45 +02:00
										 |  |  |     def initialize(formula, &block) | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       @formula = formula | 
					
						
							|  |  |  |       @run_type = RUN_TYPE_IMMEDIATE | 
					
						
							| 
									
										
										
										
											2023-02-23 10:15:06 -08:00
										 |  |  |       @run_at_load = true | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       @environment_variables = {} | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |       instance_eval(&block) if block | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-16 08:35:33 +01:00
										 |  |  |     sig { returns(Formula) } | 
					
						
							|  |  |  |     def f | 
					
						
							|  |  |  |       @formula | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def default_plist_name | 
					
						
							|  |  |  |       "homebrew.mxcl.#{@formula.name}" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-13 12:35:50 -07:00
										 |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def plist_name | 
					
						
							|  |  |  |       @plist_name ||= default_plist_name | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def default_service_name | 
					
						
							|  |  |  |       "homebrew.#{@formula.name}" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-13 12:35:50 -07:00
										 |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def service_name | 
					
						
							|  |  |  |       @service_name ||= default_service_name | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(macos: T.nilable(String), linux: T.nilable(String)).void } | 
					
						
							|  |  |  |     def name(macos: nil, linux: nil) | 
					
						
							|  |  |  |       raise TypeError, "Service#name expects at least one String" if [macos, linux].none?(String) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @plist_name = macos if macos | 
					
						
							|  |  |  |       @service_name = linux if linux | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-13 14:40:03 +01:00
										 |  |  |     sig { | 
					
						
							|  |  |  |       params( | 
					
						
							| 
									
										
										
										
											2024-04-01 14:30:10 -04:00
										 |  |  |         command: T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)), | 
					
						
							|  |  |  |         macos:   T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)), | 
					
						
							|  |  |  |         linux:   T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)), | 
					
						
							|  |  |  |       ).returns(T.nilable(T::Array[T.any(String, Pathname)])) | 
					
						
							| 
									
										
										
										
											2023-01-13 14:40:03 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     def run(command = nil, macos: nil, linux: nil) | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  |       # Save parameters for serialization | 
					
						
							| 
									
										
										
										
											2023-03-31 17:18:06 -07:00
										 |  |  |       if command | 
					
						
							|  |  |  |         @run_params = command | 
					
						
							|  |  |  |       elsif macos || linux | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         @run_params = { macos:, linux: }.compact | 
					
						
							| 
									
										
										
										
											2023-03-31 17:18:06 -07:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |       command ||= on_system_conditional(macos:, linux:) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case command | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @run | 
					
						
							|  |  |  |       when String, Pathname | 
					
						
							|  |  |  |         @run = [command] | 
					
						
							|  |  |  |       when Array | 
					
						
							|  |  |  |         @run = command | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(path: T.nilable(T.any(String, Pathname))).returns(T.nilable(String)) } | 
					
						
							|  |  |  |     def working_dir(path = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case path | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @working_dir | 
					
						
							|  |  |  |       when String, Pathname | 
					
						
							|  |  |  |         @working_dir = path.to_s | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |     sig { params(path: T.nilable(T.any(String, Pathname))).returns(T.nilable(String)) } | 
					
						
							|  |  |  |     def root_dir(path = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case path | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @root_dir | 
					
						
							|  |  |  |       when String, Pathname | 
					
						
							|  |  |  |         @root_dir = path.to_s | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(path: T.nilable(T.any(String, Pathname))).returns(T.nilable(String)) } | 
					
						
							|  |  |  |     def input_path(path = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case path | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @input_path | 
					
						
							|  |  |  |       when String, Pathname | 
					
						
							|  |  |  |         @input_path = path.to_s | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |     sig { params(path: T.nilable(T.any(String, Pathname))).returns(T.nilable(String)) } | 
					
						
							|  |  |  |     def log_path(path = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case path | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @log_path | 
					
						
							|  |  |  |       when String, Pathname | 
					
						
							|  |  |  |         @log_path = path.to_s | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(path: T.nilable(T.any(String, Pathname))).returns(T.nilable(String)) } | 
					
						
							|  |  |  |     def error_log_path(path = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case path | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @error_log_path | 
					
						
							|  |  |  |       when String, Pathname | 
					
						
							|  |  |  |         @error_log_path = path.to_s | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |     sig { | 
					
						
							|  |  |  |       params(value: T.nilable(T.any(T::Boolean, T::Hash[Symbol, T.untyped]))) | 
					
						
							|  |  |  |         .returns(T.nilable(T::Hash[Symbol, T.untyped])) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |     def keep_alive(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @keep_alive | 
					
						
							|  |  |  |       when true, false | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |         @keep_alive = { always: value } | 
					
						
							|  |  |  |       when Hash | 
					
						
							| 
									
										
										
										
											2024-05-31 15:49:12 -07:00
										 |  |  |         unless (value.keys - KEEP_ALIVE_KEYS).empty? | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |           raise TypeError, "Service#keep_alive allows only #{KEEP_ALIVE_KEYS}" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |         @keep_alive = value | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-06 13:52:53 +01:00
										 |  |  |     sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) } | 
					
						
							|  |  |  |     def require_root(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2022-11-06 13:52:53 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @require_root | 
					
						
							|  |  |  |       when true, false | 
					
						
							|  |  |  |         @require_root = value | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Returns a `Boolean` describing if a service requires root access. | 
					
						
							|  |  |  |     # @return [Boolean] | 
					
						
							|  |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def requires_root? | 
					
						
							|  |  |  |       @require_root.present? && @require_root == true | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-13 23:19:34 -08:00
										 |  |  |     sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) } | 
					
						
							|  |  |  |     def run_at_load(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2023-02-14 04:24:26 -08:00
										 |  |  |       when nil | 
					
						
							| 
									
										
										
										
											2023-02-13 23:19:34 -08:00
										 |  |  |         @run_at_load | 
					
						
							| 
									
										
										
										
											2023-02-14 04:24:26 -08:00
										 |  |  |       when true, false | 
					
						
							|  |  |  |         @run_at_load = value | 
					
						
							| 
									
										
										
										
											2023-02-13 23:19:34 -08:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-18 22:18:42 +00:00
										 |  |  |     SOCKET_STRING_REGEX = %r{^([a-z]+)://(.+):([0-9]+)$}i | 
					
						
							| 
									
										
										
										
											2023-09-29 19:10:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     sig { | 
					
						
							|  |  |  |       params(value: T.nilable(T.any(String, T::Hash[Symbol, String]))) | 
					
						
							|  |  |  |         .returns(T.nilable(T::Hash[Symbol, T::Hash[Symbol, String]])) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |     def sockets(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-29 19:10:13 -07:00
										 |  |  |       return @sockets if value.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @sockets = case value | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |       when String | 
					
						
							| 
									
										
										
										
											2023-09-29 19:10:13 -07:00
										 |  |  |         { listeners: value } | 
					
						
							|  |  |  |       when Hash | 
					
						
							|  |  |  |         value | 
					
						
							|  |  |  |       end.transform_values do |socket_string| | 
					
						
							|  |  |  |         match = socket_string.match(SOCKET_STRING_REGEX) | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |         raise TypeError, "Service#sockets a formatted socket definition as <type>://<host>:<port>" if match.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         type, host, port = match.captures | 
					
						
							| 
									
										
										
										
											2023-09-29 19:45:55 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         begin | 
					
						
							|  |  |  |           IPAddr.new(host) | 
					
						
							|  |  |  |         rescue IPAddr::InvalidAddressError | 
					
						
							|  |  |  |           raise TypeError, "Service#sockets expects a valid ipv4 or ipv6 host address" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         { host:, port:, type: } | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-11 12:42:41 -08:00
										 |  |  |     # Returns a `Boolean` describing if a service is set to be kept alive. | 
					
						
							|  |  |  |     # @return [Boolean] | 
					
						
							|  |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def keep_alive? | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |       @keep_alive.present? && @keep_alive[:always] != false | 
					
						
							| 
									
										
										
										
											2022-03-11 12:42:41 -08:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-04 11:37:29 -06:00
										 |  |  |     sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) } | 
					
						
							|  |  |  |     def launch_only_once(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2022-02-04 11:37:29 -06:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @launch_only_once | 
					
						
							|  |  |  |       when true, false | 
					
						
							|  |  |  |         @launch_only_once = value | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |     sig { params(value: T.nilable(Integer)).returns(T.nilable(Integer)) } | 
					
						
							|  |  |  |     def restart_delay(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @restart_delay | 
					
						
							|  |  |  |       when Integer | 
					
						
							|  |  |  |         @restart_delay = value | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |     sig { params(value: T.nilable(Symbol)).returns(T.nilable(Symbol)) } | 
					
						
							|  |  |  |     def process_type(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2021-09-08 21:54:13 -07:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @process_type | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |       when :background, :standard, :interactive, :adaptive | 
					
						
							|  |  |  |         @process_type = value | 
					
						
							|  |  |  |       when Symbol | 
					
						
							| 
									
										
										
										
											2022-06-28 10:09:59 +01:00
										 |  |  |         raise TypeError, "Service#process_type allows: " \ | 
					
						
							|  |  |  |                          "'#{PROCESS_TYPE_BACKGROUND}'/'#{PROCESS_TYPE_STANDARD}'/" \ | 
					
						
							| 
									
										
										
										
											2021-09-08 21:54:13 -07:00
										 |  |  |                          "'#{PROCESS_TYPE_INTERACTIVE}'/'#{PROCESS_TYPE_ADAPTIVE}'" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |     sig { params(value: T.nilable(Symbol)).returns(T.nilable(Symbol)) } | 
					
						
							|  |  |  |     def run_type(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @run_type | 
					
						
							| 
									
										
										
										
											2021-11-21 14:25:40 +01:00
										 |  |  |       when :immediate, :interval, :cron | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |         @run_type = value | 
					
						
							|  |  |  |       when Symbol | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |         raise TypeError, "Service#run_type allows: '#{RUN_TYPE_IMMEDIATE}'/'#{RUN_TYPE_INTERVAL}'/'#{RUN_TYPE_CRON}'" | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(value: T.nilable(Integer)).returns(T.nilable(Integer)) } | 
					
						
							|  |  |  |     def interval(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @interval | 
					
						
							|  |  |  |       when Integer | 
					
						
							|  |  |  |         @interval = value | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 14:25:40 +01:00
										 |  |  |     sig { params(value: T.nilable(String)).returns(T.nilable(Hash)) } | 
					
						
							|  |  |  |     def cron(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2021-11-21 14:25:40 +01:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @cron | 
					
						
							|  |  |  |       when String | 
					
						
							|  |  |  |         @cron = parse_cron(T.must(value)) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { returns(T::Hash[Symbol, T.any(Integer, String)]) } | 
					
						
							|  |  |  |     def default_cron_values | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         Month:   "*", | 
					
						
							|  |  |  |         Day:     "*", | 
					
						
							|  |  |  |         Weekday: "*", | 
					
						
							|  |  |  |         Hour:    "*", | 
					
						
							|  |  |  |         Minute:  "*", | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(cron_statement: String).returns(T::Hash[Symbol, T.any(Integer, String)]) } | 
					
						
							|  |  |  |     def parse_cron(cron_statement) | 
					
						
							|  |  |  |       parsed = default_cron_values | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       case cron_statement | 
					
						
							|  |  |  |       when "@hourly" | 
					
						
							|  |  |  |         parsed[:Minute] = 0
 | 
					
						
							|  |  |  |       when "@daily" | 
					
						
							|  |  |  |         parsed[:Minute] = 0
 | 
					
						
							|  |  |  |         parsed[:Hour] = 0
 | 
					
						
							|  |  |  |       when "@weekly" | 
					
						
							|  |  |  |         parsed[:Minute] = 0
 | 
					
						
							|  |  |  |         parsed[:Hour] = 0
 | 
					
						
							|  |  |  |         parsed[:Weekday] = 0
 | 
					
						
							|  |  |  |       when "@monthly" | 
					
						
							|  |  |  |         parsed[:Minute] = 0
 | 
					
						
							|  |  |  |         parsed[:Hour] = 0
 | 
					
						
							|  |  |  |         parsed[:Day] = 1
 | 
					
						
							|  |  |  |       when "@yearly", "@annually" | 
					
						
							|  |  |  |         parsed[:Minute] = 0
 | 
					
						
							|  |  |  |         parsed[:Hour] = 0
 | 
					
						
							|  |  |  |         parsed[:Day] = 1
 | 
					
						
							|  |  |  |         parsed[:Month] = 1
 | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         cron_parts = cron_statement.split | 
					
						
							|  |  |  |         raise TypeError, "Service#parse_cron expects a valid cron syntax" if cron_parts.length != 5
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [:Minute, :Hour, :Day, :Month, :Weekday].each_with_index do |selector, index| | 
					
						
							|  |  |  |           parsed[selector] = Integer(cron_parts.fetch(index)) if cron_parts.fetch(index) != "*" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       parsed | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  |     sig { params(variables: T::Hash[Symbol, String]).returns(T.nilable(T::Hash[Symbol, String])) } | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |     def environment_variables(variables = {}) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case variables | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       when Hash | 
					
						
							| 
									
										
										
										
											2021-05-22 10:43:39 +02:00
										 |  |  |         @environment_variables = variables.transform_values(&:to_s) | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |     sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) } | 
					
						
							|  |  |  |     def macos_legacy_timers(value = nil) | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |       case value | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |       when nil | 
					
						
							|  |  |  |         @macos_legacy_timers | 
					
						
							|  |  |  |       when true, false | 
					
						
							|  |  |  |         @macos_legacy_timers = value | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 00:00:24 +05:30
										 |  |  |     delegate [:bin, :etc, :libexec, :opt_bin, :opt_libexec, :opt_pkgshare, :opt_prefix, :opt_sbin, :var] => :@formula | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def std_service_path_env | 
					
						
							|  |  |  |       "#{HOMEBREW_PREFIX}/bin:#{HOMEBREW_PREFIX}/sbin:/usr/bin:/bin:/usr/sbin:/sbin" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-13 14:40:03 +01:00
										 |  |  |     sig { returns(T.nilable(T::Array[String])) } | 
					
						
							| 
									
										
										
										
											2021-04-13 11:25:56 +02:00
										 |  |  |     def command | 
					
						
							| 
									
										
										
										
											2023-05-15 15:50:11 +02:00
										 |  |  |       @run&.map(&:to_s)&.map { |arg| arg.start_with?("~") ? File.expand_path(arg) : arg } | 
					
						
							| 
									
										
										
										
											2021-04-13 11:25:56 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def command? | 
					
						
							|  |  |  |       @run.present? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 15:14:50 +01:00
										 |  |  |     # Returns the `String` command to run manually instead of the service. | 
					
						
							|  |  |  |     # @return [String] | 
					
						
							| 
									
										
										
										
											2021-05-22 10:59:28 +02:00
										 |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def manual_command | 
					
						
							|  |  |  |       vars = @environment_variables.except(:PATH) | 
					
						
							|  |  |  |                                    .map { |k, v| "#{k}=\"#{v}\"" } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-16 11:18:26 +01:00
										 |  |  |       out = vars + T.must(command).map { |arg| Utils::Shell.sh_quote(arg) } if command? | 
					
						
							| 
									
										
										
										
											2021-05-22 10:59:28 +02:00
										 |  |  |       out.join(" ") | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 15:14:50 +01:00
										 |  |  |     # Returns a `Boolean` describing if a service is timed. | 
					
						
							|  |  |  |     # @return [Boolean] | 
					
						
							|  |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def timed? | 
					
						
							|  |  |  |       @run_type == RUN_TYPE_CRON || @run_type == RUN_TYPE_INTERVAL | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |     # Returns a `String` plist. | 
					
						
							|  |  |  |     # @return [String] | 
					
						
							|  |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def to_plist | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |       # command needs to be first because it initializes all other values | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       base = { | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |         Label:            plist_name, | 
					
						
							| 
									
										
										
										
											2021-04-29 09:43:39 +02:00
										 |  |  |         ProgramArguments: command, | 
					
						
							| 
									
										
										
										
											2023-02-23 10:15:06 -08:00
										 |  |  |         RunAtLoad:        @run_at_load == true, | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-04 11:42:25 -06:00
										 |  |  |       base[:LaunchOnlyOnce] = @launch_only_once if @launch_only_once == true | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |       base[:LegacyTimers] = @macos_legacy_timers if @macos_legacy_timers == true | 
					
						
							|  |  |  |       base[:TimeOut] = @restart_delay if @restart_delay.present? | 
					
						
							| 
									
										
										
										
											2021-11-02 17:17:45 +01:00
										 |  |  |       base[:ProcessType] = @process_type.to_s.capitalize if @process_type.present? | 
					
						
							|  |  |  |       base[:StartInterval] = @interval if @interval.present? && @run_type == RUN_TYPE_INTERVAL | 
					
						
							| 
									
										
										
										
											2023-05-15 15:16:26 +02:00
										 |  |  |       base[:WorkingDirectory] = File.expand_path(@working_dir) if @working_dir.present? | 
					
						
							|  |  |  |       base[:RootDirectory] = File.expand_path(@root_dir) if @root_dir.present? | 
					
						
							|  |  |  |       base[:StandardInPath] = File.expand_path(@input_path) if @input_path.present? | 
					
						
							|  |  |  |       base[:StandardOutPath] = File.expand_path(@log_path) if @log_path.present? | 
					
						
							|  |  |  |       base[:StandardErrorPath] = File.expand_path(@error_log_path) if @error_log_path.present? | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       base[:EnvironmentVariables] = @environment_variables unless @environment_variables.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |       if keep_alive? | 
					
						
							|  |  |  |         if (always = @keep_alive[:always].presence) | 
					
						
							|  |  |  |           base[:KeepAlive] = always | 
					
						
							|  |  |  |         elsif @keep_alive.key?(:successful_exit) | 
					
						
							|  |  |  |           base[:KeepAlive] = { SuccessfulExit: @keep_alive[:successful_exit] } | 
					
						
							|  |  |  |         elsif @keep_alive.key?(:crashed) | 
					
						
							|  |  |  |           base[:KeepAlive] = { Crashed: @keep_alive[:crashed] } | 
					
						
							|  |  |  |         elsif @keep_alive.key?(:path) && @keep_alive[:path].present? | 
					
						
							|  |  |  |           base[:KeepAlive] = { PathState: @keep_alive[:path].to_s } | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if @sockets.present? | 
					
						
							|  |  |  |         base[:Sockets] = {} | 
					
						
							| 
									
										
										
										
											2023-09-29 19:10:13 -07:00
										 |  |  |         @sockets.each do |name, info| | 
					
						
							|  |  |  |           base[:Sockets][name] = { | 
					
						
							|  |  |  |             SockNodeName:    info[:host], | 
					
						
							|  |  |  |             SockServiceName: info[:port], | 
					
						
							|  |  |  |             SockProtocol:    info[:type].upcase, | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 14:25:40 +01:00
										 |  |  |       if @cron.present? && @run_type == RUN_TYPE_CRON | 
					
						
							|  |  |  |         base[:StartCalendarInterval] = @cron.reject { |_, value| value == "*" } | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-03 16:24:05 +02:00
										 |  |  |       # Adding all session types has as the primary effect that if you initialise it through e.g. a Background session | 
					
						
							|  |  |  |       # and you later "physically" sign in to the owning account (Aqua session), things shouldn't flip out. | 
					
						
							|  |  |  |       # Also, we're not checking @process_type here because that is used to indicate process priority and not | 
					
						
							|  |  |  |       # necessarily if it should run in a specific session type. Like database services could run with ProcessType | 
					
						
							|  |  |  |       # Interactive so they have no resource limitations enforced upon them, but they aren't really interactive in the | 
					
						
							|  |  |  |       # general sense. | 
					
						
							|  |  |  |       base[:LimitLoadToSessionType] = %w[Aqua Background LoginWindow StandardIO System] | 
					
						
							| 
									
										
										
										
											2022-07-03 15:56:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |       base.to_plist | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-04-13 16:59:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Returns a `String` systemd unit. | 
					
						
							|  |  |  |     # @return [String] | 
					
						
							|  |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def to_systemd_unit | 
					
						
							|  |  |  |       unit = <<~EOS | 
					
						
							|  |  |  |         [Unit] | 
					
						
							|  |  |  |         Description=Homebrew generated unit for #{@formula.name} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 17:59:17 +02:00
										 |  |  |         [Install] | 
					
						
							| 
									
										
										
										
											2022-09-21 15:13:28 +02:00
										 |  |  |         WantedBy=default.target | 
					
						
							| 
									
										
										
										
											2021-06-05 17:59:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 16:59:59 +02:00
										 |  |  |         [Service] | 
					
						
							|  |  |  |       EOS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 13:59:24 -06:00
										 |  |  |       # command needs to be first because it initializes all other values | 
					
						
							| 
									
										
										
										
											2023-08-16 13:58:03 +01:00
										 |  |  |       cmd = command&.map { |arg| Utils::Shell.sh_quote(arg) } | 
					
						
							|  |  |  |                    &.join(" ") | 
					
						
							| 
									
										
										
										
											2022-02-11 13:59:24 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 16:59:59 +02:00
										 |  |  |       options = [] | 
					
						
							| 
									
										
										
										
											2022-08-10 14:19:33 +01:00
										 |  |  |       options << "Type=#{(@launch_only_once == true) ? "oneshot" : "simple"}" | 
					
						
							| 
									
										
										
										
											2022-02-11 13:59:24 -06:00
										 |  |  |       options << "ExecStart=#{cmd}" | 
					
						
							| 
									
										
										
										
											2022-01-25 19:29:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       options << "Restart=always" if @keep_alive.present? && @keep_alive[:always].present? | 
					
						
							| 
									
										
										
										
											2021-05-22 18:17:36 +02:00
										 |  |  |       options << "RestartSec=#{restart_delay}" if @restart_delay.present? | 
					
						
							| 
									
										
										
										
											2023-05-15 15:16:26 +02:00
										 |  |  |       options << "WorkingDirectory=#{File.expand_path(@working_dir)}" if @working_dir.present? | 
					
						
							|  |  |  |       options << "RootDirectory=#{File.expand_path(@root_dir)}" if @root_dir.present? | 
					
						
							|  |  |  |       options << "StandardInput=file:#{File.expand_path(@input_path)}" if @input_path.present? | 
					
						
							|  |  |  |       options << "StandardOutput=append:#{File.expand_path(@log_path)}" if @log_path.present? | 
					
						
							|  |  |  |       options << "StandardError=append:#{File.expand_path(@error_log_path)}" if @error_log_path.present? | 
					
						
							| 
									
										
										
										
											2021-05-25 11:46:18 +02:00
										 |  |  |       options += @environment_variables.map { |k, v| "Environment=\"#{k}=#{v}\"" } if @environment_variables.present? | 
					
						
							| 
									
										
										
										
											2021-04-13 16:59:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       unit + options.join("\n") | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-11-20 15:14:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Returns a `String` systemd unit timer. | 
					
						
							|  |  |  |     # @return [String] | 
					
						
							|  |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def to_systemd_timer | 
					
						
							|  |  |  |       timer = <<~EOS | 
					
						
							|  |  |  |         [Unit] | 
					
						
							|  |  |  |         Description=Homebrew generated timer for #{@formula.name} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [Install] | 
					
						
							|  |  |  |         WantedBy=timers.target | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [Timer] | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |         Unit=#{service_name} | 
					
						
							| 
									
										
										
										
											2021-11-20 15:14:50 +01:00
										 |  |  |       EOS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       options = [] | 
					
						
							| 
									
										
										
										
											2021-11-21 14:25:40 +01:00
										 |  |  |       options << "Persistent=true" if @run_type == RUN_TYPE_CRON | 
					
						
							| 
									
										
										
										
											2021-11-20 15:14:50 +01:00
										 |  |  |       options << "OnUnitActiveSec=#{@interval}" if @run_type == RUN_TYPE_INTERVAL | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 14:25:40 +01:00
										 |  |  |       if @run_type == RUN_TYPE_CRON | 
					
						
							| 
									
										
										
										
											2022-08-10 14:19:33 +01:00
										 |  |  |         minutes = (@cron[:Minute] == "*") ? "*" : format("%02d", @cron[:Minute]) | 
					
						
							|  |  |  |         hours   = (@cron[:Hour] == "*") ? "*" : format("%02d", @cron[:Hour]) | 
					
						
							| 
									
										
										
										
											2021-11-21 14:25:40 +01:00
										 |  |  |         options << "OnCalendar=#{@cron[:Weekday]}-*-#{@cron[:Month]}-#{@cron[:Day]} #{hours}:#{minutes}:00" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 15:14:50 +01:00
										 |  |  |       timer + options.join("\n") | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |     # Prepare the service hash for inclusion in the formula API JSON. | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  |     sig { returns(Hash) } | 
					
						
							| 
									
										
										
										
											2024-01-30 23:07:19 -08:00
										 |  |  |     def to_hash | 
					
						
							| 
									
										
										
										
											2023-05-13 12:35:50 -07:00
										 |  |  |       name_params = { | 
					
						
							|  |  |  |         macos: (plist_name if plist_name != default_plist_name), | 
					
						
							|  |  |  |         linux: (service_name if service_name != default_service_name), | 
					
						
							|  |  |  |       }.compact | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 14:34:35 +01:00
										 |  |  |       return { name: name_params }.compact_blank if @run_params.blank? | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       cron_string = if @cron.present? | 
					
						
							|  |  |  |         [:Minute, :Hour, :Day, :Month, :Weekday] | 
					
						
							|  |  |  |           .map { |key| @cron[key].to_s } | 
					
						
							|  |  |  |           .join(" ") | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 19:45:55 -07:00
										 |  |  |       sockets_var = if @sockets.present? | 
					
						
							|  |  |  |         @sockets.transform_values { |info| "#{info[:type]}://#{info[:host]}:#{info[:port]}" } | 
					
						
							|  |  |  |                 .then do |sockets_hash| | 
					
						
							|  |  |  |                   # TODO: Remove this code when all users are running on versions of Homebrew | 
					
						
							|  |  |  |                   # that can process sockets hashes (this commit or later). | 
					
						
							|  |  |  |                   if sockets_hash.size == 1 && sockets_hash.key?(:listeners) | 
					
						
							|  |  |  |                     # When original #sockets argument was a string: `sockets "tcp://127.0.0.1:80"` | 
					
						
							|  |  |  |                     sockets_hash.fetch(:listeners) | 
					
						
							|  |  |  |                   else | 
					
						
							|  |  |  |                     # When original #sockets argument was a hash: `sockets http: "tcp://0.0.0.0:80"` | 
					
						
							|  |  |  |                     sockets_hash | 
					
						
							|  |  |  |                   end | 
					
						
							|  |  |  |                 end | 
					
						
							| 
									
										
										
										
											2023-09-29 19:10:13 -07:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2023-05-13 12:35:50 -07:00
										 |  |  |         name:                  name_params.presence, | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |         run:                   @run_params, | 
					
						
							|  |  |  |         run_type:              @run_type, | 
					
						
							|  |  |  |         interval:              @interval, | 
					
						
							|  |  |  |         cron:                  cron_string, | 
					
						
							|  |  |  |         keep_alive:            @keep_alive, | 
					
						
							|  |  |  |         launch_only_once:      @launch_only_once, | 
					
						
							|  |  |  |         require_root:          @require_root, | 
					
						
							|  |  |  |         environment_variables: @environment_variables.presence, | 
					
						
							|  |  |  |         working_dir:           @working_dir, | 
					
						
							|  |  |  |         root_dir:              @root_dir, | 
					
						
							|  |  |  |         input_path:            @input_path, | 
					
						
							|  |  |  |         log_path:              @log_path, | 
					
						
							|  |  |  |         error_log_path:        @error_log_path, | 
					
						
							|  |  |  |         restart_delay:         @restart_delay, | 
					
						
							|  |  |  |         process_type:          @process_type, | 
					
						
							|  |  |  |         macos_legacy_timers:   @macos_legacy_timers, | 
					
						
							| 
									
										
										
										
											2023-09-29 19:45:55 -07:00
										 |  |  |         sockets:               sockets_var, | 
					
						
							| 
									
										
										
										
											2023-03-17 23:24:37 -07:00
										 |  |  |       }.compact | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Turn the service API hash values back into what is expected by the formula DSL. | 
					
						
							|  |  |  |     sig { params(api_hash: Hash).returns(Hash) } | 
					
						
							| 
									
										
										
										
											2024-01-30 23:07:19 -08:00
										 |  |  |     def self.from_hash(api_hash) | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |       hash = {} | 
					
						
							| 
									
										
										
										
											2023-05-13 12:35:50 -07:00
										 |  |  |       hash[:name] = api_hash["name"].transform_keys(&:to_sym) if api_hash.key?("name") | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       # The service hash might not have a "run" command if it only documents | 
					
						
							| 
									
										
										
										
											2023-05-13 12:35:50 -07:00
										 |  |  |       # an existing service file with the "name" command. | 
					
						
							| 
									
										
										
										
											2023-04-13 23:33:31 -07:00
										 |  |  |       return hash unless api_hash.key?("run") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |       hash[:run] = | 
					
						
							|  |  |  |         case api_hash["run"] | 
					
						
							| 
									
										
										
										
											2023-03-31 17:18:06 -07:00
										 |  |  |         when String | 
					
						
							|  |  |  |           replace_placeholders(api_hash["run"]) | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |         when Array | 
					
						
							| 
									
										
										
										
											2024-04-08 09:47:06 -07:00
										 |  |  |           api_hash["run"].map { replace_placeholders(_1) } | 
					
						
							| 
									
										
										
										
											2023-03-31 17:18:06 -07:00
										 |  |  |         when Hash | 
					
						
							|  |  |  |           api_hash["run"].to_h do |key, elem| | 
					
						
							|  |  |  |             run_cmd = if elem.is_a?(Array) | 
					
						
							| 
									
										
										
										
											2024-04-08 09:47:06 -07:00
										 |  |  |               elem.map { replace_placeholders(_1) } | 
					
						
							| 
									
										
										
										
											2023-03-31 17:18:06 -07:00
										 |  |  |             else | 
					
						
							|  |  |  |               replace_placeholders(elem) | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             [key.to_sym, run_cmd] | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2023-04-03 08:41:21 +01:00
										 |  |  |           raise ArgumentError, "Unexpected run command: #{api_hash["run"]}" | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if api_hash.key?("environment_variables") | 
					
						
							|  |  |  |         hash[:environment_variables] = api_hash["environment_variables"].to_h do |key, value| | 
					
						
							|  |  |  |           [key.to_sym, replace_placeholders(value)] | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       %w[run_type process_type].each do |key| | 
					
						
							|  |  |  |         next unless (value = api_hash[key]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         hash[key.to_sym] = value.to_sym | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       %w[working_dir root_dir input_path log_path error_log_path].each do |key| | 
					
						
							|  |  |  |         next unless (value = api_hash[key]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         hash[key.to_sym] = replace_placeholders(value) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 19:10:13 -07:00
										 |  |  |       %w[interval cron launch_only_once require_root restart_delay macos_legacy_timers].each do |key| | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |         next if (value = api_hash[key]).nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         hash[key.to_sym] = value | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 19:10:13 -07:00
										 |  |  |       %w[sockets keep_alive].each do |key| | 
					
						
							|  |  |  |         next unless (value = api_hash[key]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         hash[key.to_sym] = if value.is_a?(Hash) | 
					
						
							|  |  |  |           value.transform_keys(&:to_sym) | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           value | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |       hash | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Replace API path placeholders with local paths. | 
					
						
							|  |  |  |     sig { params(string: String).returns(String) } | 
					
						
							|  |  |  |     def self.replace_placeholders(string) | 
					
						
							|  |  |  |       string.gsub(HOMEBREW_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX) | 
					
						
							| 
									
										
										
										
											2023-07-18 10:59:27 +01:00
										 |  |  |             .gsub(HOMEBREW_CELLAR_PLACEHOLDER, HOMEBREW_CELLAR) | 
					
						
							| 
									
										
										
										
											2023-03-21 21:53:52 -07:00
										 |  |  |             .gsub(HOMEBREW_HOME_PLACEHOLDER, Dir.home) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-12-11 23:14:50 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | end |