This commit is contained in:
João Moreno 2020-11-09 15:19:15 +01:00
parent df4524f713
commit ec084a25bd

View file

@ -6,7 +6,7 @@
import { lstat, Stats } from 'fs';
import * as os from 'os';
import * as path from 'path';
import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, SourceControl, TextDocumentContentProvider } from 'vscode';
import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider } from 'vscode';
import TelemetryReporter from 'vscode-extension-telemetry';
import * as nls from 'vscode-nls';
import { Branch, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourceProvider } from './api/git';
@ -1786,25 +1786,20 @@ export class CommandCenter {
@command('git.checkout', { repository: true })
async checkout(repository: Repository, treeish?: string): Promise<boolean> {
if (typeof treeish === 'string') {
await repository.checkout(treeish);
return true;
}
return this._checkout(repository);
return this._checkout(repository, { treeish });
}
@command('git.checkoutDetached', { repository: true })
async checkoutDetached(repository: Repository, treeish?: string): Promise<boolean> {
if (typeof treeish === 'string') {
await repository.checkout(treeish, { detached: true });
return this._checkout(repository, { detached: true, treeish });
}
private async _checkout(repository: Repository, opts?: { detached?: boolean, treeish?: string }): Promise<boolean> {
if (typeof opts?.treeish === 'string') {
await repository.checkout(opts?.treeish, opts);
return true;
}
return this._checkout(repository, { detached: true });
}
private async _checkout(repository: Repository, opts?: { detached?: boolean }): Promise<boolean> {
const createBranch = new CreateBranchItem();
const createBranchFrom = new CreateBranchFromItem();
const checkoutDetached = new CheckoutDetachedItem();
@ -1838,7 +1833,28 @@ export class CommandCenter {
} else if (choice === checkoutDetached) {
return this._checkout(repository, { detached: true });
} else {
await (choice as CheckoutItem).run(repository, opts);
const item = choice as CheckoutItem;
try {
await item.run(repository, opts);
} catch (err) {
if (err.gitErrorCode !== GitErrorCodes.DirtyWorkTree) {
throw err;
}
const force = localize('force', "Force Checkout");
const stash = localize('stashcheckout', "Stash & Checkout");
const choice = await window.showWarningMessage(localize('local changes', "Your local changes would be overwritten by checkout."), { modal: true }, force, stash);
if (choice === force) {
await this.cleanAll(repository);
await item.run(repository, opts);
} else if (choice === stash) {
await this.stash(repository);
await item.run(repository, opts);
await this.stashPopLatest(repository);
}
}
}
return true;
@ -2732,7 +2748,18 @@ export class CommandCenter {
if (!options.repository) {
result = Promise.resolve(method.apply(this, args));
} else {
const repositoryPromise = this.guessRepository(args[0]);
// try to guess the repository based on the first argument
const repository = this.model.getRepository(args[0]);
let repositoryPromise: Promise<Repository | undefined>;
if (repository) {
repositoryPromise = Promise.resolve(repository);
} else if (this.model.repositories.length === 1) {
repositoryPromise = Promise.resolve(this.model.repositories[0]);
} else {
repositoryPromise = this.model.pickRepository();
}
result = repositoryPromise.then(repository => {
if (!repository) {
return Promise.resolve();
@ -2759,8 +2786,6 @@ export class CommandCenter {
const choices = new Map<string, () => void>();
const openOutputChannelChoice = localize('open git log', "Open Git Log");
const forceCheckoutChoice = localize('force checkout', "Force Checkout");
const smartCheckoutChoice = localize('smart checkout', "Smart Checkout");
const outputChannel = this.outputChannel as OutputChannel;
choices.set(openOutputChannelChoice, () => outputChannel.show());
@ -2792,11 +2817,6 @@ export class CommandCenter {
switch (err.gitErrorCode) {
case GitErrorCodes.DirtyWorkTree:
message = localize('clean repo', "Please clean your repository working tree before checkout.");
if (err.gitTreeish) {
options.modal = true;
choices.set(forceCheckoutChoice, () => forceCheckout(err.gitTreeish, args));
choices.set(smartCheckoutChoice, () => smartCheckout(err.gitTreeish, args));
}
break;
case GitErrorCodes.PushRejected:
message = localize('cant push', "Can't push refs to remote. Try running 'Pull' first to integrate your changes.");
@ -2859,59 +2879,12 @@ export class CommandCenter {
});
};
const forceCheckout = async (treeish: string, args: any[]) => {
const repo = await this.guessRepository(args[0]);
if (!repo) {
return;
}
this.outputChannel.appendLine('force checkout: clean all');
await this.cleanAll(repo);
this.outputChannel.appendLine(`force checkout: checkout ${treeish}`);
await repo.checkout(treeish);
this.outputChannel.appendLine('force checkout: done');
};
const smartCheckout = async (treeish: string, args: any[]) => {
const repo = await this.guessRepository(args[0]);
if (!repo) {
return;
}
this.outputChannel.appendLine('smart checkout: stash');
await repo.createStash();
try {
this.outputChannel.appendLine(`smart checkout: checkout ${treeish}`);
await repo.checkout(treeish);
} finally {
this.outputChannel.appendLine('smart checkout pop stash');
await repo.popStash();
}
this.outputChannel.appendLine('smart checkout: done');
};
// patch this object, so people can call methods directly
(this as any)[key] = result;
return result;
}
/**
* try to guess the repository based on the first argument
* @param sourceControl
*/
private guessRepository(sourceControl: SourceControl) {
const repository = this.model.getRepository(sourceControl);
if (repository) {
return Promise.resolve(repository);
} else if (this.model.repositories.length === 1) {
return Promise.resolve(this.model.repositories[0]);
} else {
return this.model.pickRepository();
}
}
private getSCMResource(uri?: Uri): Resource | undefined {
uri = uri ? uri : (window.activeTextEditor && window.activeTextEditor.document.uri);