Repository: sxyazi/yazi
File: yazi-plugin/preset/plugins/extract.lua (Lua)

Code before:
		end
	end
end

function M:is_tar_compatible(url)
	local tar_extensions = { ".tar", ".tgz", ".tar.gz", ".tar.bz2" }
	for _, ext in ipairs(tar_extensions) do
		if url:find(ext .. "$") then
			return true
		end
	end
	return false
end

function M:try_with(url, pwd)
	local parent = url:parent()
	if not parent then
		fail("Invalid URL '%s'", url)
	end

	local tmp = fs.unique_name(parent:join(self.tmp_name(url)))
	if not tmp then
		fail("Failed to determine a temporary directory for %s", url)
	end

	os.execute("mkdir -p " .. tostring(tmp))
	local archive = require("archive")
	if self:is_tar_compatible(tostring(url)) then
		local child, code = archive:spawn_tar { "-xvf", tostring(url), "-C", tostring(tmp) }
		if not child then
			fail("Failed to spawn `tar` command, error code %s", code)
		end

		local output, err = child:wait_with_output()
		if output and output.status.code == 2 and archive:is_encrypted(output.stderr) then
			fs.remove("dir_clean", tmp)
			return true -- Needs retry
		end

		self:tidy(url, tmp)
		if not output then
			fail("tar failed to output when extracting '%s', error code %s", err, url)
		elseif output.status.code ~= 0 then
			fail("tar exited when extracting '%s', error code %s", url, output.status.code)
		end
	else
		-- Fall back to 7z for other file types or needs password authentification
		local child, code = archive:spawn_7z { "x", "-aou", "-p" .. pwd, "-o" .. tostring(tmp), tostring(url) }
		if not child then
			fail("Spawn `7z` and `7zz` both commands failed, error code %s", code)
		end

Review comment (suggestion):
Please add a new method `fs.create(type, url)` above and similar to the `fs.remove()` method here and use it instead to achieve cross-platform compatibility https://github.com/sxyazi/yazi/blob/640e497c358c5ef576643e646cdb73be67bf7c52/yazi-plugin/src/fs/fs.rs#L36-L54

- type: available values `"file"`, `"dir"`
- url: Url to operate

Code after:
		end
	end
end

function M:try_with(from, pwd, to)
	to = to or from:parent()
	if not to then
		fail("Invalid URL '%s'", from)
	end

	local tmp = fs.unique_name(to:join(self.tmp_name(from)))
	if not tmp then
		fail("Failed to determine a temporary directory for %s", from)
	end

	local archive = require("archive")
	local child, code = archive:spawn_7z { "x", "-aou", "-p" .. pwd, "-o" .. tostring(tmp), tostring(from) }
	if not child then
		fail("Spawn `7z` and `7zz` both commands failed, error code %s", code)
	end

	local output, err = child:wait_with_output()
	if output and output.status.code == 2 and archive:is_encrypted(output.stderr) then
		fs.remove("dir_clean", tmp)
		return true -- Need to retry
	end

	self:tidy(from, to, tmp)
	if not output then
		fail("7zip failed to output when extracting '%s', error code %s", err, from)
	elseif output.status.code ~= 0 then
		fail("7zip exited when extracting '%s', error code %s", from, output.status.code)
	end
end

function M:tidy(from, to, tmp)
	local outs = fs.read_dir(tmp, { limit = 2 })
	if not outs then
		fail("Failed to read the temporary directory '%s' when extracting '%s'", tmp, from)
	elseif #outs == 0 then
		fs.remove("dir", tmp)
		fail("No files extracted from '%s'", from)
	end

	local only = #outs == 1
	if only and not outs[1].cha.is_dir and require("archive"):is_tar(outs[1].url) then
		self:entry { tostring(outs[1].url), tostring(to) }
		fs.remove("file", outs[1].url)
		fs.remove("dir", tmp)
		return
	end