@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
67 lines • 2.58 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadIgnore = loadIgnore;
exports.globMatcher = globMatcher;
exports.rbuildignoreMatcher = rbuildignoreMatcher;
const files_1 = require("./files");
const log_1 = require("./log");
const rbuildignoreLog = log_1.log.getSubLogger({ name: 'rbuildignore' });
let ignoreFactory;
/** The `ignore` factory, required on first use only. */
function loadIgnore() {
// eslint-disable-next-line @typescript-eslint/no-require-imports -- loaded on demand, see above
return ignoreFactory ??= require('ignore');
}
/** `ignore` rejects absolute and windows paths */
function relative(filePath) {
return (0, files_1.toPosixPath)(filePath).replace(/^([a-zA-Z]:)?\/+/, '');
}
/**
* Tests paths against `pattern`, ignoring capitalization: `?` and `*` stay within one path segment, `**` spans them.
* A pattern anchored with a leading `/` has to match from the start, any other matches at any depth
* (`global.R` matches `pkg/R/global.R`).
*/
function globMatcher(pattern) {
const cleaned = relative(pattern);
const ig = loadIgnore()({ ignorecase: true }).add(pattern.startsWith('/') ? cleaned : `**/${cleaned}`);
return filePath => ig.ignores(relative(filePath));
}
/**
* Unlike `.gitignore`, the lines of an `.Rbuildignore` are (Perl-compatible) *regular expressions* rather than
* globs, matched unanchored and case-insensitively against the path relative to the package root, as `R CMD build` does.
* Invalid lines are dropped with a warning.
*/
function rbuildignoreMatcher(content) {
const patterns = [];
for (const line of content.split(/\r?\n/)) {
const trimmed = line.trim();
if (trimmed.length === 0) {
continue;
}
try {
patterns.push(new RegExp(trimmed, 'i'));
}
catch {
rbuildignoreLog.warn(`Ignoring invalid .Rbuildignore pattern '${trimmed}'.`);
}
}
if (patterns.length === 0) {
return () => false;
}
return relativePath => {
const posix = relative(relativePath);
if (posix === '') {
return false;
}
const segments = posix.split('/');
// R walks the tree, so a match on any ancestor prefix drops the whole subtree
for (let i = 1; i <= segments.length; i++) {
const prefix = segments.slice(0, i).join('/');
if (patterns.some(p => p.test(prefix))) {
return true;
}
}
return false;
};
}
//# sourceMappingURL=glob.js.map