UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

62 lines 3.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FlowrAnalyzerPackageVersionsSessionInfoPlugin = exports.sessionInfoLog = void 0; const flowr_analyzer_package_versions_plugin_1 = require("./flowr-analyzer-package-versions-plugin"); const semver_1 = require("semver"); const package_1 = require("./package"); const flowr_file_1 = require("../../context/flowr-file"); const log_1 = require("../../../util/log"); exports.sessionInfoLog = log_1.log.getSubLogger({ name: 'flowr-analyzer-package-versions-session-info-plugin' }); /** matches the `R version 4.3.1 (2023-06-16)` line of `sessionInfo()`/`sessionInfo` output */ const rVersionRe = /\bR version\s+(\d+\.\d+\.\d+)/; /** the section headers `sessionInfo()` prints right before a `[n] pkg_version ...` package listing */ const packageHeaderRe = /\b(?:other attached packages|loaded via a namespace \(and not attached\))\s*:/; /** an `[n] ...` listing line as printed by R for a vector of packages (the `[n]` may itself be commented out) */ const packageListingLineRe = /\[\d+\]\s*(.+)$/gm; /** a single `name_version` token within a listing line, e.g. `dplyr_1.1.2` or `data.table_1.14.8` */ const packageTokenRe = /([A-Za-z][A-Za-z0-9.]*)_(\d+(?:[.-]\d+)+)/g; function pin(ctx, name, version) { const range = package_1.Package.parsePkgVersionRange(undefined, version); ctx.deps.addDeclaredDependency(new package_1.Package({ name, versionConstraints: range ? [range] : undefined })); } /** * Reads package (and R) versions from a pasted `sessionInfo()` output block within a source file (typically inside * a comment). This is how R users record a reproducible environment, so when present it pins exact versions, just * like a lockfile. Detection is conservative: we only act once we see the `R version` line and/or one of * `sessionInfo()`'s package-listing headers, and additionally require at least one `pkg_version` token so unrelated * text is not misread. */ class FlowrAnalyzerPackageVersionsSessionInfoPlugin extends flowr_analyzer_package_versions_plugin_1.FlowrAnalyzerPackageVersionsPlugin { name = 'flowr-analyzer-package-versions-session-info-plugin'; description = 'Extracts package and R versions from a pasted sessionInfo() output block.'; version = new semver_1.SemVer('0.1.0'); process(ctx) { for (const file of ctx.files.getFilesByRole(flowr_file_1.FileRole.Source)) { this.processContent(ctx, file.content().toString()); } } processContent(ctx, content) { const rVersionMatch = rVersionRe.exec(content); if (!rVersionMatch && !packageHeaderRe.test(content)) { return; } const packages = new Map(); for (const line of content.matchAll(packageListingLineRe)) { for (const token of line[1].matchAll(packageTokenRe)) { packages.set(token[1], token[2]); } } if (packages.size === 0) { exports.sessionInfoLog.debug('Found sessionInfo() markers but no package version tokens, skipping.'); return; } if (rVersionMatch) { pin(ctx, 'R', rVersionMatch[1]); } for (const [name, version] of packages) { pin(ctx, name, version); } } } exports.FlowrAnalyzerPackageVersionsSessionInfoPlugin = FlowrAnalyzerPackageVersionsSessionInfoPlugin; //# sourceMappingURL=flowr-analyzer-package-versions-session-info-plugin.js.map