From 3faf29c29b49073af6c77e1bf1e4951fda5a9e43 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:13:52 -0800 Subject: [PATCH 01/26] wip: add incremental mtime restore --- action.yml | 4 ++++ src/cleanup.ts | 59 ++++++++++++++++++++++++++++++++++------------ src/config.ts | 5 +++- src/incremental.ts | 48 +++++++++++++++++++++++++++++++++++++ src/restore.ts | 17 ++++++++++--- src/save.ts | 4 ++-- 6 files changed, 116 insertions(+), 21 deletions(-) create mode 100644 src/incremental.ts diff --git a/action.yml b/action.yml index cb4c157..0f1b024 100644 --- a/action.yml +++ b/action.yml @@ -48,6 +48,10 @@ inputs: description: "Check if a cache entry exists without downloading the cache" required: false default: "false" + incremental: + description: "Determines whether to cache incremental builds - speeding up builds for more disk usage. Defaults to false." + required: false + default: "false" outputs: cache-hit: description: "A boolean value that indicates an exact match was found." diff --git a/src/cleanup.ts b/src/cleanup.ts index d84a9d5..19b0c74 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -7,7 +7,7 @@ import { CARGO_HOME } from "./config"; import { exists } from "./utils"; import { Packages } from "./workspace"; -export async function cleanTargetDir(targetDir: string, packages: Packages, checkTimestamp = false) { +export async function cleanTargetDir(targetDir: string, packages: Packages, checkTimestamp: boolean, incremental: boolean) { core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory @@ -21,18 +21,18 @@ export async function cleanTargetDir(targetDir: string, packages: Packages, chec try { if (isNestedTarget) { - await cleanTargetDir(dirName, packages, checkTimestamp); + await cleanTargetDir(dirName, packages, checkTimestamp, incremental); } else { - await cleanProfileTarget(dirName, packages, checkTimestamp); + await cleanProfileTarget(dirName, packages, checkTimestamp, incremental); } - } catch {} + } catch { } } else if (dirent.name !== "CACHEDIR.TAG") { await rm(dir.path, dirent); } } } -async function cleanProfileTarget(profileDir: string, packages: Packages, checkTimestamp = false) { +async function cleanProfileTarget(profileDir: string, packages: Packages, checkTimestamp: boolean, incremental: boolean) { core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested @@ -42,15 +42,44 @@ async function cleanProfileTarget(profileDir: string, packages: Packages, checkT try { // https://github.com/vertexclique/kaos/blob/9876f6c890339741cc5be4b7cb9df72baa5a6d79/src/cargo.rs#L25 // https://github.com/eupn/macrotest/blob/c4151a5f9f545942f4971980b5d264ebcd0b1d11/src/cargo.rs#L27 - cleanTargetDir(path.join(profileDir, "target"), packages, checkTimestamp); - } catch {} + cleanTargetDir(path.join(profileDir, "target"), packages, checkTimestamp, incremental); + } catch { } + try { // https://github.com/dtolnay/trybuild/blob/eec8ca6cb9b8f53d0caf1aa499d99df52cae8b40/src/cargo.rs#L50 - cleanTargetDir(path.join(profileDir, "trybuild"), packages, checkTimestamp); - } catch {} + cleanTargetDir(path.join(profileDir, "trybuild"), packages, checkTimestamp, incremental); + } catch { } // Delete everything else. - await rmExcept(profileDir, new Set(["target", "trybuild"]), checkTimestamp); + let except = new Set(["target", "trybuild"]); + + // Keep the incremental folder if incremental builds are enabled + if (incremental) { + except.add("incremental"); + + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = path.join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir: string) => { + const dirEntries = await fs.promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(path.join(dir, dirent.name)); + } else { + const fileName = path.join(dir, dirent.name); + const { mtime } = await fs.promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + + // Write the modified times to the incremental folder + const contents = JSON.stringify({ modifiedTimes }); + await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); + } + + await rmExcept(profileDir, except, checkTimestamp); return; } @@ -86,7 +115,7 @@ export async function getCargoBins(): Promise> { bins.add(bin); } } - } catch {} + } catch { } return bins; } @@ -117,7 +146,7 @@ export async function cleanRegistry(packages: Packages, crates = true) { const credentials = path.join(CARGO_HOME, ".cargo", "credentials.toml"); core.debug(`deleting "${credentials}"`); await fs.promises.unlink(credentials); - } catch {} + } catch { } // `.cargo/registry/index` let pkgSet = new Set(packages.map((p) => p.name)); @@ -229,7 +258,7 @@ export async function cleanGit(packages: Packages) { await rm(dir.path, dirent); } } - } catch {} + } catch { } // clean the checkouts try { @@ -250,7 +279,7 @@ export async function cleanGit(packages: Packages) { } } } - } catch {} + } catch { } } const ONE_WEEK = 7 * 24 * 3600 * 1000; @@ -302,7 +331,7 @@ async function rm(parent: string, dirent: fs.Dirent) { } else if (dirent.isDirectory()) { await io.rmRF(fileName); } - } catch {} + } catch { } } async function rmRF(dirName: string) { diff --git a/src/config.ts b/src/config.ts index 5104f5c..08a6490 100644 --- a/src/config.ts +++ b/src/config.ts @@ -34,6 +34,9 @@ export class CacheConfig { /** The cargo binaries present during main step */ public cargoBins: Array = []; + /** Whether to cache incremental builds */ + public incremental: boolean = false; + /** The prefix portion of the cache key */ private keyPrefix = ""; /** The rust version considered for the cache key */ @@ -43,7 +46,7 @@ export class CacheConfig { /** The files considered for the cache key */ private keyFiles: Array = []; - private constructor() {} + private constructor() { } /** * Constructs a [`CacheConfig`] with all the paths and keys. diff --git a/src/incremental.ts b/src/incremental.ts new file mode 100644 index 0000000..3b054f9 --- /dev/null +++ b/src/incremental.ts @@ -0,0 +1,48 @@ +import * as core from "@actions/core"; +import * as io from "@actions/io"; +import fs from "fs"; +import path from "path"; + +import { CARGO_HOME } from "./config"; +import { exists } from "./utils"; +import { Packages } from "./workspace"; + + +export async function restoreIncremental(targetDir: string) { + core.debug(`restoring incremental directory "${targetDir}"`); + + + let dir = await fs.promises.opendir(targetDir); + for await (const dirent of dir) { + if (dirent.isDirectory()) { + let dirName = path.join(dir.path, dirent.name); + // is it a profile dir, or a nested target dir? + let isNestedTarget = + (await exists(path.join(dirName, "CACHEDIR.TAG"))) || (await exists(path.join(dirName, ".rustc_info.json"))); + + try { + if (isNestedTarget) { + await restoreIncremental(dirName); + } else { + await restoreIncrementalProfile(dirName); + } restoreIncrementalProfile + } catch { } + } + } +} + +async function restoreIncrementalProfile(dirName: string) { + core.debug(`restoring incremental profile directory "${dirName}"`); + const incrementalJson = path.join(dirName, "incremental-restore.json"); + if (await exists(incrementalJson)) { + const contents = await fs.promises.readFile(incrementalJson, "utf8"); + const { modifiedTimes } = JSON.parse(contents); + + // Write the mtimes to all the files in the profile directory + for (const fileName of Object.keys(modifiedTimes)) { + const mtime = modifiedTimes[fileName]; + const filePath = path.join(dirName, fileName); + await fs.promises.utimes(filePath, new Date(mtime), new Date(mtime)); + } + } +} diff --git a/src/restore.ts b/src/restore.ts index 21af56f..c02c2f0 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -3,6 +3,7 @@ import * as core from "@actions/core"; import { cleanTargetDir } from "./cleanup"; import { CacheConfig } from "./config"; import { getCacheProvider, reportError } from "./utils"; +import { restoreIncremental } from "./incremental"; process.on("uncaughtException", (e) => { core.error(e.message); @@ -27,12 +28,15 @@ async function run() { var lookupOnly = core.getInput("lookup-only").toLowerCase() === "true"; core.exportVariable("CACHE_ON_FAILURE", cacheOnFailure); - core.exportVariable("CARGO_INCREMENTAL", 0); const config = await CacheConfig.new(); config.printInfo(cacheProvider); core.info(""); + if (!config.incremental) { + core.exportVariable("CARGO_INCREMENTAL", 0); + } + core.info(`... ${lookupOnly ? "Checking" : "Restoring"} cache ...`); const key = config.cacheKey; // Pass a copy of cachePaths to avoid mutating the original array as reported by: @@ -44,12 +48,19 @@ async function run() { if (restoreKey) { const match = restoreKey === key; core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); + + if (config.incremental) { + for (const workspace of config.workspaces) { + await restoreIncremental(workspace.target); + } + } + if (!match) { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { - await cleanTargetDir(workspace.target, [], true); - } catch {} + await cleanTargetDir(workspace.target, [], true, false); + } catch { } } // We restored the cache but it is not a full match. diff --git a/src/save.ts b/src/save.ts index a62019e..d199328 100644 --- a/src/save.ts +++ b/src/save.ts @@ -42,7 +42,7 @@ async function run() { allPackages.push(...packages); try { core.info(`... Cleaning ${workspace.target} ...`); - await cleanTargetDir(workspace.target, packages); + await cleanTargetDir(workspace.target, packages, false, config.incremental); } catch (e) { core.debug(`${(e as any).stack}`); } @@ -90,5 +90,5 @@ async function macOsWorkaround() { // Workaround for https://github.com/actions/cache/issues/403 // Also see https://github.com/rust-lang/cargo/issues/8603 await exec.exec("sudo", ["/usr/sbin/purge"], { silent: true }); - } catch {} + } catch { } } From 3c291936b0189d337306dc8fc2f9feed695e3cf4 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:22:39 -0800 Subject: [PATCH 02/26] add logging --- src/incremental.ts | 2 ++ src/restore.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/src/incremental.ts b/src/incremental.ts index 3b054f9..98ec46c 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -38,6 +38,8 @@ async function restoreIncrementalProfile(dirName: string) { const contents = await fs.promises.readFile(incrementalJson, "utf8"); const { modifiedTimes } = JSON.parse(contents); + core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); + // Write the mtimes to all the files in the profile directory for (const fileName of Object.keys(modifiedTimes)) { const mtime = modifiedTimes[fileName]; diff --git a/src/restore.ts b/src/restore.ts index c02c2f0..bc8c274 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -50,6 +50,7 @@ async function run() { core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); if (config.incremental) { + core.debug("restoring incremental builds"); for (const workspace of config.workspaces) { await restoreIncremental(workspace.target); } From 046710c449bd475232d601cd5e8339b95c640b51 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:24:39 -0800 Subject: [PATCH 03/26] add incremental flag to constructor --- src/config.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config.ts b/src/config.ts index 08a6490..c71db36 100644 --- a/src/config.ts +++ b/src/config.ts @@ -62,6 +62,8 @@ export class CacheConfig { let key = core.getInput("prefix-key") || "v0-rust"; + self.incremental = core.getInput("incremental").toLowerCase() == "true"; + const sharedKey = core.getInput("shared-key"); if (sharedKey) { key += `-${sharedKey}`; From c9276fc739365f9317d411bcf32ca8dea3d39142 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:38:08 -0800 Subject: [PATCH 04/26] make sure to invalidate cache --- src/config.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index c71db36..f1102d6 100644 --- a/src/config.ts +++ b/src/config.ts @@ -62,7 +62,7 @@ export class CacheConfig { let key = core.getInput("prefix-key") || "v0-rust"; - self.incremental = core.getInput("incremental").toLowerCase() == "true"; + const sharedKey = core.getInput("shared-key"); if (sharedKey) { @@ -124,6 +124,10 @@ export class CacheConfig { self.restoreKey = key; + // Make sure we consider incremental builds + self.incremental = core.getInput("incremental").toLowerCase() == "true"; + hasher.update(`incremental=${self.incremental}`); + // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. From debe4b4f36aa52cfca73e5352d2e0ce5333a47d8 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:42:45 -0800 Subject: [PATCH 05/26] add logging re incremnetal --- src/config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config.ts b/src/config.ts index f1102d6..c72f5dd 100644 --- a/src/config.ts +++ b/src/config.ts @@ -330,6 +330,7 @@ export class CacheConfig { for (const file of this.keyFiles) { core.info(` - ${file}`); } + core.info(`.. Incremental: ${this.incremental}`); core.endGroup(); } From 9fdf1295a57a8945c73f6318d29312d746840cca Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:49:43 -0800 Subject: [PATCH 06/26] damn im dumb, commit the js --- dist/restore/index.js | 103 ++++++++++++++++++++++++++++++++++++++---- dist/save/index.js | 47 +++++++++++++++---- src/incremental.ts | 6 +-- 3 files changed, 136 insertions(+), 20 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index ea98ed1..6bd0736 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86721,6 +86721,8 @@ class CacheConfig { this.workspaces = []; /** The cargo binaries present during main step */ this.cargoBins = []; + /** Whether to cache incremental builds */ + this.incremental = false; /** The prefix portion of the cache key */ this.keyPrefix = ""; /** The rust version considered for the cache key */ @@ -86789,6 +86791,9 @@ class CacheConfig { self.keyEnvs = keyEnvs; key += `-${digest(hasher)}`; self.restoreKey = key; + // Make sure we consider incremental builds + self.incremental = lib_core.getInput("incremental").toLowerCase() == "true"; + hasher.update(`incremental=${self.incremental}`); // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. @@ -86958,6 +86963,7 @@ class CacheConfig { for (const file of this.keyFiles) { lib_core.info(` - ${file}`); } + lib_core.info(`.. Incremental: ${this.incremental}`); lib_core.endGroup(); } /** @@ -87027,7 +87033,7 @@ function sort_and_uniq(a) { -async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { +async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) { lib_core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory let dir = await external_fs_default().promises.opendir(targetDir); @@ -87038,10 +87044,10 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); try { if (isNestedTarget) { - await cleanTargetDir(dirName, packages, checkTimestamp); + await cleanTargetDir(dirName, packages, checkTimestamp, incremental); } else { - await cleanProfileTarget(dirName, packages, checkTimestamp); + await cleanProfileTarget(dirName, packages, checkTimestamp, incremental); } } catch { } @@ -87051,7 +87057,7 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { } } } -async function cleanProfileTarget(profileDir, packages, checkTimestamp = false) { +async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremental) { lib_core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested // workspaces under `target/tests`. Notably, `target/tests/target` and @@ -87060,16 +87066,41 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp = false) try { // https://github.com/vertexclique/kaos/blob/9876f6c890339741cc5be4b7cb9df72baa5a6d79/src/cargo.rs#L25 // https://github.com/eupn/macrotest/blob/c4151a5f9f545942f4971980b5d264ebcd0b1d11/src/cargo.rs#L27 - cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp); + cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp, incremental); } catch { } try { // https://github.com/dtolnay/trybuild/blob/eec8ca6cb9b8f53d0caf1aa499d99df52cae8b40/src/cargo.rs#L50 - cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp); + cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp, incremental); } catch { } // Delete everything else. - await rmExcept(profileDir, new Set(["target", "trybuild"]), checkTimestamp); + let except = new Set(["target", "trybuild"]); + // Keep the incremental folder if incremental builds are enabled + if (incremental) { + except.add("incremental"); + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = external_path_default().join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir) => { + const dirEntries = await external_fs_default().promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(external_path_default().join(dir, dirent.name)); + } + else { + const fileName = external_path_default().join(dir, dirent.name); + const { mtime } = await external_fs_default().promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + // Write the modified times to the incremental folder + const contents = JSON.stringify({ modifiedTimes }); + await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); + } + await rmExcept(profileDir, except, checkTimestamp); return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); @@ -87309,11 +87340,57 @@ async function rmRF(dirName) { await io.rmRF(dirName); } +;// CONCATENATED MODULE: ./src/incremental.ts + +// import * as io from "@actions/io"; + + +// import { CARGO_HOME } from "./config"; + +// import { Packages } from "./workspace"; +async function restoreIncremental(targetDir) { + lib_core.debug(`restoring incremental directory "${targetDir}"`); + let dir = await external_fs_default().promises.opendir(targetDir); + for await (const dirent of dir) { + if (dirent.isDirectory()) { + let dirName = external_path_default().join(dir.path, dirent.name); + // is it a profile dir, or a nested target dir? + let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); + try { + if (isNestedTarget) { + await restoreIncremental(dirName); + } + else { + await restoreIncrementalProfile(dirName); + } + restoreIncrementalProfile; + } + catch { } + } + } +} +async function restoreIncrementalProfile(dirName) { + lib_core.debug(`restoring incremental profile directory "${dirName}"`); + const incrementalJson = external_path_default().join(dirName, "incremental-restore.json"); + if (await utils_exists(incrementalJson)) { + const contents = await external_fs_default().promises.readFile(incrementalJson, "utf8"); + const { modifiedTimes } = JSON.parse(contents); + lib_core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); + // Write the mtimes to all the files in the profile directory + for (const fileName of Object.keys(modifiedTimes)) { + const mtime = modifiedTimes[fileName]; + const filePath = external_path_default().join(dirName, fileName); + await external_fs_default().promises.utimes(filePath, new Date(mtime), new Date(mtime)); + } + } +} + ;// CONCATENATED MODULE: ./src/restore.ts + process.on("uncaughtException", (e) => { lib_core.error(e.message); if (e.stack) { @@ -87333,10 +87410,12 @@ async function run() { } var lookupOnly = lib_core.getInput("lookup-only").toLowerCase() === "true"; lib_core.exportVariable("CACHE_ON_FAILURE", cacheOnFailure); - lib_core.exportVariable("CARGO_INCREMENTAL", 0); const config = await CacheConfig.new(); config.printInfo(cacheProvider); lib_core.info(""); + if (!config.incremental) { + lib_core.exportVariable("CARGO_INCREMENTAL", 0); + } lib_core.info(`... ${lookupOnly ? "Checking" : "Restoring"} cache ...`); const key = config.cacheKey; // Pass a copy of cachePaths to avoid mutating the original array as reported by: @@ -87348,11 +87427,17 @@ async function run() { if (restoreKey) { const match = restoreKey === key; lib_core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); + if (config.incremental) { + lib_core.debug("restoring incremental builds"); + for (const workspace of config.workspaces) { + await restoreIncremental(workspace.target); + } + } if (!match) { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { - await cleanTargetDir(workspace.target, [], true); + await cleanTargetDir(workspace.target, [], true, false); } catch { } } diff --git a/dist/save/index.js b/dist/save/index.js index ea2ddfb..92a76fe 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -86721,6 +86721,8 @@ class CacheConfig { this.workspaces = []; /** The cargo binaries present during main step */ this.cargoBins = []; + /** Whether to cache incremental builds */ + this.incremental = false; /** The prefix portion of the cache key */ this.keyPrefix = ""; /** The rust version considered for the cache key */ @@ -86789,6 +86791,9 @@ class CacheConfig { self.keyEnvs = keyEnvs; key += `-${digest(hasher)}`; self.restoreKey = key; + // Make sure we consider incremental builds + self.incremental = core.getInput("incremental").toLowerCase() == "true"; + hasher.update(`incremental=${self.incremental}`); // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. @@ -86958,6 +86963,7 @@ class CacheConfig { for (const file of this.keyFiles) { core.info(` - ${file}`); } + core.info(`.. Incremental: ${this.incremental}`); core.endGroup(); } /** @@ -87027,7 +87033,7 @@ function sort_and_uniq(a) { -async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { +async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) { core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory let dir = await external_fs_default().promises.opendir(targetDir); @@ -87038,10 +87044,10 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { let isNestedTarget = (await exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await exists(external_path_default().join(dirName, ".rustc_info.json"))); try { if (isNestedTarget) { - await cleanTargetDir(dirName, packages, checkTimestamp); + await cleanTargetDir(dirName, packages, checkTimestamp, incremental); } else { - await cleanProfileTarget(dirName, packages, checkTimestamp); + await cleanProfileTarget(dirName, packages, checkTimestamp, incremental); } } catch { } @@ -87051,7 +87057,7 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { } } } -async function cleanProfileTarget(profileDir, packages, checkTimestamp = false) { +async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremental) { core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested // workspaces under `target/tests`. Notably, `target/tests/target` and @@ -87060,16 +87066,41 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp = false) try { // https://github.com/vertexclique/kaos/blob/9876f6c890339741cc5be4b7cb9df72baa5a6d79/src/cargo.rs#L25 // https://github.com/eupn/macrotest/blob/c4151a5f9f545942f4971980b5d264ebcd0b1d11/src/cargo.rs#L27 - cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp); + cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp, incremental); } catch { } try { // https://github.com/dtolnay/trybuild/blob/eec8ca6cb9b8f53d0caf1aa499d99df52cae8b40/src/cargo.rs#L50 - cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp); + cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp, incremental); } catch { } // Delete everything else. - await rmExcept(profileDir, new Set(["target", "trybuild"]), checkTimestamp); + let except = new Set(["target", "trybuild"]); + // Keep the incremental folder if incremental builds are enabled + if (incremental) { + except.add("incremental"); + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = external_path_default().join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir) => { + const dirEntries = await external_fs_default().promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(external_path_default().join(dir, dirent.name)); + } + else { + const fileName = external_path_default().join(dir, dirent.name); + const { mtime } = await external_fs_default().promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + // Write the modified times to the incremental folder + const contents = JSON.stringify({ modifiedTimes }); + await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); + } + await rmExcept(profileDir, except, checkTimestamp); return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); @@ -87345,7 +87376,7 @@ async function run() { allPackages.push(...packages); try { core.info(`... Cleaning ${workspace.target} ...`); - await cleanTargetDir(workspace.target, packages); + await cleanTargetDir(workspace.target, packages, false, config.incremental); } catch (e) { core.debug(`${e.stack}`); diff --git a/src/incremental.ts b/src/incremental.ts index 98ec46c..0a5fed1 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -1,11 +1,11 @@ import * as core from "@actions/core"; -import * as io from "@actions/io"; +// import * as io from "@actions/io"; import fs from "fs"; import path from "path"; -import { CARGO_HOME } from "./config"; +// import { CARGO_HOME } from "./config"; import { exists } from "./utils"; -import { Packages } from "./workspace"; +// import { Packages } from "./workspace"; export async function restoreIncremental(targetDir: string) { From acd529160669df0dbd48a55a92cd638ca459d7b6 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:52:29 -0800 Subject: [PATCH 07/26] dist --- dist/restore/index.js | 906 +++++++++++++++++++++--------------------- src/config.ts | 8 +- 2 files changed, 458 insertions(+), 456 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 6bd0736..0653655 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -49931,457 +49931,457 @@ module.exports = toNumber /***/ 1860: /***/ ((module) => { -/****************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ -/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */ -var __extends; -var __assign; -var __rest; -var __decorate; -var __param; -var __esDecorate; -var __runInitializers; -var __propKey; -var __setFunctionName; -var __metadata; -var __awaiter; -var __generator; -var __exportStar; -var __values; -var __read; -var __spread; -var __spreadArrays; -var __spreadArray; -var __await; -var __asyncGenerator; -var __asyncDelegator; -var __asyncValues; -var __makeTemplateObject; -var __importStar; -var __importDefault; -var __classPrivateFieldGet; -var __classPrivateFieldSet; -var __classPrivateFieldIn; -var __createBinding; -var __addDisposableResource; -var __disposeResources; -var __rewriteRelativeImportExtension; -(function (factory) { - var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; - if (typeof define === "function" && define.amd) { - define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); - } - else if ( true && typeof module.exports === "object") { - factory(createExporter(root, createExporter(module.exports))); - } - else { - factory(createExporter(root)); - } - function createExporter(exports, previous) { - if (exports !== root) { - if (typeof Object.create === "function") { - Object.defineProperty(exports, "__esModule", { value: true }); - } - else { - exports.__esModule = true; - } - } - return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; - } -}) -(function (exporter) { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - - __extends = function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - - __assign = Object.assign || function (t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; - }; - - __rest = function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; - }; - - __decorate = function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; - }; - - __param = function (paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } - }; - - __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { - function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } - var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; - var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; - var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); - var _, done = false; - for (var i = decorators.length - 1; i >= 0; i--) { - var context = {}; - for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; - for (var p in contextIn.access) context.access[p] = contextIn.access[p]; - context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; - var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); - if (kind === "accessor") { - if (result === void 0) continue; - if (result === null || typeof result !== "object") throw new TypeError("Object expected"); - if (_ = accept(result.get)) descriptor.get = _; - if (_ = accept(result.set)) descriptor.set = _; - if (_ = accept(result.init)) initializers.unshift(_); - } - else if (_ = accept(result)) { - if (kind === "field") initializers.unshift(_); - else descriptor[key] = _; - } - } - if (target) Object.defineProperty(target, contextIn.name, descriptor); - done = true; - }; - - __runInitializers = function (thisArg, initializers, value) { - var useValue = arguments.length > 2; - for (var i = 0; i < initializers.length; i++) { - value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); - } - return useValue ? value : void 0; - }; - - __propKey = function (x) { - return typeof x === "symbol" ? x : "".concat(x); - }; - - __setFunctionName = function (f, name, prefix) { - if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; - return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); - }; - - __metadata = function (metadataKey, metadataValue) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); - }; - - __awaiter = function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - }; - - __generator = function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } - }; - - __exportStar = function(m, o) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); - }; - - __createBinding = Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); - }) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; - }); - - __values = function (o) { - var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; - if (m) return m.call(o); - if (o && typeof o.length === "number") return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; - throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); - }; - - __read = function (o, n) { - var m = typeof Symbol === "function" && o[Symbol.iterator]; - if (!m) return o; - var i = m.call(o), r, ar = [], e; - try { - while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); - } - catch (error) { e = { error: error }; } - finally { - try { - if (r && !r.done && (m = i["return"])) m.call(i); - } - finally { if (e) throw e.error; } - } - return ar; - }; - - /** @deprecated */ - __spread = function () { - for (var ar = [], i = 0; i < arguments.length; i++) - ar = ar.concat(__read(arguments[i])); - return ar; - }; - - /** @deprecated */ - __spreadArrays = function () { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j]; - return r; - }; - - __spreadArray = function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; - - __await = function (v) { - return this instanceof __await ? (this.v = v, this) : new __await(v); - }; - - __asyncGenerator = function (thisArg, _arguments, generator) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; - function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } - function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } - function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } - function fulfill(value) { resume("next", value); } - function reject(value) { resume("throw", value); } - function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } - }; - - __asyncDelegator = function (o) { - var i, p; - return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } - }; - - __asyncValues = function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } - }; - - __makeTemplateObject = function (cooked, raw) { - if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } - return cooked; - }; - - var __setModuleDefault = Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - }) : function(o, v) { - o["default"] = v; - }; - - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - - __importStar = function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; - - __importDefault = function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; - }; - - __classPrivateFieldGet = function (receiver, state, kind, f) { - if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); - if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); - return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); - }; - - __classPrivateFieldSet = function (receiver, state, value, kind, f) { - if (kind === "m") throw new TypeError("Private method is not writable"); - if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); - if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); - return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; - }; - - __classPrivateFieldIn = function (state, receiver) { - if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); - return typeof state === "function" ? receiver === state : state.has(receiver); - }; - - __addDisposableResource = function (env, value, async) { - if (value !== null && value !== void 0) { - if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); - var dispose, inner; - if (async) { - if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); - dispose = value[Symbol.asyncDispose]; - } - if (dispose === void 0) { - if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); - dispose = value[Symbol.dispose]; - if (async) inner = dispose; - } - if (typeof dispose !== "function") throw new TypeError("Object not disposable."); - if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; - env.stack.push({ value: value, dispose: dispose, async: async }); - } - else if (async) { - env.stack.push({ async: true }); - } - return value; - }; - - var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { - var e = new Error(message); - return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; - }; - - __disposeResources = function (env) { - function fail(e) { - env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; - env.hasError = true; - } - var r, s = 0; - function next() { - while (r = env.stack.pop()) { - try { - if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); - if (r.dispose) { - var result = r.dispose.call(r.value); - if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); - } - else s |= 1; - } - catch (e) { - fail(e); - } - } - if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); - if (env.hasError) throw env.error; - } - return next(); - }; - - __rewriteRelativeImportExtension = function (path, preserveJsx) { - if (typeof path === "string" && /^\.\.?\//.test(path)) { - return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { - return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); - }); - } - return path; - }; - - exporter("__extends", __extends); - exporter("__assign", __assign); - exporter("__rest", __rest); - exporter("__decorate", __decorate); - exporter("__param", __param); - exporter("__esDecorate", __esDecorate); - exporter("__runInitializers", __runInitializers); - exporter("__propKey", __propKey); - exporter("__setFunctionName", __setFunctionName); - exporter("__metadata", __metadata); - exporter("__awaiter", __awaiter); - exporter("__generator", __generator); - exporter("__exportStar", __exportStar); - exporter("__createBinding", __createBinding); - exporter("__values", __values); - exporter("__read", __read); - exporter("__spread", __spread); - exporter("__spreadArrays", __spreadArrays); - exporter("__spreadArray", __spreadArray); - exporter("__await", __await); - exporter("__asyncGenerator", __asyncGenerator); - exporter("__asyncDelegator", __asyncDelegator); - exporter("__asyncValues", __asyncValues); - exporter("__makeTemplateObject", __makeTemplateObject); - exporter("__importStar", __importStar); - exporter("__importDefault", __importDefault); - exporter("__classPrivateFieldGet", __classPrivateFieldGet); - exporter("__classPrivateFieldSet", __classPrivateFieldSet); - exporter("__classPrivateFieldIn", __classPrivateFieldIn); - exporter("__addDisposableResource", __addDisposableResource); - exporter("__disposeResources", __disposeResources); - exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension); -}); - -0 && (0); +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */ +var __extends; +var __assign; +var __rest; +var __decorate; +var __param; +var __esDecorate; +var __runInitializers; +var __propKey; +var __setFunctionName; +var __metadata; +var __awaiter; +var __generator; +var __exportStar; +var __values; +var __read; +var __spread; +var __spreadArrays; +var __spreadArray; +var __await; +var __asyncGenerator; +var __asyncDelegator; +var __asyncValues; +var __makeTemplateObject; +var __importStar; +var __importDefault; +var __classPrivateFieldGet; +var __classPrivateFieldSet; +var __classPrivateFieldIn; +var __createBinding; +var __addDisposableResource; +var __disposeResources; +var __rewriteRelativeImportExtension; +(function (factory) { + var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; + if (typeof define === "function" && define.amd) { + define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); + } + else if ( true && typeof module.exports === "object") { + factory(createExporter(root, createExporter(module.exports))); + } + else { + factory(createExporter(root)); + } + function createExporter(exports, previous) { + if (exports !== root) { + if (typeof Object.create === "function") { + Object.defineProperty(exports, "__esModule", { value: true }); + } + else { + exports.__esModule = true; + } + } + return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; + } +}) +(function (exporter) { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + + __extends = function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + + __assign = Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + + __rest = function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + }; + + __decorate = function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + }; + + __param = function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } + }; + + __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; + }; + + __runInitializers = function (thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; + }; + + __propKey = function (x) { + return typeof x === "symbol" ? x : "".concat(x); + }; + + __setFunctionName = function (f, name, prefix) { + if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; + return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); + }; + + __metadata = function (metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); + }; + + __awaiter = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + + __generator = function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + + __exportStar = function(m, o) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); + }; + + __createBinding = Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); + + __values = function (o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); + }; + + __read = function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + }; + + /** @deprecated */ + __spread = function () { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + }; + + /** @deprecated */ + __spreadArrays = function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + }; + + __spreadArray = function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); + }; + + __await = function (v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); + }; + + __asyncGenerator = function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } + }; + + __asyncDelegator = function (o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } + }; + + __asyncValues = function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } + }; + + __makeTemplateObject = function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; + }; + + var __setModuleDefault = Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }; + + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + + __importStar = function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + + __importDefault = function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + + __classPrivateFieldGet = function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + + __classPrivateFieldSet = function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + + __classPrivateFieldIn = function (state, receiver) { + if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); + return typeof state === "function" ? receiver === state : state.has(receiver); + }; + + __addDisposableResource = function (env, value, async) { + if (value !== null && value !== void 0) { + if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); + var dispose, inner; + if (async) { + if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); + dispose = value[Symbol.asyncDispose]; + } + if (dispose === void 0) { + if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); + dispose = value[Symbol.dispose]; + if (async) inner = dispose; + } + if (typeof dispose !== "function") throw new TypeError("Object not disposable."); + if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; + env.stack.push({ value: value, dispose: dispose, async: async }); + } + else if (async) { + env.stack.push({ async: true }); + } + return value; + }; + + var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; + + __disposeResources = function (env) { + function fail(e) { + env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; + env.hasError = true; + } + var r, s = 0; + function next() { + while (r = env.stack.pop()) { + try { + if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); + if (r.dispose) { + var result = r.dispose.call(r.value); + if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + else s |= 1; + } + catch (e) { + fail(e); + } + } + if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); + if (env.hasError) throw env.error; + } + return next(); + }; + + __rewriteRelativeImportExtension = function (path, preserveJsx) { + if (typeof path === "string" && /^\.\.?\//.test(path)) { + return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { + return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); + }); + } + return path; + }; + + exporter("__extends", __extends); + exporter("__assign", __assign); + exporter("__rest", __rest); + exporter("__decorate", __decorate); + exporter("__param", __param); + exporter("__esDecorate", __esDecorate); + exporter("__runInitializers", __runInitializers); + exporter("__propKey", __propKey); + exporter("__setFunctionName", __setFunctionName); + exporter("__metadata", __metadata); + exporter("__awaiter", __awaiter); + exporter("__generator", __generator); + exporter("__exportStar", __exportStar); + exporter("__createBinding", __createBinding); + exporter("__values", __values); + exporter("__read", __read); + exporter("__spread", __spread); + exporter("__spreadArrays", __spreadArrays); + exporter("__spreadArray", __spreadArray); + exporter("__await", __await); + exporter("__asyncGenerator", __asyncGenerator); + exporter("__asyncDelegator", __asyncDelegator); + exporter("__asyncValues", __asyncValues); + exporter("__makeTemplateObject", __makeTemplateObject); + exporter("__importStar", __importStar); + exporter("__importDefault", __importDefault); + exporter("__classPrivateFieldGet", __classPrivateFieldGet); + exporter("__classPrivateFieldSet", __classPrivateFieldSet); + exporter("__classPrivateFieldIn", __classPrivateFieldIn); + exporter("__addDisposableResource", __addDisposableResource); + exporter("__disposeResources", __disposeResources); + exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension); +}); + +0 && (0); /***/ }), @@ -86789,11 +86789,11 @@ class CacheConfig { } } self.keyEnvs = keyEnvs; - key += `-${digest(hasher)}`; - self.restoreKey = key; // Make sure we consider incremental builds self.incremental = lib_core.getInput("incremental").toLowerCase() == "true"; hasher.update(`incremental=${self.incremental}`); + key += `-${digest(hasher)}`; + self.restoreKey = key; // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. diff --git a/src/config.ts b/src/config.ts index c72f5dd..ab9d311 100644 --- a/src/config.ts +++ b/src/config.ts @@ -120,14 +120,16 @@ export class CacheConfig { self.keyEnvs = keyEnvs; - key += `-${digest(hasher)}`; - - self.restoreKey = key; // Make sure we consider incremental builds self.incremental = core.getInput("incremental").toLowerCase() == "true"; hasher.update(`incremental=${self.incremental}`); + key += `-${digest(hasher)}`; + + self.restoreKey = key; + + // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. From 3231cccddee9a2afbd6d3e11d66616336b5e84dd Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 18:53:15 -0800 Subject: [PATCH 08/26] dist --- dist/restore/index.js | 902 +++++++++++++++++++++--------------------- dist/save/index.js | 4 +- 2 files changed, 453 insertions(+), 453 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 0653655..97e47d5 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -49931,457 +49931,457 @@ module.exports = toNumber /***/ 1860: /***/ ((module) => { -/****************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ -/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */ -var __extends; -var __assign; -var __rest; -var __decorate; -var __param; -var __esDecorate; -var __runInitializers; -var __propKey; -var __setFunctionName; -var __metadata; -var __awaiter; -var __generator; -var __exportStar; -var __values; -var __read; -var __spread; -var __spreadArrays; -var __spreadArray; -var __await; -var __asyncGenerator; -var __asyncDelegator; -var __asyncValues; -var __makeTemplateObject; -var __importStar; -var __importDefault; -var __classPrivateFieldGet; -var __classPrivateFieldSet; -var __classPrivateFieldIn; -var __createBinding; -var __addDisposableResource; -var __disposeResources; -var __rewriteRelativeImportExtension; -(function (factory) { - var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; - if (typeof define === "function" && define.amd) { - define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); - } - else if ( true && typeof module.exports === "object") { - factory(createExporter(root, createExporter(module.exports))); - } - else { - factory(createExporter(root)); - } - function createExporter(exports, previous) { - if (exports !== root) { - if (typeof Object.create === "function") { - Object.defineProperty(exports, "__esModule", { value: true }); - } - else { - exports.__esModule = true; - } - } - return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; - } -}) -(function (exporter) { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - - __extends = function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - - __assign = Object.assign || function (t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; - }; - - __rest = function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; - }; - - __decorate = function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; - }; - - __param = function (paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } - }; - - __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { - function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } - var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; - var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; - var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); - var _, done = false; - for (var i = decorators.length - 1; i >= 0; i--) { - var context = {}; - for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; - for (var p in contextIn.access) context.access[p] = contextIn.access[p]; - context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; - var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); - if (kind === "accessor") { - if (result === void 0) continue; - if (result === null || typeof result !== "object") throw new TypeError("Object expected"); - if (_ = accept(result.get)) descriptor.get = _; - if (_ = accept(result.set)) descriptor.set = _; - if (_ = accept(result.init)) initializers.unshift(_); - } - else if (_ = accept(result)) { - if (kind === "field") initializers.unshift(_); - else descriptor[key] = _; - } - } - if (target) Object.defineProperty(target, contextIn.name, descriptor); - done = true; - }; - - __runInitializers = function (thisArg, initializers, value) { - var useValue = arguments.length > 2; - for (var i = 0; i < initializers.length; i++) { - value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); - } - return useValue ? value : void 0; - }; - - __propKey = function (x) { - return typeof x === "symbol" ? x : "".concat(x); - }; - - __setFunctionName = function (f, name, prefix) { - if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; - return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); - }; - - __metadata = function (metadataKey, metadataValue) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); - }; - - __awaiter = function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - }; - - __generator = function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } - }; - - __exportStar = function(m, o) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); - }; - - __createBinding = Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); - }) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; - }); - - __values = function (o) { - var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; - if (m) return m.call(o); - if (o && typeof o.length === "number") return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; - throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); - }; - - __read = function (o, n) { - var m = typeof Symbol === "function" && o[Symbol.iterator]; - if (!m) return o; - var i = m.call(o), r, ar = [], e; - try { - while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); - } - catch (error) { e = { error: error }; } - finally { - try { - if (r && !r.done && (m = i["return"])) m.call(i); - } - finally { if (e) throw e.error; } - } - return ar; - }; - - /** @deprecated */ - __spread = function () { - for (var ar = [], i = 0; i < arguments.length; i++) - ar = ar.concat(__read(arguments[i])); - return ar; - }; - - /** @deprecated */ - __spreadArrays = function () { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j]; - return r; - }; - - __spreadArray = function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; - - __await = function (v) { - return this instanceof __await ? (this.v = v, this) : new __await(v); - }; - - __asyncGenerator = function (thisArg, _arguments, generator) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; - function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } - function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } - function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } - function fulfill(value) { resume("next", value); } - function reject(value) { resume("throw", value); } - function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } - }; - - __asyncDelegator = function (o) { - var i, p; - return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } - }; - - __asyncValues = function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } - }; - - __makeTemplateObject = function (cooked, raw) { - if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } - return cooked; - }; - - var __setModuleDefault = Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - }) : function(o, v) { - o["default"] = v; - }; - - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - - __importStar = function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; - - __importDefault = function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; - }; - - __classPrivateFieldGet = function (receiver, state, kind, f) { - if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); - if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); - return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); - }; - - __classPrivateFieldSet = function (receiver, state, value, kind, f) { - if (kind === "m") throw new TypeError("Private method is not writable"); - if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); - if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); - return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; - }; - - __classPrivateFieldIn = function (state, receiver) { - if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); - return typeof state === "function" ? receiver === state : state.has(receiver); - }; - - __addDisposableResource = function (env, value, async) { - if (value !== null && value !== void 0) { - if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); - var dispose, inner; - if (async) { - if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); - dispose = value[Symbol.asyncDispose]; - } - if (dispose === void 0) { - if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); - dispose = value[Symbol.dispose]; - if (async) inner = dispose; - } - if (typeof dispose !== "function") throw new TypeError("Object not disposable."); - if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; - env.stack.push({ value: value, dispose: dispose, async: async }); - } - else if (async) { - env.stack.push({ async: true }); - } - return value; - }; - - var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { - var e = new Error(message); - return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; - }; - - __disposeResources = function (env) { - function fail(e) { - env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; - env.hasError = true; - } - var r, s = 0; - function next() { - while (r = env.stack.pop()) { - try { - if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); - if (r.dispose) { - var result = r.dispose.call(r.value); - if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); - } - else s |= 1; - } - catch (e) { - fail(e); - } - } - if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); - if (env.hasError) throw env.error; - } - return next(); - }; - - __rewriteRelativeImportExtension = function (path, preserveJsx) { - if (typeof path === "string" && /^\.\.?\//.test(path)) { - return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { - return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); - }); - } - return path; - }; - - exporter("__extends", __extends); - exporter("__assign", __assign); - exporter("__rest", __rest); - exporter("__decorate", __decorate); - exporter("__param", __param); - exporter("__esDecorate", __esDecorate); - exporter("__runInitializers", __runInitializers); - exporter("__propKey", __propKey); - exporter("__setFunctionName", __setFunctionName); - exporter("__metadata", __metadata); - exporter("__awaiter", __awaiter); - exporter("__generator", __generator); - exporter("__exportStar", __exportStar); - exporter("__createBinding", __createBinding); - exporter("__values", __values); - exporter("__read", __read); - exporter("__spread", __spread); - exporter("__spreadArrays", __spreadArrays); - exporter("__spreadArray", __spreadArray); - exporter("__await", __await); - exporter("__asyncGenerator", __asyncGenerator); - exporter("__asyncDelegator", __asyncDelegator); - exporter("__asyncValues", __asyncValues); - exporter("__makeTemplateObject", __makeTemplateObject); - exporter("__importStar", __importStar); - exporter("__importDefault", __importDefault); - exporter("__classPrivateFieldGet", __classPrivateFieldGet); - exporter("__classPrivateFieldSet", __classPrivateFieldSet); - exporter("__classPrivateFieldIn", __classPrivateFieldIn); - exporter("__addDisposableResource", __addDisposableResource); - exporter("__disposeResources", __disposeResources); - exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension); -}); - -0 && (0); +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */ +var __extends; +var __assign; +var __rest; +var __decorate; +var __param; +var __esDecorate; +var __runInitializers; +var __propKey; +var __setFunctionName; +var __metadata; +var __awaiter; +var __generator; +var __exportStar; +var __values; +var __read; +var __spread; +var __spreadArrays; +var __spreadArray; +var __await; +var __asyncGenerator; +var __asyncDelegator; +var __asyncValues; +var __makeTemplateObject; +var __importStar; +var __importDefault; +var __classPrivateFieldGet; +var __classPrivateFieldSet; +var __classPrivateFieldIn; +var __createBinding; +var __addDisposableResource; +var __disposeResources; +var __rewriteRelativeImportExtension; +(function (factory) { + var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; + if (typeof define === "function" && define.amd) { + define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); + } + else if ( true && typeof module.exports === "object") { + factory(createExporter(root, createExporter(module.exports))); + } + else { + factory(createExporter(root)); + } + function createExporter(exports, previous) { + if (exports !== root) { + if (typeof Object.create === "function") { + Object.defineProperty(exports, "__esModule", { value: true }); + } + else { + exports.__esModule = true; + } + } + return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; + } +}) +(function (exporter) { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + + __extends = function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + + __assign = Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + + __rest = function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + }; + + __decorate = function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + }; + + __param = function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } + }; + + __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; + }; + + __runInitializers = function (thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; + }; + + __propKey = function (x) { + return typeof x === "symbol" ? x : "".concat(x); + }; + + __setFunctionName = function (f, name, prefix) { + if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; + return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); + }; + + __metadata = function (metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); + }; + + __awaiter = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + + __generator = function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + + __exportStar = function(m, o) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); + }; + + __createBinding = Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); + + __values = function (o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); + }; + + __read = function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + }; + + /** @deprecated */ + __spread = function () { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + }; + + /** @deprecated */ + __spreadArrays = function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + }; + + __spreadArray = function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); + }; + + __await = function (v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); + }; + + __asyncGenerator = function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } + }; + + __asyncDelegator = function (o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } + }; + + __asyncValues = function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } + }; + + __makeTemplateObject = function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; + }; + + var __setModuleDefault = Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }; + + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + + __importStar = function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + + __importDefault = function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + + __classPrivateFieldGet = function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + + __classPrivateFieldSet = function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + + __classPrivateFieldIn = function (state, receiver) { + if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); + return typeof state === "function" ? receiver === state : state.has(receiver); + }; + + __addDisposableResource = function (env, value, async) { + if (value !== null && value !== void 0) { + if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); + var dispose, inner; + if (async) { + if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); + dispose = value[Symbol.asyncDispose]; + } + if (dispose === void 0) { + if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); + dispose = value[Symbol.dispose]; + if (async) inner = dispose; + } + if (typeof dispose !== "function") throw new TypeError("Object not disposable."); + if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; + env.stack.push({ value: value, dispose: dispose, async: async }); + } + else if (async) { + env.stack.push({ async: true }); + } + return value; + }; + + var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; + + __disposeResources = function (env) { + function fail(e) { + env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; + env.hasError = true; + } + var r, s = 0; + function next() { + while (r = env.stack.pop()) { + try { + if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); + if (r.dispose) { + var result = r.dispose.call(r.value); + if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + else s |= 1; + } + catch (e) { + fail(e); + } + } + if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); + if (env.hasError) throw env.error; + } + return next(); + }; + + __rewriteRelativeImportExtension = function (path, preserveJsx) { + if (typeof path === "string" && /^\.\.?\//.test(path)) { + return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { + return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); + }); + } + return path; + }; + + exporter("__extends", __extends); + exporter("__assign", __assign); + exporter("__rest", __rest); + exporter("__decorate", __decorate); + exporter("__param", __param); + exporter("__esDecorate", __esDecorate); + exporter("__runInitializers", __runInitializers); + exporter("__propKey", __propKey); + exporter("__setFunctionName", __setFunctionName); + exporter("__metadata", __metadata); + exporter("__awaiter", __awaiter); + exporter("__generator", __generator); + exporter("__exportStar", __exportStar); + exporter("__createBinding", __createBinding); + exporter("__values", __values); + exporter("__read", __read); + exporter("__spread", __spread); + exporter("__spreadArrays", __spreadArrays); + exporter("__spreadArray", __spreadArray); + exporter("__await", __await); + exporter("__asyncGenerator", __asyncGenerator); + exporter("__asyncDelegator", __asyncDelegator); + exporter("__asyncValues", __asyncValues); + exporter("__makeTemplateObject", __makeTemplateObject); + exporter("__importStar", __importStar); + exporter("__importDefault", __importDefault); + exporter("__classPrivateFieldGet", __classPrivateFieldGet); + exporter("__classPrivateFieldSet", __classPrivateFieldSet); + exporter("__classPrivateFieldIn", __classPrivateFieldIn); + exporter("__addDisposableResource", __addDisposableResource); + exporter("__disposeResources", __disposeResources); + exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension); +}); + +0 && (0); /***/ }), diff --git a/dist/save/index.js b/dist/save/index.js index 92a76fe..4f2df23 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -86789,11 +86789,11 @@ class CacheConfig { } } self.keyEnvs = keyEnvs; - key += `-${digest(hasher)}`; - self.restoreKey = key; // Make sure we consider incremental builds self.incremental = core.getInput("incremental").toLowerCase() == "true"; hasher.update(`incremental=${self.incremental}`); + key += `-${digest(hasher)}`; + self.restoreKey = key; // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. From 0381560ff996e69033ce81ee7cb6bce8eaea2453 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 19:03:35 -0800 Subject: [PATCH 09/26] move target clean --- dist/restore/index.js | 54 +++++++++++++++++++-------------------- dist/save/index.js | 52 +++++++++++++++++++------------------- src/cleanup.ts | 59 +++++++++++++++++++++---------------------- src/restore.ts | 2 +- 4 files changed, 83 insertions(+), 84 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 97e47d5..697c5dc 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -87075,35 +87075,35 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen } catch { } // Delete everything else. - let except = new Set(["target", "trybuild"]); - // Keep the incremental folder if incremental builds are enabled - if (incremental) { - except.add("incremental"); - // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = external_path_default().join(profileDir, "incremental"); - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir) => { - const dirEntries = await external_fs_default().promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(external_path_default().join(dir, dirent.name)); - } - else { - const fileName = external_path_default().join(dir, dirent.name); - const { mtime } = await external_fs_default().promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); - // Write the modified times to the incremental folder - const contents = JSON.stringify({ modifiedTimes }); - await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); - } - await rmExcept(profileDir, except, checkTimestamp); + await rmExcept(profileDir, new Set(["target", "trybuild"]), checkTimestamp); return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); + // Keep the incremental folder if incremental builds are enabled + if (incremental) { + keepProfile.add("incremental"); + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = external_path_default().join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir) => { + const dirEntries = await external_fs_default().promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(external_path_default().join(dir, dirent.name)); + } + else { + const fileName = external_path_default().join(dir, dirent.name); + const { mtime } = await external_fs_default().promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + // Write the modified times to the incremental folder + lib_core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); + const contents = JSON.stringify({ modifiedTimes }); + await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); + } await rmExcept(profileDir, keepProfile); const keepPkg = new Set(packages.map((p) => p.name)); await rmExcept(external_path_default().join(profileDir, "build"), keepPkg, checkTimestamp); @@ -87437,7 +87437,7 @@ async function run() { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { - await cleanTargetDir(workspace.target, [], true, false); + await cleanTargetDir(workspace.target, [], true, config.incremental); } catch { } } diff --git a/dist/save/index.js b/dist/save/index.js index 4f2df23..15ddf1e 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -87075,35 +87075,35 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen } catch { } // Delete everything else. - let except = new Set(["target", "trybuild"]); - // Keep the incremental folder if incremental builds are enabled - if (incremental) { - except.add("incremental"); - // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = external_path_default().join(profileDir, "incremental"); - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir) => { - const dirEntries = await external_fs_default().promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(external_path_default().join(dir, dirent.name)); - } - else { - const fileName = external_path_default().join(dir, dirent.name); - const { mtime } = await external_fs_default().promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); - // Write the modified times to the incremental folder - const contents = JSON.stringify({ modifiedTimes }); - await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); - } - await rmExcept(profileDir, except, checkTimestamp); + await rmExcept(profileDir, new Set(["target", "trybuild"]), checkTimestamp); return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); + // Keep the incremental folder if incremental builds are enabled + if (incremental) { + keepProfile.add("incremental"); + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = external_path_default().join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir) => { + const dirEntries = await external_fs_default().promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(external_path_default().join(dir, dirent.name)); + } + else { + const fileName = external_path_default().join(dir, dirent.name); + const { mtime } = await external_fs_default().promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + // Write the modified times to the incremental folder + core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); + const contents = JSON.stringify({ modifiedTimes }); + await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); + } await rmExcept(profileDir, keepProfile); const keepPkg = new Set(packages.map((p) => p.name)); await rmExcept(external_path_default().join(profileDir, "build"), keepPkg, checkTimestamp); diff --git a/src/cleanup.ts b/src/cleanup.ts index 19b0c74..85e6903 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -51,40 +51,39 @@ async function cleanProfileTarget(profileDir: string, packages: Packages, checkT } catch { } // Delete everything else. - let except = new Set(["target", "trybuild"]); - - // Keep the incremental folder if incremental builds are enabled - if (incremental) { - except.add("incremental"); - - // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = path.join(profileDir, "incremental"); - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir: string) => { - const dirEntries = await fs.promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(path.join(dir, dirent.name)); - } else { - const fileName = path.join(dir, dirent.name); - const { mtime } = await fs.promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); - - // Write the modified times to the incremental folder - const contents = JSON.stringify({ modifiedTimes }); - await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); - } - - await rmExcept(profileDir, except, checkTimestamp); - + await rmExcept(profileDir, new Set(["target", "trybuild"]), checkTimestamp); return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); + + // Keep the incremental folder if incremental builds are enabled + if (incremental) { + keepProfile.add("incremental"); + + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = path.join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir: string) => { + const dirEntries = await fs.promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(path.join(dir, dirent.name)); + } else { + const fileName = path.join(dir, dirent.name); + const { mtime } = await fs.promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + + // Write the modified times to the incremental folder + core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); + const contents = JSON.stringify({ modifiedTimes }); + await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); + } + await rmExcept(profileDir, keepProfile); const keepPkg = new Set(packages.map((p) => p.name)); diff --git a/src/restore.ts b/src/restore.ts index bc8c274..a1d8a5d 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -60,7 +60,7 @@ async function run() { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { - await cleanTargetDir(workspace.target, [], true, false); + await cleanTargetDir(workspace.target, [], true, config.incremental); } catch { } } From 36c8b73442fa295feec779b5c26f469e4517a2c9 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 19:22:56 -0800 Subject: [PATCH 10/26] cause save state if no incrementa.json --- dist/restore/index.js | 114 ++++++++++++++---------- dist/save/index.js | 203 ++++++++++++++++++++++++++++-------------- src/config.ts | 20 ++++- src/incremental.ts | 9 +- src/restore.ts | 2 +- 5 files changed, 229 insertions(+), 119 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 697c5dc..7adf64f 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86691,6 +86691,59 @@ class Workspace { } } +;// CONCATENATED MODULE: ./src/incremental.ts + +// import * as io from "@actions/io"; + + +// import { CARGO_HOME } from "./config"; + +// import { Packages } from "./workspace"; +let incremental_missing = false; +function isIncrementalMissing() { + return incremental_missing; +} +async function restoreIncremental(targetDir) { + lib_core.debug(`restoring incremental directory "${targetDir}"`); + let dir = await external_fs_default().promises.opendir(targetDir); + for await (const dirent of dir) { + if (dirent.isDirectory()) { + let dirName = external_path_default().join(dir.path, dirent.name); + // is it a profile dir, or a nested target dir? + let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); + try { + if (isNestedTarget) { + await restoreIncremental(dirName); + } + else { + await restoreIncrementalProfile(dirName); + } + restoreIncrementalProfile; + } + catch { } + } + } +} +async function restoreIncrementalProfile(dirName) { + lib_core.debug(`restoring incremental profile directory "${dirName}"`); + const incrementalJson = external_path_default().join(dirName, "incremental-restore.json"); + if (await utils_exists(incrementalJson)) { + const contents = await external_fs_default().promises.readFile(incrementalJson, "utf8"); + const { modifiedTimes } = JSON.parse(contents); + lib_core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); + // Write the mtimes to all the files in the profile directory + for (const fileName of Object.keys(modifiedTimes)) { + const mtime = modifiedTimes[fileName]; + const filePath = external_path_default().join(dirName, fileName); + await external_fs_default().promises.utimes(filePath, new Date(mtime), new Date(mtime)); + } + } + else { + lib_core.debug(`incremental-restore.json not found for ${dirName}`); + incremental_missing = true; + } +} + ;// CONCATENATED MODULE: ./src/config.ts @@ -86703,6 +86756,7 @@ class Workspace { + const HOME = external_os_default().homedir(); const config_CARGO_HOME = process.env.CARGO_HOME || external_path_default().join(HOME, ".cargo"); const STATE_CONFIG = "RUST_CACHE_CONFIG"; @@ -86911,6 +86965,13 @@ class CacheConfig { for (const dir of cacheDirectories.trim().split(/\s+/).filter(Boolean)) { self.cachePaths.push(dir); } + if (self.incremental) { + if (cacheTargets === "true") { + for (const target of self.workspaces.map((ws) => ws.target)) { + self.cachePaths.push(external_path_default().join(target, "incremental")); + } + } + } const bins = await getCargoBins(); self.cargoBins = Array.from(bins.values()); return self; @@ -86973,6 +87034,12 @@ class CacheConfig { saveState() { lib_core.saveState(STATE_CONFIG, this); } + isIncrementalMissing() { + if (this.incremental) { + return isIncrementalMissing(); + } + return false; + } } /** * Checks if the cache is up to date. @@ -87340,51 +87407,6 @@ async function rmRF(dirName) { await io.rmRF(dirName); } -;// CONCATENATED MODULE: ./src/incremental.ts - -// import * as io from "@actions/io"; - - -// import { CARGO_HOME } from "./config"; - -// import { Packages } from "./workspace"; -async function restoreIncremental(targetDir) { - lib_core.debug(`restoring incremental directory "${targetDir}"`); - let dir = await external_fs_default().promises.opendir(targetDir); - for await (const dirent of dir) { - if (dirent.isDirectory()) { - let dirName = external_path_default().join(dir.path, dirent.name); - // is it a profile dir, or a nested target dir? - let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); - try { - if (isNestedTarget) { - await restoreIncremental(dirName); - } - else { - await restoreIncrementalProfile(dirName); - } - restoreIncrementalProfile; - } - catch { } - } - } -} -async function restoreIncrementalProfile(dirName) { - lib_core.debug(`restoring incremental profile directory "${dirName}"`); - const incrementalJson = external_path_default().join(dirName, "incremental-restore.json"); - if (await utils_exists(incrementalJson)) { - const contents = await external_fs_default().promises.readFile(incrementalJson, "utf8"); - const { modifiedTimes } = JSON.parse(contents); - lib_core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); - // Write the mtimes to all the files in the profile directory - for (const fileName of Object.keys(modifiedTimes)) { - const mtime = modifiedTimes[fileName]; - const filePath = external_path_default().join(dirName, fileName); - await external_fs_default().promises.utimes(filePath, new Date(mtime), new Date(mtime)); - } - } -} - ;// CONCATENATED MODULE: ./src/restore.ts @@ -87433,7 +87455,7 @@ async function run() { await restoreIncremental(workspace.target); } } - if (!match) { + if (!match || config.isIncrementalMissing()) { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { diff --git a/dist/save/index.js b/dist/save/index.js index 15ddf1e..714a7c6 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -85430,7 +85430,7 @@ var __webpack_exports__ = {}; "use strict"; // EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js -var core = __nccwpck_require__(7484); +var lib_core = __nccwpck_require__(7484); // EXTERNAL MODULE: ./node_modules/@actions/exec/lib/exec.js var exec = __nccwpck_require__(5236); // EXTERNAL MODULE: ./node_modules/@actions/io/lib/io.js @@ -86601,11 +86601,11 @@ var cache_lib_cache = __nccwpck_require__(5116); function reportError(e) { const { commandFailed } = e; if (commandFailed) { - core.error(`Command failed: ${commandFailed.command}`); - core.error(commandFailed.stderr); + lib_core.error(`Command failed: ${commandFailed.command}`); + lib_core.error(commandFailed.stderr); } else { - core.error(`${e.stack}`); + lib_core.error(`${e.stack}`); } } async function getCmdOutput(cmd, args = [], options = {}) { @@ -86635,7 +86635,7 @@ async function getCmdOutput(cmd, args = [], options = {}) { return stdout; } function getCacheProvider() { - const cacheProvider = core.getInput("cache-provider"); + const cacheProvider = lib_core.getInput("cache-provider"); const cache = cacheProvider === "github" ? cache_lib_cache : cacheProvider === "buildjet" ? lib_cache : undefined; if (!cache) { throw new Error(`The \`cache-provider\` \`{cacheProvider}\` is not valid.`); @@ -86645,7 +86645,7 @@ function getCacheProvider() { cache: cache, }; } -async function exists(path) { +async function utils_exists(path) { try { await external_fs_default().promises.access(path); return true; @@ -86668,11 +86668,11 @@ class Workspace { async getPackages(filter, ...extraArgs) { let packages = []; try { - core.debug(`collecting metadata for "${this.root}"`); + lib_core.debug(`collecting metadata for "${this.root}"`); const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1", ...extraArgs], { cwd: this.root, })); - core.debug(`workspace "${this.root}" has ${meta.packages.length} packages`); + lib_core.debug(`workspace "${this.root}" has ${meta.packages.length} packages`); for (const pkg of meta.packages.filter(filter)) { const targets = pkg.targets.filter((t) => t.kind.some((kind) => SAVE_TARGETS.has(kind))).map((t) => t.name); packages.push({ name: pkg.name, version: pkg.version, targets, path: external_path_default().dirname(pkg.manifest_path) }); @@ -86691,6 +86691,59 @@ class Workspace { } } +;// CONCATENATED MODULE: ./src/incremental.ts + +// import * as io from "@actions/io"; + + +// import { CARGO_HOME } from "./config"; + +// import { Packages } from "./workspace"; +let incremental_missing = false; +function isIncrementalMissing() { + return incremental_missing; +} +async function restoreIncremental(targetDir) { + core.debug(`restoring incremental directory "${targetDir}"`); + let dir = await fs.promises.opendir(targetDir); + for await (const dirent of dir) { + if (dirent.isDirectory()) { + let dirName = path.join(dir.path, dirent.name); + // is it a profile dir, or a nested target dir? + let isNestedTarget = (await exists(path.join(dirName, "CACHEDIR.TAG"))) || (await exists(path.join(dirName, ".rustc_info.json"))); + try { + if (isNestedTarget) { + await restoreIncremental(dirName); + } + else { + await restoreIncrementalProfile(dirName); + } + restoreIncrementalProfile; + } + catch { } + } + } +} +async function restoreIncrementalProfile(dirName) { + core.debug(`restoring incremental profile directory "${dirName}"`); + const incrementalJson = path.join(dirName, "incremental-restore.json"); + if (await exists(incrementalJson)) { + const contents = await fs.promises.readFile(incrementalJson, "utf8"); + const { modifiedTimes } = JSON.parse(contents); + core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); + // Write the mtimes to all the files in the profile directory + for (const fileName of Object.keys(modifiedTimes)) { + const mtime = modifiedTimes[fileName]; + const filePath = path.join(dirName, fileName); + await fs.promises.utimes(filePath, new Date(mtime), new Date(mtime)); + } + } + else { + core.debug(`incremental-restore.json not found for ${dirName}`); + incremental_missing = true; + } +} + ;// CONCATENATED MODULE: ./src/config.ts @@ -86703,6 +86756,7 @@ class Workspace { + const HOME = external_os_default().homedir(); const CARGO_HOME = process.env.CARGO_HOME || external_path_default().join(HOME, ".cargo"); const STATE_CONFIG = "RUST_CACHE_CONFIG"; @@ -86742,13 +86796,13 @@ class CacheConfig { // Construct key prefix: // This uses either the `shared-key` input, // or the `key` input combined with the `job` key. - let key = core.getInput("prefix-key") || "v0-rust"; - const sharedKey = core.getInput("shared-key"); + let key = lib_core.getInput("prefix-key") || "v0-rust"; + const sharedKey = lib_core.getInput("shared-key"); if (sharedKey) { key += `-${sharedKey}`; } else { - const inputKey = core.getInput("key"); + const inputKey = lib_core.getInput("key"); if (inputKey) { key += `-${inputKey}`; } @@ -86776,7 +86830,7 @@ class CacheConfig { self.keyRust = keyRust; // these prefixes should cover most of the compiler / rust / cargo keys const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"]; - envPrefixes.push(...core.getInput("env-vars").split(/\s+/).filter(Boolean)); + envPrefixes.push(...lib_core.getInput("env-vars").split(/\s+/).filter(Boolean)); // sort the available env vars so we have a more stable hash const keyEnvs = []; const envKeys = Object.keys(process.env); @@ -86790,18 +86844,18 @@ class CacheConfig { } self.keyEnvs = keyEnvs; // Make sure we consider incremental builds - self.incremental = core.getInput("incremental").toLowerCase() == "true"; + self.incremental = lib_core.getInput("incremental").toLowerCase() == "true"; hasher.update(`incremental=${self.incremental}`); key += `-${digest(hasher)}`; self.restoreKey = key; // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. - self.cacheBin = core.getInput("cache-bin").toLowerCase() == "true"; + self.cacheBin = lib_core.getInput("cache-bin").toLowerCase() == "true"; // Constructs the workspace config and paths to restore: // The workspaces are given using a `$workspace -> $target` syntax. const workspaces = []; - const workspacesInput = core.getInput("workspaces") || "."; + const workspacesInput = lib_core.getInput("workspaces") || "."; for (const workspace of workspacesInput.trim().split("\n")) { let [root, target = "target"] = workspace.split("->").map((s) => s.trim()); root = external_path_default().resolve(root); @@ -86854,19 +86908,19 @@ class CacheConfig { } catch (e) { // Fallback to caching them as regular file - core.warning(`Error parsing Cargo.toml manifest, fallback to caching entire file: ${e}`); + lib_core.warning(`Error parsing Cargo.toml manifest, fallback to caching entire file: ${e}`); keyFiles.push(cargo_manifest); } } const cargo_lock = external_path_default().join(workspace.root, "Cargo.lock"); - if (await exists(cargo_lock)) { + if (await utils_exists(cargo_lock)) { try { const content = await promises_default().readFile(cargo_lock, { encoding: "utf8" }); const parsed = parse(content); if ((parsed.version !== 3 && parsed.version !== 4) || !("package" in parsed)) { // Fallback to caching them as regular file since this action // can only handle Cargo.lock format version 3 - core.warning("Unsupported Cargo.lock format, fallback to caching entire file"); + lib_core.warning("Unsupported Cargo.lock format, fallback to caching entire file"); keyFiles.push(cargo_lock); continue; } @@ -86878,7 +86932,7 @@ class CacheConfig { } catch (e) { // Fallback to caching them as regular file - core.warning(`Error parsing Cargo.lock manifest, fallback to caching entire file: ${e}`); + lib_core.warning(`Error parsing Cargo.lock manifest, fallback to caching entire file: ${e}`); keyFiles.push(cargo_lock); } } @@ -86903,14 +86957,21 @@ class CacheConfig { ...self.cachePaths, ]; } - const cacheTargets = core.getInput("cache-targets").toLowerCase() || "true"; + const cacheTargets = lib_core.getInput("cache-targets").toLowerCase() || "true"; if (cacheTargets === "true") { self.cachePaths.push(...workspaces.map((ws) => ws.target)); } - const cacheDirectories = core.getInput("cache-directories"); + const cacheDirectories = lib_core.getInput("cache-directories"); for (const dir of cacheDirectories.trim().split(/\s+/).filter(Boolean)) { self.cachePaths.push(dir); } + if (self.incremental) { + if (cacheTargets === "true") { + for (const target of self.workspaces.map((ws) => ws.target)) { + self.cachePaths.push(external_path_default().join(target, "incremental")); + } + } + } const bins = await getCargoBins(); self.cargoBins = Array.from(bins.values()); return self; @@ -86924,7 +86985,7 @@ class CacheConfig { * @see {@link CacheConfig#new} */ static fromState() { - const source = core.getState(STATE_CONFIG); + const source = lib_core.getState(STATE_CONFIG); if (!source) { throw new Error("Cache configuration not found in state"); } @@ -86937,41 +86998,47 @@ class CacheConfig { * Prints the configuration to the action log. */ printInfo(cacheProvider) { - core.startGroup("Cache Configuration"); - core.info(`Cache Provider:`); - core.info(` ${cacheProvider.name}`); - core.info(`Workspaces:`); + lib_core.startGroup("Cache Configuration"); + lib_core.info(`Cache Provider:`); + lib_core.info(` ${cacheProvider.name}`); + lib_core.info(`Workspaces:`); for (const workspace of this.workspaces) { - core.info(` ${workspace.root}`); + lib_core.info(` ${workspace.root}`); } - core.info(`Cache Paths:`); + lib_core.info(`Cache Paths:`); for (const path of this.cachePaths) { - core.info(` ${path}`); + lib_core.info(` ${path}`); } - core.info(`Restore Key:`); - core.info(` ${this.restoreKey}`); - core.info(`Cache Key:`); - core.info(` ${this.cacheKey}`); - core.info(`.. Prefix:`); - core.info(` - ${this.keyPrefix}`); - core.info(`.. Environment considered:`); - core.info(` - Rust Version: ${this.keyRust}`); + lib_core.info(`Restore Key:`); + lib_core.info(` ${this.restoreKey}`); + lib_core.info(`Cache Key:`); + lib_core.info(` ${this.cacheKey}`); + lib_core.info(`.. Prefix:`); + lib_core.info(` - ${this.keyPrefix}`); + lib_core.info(`.. Environment considered:`); + lib_core.info(` - Rust Version: ${this.keyRust}`); for (const env of this.keyEnvs) { - core.info(` - ${env}`); + lib_core.info(` - ${env}`); } - core.info(`.. Lockfiles considered:`); + lib_core.info(`.. Lockfiles considered:`); for (const file of this.keyFiles) { - core.info(` - ${file}`); + lib_core.info(` - ${file}`); } - core.info(`.. Incremental: ${this.incremental}`); - core.endGroup(); + lib_core.info(`.. Incremental: ${this.incremental}`); + lib_core.endGroup(); } /** * Saves the configuration to the state store. * This is used to restore the configuration in the post action. */ saveState() { - core.saveState(STATE_CONFIG, this); + lib_core.saveState(STATE_CONFIG, this); + } + isIncrementalMissing() { + if (this.incremental) { + return isIncrementalMissing(); + } + return false; } } /** @@ -86980,7 +87047,7 @@ class CacheConfig { * @returns `true` if the cache is up to date, `false` otherwise. */ function isCacheUpToDate() { - return core.getState(STATE_CONFIG) === ""; + return lib_core.getState(STATE_CONFIG) === ""; } /** * Returns a hex digest of the given hasher truncated to `HASH_LENGTH`. @@ -87034,14 +87101,14 @@ function sort_and_uniq(a) { async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) { - core.debug(`cleaning target directory "${targetDir}"`); + lib_core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory let dir = await external_fs_default().promises.opendir(targetDir); for await (const dirent of dir) { if (dirent.isDirectory()) { let dirName = external_path_default().join(dir.path, dirent.name); // is it a profile dir, or a nested target dir? - let isNestedTarget = (await exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await exists(external_path_default().join(dirName, ".rustc_info.json"))); + let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); try { if (isNestedTarget) { await cleanTargetDir(dirName, packages, checkTimestamp, incremental); @@ -87058,7 +87125,7 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) } } async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremental) { - core.debug(`cleaning profile directory "${profileDir}"`); + lib_core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested // workspaces under `target/tests`. Notably, `target/tests/target` and // `target/tests/trybuild`. @@ -87100,7 +87167,7 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen }; await fillModifiedTimes(incrementalDir); // Write the modified times to the incremental folder - core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); + lib_core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); const contents = JSON.stringify({ modifiedTimes }); await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); } @@ -87153,7 +87220,7 @@ async function cleanRegistry(packages, crates = true) { // remove `.cargo/credentials.toml` try { const credentials = external_path_default().join(CARGO_HOME, ".cargo", "credentials.toml"); - core.debug(`deleting "${credentials}"`); + lib_core.debug(`deleting "${credentials}"`); await external_fs_default().promises.unlink(credentials); } catch { } @@ -87166,7 +87233,7 @@ async function cleanRegistry(packages, crates = true) { // or `.cargo/registry/index/index.crates.io-e139d0d48fed7772` const dirPath = external_path_default().join(indexDir.path, dirent.name); // for a git registry, we can remove `.cache`, as cargo will recreate it from git - if (await exists(external_path_default().join(dirPath, ".git"))) { + if (await utils_exists(external_path_default().join(dirPath, ".git"))) { await rmRF(external_path_default().join(dirPath, ".cache")); } else { @@ -87175,7 +87242,7 @@ async function cleanRegistry(packages, crates = true) { } } if (!crates) { - core.debug("skipping registry cache and src cleanup"); + lib_core.debug("skipping registry cache and src cleanup"); return; } // `.cargo/registry/src` @@ -87325,7 +87392,7 @@ async function rmExcept(dirName, keepPrefix, checkTimestamp = false) { async function rm(parent, dirent) { try { const fileName = external_path_default().join(parent, dirent.name); - core.debug(`deleting "${fileName}"`); + lib_core.debug(`deleting "${fileName}"`); if (dirent.isFile()) { await external_fs_default().promises.unlink(fileName); } @@ -87336,7 +87403,7 @@ async function rm(parent, dirent) { catch { } } async function rmRF(dirName) { - core.debug(`deleting "${dirName}"`); + lib_core.debug(`deleting "${dirName}"`); await io.rmRF(dirName); } @@ -87347,25 +87414,25 @@ async function rmRF(dirName) { process.on("uncaughtException", (e) => { - core.error(e.message); + lib_core.error(e.message); if (e.stack) { - core.error(e.stack); + lib_core.error(e.stack); } }); async function run() { const cacheProvider = getCacheProvider(); - const save = core.getInput("save-if").toLowerCase() || "true"; + const save = lib_core.getInput("save-if").toLowerCase() || "true"; if (!(cacheProvider.cache.isFeatureAvailable() && save === "true")) { return; } try { if (isCacheUpToDate()) { - core.info(`Cache up-to-date.`); + lib_core.info(`Cache up-to-date.`); return; } const config = CacheConfig.fromState(); config.printInfo(cacheProvider); - core.info(""); + lib_core.info(""); // TODO: remove this once https://github.com/actions/toolkit/pull/553 lands if (process.env["RUNNER_OS"] == "macOS") { await macOsWorkaround(); @@ -87375,38 +87442,38 @@ async function run() { const packages = await workspace.getPackagesOutsideWorkspaceRoot(); allPackages.push(...packages); try { - core.info(`... Cleaning ${workspace.target} ...`); + lib_core.info(`... Cleaning ${workspace.target} ...`); await cleanTargetDir(workspace.target, packages, false, config.incremental); } catch (e) { - core.debug(`${e.stack}`); + lib_core.debug(`${e.stack}`); } } try { - const crates = core.getInput("cache-all-crates").toLowerCase() || "false"; - core.info(`... Cleaning cargo registry (cache-all-crates: ${crates}) ...`); + const crates = lib_core.getInput("cache-all-crates").toLowerCase() || "false"; + lib_core.info(`... Cleaning cargo registry (cache-all-crates: ${crates}) ...`); await cleanRegistry(allPackages, crates !== "true"); } catch (e) { - core.debug(`${e.stack}`); + lib_core.debug(`${e.stack}`); } if (config.cacheBin) { try { - core.info(`... Cleaning cargo/bin ...`); + lib_core.info(`... Cleaning cargo/bin ...`); await cleanBin(config.cargoBins); } catch (e) { - core.debug(`${e.stack}`); + lib_core.debug(`${e.stack}`); } } try { - core.info(`... Cleaning cargo git cache ...`); + lib_core.info(`... Cleaning cargo git cache ...`); await cleanGit(allPackages); } catch (e) { - core.debug(`${e.stack}`); + lib_core.debug(`${e.stack}`); } - core.info(`... Saving cache ...`); + lib_core.info(`... Saving cache ...`); // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. diff --git a/src/config.ts b/src/config.ts index ab9d311..ecec9c6 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,6 +10,7 @@ import * as toml from "smol-toml"; import { getCargoBins } from "./cleanup"; import { CacheProvider, exists, getCmdOutput } from "./utils"; import { Workspace } from "./workspace"; +import { isIncrementalMissing } from "./incremental"; const HOME = os.homedir(); export const CARGO_HOME = process.env.CARGO_HOME || path.join(HOME, ".cargo"); @@ -62,8 +63,6 @@ export class CacheConfig { let key = core.getInput("prefix-key") || "v0-rust"; - - const sharedKey = core.getInput("shared-key"); if (sharedKey) { key += `-${sharedKey}`; @@ -120,7 +119,6 @@ export class CacheConfig { self.keyEnvs = keyEnvs; - // Make sure we consider incremental builds self.incremental = core.getInput("incremental").toLowerCase() == "true"; hasher.update(`incremental=${self.incremental}`); @@ -275,6 +273,14 @@ export class CacheConfig { self.cachePaths.push(dir); } + if (self.incremental) { + if (cacheTargets === "true") { + for (const target of self.workspaces.map((ws) => ws.target)) { + self.cachePaths.push(path.join(target, "incremental")); + } + } + } + const bins = await getCargoBins(); self.cargoBins = Array.from(bins.values()); @@ -343,6 +349,14 @@ export class CacheConfig { saveState() { core.saveState(STATE_CONFIG, this); } + + isIncrementalMissing(): boolean { + if (this.incremental) { + return isIncrementalMissing(); + } + + return false; + } } /** diff --git a/src/incremental.ts b/src/incremental.ts index 0a5fed1..43303f0 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -7,11 +7,15 @@ import path from "path"; import { exists } from "./utils"; // import { Packages } from "./workspace"; +let incremental_missing = false; + +export function isIncrementalMissing(): boolean { + return incremental_missing; +} export async function restoreIncremental(targetDir: string) { core.debug(`restoring incremental directory "${targetDir}"`); - let dir = await fs.promises.opendir(targetDir); for await (const dirent of dir) { if (dirent.isDirectory()) { @@ -46,5 +50,8 @@ async function restoreIncrementalProfile(dirName: string) { const filePath = path.join(dirName, fileName); await fs.promises.utimes(filePath, new Date(mtime), new Date(mtime)); } + } else { + core.debug(`incremental-restore.json not found for ${dirName}`); + incremental_missing = true; } } diff --git a/src/restore.ts b/src/restore.ts index a1d8a5d..f592d26 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -56,7 +56,7 @@ async function run() { } } - if (!match) { + if (!match || config.isIncrementalMissing()) { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { From 2de18fd6ad9ce58daae1d82e04b3e24eb0ba0c2c Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 20:19:58 -0800 Subject: [PATCH 11/26] tack on incremental for incremental caches --- src/config.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config.ts b/src/config.ts index ecec9c6..706e6e2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -251,6 +251,10 @@ export class CacheConfig { keyFiles.push(...parsedKeyFiles); self.keyFiles = sort_and_uniq(keyFiles); + if (self.incremental) { + key += `-incremental`; + } + key += `-${lockHash}`; self.cacheKey = key; From 8c044fe7ccf98445e70dbfe6c66448b51a8adbb1 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 20:24:43 -0800 Subject: [PATCH 12/26] disambiguate incremental caches --- dist/restore/index.js | 11 ++++++++++- dist/save/index.js | 11 ++++++++++- src/config.ts | 8 +++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 7adf64f..05267ef 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86767,7 +86767,11 @@ class CacheConfig { this.cachePaths = []; /** The primary cache key */ this.cacheKey = ""; - /** The secondary (restore) key that only contains the prefix and environment */ + /** + * The secondary (restore) key that only contains the prefix and environment + * This should be used if the primary cacheKey is not available - IE pulling from main on a branch + * instead of the branch itself + * */ this.restoreKey = ""; /** Whether to cache CARGO_HOME/.bin */ this.cacheBin = true; @@ -86946,6 +86950,11 @@ class CacheConfig { let lockHash = digest(hasher); keyFiles.push(...parsedKeyFiles); self.keyFiles = sort_and_uniq(keyFiles); + // todo(jon): make sure we differentiate incrementals on different branches + // we can use just a single cache per incremental branch + if (self.incremental) { + key += `-incremental`; + } key += `-${lockHash}`; self.cacheKey = key; self.cachePaths = [external_path_default().join(config_CARGO_HOME, "registry"), external_path_default().join(config_CARGO_HOME, "git")]; diff --git a/dist/save/index.js b/dist/save/index.js index 714a7c6..9fb3841 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -86767,7 +86767,11 @@ class CacheConfig { this.cachePaths = []; /** The primary cache key */ this.cacheKey = ""; - /** The secondary (restore) key that only contains the prefix and environment */ + /** + * The secondary (restore) key that only contains the prefix and environment + * This should be used if the primary cacheKey is not available - IE pulling from main on a branch + * instead of the branch itself + * */ this.restoreKey = ""; /** Whether to cache CARGO_HOME/.bin */ this.cacheBin = true; @@ -86946,6 +86950,11 @@ class CacheConfig { let lockHash = digest(hasher); keyFiles.push(...parsedKeyFiles); self.keyFiles = sort_and_uniq(keyFiles); + // todo(jon): make sure we differentiate incrementals on different branches + // we can use just a single cache per incremental branch + if (self.incremental) { + key += `-incremental`; + } key += `-${lockHash}`; self.cacheKey = key; self.cachePaths = [external_path_default().join(CARGO_HOME, "registry"), external_path_default().join(CARGO_HOME, "git")]; diff --git a/src/config.ts b/src/config.ts index 706e6e2..ecae9fb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -23,7 +23,11 @@ export class CacheConfig { public cachePaths: Array = []; /** The primary cache key */ public cacheKey = ""; - /** The secondary (restore) key that only contains the prefix and environment */ + /** + * The secondary (restore) key that only contains the prefix and environment + * This should be used if the primary cacheKey is not available - IE pulling from main on a branch + * instead of the branch itself + * */ public restoreKey = ""; /** Whether to cache CARGO_HOME/.bin */ @@ -251,6 +255,8 @@ export class CacheConfig { keyFiles.push(...parsedKeyFiles); self.keyFiles = sort_and_uniq(keyFiles); + // todo(jon): make sure we differentiate incrementals on different branches + // we can use just a single cache per incremental branch if (self.incremental) { key += `-incremental`; } From af6c167d5db0f8285b4f464372fdfb5b0dc2537a Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 20:59:32 -0800 Subject: [PATCH 13/26] restore from secondary branch --- action.yml | 4 ++++ src/config.ts | 23 ++++++++++++++++------- src/restore.ts | 16 ++++++++++------ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/action.yml b/action.yml index 0f1b024..36b03c5 100644 --- a/action.yml +++ b/action.yml @@ -52,6 +52,10 @@ inputs: description: "Determines whether to cache incremental builds - speeding up builds for more disk usage. Defaults to false." required: false default: "false" + incremental-key: + description: "The key to use for incremental builds. Used on a per-branch basis" + required: false + default: ${{ github.ref }} outputs: cache-hit: description: "A boolean value that indicates an exact match was found." diff --git a/src/config.ts b/src/config.ts index ecae9fb..062e95e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -21,8 +21,16 @@ const HASH_LENGTH = 8; export class CacheConfig { /** All the paths we want to cache */ public cachePaths: Array = []; + + /** All the paths we want to cache for incremental builds */ + public incrementalPaths: Array = []; + /** The primary cache key */ public cacheKey = ""; + + /** The primary cache key for incremental builds */ + public incrementalKey = ""; + /** * The secondary (restore) key that only contains the prefix and environment * This should be used if the primary cacheKey is not available - IE pulling from main on a branch @@ -255,15 +263,16 @@ export class CacheConfig { keyFiles.push(...parsedKeyFiles); self.keyFiles = sort_and_uniq(keyFiles); - // todo(jon): make sure we differentiate incrementals on different branches - // we can use just a single cache per incremental branch - if (self.incremental) { - key += `-incremental`; - } - key += `-${lockHash}`; self.cacheKey = key; + if (self.incremental) { + // wire the incremental key to be just for this branch + const branchName = core.getInput("incremental-key") || "-shared"; + const incrementalKey = key + `-incremental` + branchName; + self.incrementalKey = incrementalKey; + } + self.cachePaths = [path.join(CARGO_HOME, "registry"), path.join(CARGO_HOME, "git")]; if (self.cacheBin) { self.cachePaths = [ @@ -286,7 +295,7 @@ export class CacheConfig { if (self.incremental) { if (cacheTargets === "true") { for (const target of self.workspaces.map((ws) => ws.target)) { - self.cachePaths.push(path.join(target, "incremental")); + self.incrementalPaths.push(path.join(target, "incremental")); } } } diff --git a/src/restore.ts b/src/restore.ts index f592d26..c459ca5 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -39,20 +39,24 @@ async function run() { core.info(`... ${lookupOnly ? "Checking" : "Restoring"} cache ...`); const key = config.cacheKey; + // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. - const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { - lookupOnly, - }); + const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { lookupOnly }); + if (restoreKey) { const match = restoreKey === key; core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); if (config.incremental) { - core.debug("restoring incremental builds"); - for (const workspace of config.workspaces) { - await restoreIncremental(workspace.target); + const incrementalKey = await cacheProvider.cache.restoreCache(config.incrementalPaths.slice(), config.incrementalKey, [config.restoreKey], { lookupOnly }); + core.debug(`restoring incremental builds from ${incrementalKey}`); + + if (incrementalKey) { + for (const workspace of config.workspaces) { + await restoreIncremental(workspace.target); + } } } From a0f80e7b74787ce3679013197617c69960c18e1e Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 21:00:55 -0800 Subject: [PATCH 14/26] save incrementals --- src/save.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/save.ts b/src/save.ts index d199328..78532fd 100644 --- a/src/save.ts +++ b/src/save.ts @@ -77,6 +77,11 @@ async function run() { // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. await cacheProvider.cache.saveCache(config.cachePaths.slice(), config.cacheKey); + + if (config.incremental) { + core.info(`... Saving incremental cache ...`); + await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); + } } catch (e) { reportError(e); } From 70758ffdc7fafcf0ff9ca2eb6017bce7a7665dcc Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 21:14:58 -0800 Subject: [PATCH 15/26] better logging, better staging --- src/cleanup.ts | 6 +++++- src/save.ts | 15 +++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/cleanup.ts b/src/cleanup.ts index 85e6903..b4700b1 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -79,11 +79,15 @@ async function cleanProfileTarget(profileDir: string, packages: Packages, checkT await fillModifiedTimes(incrementalDir); // Write the modified times to the incremental folder - core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); + core.debug(`writing incremental-restore.json for ${incrementalDir} files`); + for (const file of modifiedTimes.keys()) { + core.debug(` ${file} -> ${modifiedTimes.get(file)}`); + } const contents = JSON.stringify({ modifiedTimes }); await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); } + await rmExcept(profileDir, keepProfile); const keepPkg = new Set(packages.map((p) => p.name)); diff --git a/src/save.ts b/src/save.ts index 78532fd..b91beeb 100644 --- a/src/save.ts +++ b/src/save.ts @@ -4,6 +4,7 @@ import * as exec from "@actions/exec"; import { cleanBin, cleanGit, cleanRegistry, cleanTargetDir } from "./cleanup"; import { CacheConfig, isCacheUpToDate } from "./config"; import { getCacheProvider, reportError } from "./utils"; +import { rm } from "fs/promises"; process.on("uncaughtException", (e) => { core.error(e.message); @@ -72,16 +73,22 @@ async function run() { core.debug(`${(e as any).stack}`); } + // Save the incremental cache before we delete it + if (config.incremental) { + core.info(`... Saving incremental cache ...`); + await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); + for (const path of config.incrementalPaths) { + core.debug(` deleting ${path}`); + await rm(path); + } + } + core.info(`... Saving cache ...`); // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. await cacheProvider.cache.saveCache(config.cachePaths.slice(), config.cacheKey); - if (config.incremental) { - core.info(`... Saving incremental cache ...`); - await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); - } } catch (e) { reportError(e); } From 8c8c35255e3415a23bcd71a1d4d82396beb03523 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 21:27:46 -0800 Subject: [PATCH 16/26] bump js --- dist/restore/index.js | 35 ++++++++++++++++++++++------------- dist/save/index.js | 32 +++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 05267ef..41fe7f8 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86765,8 +86765,12 @@ class CacheConfig { constructor() { /** All the paths we want to cache */ this.cachePaths = []; + /** All the paths we want to cache for incremental builds */ + this.incrementalPaths = []; /** The primary cache key */ this.cacheKey = ""; + /** The primary cache key for incremental builds */ + this.incrementalKey = ""; /** * The secondary (restore) key that only contains the prefix and environment * This should be used if the primary cacheKey is not available - IE pulling from main on a branch @@ -86950,13 +86954,14 @@ class CacheConfig { let lockHash = digest(hasher); keyFiles.push(...parsedKeyFiles); self.keyFiles = sort_and_uniq(keyFiles); - // todo(jon): make sure we differentiate incrementals on different branches - // we can use just a single cache per incremental branch - if (self.incremental) { - key += `-incremental`; - } key += `-${lockHash}`; self.cacheKey = key; + if (self.incremental) { + // wire the incremental key to be just for this branch + const branchName = lib_core.getInput("incremental-key") || "-shared"; + const incrementalKey = key + `-incremental` + branchName; + self.incrementalKey = incrementalKey; + } self.cachePaths = [external_path_default().join(config_CARGO_HOME, "registry"), external_path_default().join(config_CARGO_HOME, "git")]; if (self.cacheBin) { self.cachePaths = [ @@ -86977,7 +86982,7 @@ class CacheConfig { if (self.incremental) { if (cacheTargets === "true") { for (const target of self.workspaces.map((ws) => ws.target)) { - self.cachePaths.push(external_path_default().join(target, "incremental")); + self.incrementalPaths.push(external_path_default().join(target, "incremental")); } } } @@ -87176,7 +87181,10 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen }; await fillModifiedTimes(incrementalDir); // Write the modified times to the incremental folder - lib_core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); + lib_core.debug(`writing incremental-restore.json for ${incrementalDir} files`); + for (const file of modifiedTimes.keys()) { + lib_core.debug(` ${file} -> ${modifiedTimes.get(file)}`); + } const contents = JSON.stringify({ modifiedTimes }); await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); } @@ -87452,16 +87460,17 @@ async function run() { // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. - const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { - lookupOnly, - }); + const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { lookupOnly }); if (restoreKey) { const match = restoreKey === key; lib_core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); if (config.incremental) { - lib_core.debug("restoring incremental builds"); - for (const workspace of config.workspaces) { - await restoreIncremental(workspace.target); + const incrementalKey = await cacheProvider.cache.restoreCache(config.incrementalPaths.slice(), config.incrementalKey, [config.restoreKey], { lookupOnly }); + lib_core.debug(`restoring incremental builds from ${incrementalKey}`); + if (incrementalKey) { + for (const workspace of config.workspaces) { + await restoreIncremental(workspace.target); + } } } if (!match || config.isIncrementalMissing()) { diff --git a/dist/save/index.js b/dist/save/index.js index 9fb3841..c5321ef 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -86765,8 +86765,12 @@ class CacheConfig { constructor() { /** All the paths we want to cache */ this.cachePaths = []; + /** All the paths we want to cache for incremental builds */ + this.incrementalPaths = []; /** The primary cache key */ this.cacheKey = ""; + /** The primary cache key for incremental builds */ + this.incrementalKey = ""; /** * The secondary (restore) key that only contains the prefix and environment * This should be used if the primary cacheKey is not available - IE pulling from main on a branch @@ -86950,13 +86954,14 @@ class CacheConfig { let lockHash = digest(hasher); keyFiles.push(...parsedKeyFiles); self.keyFiles = sort_and_uniq(keyFiles); - // todo(jon): make sure we differentiate incrementals on different branches - // we can use just a single cache per incremental branch - if (self.incremental) { - key += `-incremental`; - } key += `-${lockHash}`; self.cacheKey = key; + if (self.incremental) { + // wire the incremental key to be just for this branch + const branchName = lib_core.getInput("incremental-key") || "-shared"; + const incrementalKey = key + `-incremental` + branchName; + self.incrementalKey = incrementalKey; + } self.cachePaths = [external_path_default().join(CARGO_HOME, "registry"), external_path_default().join(CARGO_HOME, "git")]; if (self.cacheBin) { self.cachePaths = [ @@ -86977,7 +86982,7 @@ class CacheConfig { if (self.incremental) { if (cacheTargets === "true") { for (const target of self.workspaces.map((ws) => ws.target)) { - self.cachePaths.push(external_path_default().join(target, "incremental")); + self.incrementalPaths.push(external_path_default().join(target, "incremental")); } } } @@ -87176,7 +87181,10 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen }; await fillModifiedTimes(incrementalDir); // Write the modified times to the incremental folder - lib_core.debug(`writing incremental-restore.json for ${incrementalDir} with ${modifiedTimes} files`); + lib_core.debug(`writing incremental-restore.json for ${incrementalDir} files`); + for (const file of modifiedTimes.keys()) { + lib_core.debug(` ${file} -> ${modifiedTimes.get(file)}`); + } const contents = JSON.stringify({ modifiedTimes }); await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); } @@ -87422,6 +87430,7 @@ async function rmRF(dirName) { + process.on("uncaughtException", (e) => { lib_core.error(e.message); if (e.stack) { @@ -87482,6 +87491,15 @@ async function run() { catch (e) { lib_core.debug(`${e.stack}`); } + // Save the incremental cache before we delete it + if (config.incremental) { + lib_core.info(`... Saving incremental cache ...`); + await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); + for (const path of config.incrementalPaths) { + lib_core.debug(` deleting ${path}`); + await (0,promises_.rm)(path); + } + } lib_core.info(`... Saving cache ...`); // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 From 6f58383b83b2c609b0e5f96b523d6888915e12a3 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 21:41:21 -0800 Subject: [PATCH 17/26] save before clearing --- dist/restore/index.js | 28 ---------------- dist/save/index.js | 78 +++++++++++++++++++++++-------------------- src/cleanup.ts | 30 ----------------- src/save.ts | 55 ++++++++++++++++++++++++------ 4 files changed, 86 insertions(+), 105 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 41fe7f8..597fba0 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -87160,34 +87160,6 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); - // Keep the incremental folder if incremental builds are enabled - if (incremental) { - keepProfile.add("incremental"); - // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = external_path_default().join(profileDir, "incremental"); - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir) => { - const dirEntries = await external_fs_default().promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(external_path_default().join(dir, dirent.name)); - } - else { - const fileName = external_path_default().join(dir, dirent.name); - const { mtime } = await external_fs_default().promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); - // Write the modified times to the incremental folder - lib_core.debug(`writing incremental-restore.json for ${incrementalDir} files`); - for (const file of modifiedTimes.keys()) { - lib_core.debug(` ${file} -> ${modifiedTimes.get(file)}`); - } - const contents = JSON.stringify({ modifiedTimes }); - await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); - } await rmExcept(profileDir, keepProfile); const keepPkg = new Set(packages.map((p) => p.name)); await rmExcept(external_path_default().join(profileDir, "build"), keepPkg, checkTimestamp); diff --git a/dist/save/index.js b/dist/save/index.js index c5321ef..41c466e 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -87160,34 +87160,6 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); - // Keep the incremental folder if incremental builds are enabled - if (incremental) { - keepProfile.add("incremental"); - // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = external_path_default().join(profileDir, "incremental"); - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir) => { - const dirEntries = await external_fs_default().promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(external_path_default().join(dir, dirent.name)); - } - else { - const fileName = external_path_default().join(dir, dirent.name); - const { mtime } = await external_fs_default().promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); - // Write the modified times to the incremental folder - lib_core.debug(`writing incremental-restore.json for ${incrementalDir} files`); - for (const file of modifiedTimes.keys()) { - lib_core.debug(` ${file} -> ${modifiedTimes.get(file)}`); - } - const contents = JSON.stringify({ modifiedTimes }); - await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); - } await rmExcept(profileDir, keepProfile); const keepPkg = new Set(packages.map((p) => p.name)); await rmExcept(external_path_default().join(profileDir, "build"), keepPkg, checkTimestamp); @@ -87431,6 +87403,8 @@ async function rmRF(dirName) { + + process.on("uncaughtException", (e) => { lib_core.error(e.message); if (e.stack) { @@ -87455,6 +87429,19 @@ async function run() { if (process.env["RUNNER_OS"] == "macOS") { await macOsWorkaround(); } + // Save the incremental cache before we delete it + if (config.incremental) { + lib_core.info(`... Saving incremental cache ...`); + lib_core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); + for (const paths of config.incrementalPaths) { + await saveIncrementalDirs(paths); + } + await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); + for (const path of config.incrementalPaths) { + lib_core.debug(` deleting ${path}`); + await (0,promises_.rm)(path); + } + } const allPackages = []; for (const workspace of config.workspaces) { const packages = await workspace.getPackagesOutsideWorkspaceRoot(); @@ -87491,15 +87478,6 @@ async function run() { catch (e) { lib_core.debug(`${e.stack}`); } - // Save the incremental cache before we delete it - if (config.incremental) { - lib_core.info(`... Saving incremental cache ...`); - await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); - for (const path of config.incrementalPaths) { - lib_core.debug(` deleting ${path}`); - await (0,promises_.rm)(path); - } - } lib_core.info(`... Saving cache ...`); // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 @@ -87520,6 +87498,32 @@ async function macOsWorkaround() { } catch { } } +async function saveIncrementalDirs(profileDir) { + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = external_path_default().join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir) => { + const dirEntries = await external_fs_default().promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(external_path_default().join(dir, dirent.name)); + } + else { + const fileName = external_path_default().join(dir, dirent.name); + const { mtime } = await external_fs_default().promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + // Write the modified times to the incremental folder + lib_core.debug(`writing incremental-restore.json for ${incrementalDir} files`); + for (const file of modifiedTimes.keys()) { + lib_core.debug(` ${file} -> ${modifiedTimes.get(file)}`); + } + const contents = JSON.stringify({ modifiedTimes }); + await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); +} })(); diff --git a/src/cleanup.ts b/src/cleanup.ts index b4700b1..55ae995 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -57,36 +57,6 @@ async function cleanProfileTarget(profileDir: string, packages: Packages, checkT let keepProfile = new Set(["build", ".fingerprint", "deps"]); - // Keep the incremental folder if incremental builds are enabled - if (incremental) { - keepProfile.add("incremental"); - - // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = path.join(profileDir, "incremental"); - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir: string) => { - const dirEntries = await fs.promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(path.join(dir, dirent.name)); - } else { - const fileName = path.join(dir, dirent.name); - const { mtime } = await fs.promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); - - // Write the modified times to the incremental folder - core.debug(`writing incremental-restore.json for ${incrementalDir} files`); - for (const file of modifiedTimes.keys()) { - core.debug(` ${file} -> ${modifiedTimes.get(file)}`); - } - const contents = JSON.stringify({ modifiedTimes }); - await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); - } - await rmExcept(profileDir, keepProfile); diff --git a/src/save.ts b/src/save.ts index b91beeb..8aaf170 100644 --- a/src/save.ts +++ b/src/save.ts @@ -5,6 +5,8 @@ import { cleanBin, cleanGit, cleanRegistry, cleanTargetDir } from "./cleanup"; import { CacheConfig, isCacheUpToDate } from "./config"; import { getCacheProvider, reportError } from "./utils"; import { rm } from "fs/promises"; +import fs from "fs"; +import path from "path"; process.on("uncaughtException", (e) => { core.error(e.message); @@ -37,6 +39,20 @@ async function run() { await macOsWorkaround(); } + // Save the incremental cache before we delete it + if (config.incremental) { + core.info(`... Saving incremental cache ...`); + core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); + for (const paths of config.incrementalPaths) { + await saveIncrementalDirs(paths); + } + await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); + for (const path of config.incrementalPaths) { + core.debug(` deleting ${path}`); + await rm(path); + } + } + const allPackages = []; for (const workspace of config.workspaces) { const packages = await workspace.getPackagesOutsideWorkspaceRoot(); @@ -73,16 +89,6 @@ async function run() { core.debug(`${(e as any).stack}`); } - // Save the incremental cache before we delete it - if (config.incremental) { - core.info(`... Saving incremental cache ...`); - await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); - for (const path of config.incrementalPaths) { - core.debug(` deleting ${path}`); - await rm(path); - } - } - core.info(`... Saving cache ...`); // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 @@ -104,3 +110,32 @@ async function macOsWorkaround() { await exec.exec("sudo", ["/usr/sbin/purge"], { silent: true }); } catch { } } + + +async function saveIncrementalDirs(profileDir: string) { + // Traverse the incremental folder recursively and collect the modified times in a map + const incrementalDir = path.join(profileDir, "incremental"); + const modifiedTimes = new Map(); + const fillModifiedTimes = async (dir: string) => { + const dirEntries = await fs.promises.opendir(dir); + for await (const dirent of dirEntries) { + if (dirent.isDirectory()) { + await fillModifiedTimes(path.join(dir, dirent.name)); + } else { + const fileName = path.join(dir, dirent.name); + const { mtime } = await fs.promises.stat(fileName); + modifiedTimes.set(fileName, mtime.getTime()); + } + } + }; + await fillModifiedTimes(incrementalDir); + + // Write the modified times to the incremental folder + core.debug(`writing incremental-restore.json for ${incrementalDir} files`); + for (const file of modifiedTimes.keys()) { + core.debug(` ${file} -> ${modifiedTimes.get(file)}`); + } + const contents = JSON.stringify({ modifiedTimes }); + await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); + +} From bd6c4068e7ef3753f978001aea251b025313486f Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 21:45:23 -0800 Subject: [PATCH 18/26] fix accidentally deleting ache --- dist/restore/index.js | 16 ++++++++-------- dist/save/index.js | 14 +++++++------- src/cleanup.ts | 13 ++++++------- src/restore.ts | 4 ++-- src/save.ts | 2 +- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 597fba0..697901a 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -87114,7 +87114,7 @@ function sort_and_uniq(a) { -async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) { +async function cleanTargetDir(targetDir, packages, checkTimestamp) { lib_core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory let dir = await external_fs_default().promises.opendir(targetDir); @@ -87125,10 +87125,10 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); try { if (isNestedTarget) { - await cleanTargetDir(dirName, packages, checkTimestamp, incremental); + await cleanTargetDir(dirName, packages, checkTimestamp); } else { - await cleanProfileTarget(dirName, packages, checkTimestamp, incremental); + await cleanProfileTarget(dirName, packages, checkTimestamp); } } catch { } @@ -87138,7 +87138,7 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) } } } -async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremental) { +async function cleanProfileTarget(profileDir, packages, checkTimestamp) { lib_core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested // workspaces under `target/tests`. Notably, `target/tests/target` and @@ -87147,12 +87147,12 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen try { // https://github.com/vertexclique/kaos/blob/9876f6c890339741cc5be4b7cb9df72baa5a6d79/src/cargo.rs#L25 // https://github.com/eupn/macrotest/blob/c4151a5f9f545942f4971980b5d264ebcd0b1d11/src/cargo.rs#L27 - cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp, incremental); + cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp); } catch { } try { // https://github.com/dtolnay/trybuild/blob/eec8ca6cb9b8f53d0caf1aa499d99df52cae8b40/src/cargo.rs#L50 - cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp, incremental); + cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp); } catch { } // Delete everything else. @@ -87445,11 +87445,11 @@ async function run() { } } } - if (!match || config.isIncrementalMissing()) { + if (!match) { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { - await cleanTargetDir(workspace.target, [], true, config.incremental); + await cleanTargetDir(workspace.target, [], true); } catch { } } diff --git a/dist/save/index.js b/dist/save/index.js index 41c466e..877a315 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -87114,7 +87114,7 @@ function sort_and_uniq(a) { -async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) { +async function cleanTargetDir(targetDir, packages, checkTimestamp) { lib_core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory let dir = await external_fs_default().promises.opendir(targetDir); @@ -87125,10 +87125,10 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); try { if (isNestedTarget) { - await cleanTargetDir(dirName, packages, checkTimestamp, incremental); + await cleanTargetDir(dirName, packages, checkTimestamp); } else { - await cleanProfileTarget(dirName, packages, checkTimestamp, incremental); + await cleanProfileTarget(dirName, packages, checkTimestamp); } } catch { } @@ -87138,7 +87138,7 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp, incremental) } } } -async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremental) { +async function cleanProfileTarget(profileDir, packages, checkTimestamp) { lib_core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested // workspaces under `target/tests`. Notably, `target/tests/target` and @@ -87147,12 +87147,12 @@ async function cleanProfileTarget(profileDir, packages, checkTimestamp, incremen try { // https://github.com/vertexclique/kaos/blob/9876f6c890339741cc5be4b7cb9df72baa5a6d79/src/cargo.rs#L25 // https://github.com/eupn/macrotest/blob/c4151a5f9f545942f4971980b5d264ebcd0b1d11/src/cargo.rs#L27 - cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp, incremental); + cleanTargetDir(external_path_default().join(profileDir, "target"), packages, checkTimestamp); } catch { } try { // https://github.com/dtolnay/trybuild/blob/eec8ca6cb9b8f53d0caf1aa499d99df52cae8b40/src/cargo.rs#L50 - cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp, incremental); + cleanTargetDir(external_path_default().join(profileDir, "trybuild"), packages, checkTimestamp); } catch { } // Delete everything else. @@ -87448,7 +87448,7 @@ async function run() { allPackages.push(...packages); try { lib_core.info(`... Cleaning ${workspace.target} ...`); - await cleanTargetDir(workspace.target, packages, false, config.incremental); + await cleanTargetDir(workspace.target, packages, false); } catch (e) { lib_core.debug(`${e.stack}`); diff --git a/src/cleanup.ts b/src/cleanup.ts index 55ae995..1ba46df 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -7,7 +7,7 @@ import { CARGO_HOME } from "./config"; import { exists } from "./utils"; import { Packages } from "./workspace"; -export async function cleanTargetDir(targetDir: string, packages: Packages, checkTimestamp: boolean, incremental: boolean) { +export async function cleanTargetDir(targetDir: string, packages: Packages, checkTimestamp: boolean) { core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory @@ -21,9 +21,9 @@ export async function cleanTargetDir(targetDir: string, packages: Packages, chec try { if (isNestedTarget) { - await cleanTargetDir(dirName, packages, checkTimestamp, incremental); + await cleanTargetDir(dirName, packages, checkTimestamp); } else { - await cleanProfileTarget(dirName, packages, checkTimestamp, incremental); + await cleanProfileTarget(dirName, packages, checkTimestamp); } } catch { } } else if (dirent.name !== "CACHEDIR.TAG") { @@ -32,7 +32,7 @@ export async function cleanTargetDir(targetDir: string, packages: Packages, chec } } -async function cleanProfileTarget(profileDir: string, packages: Packages, checkTimestamp: boolean, incremental: boolean) { +async function cleanProfileTarget(profileDir: string, packages: Packages, checkTimestamp: boolean) { core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested @@ -42,12 +42,11 @@ async function cleanProfileTarget(profileDir: string, packages: Packages, checkT try { // https://github.com/vertexclique/kaos/blob/9876f6c890339741cc5be4b7cb9df72baa5a6d79/src/cargo.rs#L25 // https://github.com/eupn/macrotest/blob/c4151a5f9f545942f4971980b5d264ebcd0b1d11/src/cargo.rs#L27 - cleanTargetDir(path.join(profileDir, "target"), packages, checkTimestamp, incremental); + cleanTargetDir(path.join(profileDir, "target"), packages, checkTimestamp); } catch { } - try { // https://github.com/dtolnay/trybuild/blob/eec8ca6cb9b8f53d0caf1aa499d99df52cae8b40/src/cargo.rs#L50 - cleanTargetDir(path.join(profileDir, "trybuild"), packages, checkTimestamp, incremental); + cleanTargetDir(path.join(profileDir, "trybuild"), packages, checkTimestamp); } catch { } // Delete everything else. diff --git a/src/restore.ts b/src/restore.ts index c459ca5..510a559 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -60,11 +60,11 @@ async function run() { } } - if (!match || config.isIncrementalMissing()) { + if (!match) { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { try { - await cleanTargetDir(workspace.target, [], true, config.incremental); + await cleanTargetDir(workspace.target, [], true); } catch { } } diff --git a/src/save.ts b/src/save.ts index 8aaf170..6e496da 100644 --- a/src/save.ts +++ b/src/save.ts @@ -59,7 +59,7 @@ async function run() { allPackages.push(...packages); try { core.info(`... Cleaning ${workspace.target} ...`); - await cleanTargetDir(workspace.target, packages, false, config.incremental); + await cleanTargetDir(workspace.target, packages, false); } catch (e) { core.debug(`${(e as any).stack}`); } From 07fbca13c8ccfacee71257f402e1ca84693d2e39 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 21:52:44 -0800 Subject: [PATCH 19/26] hmm --- dist/restore/index.js | 16 +++++++--------- dist/save/index.js | 14 ++++++-------- src/config.ts | 19 ++++++++----------- src/restore.ts | 2 +- 4 files changed, 22 insertions(+), 29 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 697901a..cb1b9c1 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86956,12 +86956,6 @@ class CacheConfig { self.keyFiles = sort_and_uniq(keyFiles); key += `-${lockHash}`; self.cacheKey = key; - if (self.incremental) { - // wire the incremental key to be just for this branch - const branchName = lib_core.getInput("incremental-key") || "-shared"; - const incrementalKey = key + `-incremental` + branchName; - self.incrementalKey = incrementalKey; - } self.cachePaths = [external_path_default().join(config_CARGO_HOME, "registry"), external_path_default().join(config_CARGO_HOME, "git")]; if (self.cacheBin) { self.cachePaths = [ @@ -86979,15 +86973,19 @@ class CacheConfig { for (const dir of cacheDirectories.trim().split(/\s+/).filter(Boolean)) { self.cachePaths.push(dir); } + const bins = await getCargoBins(); + self.cargoBins = Array.from(bins.values()); if (self.incremental) { + // wire the incremental key to be just for this branch + const branchName = lib_core.getInput("incremental-key") || "-shared"; + const incrementalKey = key + `-incremental--` + branchName; + self.incrementalKey = incrementalKey; if (cacheTargets === "true") { for (const target of self.workspaces.map((ws) => ws.target)) { self.incrementalPaths.push(external_path_default().join(target, "incremental")); } } } - const bins = await getCargoBins(); - self.cargoBins = Array.from(bins.values()); return self; } /** @@ -87459,7 +87457,7 @@ async function run() { setCacheHitOutput(match); } else { - lib_core.info("No cache found."); + lib_core.info(`No cache found for ${config.cacheKey} - this key was found ${restoreKey}`); config.saveState(); setCacheHitOutput(false); } diff --git a/dist/save/index.js b/dist/save/index.js index 877a315..56ba4fb 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -86956,12 +86956,6 @@ class CacheConfig { self.keyFiles = sort_and_uniq(keyFiles); key += `-${lockHash}`; self.cacheKey = key; - if (self.incremental) { - // wire the incremental key to be just for this branch - const branchName = lib_core.getInput("incremental-key") || "-shared"; - const incrementalKey = key + `-incremental` + branchName; - self.incrementalKey = incrementalKey; - } self.cachePaths = [external_path_default().join(CARGO_HOME, "registry"), external_path_default().join(CARGO_HOME, "git")]; if (self.cacheBin) { self.cachePaths = [ @@ -86979,15 +86973,19 @@ class CacheConfig { for (const dir of cacheDirectories.trim().split(/\s+/).filter(Boolean)) { self.cachePaths.push(dir); } + const bins = await getCargoBins(); + self.cargoBins = Array.from(bins.values()); if (self.incremental) { + // wire the incremental key to be just for this branch + const branchName = lib_core.getInput("incremental-key") || "-shared"; + const incrementalKey = key + `-incremental--` + branchName; + self.incrementalKey = incrementalKey; if (cacheTargets === "true") { for (const target of self.workspaces.map((ws) => ws.target)) { self.incrementalPaths.push(external_path_default().join(target, "incremental")); } } } - const bins = await getCargoBins(); - self.cargoBins = Array.from(bins.values()); return self; } /** diff --git a/src/config.ts b/src/config.ts index 062e95e..b114c0d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -139,7 +139,6 @@ export class CacheConfig { self.restoreKey = key; - // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. @@ -266,13 +265,6 @@ export class CacheConfig { key += `-${lockHash}`; self.cacheKey = key; - if (self.incremental) { - // wire the incremental key to be just for this branch - const branchName = core.getInput("incremental-key") || "-shared"; - const incrementalKey = key + `-incremental` + branchName; - self.incrementalKey = incrementalKey; - } - self.cachePaths = [path.join(CARGO_HOME, "registry"), path.join(CARGO_HOME, "git")]; if (self.cacheBin) { self.cachePaths = [ @@ -292,7 +284,15 @@ export class CacheConfig { self.cachePaths.push(dir); } + const bins = await getCargoBins(); + self.cargoBins = Array.from(bins.values()); + if (self.incremental) { + // wire the incremental key to be just for this branch + const branchName = core.getInput("incremental-key") || "-shared"; + const incrementalKey = key + `-incremental--` + branchName; + self.incrementalKey = incrementalKey; + if (cacheTargets === "true") { for (const target of self.workspaces.map((ws) => ws.target)) { self.incrementalPaths.push(path.join(target, "incremental")); @@ -300,9 +300,6 @@ export class CacheConfig { } } - const bins = await getCargoBins(); - self.cargoBins = Array.from(bins.values()); - return self; } diff --git a/src/restore.ts b/src/restore.ts index 510a559..f7a59c9 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -74,7 +74,7 @@ async function run() { setCacheHitOutput(match); } else { - core.info("No cache found."); + core.info(`No cache found for ${config.cacheKey} - this key was found ${restoreKey}`); config.saveState(); setCacheHitOutput(false); From b37d2821f8737044cac9371f4ae4ad56be167cbd Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 21:58:20 -0800 Subject: [PATCH 20/26] remove invalidation --- dist/restore/index.js | 116 +++++++++++------------ dist/save/index.js | 210 +++++++++++++++--------------------------- src/cleanup.ts | 7 +- src/config.ts | 9 -- src/incremental.ts | 7 -- src/restore.ts | 6 +- src/save.ts | 2 +- 7 files changed, 135 insertions(+), 222 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index cb1b9c1..5b10569 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86691,59 +86691,6 @@ class Workspace { } } -;// CONCATENATED MODULE: ./src/incremental.ts - -// import * as io from "@actions/io"; - - -// import { CARGO_HOME } from "./config"; - -// import { Packages } from "./workspace"; -let incremental_missing = false; -function isIncrementalMissing() { - return incremental_missing; -} -async function restoreIncremental(targetDir) { - lib_core.debug(`restoring incremental directory "${targetDir}"`); - let dir = await external_fs_default().promises.opendir(targetDir); - for await (const dirent of dir) { - if (dirent.isDirectory()) { - let dirName = external_path_default().join(dir.path, dirent.name); - // is it a profile dir, or a nested target dir? - let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); - try { - if (isNestedTarget) { - await restoreIncremental(dirName); - } - else { - await restoreIncrementalProfile(dirName); - } - restoreIncrementalProfile; - } - catch { } - } - } -} -async function restoreIncrementalProfile(dirName) { - lib_core.debug(`restoring incremental profile directory "${dirName}"`); - const incrementalJson = external_path_default().join(dirName, "incremental-restore.json"); - if (await utils_exists(incrementalJson)) { - const contents = await external_fs_default().promises.readFile(incrementalJson, "utf8"); - const { modifiedTimes } = JSON.parse(contents); - lib_core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); - // Write the mtimes to all the files in the profile directory - for (const fileName of Object.keys(modifiedTimes)) { - const mtime = modifiedTimes[fileName]; - const filePath = external_path_default().join(dirName, fileName); - await external_fs_default().promises.utimes(filePath, new Date(mtime), new Date(mtime)); - } - } - else { - lib_core.debug(`incremental-restore.json not found for ${dirName}`); - incremental_missing = true; - } -} - ;// CONCATENATED MODULE: ./src/config.ts @@ -86756,7 +86703,6 @@ async function restoreIncrementalProfile(dirName) { - const HOME = external_os_default().homedir(); const config_CARGO_HOME = process.env.CARGO_HOME || external_path_default().join(HOME, ".cargo"); const STATE_CONFIG = "RUST_CACHE_CONFIG"; @@ -87046,12 +86992,6 @@ class CacheConfig { saveState() { lib_core.saveState(STATE_CONFIG, this); } - isIncrementalMissing() { - if (this.incremental) { - return isIncrementalMissing(); - } - return false; - } } /** * Checks if the cache is up to date. @@ -87112,7 +87052,7 @@ function sort_and_uniq(a) { -async function cleanTargetDir(targetDir, packages, checkTimestamp) { +async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { lib_core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory let dir = await external_fs_default().promises.opendir(targetDir); @@ -87136,7 +87076,7 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp) { } } } -async function cleanProfileTarget(profileDir, packages, checkTimestamp) { +async function cleanProfileTarget(profileDir, packages, checkTimestamp = false) { lib_core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested // workspaces under `target/tests`. Notably, `target/tests/target` and @@ -87394,6 +87334,54 @@ async function rmRF(dirName) { await io.rmRF(dirName); } +;// CONCATENATED MODULE: ./src/incremental.ts + +// import * as io from "@actions/io"; + + +// import { CARGO_HOME } from "./config"; + +// import { Packages } from "./workspace"; +async function restoreIncremental(targetDir) { + lib_core.debug(`restoring incremental directory "${targetDir}"`); + let dir = await external_fs_default().promises.opendir(targetDir); + for await (const dirent of dir) { + if (dirent.isDirectory()) { + let dirName = external_path_default().join(dir.path, dirent.name); + // is it a profile dir, or a nested target dir? + let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); + try { + if (isNestedTarget) { + await restoreIncremental(dirName); + } + else { + await restoreIncrementalProfile(dirName); + } + restoreIncrementalProfile; + } + catch { } + } + } +} +async function restoreIncrementalProfile(dirName) { + lib_core.debug(`restoring incremental profile directory "${dirName}"`); + const incrementalJson = external_path_default().join(dirName, "incremental-restore.json"); + if (await utils_exists(incrementalJson)) { + const contents = await external_fs_default().promises.readFile(incrementalJson, "utf8"); + const { modifiedTimes } = JSON.parse(contents); + lib_core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); + // Write the mtimes to all the files in the profile directory + for (const fileName of Object.keys(modifiedTimes)) { + const mtime = modifiedTimes[fileName]; + const filePath = external_path_default().join(dirName, fileName); + await external_fs_default().promises.utimes(filePath, new Date(mtime), new Date(mtime)); + } + } + else { + lib_core.debug(`incremental-restore.json not found for ${dirName}`); + } +} + ;// CONCATENATED MODULE: ./src/restore.ts @@ -87430,7 +87418,9 @@ async function run() { // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. - const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { lookupOnly }); + const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { + lookupOnly, + }); if (restoreKey) { const match = restoreKey === key; lib_core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); diff --git a/dist/save/index.js b/dist/save/index.js index 56ba4fb..237cf3f 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -85430,7 +85430,7 @@ var __webpack_exports__ = {}; "use strict"; // EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js -var lib_core = __nccwpck_require__(7484); +var core = __nccwpck_require__(7484); // EXTERNAL MODULE: ./node_modules/@actions/exec/lib/exec.js var exec = __nccwpck_require__(5236); // EXTERNAL MODULE: ./node_modules/@actions/io/lib/io.js @@ -86601,11 +86601,11 @@ var cache_lib_cache = __nccwpck_require__(5116); function reportError(e) { const { commandFailed } = e; if (commandFailed) { - lib_core.error(`Command failed: ${commandFailed.command}`); - lib_core.error(commandFailed.stderr); + core.error(`Command failed: ${commandFailed.command}`); + core.error(commandFailed.stderr); } else { - lib_core.error(`${e.stack}`); + core.error(`${e.stack}`); } } async function getCmdOutput(cmd, args = [], options = {}) { @@ -86635,7 +86635,7 @@ async function getCmdOutput(cmd, args = [], options = {}) { return stdout; } function getCacheProvider() { - const cacheProvider = lib_core.getInput("cache-provider"); + const cacheProvider = core.getInput("cache-provider"); const cache = cacheProvider === "github" ? cache_lib_cache : cacheProvider === "buildjet" ? lib_cache : undefined; if (!cache) { throw new Error(`The \`cache-provider\` \`{cacheProvider}\` is not valid.`); @@ -86645,7 +86645,7 @@ function getCacheProvider() { cache: cache, }; } -async function utils_exists(path) { +async function exists(path) { try { await external_fs_default().promises.access(path); return true; @@ -86668,11 +86668,11 @@ class Workspace { async getPackages(filter, ...extraArgs) { let packages = []; try { - lib_core.debug(`collecting metadata for "${this.root}"`); + core.debug(`collecting metadata for "${this.root}"`); const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1", ...extraArgs], { cwd: this.root, })); - lib_core.debug(`workspace "${this.root}" has ${meta.packages.length} packages`); + core.debug(`workspace "${this.root}" has ${meta.packages.length} packages`); for (const pkg of meta.packages.filter(filter)) { const targets = pkg.targets.filter((t) => t.kind.some((kind) => SAVE_TARGETS.has(kind))).map((t) => t.name); packages.push({ name: pkg.name, version: pkg.version, targets, path: external_path_default().dirname(pkg.manifest_path) }); @@ -86691,59 +86691,6 @@ class Workspace { } } -;// CONCATENATED MODULE: ./src/incremental.ts - -// import * as io from "@actions/io"; - - -// import { CARGO_HOME } from "./config"; - -// import { Packages } from "./workspace"; -let incremental_missing = false; -function isIncrementalMissing() { - return incremental_missing; -} -async function restoreIncremental(targetDir) { - core.debug(`restoring incremental directory "${targetDir}"`); - let dir = await fs.promises.opendir(targetDir); - for await (const dirent of dir) { - if (dirent.isDirectory()) { - let dirName = path.join(dir.path, dirent.name); - // is it a profile dir, or a nested target dir? - let isNestedTarget = (await exists(path.join(dirName, "CACHEDIR.TAG"))) || (await exists(path.join(dirName, ".rustc_info.json"))); - try { - if (isNestedTarget) { - await restoreIncremental(dirName); - } - else { - await restoreIncrementalProfile(dirName); - } - restoreIncrementalProfile; - } - catch { } - } - } -} -async function restoreIncrementalProfile(dirName) { - core.debug(`restoring incremental profile directory "${dirName}"`); - const incrementalJson = path.join(dirName, "incremental-restore.json"); - if (await exists(incrementalJson)) { - const contents = await fs.promises.readFile(incrementalJson, "utf8"); - const { modifiedTimes } = JSON.parse(contents); - core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); - // Write the mtimes to all the files in the profile directory - for (const fileName of Object.keys(modifiedTimes)) { - const mtime = modifiedTimes[fileName]; - const filePath = path.join(dirName, fileName); - await fs.promises.utimes(filePath, new Date(mtime), new Date(mtime)); - } - } - else { - core.debug(`incremental-restore.json not found for ${dirName}`); - incremental_missing = true; - } -} - ;// CONCATENATED MODULE: ./src/config.ts @@ -86756,7 +86703,6 @@ async function restoreIncrementalProfile(dirName) { - const HOME = external_os_default().homedir(); const CARGO_HOME = process.env.CARGO_HOME || external_path_default().join(HOME, ".cargo"); const STATE_CONFIG = "RUST_CACHE_CONFIG"; @@ -86804,13 +86750,13 @@ class CacheConfig { // Construct key prefix: // This uses either the `shared-key` input, // or the `key` input combined with the `job` key. - let key = lib_core.getInput("prefix-key") || "v0-rust"; - const sharedKey = lib_core.getInput("shared-key"); + let key = core.getInput("prefix-key") || "v0-rust"; + const sharedKey = core.getInput("shared-key"); if (sharedKey) { key += `-${sharedKey}`; } else { - const inputKey = lib_core.getInput("key"); + const inputKey = core.getInput("key"); if (inputKey) { key += `-${inputKey}`; } @@ -86838,7 +86784,7 @@ class CacheConfig { self.keyRust = keyRust; // these prefixes should cover most of the compiler / rust / cargo keys const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"]; - envPrefixes.push(...lib_core.getInput("env-vars").split(/\s+/).filter(Boolean)); + envPrefixes.push(...core.getInput("env-vars").split(/\s+/).filter(Boolean)); // sort the available env vars so we have a more stable hash const keyEnvs = []; const envKeys = Object.keys(process.env); @@ -86852,18 +86798,18 @@ class CacheConfig { } self.keyEnvs = keyEnvs; // Make sure we consider incremental builds - self.incremental = lib_core.getInput("incremental").toLowerCase() == "true"; + self.incremental = core.getInput("incremental").toLowerCase() == "true"; hasher.update(`incremental=${self.incremental}`); key += `-${digest(hasher)}`; self.restoreKey = key; // Construct the lockfiles portion of the key: // This considers all the files found via globbing for various manifests // and lockfiles. - self.cacheBin = lib_core.getInput("cache-bin").toLowerCase() == "true"; + self.cacheBin = core.getInput("cache-bin").toLowerCase() == "true"; // Constructs the workspace config and paths to restore: // The workspaces are given using a `$workspace -> $target` syntax. const workspaces = []; - const workspacesInput = lib_core.getInput("workspaces") || "."; + const workspacesInput = core.getInput("workspaces") || "."; for (const workspace of workspacesInput.trim().split("\n")) { let [root, target = "target"] = workspace.split("->").map((s) => s.trim()); root = external_path_default().resolve(root); @@ -86916,19 +86862,19 @@ class CacheConfig { } catch (e) { // Fallback to caching them as regular file - lib_core.warning(`Error parsing Cargo.toml manifest, fallback to caching entire file: ${e}`); + core.warning(`Error parsing Cargo.toml manifest, fallback to caching entire file: ${e}`); keyFiles.push(cargo_manifest); } } const cargo_lock = external_path_default().join(workspace.root, "Cargo.lock"); - if (await utils_exists(cargo_lock)) { + if (await exists(cargo_lock)) { try { const content = await promises_default().readFile(cargo_lock, { encoding: "utf8" }); const parsed = parse(content); if ((parsed.version !== 3 && parsed.version !== 4) || !("package" in parsed)) { // Fallback to caching them as regular file since this action // can only handle Cargo.lock format version 3 - lib_core.warning("Unsupported Cargo.lock format, fallback to caching entire file"); + core.warning("Unsupported Cargo.lock format, fallback to caching entire file"); keyFiles.push(cargo_lock); continue; } @@ -86940,7 +86886,7 @@ class CacheConfig { } catch (e) { // Fallback to caching them as regular file - lib_core.warning(`Error parsing Cargo.lock manifest, fallback to caching entire file: ${e}`); + core.warning(`Error parsing Cargo.lock manifest, fallback to caching entire file: ${e}`); keyFiles.push(cargo_lock); } } @@ -86965,11 +86911,11 @@ class CacheConfig { ...self.cachePaths, ]; } - const cacheTargets = lib_core.getInput("cache-targets").toLowerCase() || "true"; + const cacheTargets = core.getInput("cache-targets").toLowerCase() || "true"; if (cacheTargets === "true") { self.cachePaths.push(...workspaces.map((ws) => ws.target)); } - const cacheDirectories = lib_core.getInput("cache-directories"); + const cacheDirectories = core.getInput("cache-directories"); for (const dir of cacheDirectories.trim().split(/\s+/).filter(Boolean)) { self.cachePaths.push(dir); } @@ -86977,7 +86923,7 @@ class CacheConfig { self.cargoBins = Array.from(bins.values()); if (self.incremental) { // wire the incremental key to be just for this branch - const branchName = lib_core.getInput("incremental-key") || "-shared"; + const branchName = core.getInput("incremental-key") || "-shared"; const incrementalKey = key + `-incremental--` + branchName; self.incrementalKey = incrementalKey; if (cacheTargets === "true") { @@ -86997,7 +86943,7 @@ class CacheConfig { * @see {@link CacheConfig#new} */ static fromState() { - const source = lib_core.getState(STATE_CONFIG); + const source = core.getState(STATE_CONFIG); if (!source) { throw new Error("Cache configuration not found in state"); } @@ -87010,47 +86956,41 @@ class CacheConfig { * Prints the configuration to the action log. */ printInfo(cacheProvider) { - lib_core.startGroup("Cache Configuration"); - lib_core.info(`Cache Provider:`); - lib_core.info(` ${cacheProvider.name}`); - lib_core.info(`Workspaces:`); + core.startGroup("Cache Configuration"); + core.info(`Cache Provider:`); + core.info(` ${cacheProvider.name}`); + core.info(`Workspaces:`); for (const workspace of this.workspaces) { - lib_core.info(` ${workspace.root}`); + core.info(` ${workspace.root}`); } - lib_core.info(`Cache Paths:`); + core.info(`Cache Paths:`); for (const path of this.cachePaths) { - lib_core.info(` ${path}`); + core.info(` ${path}`); } - lib_core.info(`Restore Key:`); - lib_core.info(` ${this.restoreKey}`); - lib_core.info(`Cache Key:`); - lib_core.info(` ${this.cacheKey}`); - lib_core.info(`.. Prefix:`); - lib_core.info(` - ${this.keyPrefix}`); - lib_core.info(`.. Environment considered:`); - lib_core.info(` - Rust Version: ${this.keyRust}`); + core.info(`Restore Key:`); + core.info(` ${this.restoreKey}`); + core.info(`Cache Key:`); + core.info(` ${this.cacheKey}`); + core.info(`.. Prefix:`); + core.info(` - ${this.keyPrefix}`); + core.info(`.. Environment considered:`); + core.info(` - Rust Version: ${this.keyRust}`); for (const env of this.keyEnvs) { - lib_core.info(` - ${env}`); + core.info(` - ${env}`); } - lib_core.info(`.. Lockfiles considered:`); + core.info(`.. Lockfiles considered:`); for (const file of this.keyFiles) { - lib_core.info(` - ${file}`); + core.info(` - ${file}`); } - lib_core.info(`.. Incremental: ${this.incremental}`); - lib_core.endGroup(); + core.info(`.. Incremental: ${this.incremental}`); + core.endGroup(); } /** * Saves the configuration to the state store. * This is used to restore the configuration in the post action. */ saveState() { - lib_core.saveState(STATE_CONFIG, this); - } - isIncrementalMissing() { - if (this.incremental) { - return isIncrementalMissing(); - } - return false; + core.saveState(STATE_CONFIG, this); } } /** @@ -87059,7 +86999,7 @@ class CacheConfig { * @returns `true` if the cache is up to date, `false` otherwise. */ function isCacheUpToDate() { - return lib_core.getState(STATE_CONFIG) === ""; + return core.getState(STATE_CONFIG) === ""; } /** * Returns a hex digest of the given hasher truncated to `HASH_LENGTH`. @@ -87112,15 +87052,15 @@ function sort_and_uniq(a) { -async function cleanTargetDir(targetDir, packages, checkTimestamp) { - lib_core.debug(`cleaning target directory "${targetDir}"`); +async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { + core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory let dir = await external_fs_default().promises.opendir(targetDir); for await (const dirent of dir) { if (dirent.isDirectory()) { let dirName = external_path_default().join(dir.path, dirent.name); // is it a profile dir, or a nested target dir? - let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); + let isNestedTarget = (await exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await exists(external_path_default().join(dirName, ".rustc_info.json"))); try { if (isNestedTarget) { await cleanTargetDir(dirName, packages, checkTimestamp); @@ -87136,8 +87076,8 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp) { } } } -async function cleanProfileTarget(profileDir, packages, checkTimestamp) { - lib_core.debug(`cleaning profile directory "${profileDir}"`); +async function cleanProfileTarget(profileDir, packages, checkTimestamp = false) { + core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested // workspaces under `target/tests`. Notably, `target/tests/target` and // `target/tests/trybuild`. @@ -87207,7 +87147,7 @@ async function cleanRegistry(packages, crates = true) { // remove `.cargo/credentials.toml` try { const credentials = external_path_default().join(CARGO_HOME, ".cargo", "credentials.toml"); - lib_core.debug(`deleting "${credentials}"`); + core.debug(`deleting "${credentials}"`); await external_fs_default().promises.unlink(credentials); } catch { } @@ -87220,7 +87160,7 @@ async function cleanRegistry(packages, crates = true) { // or `.cargo/registry/index/index.crates.io-e139d0d48fed7772` const dirPath = external_path_default().join(indexDir.path, dirent.name); // for a git registry, we can remove `.cache`, as cargo will recreate it from git - if (await utils_exists(external_path_default().join(dirPath, ".git"))) { + if (await exists(external_path_default().join(dirPath, ".git"))) { await rmRF(external_path_default().join(dirPath, ".cache")); } else { @@ -87229,7 +87169,7 @@ async function cleanRegistry(packages, crates = true) { } } if (!crates) { - lib_core.debug("skipping registry cache and src cleanup"); + core.debug("skipping registry cache and src cleanup"); return; } // `.cargo/registry/src` @@ -87379,7 +87319,7 @@ async function rmExcept(dirName, keepPrefix, checkTimestamp = false) { async function rm(parent, dirent) { try { const fileName = external_path_default().join(parent, dirent.name); - lib_core.debug(`deleting "${fileName}"`); + core.debug(`deleting "${fileName}"`); if (dirent.isFile()) { await external_fs_default().promises.unlink(fileName); } @@ -87390,7 +87330,7 @@ async function rm(parent, dirent) { catch { } } async function rmRF(dirName) { - lib_core.debug(`deleting "${dirName}"`); + core.debug(`deleting "${dirName}"`); await io.rmRF(dirName); } @@ -87404,39 +87344,39 @@ async function rmRF(dirName) { process.on("uncaughtException", (e) => { - lib_core.error(e.message); + core.error(e.message); if (e.stack) { - lib_core.error(e.stack); + core.error(e.stack); } }); async function run() { const cacheProvider = getCacheProvider(); - const save = lib_core.getInput("save-if").toLowerCase() || "true"; + const save = core.getInput("save-if").toLowerCase() || "true"; if (!(cacheProvider.cache.isFeatureAvailable() && save === "true")) { return; } try { if (isCacheUpToDate()) { - lib_core.info(`Cache up-to-date.`); + core.info(`Cache up-to-date.`); return; } const config = CacheConfig.fromState(); config.printInfo(cacheProvider); - lib_core.info(""); + core.info(""); // TODO: remove this once https://github.com/actions/toolkit/pull/553 lands if (process.env["RUNNER_OS"] == "macOS") { await macOsWorkaround(); } // Save the incremental cache before we delete it if (config.incremental) { - lib_core.info(`... Saving incremental cache ...`); - lib_core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); + core.info(`... Saving incremental cache ...`); + core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); for (const paths of config.incrementalPaths) { await saveIncrementalDirs(paths); } await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); for (const path of config.incrementalPaths) { - lib_core.debug(` deleting ${path}`); + core.debug(` deleting ${path}`); await (0,promises_.rm)(path); } } @@ -87445,38 +87385,38 @@ async function run() { const packages = await workspace.getPackagesOutsideWorkspaceRoot(); allPackages.push(...packages); try { - lib_core.info(`... Cleaning ${workspace.target} ...`); + core.info(`... Cleaning ${workspace.target} ...`); await cleanTargetDir(workspace.target, packages, false); } catch (e) { - lib_core.debug(`${e.stack}`); + core.debug(`${e.stack}`); } } try { - const crates = lib_core.getInput("cache-all-crates").toLowerCase() || "false"; - lib_core.info(`... Cleaning cargo registry (cache-all-crates: ${crates}) ...`); + const crates = core.getInput("cache-all-crates").toLowerCase() || "false"; + core.info(`... Cleaning cargo registry (cache-all-crates: ${crates}) ...`); await cleanRegistry(allPackages, crates !== "true"); } catch (e) { - lib_core.debug(`${e.stack}`); + core.debug(`${e.stack}`); } if (config.cacheBin) { try { - lib_core.info(`... Cleaning cargo/bin ...`); + core.info(`... Cleaning cargo/bin ...`); await cleanBin(config.cargoBins); } catch (e) { - lib_core.debug(`${e.stack}`); + core.debug(`${e.stack}`); } } try { - lib_core.info(`... Cleaning cargo git cache ...`); + core.info(`... Cleaning cargo git cache ...`); await cleanGit(allPackages); } catch (e) { - lib_core.debug(`${e.stack}`); + core.debug(`${e.stack}`); } - lib_core.info(`... Saving cache ...`); + core.info(`... Saving cache with key ${config.cacheKey}`); // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. @@ -87515,9 +87455,9 @@ async function saveIncrementalDirs(profileDir) { }; await fillModifiedTimes(incrementalDir); // Write the modified times to the incremental folder - lib_core.debug(`writing incremental-restore.json for ${incrementalDir} files`); + core.debug(`writing incremental-restore.json for ${incrementalDir} files`); for (const file of modifiedTimes.keys()) { - lib_core.debug(` ${file} -> ${modifiedTimes.get(file)}`); + core.debug(` ${file} -> ${modifiedTimes.get(file)}`); } const contents = JSON.stringify({ modifiedTimes }); await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); diff --git a/src/cleanup.ts b/src/cleanup.ts index 1ba46df..68edbdf 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -7,7 +7,7 @@ import { CARGO_HOME } from "./config"; import { exists } from "./utils"; import { Packages } from "./workspace"; -export async function cleanTargetDir(targetDir: string, packages: Packages, checkTimestamp: boolean) { +export async function cleanTargetDir(targetDir: string, packages: Packages, checkTimestamp = false) { core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory @@ -32,7 +32,7 @@ export async function cleanTargetDir(targetDir: string, packages: Packages, chec } } -async function cleanProfileTarget(profileDir: string, packages: Packages, checkTimestamp: boolean) { +async function cleanProfileTarget(profileDir: string, packages: Packages, checkTimestamp = false) { core.debug(`cleaning profile directory "${profileDir}"`); // Quite a few testing utility crates store compilation artifacts as nested @@ -51,12 +51,11 @@ async function cleanProfileTarget(profileDir: string, packages: Packages, checkT // Delete everything else. await rmExcept(profileDir, new Set(["target", "trybuild"]), checkTimestamp); + return; } let keepProfile = new Set(["build", ".fingerprint", "deps"]); - - await rmExcept(profileDir, keepProfile); const keepPkg = new Set(packages.map((p) => p.name)); diff --git a/src/config.ts b/src/config.ts index b114c0d..0c95e94 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,7 +10,6 @@ import * as toml from "smol-toml"; import { getCargoBins } from "./cleanup"; import { CacheProvider, exists, getCmdOutput } from "./utils"; import { Workspace } from "./workspace"; -import { isIncrementalMissing } from "./incremental"; const HOME = os.homedir(); export const CARGO_HOME = process.env.CARGO_HOME || path.join(HOME, ".cargo"); @@ -365,14 +364,6 @@ export class CacheConfig { saveState() { core.saveState(STATE_CONFIG, this); } - - isIncrementalMissing(): boolean { - if (this.incremental) { - return isIncrementalMissing(); - } - - return false; - } } /** diff --git a/src/incremental.ts b/src/incremental.ts index 43303f0..56e75ba 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -7,12 +7,6 @@ import path from "path"; import { exists } from "./utils"; // import { Packages } from "./workspace"; -let incremental_missing = false; - -export function isIncrementalMissing(): boolean { - return incremental_missing; -} - export async function restoreIncremental(targetDir: string) { core.debug(`restoring incremental directory "${targetDir}"`); @@ -52,6 +46,5 @@ async function restoreIncrementalProfile(dirName: string) { } } else { core.debug(`incremental-restore.json not found for ${dirName}`); - incremental_missing = true; } } diff --git a/src/restore.ts b/src/restore.ts index f7a59c9..9adde48 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -39,12 +39,12 @@ async function run() { core.info(`... ${lookupOnly ? "Checking" : "Restoring"} cache ...`); const key = config.cacheKey; - // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. - const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { lookupOnly }); - + const restoreKey = await cacheProvider.cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey], { + lookupOnly, + }); if (restoreKey) { const match = restoreKey === key; core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); diff --git a/src/save.ts b/src/save.ts index 6e496da..59135db 100644 --- a/src/save.ts +++ b/src/save.ts @@ -89,7 +89,7 @@ async function run() { core.debug(`${(e as any).stack}`); } - core.info(`... Saving cache ...`); + core.info(`... Saving cache with key ${config.cacheKey}`); // Pass a copy of cachePaths to avoid mutating the original array as reported by: // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. From 64b8867183597c18966a0dcc8f97f1743fc6b4de Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 22:02:28 -0800 Subject: [PATCH 21/26] fix paths for cache dir --- dist/save/index.js | 23 ++++++++++++++--------- src/save.ts | 24 ++++++++++++++---------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/dist/save/index.js b/dist/save/index.js index 237cf3f..2d1c5cc 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -87370,14 +87370,20 @@ async function run() { // Save the incremental cache before we delete it if (config.incremental) { core.info(`... Saving incremental cache ...`); - core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); - for (const paths of config.incrementalPaths) { - await saveIncrementalDirs(paths); + try { + core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); + for (const paths of config.incrementalPaths) { + await saveIncrementalDirs(paths); + } + await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); + for (const path of config.incrementalPaths) { + core.debug(` deleting ${path}`); + await (0,promises_.rm)(path); + } } - await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); - for (const path of config.incrementalPaths) { - core.debug(` deleting ${path}`); - await (0,promises_.rm)(path); + catch (e) { + core.debug(`Failed to save incremental cache`); + core.debug(`${e.stack}`); } } const allPackages = []; @@ -87436,9 +87442,8 @@ async function macOsWorkaround() { } catch { } } -async function saveIncrementalDirs(profileDir) { +async function saveIncrementalDirs(incrementalDir) { // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = external_path_default().join(profileDir, "incremental"); const modifiedTimes = new Map(); const fillModifiedTimes = async (dir) => { const dirEntries = await external_fs_default().promises.opendir(dir); diff --git a/src/save.ts b/src/save.ts index 59135db..b452669 100644 --- a/src/save.ts +++ b/src/save.ts @@ -42,14 +42,19 @@ async function run() { // Save the incremental cache before we delete it if (config.incremental) { core.info(`... Saving incremental cache ...`); - core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); - for (const paths of config.incrementalPaths) { - await saveIncrementalDirs(paths); - } - await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); - for (const path of config.incrementalPaths) { - core.debug(` deleting ${path}`); - await rm(path); + try { + core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); + for (const paths of config.incrementalPaths) { + await saveIncrementalDirs(paths); + } + await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); + for (const path of config.incrementalPaths) { + core.debug(` deleting ${path}`); + await rm(path); + } + } catch (e) { + core.debug(`Failed to save incremental cache`); + core.debug(`${(e as any).stack}`); } } @@ -112,9 +117,8 @@ async function macOsWorkaround() { } -async function saveIncrementalDirs(profileDir: string) { +async function saveIncrementalDirs(incrementalDir: string) { // Traverse the incremental folder recursively and collect the modified times in a map - const incrementalDir = path.join(profileDir, "incremental"); const modifiedTimes = new Map(); const fillModifiedTimes = async (dir: string) => { const dirEntries = await fs.promises.opendir(dir); From 01addf7215cd9af9bda1c1226b20af635b636bbe Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 22:28:27 -0800 Subject: [PATCH 22/26] new restore technique --- dist/restore/index.js | 75 +++++++----------------------- dist/save/index.js | 105 +++++++++++++++++++++++++++--------------- src/config.ts | 9 ++-- src/incremental.ts | 56 ++++++++-------------- src/restore.ts | 22 +++++---- src/save.ts | 72 ++++++++++++++++------------- 6 files changed, 157 insertions(+), 182 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 5b10569..310327f 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86712,7 +86712,7 @@ class CacheConfig { /** All the paths we want to cache */ this.cachePaths = []; /** All the paths we want to cache for incremental builds */ - this.incrementalPaths = []; + // public incrementalPaths: Array = []; /** The primary cache key */ this.cacheKey = ""; /** The primary cache key for incremental builds */ @@ -86926,11 +86926,8 @@ class CacheConfig { const branchName = lib_core.getInput("incremental-key") || "-shared"; const incrementalKey = key + `-incremental--` + branchName; self.incrementalKey = incrementalKey; - if (cacheTargets === "true") { - for (const target of self.workspaces.map((ws) => ws.target)) { - self.incrementalPaths.push(external_path_default().join(target, "incremental")); - } - } + // Add the incremental cache to the cachePaths so we can restore it + self.cachePaths.push(external_path_default().join(config_CARGO_HOME, "incremental-restore.json")); } return self; } @@ -87334,59 +87331,13 @@ async function rmRF(dirName) { await io.rmRF(dirName); } -;// CONCATENATED MODULE: ./src/incremental.ts - -// import * as io from "@actions/io"; - - -// import { CARGO_HOME } from "./config"; - -// import { Packages } from "./workspace"; -async function restoreIncremental(targetDir) { - lib_core.debug(`restoring incremental directory "${targetDir}"`); - let dir = await external_fs_default().promises.opendir(targetDir); - for await (const dirent of dir) { - if (dirent.isDirectory()) { - let dirName = external_path_default().join(dir.path, dirent.name); - // is it a profile dir, or a nested target dir? - let isNestedTarget = (await utils_exists(external_path_default().join(dirName, "CACHEDIR.TAG"))) || (await utils_exists(external_path_default().join(dirName, ".rustc_info.json"))); - try { - if (isNestedTarget) { - await restoreIncremental(dirName); - } - else { - await restoreIncrementalProfile(dirName); - } - restoreIncrementalProfile; - } - catch { } - } - } -} -async function restoreIncrementalProfile(dirName) { - lib_core.debug(`restoring incremental profile directory "${dirName}"`); - const incrementalJson = external_path_default().join(dirName, "incremental-restore.json"); - if (await utils_exists(incrementalJson)) { - const contents = await external_fs_default().promises.readFile(incrementalJson, "utf8"); - const { modifiedTimes } = JSON.parse(contents); - lib_core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); - // Write the mtimes to all the files in the profile directory - for (const fileName of Object.keys(modifiedTimes)) { - const mtime = modifiedTimes[fileName]; - const filePath = external_path_default().join(dirName, fileName); - await external_fs_default().promises.utimes(filePath, new Date(mtime), new Date(mtime)); - } - } - else { - lib_core.debug(`incremental-restore.json not found for ${dirName}`); - } -} - ;// CONCATENATED MODULE: ./src/restore.ts +// import { saveMtimes } from "./incremental"; + process.on("uncaughtException", (e) => { lib_core.error(e.message); @@ -87424,14 +87375,20 @@ async function run() { if (restoreKey) { const match = restoreKey === key; lib_core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); + // Restore the incremental-restore.json file and write the mtimes to all the files in the list if (config.incremental) { - const incrementalKey = await cacheProvider.cache.restoreCache(config.incrementalPaths.slice(), config.incrementalKey, [config.restoreKey], { lookupOnly }); - lib_core.debug(`restoring incremental builds from ${incrementalKey}`); - if (incrementalKey) { - for (const workspace of config.workspaces) { - await restoreIncremental(workspace.target); + try { + const restoreJson = external_path_default().join(config_CARGO_HOME, "incremental-restore.json"); + const restoreString = await external_fs_default().promises.readFile(restoreJson, "utf8"); + const restoreData = JSON.parse(restoreString); + for (const [file, mtime] of Object.entries(restoreData)) { + await external_fs_default().promises.utimes(file, new Date(mtime), new Date(mtime)); } } + catch (err) { + lib_core.debug(`Could not restore incremental cache - ${err}`); + lib_core.debug(`${err.stack}`); + } } if (!match) { // pre-clean the target directory on cache mismatch diff --git a/dist/save/index.js b/dist/save/index.js index 2d1c5cc..5683009 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -86712,7 +86712,7 @@ class CacheConfig { /** All the paths we want to cache */ this.cachePaths = []; /** All the paths we want to cache for incremental builds */ - this.incrementalPaths = []; + // public incrementalPaths: Array = []; /** The primary cache key */ this.cacheKey = ""; /** The primary cache key for incremental builds */ @@ -86926,11 +86926,8 @@ class CacheConfig { const branchName = core.getInput("incremental-key") || "-shared"; const incrementalKey = key + `-incremental--` + branchName; self.incrementalKey = incrementalKey; - if (cacheTargets === "true") { - for (const target of self.workspaces.map((ws) => ws.target)) { - self.incrementalPaths.push(external_path_default().join(target, "incremental")); - } - } + // Add the incremental cache to the cachePaths so we can restore it + self.cachePaths.push(external_path_default().join(CARGO_HOME, "incremental-restore.json")); } return self; } @@ -87334,6 +87331,34 @@ async function rmRF(dirName) { await io.rmRF(dirName); } +;// CONCATENATED MODULE: ./src/incremental.ts +// import * as core from "@actions/core"; +// import * as io from "@actions/io"; + + +// import { CARGO_HOME } from "./config"; +// import { exists } from "./utils"; +// import { Packages } from "./workspace"; +async function saveMtimes(targetDirs) { + let cache = new Map(); + let stack = targetDirs.slice(); + while (stack.length > 0) { + const dirName = stack.pop(); + const dir = await external_fs_default().promises.opendir(dirName); + for await (const dirent of dir) { + if (dirent.isDirectory()) { + stack.push(external_path_default().join(dirName, dirent.name)); + } + else { + const fileName = external_path_default().join(dirName, dirent.name); + const { mtime } = await external_fs_default().promises.stat(fileName); + cache.set(fileName, mtime.getTime()); + } + } + } + return cache; +} + ;// CONCATENATED MODULE: ./src/save.ts @@ -87343,6 +87368,7 @@ async function rmRF(dirName) { + process.on("uncaughtException", (e) => { core.error(e.message); if (e.stack) { @@ -87371,12 +87397,16 @@ async function run() { if (config.incremental) { core.info(`... Saving incremental cache ...`); try { - core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); - for (const paths of config.incrementalPaths) { - await saveIncrementalDirs(paths); - } - await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); - for (const path of config.incrementalPaths) { + const targetDirs = config.workspaces.map((ws) => ws.target); + const cache = await saveMtimes(targetDirs); + const paths = Array.from(cache.keys()); + const saved = await cacheProvider.cache.saveCache(paths, config.incrementalKey); + core.debug(`saved incremental cache with key ${saved} with contents ${paths}`); + // write the incremental-restore.json file + const serialized = JSON.stringify(cache); + await external_fs_default().promises.writeFile(external_path_default().join(CARGO_HOME, "incremental-restore.json"), serialized); + // Delete the incremental cache before proceeding + for (const [path, _mtime] of cache) { core.debug(` deleting ${path}`); await (0,promises_.rm)(path); } @@ -87392,7 +87422,7 @@ async function run() { allPackages.push(...packages); try { core.info(`... Cleaning ${workspace.target} ...`); - await cleanTargetDir(workspace.target, packages, false); + await cleanTargetDir(workspace.target, packages); } catch (e) { core.debug(`${e.stack}`); @@ -87442,31 +87472,30 @@ async function macOsWorkaround() { } catch { } } -async function saveIncrementalDirs(incrementalDir) { - // Traverse the incremental folder recursively and collect the modified times in a map - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir) => { - const dirEntries = await external_fs_default().promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(external_path_default().join(dir, dirent.name)); - } - else { - const fileName = external_path_default().join(dir, dirent.name); - const { mtime } = await external_fs_default().promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); - // Write the modified times to the incremental folder - core.debug(`writing incremental-restore.json for ${incrementalDir} files`); - for (const file of modifiedTimes.keys()) { - core.debug(` ${file} -> ${modifiedTimes.get(file)}`); - } - const contents = JSON.stringify({ modifiedTimes }); - await external_fs_default().promises.writeFile(external_path_default().join(incrementalDir, "incremental-restore.json"), contents); -} +// async function saveIncrementalDirs(incrementalDir: string) { +// // Traverse the incremental folder recursively and collect the modified times in a map +// const modifiedTimes = new Map(); +// const fillModifiedTimes = async (dir: string) => { +// const dirEntries = await fs.promises.opendir(dir); +// for await (const dirent of dirEntries) { +// if (dirent.isDirectory()) { +// await fillModifiedTimes(path.join(dir, dirent.name)); +// } else { +// const fileName = path.join(dir, dirent.name); +// const { mtime } = await fs.promises.stat(fileName); +// modifiedTimes.set(fileName, mtime.getTime()); +// } +// } +// }; +// await fillModifiedTimes(incrementalDir); +// // Write the modified times to the incremental folder +// core.debug(`writing incremental-restore.json for ${incrementalDir} files`); +// for (const file of modifiedTimes.keys()) { +// core.debug(` ${file} -> ${modifiedTimes.get(file)}`); +// } +// const contents = JSON.stringify({ modifiedTimes }); +// await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); +// } })(); diff --git a/src/config.ts b/src/config.ts index 0c95e94..455f53c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -22,7 +22,7 @@ export class CacheConfig { public cachePaths: Array = []; /** All the paths we want to cache for incremental builds */ - public incrementalPaths: Array = []; + // public incrementalPaths: Array = []; /** The primary cache key */ public cacheKey = ""; @@ -292,11 +292,8 @@ export class CacheConfig { const incrementalKey = key + `-incremental--` + branchName; self.incrementalKey = incrementalKey; - if (cacheTargets === "true") { - for (const target of self.workspaces.map((ws) => ws.target)) { - self.incrementalPaths.push(path.join(target, "incremental")); - } - } + // Add the incremental cache to the cachePaths so we can restore it + self.cachePaths.push(path.join(CARGO_HOME, "incremental-restore.json")); } return self; diff --git a/src/incremental.ts b/src/incremental.ts index 56e75ba..a6c8b79 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -1,50 +1,30 @@ -import * as core from "@actions/core"; +// import * as core from "@actions/core"; // import * as io from "@actions/io"; import fs from "fs"; import path from "path"; // import { CARGO_HOME } from "./config"; -import { exists } from "./utils"; +// import { exists } from "./utils"; // import { Packages } from "./workspace"; -export async function restoreIncremental(targetDir: string) { - core.debug(`restoring incremental directory "${targetDir}"`); +export async function saveMtimes(targetDirs: string[]): Promise> { + let cache = new Map(); + let stack = targetDirs.slice(); - let dir = await fs.promises.opendir(targetDir); - for await (const dirent of dir) { - if (dirent.isDirectory()) { - let dirName = path.join(dir.path, dirent.name); - // is it a profile dir, or a nested target dir? - let isNestedTarget = - (await exists(path.join(dirName, "CACHEDIR.TAG"))) || (await exists(path.join(dirName, ".rustc_info.json"))); + while (stack.length > 0) { + const dirName = stack.pop()!; + const dir = await fs.promises.opendir(dirName); - try { - if (isNestedTarget) { - await restoreIncremental(dirName); - } else { - await restoreIncrementalProfile(dirName); - } restoreIncrementalProfile - } catch { } + for await (const dirent of dir) { + if (dirent.isDirectory()) { + stack.push(path.join(dirName, dirent.name)); + } else { + const fileName = path.join(dirName, dirent.name); + const { mtime } = await fs.promises.stat(fileName); + cache.set(fileName, mtime.getTime()); + } } } -} - -async function restoreIncrementalProfile(dirName: string) { - core.debug(`restoring incremental profile directory "${dirName}"`); - const incrementalJson = path.join(dirName, "incremental-restore.json"); - if (await exists(incrementalJson)) { - const contents = await fs.promises.readFile(incrementalJson, "utf8"); - const { modifiedTimes } = JSON.parse(contents); - - core.debug(`restoring incremental profile directory "${dirName}" with ${modifiedTimes} files`); - - // Write the mtimes to all the files in the profile directory - for (const fileName of Object.keys(modifiedTimes)) { - const mtime = modifiedTimes[fileName]; - const filePath = path.join(dirName, fileName); - await fs.promises.utimes(filePath, new Date(mtime), new Date(mtime)); - } - } else { - core.debug(`incremental-restore.json not found for ${dirName}`); - } + + return cache; } diff --git a/src/restore.ts b/src/restore.ts index 9adde48..b6e3e4c 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -1,9 +1,11 @@ import * as core from "@actions/core"; import { cleanTargetDir } from "./cleanup"; -import { CacheConfig } from "./config"; +import { CacheConfig, CARGO_HOME } from "./config"; import { getCacheProvider, reportError } from "./utils"; -import { restoreIncremental } from "./incremental"; +// import { saveMtimes } from "./incremental"; +import path from "path"; +import fs from "fs"; process.on("uncaughtException", (e) => { core.error(e.message); @@ -49,14 +51,18 @@ async function run() { const match = restoreKey === key; core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); + // Restore the incremental-restore.json file and write the mtimes to all the files in the list if (config.incremental) { - const incrementalKey = await cacheProvider.cache.restoreCache(config.incrementalPaths.slice(), config.incrementalKey, [config.restoreKey], { lookupOnly }); - core.debug(`restoring incremental builds from ${incrementalKey}`); - - if (incrementalKey) { - for (const workspace of config.workspaces) { - await restoreIncremental(workspace.target); + try { + const restoreJson = path.join(CARGO_HOME, "incremental-restore.json") + const restoreString = await fs.promises.readFile(restoreJson, "utf8"); + const restoreData: Map = JSON.parse(restoreString); + for (const [file, mtime] of Object.entries(restoreData)) { + await fs.promises.utimes(file, new Date(mtime), new Date(mtime)); } + } catch (err) { + core.debug(`Could not restore incremental cache - ${err}`); + core.debug(`${(err as any).stack}`); } } diff --git a/src/save.ts b/src/save.ts index b452669..558db6e 100644 --- a/src/save.ts +++ b/src/save.ts @@ -2,11 +2,12 @@ import * as core from "@actions/core"; import * as exec from "@actions/exec"; import { cleanBin, cleanGit, cleanRegistry, cleanTargetDir } from "./cleanup"; -import { CacheConfig, isCacheUpToDate } from "./config"; +import { CacheConfig, CARGO_HOME, isCacheUpToDate } from "./config"; import { getCacheProvider, reportError } from "./utils"; import { rm } from "fs/promises"; import fs from "fs"; import path from "path"; +import { saveMtimes } from "./incremental"; process.on("uncaughtException", (e) => { core.error(e.message); @@ -43,12 +44,18 @@ async function run() { if (config.incremental) { core.info(`... Saving incremental cache ...`); try { - core.debug(`paths include ${config.incrementalPaths} with key ${config.incrementalKey}`); - for (const paths of config.incrementalPaths) { - await saveIncrementalDirs(paths); - } - await cacheProvider.cache.saveCache(config.incrementalPaths.slice(), config.incrementalKey); - for (const path of config.incrementalPaths) { + const targetDirs = config.workspaces.map((ws) => ws.target); + const cache = await saveMtimes(targetDirs); + const paths = Array.from(cache.keys()); + const saved = await cacheProvider.cache.saveCache(paths, config.incrementalKey); + core.debug(`saved incremental cache with key ${saved} with contents ${paths}`); + + // write the incremental-restore.json file + const serialized = JSON.stringify(cache); + await fs.promises.writeFile(path.join(CARGO_HOME, "incremental-restore.json"), serialized); + + // Delete the incremental cache before proceeding + for (const [path, _mtime] of cache) { core.debug(` deleting ${path}`); await rm(path); } @@ -64,7 +71,7 @@ async function run() { allPackages.push(...packages); try { core.info(`... Cleaning ${workspace.target} ...`); - await cleanTargetDir(workspace.target, packages, false); + await cleanTargetDir(workspace.target, packages); } catch (e) { core.debug(`${(e as any).stack}`); } @@ -99,7 +106,6 @@ async function run() { // https://github.com/actions/toolkit/pull/1378 // TODO: remove this once the underlying bug is fixed. await cacheProvider.cache.saveCache(config.cachePaths.slice(), config.cacheKey); - } catch (e) { reportError(e); } @@ -117,29 +123,29 @@ async function macOsWorkaround() { } -async function saveIncrementalDirs(incrementalDir: string) { - // Traverse the incremental folder recursively and collect the modified times in a map - const modifiedTimes = new Map(); - const fillModifiedTimes = async (dir: string) => { - const dirEntries = await fs.promises.opendir(dir); - for await (const dirent of dirEntries) { - if (dirent.isDirectory()) { - await fillModifiedTimes(path.join(dir, dirent.name)); - } else { - const fileName = path.join(dir, dirent.name); - const { mtime } = await fs.promises.stat(fileName); - modifiedTimes.set(fileName, mtime.getTime()); - } - } - }; - await fillModifiedTimes(incrementalDir); +// async function saveIncrementalDirs(incrementalDir: string) { +// // Traverse the incremental folder recursively and collect the modified times in a map +// const modifiedTimes = new Map(); +// const fillModifiedTimes = async (dir: string) => { +// const dirEntries = await fs.promises.opendir(dir); +// for await (const dirent of dirEntries) { +// if (dirent.isDirectory()) { +// await fillModifiedTimes(path.join(dir, dirent.name)); +// } else { +// const fileName = path.join(dir, dirent.name); +// const { mtime } = await fs.promises.stat(fileName); +// modifiedTimes.set(fileName, mtime.getTime()); +// } +// } +// }; +// await fillModifiedTimes(incrementalDir); - // Write the modified times to the incremental folder - core.debug(`writing incremental-restore.json for ${incrementalDir} files`); - for (const file of modifiedTimes.keys()) { - core.debug(` ${file} -> ${modifiedTimes.get(file)}`); - } - const contents = JSON.stringify({ modifiedTimes }); - await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); +// // Write the modified times to the incremental folder +// core.debug(`writing incremental-restore.json for ${incrementalDir} files`); +// for (const file of modifiedTimes.keys()) { +// core.debug(` ${file} -> ${modifiedTimes.get(file)}`); +// } +// const contents = JSON.stringify({ modifiedTimes }); +// await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); -} +// } From 6095cc4363e445dab3543d797dd793d0ee426e6f Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 22:53:29 -0800 Subject: [PATCH 23/26] cache the roots not the files --- dist/restore/index.js | 5 ++++- dist/save/index.js | 30 +++++++++++++++++++----------- src/incremental.ts | 29 ++++++++++++++++++++++++----- src/restore.ts | 13 ++++++++++--- src/save.ts | 7 +++---- 5 files changed, 60 insertions(+), 24 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 310327f..72cc878 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -87381,7 +87381,10 @@ async function run() { const restoreJson = external_path_default().join(config_CARGO_HOME, "incremental-restore.json"); const restoreString = await external_fs_default().promises.readFile(restoreJson, "utf8"); const restoreData = JSON.parse(restoreString); - for (const [file, mtime] of Object.entries(restoreData)) { + const incrementalKey = await cacheProvider.cache.restoreCache(restoreData.roots, config.incrementalKey, [config.restoreKey], { lookupOnly }); + lib_core.debug(`restoring incremental builds from ${incrementalKey}`); + for (const [file, mtime] of Object.entries(restoreData.times)) { + lib_core.debug(`restoring ${file} with mtime ${mtime}`); await external_fs_default().promises.utimes(file, new Date(mtime), new Date(mtime)); } } diff --git a/dist/save/index.js b/dist/save/index.js index 5683009..c1a8ccc 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -87336,12 +87336,21 @@ async function rmRF(dirName) { // import * as io from "@actions/io"; -// import { CARGO_HOME } from "./config"; -// import { exists } from "./utils"; -// import { Packages } from "./workspace"; async function saveMtimes(targetDirs) { - let cache = new Map(); - let stack = targetDirs.slice(); + let times = new Map(); + let stack = new Array(); + // Collect all the incremental files + for (const dir of targetDirs) { + for (const maybeProfile of await external_fs_default().promises.readdir(dir)) { + const profileDir = external_path_default().join(dir, maybeProfile); + const incrementalDir = external_path_default().join(profileDir, "incremental"); + if (external_fs_default().existsSync(incrementalDir)) { + stack.push(incrementalDir); + } + } + } + // Save the stack as the roots - we cache these directly + let roots = stack.slice(); while (stack.length > 0) { const dirName = stack.pop(); const dir = await external_fs_default().promises.opendir(dirName); @@ -87352,11 +87361,11 @@ async function saveMtimes(targetDirs) { else { const fileName = external_path_default().join(dirName, dirent.name); const { mtime } = await external_fs_default().promises.stat(fileName); - cache.set(fileName, mtime.getTime()); + times.set(fileName, mtime.getTime()); } } } - return cache; + return { roots, times: times }; } ;// CONCATENATED MODULE: ./src/save.ts @@ -87399,14 +87408,13 @@ async function run() { try { const targetDirs = config.workspaces.map((ws) => ws.target); const cache = await saveMtimes(targetDirs); - const paths = Array.from(cache.keys()); - const saved = await cacheProvider.cache.saveCache(paths, config.incrementalKey); - core.debug(`saved incremental cache with key ${saved} with contents ${paths}`); + const saved = await cacheProvider.cache.saveCache(cache.roots, config.incrementalKey); + core.debug(`saved incremental cache with key ${saved} with contents ${cache.roots}, ${cache.times}`); // write the incremental-restore.json file const serialized = JSON.stringify(cache); await external_fs_default().promises.writeFile(external_path_default().join(CARGO_HOME, "incremental-restore.json"), serialized); // Delete the incremental cache before proceeding - for (const [path, _mtime] of cache) { + for (const [path, _mtime] of cache.roots) { core.debug(` deleting ${path}`); await (0,promises_.rm)(path); } diff --git a/src/incremental.ts b/src/incremental.ts index a6c8b79..b33272e 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -7,9 +7,28 @@ import path from "path"; // import { exists } from "./utils"; // import { Packages } from "./workspace"; -export async function saveMtimes(targetDirs: string[]): Promise> { - let cache = new Map(); - let stack = targetDirs.slice(); +export type MtimeData = { + roots: Array, + times: Map +}; + +export async function saveMtimes(targetDirs: string[]): Promise { + let times = new Map(); + let stack = new Array(); + + // Collect all the incremental files + for (const dir of targetDirs) { + for (const maybeProfile of await fs.promises.readdir(dir)) { + const profileDir = path.join(dir, maybeProfile); + const incrementalDir = path.join(profileDir, "incremental"); + if (fs.existsSync(incrementalDir)) { + stack.push(incrementalDir); + } + } + } + + // Save the stack as the roots - we cache these directly + let roots = stack.slice(); while (stack.length > 0) { const dirName = stack.pop()!; @@ -21,10 +40,10 @@ export async function saveMtimes(targetDirs: string[]): Promise { core.error(e.message); @@ -54,12 +55,18 @@ async function run() { // Restore the incremental-restore.json file and write the mtimes to all the files in the list if (config.incremental) { try { - const restoreJson = path.join(CARGO_HOME, "incremental-restore.json") + const restoreJson = path.join(CARGO_HOME, "incremental-restore.json"); const restoreString = await fs.promises.readFile(restoreJson, "utf8"); - const restoreData: Map = JSON.parse(restoreString); - for (const [file, mtime] of Object.entries(restoreData)) { + const restoreData: MtimeData = JSON.parse(restoreString); + + const incrementalKey = await cacheProvider.cache.restoreCache(restoreData.roots, config.incrementalKey, [config.restoreKey], { lookupOnly }); + core.debug(`restoring incremental builds from ${incrementalKey}`); + + for (const [file, mtime] of Object.entries(restoreData.times)) { + core.debug(`restoring ${file} with mtime ${mtime}`); await fs.promises.utimes(file, new Date(mtime), new Date(mtime)); } + } catch (err) { core.debug(`Could not restore incremental cache - ${err}`); core.debug(`${(err as any).stack}`); diff --git a/src/save.ts b/src/save.ts index 558db6e..259087b 100644 --- a/src/save.ts +++ b/src/save.ts @@ -46,16 +46,15 @@ async function run() { try { const targetDirs = config.workspaces.map((ws) => ws.target); const cache = await saveMtimes(targetDirs); - const paths = Array.from(cache.keys()); - const saved = await cacheProvider.cache.saveCache(paths, config.incrementalKey); - core.debug(`saved incremental cache with key ${saved} with contents ${paths}`); + const saved = await cacheProvider.cache.saveCache(cache.roots, config.incrementalKey); + core.debug(`saved incremental cache with key ${saved} with contents ${cache.roots}, ${cache.times}`); // write the incremental-restore.json file const serialized = JSON.stringify(cache); await fs.promises.writeFile(path.join(CARGO_HOME, "incremental-restore.json"), serialized); // Delete the incremental cache before proceeding - for (const [path, _mtime] of cache) { + for (const [path, _mtime] of cache.roots) { core.debug(` deleting ${path}`); await rm(path); } From 470b5b92f9f2b4d55e157c818d19b1af6dea3ad2 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 23:07:34 -0800 Subject: [PATCH 24/26] force a cache --- dist/restore/index.js | 42 +++++++++++++++++++++++------------------- dist/save/index.js | 27 +++------------------------ src/incremental.ts | 6 +++--- src/restore.ts | 31 ++++++++++++++++++------------- src/save.ts | 28 ---------------------------- 5 files changed, 47 insertions(+), 87 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 72cc878..dc66796 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -87373,26 +87373,8 @@ async function run() { lookupOnly, }); if (restoreKey) { - const match = restoreKey === key; + let match = restoreKey === key; lib_core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); - // Restore the incremental-restore.json file and write the mtimes to all the files in the list - if (config.incremental) { - try { - const restoreJson = external_path_default().join(config_CARGO_HOME, "incremental-restore.json"); - const restoreString = await external_fs_default().promises.readFile(restoreJson, "utf8"); - const restoreData = JSON.parse(restoreString); - const incrementalKey = await cacheProvider.cache.restoreCache(restoreData.roots, config.incrementalKey, [config.restoreKey], { lookupOnly }); - lib_core.debug(`restoring incremental builds from ${incrementalKey}`); - for (const [file, mtime] of Object.entries(restoreData.times)) { - lib_core.debug(`restoring ${file} with mtime ${mtime}`); - await external_fs_default().promises.utimes(file, new Date(mtime), new Date(mtime)); - } - } - catch (err) { - lib_core.debug(`Could not restore incremental cache - ${err}`); - lib_core.debug(`${err.stack}`); - } - } if (!match) { // pre-clean the target directory on cache mismatch for (const workspace of config.workspaces) { @@ -87404,6 +87386,28 @@ async function run() { // We restored the cache but it is not a full match. config.saveState(); } + // Restore the incremental-restore.json file and write the mtimes to all the files in the list + if (config.incremental) { + try { + const restoreJson = external_path_default().join(config_CARGO_HOME, "incremental-restore.json"); + const restoreString = await external_fs_default().promises.readFile(restoreJson, "utf8"); + const restoreData = JSON.parse(restoreString); + if (restoreData.roots.length == 0) { + throw new Error("No incremental roots found"); + } + const incrementalKey = await cacheProvider.cache.restoreCache(restoreData.roots, config.incrementalKey, [config.restoreKey], { lookupOnly }); + lib_core.debug(`restoring incremental builds from ${incrementalKey}`); + for (const [file, mtime] of Object.entries(restoreData.times)) { + lib_core.debug(`restoring ${file} with mtime ${mtime}`); + await external_fs_default().promises.utimes(file, new Date(mtime), new Date(mtime)); + } + } + catch (err) { + lib_core.debug(`Could not restore incremental cache - ${err}`); + lib_core.debug(`${err.stack}`); + match = false; + } + } setCacheHitOutput(match); } else { diff --git a/dist/save/index.js b/dist/save/index.js index c1a8ccc..d21f420 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -87334,6 +87334,9 @@ async function rmRF(dirName) { ;// CONCATENATED MODULE: ./src/incremental.ts // import * as core from "@actions/core"; // import * as io from "@actions/io"; +// import { CARGO_HOME } from "./config"; +// import { exists } from "./utils"; +// import { Packages } from "./workspace"; async function saveMtimes(targetDirs) { @@ -87480,30 +87483,6 @@ async function macOsWorkaround() { } catch { } } -// async function saveIncrementalDirs(incrementalDir: string) { -// // Traverse the incremental folder recursively and collect the modified times in a map -// const modifiedTimes = new Map(); -// const fillModifiedTimes = async (dir: string) => { -// const dirEntries = await fs.promises.opendir(dir); -// for await (const dirent of dirEntries) { -// if (dirent.isDirectory()) { -// await fillModifiedTimes(path.join(dir, dirent.name)); -// } else { -// const fileName = path.join(dir, dirent.name); -// const { mtime } = await fs.promises.stat(fileName); -// modifiedTimes.set(fileName, mtime.getTime()); -// } -// } -// }; -// await fillModifiedTimes(incrementalDir); -// // Write the modified times to the incremental folder -// core.debug(`writing incremental-restore.json for ${incrementalDir} files`); -// for (const file of modifiedTimes.keys()) { -// core.debug(` ${file} -> ${modifiedTimes.get(file)}`); -// } -// const contents = JSON.stringify({ modifiedTimes }); -// await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); -// } })(); diff --git a/src/incremental.ts b/src/incremental.ts index b33272e..2738179 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -1,12 +1,12 @@ // import * as core from "@actions/core"; // import * as io from "@actions/io"; -import fs from "fs"; -import path from "path"; - // import { CARGO_HOME } from "./config"; // import { exists } from "./utils"; // import { Packages } from "./workspace"; +import fs from "fs"; +import path from "path"; + export type MtimeData = { roots: Array, times: Map diff --git a/src/restore.ts b/src/restore.ts index 81f9142..9a8c7e9 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -49,9 +49,21 @@ async function run() { lookupOnly, }); if (restoreKey) { - const match = restoreKey === key; + let match = restoreKey === key; core.info(`${lookupOnly ? "Found" : "Restored from"} cache key "${restoreKey}" full match: ${match}.`); + if (!match) { + // pre-clean the target directory on cache mismatch + for (const workspace of config.workspaces) { + try { + await cleanTargetDir(workspace.target, [], true); + } catch { } + } + + // We restored the cache but it is not a full match. + config.saveState(); + } + // Restore the incremental-restore.json file and write the mtimes to all the files in the list if (config.incremental) { try { @@ -59,6 +71,10 @@ async function run() { const restoreString = await fs.promises.readFile(restoreJson, "utf8"); const restoreData: MtimeData = JSON.parse(restoreString); + if (restoreData.roots.length == 0) { + throw new Error("No incremental roots found"); + } + const incrementalKey = await cacheProvider.cache.restoreCache(restoreData.roots, config.incrementalKey, [config.restoreKey], { lookupOnly }); core.debug(`restoring incremental builds from ${incrementalKey}`); @@ -70,21 +86,10 @@ async function run() { } catch (err) { core.debug(`Could not restore incremental cache - ${err}`); core.debug(`${(err as any).stack}`); + match = false; } } - if (!match) { - // pre-clean the target directory on cache mismatch - for (const workspace of config.workspaces) { - try { - await cleanTargetDir(workspace.target, [], true); - } catch { } - } - - // We restored the cache but it is not a full match. - config.saveState(); - } - setCacheHitOutput(match); } else { core.info(`No cache found for ${config.cacheKey} - this key was found ${restoreKey}`); diff --git a/src/save.ts b/src/save.ts index 259087b..be36fbc 100644 --- a/src/save.ts +++ b/src/save.ts @@ -120,31 +120,3 @@ async function macOsWorkaround() { await exec.exec("sudo", ["/usr/sbin/purge"], { silent: true }); } catch { } } - - -// async function saveIncrementalDirs(incrementalDir: string) { -// // Traverse the incremental folder recursively and collect the modified times in a map -// const modifiedTimes = new Map(); -// const fillModifiedTimes = async (dir: string) => { -// const dirEntries = await fs.promises.opendir(dir); -// for await (const dirent of dirEntries) { -// if (dirent.isDirectory()) { -// await fillModifiedTimes(path.join(dir, dirent.name)); -// } else { -// const fileName = path.join(dir, dirent.name); -// const { mtime } = await fs.promises.stat(fileName); -// modifiedTimes.set(fileName, mtime.getTime()); -// } -// } -// }; -// await fillModifiedTimes(incrementalDir); - -// // Write the modified times to the incremental folder -// core.debug(`writing incremental-restore.json for ${incrementalDir} files`); -// for (const file of modifiedTimes.keys()) { -// core.debug(` ${file} -> ${modifiedTimes.get(file)}`); -// } -// const contents = JSON.stringify({ modifiedTimes }); -// await fs.promises.writeFile(path.join(incrementalDir, "incremental-restore.json"), contents); - -// } From 5bbbdb911510b4a5e75004a05162562f6c4c0c0b Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 23:20:55 -0800 Subject: [PATCH 25/26] save state with incremental --- dist/restore/index.js | 1 + src/restore.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/dist/restore/index.js b/dist/restore/index.js index dc66796..8005768 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -87407,6 +87407,7 @@ async function run() { lib_core.debug(`${err.stack}`); match = false; } + config.saveState(); } setCacheHitOutput(match); } diff --git a/src/restore.ts b/src/restore.ts index 9a8c7e9..dcd1caa 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -88,6 +88,7 @@ async function run() { core.debug(`${(err as any).stack}`); match = false; } + config.saveState(); } setCacheHitOutput(match); From 829dfd6b080c828ef2dddc6752b3d41753ccbd1b Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Jan 2025 23:37:52 -0800 Subject: [PATCH 26/26] serialization bugs --- dist/restore/index.js | 1 + dist/save/index.js | 13 ++++++++----- src/incremental.ts | 19 ++++++++++++------- src/restore.ts | 2 ++ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 8005768..6882650 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -87392,6 +87392,7 @@ async function run() { const restoreJson = external_path_default().join(config_CARGO_HOME, "incremental-restore.json"); const restoreString = await external_fs_default().promises.readFile(restoreJson, "utf8"); const restoreData = JSON.parse(restoreString); + lib_core.debug(`restoreData: ${JSON.stringify(restoreData)}`); if (restoreData.roots.length == 0) { throw new Error("No incremental roots found"); } diff --git a/dist/save/index.js b/dist/save/index.js index d21f420..cee0247 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -87340,8 +87340,11 @@ async function rmRF(dirName) { async function saveMtimes(targetDirs) { - let times = new Map(); - let stack = new Array(); + let data = { + roots: [], + times: {}, + }; + let stack = []; // Collect all the incremental files for (const dir of targetDirs) { for (const maybeProfile of await external_fs_default().promises.readdir(dir)) { @@ -87353,7 +87356,7 @@ async function saveMtimes(targetDirs) { } } // Save the stack as the roots - we cache these directly - let roots = stack.slice(); + data.roots = stack.slice(); while (stack.length > 0) { const dirName = stack.pop(); const dir = await external_fs_default().promises.opendir(dirName); @@ -87364,11 +87367,11 @@ async function saveMtimes(targetDirs) { else { const fileName = external_path_default().join(dirName, dirent.name); const { mtime } = await external_fs_default().promises.stat(fileName); - times.set(fileName, mtime.getTime()); + data.times[fileName] = mtime.getTime(); } } } - return { roots, times: times }; + return data; } ;// CONCATENATED MODULE: ./src/save.ts diff --git a/src/incremental.ts b/src/incremental.ts index 2738179..4e8865a 100644 --- a/src/incremental.ts +++ b/src/incremental.ts @@ -8,13 +8,18 @@ import fs from "fs"; import path from "path"; export type MtimeData = { - roots: Array, - times: Map + roots: string[], + times: { + [key: string]: number + } }; export async function saveMtimes(targetDirs: string[]): Promise { - let times = new Map(); - let stack = new Array(); + let data: MtimeData = { + roots: [], + times: {}, + }; + let stack: string[] = []; // Collect all the incremental files for (const dir of targetDirs) { @@ -28,7 +33,7 @@ export async function saveMtimes(targetDirs: string[]): Promise { } // Save the stack as the roots - we cache these directly - let roots = stack.slice(); + data.roots = stack.slice(); while (stack.length > 0) { const dirName = stack.pop()!; @@ -40,10 +45,10 @@ export async function saveMtimes(targetDirs: string[]): Promise { } else { const fileName = path.join(dirName, dirent.name); const { mtime } = await fs.promises.stat(fileName); - times.set(fileName, mtime.getTime()); + data.times[fileName] = mtime.getTime(); } } } - return { roots, times: times }; + return data; } diff --git a/src/restore.ts b/src/restore.ts index dcd1caa..78e7975 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -71,6 +71,8 @@ async function run() { const restoreString = await fs.promises.readFile(restoreJson, "utf8"); const restoreData: MtimeData = JSON.parse(restoreString); + core.debug(`restoreData: ${JSON.stringify(restoreData)}`); + if (restoreData.roots.length == 0) { throw new Error("No incremental roots found"); }