Skip to content

Commit 5553acb

Browse files
committed
cleanup git stash functionality
1 parent 31c21ce commit 5553acb

3 files changed

Lines changed: 62 additions & 37 deletions

File tree

extensions/git/src/commands.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,45 +1093,55 @@ export class CommandCenter {
10931093
}
10941094

10951095
@command('git.stash')
1096-
async stash() : Promise<void> {
1097-
const noUnstagedChanges = this.model.workingTreeGroup.resources.length === 0;
1098-
if (noUnstagedChanges){
1096+
async stash(): Promise<void> {
1097+
if (this.model.workingTreeGroup.resources.length === 0) {
10991098
window.showInformationMessage(localize('no changes stash', "There are no changes to stash."));
11001099
return;
11011100
}
1102-
return await this.model.stash();
1101+
1102+
const message = await window.showInputBox({
1103+
prompt: localize('provide stash message', "Optionally provide a stash message"),
1104+
placeHolder: localize('stash message', "Stash message")
1105+
});
1106+
1107+
if (typeof message === 'undefined') {
1108+
return;
1109+
}
1110+
1111+
await this.model.createStash(message);
11031112
}
11041113

11051114
@command('git.stashPop')
11061115
async stashPop(): Promise<void> {
1107-
let stashes = await this.model.getStashes();
1108-
const noStashes = stashes.length === 0;
1109-
if (noStashes){
1116+
const stashes = await this.model.getStashes();
1117+
1118+
if (stashes.length === 0) {
11101119
window.showInformationMessage(localize('no stashes', "There are no stashes to restore."));
11111120
return;
11121121
}
11131122

1114-
const picks = stashes.map(r => { return { label: `#${r.id}: ${r.description}`, description: "", derails: "", id: r.id }; });
1115-
const placeHolder = localize('pick stash', "Pick a stash");
1123+
const picks = stashes.map(r => ({ label: `#${r.index}: ${r.description}`, description: '', details: '', id: r.index }));
1124+
const placeHolder = localize('pick stash to pop', "Pick a stash to pop");
11161125
const choice = await window.showQuickPick(picks, { placeHolder });
11171126

11181127
if (!choice) {
11191128
return;
11201129
}
1121-
return await this.model.stash(true, choice.id);
1130+
1131+
await this.model.popStash(choice.id);
11221132
}
11231133

11241134
@command('git.stashPopLatest')
11251135
async stashPopLatest(): Promise<void> {
1126-
let stashes = await this.model.getStashes();
1127-
const noStashes = stashes.length === 0;
1128-
if (noStashes){
1136+
const stashes = await this.model.getStashes();
1137+
1138+
if (stashes.length === 0) {
11291139
window.showInformationMessage(localize('no stashes', "There are no stashes to restore."));
11301140
return;
11311141
}
1132-
return await this.model.stash(true);
1133-
}
11341142

1143+
await this.model.popStash();
1144+
}
11351145

11361146
private createCommand(id: string, key: string, method: Function, skipModelCheck: boolean): (...args: any[]) => any {
11371147
const result = (...args) => {

extensions/git/src/git.ts

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export interface Remote {
3434
}
3535

3636
export interface Stash {
37-
id : string;
37+
index: number;
3838
description: string;
3939
}
4040

@@ -842,28 +842,40 @@ export class Repository {
842842
}
843843
}
844844

845-
async stash(pop: boolean = false, index?: string): Promise<void> {
845+
async createStash(message?: string): Promise<void> {
846846
try {
847-
const args = ['stash'];
847+
const args = ['stash', 'save'];
848848

849-
if (pop) {
850-
args.push('pop');
851-
if (index) {
852-
args.push(`stash@{${index}}`);
853-
}
849+
if (message) {
850+
args.push('--', message);
854851
}
855852

856853
await this.run(args);
857854
} catch (err) {
858855
if (/No local changes to save/.test(err.stderr || '')) {
859856
err.gitErrorCode = GitErrorCodes.NoLocalChanges;
860857
}
861-
else if (/No stash found/.test(err.stderr || '')) {
862-
err.gitErrorCode = GitErrorCodes.NoStashFound;
858+
859+
throw err;
860+
}
861+
}
862+
863+
async popStash(index?: number): Promise<void> {
864+
try {
865+
const args = ['stash', 'pop'];
866+
867+
if (typeof index === 'string') {
868+
args.push(`stash@{${index}}`);
863869
}
864-
else if (/error: Your local changes to the following files would be overwritten/.test(err.stderr || '')) {
870+
871+
await this.run(args);
872+
} catch (err) {
873+
if (/No stash found/.test(err.stderr || '')) {
874+
err.gitErrorCode = GitErrorCodes.NoStashFound;
875+
} else if (/error: Your local changes to the following files would be overwritten/.test(err.stderr || '')) {
865876
err.gitErrorCode = GitErrorCodes.LocalChangesOverwritten;
866877
}
878+
867879
throw err;
868880
}
869881
}
@@ -957,15 +969,15 @@ export class Repository {
957969

958970
async getStashes(): Promise<Stash[]> {
959971
const result = await this.run(['stash', 'list']);
960-
const regex = /^stash@{(\d+)}:(.+)/;
972+
const regex = /^stash@{(\d+)}:(.+)$/;
961973
const rawStashes = result.stdout.trim().split('\n')
962974
.filter(b => !!b)
963975
.map(line => regex.exec(line))
964976
.filter(g => !!g)
965-
.map((groups: RegExpExecArray) => ({ id: groups[1], description: groups[2] }));
966-
return uniqBy(rawStashes, remote => remote.id);
967-
}
977+
.map(([, index, description]: RegExpExecArray) => ({ index: parseInt(index), description }));
968978

979+
return rawStashes;
980+
}
969981

970982
async getRemotes(): Promise<Remote[]> {
971983
const result = await this.run(['remote', '--verbose']);

extensions/git/src/model.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -543,9 +543,16 @@ export class Model implements Disposable {
543543
});
544544
}
545545

546-
@throttle
547-
async stash(pop: boolean = false, index?: string): Promise<void> {
548-
return await this.run(Operation.Stash, () => this.repository.stash(pop, index));
546+
async getStashes(): Promise<Stash[]> {
547+
return await this.repository.getStashes();
548+
}
549+
550+
async createStash(message?: string): Promise<void> {
551+
return await this.run(Operation.Stash, () => this.repository.createStash(message));
552+
}
553+
554+
async popStash(index?: number): Promise<void> {
555+
return await this.run(Operation.Stash, () => this.repository.popStash(index));
549556
}
550557

551558
async getCommitTemplate(): Promise<string> {
@@ -574,10 +581,6 @@ export class Model implements Disposable {
574581
});
575582
}
576583

577-
async getStashes(): Promise<Stash[]> {
578-
return await this.getStashes();
579-
}
580-
581584
private async run<T>(operation: Operation, runOperation: () => Promise<T> = () => Promise.resolve<any>(null)): Promise<T> {
582585
const run = async () => {
583586
this._operations = this._operations.start(operation);

0 commit comments

Comments
 (0)