| 
									
										
										
										
											2020-10-20 00:56:50 +02:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:56:50 +02:00
										 |  |  | require "system_command" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-01 07:41:52 +02:00
										 |  |  | module UnpackStrategy | 
					
						
							|  |  |  |   class Zip | 
					
						
							| 
									
										
										
										
											2020-09-20 05:57:37 +02:00
										 |  |  |     module MacOSZipExtension | 
					
						
							| 
									
										
										
										
											2020-10-20 00:56:50 +02:00
										 |  |  |       extend T::Sig | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       include UnpackStrategy | 
					
						
							|  |  |  |       include SystemCommand::Mixin | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       using Magic | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { override.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) } | 
					
						
							| 
									
										
										
										
											2018-08-06 22:59:02 +02:00
										 |  |  |       def extract_to_dir(unpack_dir, basename:, verbose:) | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |         with_env(TZ: "UTC") do | 
					
						
							|  |  |  |           if merge_xattrs && contains_extended_attributes?(path) | 
					
						
							|  |  |  |             # We use ditto directly, because dot_clean has issues if the __MACOSX | 
					
						
							|  |  |  |             # folder has incorrect permissions. | 
					
						
							|  |  |  |             # (Also, Homebrew's ZIP artifact automatically deletes this folder.) | 
					
						
							|  |  |  |             return system_command! "ditto", | 
					
						
							|  |  |  |                                    args:         ["-x", "-k", path, unpack_dir], | 
					
						
							|  |  |  |                                    verbose:      verbose, | 
					
						
							|  |  |  |                                    print_stderr: false | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2019-04-09 21:45:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |           result = begin | 
					
						
							|  |  |  |             T.let(super, T.nilable(SystemCommand::Result)) | 
					
						
							|  |  |  |           rescue ErrorDuringExecution => e | 
					
						
							|  |  |  |             raise unless e.stderr.include?("End-of-central-directory signature not found.") | 
					
						
							| 
									
										
										
										
											2019-03-29 21:06:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |             system_command! "ditto", | 
					
						
							|  |  |  |                             args:    ["-x", "-k", path, unpack_dir], | 
					
						
							|  |  |  |                             verbose: verbose | 
					
						
							|  |  |  |             nil | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2018-10-08 09:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |           return if result.blank? | 
					
						
							| 
									
										
										
										
											2020-11-10 00:11:22 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |           volumes = result.stderr.chomp | 
					
						
							|  |  |  |                           .split("\n") | 
					
						
							|  |  |  |                           .map { |l| l[/\A   skipping: (.+)  volume label\Z/, 1] } | 
					
						
							|  |  |  |                           .compact | 
					
						
							| 
									
										
										
										
											2018-10-08 09:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |           return if volumes.empty? | 
					
						
							| 
									
										
										
										
											2018-08-06 22:59:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |           Dir.mktmpdir do |tmp_unpack_dir| | 
					
						
							|  |  |  |             tmp_unpack_dir = Pathname(tmp_unpack_dir) | 
					
						
							| 
									
										
										
										
											2018-08-06 22:59:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |             # `ditto` keeps Finder attributes intact and does not skip volume labels | 
					
						
							|  |  |  |             # like `unzip` does, which can prevent disk images from being unzipped. | 
					
						
							|  |  |  |             system_command! "ditto", | 
					
						
							|  |  |  |                             args:    ["-x", "-k", path, tmp_unpack_dir], | 
					
						
							|  |  |  |                             verbose: verbose | 
					
						
							| 
									
										
										
										
											2018-08-06 22:59:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:27:00 +01:00
										 |  |  |             volumes.each do |volume| | 
					
						
							|  |  |  |               FileUtils.mv tmp_unpack_dir/volume, unpack_dir/volume, verbose: verbose | 
					
						
							|  |  |  |             end | 
					
						
							| 
									
										
										
										
											2018-08-06 22:59:02 +02:00
										 |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-10-20 00:56:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { params(path: Pathname).returns(T::Boolean) } | 
					
						
							|  |  |  |       def contains_extended_attributes?(path) | 
					
						
							|  |  |  |         path.zipinfo.grep(/(^__MACOSX|\._)/).any? | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-09-20 05:57:37 +02:00
										 |  |  |     end | 
					
						
							|  |  |  |     private_constant :MacOSZipExtension | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     prepend MacOSZipExtension | 
					
						
							| 
									
										
										
										
											2018-08-01 07:41:52 +02:00
										 |  |  |   end | 
					
						
							|  |  |  | end |