sourcecontrol
Version:
A modern TypeScript CLI application for source control
122 lines • 5.73 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkingDirectoryManager = void 0;
const index_1 = require("../../core/index");
const utils_1 = require("../../utils");
const path_1 = __importDefault(require("path"));
const internal_1 = require("./internal");
class WorkingDirectoryManager {
constructor(repository) {
this.workingDirectory = repository.workingDirectory().fullpath();
this.indexPath = path_1.default.join(repository.gitDirectory().fullpath(), index_1.IndexManager.INDEX_FILE_NAME);
this.fileService = new internal_1.FileOperationService(repository, this.workingDirectory);
this.treeAnalyzer = new internal_1.TreeAnalyzer(repository);
this.validator = new internal_1.WorkingDirectoryValidator(this.workingDirectory);
this.atomicManager = new internal_1.AtomicOperationManager(this.fileService);
this.indexUpdater = new internal_1.IndexUpdater(this.workingDirectory, this.indexPath);
}
async updateToCommit(commitSha, options = {}) {
utils_1.logger.debug(`Updating working directory to commit ${commitSha}`);
try {
if (!options.force) {
await this.performSafetyChecks();
}
const { operations, targetFiles } = await this.analyzeRequiredChanges(commitSha);
if (operations.length === 0) {
utils_1.logger.info('Working directory is already up to date');
return {
success: true,
filesChanged: 0,
operationResult: { success: true, operationsApplied: 0, totalOperations: 0 },
error: null,
};
}
if (options.dryRun) {
return await this.performDryRun(operations);
}
const operationResult = await this.atomicManager.executeAtomically(operations);
if (!operationResult.success) {
return {
success: false,
filesChanged: operationResult.operationsApplied,
error: operationResult.error ? operationResult.error : null,
operationResult,
};
}
const indexUpdateResult = await this.indexUpdater.updateToMatch(targetFiles);
if (!indexUpdateResult.success) {
utils_1.logger.error('File operations succeeded but index update failed:', indexUpdateResult.errors);
}
utils_1.logger.info(`Successfully updated ${operationResult.operationsApplied} files`);
return {
success: true,
filesChanged: operationResult.operationsApplied,
operationResult,
indexUpdateResult,
error: null,
};
}
catch (error) {
utils_1.logger.error('Failed to update working directory:', error);
return {
success: false,
filesChanged: 0,
operationResult: { success: false, operationsApplied: 0, totalOperations: 0 },
error: error,
};
}
}
async isClean() {
const index = await index_1.GitIndex.read(this.indexPath);
return await this.validator.validateCleanState(index);
}
async analyzeRequiredChanges(commitSha) {
const targetFiles = await this.treeAnalyzer.getCommitFiles(commitSha);
const currentIndex = await index_1.GitIndex.read(this.indexPath);
const indexFiles = this.treeAnalyzer.getIndexFiles(currentIndex);
const { operations, summary } = this.treeAnalyzer.analyzeChanges(indexFiles, targetFiles);
return {
operations,
targetFiles,
summary,
};
}
async performSafetyChecks() {
const status = await this.isClean();
if (!status.clean) {
const filesList = status.modifiedFiles.slice(0, 10).join('\n ');
const moreFiles = status.modifiedFiles.length > 10
? `\n ... and ${status.modifiedFiles.length - 10} more files`
: '';
throw new Error(`error: Your local changes to the following files would be overwritten by checkout:\n` +
` ${filesList}${moreFiles}\n` +
`Please commit your changes or stash them before you switch branches.\n` +
`Aborting`);
}
}
async performDryRun(operations) {
const dryRunResult = await this.atomicManager.dryRun(operations);
utils_1.logger.info('Dry run results:');
utils_1.logger.info(` Would create: ${dryRunResult.analysis.willCreate.length} files`);
utils_1.logger.info(` Would modify: ${dryRunResult.analysis.willModify.length} files`);
utils_1.logger.info(` Would delete: ${dryRunResult.analysis.willDelete.length} files`);
if (dryRunResult.analysis.conflicts.length > 0) {
utils_1.logger.warn(' Conflicts:', dryRunResult.analysis.conflicts);
}
return {
success: dryRunResult.valid,
filesChanged: 0,
operationResult: {
success: dryRunResult.valid,
operationsApplied: 0,
totalOperations: operations.length,
},
error: dryRunResult.valid ? null : new Error(`Conflicts: ${dryRunResult.errors.join(', ')}`),
};
}
}
exports.WorkingDirectoryManager = WorkingDirectoryManager;
//# sourceMappingURL=work-dir-manager.js.map
;