UNPKG

sourcecontrol

Version:

A modern TypeScript CLI application for source control

97 lines 4.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BranchCheckout = void 0; const repo_1 = require("../../../core/repo"); const utils_1 = require("../../../utils"); class BranchCheckout { constructor(repository, refService, branchCreator, workdirManager) { this.repository = repository; this.refService = refService; this.branchCreator = branchCreator; this.workdirManager = workdirManager; } async checkout(target, options = {}) { await this.validateTarget(target, options); await this.checkWorkingDirectoryStatus(options.force || false); if (options.create) { await this.branchCreator.createBranch(target); } const isBranch = await this.refService.exists(target); if (isBranch && !options.detach) { await this.checkoutBranch(target, options.force || false); } else { await this.checkoutCommit(target, options.force || false); } } async validateTarget(target, options) { const branchExists = await this.refService.exists(target); if (branchExists || options.create) { return; } try { await repo_1.ObjectReader.readCommit(this.repository, target); } catch { } if (target.length >= 4 && target.length < 40 && /^[0-9a-f]+$/i.test(target)) { utils_1.logger.warn(`Partial SHA matching not yet implemented for: ${target}`); } throw new Error(`pathspec '${target}' did not match any file(s) known to git.\n` + `Did you forget to 'git add'?`); } async checkoutBranch(branchName, force) { const commitSha = await this.refService.getBranchSha(branchName); const currentBranch = await this.refService.getCurrentBranch(); if (currentBranch === branchName) { utils_1.logger.info(`Already on '${branchName}'`); return; } const changes = await this.workdirManager.updateToCommit(commitSha, { force: force }); await this.refService.setCurrentBranch(branchName); this.logCheckoutResult(branchName, commitSha, changes.filesChanged, false); } async checkoutCommit(commitSha, force) { await repo_1.ObjectReader.readCommit(this.repository, commitSha); const { filesChanged } = await this.workdirManager.updateToCommit(commitSha, { force }); await this.refService.setDetachedHead(commitSha); this.logCheckoutResult(commitSha, commitSha, filesChanged, true); } logCheckoutResult(target, commitSha, fileChangeCount, isDetached) { const shortSha = commitSha.substring(0, 7); if (isDetached) { utils_1.logger.info(`Note: switching to '${target}'.`); utils_1.logger.info(''); utils_1.logger.info("You are in 'detached HEAD' state. You can look around, make experimental"); utils_1.logger.info('changes and commit them, and you can discard any commits you make in this'); utils_1.logger.info('state without impacting any branches by switching back to a branch.'); utils_1.logger.info(''); utils_1.logger.info(`HEAD is now at ${shortSha}`); } else { utils_1.logger.info(`Switched to branch '${target}'`); } if (fileChangeCount > 0) { utils_1.logger.debug(`Updated ${fileChangeCount} file(s) in working directory`); } } async checkWorkingDirectoryStatus(force) { if (force) { utils_1.logger.warn('Force checkout: local changes will be discarded'); return; } const status = await this.workdirManager.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`); } } } exports.BranchCheckout = BranchCheckout; //# sourceMappingURL=branch-checkout.js.map