-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathlayer.ts
71 lines (63 loc) · 2.27 KB
/
layer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import * as Debug from "debug";
import * as gunzip from "gunzip-maybe";
import * as path from "path";
import { Readable } from "stream";
import { extract, Extract } from "tar-stream";
import { isWhitedOutFile } from ".";
import { applyCallbacks, isResultEmpty } from "./callbacks";
import { ExtractAction, ExtractedLayers } from "./types";
const debug = Debug("snyk");
/**
* Extract key files from the specified TAR stream.
* @param layerTarStream image layer as a Readable TAR stream. Note: consumes the stream.
* @param extractActions array of pattern, callbacks pairs
* @returns extracted file products
*/
export async function extractImageLayer(
layerTarStream: Readable,
extractActions: ExtractAction[],
): Promise<ExtractedLayers> {
return new Promise((resolve, reject) => {
const result: ExtractedLayers = {};
const tarExtractor: Extract = extract();
tarExtractor.on("entry", async (headers, stream, next) => {
if (headers.type === "file") {
const absoluteFileName = path.join(path.sep, headers.name);
const matchedActions = extractActions.filter((action) =>
action.filePathMatches(absoluteFileName),
);
if (matchedActions.length > 0) {
try {
const callbackResult = await applyCallbacks(
matchedActions,
stream,
headers.size,
);
if (
!isResultEmpty(callbackResult) ||
isWhitedOutFile(absoluteFileName)
) {
result[absoluteFileName] = callbackResult;
}
} catch (error) {
// An ExtractAction has thrown an uncaught exception, likely a bug in the code!
debug(
`Exception thrown while applying callbacks during image layer extraction: ${error.message}`,
);
reject(error);
}
} else if (isWhitedOutFile(absoluteFileName)) {
result[absoluteFileName] = {};
}
}
stream.resume(); // auto drain the stream
next(); // ready for next entry
});
tarExtractor.on("finish", () => {
// all layer level entries read
resolve(result);
});
tarExtractor.on("error", (error) => reject(error));
layerTarStream.pipe(gunzip()).pipe(tarExtractor);
});
}