| 
									
										
										
										
											2024-04-28 02:37:18 -04:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2023-01-06 22:58:22 -05:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Apple's gzip also uses zlib so use the same buffer size here. | 
					
						
							|  |  |  | # https://github.com/apple-oss-distributions/file_cmds/blob/file_cmds-400/gzip/gzip.c#L147 | 
					
						
							| 
									
										
										
										
											2024-04-28 02:37:18 -04:00
										 |  |  | GZIP_BUFFER_SIZE = T.let(64 * 1024, Integer) | 
					
						
							| 
									
										
										
										
											2023-01-06 22:58:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | module Utils | 
					
						
							|  |  |  |   # Helper functions for creating gzip files. | 
					
						
							|  |  |  |   module Gzip | 
					
						
							|  |  |  |     sig { | 
					
						
							|  |  |  |       params( | 
					
						
							|  |  |  |         path:      T.any(String, Pathname), | 
					
						
							|  |  |  |         mtime:     T.any(Integer, Time), | 
					
						
							|  |  |  |         orig_name: String, | 
					
						
							|  |  |  |         output:    T.any(String, Pathname), | 
					
						
							|  |  |  |       ).returns(Pathname) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.compress_with_options(path, mtime: ENV["SOURCE_DATE_EPOCH"].to_i, orig_name: File.basename(path), | 
					
						
							| 
									
										
										
										
											2023-04-17 10:59:47 -07:00
										 |  |  |                                    output: "#{path}.gz") | 
					
						
							| 
									
										
										
										
											2023-01-06 22:58:22 -05:00
										 |  |  |       # Ideally, we would just set mtime = 0 if SOURCE_DATE_EPOCH is absent, but Ruby's | 
					
						
							|  |  |  |       # Zlib::GzipWriter does not properly handle the case of setting mtime = 0: | 
					
						
							|  |  |  |       # https://bugs.ruby-lang.org/issues/16285 | 
					
						
							|  |  |  |       # | 
					
						
							| 
									
										
										
										
											2023-02-20 22:02:58 +08:00
										 |  |  |       # This was fixed in https://github.com/ruby/zlib/pull/10. Remove workaround | 
					
						
							|  |  |  |       # once we are using zlib gem version 1.1.0 or newer. | 
					
						
							| 
									
										
										
										
											2023-01-06 22:58:22 -05:00
										 |  |  |       if mtime.to_i.zero? | 
					
						
							| 
									
										
										
										
											2023-02-20 22:02:58 +08:00
										 |  |  |         odebug "Setting `mtime = 1` to avoid zlib gem bug when `mtime == 0`." | 
					
						
							|  |  |  |         mtime = 1
 | 
					
						
							| 
									
										
										
										
											2023-01-06 22:58:22 -05:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       File.open(path, "rb") do |fp| | 
					
						
							|  |  |  |         odebug "Creating gzip file at #{output}" | 
					
						
							|  |  |  |         gz = Zlib::GzipWriter.open(output) | 
					
						
							|  |  |  |         gz.mtime = mtime | 
					
						
							|  |  |  |         gz.orig_name = orig_name | 
					
						
							|  |  |  |         gz.write(fp.read(GZIP_BUFFER_SIZE)) until fp.eof? | 
					
						
							|  |  |  |       ensure | 
					
						
							|  |  |  |         # GzipWriter should be closed in case of error as well | 
					
						
							|  |  |  |         gz.close | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       FileUtils.rm_f path | 
					
						
							|  |  |  |       Pathname.new(output) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { | 
					
						
							|  |  |  |       params( | 
					
						
							|  |  |  |         paths:        T.any(String, Pathname), | 
					
						
							|  |  |  |         reproducible: T::Boolean, | 
					
						
							|  |  |  |         mtime:        T.any(Integer, Time), | 
					
						
							|  |  |  |       ).returns(T::Array[Pathname]) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-17 10:37:59 -07:00
										 |  |  |     def self.compress(*paths, reproducible: true, mtime: ENV["SOURCE_DATE_EPOCH"].to_i) | 
					
						
							| 
									
										
										
										
											2023-01-06 22:58:22 -05:00
										 |  |  |       if reproducible | 
					
						
							|  |  |  |         paths.map do |path| | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           compress_with_options(path, mtime:) | 
					
						
							| 
									
										
										
										
											2023-01-06 22:58:22 -05:00
										 |  |  |         end | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         paths.map do |path| | 
					
						
							|  |  |  |           safe_system "gzip", path | 
					
						
							|  |  |  |           Pathname.new("#{path}.gz") | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |