UNPKG

@nomiclabs/buidler

Version:

Buidler is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

150 lines (118 loc) 3.95 kB
import fsExtra from "fs-extra"; import isEqual from "lodash/isEqual"; import path from "path"; import { SOLC_INPUT_FILENAME, SOLC_OUTPUT_FILENAME, } from "../../internal/constants"; import { glob } from "../../internal/util/glob"; import { getPackageJson } from "../../internal/util/packageInfo"; import { ProjectPaths, SolcConfig } from "../../types"; // Checks the earliest date of modification for compiled files against the latest date for source files (including libraries). // Furthermore, cache is invalidated if Buidler's version changes, or a different solc version is set in the buidler config. export async function areArtifactsCached( sourceTimestamps: number[], newSolcConfig: SolcConfig, paths: ProjectPaths ): Promise<boolean> { const oldConfig = await getLastUsedConfig(paths.cache); if ( oldConfig === undefined || !compareSolcConfigs(oldConfig.solc, newSolcConfig) || !(await compareBuidlerVersion(oldConfig.buidlerVersion)) ) { return false; } const maxSourceDate = getMaxSourceDate(sourceTimestamps); const minArtifactDate = await getMinArtifactDate(paths.artifacts); if ( !(await fsExtra.pathExists(path.join(paths.cache, SOLC_INPUT_FILENAME))) ) { return false; } if ( !(await fsExtra.pathExists(path.join(paths.cache, SOLC_OUTPUT_FILENAME))) ) { return false; } const lastConfigTimestamp = await getLastUsedConfigTimestamp(paths.cache); if ( lastConfigTimestamp !== undefined && lastConfigTimestamp > maxSourceDate ) { return true; } return maxSourceDate < minArtifactDate; } async function getModificationDatesInDir(dir: string): Promise<number[]> { const pattern = path.join(dir, "**", "*"); const files = await glob(pattern); return Promise.all( files.map(async (file) => (await fsExtra.stat(file)).ctimeMs) ); } function getMaxSourceDate(sourceTimestamps: number[]): number { return Math.max(...sourceTimestamps); } async function getMinArtifactDate(artifactsPath: string): Promise<number> { const timestamps = await getModificationDatesInDir(artifactsPath); if (timestamps.length === 0) { return 0; } return Math.min(...timestamps); } const LAST_CONFIG_USED_FILENAME = "last-solc-config.json"; function getPathToCachedLastConfigPath(cachePath: string) { const pathToLastConfigUsed = path.join(cachePath, LAST_CONFIG_USED_FILENAME); return pathToLastConfigUsed; } async function getLastUsedConfig( cachePath: string ): Promise<{ solc: SolcConfig; buidlerVersion: string } | undefined> { const pathToConfig = getPathToCachedLastConfigPath(cachePath); if (!(await fsExtra.pathExists(pathToConfig))) { return undefined; } return module.require(pathToConfig); } async function getLastUsedConfigTimestamp( cachePath: string ): Promise<number | undefined> { const pathToConfig = getPathToCachedLastConfigPath(cachePath); if (!(await fsExtra.pathExists(pathToConfig))) { return undefined; } return (await fsExtra.stat(pathToConfig)).ctimeMs; } export async function cacheBuidlerConfig( paths: ProjectPaths, config: SolcConfig ) { const pathToLastConfigUsed = getPathToCachedLastConfigPath(paths.cache); const newJson = { solc: config, buidlerVersion: await getCurrentBuidlerVersion(), }; await fsExtra.ensureDir(path.dirname(pathToLastConfigUsed)); return fsExtra.writeFile( pathToLastConfigUsed, JSON.stringify(newJson, undefined, 2), "utf-8" ); } function compareSolcConfigs( oldConfig: SolcConfig, newConfig: SolcConfig ): boolean { return isEqual(oldConfig, newConfig); } async function getCurrentBuidlerVersion(): Promise<string> { const packageJson = await getPackageJson(); return packageJson.version; } async function compareBuidlerVersion( lastBuidlerVersion: string ): Promise<boolean> { const currentVersion = await getCurrentBuidlerVersion(); return lastBuidlerVersion === currentVersion; }