| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: true | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-03 07:24:35 -07:00
										 |  |  | # Cleans a newly installed keg. | 
					
						
							|  |  |  | # By default: | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # * removes `.la` files | 
					
						
							| 
									
										
										
										
											2023-12-18 15:23:14 +09:00
										 |  |  | # * removes `.tbd` files | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  | # * removes `perllocal.pod` files | 
					
						
							|  |  |  | # * removes `.packlist` files | 
					
						
							| 
									
										
										
										
											2012-07-03 07:24:35 -07:00
										 |  |  | # * removes empty directories | 
					
						
							|  |  |  | # * sets permissions on executables | 
					
						
							| 
									
										
										
										
											2014-02-23 21:18:09 -08:00
										 |  |  | # * removes unresolved symlinks | 
					
						
							| 
									
										
										
										
											2010-08-21 11:06:02 -07:00
										 |  |  | class Cleaner | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  |   include Context | 
					
						
							| 
									
										
										
										
											2020-08-02 03:01:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |   # Create a cleaner for the given formula. | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |   sig { params(formula: Formula).void } | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |   def initialize(formula) | 
					
						
							|  |  |  |     @formula = formula | 
					
						
							| 
									
										
										
										
											2014-02-23 11:07:37 -08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |   # Clean the keg of the formula. | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |   sig { void } | 
					
						
							| 
									
										
										
										
											2014-02-23 11:07:37 -08:00
										 |  |  |   def clean | 
					
						
							|  |  |  |     ObserverPathnameExtension.reset_counts! | 
					
						
							| 
									
										
										
										
											2014-02-23 17:39:01 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |     # Many formulae include `lib/charset.alias`, but it is not strictly needed | 
					
						
							|  |  |  |     # and will conflict if more than one formula provides it. | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |     observe_file_removal @formula.lib/"charset.alias" | 
					
						
							| 
									
										
										
										
											2014-02-23 17:39:01 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |     [@formula.bin, @formula.sbin, @formula.lib].each { |dir| clean_dir(dir) if dir.exist? } | 
					
						
							| 
									
										
										
										
											2010-08-21 11:23:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |     # Get rid of any info `dir` files, so they don't conflict at the link stage. | 
					
						
							| 
									
										
										
										
											2022-04-28 10:19:16 -04:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |     # The `dir` files come in at least 3 locations: | 
					
						
							| 
									
										
										
										
											2022-04-28 10:19:16 -04:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |     # 1. `info/dir` | 
					
						
							|  |  |  |     # 2. `info/#{name}/dir` | 
					
						
							|  |  |  |     # 3. `info/#{arch}/dir` | 
					
						
							| 
									
										
										
										
											2022-04-28 10:19:16 -04:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |     # Of these 3 only `info/#{name}/dir` is safe to keep since the rest will | 
					
						
							| 
									
										
										
										
											2022-04-28 10:19:16 -04:00
										 |  |  |     # conflict with other formulae because they use a shared location. | 
					
						
							|  |  |  |     # | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |     # See | 
					
						
							|  |  |  |     # [cleaner: recursively delete info `dir`s][1], | 
					
						
							|  |  |  |     # [emacs 28.1 bottle does not contain `dir` file][2] and | 
					
						
							|  |  |  |     # [Keep `info/#{f.name}/dir` files in cleaner][3] | 
					
						
							|  |  |  |     # for more info. | 
					
						
							| 
									
										
										
										
											2022-04-28 10:19:16 -04:00
										 |  |  |     # | 
					
						
							|  |  |  |     # [1]: https://github.com/Homebrew/brew/pull/11597 | 
					
						
							|  |  |  |     # [2]: https://github.com/Homebrew/homebrew-core/issues/100190 | 
					
						
							|  |  |  |     # [3]: https://github.com/Homebrew/brew/pull/13215 | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |     @formula.info.glob("**/dir").each do |info_dir_file| | 
					
						
							| 
									
										
										
										
											2022-04-28 00:15:29 -04:00
										 |  |  |       next unless info_dir_file.file? | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |       next if info_dir_file == @formula.info/@formula.name/"dir" | 
					
						
							|  |  |  |       next if @formula.skip_clean?(info_dir_file) | 
					
						
							| 
									
										
										
										
											2022-04-28 00:09:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-28 00:15:29 -04:00
										 |  |  |       observe_file_removal info_dir_file | 
					
						
							| 
									
										
										
										
											2021-06-25 13:10:43 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:49:47 +01:00
										 |  |  |     rewrite_shebangs | 
					
						
							| 
									
										
										
										
											2024-03-08 13:23:25 -05:00
										 |  |  |     clean_python_metadata | 
					
						
							| 
									
										
										
										
											2021-04-29 17:49:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-21 23:28:04 -06:00
										 |  |  |     prune | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |   sig { params(path: Pathname).void } | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def observe_file_removal(path) | 
					
						
							| 
									
										
										
										
											2014-07-20 09:54:51 -07:00
										 |  |  |     path.extend(ObserverPathnameExtension).unlink if path.exist? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-23 21:18:09 -08:00
										 |  |  |   # Removes any empty directories in the formula's prefix subtree | 
					
						
							| 
									
										
										
										
											2019-04-08 10:33:49 -07:00
										 |  |  |   # Keeps any empty directories protected by skip_clean | 
					
						
							| 
									
										
										
										
											2014-07-20 09:57:33 -07:00
										 |  |  |   # Removes any unresolved symlinks | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |   sig { void } | 
					
						
							| 
									
										
										
										
											2013-12-21 23:28:04 -06:00
										 |  |  |   def prune | 
					
						
							|  |  |  |     dirs = [] | 
					
						
							|  |  |  |     symlinks = [] | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |     @formula.prefix.find do |path| | 
					
						
							|  |  |  |       if path == @formula.libexec || @formula.skip_clean?(path) | 
					
						
							| 
									
										
										
										
											2013-12-21 23:28:04 -06:00
										 |  |  |         Find.prune | 
					
						
							|  |  |  |       elsif path.symlink? | 
					
						
							|  |  |  |         symlinks << path | 
					
						
							|  |  |  |       elsif path.directory? | 
					
						
							|  |  |  |         dirs << path | 
					
						
							| 
									
										
										
										
											2013-01-08 21:27:18 -08:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-23 21:18:09 -08:00
										 |  |  |     # Remove directories opposite from traversal, so that a subtree with no | 
					
						
							|  |  |  |     # actual files gets removed correctly. | 
					
						
							| 
									
										
										
										
											2013-12-21 23:28:04 -06:00
										 |  |  |     dirs.reverse_each do |d| | 
					
						
							|  |  |  |       if d.children.empty? | 
					
						
							| 
									
										
										
										
											2020-08-02 03:01:42 +02:00
										 |  |  |         puts "rmdir: #{d} (empty)" if verbose? | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |         d.rmdir | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-21 11:06:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-23 21:18:09 -08:00
										 |  |  |     # Remove unresolved symlinks | 
					
						
							| 
									
										
										
										
											2013-12-21 23:28:04 -06:00
										 |  |  |     symlinks.reverse_each do |s| | 
					
						
							|  |  |  |       s.unlink unless s.resolved_path_exists? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-11-09 13:00:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |   sig { params(path: Pathname).returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2016-07-04 16:10:24 +01:00
										 |  |  |   def executable_path?(path) | 
					
						
							| 
									
										
										
										
											2016-07-12 19:47:27 +01:00
										 |  |  |     path.text_executable? || path.executable? | 
					
						
							| 
									
										
										
										
											2016-07-04 16:10:24 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 17:21:51 +01:00
										 |  |  |   # Both these files are completely unnecessary to package and cause | 
					
						
							|  |  |  |   # pointless conflicts with other formulae. They are removed by Debian, | 
					
						
							|  |  |  |   # Arch & MacPorts amongst other packagers as well. The files are | 
					
						
							|  |  |  |   # created as part of installing any Perl module. | 
					
						
							|  |  |  |   PERL_BASENAMES = Set.new(%w[perllocal.pod .packlist]).freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |   # Clean a top-level (`bin`, `sbin`, `lib`) directory, recursively, by fixing file | 
					
						
							| 
									
										
										
										
											2014-07-19 23:27:58 -07:00
										 |  |  |   # permissions and removing .la files, unless the files (or parent | 
					
						
							|  |  |  |   # directories) are protected by skip_clean. | 
					
						
							| 
									
										
										
										
											2014-07-20 09:51:11 -07:00
										 |  |  |   # | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |   # `bin` and `sbin` should not have any subdirectories; if either do that is | 
					
						
							|  |  |  |   # caught as an audit warning. | 
					
						
							| 
									
										
										
										
											2014-07-20 09:51:11 -07:00
										 |  |  |   # | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |   # `lib` may have a large directory tree (see Erlang for instance) and | 
					
						
							|  |  |  |   # clean_dir applies cleaning rules to the entire tree. | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |   sig { params(directory: Pathname).void } | 
					
						
							| 
									
										
										
										
											2023-03-08 00:27:19 +00:00
										 |  |  |   def clean_dir(directory) | 
					
						
							|  |  |  |     directory.find do |path| | 
					
						
							| 
									
										
										
										
											2013-12-22 13:43:51 -06:00
										 |  |  |       path.extend(ObserverPathnameExtension) | 
					
						
							| 
									
										
										
										
											2012-09-18 16:25:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |       Find.prune if @formula.skip_clean? path | 
					
						
							| 
									
										
										
										
											2013-12-22 13:43:50 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-27 18:49:25 -05:00
										 |  |  |       next if path.directory? | 
					
						
							| 
									
										
										
										
											2016-09-22 20:12:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-18 15:23:14 +09:00
										 |  |  |       if path.extname == ".la" || path.extname == ".tbd" || PERL_BASENAMES.include?(path.basename.to_s) | 
					
						
							| 
									
										
										
										
											2016-07-31 02:00:33 +01:00
										 |  |  |         path.unlink | 
					
						
							| 
									
										
										
										
											2020-11-13 10:07:02 -05:00
										 |  |  |       elsif path.symlink? | 
					
						
							|  |  |  |         # Skip it. | 
					
						
							| 
									
										
										
										
											2013-12-22 13:43:50 -06:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |         # Set permissions for executables and non-executables. | 
					
						
							| 
									
										
										
										
											2016-07-04 16:10:24 +01:00
										 |  |  |         perms = if executable_path?(path) | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |           0555
 | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           0444
 | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-08-02 03:01:42 +02:00
										 |  |  |         if debug? | 
					
						
							| 
									
										
										
										
											2014-02-23 16:46:44 -08:00
										 |  |  |           old_perms = path.stat.mode & 0777
 | 
					
						
							| 
									
										
										
										
											2019-11-29 14:54:41 -05:00
										 |  |  |           odebug "Fixing #{path} permissions from #{old_perms.to_s(8)} to #{perms.to_s(8)}" if perms != old_perms | 
					
						
							| 
									
										
										
										
											2014-02-23 16:46:44 -08:00
										 |  |  |         end | 
					
						
							|  |  |  |         path.chmod perms | 
					
						
							| 
									
										
										
										
											2010-08-21 11:06:02 -07:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2021-04-29 17:49:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-10 20:20:34 -04:00
										 |  |  |   sig { void } | 
					
						
							| 
									
										
										
										
											2021-04-29 17:49:47 +01:00
										 |  |  |   def rewrite_shebangs | 
					
						
							|  |  |  |     require "language/perl" | 
					
						
							|  |  |  |     require "utils/shebang" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |     basepath = @formula.prefix.realpath | 
					
						
							| 
									
										
										
										
											2021-04-29 17:49:47 +01:00
										 |  |  |     basepath.find do |path| | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |       Find.prune if @formula.skip_clean? path | 
					
						
							| 
									
										
										
										
											2021-04-29 17:49:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       next if path.directory? || path.symlink? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       begin | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |         Utils::Shebang.rewrite_shebang Language::Perl::Shebang.detected_perl_shebang(@formula), path | 
					
						
							| 
									
										
										
										
											2021-04-29 17:49:47 +01:00
										 |  |  |       rescue ShebangDetectionError | 
					
						
							|  |  |  |         break | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2024-03-07 18:27:26 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-08 13:23:25 -05:00
										 |  |  |   # Remove non-reproducible pip direct_url.json which records the /tmp build directory. | 
					
						
							|  |  |  |   # Remove RECORD files to prevent changes to the installed Python package. | 
					
						
							|  |  |  |   # Modify INSTALLER to provide information that files are managed by brew. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # @see https://packaging.python.org/en/latest/specifications/recording-installed-packages/ | 
					
						
							| 
									
										
										
										
											2024-03-07 18:27:26 -05:00
										 |  |  |   sig { void } | 
					
						
							| 
									
										
										
										
											2024-03-08 13:23:25 -05:00
										 |  |  |   def clean_python_metadata | 
					
						
							| 
									
										
										
										
											2024-03-07 18:27:26 -05:00
										 |  |  |     basepath = @formula.prefix.realpath | 
					
						
							|  |  |  |     basepath.find do |path| | 
					
						
							|  |  |  |       Find.prune if @formula.skip_clean?(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       next if path.directory? || path.symlink? | 
					
						
							|  |  |  |       next if path.parent.extname != ".dist-info" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-08 13:23:25 -05:00
										 |  |  |       case path.basename.to_s | 
					
						
							|  |  |  |       when "direct_url.json", "RECORD" | 
					
						
							|  |  |  |         observe_file_removal path | 
					
						
							|  |  |  |       when "INSTALLER" | 
					
						
							|  |  |  |         odebug "Modifying #{path} contents from #{path.read.chomp} to brew" | 
					
						
							|  |  |  |         path.atomic_write("brew\n") | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2024-03-07 18:27:26 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-08-21 11:06:02 -07:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2016-07-04 16:10:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | require "extend/os/cleaner" |