Add --command command line argument (#3690)

This commit is contained in:
David Shiflet 2019-01-09 17:36:01 -05:00 коммит произвёл GitHub
Родитель 589b913960
Коммит 3d3694bb8d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 210 добавлений и 47 удалений

24
.vscode/launch.json поставляемый
Просмотреть файл

@ -92,6 +92,30 @@
"webRoot": "${workspaceFolder}",
"timeout": 45000
},
{
"type": "chrome",
"request": "launch",
"name": "Launch azuredatastudio with new notebook command",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.bat"
},
"osx": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
},
"urlFilter": "*index.html*",
"runtimeArgs": [
"--inspect=5875",
"--command=notebook.command.new"
],
"skipFiles": [
"**/winjs*.js"
],
"webRoot": "${workspaceFolder}",
"timeout": 45000
},
{
"type": "node",
"request": "launch",

Просмотреть файл

@ -11,7 +11,7 @@ export interface ICommandLineProcessing {
* Interprets the various Azure Data Studio-specific command line switches and
* performs the requisite tasks such as connecting to a server
*/
processCommandLine() : void;
processCommandLine() : Promise<void>;
}
export const ICommandLineProcessing = createDecorator<ICommandLineProcessing>('commandLineService');

Просмотреть файл

@ -15,10 +15,13 @@ import { ConnectionProviderProperties, IConnectionProviderRegistry, Extensions a
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { warn } from 'sql/base/common/log';
export class CommandLineService implements ICommandLineProcessing {
private _connectionProfile: ConnectionProfile;
private _showConnectionDialog: boolean;
private _commandName:string;
constructor(
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@ -27,49 +30,96 @@ export class CommandLineService implements ICommandLineProcessing {
@IQueryEditorService private _queryEditorService: IQueryEditorService,
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
@IEditorService private _editorService: IEditorService,
@ICommandService private _commandService: ICommandService
) {
let profile = null;
if (this._environmentService && this._environmentService.args.server) {
profile = new ConnectionProfile(_capabilitiesService, null);
// We want connection store to use any matching password it finds
profile.savePassword = true;
profile.providerName = Constants.mssqlProviderName;
profile.serverName = _environmentService.args.server;
profile.databaseName = _environmentService.args.database ? _environmentService.args.database : '';
profile.userName = _environmentService.args.user ? _environmentService.args.user : '';
profile.authenticationType = _environmentService.args.integrated ? 'Integrated' : 'SqlLogin';
profile.connectionName = '';
profile.setOptionValue('applicationName', Constants.applicationName);
profile.setOptionValue('databaseDisplayName', profile.databaseName);
profile.setOptionValue('groupId', profile.groupId);
if (this._environmentService) {
if (this._commandService) {
this._commandName = this._environmentService.args.command;
}
if (this._environmentService.args.server) {
profile = new ConnectionProfile(_capabilitiesService, null);
// We want connection store to use any matching password it finds
profile.savePassword = true;
profile.providerName = Constants.mssqlProviderName;
profile.serverName = _environmentService.args.server;
profile.databaseName = _environmentService.args.database ? _environmentService.args.database : '';
profile.userName = _environmentService.args.user ? _environmentService.args.user : '';
profile.authenticationType = _environmentService.args.integrated ? 'Integrated' : 'SqlLogin';
profile.connectionName = '';
profile.setOptionValue('applicationName', Constants.applicationName);
profile.setOptionValue('databaseDisplayName', profile.databaseName);
profile.setOptionValue('groupId', profile.groupId);
}
}
this._connectionProfile = profile;
const registry = platform.Registry.as<IConnectionProviderRegistry>(ConnectionProviderExtensions.ConnectionProviderContributions);
let sqlProvider = registry.getProperties(Constants.mssqlProviderName);
// We can't connect to object explorer until the MSSQL connection provider is registered
if (sqlProvider) {
this.processCommandLine();
this.processCommandLine().catch(reason=>{warn('processCommandLine failed: ' + reason);});
} else {
registry.onNewProvider(e => {
if (e.id === Constants.mssqlProviderName) {
this.processCommandLine();
this.processCommandLine().catch(reason=>{warn('processCommandLine failed: ' + reason);});
}
});
}
}
public _serviceBrand: any;
public processCommandLine(): void {
if (!this._connectionProfile && !this._connectionManagementService.hasRegisteredServers()) {
// prompt the user for a new connection on startup if no profiles are registered
this._connectionManagementService.showConnectionDialog();
} else if (this._connectionProfile) {
this._connectionManagementService.connectIfNotConnected(this._connectionProfile, 'connection', true)
.then(result => TaskUtilities.newQuery(this._connectionProfile,
this._connectionManagementService,
this._queryEditorService,
this._objectExplorerService,
this._editorService))
.catch(() => { });
}
// We base our logic on the combination of (server, command) values.
// (serverName, commandName) => Connect object explorer and execute the command, passing the connection profile to the command. Do not load query editor.
// (null, commandName) => Launch the command with a null connection. If the command implementation needs a connection, it will need to create it.
// (serverName, null) => Connect object explorer and open a new query editor
// (null, null) => Prompt for a connection unless there are registered servers
public processCommandLine(): Promise<void> {
let self = this;
return new Promise<void>((resolve, reject) => {
if (!self._commandName && !self._connectionProfile && !self._connectionManagementService.hasRegisteredServers()) {
// prompt the user for a new connection on startup if no profiles are registered
self._connectionManagementService.showConnectionDialog()
.then(() => {
resolve();
},
error => {
reject(error);
});
} else if (self._connectionProfile) {
if (!self._commandName) {
self._connectionManagementService.connectIfNotConnected(self._connectionProfile, 'connection', true)
.then(() => {
TaskUtilities.newQuery(self._connectionProfile,
self._connectionManagementService,
self._queryEditorService,
self._objectExplorerService,
self._editorService)
.then( () => {
resolve();
}, error => {
// ignore query editor failing to open.
// the tests don't mock this out
warn('unable to open query editor ' + error);
resolve();
});
}, error => {
reject(error);
});
} else {
self._connectionManagementService.connectIfNotConnected(self._connectionProfile, 'connection', true)
.then(() => {
self._commandService.executeCommand(self._commandName, self._connectionProfile).then(() => resolve(), error => reject(error));
}, error => {
reject(error);
});
}
} else if (self._commandName) {
self._commandService.executeCommand(self._commandName).then(() => resolve(), error => reject(error));
}
else {
resolve();
}
});
}
}

Просмотреть файл

@ -30,7 +30,8 @@ import {
} from 'sql/parts/connection/common/connectionManagement';
import { ConnectionStore } from 'sql/parts/connection/common/connectionStore';
import { TestConnectionManagementService } from 'sqltest/stubs/connectionManagementService.test';
import { ICommandService, ICommandEvent, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices';
class TestParsedArgs implements ParsedArgs{
[arg: string]: any;
@ -38,6 +39,7 @@ class TestParsedArgs implements ParsedArgs{
aad?: boolean;
add?: boolean;
database?:string;
command?:string;
debugBrkPluginHost?: string;
debugBrkSearch?: string;
debugId?: string;
@ -111,7 +113,8 @@ suite('commandLineService tests', () => {
function getCommandLineService(connectionManagementService : IConnectionManagementService,
environmentService? : IEnvironmentService,
capabilitiesService? : ICapabilitiesService
capabilitiesService? : ICapabilitiesService,
commandService? : ICommandService
) : CommandLineService
{
let service= new CommandLineService(
@ -120,7 +123,8 @@ suite('commandLineService tests', () => {
environmentService,
undefined,
undefined,
undefined
undefined,
commandService
);
return service;
}
@ -129,14 +133,18 @@ suite('commandLineService tests', () => {
const connectionManagementService : TypeMoq.Mock<IConnectionManagementService>
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable();
connectionManagementService.setup((c) => c.showConnectionDialog())
.returns(() => new Promise<void>((resolve, reject) => { resolve();}))
.verifiable();
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => false);
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.verifiable(TypeMoq.Times.never());
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused');}))
.verifiable(TypeMoq.Times.never());
let service = getCommandLineService(connectionManagementService.object);
service.processCommandLine();
connectionManagementService.verifyAll();
done();
service.processCommandLine().then( () => {
connectionManagementService.verifyAll();
done();
}, error => {assert.fail(error, null, 'processCommandLine rejected ' + error); done(); });
});
test('processCommandLine does nothing if registered servers exist and no server name is provided', done => {
@ -146,11 +154,13 @@ suite('commandLineService tests', () => {
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true);
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.verifiable(TypeMoq.Times.never());
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused');}))
.verifiable(TypeMoq.Times.never());
let service = getCommandLineService(connectionManagementService.object);
service.processCommandLine();
connectionManagementService.verifyAll();
done();
service.processCommandLine().then( () => {
connectionManagementService.verifyAll();
done();
}, error => {assert.fail(error, null, 'processCommandLine rejected ' + error); done(); });
});
test('processCommandLine opens a new connection if a server name is passed', done => {
@ -165,12 +175,88 @@ suite('commandLineService tests', () => {
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true).verifiable(TypeMoq.Times.atMostOnce());
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), 'connection', true))
.returns(() => new Promise<string>((resolve, reject) => { reject('unused');}))
.verifiable(TypeMoq.Times.once());
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused');}))
.verifiable(TypeMoq.Times.once());
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService);
service.processCommandLine();
environmentService.verifyAll();
connectionManagementService.verifyAll();
done();
service.processCommandLine().then( () => {
environmentService.verifyAll();
connectionManagementService.verifyAll();
done();
}, error => {assert.fail(error, null, 'processCommandLine rejected ' + error); done(); });
});
test('processCommandLine invokes a command without a profile parameter when no server is passed', done => {
const connectionManagementService : TypeMoq.Mock<IConnectionManagementService>
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
const environmentService : TypeMoq.Mock<IEnvironmentService> = TypeMoq.Mock.ofType<IEnvironmentService>(EnvironmentService);
const commandService : TypeMoq.Mock<ICommandService> = TypeMoq.Mock.ofType<ICommandService>(TestCommandService);
const args : TestParsedArgs = new TestParsedArgs();
args.command = 'mycommand';
environmentService.setup(e => e.args).returns(() => args);
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true).verifiable(TypeMoq.Times.atMostOnce());
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.verifiable(TypeMoq.Times.never());
commandService.setup(c => c.executeCommand('mycommand'))
.returns(() => TPromise.wrap(1))
.verifiable(TypeMoq.Times.once());
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService, commandService.object);
service.processCommandLine().then( () => {
connectionManagementService.verifyAll();
commandService.verifyAll();
done();
}, error => {assert.fail(error, null, 'processCommandLine rejected ' + error); done(); });
});
test('processCommandLine invokes a command with a profile parameter when a server is passed', done => {
const connectionManagementService : TypeMoq.Mock<IConnectionManagementService>
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
const environmentService : TypeMoq.Mock<IEnvironmentService> = TypeMoq.Mock.ofType<IEnvironmentService>(EnvironmentService);
const commandService : TypeMoq.Mock<ICommandService> = TypeMoq.Mock.ofType<ICommandService>(TestCommandService);
const args : TestParsedArgs = new TestParsedArgs();
args.command = 'mycommand';
args.server = 'myserver';
environmentService.setup(e => e.args).returns(() => args);
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true).verifiable(TypeMoq.Times.atMostOnce());
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.is<ConnectionProfile>( p => p.serverName === 'myserver'), 'connection', true))
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused');}))
.verifiable(TypeMoq.Times.once());
commandService.setup(c => c.executeCommand('mycommand', TypeMoq.It.is<ConnectionProfile>( p => p.serverName === 'myserver')))
.returns(() => TPromise.wrap(1))
.verifiable(TypeMoq.Times.once());
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService, commandService.object);
service.processCommandLine().then( () => {
connectionManagementService.verifyAll();
commandService.verifyAll();
done();
}, error => {assert.fail(error, null, 'processCommandLine rejected ' + error); done(); });
});
test('processCommandLine rejects unknown commands', done => {
const connectionManagementService : TypeMoq.Mock<IConnectionManagementService>
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
const environmentService : TypeMoq.Mock<IEnvironmentService> = TypeMoq.Mock.ofType<IEnvironmentService>(EnvironmentService);
const commandService : TypeMoq.Mock<ICommandService> = TypeMoq.Mock.ofType<ICommandService>(TestCommandService);
const args : TestParsedArgs = new TestParsedArgs();
args.command = 'mycommand';
environmentService.setup(e => e.args).returns(() => args);
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true);
commandService.setup(c => c.executeCommand('mycommand'))
.returns(() => TPromise.wrapError(new Error('myerror')))
.verifiable(TypeMoq.Times.once());
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService, commandService.object);
service.processCommandLine().then( () => {
assert.fail(1,null, 'processCommandLine should reject when executeCommand errors out');
done();
}, error => {
assert.equal(error.message, 'myerror', 'unexpected error from processCommandLine ' + error);
done();
});
});
});

Просмотреть файл

@ -68,6 +68,7 @@ export interface ParsedArgs {
integrated?: boolean;
server?: string;
user?: string;
command?: string;
// {{SQL CARBON EDIT}}
}

Просмотреть файл

@ -38,6 +38,7 @@ const options: minimist.Opts = {
'database',
'server',
'user',
'command'
// {{SQL CARBON EDIT}}
],
boolean: [
@ -99,6 +100,7 @@ const options: minimist.Opts = {
integrated: 'E',
server: 'S',
user: 'U',
command : 'c',
// {{SQL CARBON EDIT}}
}
};