156 lines
4.3 KiB
TypeScript
156 lines
4.3 KiB
TypeScript
import * as plugins from './mod.plugins.js';
|
|
import * as paths from '../paths.js';
|
|
|
|
export interface IFileCache {
|
|
path: string;
|
|
checksum: string;
|
|
modified: number;
|
|
size: number;
|
|
}
|
|
|
|
export interface ICacheManifest {
|
|
version: string;
|
|
lastFormat: number;
|
|
files: IFileCache[];
|
|
}
|
|
|
|
export class ChangeCache {
|
|
private cacheDir: string;
|
|
private manifestPath: string;
|
|
private cacheVersion = '1.0.0';
|
|
|
|
constructor() {
|
|
this.cacheDir = plugins.path.join(paths.cwd, '.nogit', 'gitzone-cache');
|
|
this.manifestPath = plugins.path.join(this.cacheDir, 'manifest.json');
|
|
}
|
|
|
|
async initialize(): Promise<void> {
|
|
await plugins.smartfile.fs.ensureDir(this.cacheDir);
|
|
}
|
|
|
|
async getManifest(): Promise<ICacheManifest> {
|
|
const exists = await plugins.smartfile.fs.fileExists(this.manifestPath);
|
|
if (!exists) {
|
|
return {
|
|
version: this.cacheVersion,
|
|
lastFormat: 0,
|
|
files: []
|
|
};
|
|
}
|
|
|
|
const content = plugins.smartfile.fs.toStringSync(this.manifestPath);
|
|
return JSON.parse(content);
|
|
}
|
|
|
|
async saveManifest(manifest: ICacheManifest): Promise<void> {
|
|
await plugins.smartfile.memory.toFs(JSON.stringify(manifest, null, 2), this.manifestPath);
|
|
}
|
|
|
|
async hasFileChanged(filePath: string): Promise<boolean> {
|
|
const absolutePath = plugins.path.isAbsolute(filePath)
|
|
? filePath
|
|
: plugins.path.join(paths.cwd, filePath);
|
|
|
|
// Check if file exists
|
|
const exists = await plugins.smartfile.fs.fileExists(absolutePath);
|
|
if (!exists) {
|
|
return true; // File doesn't exist, so it's "changed" (will be created)
|
|
}
|
|
|
|
// Get current file stats
|
|
const stats = await plugins.smartfile.fs.stat(absolutePath);
|
|
|
|
// Skip directories
|
|
if (stats.isDirectory()) {
|
|
return false; // Directories are not processed
|
|
}
|
|
|
|
const content = plugins.smartfile.fs.toStringSync(absolutePath);
|
|
const currentChecksum = this.calculateChecksum(content);
|
|
|
|
// Get cached info
|
|
const manifest = await this.getManifest();
|
|
const cachedFile = manifest.files.find(f => f.path === filePath);
|
|
|
|
if (!cachedFile) {
|
|
return true; // Not in cache, so it's changed
|
|
}
|
|
|
|
// Compare checksums
|
|
return cachedFile.checksum !== currentChecksum ||
|
|
cachedFile.size !== stats.size ||
|
|
cachedFile.modified !== stats.mtimeMs;
|
|
}
|
|
|
|
async updateFileCache(filePath: string): Promise<void> {
|
|
const absolutePath = plugins.path.isAbsolute(filePath)
|
|
? filePath
|
|
: plugins.path.join(paths.cwd, filePath);
|
|
|
|
// Get current file stats
|
|
const stats = await plugins.smartfile.fs.stat(absolutePath);
|
|
|
|
// Skip directories
|
|
if (stats.isDirectory()) {
|
|
return; // Don't cache directories
|
|
}
|
|
|
|
const content = await plugins.smartfile.fs.toStringSync(absolutePath);
|
|
const checksum = this.calculateChecksum(content);
|
|
|
|
// Update manifest
|
|
const manifest = await this.getManifest();
|
|
const existingIndex = manifest.files.findIndex(f => f.path === filePath);
|
|
|
|
const cacheEntry: IFileCache = {
|
|
path: filePath,
|
|
checksum,
|
|
modified: stats.mtimeMs,
|
|
size: stats.size
|
|
};
|
|
|
|
if (existingIndex !== -1) {
|
|
manifest.files[existingIndex] = cacheEntry;
|
|
} else {
|
|
manifest.files.push(cacheEntry);
|
|
}
|
|
|
|
manifest.lastFormat = Date.now();
|
|
await this.saveManifest(manifest);
|
|
}
|
|
|
|
async getChangedFiles(filePaths: string[]): Promise<string[]> {
|
|
const changedFiles: string[] = [];
|
|
|
|
for (const filePath of filePaths) {
|
|
if (await this.hasFileChanged(filePath)) {
|
|
changedFiles.push(filePath);
|
|
}
|
|
}
|
|
|
|
return changedFiles;
|
|
}
|
|
|
|
async clean(): Promise<void> {
|
|
const manifest = await this.getManifest();
|
|
const validFiles: IFileCache[] = [];
|
|
|
|
// Remove entries for files that no longer exist
|
|
for (const file of manifest.files) {
|
|
const absolutePath = plugins.path.isAbsolute(file.path)
|
|
? file.path
|
|
: plugins.path.join(paths.cwd, file.path);
|
|
|
|
if (await plugins.smartfile.fs.fileExists(absolutePath)) {
|
|
validFiles.push(file);
|
|
}
|
|
}
|
|
|
|
manifest.files = validFiles;
|
|
await this.saveManifest(manifest);
|
|
}
|
|
|
|
private calculateChecksum(content: string | Buffer): string {
|
|
return plugins.crypto.createHash('sha256').update(content).digest('hex');
|
|
}
|
|
} |