| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-18 15:11:11 -08:00
										 |  |  | RSpec.describe Cask::Pkg, :cask do | 
					
						
							| 
									
										
										
										
											2017-03-08 03:03:49 +01:00
										 |  |  |   describe "#uninstall" do | 
					
						
							| 
									
										
										
										
											2018-07-19 23:56:51 +02:00
										 |  |  |     let(:fake_system_command) { NeverSudoSystemCommand } | 
					
						
							| 
									
										
										
										
											2023-01-22 17:04:54 -08:00
										 |  |  |     let(:empty_response) do | 
					
						
							|  |  |  |       instance_double( | 
					
						
							|  |  |  |         SystemCommand::Result, | 
					
						
							|  |  |  |         stdout: "", | 
					
						
							|  |  |  |         plist:  { "volume" => "/", "install-location" => "", "paths" => {} }, | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |     let(:pkg) { described_class.new("my.fake.pkg", fake_system_command) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-29 09:50:51 +01:00
										 |  |  |     it "removes files and dirs referenced by the pkg" do | 
					
						
							|  |  |  |       some_files = Array.new(3) { Pathname.new(Tempfile.new("plain_file").path) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       some_specials = Array.new(3) { Pathname.new(Tempfile.new("special_file").path) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       some_dirs = Array.new(3) { mktmpdir } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       root_dir = Pathname.new(mktmpdir) | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |       allow(pkg).to receive_messages(pkgutil_bom_files: some_files, pkgutil_bom_specials: some_specials, | 
					
						
							|  |  |  |                                      pkgutil_bom_dirs: some_dirs, root: root_dir) | 
					
						
							| 
									
										
										
										
											2020-06-29 09:50:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       allow(pkg).to receive(:forget) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       pkg.uninstall | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       some_files.each do |file| | 
					
						
							|  |  |  |         expect(file).not_to exist | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-18 01:32:55 +01:00
										 |  |  |       some_specials.each do |file| | 
					
						
							|  |  |  |         expect(file).not_to exist | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-29 09:50:51 +01:00
										 |  |  |       some_dirs.each do |dir| | 
					
						
							|  |  |  |         expect(dir).not_to exist | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(root_dir).not_to exist | 
					
						
							| 
									
										
										
										
											2022-10-18 01:32:55 +01:00
										 |  |  |     ensure | 
					
						
							|  |  |  |       some_files&.each { |path| FileUtils.rm_rf(path) } | 
					
						
							|  |  |  |       some_specials&.each { |path| FileUtils.rm_rf(path) } | 
					
						
							|  |  |  |       some_dirs&.each { |path| FileUtils.rm_rf(path) } | 
					
						
							|  |  |  |       FileUtils.rm_rf(root_dir) if root_dir | 
					
						
							| 
									
										
										
										
											2020-06-29 09:50:51 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 23:15:33 +00:00
										 |  |  |     describe "pkgutil" do | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |       it "forgets the pkg" do | 
					
						
							|  |  |  |         allow(fake_system_command).to receive(:run!).with( | 
					
						
							|  |  |  |           "/usr/sbin/pkgutil", | 
					
						
							| 
									
										
										
										
											2017-04-21 15:50:39 +02:00
										 |  |  |           args: ["--pkg-info-plist", "my.fake.pkg"], | 
					
						
							|  |  |  |         ).and_return(empty_response) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(fake_system_command).to receive(:run!).with( | 
					
						
							|  |  |  |           "/usr/sbin/pkgutil", | 
					
						
							|  |  |  |           args: ["--files", "my.fake.pkg"], | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |         ).and_return(empty_response) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(fake_system_command).to receive(:run!).with( | 
					
						
							|  |  |  |           "/usr/sbin/pkgutil", | 
					
						
							| 
									
										
										
										
											2023-04-26 19:51:26 -07:00
										 |  |  |           args:         ["--forget", "my.fake.pkg"], | 
					
						
							|  |  |  |           sudo:         true, | 
					
						
							|  |  |  |           sudo_as_root: true, | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pkg.uninstall | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "removes broken symlinks" do | 
					
						
							| 
									
										
										
										
											2017-08-06 12:30:40 +02:00
										 |  |  |       fake_root = mktmpdir | 
					
						
							|  |  |  |       fake_dir  = mktmpdir | 
					
						
							| 
									
										
										
										
											2018-09-02 16:15:09 +01:00
										 |  |  |       fake_file = fake_dir.join("ima_file").tap do |path| | 
					
						
							|  |  |  |         FileUtils.touch(path) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       intact_symlink = fake_dir.join("intact_symlink").tap { |path| path.make_symlink(fake_file) } | 
					
						
							|  |  |  |       broken_symlink = fake_dir.join("broken_symlink").tap { |path| path.make_symlink("im_nota_file") } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |       allow(pkg).to receive_messages(pkgutil_bom_specials: [], pkgutil_bom_files: [], pkgutil_bom_dirs: [fake_dir], | 
					
						
							|  |  |  |                                      root: fake_root) | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |       allow(pkg).to receive(:forget) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       pkg.uninstall | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(intact_symlink).to exist | 
					
						
							|  |  |  |       expect(broken_symlink).not_to exist | 
					
						
							|  |  |  |       expect(fake_dir).to exist | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  |       expect(fake_root).not_to exist | 
					
						
							| 
									
										
										
										
											2022-10-18 01:32:55 +01:00
										 |  |  |     ensure | 
					
						
							|  |  |  |       FileUtils.rm_rf(fake_dir) if fake_dir | 
					
						
							|  |  |  |       FileUtils.rm_rf(fake_root) if fake_root | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "snags permissions on ornery dirs, but returns them afterwards" do | 
					
						
							| 
									
										
										
										
											2017-08-06 12:30:40 +02:00
										 |  |  |       fake_root = mktmpdir | 
					
						
							|  |  |  |       fake_dir = mktmpdir | 
					
						
							|  |  |  |       fake_file = fake_dir.join("ima_unrelated_file").tap { |path| FileUtils.touch(path) } | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |       fake_dir.chmod(0000) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |       allow(pkg).to receive_messages(pkgutil_bom_specials: [], pkgutil_bom_files: [], pkgutil_bom_dirs: [fake_dir], | 
					
						
							|  |  |  |                                      root: fake_root) | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |       allow(pkg).to receive(:forget) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 02:07:06 +01:00
										 |  |  |       # This is expected to fail in tests since we don't use `sudo`. | 
					
						
							|  |  |  |       allow(fake_system_command).to receive(:run!).and_call_original | 
					
						
							|  |  |  |       expect(fake_system_command).to receive(:run!).with( | 
					
						
							|  |  |  |         "/usr/bin/xargs", | 
					
						
							| 
									
										
										
										
											2023-04-26 19:51:26 -07:00
										 |  |  |         args:         ["-0", "--", a_string_including("rmdir")], | 
					
						
							|  |  |  |         input:        [fake_dir].join("\0"), | 
					
						
							|  |  |  |         sudo:         true, | 
					
						
							|  |  |  |         sudo_as_root: true, | 
					
						
							| 
									
										
										
										
											2021-03-16 02:07:06 +01:00
										 |  |  |       ).and_return(instance_double(SystemCommand::Result, stdout: "")) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 19:55:05 +02:00
										 |  |  |       pkg.uninstall | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expect(fake_dir).to be_a_directory | 
					
						
							| 
									
										
										
										
											2017-08-06 12:30:40 +02:00
										 |  |  |       expect((fake_dir.stat.mode % 01000)).to eq(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fake_dir.chmod(0777) | 
					
						
							|  |  |  |       expect(fake_file).to be_a_file | 
					
						
							| 
									
										
										
										
											2022-10-18 01:32:55 +01:00
										 |  |  |     ensure | 
					
						
							|  |  |  |       if fake_dir | 
					
						
							|  |  |  |         fake_dir.chmod(0777) | 
					
						
							|  |  |  |         FileUtils.rm_rf(fake_dir) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       FileUtils.rm_rf(fake_root) if fake_root | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe "#info" do | 
					
						
							| 
									
										
										
										
											2018-07-19 23:56:51 +02:00
										 |  |  |     let(:fake_system_command) { class_double(SystemCommand) } | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     let(:volume) { "/" } | 
					
						
							|  |  |  |     let(:install_location) { "tmp" } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let(:pkg_id) { "my.fancy.package.main" } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let(:pkg_files) do | 
					
						
							|  |  |  |       %w[
 | 
					
						
							|  |  |  |         fancy/bin/fancy.exe | 
					
						
							|  |  |  |         fancy/var/fancy.data | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     let(:pkg_directories) do | 
					
						
							|  |  |  |       %w[
 | 
					
						
							|  |  |  |         fancy | 
					
						
							|  |  |  |         fancy/bin | 
					
						
							|  |  |  |         fancy/var | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let(:pkg_info_plist) do | 
					
						
							| 
									
										
										
										
											2018-07-11 15:17:40 +02:00
										 |  |  |       <<~XML | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  |         <?xml version="1.0" encoding="UTF-8"?> | 
					
						
							|  |  |  |         <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | 
					
						
							|  |  |  |         <plist version="1.0"> | 
					
						
							|  |  |  |         <dict> | 
					
						
							|  |  |  |           <key>install-location</key>
 | 
					
						
							|  |  |  |           <string>#{install_location}</string> | 
					
						
							|  |  |  |           <key>volume</key>
 | 
					
						
							|  |  |  |           <string>#{volume}</string> | 
					
						
							|  |  |  |           <key>paths</key>
 | 
					
						
							|  |  |  |           <dict> | 
					
						
							| 
									
										
										
										
											2018-06-14 22:48:37 +02:00
										 |  |  |             #{(pkg_files + pkg_directories).map { |f| "<key>#{f}</key><dict></dict>" }.join} | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  |           </dict>
 | 
					
						
							|  |  |  |         </dict>
 | 
					
						
							|  |  |  |         </plist>
 | 
					
						
							| 
									
										
										
										
											2018-07-11 15:17:40 +02:00
										 |  |  |       XML | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "correctly parses a Property List" do | 
					
						
							| 
									
										
										
										
											2019-07-23 17:09:57 +01:00
										 |  |  |       pkg = described_class.new(pkg_id, fake_system_command) | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expect(fake_system_command).to receive(:run!).with( | 
					
						
							|  |  |  |         "/usr/sbin/pkgutil", | 
					
						
							| 
									
										
										
										
											2018-06-06 23:34:19 -04:00
										 |  |  |         args: ["--pkg-info-plist", pkg_id], | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  |       ).and_return( | 
					
						
							| 
									
										
										
										
											2020-11-23 02:05:50 +01:00
										 |  |  |         SystemCommand::Result.new( | 
					
						
							|  |  |  |           ["/usr/sbin/pkgutil", "--pkg-info-plist", pkg_id], | 
					
						
							|  |  |  |           [[:stdout, pkg_info_plist]], | 
					
						
							|  |  |  |           instance_double(Process::Status, exitstatus: 0), | 
					
						
							|  |  |  |           secrets: [], | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2017-03-09 22:01:46 +01:00
										 |  |  |       ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       info = pkg.info | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(info["install-location"]).to eq(install_location) | 
					
						
							|  |  |  |       expect(info["volume"]).to eq(volume) | 
					
						
							|  |  |  |       expect(info["paths"].keys).to eq(pkg_files + pkg_directories) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2017-02-08 09:58:38 +01:00
										 |  |  | end |