| 
									
										
										
										
											2024-08-12 10:30:59 +01:00
										 |  |  |  | # typed: true # rubocop:todo Sorbet/StrictSigil | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  | require "downloadable" | 
					
						
							| 
									
										
										
										
											2018-07-13 14:42:49 +01:00
										 |  |  |  | require "mktemp" | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  | require "livecheck" | 
					
						
							| 
									
										
										
										
											2022-06-23 17:18:58 -04:00
										 |  |  |  | require "extend/on_system" | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  | # Resource is the fundamental representation of an external resource. The | 
					
						
							|  |  |  |  | # primary formula download, along with other declared resources, are instances | 
					
						
							|  |  |  |  | # of this class. | 
					
						
							| 
									
										
										
										
											2024-07-14 21:03:08 -04:00
										 |  |  |  | class Resource | 
					
						
							|  |  |  |  |   include Downloadable | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  |  |   include FileUtils | 
					
						
							| 
									
										
										
										
											2022-06-29 17:48:21 -04:00
										 |  |  |  |   include OnSystem::MacOSAndLinux | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |   attr_reader :source_modified_time, :patches, :owner | 
					
						
							|  |  |  |  |   attr_writer :checksum | 
					
						
							|  |  |  |  |   attr_accessor :download_strategy | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  |   # Formula name must be set after the DSL, as we have no access to the | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |  |   # formula name before initialization of the formula. | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |   attr_accessor :name | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-25 08:36:56 -07:00
										 |  |  |  |   sig { params(name: T.nilable(String), block: T.nilable(T.proc.bind(Resource).void)).void } | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |  |   def initialize(name = nil, &block) | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     super() | 
					
						
							| 
									
										
										
										
											2022-08-24 23:53:35 +01:00
										 |  |  |  |     # Ensure this is synced with `initialize_dup` and `freeze` (excluding simple objects like integers and booleans) | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  |  |     @name = name | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |     @patches = [] | 
					
						
							| 
									
										
										
										
											2022-08-24 23:53:35 +01:00
										 |  |  |  |     @livecheck = Livecheck.new(self) | 
					
						
							| 
									
										
											  
											
												livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
											
										 
											2024-11-27 18:20:56 -05:00
										 |  |  |  |     @livecheck_defined = false | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     @insecure = false | 
					
						
							| 
									
										
										
										
											2020-11-16 22:18:56 +01:00
										 |  |  |  |     instance_eval(&block) if block | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 23:53:35 +01:00
										 |  |  |  |   def initialize_dup(other) | 
					
						
							|  |  |  |  |     super | 
					
						
							|  |  |  |  |     @name = @name.dup | 
					
						
							|  |  |  |  |     @patches = @patches.dup | 
					
						
							|  |  |  |  |     @livecheck = @livecheck.dup | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   def freeze | 
					
						
							|  |  |  |  |     @name.freeze | 
					
						
							|  |  |  |  |     @patches.freeze | 
					
						
							|  |  |  |  |     @livecheck.freeze | 
					
						
							|  |  |  |  |     super | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |   def owner=(owner) | 
					
						
							|  |  |  |  |     @owner = owner | 
					
						
							|  |  |  |  |     patches.each { |p| p.owner = owner } | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |  |   # Removes /s from resource names; this allows Go package names | 
					
						
							| 
									
										
										
										
											2014-06-02 21:53:53 -07:00
										 |  |  |  |   # to be used as resource names without confusing software that | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |  |   # interacts with {download_name}, e.g. `github.com/foo/bar`. | 
					
						
							| 
									
										
										
										
											2014-06-02 21:53:53 -07:00
										 |  |  |  |   def escaped_name | 
					
						
							| 
									
										
										
										
											2015-08-06 15:45:52 +08:00
										 |  |  |  |     name.tr("/", "-") | 
					
						
							| 
									
										
										
										
											2014-06-02 21:53:53 -07:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:40 -05:00
										 |  |  |  |   def download_name | 
					
						
							| 
									
										
										
										
											2018-08-01 05:33:03 +02:00
										 |  |  |  |     return owner.name if name.nil? | 
					
						
							|  |  |  |  |     return escaped_name if owner.nil? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-01 05:33:03 +02:00
										 |  |  |  |     "#{owner.name}--#{escaped_name}" | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:40 -05:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |  |   # Verifies download and unpacks it. | 
					
						
							| 
									
										
										
										
											2020-08-19 06:58:36 +02:00
										 |  |  |  |   # The block may call `|resource, staging| staging.retain!` to retain the staging | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |  |   # directory. Subclasses that override stage should implement the tmp | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |  |   # dir using {Mktemp} so that works with all subtypes. | 
					
						
							| 
									
										
										
										
											2020-08-19 06:58:36 +02:00
										 |  |  |  |   # | 
					
						
							|  |  |  |  |   # @api public | 
					
						
							| 
									
										
										
										
											2022-07-31 19:59:25 +01:00
										 |  |  |  |   def stage(target = nil, debug_symbols: false, &block) | 
					
						
							| 
									
										
										
										
											2023-02-10 23:15:40 -05:00
										 |  |  |  |     raise ArgumentError, "Target directory or block is required" if !target && block.blank? | 
					
						
							| 
									
										
										
										
											2014-12-13 22:51:21 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-13 11:49:17 +01:00
										 |  |  |  |     prepare_patches | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  |  |     fetch_patches(skip_downloaded: true) | 
					
						
							|  |  |  |  |     fetch unless downloaded? | 
					
						
							| 
									
										
										
										
											2020-03-04 17:48:17 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |  |     unpack(target, debug_symbols:, &block) | 
					
						
							| 
									
										
										
										
											2013-10-30 00:43:10 -05:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-13 11:49:17 +01:00
										 |  |  |  |   def prepare_patches | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |     patches.grep(DATAPatch) { |p| p.path = owner.owner.path } | 
					
						
							| 
									
										
										
										
											2020-05-13 11:49:17 +01:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  |  |   def fetch_patches(skip_downloaded: false) | 
					
						
							| 
									
										
										
										
											2020-05-14 09:20:58 +01:00
										 |  |  |  |     external_patches = patches.select(&:external?) | 
					
						
							|  |  |  |  |     external_patches.reject!(&:downloaded?) if skip_downloaded | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  |  |     external_patches.each(&:fetch) | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   def apply_patches | 
					
						
							|  |  |  |  |     return if patches.empty? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |     ohai "Patching #{name}" | 
					
						
							|  |  |  |  |     patches.each(&:apply) | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |  |   # If a target is given, unpack there; else unpack to a temp folder. | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |  |   # If block is given, yield to that block with `|stage|`, where stage | 
					
						
							|  |  |  |  |   # is a {ResourceStageContext}. | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |  |   # A target or a block must be given, but not both. | 
					
						
							| 
									
										
										
										
											2022-07-31 19:59:25 +01:00
										 |  |  |  |   def unpack(target = nil, debug_symbols: false) | 
					
						
							| 
									
										
										
										
											2022-07-10 01:27:21 +08:00
										 |  |  |  |     current_working_directory = Pathname.pwd | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |  |     stage_resource(download_name, debug_symbols:) do |staging| | 
					
						
							| 
									
										
										
										
											2021-02-12 11:10:18 -05:00
										 |  |  |  |       downloader.stage do | 
					
						
							|  |  |  |  |         @source_modified_time = downloader.source_modified_time | 
					
						
							|  |  |  |  |         apply_patches | 
					
						
							|  |  |  |  |         if block_given? | 
					
						
							|  |  |  |  |           yield ResourceStageContext.new(self, staging) | 
					
						
							|  |  |  |  |         elsif target | 
					
						
							|  |  |  |  |           target = Pathname(target) | 
					
						
							| 
									
										
										
										
											2022-07-10 01:27:21 +08:00
										 |  |  |  |           target = current_working_directory/target if target.relative? | 
					
						
							| 
									
										
										
										
											2021-02-12 11:10:18 -05:00
										 |  |  |  |           target.install Pathname.pwd.children | 
					
						
							|  |  |  |  |         end | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  |  |       end | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:43 -05:00
										 |  |  |  |   Partial = Struct.new(:resource, :files) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   def files(*files) | 
					
						
							|  |  |  |  |     Partial.new(self, files) | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-14 11:42:22 -04:00
										 |  |  |  |   sig { | 
					
						
							|  |  |  |  |     override | 
					
						
							|  |  |  |  |       .params( | 
					
						
							|  |  |  |  |         verify_download_integrity: T::Boolean, | 
					
						
							|  |  |  |  |         timeout:                   T.nilable(T.any(Integer, Float)), | 
					
						
							|  |  |  |  |         quiet:                     T::Boolean, | 
					
						
							|  |  |  |  |       ).returns(Pathname) | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   def fetch(verify_download_integrity: true, timeout: nil, quiet: false) | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  |  |     fetch_patches | 
					
						
							| 
									
										
										
										
											2020-05-12 12:37:54 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-23 17:08:41 +01:00
										 |  |  |  |     super | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  |   # {Livecheck} can be used to check for newer versions of the software. | 
					
						
							| 
									
										
										
										
											2024-12-02 10:06:14 -05:00
										 |  |  |  |   # This method evaluates the DSL specified in the `livecheck` block of the | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  |   # {Resource} (if it exists) and sets the instance variables of a {Livecheck} | 
					
						
							|  |  |  |  |   # object accordingly. This is used by `brew livecheck` to check for newer | 
					
						
							|  |  |  |  |   # versions of the software. | 
					
						
							|  |  |  |  |   # | 
					
						
							| 
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 |  |  |  |   # ### Example | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   # ```ruby | 
					
						
							|  |  |  |  |   # livecheck do | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  |   #   url "https://example.com/foo/releases" | 
					
						
							|  |  |  |  |   #   regex /foo-(\d+(?:\.\d+)+)\.tar/ | 
					
						
							| 
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 |  |  |  |   # end | 
					
						
							|  |  |  |  |   # ``` | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   # @!attribute [w] livecheck | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  |   def livecheck(&block) | 
					
						
							|  |  |  |  |     return @livecheck unless block | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
											
										 
											2024-11-27 18:20:56 -05:00
										 |  |  |  |     @livecheck_defined = true | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  |     @livecheck.instance_eval(&block) | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   # Whether a livecheck specification is defined or not. | 
					
						
							| 
									
										
											  
											
												livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
											
										 
											2024-11-27 18:20:56 -05:00
										 |  |  |  |   # | 
					
						
							|  |  |  |  |   # It returns `true` when a `livecheck` block is present in the {Resource} | 
					
						
							|  |  |  |  |   # and `false` otherwise. | 
					
						
							|  |  |  |  |   sig { returns(T::Boolean) } | 
					
						
							|  |  |  |  |   def livecheck_defined? | 
					
						
							|  |  |  |  |     @livecheck_defined == true | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   # Whether a livecheck specification is defined or not. This is a legacy alias | 
					
						
							|  |  |  |  |   # for `#livecheck_defined?`. | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   # It returns `true` when a `livecheck` block is present in the {Resource} | 
					
						
							|  |  |  |  |   # and `false` otherwise. | 
					
						
							|  |  |  |  |   sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  |   def livecheckable? | 
					
						
							| 
									
										
											  
											
												livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
											
										 
											2024-11-27 18:20:56 -05:00
										 |  |  |  |     # odeprecated "`livecheckable?`", "`livecheck_defined?`" | 
					
						
							|  |  |  |  |     @livecheck_defined == true | 
					
						
							| 
									
										
										
										
											2022-06-30 16:08:13 +02:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-07 08:33:57 +01:00
										 |  |  |  |   def sha256(val) | 
					
						
							|  |  |  |  |     @checksum = Checksum.new(val) | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-02 10:29:40 +02:00
										 |  |  |  |   def url(val = nil, **specs) | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     return @url&.to_s if val.nil? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 14:21:03 +01:00
										 |  |  |  |     specs = specs.dup | 
					
						
							|  |  |  |  |     # Don't allow this to be set. | 
					
						
							|  |  |  |  |     specs.delete(:insecure) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     specs[:insecure] = true if @insecure | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     @url = URL.new(val, specs) | 
					
						
							| 
									
										
										
										
											2021-04-15 18:06:54 +01:00
										 |  |  |  |     @downloader = nil | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     @download_strategy = @url.download_strategy | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-14 22:51:54 -04:00
										 |  |  |  |   sig { override.params(val: T.nilable(T.any(String, Version))).returns(T.nilable(Version)) } | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |  |   def version(val = nil) | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     return super() if val.nil? | 
					
						
							| 
									
										
										
										
											2022-09-01 18:25:26 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-01 19:37:32 +01:00
										 |  |  |  |     @version = case val | 
					
						
							| 
									
										
										
										
											2023-05-01 07:59:36 +02:00
										 |  |  |  |     when String | 
					
						
							|  |  |  |  |       val.blank? ? Version::NULL : Version.new(val) | 
					
						
							|  |  |  |  |     when Version | 
					
						
							|  |  |  |  |       val | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |  |   def mirror(val) | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  |     mirrors << val | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |   def patch(strip = :p1, src = nil, &block) | 
					
						
							| 
									
										
										
										
											2024-07-14 11:42:22 -04:00
										 |  |  |  |     p = ::Patch.create(strip, src, &block) | 
					
						
							| 
									
										
										
										
											2018-01-21 08:29:38 -08:00
										 |  |  |  |     patches << p | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |   def using | 
					
						
							|  |  |  |  |     @url&.using | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   def specs | 
					
						
							|  |  |  |  |     @url&.specs || {}.freeze | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 18:13:23 +01:00
										 |  |  |  |   protected | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-31 19:59:25 +01:00
										 |  |  |  |   def stage_resource(prefix, debug_symbols: false, &block) | 
					
						
							| 
									
										
										
										
											2022-08-01 18:30:14 -07:00
										 |  |  |  |     Mktemp.new(prefix, retain_in_cache: debug_symbols).run(&block) | 
					
						
							| 
									
										
										
										
											2018-07-14 18:13:23 +01:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 21:25:38 -05:00
										 |  |  |  |   private | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 01:50:44 +08:00
										 |  |  |  |   def determine_url_mirrors | 
					
						
							|  |  |  |  |     extra_urls = [] | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     # glibc-bootstrap | 
					
						
							|  |  |  |  |     if url.start_with?("https://github.com/Homebrew/glibc-bootstrap/releases/download") | 
					
						
							| 
									
										
										
										
											2023-03-13 02:40:03 +01:00
										 |  |  |  |       if (artifact_domain = Homebrew::EnvConfig.artifact_domain.presence) | 
					
						
							| 
									
										
										
										
											2024-05-14 16:03:35 +09:00
										 |  |  |  |         artifact_url = url.sub("https://github.com", artifact_domain) | 
					
						
							|  |  |  |  |         return [artifact_url] if Homebrew::EnvConfig.artifact_domain_no_fallback? | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         extra_urls << artifact_url | 
					
						
							| 
									
										
										
										
											2022-09-16 01:50:44 +08:00
										 |  |  |  |       end | 
					
						
							| 
									
										
										
										
											2024-05-14 16:03:35 +09:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 01:50:44 +08:00
										 |  |  |  |       if Homebrew::EnvConfig.bottle_domain != HOMEBREW_BOTTLE_DEFAULT_DOMAIN | 
					
						
							|  |  |  |  |         tag, filename = url.split("/").last(2) | 
					
						
							|  |  |  |  |         extra_urls << "#{Homebrew::EnvConfig.bottle_domain}/glibc-bootstrap/#{tag}/#{filename}" | 
					
						
							|  |  |  |  |       end | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 01:57:19 +08:00
										 |  |  |  |     # PyPI packages: PEP 503 – Simple Repository API <https://peps.python.org/pep-0503> | 
					
						
							| 
									
										
										
										
											2023-03-13 02:38:03 +01:00
										 |  |  |  |     if (pip_index_url = Homebrew::EnvConfig.pip_index_url.presence) | 
					
						
							|  |  |  |  |       pip_index_base_url = pip_index_url.chomp("/").chomp("/simple") | 
					
						
							| 
									
										
										
										
											2022-09-16 01:57:19 +08:00
										 |  |  |  |       %w[https://files.pythonhosted.org https://pypi.org].each do |base_url| | 
					
						
							|  |  |  |  |         extra_urls << url.sub(base_url, pip_index_base_url) if url.start_with?("#{base_url}/packages") | 
					
						
							|  |  |  |  |       end | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 00:22:13 +01:00
										 |  |  |  |     [*extra_urls, *super].uniq | 
					
						
							| 
									
										
										
										
											2022-09-16 01:50:44 +08:00
										 |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-14 21:59:04 +02:00
										 |  |  |  |   # A local resource that doesn't need to be downloaded. | 
					
						
							|  |  |  |  |   class Local < Resource | 
					
						
							|  |  |  |  |     def initialize(path) | 
					
						
							|  |  |  |  |       super(File.basename(path)) | 
					
						
							| 
									
										
										
										
											2024-09-04 23:12:58 +02:00
										 |  |  |  |       @downloader = LocalBottleDownloadStrategy.new(path) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:59:04 +02:00
										 |  |  |  |     end | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-14 11:42:22 -04:00
										 |  |  |  |   # A resource for a formula. | 
					
						
							|  |  |  |  |   class Formula < Resource | 
					
						
							|  |  |  |  |     sig { override.returns(String) } | 
					
						
							|  |  |  |  |     def name | 
					
						
							|  |  |  |  |       T.must(owner).name | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     sig { override.returns(String) } | 
					
						
							|  |  |  |  |     def download_name | 
					
						
							|  |  |  |  |       name | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 06:58:36 +02:00
										 |  |  |  |   # A resource containing a Go package. | 
					
						
							| 
									
										
										
										
											2014-06-02 23:32:42 -07:00
										 |  |  |  |   class Go < Resource | 
					
						
							| 
									
										
										
										
											2020-11-24 15:46:47 +01:00
										 |  |  |  |     def stage(target, &block) | 
					
						
							|  |  |  |  |       super(target/name, &block) | 
					
						
							| 
									
										
										
										
											2014-06-02 23:32:42 -07:00
										 |  |  |  |     end | 
					
						
							|  |  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-01-25 08:21:57 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  |   # A resource for a bottle manifest. | 
					
						
							|  |  |  |  |   class BottleManifest < Resource | 
					
						
							| 
									
										
										
										
											2024-07-13 16:50:53 -04:00
										 |  |  |  |     class Error < RuntimeError; end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  |     attr_reader :bottle | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def initialize(bottle) | 
					
						
							|  |  |  |  |       super("#{bottle.name}_bottle_manifest") | 
					
						
							|  |  |  |  |       @bottle = bottle | 
					
						
							| 
									
										
										
										
											2024-08-26 16:59:37 -04:00
										 |  |  |  |       @manifest_annotations = nil | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def verify_download_integrity(_filename) | 
					
						
							| 
									
										
										
										
											2024-07-13 16:50:53 -04:00
										 |  |  |  |       # We don't have a checksum, but we can at least try parsing it. | 
					
						
							|  |  |  |  |       tab | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def tab | 
					
						
							| 
									
										
										
										
											2024-08-26 16:59:37 -04:00
										 |  |  |  |       tab = manifest_annotations["sh.brew.tab"] | 
					
						
							|  |  |  |  |       raise Error, "Couldn't find tab from manifest." if tab.blank? | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       begin | 
					
						
							|  |  |  |  |         JSON.parse(tab) | 
					
						
							|  |  |  |  |       rescue JSON::ParserError | 
					
						
							|  |  |  |  |         raise Error, "Couldn't parse tab JSON." | 
					
						
							|  |  |  |  |       end | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     sig { returns(T.nilable(Integer)) } | 
					
						
							|  |  |  |  |     def bottle_size | 
					
						
							|  |  |  |  |       manifest_annotations["sh.brew.bottle.size"]&.to_i | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     sig { returns(T.nilable(Integer)) } | 
					
						
							|  |  |  |  |     def installed_size | 
					
						
							|  |  |  |  |       manifest_annotations["sh.brew.bottle.installed_size"]&.to_i | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     private | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def manifest_annotations | 
					
						
							|  |  |  |  |       return @manifest_annotations unless @manifest_annotations.nil? | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  |       json = begin | 
					
						
							|  |  |  |  |         JSON.parse(cached_download.read) | 
					
						
							|  |  |  |  |       rescue JSON::ParserError | 
					
						
							| 
									
										
										
										
											2024-07-13 16:50:53 -04:00
										 |  |  |  |         raise Error, "The downloaded GitHub Packages manifest was corrupted or modified (it is not valid JSON): " \ | 
					
						
							|  |  |  |  |                      "\n#{cached_download}" | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  |       end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       manifests = json["manifests"] | 
					
						
							| 
									
										
										
										
											2024-07-13 16:50:53 -04:00
										 |  |  |  |       raise Error, "Missing 'manifests' section." if manifests.blank? | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       manifests_annotations = manifests.filter_map { |m| m["annotations"] } | 
					
						
							| 
									
										
										
										
											2024-07-13 16:50:53 -04:00
										 |  |  |  |       raise Error, "Missing 'annotations' section." if manifests_annotations.blank? | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       bottle_digest = bottle.resource.checksum.hexdigest | 
					
						
							|  |  |  |  |       image_ref = GitHubPackages.version_rebuild(bottle.resource.version, bottle.rebuild, bottle.tag.to_s) | 
					
						
							|  |  |  |  |       manifest_annotations = manifests_annotations.find do |m| | 
					
						
							|  |  |  |  |         next if m["sh.brew.bottle.digest"] != bottle_digest | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         m["org.opencontainers.image.ref.name"] == image_ref | 
					
						
							|  |  |  |  |       end | 
					
						
							| 
									
										
										
										
											2024-07-13 16:50:53 -04:00
										 |  |  |  |       raise Error, "Couldn't find manifest matching bottle checksum." if manifest_annotations.blank? | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-26 16:59:37 -04:00
										 |  |  |  |       @manifest_annotations = manifest_annotations | 
					
						
							| 
									
										
										
										
											2024-07-13 16:28:21 -04:00
										 |  |  |  |     end | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 06:58:36 +02:00
										 |  |  |  |   # A resource containing a patch. | 
					
						
							| 
									
										
										
										
											2024-07-14 11:42:22 -04:00
										 |  |  |  |   class Patch < Resource | 
					
						
							| 
									
										
										
										
											2016-01-25 08:21:57 -08:00
										 |  |  |  |     attr_reader :patch_files | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def initialize(&block) | 
					
						
							|  |  |  |  |       @patch_files = [] | 
					
						
							| 
									
										
										
										
											2020-03-08 18:33:04 +00:00
										 |  |  |  |       @directory = nil | 
					
						
							| 
									
										
										
										
											2016-01-25 08:21:57 -08:00
										 |  |  |  |       super "patch", &block | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def apply(*paths) | 
					
						
							|  |  |  |  |       paths.flatten! | 
					
						
							|  |  |  |  |       @patch_files.concat(paths) | 
					
						
							|  |  |  |  |       @patch_files.uniq! | 
					
						
							|  |  |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-03-08 18:33:04 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |     def directory(val = nil) | 
					
						
							|  |  |  |  |       return @directory if val.nil? | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       @directory = val | 
					
						
							|  |  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-01-25 08:21:57 -08:00
										 |  |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-08-06 19:52:58 -07:00
										 |  |  |  | end | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |  | # The context in which a {Resource#stage} occurs. Supports access to both | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |  | # the {Resource} and associated {Mktemp} in a single block argument. The interface | 
					
						
							|  |  |  |  | # is back-compatible with {Resource} itself as used in that context. | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  |  | class ResourceStageContext | 
					
						
							|  |  |  |  |   extend Forwardable | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |  |   # The {Resource} that is being staged. | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  |  |   attr_reader :resource | 
					
						
							| 
									
										
										
										
											2024-04-26 14:04:55 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |  |   # The {Mktemp} in which {#resource} is staged. | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  |  |   attr_reader :staging | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   def_delegators :@resource, :version, :url, :mirrors, :specs, :using, :source_modified_time | 
					
						
							|  |  |  |  |   def_delegators :@staging, :retain! | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   def initialize(resource, staging) | 
					
						
							|  |  |  |  |     @resource = resource | 
					
						
							|  |  |  |  |     @staging = staging | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |  |   sig { returns(String) } | 
					
						
							| 
									
										
										
										
											2016-04-22 16:54:09 -04:00
										 |  |  |  |   def to_s | 
					
						
							|  |  |  |  |     "<#{self.class}: resource=#{resource} staging=#{staging}>" | 
					
						
							|  |  |  |  |   end | 
					
						
							|  |  |  |  | end |