Add streaming API for zstd extraction
This commit is contained in:
parent
5b6984ee4d
commit
cd83b08c78
6 changed files with 80 additions and 47 deletions
47
lib/tar.js
generated
47
lib/tar.js
generated
|
|
@ -30,6 +30,7 @@ exports.isZstdAvailable = isZstdAvailable;
|
|||
exports.extract = extract;
|
||||
exports.extractTarZst = extractTarZst;
|
||||
exports.inferCompressionMethod = inferCompressionMethod;
|
||||
const child_process_1 = require("child_process");
|
||||
const fs = __importStar(require("fs"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const toolrunner_1 = require("@actions/exec/lib/toolrunner");
|
||||
|
|
@ -122,7 +123,7 @@ async function extract(tarPath, compressionMethod, tarVersion, logger) {
|
|||
if (!tarVersion) {
|
||||
throw new Error("Could not determine tar version, which is required to extract a Zstandard archive.");
|
||||
}
|
||||
return await extractTarZst(tarPath, tarVersion, logger);
|
||||
return await extractTarZst(fs.createReadStream(tarPath), tarVersion, logger);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
@ -132,37 +133,45 @@ async function extract(tarPath, compressionMethod, tarVersion, logger) {
|
|||
* @param dest destination directory. Optional.
|
||||
* @returns path to the destination directory
|
||||
*/
|
||||
async function extractTarZst(file, tarVersion, logger) {
|
||||
if (!file) {
|
||||
throw new Error("parameter 'file' is required");
|
||||
}
|
||||
// Create dest
|
||||
async function extractTarZst(tarStream, tarVersion, logger) {
|
||||
const dest = await createExtractFolder();
|
||||
try {
|
||||
// Initialize args
|
||||
const args = ["-x", "-v"];
|
||||
let destArg = dest;
|
||||
let fileArg = file;
|
||||
if (process.platform === "win32" && tarVersion.type === "gnu") {
|
||||
args.push("--force-local");
|
||||
destArg = dest.replace(/\\/g, "/");
|
||||
// Technically only the dest needs to have `/` but for aesthetic consistency
|
||||
// convert slashes in the file arg too.
|
||||
fileArg = file.replace(/\\/g, "/");
|
||||
}
|
||||
const args = ["-x", "--zstd"];
|
||||
if (tarVersion.type === "gnu") {
|
||||
// Suppress warnings when using GNU tar to extract archives created by BSD tar
|
||||
args.push("--warning=no-unknown-keyword");
|
||||
args.push("--overwrite");
|
||||
}
|
||||
args.push("-C", destArg, "-f", fileArg);
|
||||
await (0, actions_util_1.runTool)(`tar`, args);
|
||||
args.push("-f", "-", "-C", dest);
|
||||
process.stdout.write(`[command]tar ${args.join(" ")}\n`);
|
||||
const tarProcess = (0, child_process_1.spawn)("tar", args, { stdio: "pipe" });
|
||||
let stdout = "";
|
||||
tarProcess.stdout?.on("data", (data) => {
|
||||
stdout += data.toString();
|
||||
process.stdout.write(data);
|
||||
});
|
||||
let stderr = "";
|
||||
tarProcess.stderr?.on("data", (data) => {
|
||||
stderr += data.toString();
|
||||
// Mimic the standard behavior of the toolrunner by writing stderr to stdout
|
||||
process.stdout.write(data);
|
||||
});
|
||||
tarStream.pipe(tarProcess.stdin);
|
||||
await new Promise((resolve, reject) => {
|
||||
tarProcess.on("exit", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new actions_util_1.CommandInvocationError("tar", args, code ?? undefined, stdout, stderr));
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
return dest;
|
||||
}
|
||||
catch (e) {
|
||||
await (0, util_1.cleanUpGlob)(dest, "extraction destination directory", logger);
|
||||
throw e;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
async function createExtractFolder() {
|
||||
const dest = path_1.default.join((0, actions_util_1.getTemporaryDirectory)(), (0, uuid_1.v4)());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue