cli/commands/build-cache: refactor dirty check to make key undefined instead of cache

This commit is contained in:
Patrik Oldsberg
2020-03-30 18:16:15 +02:00
parent bfceff2c84
commit c4b6afffaf
2 changed files with 38 additions and 30 deletions
+22 -20
View File
@@ -29,9 +29,9 @@ export type CacheQueryResult = {
// If there is a cache hit and this method is defined, it needs to be called to restore the
// output contents before continuing.
copy?: (outputDir: string) => Promise<void>;
// If this method is defined, it should be called after a successful build to archive the output content.
// The content will be archived using the same key as was used in the cache.
archive?: (outputDir: string, maxEntries: number) => Promise<void>;
// Call after a successful build to archive the output content.
// The content will be archived using the same key as was used to query the cache.
archive: (outputDir: string, maxEntries: number) => Promise<void>;
};
// Key that determines whether cached output can be reused
@@ -61,26 +61,31 @@ export class Cache {
const repoPath = relativePath(options.repoRoot, process.cwd());
const location = resolvePath(options.cacheDir, repoPath);
// Make sure we don't have any uncommitted changes to the input, in that case we consider the cache to be missing
const noChanges = await runCheck(
`git diff --quiet HEAD -- ${options.inputs.join(' ')}`,
);
if (!noChanges) {
return new Cache();
}
const outputInfo = await readCacheInfo(options.output);
const localKey = outputInfo?.key;
const { entries = [] } = (await readCacheInfo(location)) ?? {};
return new Cache(entries, location, localKey);
return new Cache(location, entries, localKey);
}
// Generates a key based on the contents of the input paths
static async readInputKey(inputPaths: string[]): Promise<CacheKey> {
// Generates a key based on the contents of the input paths.
// Returns undefined if it's not possible to generate a stable key.
static async readInputKey(
inputPaths: string[],
): Promise<CacheKey | undefined> {
const quotedInputPaths = inputPaths.map(input => `'${input}'`);
// Make sure we don't have any uncommitted changes to the input, in that case we skip caching.
const noChanges = await runCheck(
`git diff --quiet HEAD -- ${quotedInputPaths.join(' ')}`,
);
if (!noChanges) {
return undefined;
}
const trees = [];
for (const inputPath of inputPaths) {
const output = await runPlain(`git ls-tree HEAD '${inputPath}'`);
for (const quotedInputPath of quotedInputPaths) {
const output = await runPlain(`git ls-tree HEAD ${quotedInputPath}`);
const [, , sha] = output.split(/\s+/, 3);
trees.push(sha);
}
@@ -88,17 +93,14 @@ export class Cache {
}
constructor(
private readonly location: string,
private readonly entries: CacheEntry[] = [],
private readonly location?: string,
private readonly localKey?: CacheKey,
) {}
// Query for the presense of cached output for a given key
query(key: CacheKey): CacheQueryResult {
const { location } = this;
if (!location) {
return { hit: false };
}
const archive = async (outputDir: string, maxEntries: number) => {
await writeCacheInfo(outputDir, { key });
+16 -10
View File
@@ -30,8 +30,15 @@ function print(msg: string) {
*/
export default async (cmd: Command, args: string[]) => {
const options = await parseOptions(cmd);
const cache = await Cache.read(options);
const key = await Cache.readInputKey(options.inputs);
if (!key) {
print('input directory is dirty, skipping cache');
await run(args[0], args.slice(1));
return;
}
const cache = await Cache.read(options);
const cacheResult = cache.query(key);
if (cacheResult.hit) {
@@ -41,14 +48,13 @@ export default async (cmd: Command, args: string[]) => {
} else {
print('cache hit, nothing to be done');
}
} else {
print('cache miss, need to build');
await run(args[0], args.slice(1));
if (cacheResult.archive) {
print('caching build output');
await cacheResult.archive(options.output, options.maxCacheEntries);
}
return;
}
print('cache miss, need to build');
await run(args[0], args.slice(1));
print('caching build output');
await cacheResult.archive(options.output, options.maxCacheEntries);
};