mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3 (#6516)
* Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3 * fix tests
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Model } from '../model';
|
||||
import { Repository as BaseRepository, Resource } from '../repository';
|
||||
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions } from './git';
|
||||
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState } from './git';
|
||||
import { Event, SourceControlInputBox, Uri, SourceControl } from 'vscode';
|
||||
import { mapEvent } from '../util';
|
||||
|
||||
@@ -214,6 +214,14 @@ export class ApiImpl implements API {
|
||||
|
||||
readonly git = new ApiGit(this._model);
|
||||
|
||||
get state(): APIState {
|
||||
return this._model.state;
|
||||
}
|
||||
|
||||
get onDidChangeState(): Event<APIState> {
|
||||
return this._model.onDidChangeState;
|
||||
}
|
||||
|
||||
get onDidOpenRepository(): Event<Repository> {
|
||||
return mapEvent(this._model.onDidOpenRepository, r => new ApiRepository(r));
|
||||
}
|
||||
|
||||
4
extensions/git/src/api/git.d.ts
vendored
4
extensions/git/src/api/git.d.ts
vendored
@@ -176,7 +176,11 @@ export interface Repository {
|
||||
log(options?: LogOptions): Promise<Commit[]>;
|
||||
}
|
||||
|
||||
export type APIState = 'uninitialized' | 'initialized';
|
||||
|
||||
export interface API {
|
||||
readonly state: APIState;
|
||||
readonly onDidChangeState: Event<APIState>;
|
||||
readonly git: Git;
|
||||
readonly repositories: Repository[];
|
||||
readonly onDidOpenRepository: Event<Repository>;
|
||||
|
||||
@@ -1115,7 +1115,7 @@ export class CommandCenter {
|
||||
|
||||
if (scmResources.length === 1) {
|
||||
if (untrackedCount > 0) {
|
||||
message = localize('confirm delete', "Are you sure you want to DELETE {0}?", path.basename(scmResources[0].resourceUri.fsPath));
|
||||
message = localize('confirm delete', "Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST.", path.basename(scmResources[0].resourceUri.fsPath));
|
||||
yes = localize('delete file', "Delete file");
|
||||
} else {
|
||||
if (scmResources[0].type === Status.DELETED) {
|
||||
@@ -1134,7 +1134,7 @@ export class CommandCenter {
|
||||
}
|
||||
|
||||
if (untrackedCount > 0) {
|
||||
message = `${message}\n\n${localize('warn untracked', "This will DELETE {0} untracked files!", untrackedCount)}`;
|
||||
message = `${message}\n\n${localize('warn untracked', "This will DELETE {0} untracked files!\nThis is IRREVERSIBLE!\nThese files will be FOREVER LOST.", untrackedCount)}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1175,7 +1175,7 @@ export class CommandCenter {
|
||||
await repository.clean(resources.map(r => r.resourceUri));
|
||||
return;
|
||||
} else if (resources.length === 1) {
|
||||
const message = localize('confirm delete', "Are you sure you want to DELETE {0}?", path.basename(resources[0].resourceUri.fsPath));
|
||||
const message = localize('confirm delete', "Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST.", path.basename(resources[0].resourceUri.fsPath));
|
||||
const yes = localize('delete file', "Delete file");
|
||||
const pick = await window.showWarningMessage(message, { modal: true }, yes);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { fromGitUri } from './uri';
|
||||
import { GitErrorCodes } from './api/git';
|
||||
import { GitErrorCodes, APIState as State } from './api/git';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -63,15 +63,22 @@ export class Model {
|
||||
|
||||
private possibleGitRepositoryPaths = new Set<string>();
|
||||
|
||||
private _onDidChangeState = new EventEmitter<State>();
|
||||
readonly onDidChangeState = this._onDidChangeState.event;
|
||||
|
||||
private _state: State = 'uninitialized';
|
||||
get state(): State { return this._state; }
|
||||
|
||||
setState(state: State): void {
|
||||
this._state = state;
|
||||
this._onDidChangeState.fire(state);
|
||||
}
|
||||
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
|
||||
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
|
||||
this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] });
|
||||
|
||||
window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables);
|
||||
this.onDidChangeVisibleTextEditors(window.visibleTextEditors);
|
||||
|
||||
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables);
|
||||
|
||||
const fsWatcher = workspace.createFileSystemWatcher('**');
|
||||
@@ -82,7 +89,15 @@ export class Model {
|
||||
const onPossibleGitRepositoryChange = filterEvent(onGitRepositoryChange, uri => !this.getRepository(uri));
|
||||
onPossibleGitRepositoryChange(this.onPossibleGitRepositoryChange, this, this.disposables);
|
||||
|
||||
this.scanWorkspaceFolders();
|
||||
this.doInitialScan().finally(() => this.setState('initialized'));
|
||||
}
|
||||
|
||||
private async doInitialScan(): Promise<void> {
|
||||
await Promise.all([
|
||||
this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] }),
|
||||
this.onDidChangeVisibleTextEditors(window.visibleTextEditors),
|
||||
this.scanWorkspaceFolders()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,8 +172,8 @@ export class Model {
|
||||
.filter(r => !activeRepositories.has(r!.repository))
|
||||
.filter(r => !(workspace.workspaceFolders || []).some(f => isDescendant(f.uri.fsPath, r!.repository.root))) as OpenRepository[];
|
||||
|
||||
possibleRepositoryFolders.forEach(p => this.openRepository(p.uri.fsPath));
|
||||
openRepositoriesToDispose.forEach(r => r.dispose());
|
||||
await Promise.all(possibleRepositoryFolders.map(p => this.openRepository(p.uri.fsPath)));
|
||||
}
|
||||
|
||||
private onDidChangeConfiguration(): void {
|
||||
@@ -175,7 +190,7 @@ export class Model {
|
||||
openRepositoriesToDispose.forEach(r => r.dispose());
|
||||
}
|
||||
|
||||
private onDidChangeVisibleTextEditors(editors: TextEditor[]): void {
|
||||
private async onDidChangeVisibleTextEditors(editors: TextEditor[]): Promise<void> {
|
||||
const config = workspace.getConfiguration('git');
|
||||
const autoRepositoryDetection = config.get<boolean | 'subFolders' | 'openEditors'>('autoRepositoryDetection');
|
||||
|
||||
@@ -183,7 +198,7 @@ export class Model {
|
||||
return;
|
||||
}
|
||||
|
||||
editors.forEach(editor => {
|
||||
await Promise.all(editors.map(async editor => {
|
||||
const uri = editor.document.uri;
|
||||
|
||||
if (uri.scheme !== 'file') {
|
||||
@@ -196,8 +211,8 @@ export class Model {
|
||||
return;
|
||||
}
|
||||
|
||||
this.openRepository(path.dirname(uri.fsPath));
|
||||
});
|
||||
await this.openRepository(path.dirname(uri.fsPath));
|
||||
}));
|
||||
}
|
||||
|
||||
@sequentialize
|
||||
@@ -236,6 +251,7 @@ export class Model {
|
||||
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this.globalState, this.outputChannel);
|
||||
|
||||
this.open(repository);
|
||||
await repository.status();
|
||||
} catch (err) {
|
||||
if (err.gitErrorCode === GitErrorCodes.NotAGitRepository) {
|
||||
return;
|
||||
@@ -421,4 +437,4 @@ export class Model {
|
||||
this.possibleGitRepositoryPaths.clear();
|
||||
this.disposables = dispose(this.disposables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,8 +519,8 @@ class DotGitWatcher implements IFileWatcher {
|
||||
this.transientDisposables.push(upstreamWatcher);
|
||||
upstreamWatcher.event(this.emitter.fire, this.emitter, this.transientDisposables);
|
||||
} catch (err) {
|
||||
if (env.logLevel <= LogLevel.Info) {
|
||||
this.outputChannel.appendLine(`Failed to watch ref '${upstreamPath}'. Ref is most likely packed.`);
|
||||
if (env.logLevel <= LogLevel.Error) {
|
||||
this.outputChannel.appendLine(`Failed to watch ref '${upstreamPath}', is most likely packed.\n${err.stack || err}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -651,19 +651,30 @@ export class Repository implements Disposable {
|
||||
const onWorkspaceRepositoryFileChange = filterEvent(onWorkspaceFileChange, uri => isDescendant(repository.root, uri.fsPath));
|
||||
const onWorkspaceWorkingTreeFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => !/\/\.git($|\/)/.test(uri.path));
|
||||
|
||||
const dotGitFileWatcher = new DotGitWatcher(this, outputChannel);
|
||||
this.disposables.push(dotGitFileWatcher);
|
||||
let onDotGitFileChange: Event<Uri>;
|
||||
|
||||
try {
|
||||
const dotGitFileWatcher = new DotGitWatcher(this, outputChannel);
|
||||
onDotGitFileChange = dotGitFileWatcher.event;
|
||||
this.disposables.push(dotGitFileWatcher);
|
||||
} catch (err) {
|
||||
if (env.logLevel <= LogLevel.Error) {
|
||||
outputChannel.appendLine(`Failed to watch '${this.dotGit}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
|
||||
}
|
||||
|
||||
onDotGitFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => /\/\.git($|\/)/.test(uri.path));
|
||||
}
|
||||
|
||||
// FS changes should trigger `git status`:
|
||||
// - any change inside the repository working tree
|
||||
// - any change whithin the first level of the `.git` folder, except the folder itself and `index.lock`
|
||||
const onFileChange = anyEvent(onWorkspaceWorkingTreeFileChange, dotGitFileWatcher.event);
|
||||
const onFileChange = anyEvent(onWorkspaceWorkingTreeFileChange, onDotGitFileChange);
|
||||
onFileChange(this.onFileChange, this, this.disposables);
|
||||
|
||||
// Relevate repository changes should trigger virtual document change events
|
||||
dotGitFileWatcher.event(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
|
||||
onDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
|
||||
|
||||
this.disposables.push(new FileEventLogger(onWorkspaceWorkingTreeFileChange, dotGitFileWatcher.event, outputChannel));
|
||||
this.disposables.push(new FileEventLogger(onWorkspaceWorkingTreeFileChange, onDotGitFileChange, outputChannel));
|
||||
|
||||
const root = Uri.file(repository.root);
|
||||
this._sourceControl = scm.createSourceControl('git', 'Git', root);
|
||||
@@ -713,7 +724,6 @@ export class Repository implements Disposable {
|
||||
this.disposables.push(progressManager);
|
||||
|
||||
this.updateCommitTemplate();
|
||||
this.status();
|
||||
}
|
||||
|
||||
validateInput(text: string, position: number): SourceControlInputBoxValidation | undefined {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"vscode-json-languageservice": "^3.3.0",
|
||||
"vscode-languageserver": "^5.3.0-next.8",
|
||||
"vscode-nls": "^4.1.1",
|
||||
"vscode-uri": "^2.0.1"
|
||||
"vscode-uri": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "2.2.33",
|
||||
|
||||
@@ -154,7 +154,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
|
||||
documentSymbolProvider: true,
|
||||
documentRangeFormattingProvider: false,
|
||||
colorProvider: {},
|
||||
foldingRangeProvider: true
|
||||
foldingRangeProvider: true,
|
||||
selectionRangeProvider: true
|
||||
};
|
||||
|
||||
return { capabilities };
|
||||
|
||||
@@ -134,3 +134,8 @@ vscode-uri@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.1.tgz#5448e4f77d21d93ffa34b96f84c6c5e09e3f5a9b"
|
||||
integrity sha512-s/k0zsYr6y+tsocFyxT/+G5aq8mEdpDZuph3LZ+UmCs7LNhx/xomiCy5kyP+jOAKC7RMCUvb6JbPD1/TgAvq0g==
|
||||
|
||||
vscode-uri@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543"
|
||||
integrity sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw==
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
suite('workspace-namespace', () => {
|
||||
|
||||
suite('Tasks', () => {
|
||||
|
||||
test('CustomExecution2 task should start and shutdown successfully', (done) => {
|
||||
interface CustomTestingTaskDefinition extends vscode.TaskDefinition {
|
||||
/**
|
||||
* One of the task properties. This can be used to customize the task in the tasks.json
|
||||
*/
|
||||
customProp1: string;
|
||||
}
|
||||
const taskType: string = 'customTesting';
|
||||
const taskName = 'First custom task';
|
||||
const reg1 = vscode.window.onDidOpenTerminal(term => {
|
||||
reg1.dispose();
|
||||
const reg2 = term.onDidWriteData(e => {
|
||||
reg2.dispose();
|
||||
assert.equal(e, 'testing\r\n');
|
||||
term.dispose();
|
||||
});
|
||||
});
|
||||
const taskProvider = vscode.tasks.registerTaskProvider(taskType, {
|
||||
provideTasks: () => {
|
||||
const result: vscode.Task[] = [];
|
||||
const kind: CustomTestingTaskDefinition = {
|
||||
type: taskType,
|
||||
customProp1: 'testing task one'
|
||||
};
|
||||
const writeEmitter = new vscode.EventEmitter<string>();
|
||||
const execution = new vscode.CustomExecution2((): Thenable<vscode.Pseudoterminal> => {
|
||||
const pty: vscode.Pseudoterminal = {
|
||||
onDidWrite: writeEmitter.event,
|
||||
open: () => {
|
||||
writeEmitter.fire('testing\r\n');
|
||||
},
|
||||
close: () => {
|
||||
taskProvider.dispose();
|
||||
done();
|
||||
}
|
||||
};
|
||||
return Promise.resolve(pty);
|
||||
});
|
||||
const task = new vscode.Task2(kind, vscode.TaskScope.Workspace, taskName, taskType, execution);
|
||||
result.push(task);
|
||||
return result;
|
||||
},
|
||||
resolveTask(_task: vscode.Task): vscode.Task | undefined {
|
||||
assert.fail('resolveTask should not trigger during the test');
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
vscode.commands.executeCommand('workbench.action.tasks.runTask', `${taskType}: ${taskName}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
8
extensions/vscode-api-tests/testWorkspace/.vscode/settings.json
vendored
Normal file
8
extensions/vscode-api-tests/testWorkspace/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"search.exclude": {
|
||||
"**/search-exclude/**": true
|
||||
},
|
||||
"files.exclude": {
|
||||
"**/files-exclude/**": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
file
|
||||
@@ -0,0 +1 @@
|
||||
file
|
||||
@@ -53,17 +53,17 @@
|
||||
"statusBar/windowIndicator": [
|
||||
{
|
||||
"command": "vscode-testresolver.newWindow",
|
||||
"when": "!remoteAuthority",
|
||||
"when": "!remoteName",
|
||||
"group": "9_local_testresolver@2"
|
||||
},
|
||||
{
|
||||
"command": "vscode-testresolver.showLog",
|
||||
"when": "remoteAuthority =~ /^test\\+.*$/",
|
||||
"when": "remoteName == test",
|
||||
"group": "1_remote_testresolver_open@3"
|
||||
},
|
||||
{
|
||||
"command": "vscode-testresolver.newWindow",
|
||||
"when": "remoteAuthority =~ /^test\\+.*$/",
|
||||
"when": "remoteName == test",
|
||||
"group": "1_remote_testresolver_open@1"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,31 +1,34 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": "",
|
||||
"blockComment": ["<!--", "-->"]
|
||||
"blockComment": [ "<!--", "-->" ]
|
||||
},
|
||||
"brackets": [
|
||||
["<", ">"]
|
||||
["<!--", "-->"],
|
||||
["<", ">"],
|
||||
["{", "}"],
|
||||
["(", ")"]
|
||||
],
|
||||
"autoClosingPairs": [
|
||||
["<", ">"],
|
||||
["'", "'"],
|
||||
["\"", "\""]
|
||||
{ "open": "{", "close": "}"},
|
||||
{ "open": "[", "close": "]"},
|
||||
{ "open": "(", "close": ")" },
|
||||
{ "open": "'", "close": "'" },
|
||||
{ "open": "\"", "close": "\"" },
|
||||
{ "open": "<!--", "close": "-->", "notIn": [ "comment", "string" ]},
|
||||
{ "open": "<![CDATA[", "close": "]]>", "notIn": [ "comment", "string" ]}
|
||||
],
|
||||
"surroundingPairs": [
|
||||
["<", ">"],
|
||||
["'", "'"],
|
||||
["\"", "\""]
|
||||
]
|
||||
|
||||
// enhancedBrackets: [{
|
||||
// tokenType: 'tag.tag-$1.xml',
|
||||
// openTrigger: '>',
|
||||
// open: /<(\w[\w\d]*)([^\/>]*(?!\/)>)[^<>]*$/i,
|
||||
// closeComplete: '</$1>',
|
||||
// closeTrigger: '>',
|
||||
// close: /<\/(\w[\w\d]*)\s*>$/i
|
||||
// }],
|
||||
|
||||
// autoClosingPairs: [['\'', '\''], ['"', '"'] ]
|
||||
|
||||
{ "open": "'", "close": "'" },
|
||||
{ "open": "\"", "close": "\"" },
|
||||
{ "open": "{", "close": "}"},
|
||||
{ "open": "[", "close": "]"},
|
||||
{ "open": "(", "close": ")" },
|
||||
{ "open": "<", "close": ">" }
|
||||
],
|
||||
"folding": {
|
||||
"markers": {
|
||||
"start": "^\\s*<!--\\s*#region\\b.*-->",
|
||||
"end": "^\\s*<!--\\s*#endregion\\b.*-->"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user