mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-09 05:32:24 +00:00
106 lines
3.0 KiB
TypeScript
106 lines
3.0 KiB
TypeScript
import is from '@sindresorhus/is';
|
|
import { GlobalConfig } from '../../../../config/global';
|
|
import { logger } from '../../../../logger';
|
|
import { compress, decompress } from '../../../compress';
|
|
import { hash } from '../../../hash';
|
|
import { safeStringify } from '../../../stringify';
|
|
import { CACHE_REVISION } from '../common';
|
|
import { RepoCacheRecord, RepoCacheV13 } from '../schema';
|
|
import type { RepoCache, RepoCacheData } from '../types';
|
|
|
|
export abstract class RepoCacheBase implements RepoCache {
|
|
protected platform = GlobalConfig.get('platform')!;
|
|
private oldHash: string | null = null;
|
|
private data: RepoCacheData = {};
|
|
|
|
protected constructor(
|
|
protected readonly repository: string,
|
|
protected readonly fingerprint: string
|
|
) {}
|
|
|
|
protected abstract read(): Promise<string | null>;
|
|
|
|
protected abstract write(data: RepoCacheRecord): Promise<void>;
|
|
|
|
private static parseData(input: string): RepoCacheData {
|
|
const data: RepoCacheData = JSON.parse(input);
|
|
// istanbul ignore next
|
|
if (data.branches) {
|
|
for (const branch of data.branches) {
|
|
if (branch.branchFingerprint) {
|
|
branch.commitFingerprint = branch.branchFingerprint;
|
|
delete branch.branchFingerprint;
|
|
}
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
private async restore(oldCache: RepoCacheRecord): Promise<void> {
|
|
if (oldCache.fingerprint !== this.fingerprint) {
|
|
logger.debug('Repository cache fingerprint is invalid');
|
|
return;
|
|
}
|
|
const jsonStr = await decompress(oldCache.payload);
|
|
this.data = RepoCacheBase.parseData(jsonStr);
|
|
this.oldHash = oldCache.hash;
|
|
}
|
|
|
|
async load(): Promise<void> {
|
|
try {
|
|
const oldCache = await this.read();
|
|
if (!is.string(oldCache)) {
|
|
logger.debug(
|
|
`RepoCacheBase.load() - expecting data of type 'string' received '${typeof oldCache}' instead - skipping`
|
|
);
|
|
return;
|
|
}
|
|
|
|
const cacheV13 = RepoCacheV13.safeParse(oldCache);
|
|
if (cacheV13.success) {
|
|
await this.restore(cacheV13.data);
|
|
logger.debug('Repository cache is restored from revision 13');
|
|
return;
|
|
}
|
|
|
|
logger.debug('Repository cache is invalid');
|
|
} catch (err) /* istanbul ignore next: not easily testable */ {
|
|
logger.debug({ err }, 'Error reading repository cache');
|
|
}
|
|
}
|
|
|
|
async save(): Promise<void> {
|
|
const jsonStr = safeStringify(this.data);
|
|
const hashedJsonStr = hash(jsonStr);
|
|
if (hashedJsonStr === this.oldHash) {
|
|
return;
|
|
}
|
|
|
|
const revision = CACHE_REVISION;
|
|
const repository = this.repository;
|
|
const fingerprint = this.fingerprint;
|
|
|
|
const payload = await compress(jsonStr);
|
|
|
|
await this.write({
|
|
revision,
|
|
repository,
|
|
fingerprint,
|
|
payload,
|
|
hash: hashedJsonStr,
|
|
});
|
|
}
|
|
|
|
getData(): RepoCacheData {
|
|
return this.data;
|
|
}
|
|
|
|
isModified(): boolean | undefined {
|
|
if (!this.oldHash) {
|
|
return undefined;
|
|
}
|
|
const jsonStr = safeStringify(this.data);
|
|
return hash(jsonStr) !== this.oldHash;
|
|
}
|
|
}
|