From d30f1144e884b1fe579845ed7a339c640dff522e Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sun, 3 Dec 2023 05:57:51 -0500 Subject: [PATCH] Only key by `Cargo.toml` and `Cargo.lock` files of workspace members (#180) --- dist/restore/index.js | 48 +++++++++++++++++++++++++------------------ dist/save/index.js | 48 +++++++++++++++++++++++++------------------ src/cleanup.ts | 10 +-------- src/config.ts | 11 +++++----- src/save.ts | 2 +- src/utils.ts | 10 +++++++++ src/workspace.ts | 21 ++++++++++++------- 7 files changed, 88 insertions(+), 62 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 42cc182..e8dfee2 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -86960,6 +86960,7 @@ var cache_lib_cache = __nccwpck_require__(7799); + function reportError(e) { const { commandFailed } = e; if (commandFailed) { @@ -87007,6 +87008,15 @@ function getCacheProvider() { cache: cache, }; } +async function utils_exists(path) { + try { + await external_fs_default().promises.access(path); + return true; + } + catch { + return false; + } +} ;// CONCATENATED MODULE: ./src/workspace.ts @@ -87018,25 +87028,30 @@ class Workspace { this.root = root; this.target = target; } - async getPackages() { + async getPackages(filter, ...extraArgs) { let packages = []; try { lib_core.debug(`collecting metadata for "${this.root}"`); - const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1"], { + 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`); - for (const pkg of meta.packages) { - if (pkg.manifest_path.startsWith(this.root)) { - continue; - } + 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) }); } } - catch { } + catch (err) { + console.error(err); + } return packages; } + async getPackagesOutsideWorkspaceRoot() { + return await this.getPackages(pkg => !pkg.manifest_path.startsWith(this.root)); + } + async getWorkspaceMembers() { + return await this.getPackages(_ => true, "--no-deps"); + } } ;// CONCATENATED MODULE: ./src/config.ts @@ -87152,7 +87167,8 @@ class CacheConfig { for (const workspace of workspaces) { const root = workspace.root; keyFiles.push(...(await globFiles(`${root}/**/.cargo/config.toml\n${root}/**/rust-toolchain\n${root}/**/rust-toolchain.toml`))); - const cargo_manifests = sort_and_uniq(await globFiles(`${root}/**/Cargo.toml`)); + const workspaceMembers = await workspace.getWorkspaceMembers(); + const cargo_manifests = sort_and_uniq(workspaceMembers.map(member => external_path_default().join(member.path, "Cargo.toml"))); for (const cargo_manifest of cargo_manifests) { try { const content = await promises_default().readFile(cargo_manifest, { encoding: "utf8" }); @@ -87193,8 +87209,8 @@ class CacheConfig { keyFiles.push(cargo_manifest); } } - const cargo_locks = sort_and_uniq(await globFiles(`${root}/**/Cargo.lock`)); - for (const cargo_lock of cargo_locks) { + const cargo_lock = external_path_default().join(workspace.root, "Cargo.lock"); + if (await utils_exists(cargo_lock)) { try { const content = await promises_default().readFile(cargo_lock, { encoding: "utf8" }); const parsed = parse(content); @@ -87357,6 +87373,7 @@ function sort_and_uniq(a) { + async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { lib_core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory @@ -87365,7 +87382,7 @@ async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { 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); @@ -87638,15 +87655,6 @@ async function rmRF(dirName) { core.debug(`deleting "${dirName}"`); await io.rmRF(dirName); } -async function exists(path) { - try { - await external_fs_default().promises.access(path); - return true; - } - catch { - return false; - } -} ;// CONCATENATED MODULE: ./src/restore.ts diff --git a/dist/save/index.js b/dist/save/index.js index cb46c0a..358f4aa 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -86960,6 +86960,7 @@ var cache_lib_cache = __nccwpck_require__(7799); + function reportError(e) { const { commandFailed } = e; if (commandFailed) { @@ -87007,6 +87008,15 @@ function getCacheProvider() { cache: cache, }; } +async function exists(path) { + try { + await external_fs_default().promises.access(path); + return true; + } + catch { + return false; + } +} ;// CONCATENATED MODULE: ./src/workspace.ts @@ -87018,25 +87028,30 @@ class Workspace { this.root = root; this.target = target; } - async getPackages() { + async getPackages(filter, ...extraArgs) { let packages = []; try { core.debug(`collecting metadata for "${this.root}"`); - const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1"], { + 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`); - for (const pkg of meta.packages) { - if (pkg.manifest_path.startsWith(this.root)) { - continue; - } + 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) }); } } - catch { } + catch (err) { + console.error(err); + } return packages; } + async getPackagesOutsideWorkspaceRoot() { + return await this.getPackages(pkg => !pkg.manifest_path.startsWith(this.root)); + } + async getWorkspaceMembers() { + return await this.getPackages(_ => true, "--no-deps"); + } } ;// CONCATENATED MODULE: ./src/config.ts @@ -87152,7 +87167,8 @@ class CacheConfig { for (const workspace of workspaces) { const root = workspace.root; keyFiles.push(...(await globFiles(`${root}/**/.cargo/config.toml\n${root}/**/rust-toolchain\n${root}/**/rust-toolchain.toml`))); - const cargo_manifests = sort_and_uniq(await globFiles(`${root}/**/Cargo.toml`)); + const workspaceMembers = await workspace.getWorkspaceMembers(); + const cargo_manifests = sort_and_uniq(workspaceMembers.map(member => external_path_default().join(member.path, "Cargo.toml"))); for (const cargo_manifest of cargo_manifests) { try { const content = await promises_default().readFile(cargo_manifest, { encoding: "utf8" }); @@ -87193,8 +87209,8 @@ class CacheConfig { keyFiles.push(cargo_manifest); } } - const cargo_locks = sort_and_uniq(await globFiles(`${root}/**/Cargo.lock`)); - for (const cargo_lock of cargo_locks) { + const cargo_lock = external_path_default().join(workspace.root, "Cargo.lock"); + if (await exists(cargo_lock)) { try { const content = await promises_default().readFile(cargo_lock, { encoding: "utf8" }); const parsed = parse(content); @@ -87357,6 +87373,7 @@ function sort_and_uniq(a) { + async function cleanTargetDir(targetDir, packages, checkTimestamp = false) { core.debug(`cleaning target directory "${targetDir}"`); // remove all *files* from the profile directory @@ -87638,15 +87655,6 @@ async function rmRF(dirName) { core.debug(`deleting "${dirName}"`); await io.rmRF(dirName); } -async function exists(path) { - try { - await external_fs_default().promises.access(path); - return true; - } - catch { - return false; - } -} ;// CONCATENATED MODULE: ./src/save.ts @@ -87678,7 +87686,7 @@ async function run() { await macOsWorkaround(); const allPackages = []; for (const workspace of config.workspaces) { - const packages = await workspace.getPackages(); + const packages = await workspace.getPackagesOutsideWorkspaceRoot(); allPackages.push(...packages); try { core.info(`... Cleaning ${workspace.target} ...`); diff --git a/src/cleanup.ts b/src/cleanup.ts index 854f404..56fe9b4 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -4,6 +4,7 @@ import fs from "fs"; import path from "path"; import { CARGO_HOME } from "./config"; +import { exists } from "./utils"; import { Packages } from "./workspace"; export async function cleanTargetDir(targetDir: string, packages: Packages, checkTimestamp = false) { @@ -308,12 +309,3 @@ async function rmRF(dirName: string) { core.debug(`deleting "${dirName}"`); await io.rmRF(dirName); } - -async function exists(path: string) { - try { - await fs.promises.access(path); - return true; - } catch { - return false; - } -} diff --git a/src/config.ts b/src/config.ts index 79045ed..2b24788 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,7 +8,7 @@ import path from "path"; import * as toml from "smol-toml"; import { getCargoBins } from "./cleanup"; -import { CacheProvider, getCmdOutput } from "./utils"; +import { CacheProvider, exists, getCmdOutput } from "./utils"; import { Workspace } from "./workspace"; const HOME = os.homedir(); @@ -142,7 +142,9 @@ export class CacheConfig { )), ); - const cargo_manifests = sort_and_uniq(await globFiles(`${root}/**/Cargo.toml`)); + const workspaceMembers = await workspace.getWorkspaceMembers(); + + const cargo_manifests = sort_and_uniq(workspaceMembers.map(member => path.join(member.path, "Cargo.toml"))); for (const cargo_manifest of cargo_manifests) { try { @@ -189,9 +191,8 @@ export class CacheConfig { } } - const cargo_locks = sort_and_uniq(await globFiles(`${root}/**/Cargo.lock`)); - - for (const cargo_lock of cargo_locks) { + const cargo_lock = path.join(workspace.root, "Cargo.lock"); + if (await exists(cargo_lock)) { try { const content = await fs_promises.readFile(cargo_lock, { encoding: "utf8" }); const parsed = toml.parse(content); diff --git a/src/save.ts b/src/save.ts index 927020d..939665a 100644 --- a/src/save.ts +++ b/src/save.ts @@ -36,7 +36,7 @@ async function run() { const allPackages = []; for (const workspace of config.workspaces) { - const packages = await workspace.getPackages(); + const packages = await workspace.getPackagesOutsideWorkspaceRoot(); allPackages.push(...packages); try { core.info(`... Cleaning ${workspace.target} ...`); diff --git a/src/utils.ts b/src/utils.ts index bb393f3..a276e5d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,6 +2,7 @@ import * as core from "@actions/core"; import * as exec from "@actions/exec"; import * as buildjetCache from "@actions/buildjet-cache"; import * as ghCache from "@actions/cache"; +import fs from "fs"; export function reportError(e: any) { const { commandFailed } = e; @@ -61,3 +62,12 @@ export function getCacheProvider(): CacheProvider { cache: cache, }; } + +export async function exists(path: string) { + try { + await fs.promises.access(path); + return true; + } catch { + return false; + } +} diff --git a/src/workspace.ts b/src/workspace.ts index b770fca..dec38e4 100644 --- a/src/workspace.ts +++ b/src/workspace.ts @@ -8,26 +8,33 @@ const SAVE_TARGETS = new Set(["lib", "proc-macro"]); export class Workspace { constructor(public root: string, public target: string) {} - public async getPackages(): Promise { + async getPackages(filter: ((p: Meta['packages'][0]) => boolean), ...extraArgs: string[]): Promise { let packages: Packages = []; try { core.debug(`collecting metadata for "${this.root}"`); const meta: Meta = JSON.parse( - await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1"], { + await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1", ...extraArgs], { cwd: this.root, }), ); core.debug(`workspace "${this.root}" has ${meta.packages.length} packages`); - for (const pkg of meta.packages) { - if (pkg.manifest_path.startsWith(this.root)) { - continue; - } + 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: path.dirname(pkg.manifest_path) }); } - } catch {} + } catch (err) { + console.error(err); + } return packages; } + + public async getPackagesOutsideWorkspaceRoot(): Promise { + return await this.getPackages(pkg => !pkg.manifest_path.startsWith(this.root)); + } + + public async getWorkspaceMembers(): Promise { + return await this.getPackages(_ => true, "--no-deps"); + } } export interface PackageDefinition {