mirror of
https://github.com/Swatinem/rust-cache
synced 2025-11-07 16:05:05 +00:00
rewrite it all
This commit is contained in:
parent
5df06440c6
commit
6ed4c28a7c
8 changed files with 527 additions and 466 deletions
150
src/save.ts
150
src/save.ts
|
|
@ -2,20 +2,17 @@ import * as cache from "@actions/cache";
|
|||
import * as core from "@actions/core";
|
||||
import * as exec from "@actions/exec";
|
||||
import * as glob from "@actions/glob";
|
||||
import * as io from "@actions/io";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import {
|
||||
cleanTarget,
|
||||
getCacheConfig,
|
||||
getCargoBins,
|
||||
getPackages,
|
||||
Packages,
|
||||
paths,
|
||||
rm,
|
||||
stateBins,
|
||||
stateKey,
|
||||
} from "./common";
|
||||
|
||||
import { cleanBin, cleanGit, cleanRegistry, cleanTargetDir } from "./cleanup";
|
||||
import { CacheConfig, STATE_KEY } from "./config";
|
||||
|
||||
process.on("uncaughtException", (e) => {
|
||||
core.info(`[warning] ${e.message}`);
|
||||
if (e.stack) {
|
||||
core.info(e.stack);
|
||||
}
|
||||
});
|
||||
|
||||
async function run() {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
|
|
@ -23,10 +20,9 @@ async function run() {
|
|||
}
|
||||
|
||||
try {
|
||||
const { paths, workspaces, key } = await getCacheConfig();
|
||||
const savePaths = paths.concat(workspaces);
|
||||
const config = await CacheConfig.new();
|
||||
|
||||
if (core.getState(stateKey) === key) {
|
||||
if (core.getState(STATE_KEY) === config.cacheKey) {
|
||||
core.info(`Cache up-to-date.`);
|
||||
return;
|
||||
}
|
||||
|
|
@ -34,44 +30,42 @@ async function run() {
|
|||
// TODO: remove this once https://github.com/actions/toolkit/pull/553 lands
|
||||
await macOsWorkaround();
|
||||
|
||||
const registryName = await getRegistryName();
|
||||
const packages = await getPackages(workspaces);
|
||||
core.info("Detected repository packages to cache: " + JSON.stringify(packages));
|
||||
const registryName = await getRegistryName(config);
|
||||
|
||||
const allPackages = [];
|
||||
for (const workspace of config.workspaces) {
|
||||
const packages = await workspace.getPackages();
|
||||
allPackages.push(...packages);
|
||||
try {
|
||||
await cleanTargetDir(workspace.target, packages);
|
||||
} catch (e) {
|
||||
core.info(`[warning] ${(e as any).stack}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (registryName) {
|
||||
try {
|
||||
await cleanRegistry(registryName, packages);
|
||||
await cleanRegistry(config, registryName, allPackages);
|
||||
} catch (e) {
|
||||
core.info(`[warning] ${(e as any).stack}`);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await cleanBin();
|
||||
await cleanBin(config);
|
||||
} catch (e) {
|
||||
core.info(`[warning] ${(e as any).stack}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await cleanGit(packages);
|
||||
await cleanGit(config, allPackages);
|
||||
} catch (e) {
|
||||
core.info(`[warning] ${(e as any).stack}`);
|
||||
}
|
||||
|
||||
for (const workspace of workspaces) {
|
||||
const target = path.join(workspace, "target");
|
||||
try {
|
||||
await cleanTarget(target, packages);
|
||||
}
|
||||
catch (e) {
|
||||
core.info(`[warning] ${(e as any).stack}`);
|
||||
}
|
||||
}
|
||||
|
||||
core.info(`Saving paths:\n ${savePaths.join("\n ")}`);
|
||||
core.info(`In directory:\n ${process.cwd()}`);
|
||||
core.info(`Using key:\n ${key}`);
|
||||
await cache.saveCache(savePaths, key);
|
||||
core.info(`# Saving cache`);
|
||||
config.printInfo();
|
||||
await cache.saveCache(config.cachePaths, config.cacheKey);
|
||||
} catch (e) {
|
||||
core.info(`[warning] ${(e as any).stack}`);
|
||||
}
|
||||
|
|
@ -79,8 +73,8 @@ async function run() {
|
|||
|
||||
run();
|
||||
|
||||
async function getRegistryName(): Promise<string | null> {
|
||||
const globber = await glob.create(`${paths.index}/**/.last-updated`, { followSymbolicLinks: false });
|
||||
async function getRegistryName(config: CacheConfig): Promise<string | null> {
|
||||
const globber = await glob.create(`${config.cargoIndex}/**/.last-updated`, { followSymbolicLinks: false });
|
||||
const files = await globber.glob();
|
||||
if (files.length > 1) {
|
||||
core.warning(`got multiple registries: "${files.join('", "')}"`);
|
||||
|
|
@ -93,88 +87,10 @@ async function getRegistryName(): Promise<string | null> {
|
|||
return path.basename(path.dirname(first));
|
||||
}
|
||||
|
||||
async function cleanBin() {
|
||||
const bins = await getCargoBins();
|
||||
const oldBins = JSON.parse(core.getState(stateBins));
|
||||
|
||||
for (const bin of oldBins) {
|
||||
bins.delete(bin);
|
||||
}
|
||||
|
||||
const dir = await fs.promises.opendir(path.join(paths.cargoHome, "bin"));
|
||||
for await (const dirent of dir) {
|
||||
if (dirent.isFile() && !bins.has(dirent.name)) {
|
||||
await rm(dir.path, dirent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanRegistry(registryName: string, packages: Packages) {
|
||||
await io.rmRF(path.join(paths.index, registryName, ".cache"));
|
||||
|
||||
const pkgSet = new Set(packages.map((p) => `${p.name}-${p.version}.crate`));
|
||||
|
||||
const dir = await fs.promises.opendir(path.join(paths.cache, registryName));
|
||||
for await (const dirent of dir) {
|
||||
if (dirent.isFile() && !pkgSet.has(dirent.name)) {
|
||||
await rm(dir.path, dirent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanGit(packages: Packages) {
|
||||
const coPath = path.join(paths.git, "checkouts");
|
||||
const dbPath = path.join(paths.git, "db");
|
||||
const repos = new Map<string, Set<string>>();
|
||||
for (const p of packages) {
|
||||
if (!p.path.startsWith(coPath)) {
|
||||
continue;
|
||||
}
|
||||
const [repo, ref] = p.path.slice(coPath.length + 1).split(path.sep);
|
||||
const refs = repos.get(repo);
|
||||
if (refs) {
|
||||
refs.add(ref);
|
||||
} else {
|
||||
repos.set(repo, new Set([ref]));
|
||||
}
|
||||
}
|
||||
|
||||
// we have to keep both the clone, and the checkout, removing either will
|
||||
// trigger a rebuild
|
||||
|
||||
let dir: fs.Dir;
|
||||
// clean the db
|
||||
dir = await fs.promises.opendir(dbPath);
|
||||
for await (const dirent of dir) {
|
||||
if (!repos.has(dirent.name)) {
|
||||
await rm(dir.path, dirent);
|
||||
}
|
||||
}
|
||||
|
||||
// clean the checkouts
|
||||
dir = await fs.promises.opendir(coPath);
|
||||
for await (const dirent of dir) {
|
||||
const refs = repos.get(dirent.name);
|
||||
if (!refs) {
|
||||
await rm(dir.path, dirent);
|
||||
continue;
|
||||
}
|
||||
if (!dirent.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
const refsDir = await fs.promises.opendir(path.join(dir.path, dirent.name));
|
||||
for await (const dirent of refsDir) {
|
||||
if (!refs.has(dirent.name)) {
|
||||
await rm(refsDir.path, dirent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function macOsWorkaround() {
|
||||
try {
|
||||
// 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 {}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue