|
| 1 | +import type { StatusBarItem } from 'vscode'; |
| 2 | +import { MarkdownString , StatusBarAlignment , window} from 'vscode'; |
| 3 | +import type { Container } from '../container'; |
| 4 | +import type { GitBranch } from '../git/models/branch'; |
| 5 | +import type { |
| 6 | + ViewRefNode, |
| 7 | +} from './nodes/viewNode'; |
| 8 | + |
| 9 | +export class CommitStack { |
| 10 | + private container: Container; |
| 11 | + // The stack which is pushed to and popped from. |
| 12 | + // We push and pop ViewRefNode types for convenience since these nodes |
| 13 | + // coorespond to commit refs in the Commit view. |
| 14 | + private stack: ViewRefNode[] = []; |
| 15 | + // A StatusBarItem is created and displayed when the stack is not empty. |
| 16 | + private statusBarItem?: StatusBarItem; |
| 17 | + // The git ref that was checked out before any commit was pushed to the stack. |
| 18 | + private originalRef?: GitBranch; |
| 19 | + |
| 20 | + constructor(container: Container) { |
| 21 | + this.container = container; |
| 22 | + } |
| 23 | + |
| 24 | + private renderStatusBarTooltip = (): MarkdownString => { |
| 25 | + const tooltip = new MarkdownString(); |
| 26 | + if (this.originalRef) { |
| 27 | + tooltip.appendMarkdown(`**original ref**: ${this.originalRef.name}\n\n`); |
| 28 | + } |
| 29 | + this.stack.forEach((n: ViewRefNode, i: number) => { |
| 30 | + tooltip.appendMarkdown(`**${i}**. **commit**: ${n.ref.name}\n\n`); |
| 31 | + }); |
| 32 | + return tooltip; |
| 33 | + }; |
| 34 | + |
| 35 | + async push(commit: ViewRefNode): Promise<void> { |
| 36 | + if (this.stack.length == 0) { |
| 37 | + // track the 'ref' the branh was on before we start adding to the |
| 38 | + // stack, we'll restore to this ref after the stack is emptied. |
| 39 | + this.originalRef = await this.container.git.getBranch(commit.repoPath); |
| 40 | + this.statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 100); |
| 41 | + this.statusBarItem.show(); |
| 42 | + } |
| 43 | + this.stack.push(commit); |
| 44 | + if (this.statusBarItem) { |
| 45 | + this.statusBarItem.text = `commit stack: ${commit.ref.name} ${this.stack.length}`; |
| 46 | + this.statusBarItem.tooltip = this.renderStatusBarTooltip(); |
| 47 | + } |
| 48 | + void window.showInformationMessage(`Pushed ${commit.ref.name} onto stack`); |
| 49 | + return Promise.resolve(); |
| 50 | + } |
| 51 | + |
| 52 | + async pop(): Promise<ViewRefNode|void>{ |
| 53 | + if (this.stack.length == 0) { |
| 54 | + void window.showErrorMessage("Stack is empty.\nUse 'Switch to Commit (Stacked) command to push a commit to the stack."); |
| 55 | + return; |
| 56 | + } |
| 57 | + const node = this.stack.pop(); |
| 58 | + // this just shuts the compiler up, it doesn't understand that pop() |
| 59 | + // won't return an undefined since we check length above. |
| 60 | + if (!node) { |
| 61 | + return; |
| 62 | + } |
| 63 | + void window.showInformationMessage(`Popped ${node.ref.name} from stack`); |
| 64 | + if (this.stack.length == 0) { |
| 65 | + await this.empty(); |
| 66 | + return; |
| 67 | + } |
| 68 | + const curNode = this.stack[this.stack.length-1]; |
| 69 | + if (this.statusBarItem) { |
| 70 | + this.statusBarItem.text = `commit stack: ${curNode.ref.name} ${this.stack.length}`; |
| 71 | + this.statusBarItem.tooltip = this.renderStatusBarTooltip(); |
| 72 | + } |
| 73 | + return curNode; |
| 74 | + } |
| 75 | + |
| 76 | + async empty(): Promise<void> { |
| 77 | + this.stack = []; |
| 78 | + this.statusBarItem?.dispose(); |
| 79 | + this.statusBarItem = undefined; |
| 80 | + void window.showInformationMessage('Stack is now empty.'); |
| 81 | + if (this.originalRef) { |
| 82 | + // if we stored a original 'ref' before pushing to the stack, |
| 83 | + // restore it. |
| 84 | + await this.container.git.checkout(this.originalRef.repoPath, this.originalRef.ref); |
| 85 | + void window.showInformationMessage(`Restored original ref to ${this.originalRef.name}`); |
| 86 | + this.originalRef = undefined; |
| 87 | + } |
| 88 | + return Promise.resolve(); |
| 89 | + } |
| 90 | + |
| 91 | +} |
0 commit comments