UNPKG

@git.zone/cli

Version:

A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.

259 lines 22.6 kB
import * as plugins from './mod.plugins.js'; import * as paths from '../paths.js'; export class RollbackManager { backupDir; manifestPath; constructor() { this.backupDir = plugins.path.join(paths.cwd, '.nogit', 'gitzone-backups'); this.manifestPath = plugins.path.join(this.backupDir, 'manifest.json'); } async createOperation() { await this.ensureBackupDir(); const operation = { id: this.generateOperationId(), timestamp: Date.now(), files: [], status: 'pending', }; await this.updateManifest(operation); return operation; } async backupFile(filepath, operationId) { const operation = await this.getOperation(operationId); if (!operation) { throw new Error(`Operation ${operationId} not found`); } const absolutePath = plugins.path.isAbsolute(filepath) ? filepath : plugins.path.join(paths.cwd, filepath); // Check if file exists const exists = await plugins.smartfs.file(absolutePath).exists(); if (!exists) { // File doesn't exist yet (will be created), so we skip backup return; } // Read file content and metadata const content = (await plugins.smartfs .file(absolutePath) .encoding('utf8') .read()); const stats = await plugins.smartfs.file(absolutePath).stat(); const checksum = this.calculateChecksum(content); // Create backup const backupPath = this.getBackupPath(operationId, filepath); await plugins.smartfs .directory(plugins.path.dirname(backupPath)) .recursive() .create(); await plugins.smartfs.file(backupPath).encoding('utf8').write(content); // Update operation operation.files.push({ path: filepath, originalContent: content, checksum, permissions: stats.mode.toString(8), }); await this.updateManifest(operation); } async rollback(operationId) { const operation = await this.getOperation(operationId); if (!operation) { // Operation doesn't exist, might have already been rolled back or never created console.warn(`Operation ${operationId} not found for rollback, skipping`); return; } if (operation.status === 'rolled-back') { throw new Error(`Operation ${operationId} has already been rolled back`); } // Restore files in reverse order for (let i = operation.files.length - 1; i >= 0; i--) { const file = operation.files[i]; const absolutePath = plugins.path.isAbsolute(file.path) ? file.path : plugins.path.join(paths.cwd, file.path); // Verify backup integrity const backupPath = this.getBackupPath(operationId, file.path); const backupContent = await plugins.smartfs .file(backupPath) .encoding('utf8') .read(); const backupChecksum = this.calculateChecksum(backupContent); if (backupChecksum !== file.checksum) { throw new Error(`Backup integrity check failed for ${file.path}`); } // Restore file await plugins.smartfs .file(absolutePath) .encoding('utf8') .write(file.originalContent); // Restore permissions const mode = parseInt(file.permissions, 8); // Note: Permissions restoration may not work on all platforms } // Update operation status operation.status = 'rolled-back'; await this.updateManifest(operation); } async markComplete(operationId) { const operation = await this.getOperation(operationId); if (!operation) { throw new Error(`Operation ${operationId} not found`); } operation.status = 'completed'; await this.updateManifest(operation); } async cleanOldBackups(retentionDays) { const manifest = await this.getManifest(); const cutoffTime = Date.now() - retentionDays * 24 * 60 * 60 * 1000; const operationsToDelete = manifest.operations.filter((op) => op.timestamp < cutoffTime && op.status === 'completed'); for (const operation of operationsToDelete) { // Remove backup files const operationDir = plugins.path.join(this.backupDir, 'operations', operation.id); await plugins.smartfs.directory(operationDir).recursive().delete(); // Remove from manifest manifest.operations = manifest.operations.filter((op) => op.id !== operation.id); } await this.saveManifest(manifest); } async verifyBackup(operationId) { const operation = await this.getOperation(operationId); if (!operation) { return false; } for (const file of operation.files) { const backupPath = this.getBackupPath(operationId, file.path); const exists = await plugins.smartfs.file(backupPath).exists(); if (!exists) { return false; } const content = await plugins.smartfs .file(backupPath) .encoding('utf8') .read(); const checksum = this.calculateChecksum(content); if (checksum !== file.checksum) { return false; } } return true; } async listBackups() { const manifest = await this.getManifest(); return manifest.operations; } async ensureBackupDir() { await plugins.smartfs.directory(this.backupDir).recursive().create(); await plugins.smartfs .directory(plugins.path.join(this.backupDir, 'operations')) .recursive() .create(); } generateOperationId() { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const random = Math.random().toString(36).substring(2, 8); return `${timestamp}-${random}`; } getBackupPath(operationId, filepath) { const filename = plugins.path.basename(filepath); const dir = plugins.path.dirname(filepath); const safeDir = dir.replace(/[/\\]/g, '__'); return plugins.path.join(this.backupDir, 'operations', operationId, 'files', safeDir, `${filename}.backup`); } calculateChecksum(content) { return plugins.crypto.createHash('sha256').update(content).digest('hex'); } async getManifest() { const defaultManifest = { operations: [] }; const exists = await plugins.smartfs.file(this.manifestPath).exists(); if (!exists) { return defaultManifest; } try { const content = (await plugins.smartfs .file(this.manifestPath) .encoding('utf8') .read()); const manifest = JSON.parse(content); // Validate the manifest structure if (this.isValidManifest(manifest)) { return manifest; } else { console.warn('Invalid rollback manifest structure, returning default manifest'); return defaultManifest; } } catch (error) { console.warn(`Failed to read rollback manifest: ${error.message}, returning default manifest`); // Try to delete the corrupted file try { await plugins.smartfs.file(this.manifestPath).delete(); } catch (removeError) { // Ignore removal errors } return defaultManifest; } } async saveManifest(manifest) { // Validate before saving if (!this.isValidManifest(manifest)) { throw new Error('Invalid rollback manifest structure, cannot save'); } // Ensure directory exists await this.ensureBackupDir(); // Write directly with proper JSON stringification const jsonContent = JSON.stringify(manifest, null, 2); await plugins.smartfs .file(this.manifestPath) .encoding('utf8') .write(jsonContent); } async getOperation(operationId) { const manifest = await this.getManifest(); return manifest.operations.find((op) => op.id === operationId) || null; } async updateManifest(operation) { const manifest = await this.getManifest(); const existingIndex = manifest.operations.findIndex((op) => op.id === operation.id); if (existingIndex !== -1) { manifest.operations[existingIndex] = operation; } else { manifest.operations.push(operation); } await this.saveManifest(manifest); } isValidManifest(manifest) { // Check if manifest has the required structure if (!manifest || typeof manifest !== 'object') { return false; } // Check required fields if (!Array.isArray(manifest.operations)) { return false; } // Check each operation entry for (const operation of manifest.operations) { if (!operation || typeof operation !== 'object' || typeof operation.id !== 'string' || typeof operation.timestamp !== 'number' || typeof operation.status !== 'string' || !Array.isArray(operation.files)) { return false; } // Check each file in the operation for (const file of operation.files) { if (!file || typeof file !== 'object' || typeof file.path !== 'string' || typeof file.checksum !== 'string') { return false; } } } return true; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yb2xsYmFja21hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfZm9ybWF0L2NsYXNzZXMucm9sbGJhY2ttYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLEtBQUssTUFBTSxhQUFhLENBQUM7QUFHckMsTUFBTSxPQUFPLGVBQWU7SUFDbEIsU0FBUyxDQUFTO0lBQ2xCLFlBQVksQ0FBUztJQUU3QjtRQUNFLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUMzRSxJQUFJLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlO1FBQ25CLE1BQU0sSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRTdCLE1BQU0sU0FBUyxHQUFxQjtZQUNsQyxFQUFFLEVBQUUsSUFBSSxDQUFDLG1CQUFtQixFQUFFO1lBQzlCLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ3JCLEtBQUssRUFBRSxFQUFFO1lBQ1QsTUFBTSxFQUFFLFNBQVM7U0FDbEIsQ0FBQztRQUVGLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFnQixFQUFFLFdBQW1CO1FBQ3BELE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7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