@@ -59977,8 +59977,8 @@ async function getCmdOutput(cmd, args = [], options = {}) {
5997759977 });
5997859978 }
5997959979 catch (e) {
59980- lib_core.info(`[warning] Command failed: ${cmd} ${args.join(" ")}`);
59981- lib_core.info(`[warning] ${ stderr}` );
59980+ lib_core.error(` Command failed: ${cmd} ${args.join(" ")}`);
59981+ lib_core.error( stderr);
5998259982 throw e;
5998359983 }
5998459984 return stdout;
@@ -60024,12 +60024,10 @@ class Workspace {
6002460024
6002560025
6002660026
60027+
6002760028const HOME = external_os_default().homedir();
6002860029const config_CARGO_HOME = process.env.CARGO_HOME || external_path_default().join(HOME, ".cargo");
60029- const STATE_LOCKFILE_HASH = "RUST_CACHE_LOCKFILE_HASH";
60030- const STATE_LOCKFILES = "RUST_CACHE_LOCKFILES";
60031- const config_STATE_BINS = "RUST_CACHE_BINS";
60032- const STATE_KEY = "RUST_CACHE_KEY";
60030+ const STATE_CONFIG = "RUST_CACHE_CONFIG";
6003360031class CacheConfig {
6003460032 constructor() {
6003560033 /** All the paths we want to cache */
@@ -60040,6 +60038,8 @@ class CacheConfig {
6004060038 this.restoreKey = "";
6004160039 /** The workspace configurations */
6004260040 this.workspaces = [];
60041+ /** The cargo binaries present during main step */
60042+ this.cargoBins = [];
6004360043 /** The prefix portion of the cache key */
6004460044 this.keyPrefix = "";
6004560045 /** The rust version considered for the cache key */
@@ -60103,20 +60103,11 @@ class CacheConfig {
6010360103 }
6010460104 }
6010560105 self.keyEnvs = keyEnvs;
60106- // Installed packages and their versions are also considered for the key.
60107- const packages = await getPackages();
60108- hasher.update(packages);
6010960106 key += `-${hasher.digest("hex")}`;
6011060107 self.restoreKey = key;
6011160108 // Construct the lockfiles portion of the key:
6011260109 // This considers all the files found via globbing for various manifests
6011360110 // and lockfiles.
60114- // This part is computed in the "pre"/"restore" part of the job and persisted
60115- // into the `state`. That state is loaded in the "post"/"save" part of the
60116- // job so we have consistent values even though the "main" actions run
60117- // might create/overwrite lockfiles.
60118- let lockHash = lib_core.getState(STATE_LOCKFILE_HASH);
60119- let keyFiles = JSON.parse(lib_core.getState(STATE_LOCKFILES) || "[]");
6012060111 // Constructs the workspace config and paths to restore:
6012160112 // The workspaces are given using a `$workspace -> $target` syntax.
6012260113 const workspaces = [];
@@ -60128,24 +60119,20 @@ class CacheConfig {
6012860119 workspaces.push(new Workspace(root, target));
6012960120 }
6013060121 self.workspaces = workspaces;
60131- if (!lockHash) {
60132- keyFiles = keyFiles.concat(await globFiles("rust-toolchain\nrust-toolchain.toml"));
60133- for (const workspace of workspaces) {
60134- const root = workspace.root;
60135- keyFiles.push(...(await globFiles(`${root}/**/Cargo.toml\n${root}/**/Cargo.lock\n${root}/**/rust-toolchain\n${root}/**/rust-toolchain.toml`)));
60136- }
60137- keyFiles = keyFiles.filter(file => !external_fs_default().statSync(file).isDirectory());
60138- keyFiles.sort((a, b) => a.localeCompare(b));
60139- hasher = external_crypto_default().createHash("sha1");
60140- for (const file of keyFiles) {
60141- for await (const chunk of external_fs_default().createReadStream(file)) {
60142- hasher.update(chunk);
60143- }
60122+ let keyFiles = await globFiles("rust-toolchain\nrust-toolchain.toml");
60123+ for (const workspace of workspaces) {
60124+ const root = workspace.root;
60125+ keyFiles.push(...(await globFiles(`${root}/**/Cargo.toml\n${root}/**/Cargo.lock\n${root}/**/rust-toolchain\n${root}/**/rust-toolchain.toml`)));
60126+ }
60127+ keyFiles = keyFiles.filter(file => !external_fs_default().statSync(file).isDirectory());
60128+ keyFiles.sort((a, b) => a.localeCompare(b));
60129+ hasher = external_crypto_default().createHash("sha1");
60130+ for (const file of keyFiles) {
60131+ for await (const chunk of external_fs_default().createReadStream(file)) {
60132+ hasher.update(chunk);
6014460133 }
60145- lockHash = hasher.digest("hex");
60146- lib_core.saveState(STATE_LOCKFILE_HASH, lockHash);
60147- lib_core.saveState(STATE_LOCKFILES, JSON.stringify(keyFiles));
6014860134 }
60135+ let lockHash = hasher.digest("hex");
6014960136 self.keyFiles = keyFiles;
6015060137 key += `-${lockHash}`;
6015160138 self.cacheKey = key;
@@ -60158,8 +60145,32 @@ class CacheConfig {
6015860145 for (const dir of cacheDirectories.trim().split(/\s+/).filter(Boolean)) {
6015960146 self.cachePaths.push(dir);
6016060147 }
60148+ const bins = await getCargoBins();
60149+ self.cargoBins = Array.from(bins.values());
6016160150 return self;
6016260151 }
60152+ /**
60153+ * Reads and returns the cache config from the action `state`.
60154+ *
60155+ * @throws {Error} if the state is not present.
60156+ * @returns {CacheConfig} the configuration.
60157+ * @see {@link CacheConfig#saveState}
60158+ * @see {@link CacheConfig#new}
60159+ */
60160+ static fromState() {
60161+ const source = lib_core.getState(STATE_CONFIG);
60162+ if (!source) {
60163+ throw new Error("Cache configuration not found in state");
60164+ }
60165+ const self = new CacheConfig();
60166+ Object.assign(self, JSON.parse(source));
60167+ self.workspaces = self.workspaces
60168+ .map((w) => new Workspace(w.root, w.target));
60169+ return self;
60170+ }
60171+ /**
60172+ * Prints the configuration to the action log.
60173+ */
6016360174 printInfo() {
6016460175 lib_core.startGroup("Cache Configuration");
6016560176 lib_core.info(`Workspaces:`);
@@ -60187,6 +60198,21 @@ class CacheConfig {
6018760198 }
6018860199 lib_core.endGroup();
6018960200 }
60201+ /**
60202+ * Saves the configuration to the state store.
60203+ * This is used to restore the configuration in the post action.
60204+ */
60205+ saveState() {
60206+ lib_core.saveState(STATE_CONFIG, this);
60207+ }
60208+ }
60209+ /**
60210+ * Checks if the cache is up to date.
60211+ *
60212+ * @returns `true` if the cache is up to date, `false` otherwise.
60213+ */
60214+ function isCacheUpToDate() {
60215+ return core.getState(STATE_CONFIG) === "";
6019060216}
6019160217async function getRustVersion() {
6019260218 const stdout = await getCmdOutput("rustc", ["-vV"]);
@@ -60197,11 +60223,6 @@ async function getRustVersion() {
6019760223 .filter((s) => s.length === 2);
6019860224 return Object.fromEntries(splits);
6019960225}
60200- async function getPackages() {
60201- let stdout = await getCmdOutput("cargo", ["install", "--list"]);
60202- // Make OS independent.
60203- return stdout.split(/[\n\r]+/).join("\n");
60204- }
6020560226async function globFiles(pattern) {
6020660227 const globber = await glob.create(pattern, {
6020760228 followSymbolicLinks: false,
@@ -60269,9 +60290,14 @@ async function getCargoBins() {
6026960290 catch { }
6027060291 return bins;
6027160292}
60272- async function cleanBin() {
60293+ /**
60294+ * Clean the cargo bin directory, removing the binaries that existed
60295+ * when the action started, as they were not created by the build.
60296+ *
60297+ * @param oldBins The binaries that existed when the action started.
60298+ */
60299+ async function cleanBin(oldBins) {
6027360300 const bins = await getCargoBins();
60274- const oldBins = JSON.parse(core.getState(STATE_BINS));
6027560301 for (const bin of oldBins) {
6027660302 bins.delete(bin);
6027760303 }
@@ -60439,9 +60465,9 @@ async function exists(path) {
6043960465
6044060466
6044160467process.on("uncaughtException", (e) => {
60442- lib_core.info(`[warning] ${ e.message}` );
60468+ lib_core.error( e.message);
6044360469 if (e.stack) {
60444- lib_core.info (e.stack);
60470+ lib_core.error (e.stack);
6044560471 }
6044660472});
6044760473async function run() {
@@ -60459,36 +60485,37 @@ async function run() {
6045960485 const config = await CacheConfig["new"]();
6046060486 config.printInfo();
6046160487 lib_core.info("");
60462- const bins = await getCargoBins();
60463- lib_core.saveState(config_STATE_BINS, JSON.stringify([...bins]));
6046460488 lib_core.info(`... Restoring cache ...`);
6046560489 const key = config.cacheKey;
6046660490 // Pass a copy of cachePaths to avoid mutating the original array as reported by:
6046760491 // https://github.com/actions/toolkit/pull/1378
6046860492 // TODO: remove this once the underlying bug is fixed.
6046960493 const restoreKey = await cache.restoreCache(config.cachePaths.slice(), key, [config.restoreKey]);
6047060494 if (restoreKey) {
60471- lib_core.info(`Restored from cache key "${ restoreKey}".`) ;
60472- lib_core.saveState(STATE_KEY, restoreKey);
60473- if (restoreKey !== key ) {
60495+ const match = restoreKey === key ;
60496+ lib_core.info(`Restored from cache key "${ restoreKey}" full match: ${match}.` );
60497+ if (!match ) {
6047460498 // pre-clean the target directory on cache mismatch
6047560499 for (const workspace of config.workspaces) {
6047660500 try {
6047760501 await cleanTargetDir(workspace.target, [], true);
6047860502 }
6047960503 catch { }
6048060504 }
60505+ // We restored the cache but it is not a full match.
60506+ config.saveState();
6048160507 }
60482- setCacheHitOutput(restoreKey === key );
60508+ setCacheHitOutput(match );
6048360509 }
6048460510 else {
6048560511 lib_core.info("No cache found.");
60512+ config.saveState();
6048660513 setCacheHitOutput(false);
6048760514 }
6048860515 }
6048960516 catch (e) {
6049060517 setCacheHitOutput(false);
60491- lib_core.info(`[warning] ${e.stack}`);
60518+ lib_core.error(` ${e.stack}`);
6049260519 }
6049360520}
6049460521function setCacheHitOutput(cacheHit) {
0 commit comments