@atomist/sdm
Version:
Atomist Software Delivery Machine SDK
150 lines • 4.84 kB
JavaScript
"use strict";
/*
* Copyright © 2020 Atomist, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DockerFileParser = void 0;
const logger_1 = require("@atomist/automation-client/lib/util/logger");
const dockerfile_ast_1 = require("dockerfile-ast");
class DockerFileParserClass {
async toAst(f) {
try {
const dockerfile = dockerfile_ast_1.DockerfileParser.parse(await f.getContent());
const doc = dockerfile.document;
const $children = dockerfile.getInstructions().map(i => instructionToTreeNode(i, doc));
return {
$name: f.name,
$children,
};
}
catch (err) {
logger_1.logger.error("Error parsing Dockerfile", err);
throw err;
}
}
}
/**
* FileParser instance to use for Docker files.
* Example path expressions, given "node:argon" as the image
* //FROM/image/name - returns a node with the value "node" etc
* //FROM/image/tag - returns a node with the value "argon" etc
* @type {DockerFileParserClass}
*/
exports.DockerFileParser = new DockerFileParserClass();
function instructionToTreeNode(l, doc, parent) {
const n = {
$name: l.getKeyword(),
$value: l.getTextContent(),
$parent: parent,
$offset: l.getRange() ? convertToOffset(l.getRange().start, doc) : undefined,
};
// Deconstruct subelements. There is no generic tree structure in the
// AST library, so we need to do this manually for subelements we care about.
if (isFrom(l)) {
addChildrenFromFromStructure(n, l, doc);
}
else if (isLabel(l)) {
addChildrenFromLabelStructure(n, l, doc);
}
else {
switch (l.getKeyword()) {
case "MAINTAINER":
addChildrenFromMaintainer(n, l, doc);
break;
case "EXPOSE":
n.$children = [
{
$name: "port",
$value: l.getArgumentsContent(),
},
];
break;
default:
break;
}
}
return n;
}
function isFrom(l) {
const maybe = l;
return !!maybe.getImageName;
}
function isLabel(l) {
const maybe = l;
return !!maybe.getProperties;
}
// Deconstruct FROM to add children.
// We need to do this for all structures we want to see inside
function addChildrenFromFromStructure(n, l, doc) {
const nameChild = {
$name: "name",
$value: l.getImageName(),
$offset: convertToOffset(l.getImageNameRange().start, doc),
};
const $children = [nameChild];
if (!!l.getImageTag()) {
$children.push({
$name: "tag",
$value: l.getImageTag(),
$offset: convertToOffset(l.getImageTagRange().start, doc),
});
}
n.$children = [
{
$parent: n,
$name: "image",
$value: l.getImage(),
$offset: convertToOffset(l.getImageRange().start, doc),
$children,
},
];
}
function addChildrenFromLabelStructure(n, l, doc) {
n.$children = l.getProperties().map(prop => ({
$parent: n,
$name: "pair",
$value: l.getTextContent().slice("LABEL ".length),
// Children are the name and value
$children: [
{
$name: "key",
$value: prop.getName(),
$offset: convertToOffset(prop.getNameRange().start, doc),
},
{
$name: "value",
$value: prop.getValue(),
$offset: prop.getValueRange() ? convertToOffset(prop.getValueRange().start, doc) : undefined,
},
],
}));
}
function addChildrenFromMaintainer(n, m, doc) {
const rest = n.$value.slice("MAINTAINER ".length);
n.$children = [
{
$parent: n,
$name: "maintainer",
$value: rest,
$offset: n.$offset + "MAINTAINER ".length,
$children: [],
},
];
}
// Convert a position to an offset, given the document
function convertToOffset(pos, doc) {
return doc.offsetAt(pos);
}
//# sourceMappingURL=DockerFileParser.js.map