@atomist/sdm-pack-aspect
Version:
an Atomist SDM Extension Pack for visualizing drift across an organization
107 lines (96 loc) • 3.16 kB
text/typescript
/*
* Copyright © 2019 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.
*/
import {
FileParser,
} from "@atomist/automation-client";
import { fileHitIterator } from "@atomist/automation-client/lib/tree/ast/astUtils";
import {
Aspect,
fingerprintOf,
FP,
} from "@atomist/sdm-pack-fingerprint";
import { Omit } from "../../util/omit";
export interface FileMatch {
filePath: string;
pathExpression: string;
matchValue: string;
}
const FileMatchType = "file-match";
type FileMatchType = "file-match";
export interface FileMatchData {
kind: FileMatchType;
glob: string;
matches: FileMatch[];
}
export function isFileMatchFingerprint(fp: FP): fp is FP<FileMatchData> {
const maybe = fp.data as FileMatchData;
return !!maybe && maybe.kind === FileMatchType && maybe.kind === "file-match" && !!maybe.glob;
}
export interface FileMatchParams {
/**
* Glob to look for
*/
glob: string;
parseWith: FileParser;
pathExpression: string;
}
/**
* Check for presence of a match within the AST of files matching the glob.
* Always return something, but may have an empty path.
*/
export function fileMatchAspect(config: Omit<Aspect, "stats" | "extract" | "apply"> &
FileMatchParams): Aspect<FileMatchData> {
return {
toDisplayableFingerprintName: name => `File match '${config.glob}'`,
toDisplayableFingerprint: fp =>
fp.data.matches.length === 0 ?
"None" :
fp.data.matches
.map(m => m.matchValue)
.join(),
stats: {
defaultStatStatus: {
entropy: false,
},
},
...config,
extract:
async p => {
const matches: FileMatch[] = [];
const it = fileHitIterator(p, {
parseWith: config.parseWith,
pathExpression: config.pathExpression,
globPatterns: config.glob,
});
for await (const match of it) {
matches.push({
filePath: match.file.path,
pathExpression: config.pathExpression,
matchValue: match.matches[0].$value,
});
}
const data = {
kind: FileMatchType as any,
matches,
glob: config.glob,
};
return fingerprintOf({
type: config.name,
data,
});
},
};
}