mirror of
https://github.com/Swatinem/rust-cache
synced 2025-04-07 13:45:20 +00:00
Add a selftest and support for .cargo/bin
This commit is contained in:
parent
83aad8d470
commit
b495963495
29
.github/workflows/selftest.yml
vendored
Normal file
29
.github/workflows/selftest.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
selftest:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
|
||||||
|
name: Test Action on ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: ./
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
cargo install cargo-deny --locked
|
||||||
|
cargo check
|
||||||
|
cargo test
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
node_modules
|
node_modules
|
||||||
|
/target
|
||||||
|
|
1665
Cargo.lock
generated
Normal file
1665
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
publish = false
|
||||||
|
name = "rust-cache"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Arpad Borsos <arpad.borsos@googlemail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
reqwest = "0.11.0"
|
||||||
|
actix-web = { git = "https://github.com/actix/actix-web.git", rev = "bd26083f333ecf63e3eb444748250364ce124f5e" }
|
24
dist/restore/index.js
vendored
24
dist/restore/index.js
vendored
|
@ -55710,11 +55710,13 @@ const cwd = core.getInput("working-directory");
|
||||||
if (cwd) {
|
if (cwd) {
|
||||||
process.chdir(cwd);
|
process.chdir(cwd);
|
||||||
}
|
}
|
||||||
|
const stateBins = "RUST_CACHE_BINS";
|
||||||
const stateKey = "RUST_CACHE_KEY";
|
const stateKey = "RUST_CACHE_KEY";
|
||||||
const stateHash = "RUST_CACHE_HASH";
|
const stateHash = "RUST_CACHE_HASH";
|
||||||
const home = external_os_default().homedir();
|
const home = external_os_default().homedir();
|
||||||
const cargoHome = process.env.CARGO_HOME || external_path_default().join(home, ".cargo");
|
const cargoHome = process.env.CARGO_HOME || external_path_default().join(home, ".cargo");
|
||||||
const paths = {
|
const paths = {
|
||||||
|
cargoHome,
|
||||||
index: external_path_default().join(cargoHome, "registry/index"),
|
index: external_path_default().join(cargoHome, "registry/index"),
|
||||||
cache: external_path_default().join(cargoHome, "registry/cache"),
|
cache: external_path_default().join(cargoHome, "registry/cache"),
|
||||||
git: external_path_default().join(cargoHome, "git"),
|
git: external_path_default().join(cargoHome, "git"),
|
||||||
|
@ -55747,11 +55749,29 @@ async function getCacheConfig() {
|
||||||
}
|
}
|
||||||
key += await getRustKey();
|
key += await getRustKey();
|
||||||
return {
|
return {
|
||||||
paths: [paths.index, paths.cache, paths.git, paths.target],
|
paths: [
|
||||||
|
external_path_default().join(cargoHome, "bin"),
|
||||||
|
external_path_default().join(cargoHome, ".crates2.json"),
|
||||||
|
external_path_default().join(cargoHome, ".crates.toml"),
|
||||||
|
paths.git,
|
||||||
|
paths.cache,
|
||||||
|
paths.index,
|
||||||
|
paths.target,
|
||||||
|
],
|
||||||
key: `${key}-${lockHash}`,
|
key: `${key}-${lockHash}`,
|
||||||
restoreKeys: [key],
|
restoreKeys: [key],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
async function getCargoBins() {
|
||||||
|
const { installs } = JSON.parse(await external_fs_default().promises.readFile(external_path_default().join(paths.cargoHome, ".crates2.json"), "utf8"));
|
||||||
|
const bins = new Set();
|
||||||
|
for (const pkg of Object.values(installs)) {
|
||||||
|
for (const bin of pkg.bins) {
|
||||||
|
bins.add(bin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bins;
|
||||||
|
}
|
||||||
async function getRustKey() {
|
async function getRustKey() {
|
||||||
const rustc = await getRustVersion();
|
const rustc = await getRustVersion();
|
||||||
return `${rustc.release}-${rustc.host}-${rustc["commit-hash"].slice(0, 12)}`;
|
return `${rustc.release}-${rustc.host}-${rustc["commit-hash"].slice(0, 12)}`;
|
||||||
|
@ -55864,6 +55884,8 @@ async function run() {
|
||||||
try {
|
try {
|
||||||
core.exportVariable("CARGO_INCREMENTAL", 0);
|
core.exportVariable("CARGO_INCREMENTAL", 0);
|
||||||
const { paths, key, restoreKeys } = await getCacheConfig();
|
const { paths, key, restoreKeys } = await getCacheConfig();
|
||||||
|
const bins = await getCargoBins();
|
||||||
|
core.saveState(stateBins, JSON.stringify([...bins]));
|
||||||
core.info(`Restoring paths:\n ${paths.join("\n ")}`);
|
core.info(`Restoring paths:\n ${paths.join("\n ")}`);
|
||||||
core.info(`In directory:\n ${process.cwd()}`);
|
core.info(`In directory:\n ${process.cwd()}`);
|
||||||
core.info(`Using keys:\n ${[key, ...restoreKeys].join("\n ")}`);
|
core.info(`Using keys:\n ${[key, ...restoreKeys].join("\n ")}`);
|
||||||
|
|
39
dist/save/index.js
vendored
39
dist/save/index.js
vendored
|
@ -55710,11 +55710,13 @@ const cwd = core.getInput("working-directory");
|
||||||
if (cwd) {
|
if (cwd) {
|
||||||
process.chdir(cwd);
|
process.chdir(cwd);
|
||||||
}
|
}
|
||||||
|
const stateBins = "RUST_CACHE_BINS";
|
||||||
const stateKey = "RUST_CACHE_KEY";
|
const stateKey = "RUST_CACHE_KEY";
|
||||||
const stateHash = "RUST_CACHE_HASH";
|
const stateHash = "RUST_CACHE_HASH";
|
||||||
const home = external_os_default().homedir();
|
const home = external_os_default().homedir();
|
||||||
const cargoHome = process.env.CARGO_HOME || external_path_default().join(home, ".cargo");
|
const cargoHome = process.env.CARGO_HOME || external_path_default().join(home, ".cargo");
|
||||||
const paths = {
|
const paths = {
|
||||||
|
cargoHome,
|
||||||
index: external_path_default().join(cargoHome, "registry/index"),
|
index: external_path_default().join(cargoHome, "registry/index"),
|
||||||
cache: external_path_default().join(cargoHome, "registry/cache"),
|
cache: external_path_default().join(cargoHome, "registry/cache"),
|
||||||
git: external_path_default().join(cargoHome, "git"),
|
git: external_path_default().join(cargoHome, "git"),
|
||||||
|
@ -55747,11 +55749,29 @@ async function getCacheConfig() {
|
||||||
}
|
}
|
||||||
key += await getRustKey();
|
key += await getRustKey();
|
||||||
return {
|
return {
|
||||||
paths: [paths.index, paths.cache, paths.git, paths.target],
|
paths: [
|
||||||
|
external_path_default().join(cargoHome, "bin"),
|
||||||
|
external_path_default().join(cargoHome, ".crates2.json"),
|
||||||
|
external_path_default().join(cargoHome, ".crates.toml"),
|
||||||
|
paths.git,
|
||||||
|
paths.cache,
|
||||||
|
paths.index,
|
||||||
|
paths.target,
|
||||||
|
],
|
||||||
key: `${key}-${lockHash}`,
|
key: `${key}-${lockHash}`,
|
||||||
restoreKeys: [key],
|
restoreKeys: [key],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
async function getCargoBins() {
|
||||||
|
const { installs } = JSON.parse(await external_fs_default().promises.readFile(external_path_default().join(paths.cargoHome, ".crates2.json"), "utf8"));
|
||||||
|
const bins = new Set();
|
||||||
|
for (const pkg of Object.values(installs)) {
|
||||||
|
for (const bin of pkg.bins) {
|
||||||
|
bins.add(bin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bins;
|
||||||
|
}
|
||||||
async function getRustKey() {
|
async function getRustKey() {
|
||||||
const rustc = await getRustVersion();
|
const rustc = await getRustVersion();
|
||||||
return `${rustc.release}-${rustc.host}-${rustc["commit-hash"].slice(0, 12)}`;
|
return `${rustc.release}-${rustc.host}-${rustc["commit-hash"].slice(0, 12)}`;
|
||||||
|
@ -55880,6 +55900,10 @@ async function run() {
|
||||||
await cleanRegistry(registryName, packages);
|
await cleanRegistry(registryName, packages);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
try {
|
||||||
|
await cleanBin();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
try {
|
try {
|
||||||
await cleanGit(packages);
|
await cleanGit(packages);
|
||||||
}
|
}
|
||||||
|
@ -55907,6 +55931,19 @@ async function getRegistryName() {
|
||||||
const first = files.shift();
|
const first = files.shift();
|
||||||
return external_path_default().basename(external_path_default().dirname(first));
|
return external_path_default().basename(external_path_default().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 external_fs_default().promises.opendir(external_path_default().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, packages) {
|
async function cleanRegistry(registryName, packages) {
|
||||||
await io.rmRF(external_path_default().join(paths.index, registryName, ".cache"));
|
await io.rmRF(external_path_default().join(paths.index, registryName, ".cache"));
|
||||||
const pkgSet = new Set(packages.map((p) => `${p.name}-${p.version}.crate`));
|
const pkgSet = new Set(packages.map((p) => `${p.name}-${p.version}.crate`));
|
||||||
|
|
129
package-lock.json
generated
129
package-lock.json
generated
|
@ -8,7 +8,7 @@
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"license": "LGPL-3.0",
|
"license": "LGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^1.0.5",
|
"@actions/cache": "^1.0.6",
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.4",
|
"@actions/exec": "^1.0.4",
|
||||||
"@actions/glob": "^0.1.1",
|
"@actions/glob": "^0.1.1",
|
||||||
|
@ -16,16 +16,16 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vercel/ncc": "^0.27.0",
|
"@vercel/ncc": "^0.27.0",
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.1.5"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/Swatinem"
|
"url": "https://github.com/sponsors/Swatinem"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/cache": {
|
"node_modules/@actions/cache": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-1.0.6.tgz",
|
||||||
"integrity": "sha512-TcvJOduwsPP27KLmIa5cqXsQYFK2GzILcEpnhvYmhGwi1aYx9XwhKmp6Im8X6DJMBxbvupKPsOntG6f6sSkIPA==",
|
"integrity": "sha512-c8CSJS6uCatX07VHazgvL4XPMpTdawOyyD+OCThRE0v486lqThYa4tayRqTyl6FSyD5LclQyB8/FQlZ5cxTNJA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.1",
|
"@actions/exec": "^1.0.1",
|
||||||
|
@ -95,9 +95,9 @@
|
||||||
"integrity": "sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg=="
|
"integrity": "sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg=="
|
||||||
},
|
},
|
||||||
"node_modules/@azure/core-auth": {
|
"node_modules/@azure/core-auth": {
|
||||||
"version": "1.1.4",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.2.0.tgz",
|
||||||
"integrity": "sha512-+j1embyH1jqf04AIfJPdLafd5SC1y6z1Jz4i+USR1XkTp6KM8P5u4/AjmWMVoEQdM/M29PJcRDZcCEWjK9S1bw==",
|
"integrity": "sha512-KUl+Nwn/Sm6Lw5d3U90m1jZfNSL087SPcqHLxwn2T6PupNKmcgsEbDjHB25gDvHO4h7pBsTlrdJAY7dz+Qk8GA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/abort-controller": "^1.0.0",
|
"@azure/abort-controller": "^1.0.0",
|
||||||
"tslib": "^2.0.0"
|
"tslib": "^2.0.0"
|
||||||
|
@ -112,9 +112,9 @@
|
||||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||||
},
|
},
|
||||||
"node_modules/@azure/core-http": {
|
"node_modules/@azure/core-http": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.2.3.tgz",
|
||||||
"integrity": "sha512-9eu2OcbR7e44gqBy4U1Uv8NTWgLIMwKXMEGgO2MahsJy5rdTiAhs5fJHQffPq8uX2MFh21iBODwO9R/Xlov88A==",
|
"integrity": "sha512-g5C1zUJO5dehP2Riv+vy9iCYoS1UwKnZsBVCzanScz9A83LbnXKpZDa9wie26G9dfXUhQoFZoFT8LYWhPKmwcg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/abort-controller": "^1.0.0",
|
"@azure/abort-controller": "^1.0.0",
|
||||||
"@azure/core-auth": "^1.1.3",
|
"@azure/core-auth": "^1.1.3",
|
||||||
|
@ -137,9 +137,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/core-http/node_modules/form-data": {
|
"node_modules/@azure/core-http/node_modules/form-data": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
|
@ -240,10 +240,11 @@
|
||||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||||
},
|
},
|
||||||
"node_modules/@azure/ms-rest-js": {
|
"node_modules/@azure/ms-rest-js": {
|
||||||
"version": "2.1.0",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.2.3.tgz",
|
||||||
"integrity": "sha512-4BXLVImYRt+jcUmEJ5LUWglI8RBNVQndY6IcyvQ4U8O4kIXdmlRz3cJdA/RpXf5rKT38KOoTO2T6Z1f6Z1HDBg==",
|
"integrity": "sha512-sXOhOu/37Tr8428f32Jwuwga975Xw64pYg1UeUwOBMhkNgtn5vUuNRa3fhmem+I6f8EKoi6hOsYDFlaHeZ52jA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@azure/core-auth": "^1.1.4",
|
||||||
"@types/node-fetch": "^2.3.7",
|
"@types/node-fetch": "^2.3.7",
|
||||||
"@types/tunnel": "0.0.1",
|
"@types/tunnel": "0.0.1",
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
|
@ -257,9 +258,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/storage-blob": {
|
"node_modules/@azure/storage-blob": {
|
||||||
"version": "12.3.0",
|
"version": "12.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.4.1.tgz",
|
||||||
"integrity": "sha512-nCySzNfm782pEW3sg9GHj1zE4gBeVVMeEBdWb4MefifrCwQQOoz5cXZTNFiUJAJqAO+/72r2UjZcUwHk/QmzkA==",
|
"integrity": "sha512-RH6ru8LbnCC+m1rlVLon6mYUXdHsTcyUXFCJAWRQQM7p0XOwVKPS+UiVk2tZXfvMWd3q/qT/meOrEbHEcp/c4g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/abort-controller": "^1.0.0",
|
"@azure/abort-controller": "^1.0.0",
|
||||||
"@azure/core-http": "^1.2.0",
|
"@azure/core-http": "^1.2.0",
|
||||||
|
@ -270,6 +271,9 @@
|
||||||
"@opentelemetry/api": "^0.10.2",
|
"@opentelemetry/api": "^0.10.2",
|
||||||
"events": "^3.0.0",
|
"events": "^3.0.0",
|
||||||
"tslib": "^2.0.0"
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/storage-blob/node_modules/tslib": {
|
"node_modules/@azure/storage-blob/node_modules/tslib": {
|
||||||
|
@ -305,23 +309,23 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "14.14.20",
|
"version": "14.14.28",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.28.tgz",
|
||||||
"integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A=="
|
"integrity": "sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/node-fetch": {
|
"node_modules/@types/node-fetch": {
|
||||||
"version": "2.5.7",
|
"version": "2.5.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz",
|
||||||
"integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==",
|
"integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"form-data": "^3.0.0"
|
"form-data": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node-fetch/node_modules/form-data": {
|
"node_modules/@types/node-fetch/node_modules/form-data": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
|
@ -538,9 +542,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz",
|
||||||
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
|
"integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
|
@ -589,9 +593,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": {
|
"@actions/cache": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-1.0.6.tgz",
|
||||||
"integrity": "sha512-TcvJOduwsPP27KLmIa5cqXsQYFK2GzILcEpnhvYmhGwi1aYx9XwhKmp6Im8X6DJMBxbvupKPsOntG6f6sSkIPA==",
|
"integrity": "sha512-c8CSJS6uCatX07VHazgvL4XPMpTdawOyyD+OCThRE0v486lqThYa4tayRqTyl6FSyD5LclQyB8/FQlZ5cxTNJA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.1",
|
"@actions/exec": "^1.0.1",
|
||||||
|
@ -660,9 +664,9 @@
|
||||||
"integrity": "sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg=="
|
"integrity": "sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg=="
|
||||||
},
|
},
|
||||||
"@azure/core-auth": {
|
"@azure/core-auth": {
|
||||||
"version": "1.1.4",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.2.0.tgz",
|
||||||
"integrity": "sha512-+j1embyH1jqf04AIfJPdLafd5SC1y6z1Jz4i+USR1XkTp6KM8P5u4/AjmWMVoEQdM/M29PJcRDZcCEWjK9S1bw==",
|
"integrity": "sha512-KUl+Nwn/Sm6Lw5d3U90m1jZfNSL087SPcqHLxwn2T6PupNKmcgsEbDjHB25gDvHO4h7pBsTlrdJAY7dz+Qk8GA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@azure/abort-controller": "^1.0.0",
|
"@azure/abort-controller": "^1.0.0",
|
||||||
"tslib": "^2.0.0"
|
"tslib": "^2.0.0"
|
||||||
|
@ -676,9 +680,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@azure/core-http": {
|
"@azure/core-http": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.2.3.tgz",
|
||||||
"integrity": "sha512-9eu2OcbR7e44gqBy4U1Uv8NTWgLIMwKXMEGgO2MahsJy5rdTiAhs5fJHQffPq8uX2MFh21iBODwO9R/Xlov88A==",
|
"integrity": "sha512-g5C1zUJO5dehP2Riv+vy9iCYoS1UwKnZsBVCzanScz9A83LbnXKpZDa9wie26G9dfXUhQoFZoFT8LYWhPKmwcg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@azure/abort-controller": "^1.0.0",
|
"@azure/abort-controller": "^1.0.0",
|
||||||
"@azure/core-auth": "^1.1.3",
|
"@azure/core-auth": "^1.1.3",
|
||||||
|
@ -698,9 +702,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
|
@ -788,10 +792,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@azure/ms-rest-js": {
|
"@azure/ms-rest-js": {
|
||||||
"version": "2.1.0",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.2.3.tgz",
|
||||||
"integrity": "sha512-4BXLVImYRt+jcUmEJ5LUWglI8RBNVQndY6IcyvQ4U8O4kIXdmlRz3cJdA/RpXf5rKT38KOoTO2T6Z1f6Z1HDBg==",
|
"integrity": "sha512-sXOhOu/37Tr8428f32Jwuwga975Xw64pYg1UeUwOBMhkNgtn5vUuNRa3fhmem+I6f8EKoi6hOsYDFlaHeZ52jA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@azure/core-auth": "^1.1.4",
|
||||||
"@types/node-fetch": "^2.3.7",
|
"@types/node-fetch": "^2.3.7",
|
||||||
"@types/tunnel": "0.0.1",
|
"@types/tunnel": "0.0.1",
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
|
@ -805,9 +810,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@azure/storage-blob": {
|
"@azure/storage-blob": {
|
||||||
"version": "12.3.0",
|
"version": "12.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.4.1.tgz",
|
||||||
"integrity": "sha512-nCySzNfm782pEW3sg9GHj1zE4gBeVVMeEBdWb4MefifrCwQQOoz5cXZTNFiUJAJqAO+/72r2UjZcUwHk/QmzkA==",
|
"integrity": "sha512-RH6ru8LbnCC+m1rlVLon6mYUXdHsTcyUXFCJAWRQQM7p0XOwVKPS+UiVk2tZXfvMWd3q/qT/meOrEbHEcp/c4g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@azure/abort-controller": "^1.0.0",
|
"@azure/abort-controller": "^1.0.0",
|
||||||
"@azure/core-http": "^1.2.0",
|
"@azure/core-http": "^1.2.0",
|
||||||
|
@ -846,23 +851,23 @@
|
||||||
"integrity": "sha512-hZNKjKOYsckoOEgBziGMnBcX0M7EtstnCmwz5jZUOUYwlZ+/xxX6z3jPu1XVO2Jivk0eLfuP9GP+vFD49CMetw=="
|
"integrity": "sha512-hZNKjKOYsckoOEgBziGMnBcX0M7EtstnCmwz5jZUOUYwlZ+/xxX6z3jPu1XVO2Jivk0eLfuP9GP+vFD49CMetw=="
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "14.14.20",
|
"version": "14.14.28",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.28.tgz",
|
||||||
"integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A=="
|
"integrity": "sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g=="
|
||||||
},
|
},
|
||||||
"@types/node-fetch": {
|
"@types/node-fetch": {
|
||||||
"version": "2.5.7",
|
"version": "2.5.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz",
|
||||||
"integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==",
|
"integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"form-data": "^3.0.0"
|
"form-data": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
|
@ -1027,9 +1032,9 @@
|
||||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz",
|
||||||
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
|
"integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"universalify": {
|
"universalify": {
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/Swatinem/rust-cache#readme",
|
"homepage": "https://github.com/Swatinem/rust-cache#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^1.0.5",
|
"@actions/cache": "^1.0.6",
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.4",
|
"@actions/exec": "^1.0.4",
|
||||||
"@actions/glob": "^0.1.1",
|
"@actions/glob": "^0.1.1",
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vercel/ncc": "^0.27.0",
|
"@vercel/ncc": "^0.27.0",
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.1.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "ncc build --target es2020 -o dist/restore src/restore.ts && ncc build --target es2020 -o dist/save src/save.ts"
|
"prepare": "ncc build --target es2020 -o dist/restore src/restore.ts && ncc build --target es2020 -o dist/save src/save.ts"
|
||||||
|
|
|
@ -16,12 +16,14 @@ if (cwd) {
|
||||||
process.chdir(cwd);
|
process.chdir(cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const stateBins = "RUST_CACHE_BINS";
|
||||||
export const stateKey = "RUST_CACHE_KEY";
|
export const stateKey = "RUST_CACHE_KEY";
|
||||||
const stateHash = "RUST_CACHE_HASH";
|
const stateHash = "RUST_CACHE_HASH";
|
||||||
|
|
||||||
const home = os.homedir();
|
const home = os.homedir();
|
||||||
const cargoHome = process.env.CARGO_HOME || path.join(home, ".cargo");
|
const cargoHome = process.env.CARGO_HOME || path.join(home, ".cargo");
|
||||||
export const paths = {
|
export const paths = {
|
||||||
|
cargoHome,
|
||||||
index: path.join(cargoHome, "registry/index"),
|
index: path.join(cargoHome, "registry/index"),
|
||||||
cache: path.join(cargoHome, "registry/cache"),
|
cache: path.join(cargoHome, "registry/cache"),
|
||||||
git: path.join(cargoHome, "git"),
|
git: path.join(cargoHome, "git"),
|
||||||
|
@ -67,12 +69,33 @@ export async function getCacheConfig(): Promise<CacheConfig> {
|
||||||
key += await getRustKey();
|
key += await getRustKey();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
paths: [paths.index, paths.cache, paths.git, paths.target],
|
paths: [
|
||||||
|
path.join(cargoHome, "bin"),
|
||||||
|
path.join(cargoHome, ".crates2.json"),
|
||||||
|
path.join(cargoHome, ".crates.toml"),
|
||||||
|
paths.git,
|
||||||
|
paths.cache,
|
||||||
|
paths.index,
|
||||||
|
paths.target,
|
||||||
|
],
|
||||||
key: `${key}-${lockHash}`,
|
key: `${key}-${lockHash}`,
|
||||||
restoreKeys: [key],
|
restoreKeys: [key],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getCargoBins(): Promise<Set<string>> {
|
||||||
|
const { installs }: { installs: { [key: string]: { bins: Array<string> } } } = JSON.parse(
|
||||||
|
await fs.promises.readFile(path.join(paths.cargoHome, ".crates2.json"), "utf8"),
|
||||||
|
);
|
||||||
|
const bins = new Set<string>();
|
||||||
|
for (const pkg of Object.values(installs)) {
|
||||||
|
for (const bin of pkg.bins) {
|
||||||
|
bins.add(bin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bins;
|
||||||
|
}
|
||||||
|
|
||||||
async function getRustKey(): Promise<string> {
|
async function getRustKey(): Promise<string> {
|
||||||
const rustc = await getRustVersion();
|
const rustc = await getRustVersion();
|
||||||
return `${rustc.release}-${rustc.host}-${rustc["commit-hash"].slice(0, 12)}`;
|
return `${rustc.release}-${rustc.host}-${rustc["commit-hash"].slice(0, 12)}`;
|
||||||
|
|
3
src/main.rs
Normal file
3
src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { cleanTarget, getCacheConfig, getPackages, stateKey } from "./common";
|
import { cleanTarget, getCacheConfig, getCargoBins, getPackages, stateBins, stateKey } from "./common";
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
|
@ -8,6 +8,9 @@ async function run() {
|
||||||
|
|
||||||
const { paths, key, restoreKeys } = await getCacheConfig();
|
const { paths, key, restoreKeys } = await getCacheConfig();
|
||||||
|
|
||||||
|
const bins = await getCargoBins();
|
||||||
|
core.saveState(stateBins, JSON.stringify([...bins]));
|
||||||
|
|
||||||
core.info(`Restoring paths:\n ${paths.join("\n ")}`);
|
core.info(`Restoring paths:\n ${paths.join("\n ")}`);
|
||||||
core.info(`In directory:\n ${process.cwd()}`);
|
core.info(`In directory:\n ${process.cwd()}`);
|
||||||
core.info(`Using keys:\n ${[key, ...restoreKeys].join("\n ")}`);
|
core.info(`Using keys:\n ${[key, ...restoreKeys].join("\n ")}`);
|
||||||
|
|
32
src/save.ts
32
src/save.ts
|
@ -5,7 +5,17 @@ import * as glob from "@actions/glob";
|
||||||
import * as io from "@actions/io";
|
import * as io from "@actions/io";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { cleanTarget, getCacheConfig, getPackages, Packages, paths, rm, stateKey } from "./common";
|
import {
|
||||||
|
cleanTarget,
|
||||||
|
getCacheConfig,
|
||||||
|
getCargoBins,
|
||||||
|
getPackages,
|
||||||
|
Packages,
|
||||||
|
paths,
|
||||||
|
rm,
|
||||||
|
stateBins,
|
||||||
|
stateKey,
|
||||||
|
} from "./common";
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
|
@ -26,6 +36,10 @@ async function run() {
|
||||||
await cleanRegistry(registryName, packages);
|
await cleanRegistry(registryName, packages);
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cleanBin();
|
||||||
|
} catch {}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await cleanGit(packages);
|
await cleanGit(packages);
|
||||||
} catch {}
|
} catch {}
|
||||||
|
@ -56,6 +70,22 @@ async function getRegistryName(): Promise<string> {
|
||||||
return path.basename(path.dirname(first));
|
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) {
|
async function cleanRegistry(registryName: string, packages: Packages) {
|
||||||
await io.rmRF(path.join(paths.index, registryName, ".cache"));
|
await io.rmRF(path.join(paths.index, registryName, ".cache"));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue