Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -10,9 +10,10 @@ import { Ref, RefType, Git, GitErrorCodes, Branch } from './git';
import { Repository, Resource, Status, CommitOptions, ResourceGroupType } from './repository';
import { Model } from './model';
import { toGitUri, fromGitUri } from './uri';
import { grep } from './util';
import { applyLineChanges, intersectDiffWithRange, toLineRanges, invertLineChange } from './staging';
import { grep, isDescendant } from './util';
import { applyLineChanges, intersectDiffWithRange, toLineRanges, invertLineChange, getModifiedRange } from './staging';
import * as path from 'path';
import { lstat, Stats } from 'fs';
import * as os from 'os';
import TelemetryReporter from 'vscode-extension-telemetry';
import * as nls from 'vscode-nls';
@@ -168,8 +169,28 @@ export class CommandCenter {
}
private async _openResource(resource: Resource, preview?: boolean, preserveFocus?: boolean, preserveSelection?: boolean): Promise<void> {
const left = await this.getLeftResource(resource);
const right = await this.getRightResource(resource);
let stat: Stats | undefined;
try {
stat = await new Promise<Stats>((c, e) => lstat(resource.resourceUri.fsPath, (err, stat) => err ? e(err) : c(stat)));
} catch (err) {
// noop
}
let left: Uri | undefined;
let right: Uri | undefined;
if (stat && stat.isDirectory()) {
const repository = this.model.getRepositoryForSubmodule(resource.resourceUri);
if (repository) {
right = toGitUri(resource.resourceUri, resource.resourceGroupType === ResourceGroupType.Index ? 'index' : 'wt', { submoduleOf: repository.root });
}
} else {
left = await this.getLeftResource(resource);
right = await this.getRightResource(resource);
}
const title = this.getTitle(resource);
if (!right) {
@@ -216,7 +237,7 @@ export class CommandCenter {
}
const { size, object } = await repository.lstree(gitRef, uri.fsPath);
const { mimetype, encoding } = await repository.detectObjectType(object);
const { mimetype } = await repository.detectObjectType(object);
if (mimetype === 'text/plain') {
return toGitUri(uri, ref);
@@ -330,7 +351,6 @@ export class CommandCenter {
const config = workspace.getConfiguration('git');
let value = config.get<string>('defaultCloneDirectory') || os.homedir();
value = value.replace(/^~/, os.homedir());
const parentPath = await window.showInputBox({
prompt: localize('parent', "Parent Directory"),
@@ -358,11 +378,10 @@ export class CommandCenter {
statusBarItem.command = cancelCommandId;
statusBarItem.show();
const clonePromise = this.git.clone(url, parentPath, tokenSource.token);
const clonePromise = this.git.clone(url, parentPath.replace(/^~/, os.homedir()), tokenSource.token);
try {
window.withProgress({ location: ProgressLocation.SourceControl, title: localize('cloning', "Cloning git repository...") }, () => clonePromise);
// window.withProgress({ location: ProgressLocation.Window, title: localize('cloning', "Cloning git repository...") }, () => clonePromise);
const repositoryPath = await clonePromise;
@@ -484,7 +503,10 @@ export class CommandCenter {
}
if (resource) {
uris = [...resourceStates.map(r => r.resourceUri), resource.resourceUri];
const resources = ([resource, ...resourceStates] as Resource[])
.filter(r => r.type !== Status.DELETED && r.type !== Status.INDEX_DELETED);
uris = resources.map(r => r.resourceUri);
}
}
@@ -511,6 +533,11 @@ export class CommandCenter {
}
}
@command('git.openFile2')
async openFile2(arg?: Resource | Uri, ...resourceStates: SourceControlResourceState[]): Promise<void> {
this.openFile(arg, ...resourceStates);
}
@command('git.openHEADFile')
async openHEADFile(arg?: Resource | Uri): Promise<void> {
let resource: Resource | undefined = undefined;
@@ -709,10 +736,7 @@ export class CommandCenter {
const modifiedDocument = textEditor.document;
const selections = textEditor.selections;
const selectedChanges = changes.filter(change => {
const modifiedRange = change.modifiedEndLineNumber === 0
? new Range(modifiedDocument.lineAt(change.modifiedStartLineNumber - 1).range.end, modifiedDocument.lineAt(change.modifiedStartLineNumber).range.start)
: new Range(modifiedDocument.lineAt(change.modifiedStartLineNumber - 1).range.start, modifiedDocument.lineAt(change.modifiedEndLineNumber - 1).range.end);
const modifiedRange = getModifiedRange(modifiedDocument, change);
return selections.every(selection => !selection.intersection(modifiedRange));
});
@@ -940,6 +964,29 @@ export class CommandCenter {
opts?: CommitOptions
): Promise<boolean> {
const config = workspace.getConfiguration('git');
const promptToSaveFilesBeforeCommit = config.get<boolean>('promptToSaveFilesBeforeCommit') === true;
if (promptToSaveFilesBeforeCommit) {
const unsavedTextDocuments = workspace.textDocuments
.filter(d => !d.isUntitled && d.isDirty && isDescendant(repository.root, d.uri.fsPath));
if (unsavedTextDocuments.length > 0) {
const message = unsavedTextDocuments.length === 1
? localize('unsaved files single', "The following file is unsaved: {0}.\n\nWould you like to save it before comitting?", path.basename(unsavedTextDocuments[0].uri.fsPath))
: localize('unsaved files', "There are {0} unsaved files.\n\nWould you like to save them before comitting?", unsavedTextDocuments.length);
const saveAndCommit = localize('save and commit', "Save All & Commit");
const commit = localize('commit', "Commit Anyway");
const pick = await window.showWarningMessage(message, { modal: true }, saveAndCommit, commit);
if (pick === saveAndCommit) {
await Promise.all(unsavedTextDocuments.map(d => d.save()));
await repository.status();
} else if (pick !== commit) {
return false; // do not commit on cancel
}
}
}
const enableSmartCommit = config.get<boolean>('enableSmartCommit') === true;
const enableCommitSigning = config.get<boolean>('enableCommitSigning') === true;
const noStagedChanges = repository.indexGroup.resourceStates.length === 0;
@@ -963,6 +1010,8 @@ export class CommandCenter {
if (!opts) {
opts = { all: noStagedChanges };
} else if (!opts.all && noStagedChanges) {
opts = { ...opts, all: true };
}
// enable signing of commits if configurated
@@ -996,8 +1045,14 @@ export class CommandCenter {
return message;
}
let value: string | undefined = undefined;
if (opts && opts.amend && repository.HEAD && repository.HEAD.commit) {
value = (await repository.getCommit(repository.HEAD.commit)).message;
}
return await window.showInputBox({
value: opts && opts.defaultMsg,
value,
placeHolder: localize('commit message', "Commit message"),
prompt: localize('provide commit message', "Please provide a commit message"),
ignoreFocusOut: true
@@ -1041,15 +1096,7 @@ export class CommandCenter {
@command('git.commitStagedAmend', { repository: true })
async commitStagedAmend(repository: Repository): Promise<void> {
let msg;
if (repository.HEAD) {
if (repository.HEAD.commit) {
let id = repository.HEAD.commit;
let commit = await repository.getCommit(id);
msg = commit.message;
}
}
await this.commitWithAnyInput(repository, { all: false, amend: true, defaultMsg: msg });
await this.commitWithAnyInput(repository, { all: false, amend: true });
}
@command('git.commitAll', { repository: true })
@@ -1267,25 +1314,26 @@ export class CommandCenter {
return;
}
const picks = remotes.map(r => ({ label: r.name, description: r.url }));
const remotePicks = remotes.map(r => ({ label: r.name, description: r.url }));
const placeHolder = localize('pick remote pull repo', "Pick a remote to pull the branch from");
const pick = await window.showQuickPick(picks, { placeHolder });
const remotePick = await window.showQuickPick(remotePicks, { placeHolder });
if (!pick) {
if (!remotePick) {
return;
}
const branchName = await window.showInputBox({
placeHolder: localize('branch name', "Branch name"),
prompt: localize('provide branch name', "Please provide a branch name"),
ignoreFocusOut: true
});
const remoteRefs = repository.refs;
const remoteRefsFiltered = remoteRefs.filter(r => (r.remote === remotePick.label));
const branchPicks = remoteRefsFiltered.map(r => ({ label: r.name })) as { label: string; description: string }[];
const branchPick = await window.showQuickPick(branchPicks, { placeHolder });
if (!branchName) {
if (!branchPick) {
return;
}
repository.pull(false, pick.label, branchName);
const remoteCharCnt = remotePick.label.length;
repository.pull(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1));
}
@command('git.pull', { repository: true })
@@ -1321,7 +1369,27 @@ export class CommandCenter {
return;
}
await repository.push();
if (!repository.HEAD || !repository.HEAD.name) {
window.showWarningMessage(localize('nobranch', "Please check out a branch to push to a remote."));
return;
}
try {
await repository.push();
} catch (err) {
if (err.gitErrorCode !== GitErrorCodes.NoUpstreamBranch) {
throw err;
}
const branchName = repository.HEAD.name;
const message = localize('confirm publish branch', "The branch '{0}' has no upstream branch. Would you like to publish this branch?", branchName);
const yes = localize('ok', "OK");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick === yes) {
await this.publish(repository);
}
}
}
@command('git.pushWithTags', { repository: true })
@@ -1377,7 +1445,7 @@ export class CommandCenter {
if (shouldPrompt) {
const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}'.", HEAD.upstream);
const yes = localize('ok', "OK");
const neverAgain = localize('never again', "OK, Never Show Again");
const neverAgain = localize('never again', "OK, Don't Show Again");
const pick = await window.showWarningMessage(message, { modal: true }, yes, neverAgain);
if (pick === neverAgain) {
@@ -1465,7 +1533,10 @@ export class CommandCenter {
}
private async _stash(repository: Repository, includeUntracked = false): Promise<void> {
if (repository.workingTreeGroup.resourceStates.length === 0) {
const noUnstagedChanges = repository.workingTreeGroup.resourceStates.length === 0;
const noStagedChanges = repository.indexGroup.resourceStates.length === 0;
if (noUnstagedChanges && noStagedChanges) {
window.showInformationMessage(localize('no changes stash', "There are no changes to stash."));
return;
}
@@ -1641,13 +1712,18 @@ export class CommandCenter {
const isSingleResource = arg instanceof Uri;
const groups = resources.reduce((result, resource) => {
const repository = this.model.getRepository(resource);
let repository = this.model.getRepository(resource);
if (!repository) {
console.warn('Could not find git repository for ', resource);
return result;
}
// Could it be a submodule?
if (resource.fsPath === repository.root) {
repository = this.model.getRepositoryForSubmodule(resource) || repository;
}
const tuple = result.filter(p => p.repository === repository)[0];
if (tuple) {