Refresh master with initial release/0.24 snapshot (#332)

* Initial port of release/0.24 source code

* Fix additional headers

* Fix a typo in launch.json
This commit is contained in:
Karl Burtram
2017-12-15 15:38:57 -08:00
committed by GitHub
parent 271b3a0b82
commit 6ad0df0e3e
7118 changed files with 107999 additions and 56466 deletions

View File

@@ -11,6 +11,6 @@ trim_trailing_whitespace = true
# The indent size used in the `package.json` file cannot be changed
# https://github.com/npm/npm/pull/3180#issuecomment-16336516
[{.travis.yml,npm-shrinkwrap.json,package.json}]
[{*.yml,*.yaml,npm-shrinkwrap.json,package.json}]
indent_style = space
indent_size = 2

View File

@@ -5,6 +5,10 @@ os:
- linux
- osx
cache:
directories:
- $HOME/.npm
notifications:
email: false
@@ -27,8 +31,8 @@ before_install:
- git submodule update --init --recursive
- git clone --depth 1 https://github.com/creationix/nvm.git ./.nvm
- source ./.nvm/nvm.sh
- nvm install 7.4.0
- nvm use 7.4.0
- nvm install 7.9.0
- nvm use 7.9.0
- npm config set python `which python`
- npm install -g gulp
- if [ $TRAVIS_OS_NAME == "linux" ]; then

47
.vscode/launch.json vendored
View File

@@ -6,12 +6,12 @@
"type": "node",
"request": "launch",
"name": "Gulp Build",
"program": "${workspaceRoot}/node_modules/gulp/bin/gulp.js",
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
"stopOnEntry": true,
"args": [
"watch-extension:json-client"
],
"cwd": "${workspaceRoot}"
"cwd": "${workspaceFolder}"
},
{
"type": "node",
@@ -21,7 +21,7 @@
"port": 5870,
"restart": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -31,17 +31,17 @@
"protocol": "inspector",
"port": 5871,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
"type": "node",
"request": "attach",
"protocol": "inspector",
"name": "Attach to Search process",
"port": 7890,
"name": "Attach to Search Process",
"port": 5876,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -51,7 +51,7 @@
"protocol": "inspector",
"port": 5874,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -61,9 +61,9 @@
"protocol": "inspector",
"port": 5875,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
},
{
"type": "chrome",
"request": "attach",
@@ -75,44 +75,44 @@
"request": "launch",
"name": "Launch sqlops",
"windows": {
"runtimeExecutable": "${workspaceRoot}/scripts/sql.bat"
"runtimeExecutable": "${workspaceFolder}/scripts/sql.bat"
},
"osx": {
"runtimeExecutable": "${workspaceRoot}/scripts/sql.sh"
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
},
"linux": {
"runtimeExecutable": "${workspaceRoot}/scripts/sql.sh"
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
},
"urlFilter": "*index.html*",
"runtimeArgs": [
"--inspect=5875"
],
"webRoot": "${workspaceRoot}"
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "Unit Tests",
"protocol": "inspector",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"runtimeExecutable": "${workspaceRoot}/.build/electron/sqlops.app/Contents/MacOS/Electron",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"runtimeExecutable": "${workspaceFolder}/.build/electron/sqlops.app/Contents/MacOS/Electron",
"windows": {
"runtimeExecutable": "${workspaceRoot}/.build/electron/sqlops.exe"
"runtimeExecutable": "${workspaceFolder}/.build/electron/sqlops.exe"
},
"linux": {
"runtimeExecutable": "${workspaceRoot}/.build/electron/sqlops"
"runtimeExecutable": "${workspaceFolder}/.build/electron/sqlops"
},
"stopOnEntry": false,
"args": [
"--timeout",
"2000"
],
"cwd": "${workspaceRoot}",
"cwd": "${workspaceFolder}",
"env": {
"ELECTRON_RUN_AS_NODE": "true"
},
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
}
],
@@ -123,6 +123,13 @@
"Launch sqlops",
"Attach to Main Process"
]
},
{
"name": "Search and Renderer processes",
"configurations": [
"Launch sqlops",
"Attach to Search Process"
]
}
]
}

11
.vscode/settings.json vendored
View File

@@ -14,9 +14,12 @@
"**/node_modules": true,
"**/bower_components": true,
".build/**": true,
"out*/**": true,
"out/**": true,
"out-build/**": true,
"out-vscode/**": true,
"i18n/**": true,
"extensions/**/out/**": true
"extensions/**/out/**": true,
"test/smoke/out/**": true
},
"tslint.enable": true,
"lcov.path": [
@@ -26,9 +29,9 @@
"lcov.watch": [
{
"pattern": "**/*.test.js",
"command": "${workspaceRoot}/scripts/test.sh --coverage --run ${file}",
"command": "${workspaceFolder}/scripts/test.sh --coverage --run ${file}",
"windows": {
"command": "${workspaceRoot}\\scripts\\test.bat --coverage --run ${file}"
"command": "${workspaceFolder}\\scripts\\test.bat --coverage --run ${file}"
}
}
]

2
.vscode/tasks.json vendored
View File

@@ -69,4 +69,4 @@
"problemMatcher": []
}
]
}
}

View File

@@ -2,16 +2,16 @@ MICROSOFT SOFTWARE LICENSE TERMS
MICROSOFT SQL OPERATIONS STUDIO
Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
royalty-free right to use, copy, and modify the software code provided by us
Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
royalty-free right to use, copy, and modify the software code provided by us
("Software Code"). You may not sublicense the Software Code or any use of it
(except to your affiliates and to vendors to perform work on your behalf)
through distribution, network access, service agreement, lease, rental, or
otherwise. Unless applicable law gives you more rights, Microsoft reserves all
other rights not expressly granted herein, whether by implication, estoppel or
otherwise. 
 
THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
otherwise. 
 
THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL MICROSOFT OR ITS
LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

View File

@@ -44,7 +44,6 @@ expressly granted herein, whether by implication, estoppel or otherwise.
pretty-data: https://github.com/vkiryukhin/pretty-data
primeng: https://github.com/primefaces/primeng
pty.js: https://github.com/chjj/pty.js
rangy: https://github.com/timdown/rangy
reflect-metadata: https://github.com/rbuckton/reflect-metadata
rxjs: https://github.com/ReactiveX/RxJS
semver: https://github.com/npm/node-semver
@@ -1395,32 +1394,6 @@ THE SOFTWARE.
=========================================
END OF pty.js NOTICES AND INFORMATION
%% rangy NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License (MIT)
Copyright (c) 2014 Tim Down
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=========================================
END OF rangy NOTICES AND INFORMATION
%% reflect-metadata NOTICES AND INFORMATION BEGIN HERE
=========================================
Apache License

View File

@@ -2,14 +2,16 @@ environment:
ELECTRON_RUN_AS_NODE: 1
VSCODE_BUILD_VERBOSE: true
cache:
- '%APPDATA%\npm-cache'
install:
- ps: Install-Product node 7.4.0 x64
- ps: Install-Product node 7.9.0 x64
- npm install -g npm@4 --silent
- npm install -g gulp mocha --silent
build_script:
- .\scripts\npm.bat install
- gulp electron
- .\node_modules\.bin\gulp electron
- npm run compile
test_script:

View File

@@ -12,6 +12,7 @@ const gulptslint = require('gulp-tslint');
const gulpeslint = require('gulp-eslint');
const tsfmt = require('typescript-formatter');
const tslint = require('tslint');
const vfs = require('vinyl-fs');
/**
* Hygiene works by creating cascading subsets of all our files and
@@ -53,6 +54,7 @@ const indentationFilter = [
'!**/*.md',
'!**/*.ps1',
'!**/*.template',
'!**/*.yaml',
'!**/*.yml',
'!**/lib/**',
'!extensions/**/*.d.ts',
@@ -92,6 +94,7 @@ const copyrightFilter = [
'!**/*.opts',
'!**/*.disabled',
'!build/**/*.init',
'!resources/linux/snap/snapcraft.yaml',
'!resources/win32/bin/code.js',
'!extensions/markdown/media/tomorrow.css',
'!extensions/html/server/src/modes/typescript/*'
@@ -141,7 +144,7 @@ function reportFailures(failures) {
}
gulp.task('eslint', () => {
return gulp.src(all, { base: '.' })
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(eslintFilter))
.pipe(gulpeslint('src/.eslintrc'))
.pipe(gulpeslint.formatEach('compact'))
@@ -151,7 +154,7 @@ gulp.task('eslint', () => {
gulp.task('tslint', () => {
const options = { summarizeFailureOutput: true };
return gulp.src(all, { base: '.' })
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(tslintFilter))
.pipe(gulptslint({ rulesDirectory: 'build/lib/tslint' }))
.pipe(gulptslint.report(reportFailures, options));
@@ -232,7 +235,7 @@ const hygiene = exports.hygiene = (some, options) => {
this.emit('data', file);
});
const result = gulp.src(some || all, { base: '.' })
const result = vfs.src(some || all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(f => !f.stat.isDirectory()))
.pipe(filter(eolFilter))
// {{SQL CARBON EDIT}}
@@ -267,7 +270,7 @@ const hygiene = exports.hygiene = (some, options) => {
}));
};
gulp.task('hygiene', () => hygiene());
gulp.task('hygiene', () => hygiene(''));
// this allows us to run hygiene as a git pre-commit hook
if (require.main === module) {

View File

@@ -17,7 +17,6 @@ gulp.task('clean-client', util.rimraf('dataprotocol-node/client/node_modules'));
gulp.task('clean-jsonrpc', util.rimraf('dataprotocol-node/jsonrpc/node_modules'));
gulp.task('clean-server', util.rimraf('dataprotocol-node/server/node_modules'));
gulp.task('clean-types', util.rimraf('dataprotocol-node/types/node_modules'));
// {{SQL CARBON EDIT}}
gulp.task('clean-extensions-modules', util.rimraf('extensions-modules/node_modules'));
gulp.task('clean-protocol', ['clean-extensions-modules', 'clean-mssql-extension', 'clean-credentials-extension', 'clean-client', 'clean-jsonrpc', 'clean-server', 'clean-types']);

View File

@@ -7,6 +7,8 @@
const gulp = require('gulp');
const fs = require('fs');
const os = require('os');
const cp = require('child_process');
const path = require('path');
const es = require('event-stream');
const azure = require('gulp-azure-storage');
@@ -47,17 +49,15 @@ const nodeModules = [
'rxjs/Observable',
'rxjs/Subject',
'rxjs/Observer',
'ng2-charts/ng2-charts',
'rangy/lib/rangy-textrange']
'ng2-charts/ng2-charts']
.concat(dependencies)
.concat(baseModules);
// Build
const builtInExtensions = [
{ name: 'ms-vscode.node-debug', version: '1.16.10' },
{ name: 'ms-vscode.node-debug2', version: '1.16.9' }
{ name: 'ms-vscode.node-debug', version: '1.18.3' },
{ name: 'ms-vscode.node-debug2', version: '1.18.5' }
];
const excludedExtensions = [
@@ -168,7 +168,7 @@ const config = {
role: 'Editor',
ostypes: ["TEXT", "utxt", "TUTX", "****"],
// {{SQL CARBON EDIT}}
extensions: ["csv", "json", "showplan", "sql", "xml"],
extensions: ["csv", "json", "sqlplan", "sql", "xml"],
iconFile: 'resources/darwin/code_file.icns'
}],
darwinBundleURLTypes: [{
@@ -304,9 +304,10 @@ function packageTask(platform, arch, opts) {
const packageJsonStream = gulp.src(['package.json'], { base: '.' })
.pipe(json({ name, version }));
const settingsSearchBuildId = getBuildNumber();
const date = new Date().toISOString();
const productJsonStream = gulp.src(['product.json'], { base: '.' })
.pipe(json({ commit, date, checksums }));
.pipe(json({ commit, date, checksums, settingsSearchBuildId }));
const license = gulp.src(['LICENSES.chromium.html', 'LICENSE.txt', 'ThirdPartyNotices.txt', 'licenses/**'], { base: '.' });
@@ -315,13 +316,10 @@ function packageTask(platform, arch, opts) {
// TODO the API should be copied to `out` during compile, not here
const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts'));
// {{SQL CARBON EDIT}}
const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts'));
const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts'));
const depsSrc = _.flatten(dependencies
.map(function (d) { return ['node_modules/' + d + '/**',
'!node_modules/' + d + '/**/{test,tests}/**',
'!node_modules/' + d + '/**/test.*',
'!node_modules/' + d + '/**/*.test.*']; }));
.map(function (d) { return ['node_modules/' + d + '/**', '!node_modules/' + d + '/**/{test,tests}/**']; }));
const deps = gulp.src(depsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json']))
@@ -335,6 +333,7 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js']))
.pipe(util.cleanNodeModule('v8-profiler', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js']))
.pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/**']))
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']));
@@ -352,7 +351,7 @@ function packageTask(platform, arch, opts) {
);
if (platform === 'win32') {
all = es.merge(all, gulp.src('resources/win32/code_file.ico', { base: '.' }));
all = es.merge(all, gulp.src(['resources/win32/code_file.ico', 'resources/win32/code_70x70.png', 'resources/win32/code_150x150.png'], { base: '.' }));
} else if (platform === 'linux') {
all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' }));
} else if (platform === 'darwin') {
@@ -378,6 +377,9 @@ function packageTask(platform, arch, opts) {
result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' })
.pipe(replace('@@NAME@@', product.nameShort))
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
.pipe(rename(product.nameShort + '.VisualElementsManifest.xml')));
} else if (platform === 'linux') {
result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
@@ -482,6 +484,139 @@ gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], () => {
}));
});
const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json');
gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () => {
const branch = process.env.BUILD_SOURCEBRANCH;
if (!branch.endsWith('/master') && !branch.indexOf('/release/') >= 0) {
console.log(`Only runs on master and release branches, not ${branch}`);
return;
}
if (!fs.existsSync(allConfigDetailsPath)) {
console.error(`configuration file at ${allConfigDetailsPath} does not exist`);
return;
}
const settingsSearchBuildId = getBuildNumber();
if (!settingsSearchBuildId) {
console.error('Failed to compute build number');
return;
}
return gulp.src(allConfigDetailsPath)
.pipe(azure.upload({
account: process.env.AZURE_STORAGE_ACCOUNT,
key: process.env.AZURE_STORAGE_ACCESS_KEY,
container: 'configuration',
prefix: `${settingsSearchBuildId}/${commit}/`
}));
});
function getBuildNumber() {
const previous = getPreviousVersion(packageJson.version);
if (!previous) {
return 0;
}
try {
const out = cp.execSync(`git rev-list ${previous}..HEAD --count`);
const count = parseInt(out.toString());
return versionStringToNumber(packageJson.version) * 1e4 + count;
} catch (e) {
console.error('Could not determine build number: ' + e.toString());
return 0;
}
}
/**
* Given 1.17.2, return 1.17.1
* 1.18.0 => 1.17.2.
* 2.0.0 => 1.18.0 (or the highest 1.x)
*/
function getPreviousVersion(versionStr) {
function tagExists(tagName) {
try {
cp.execSync(`git rev-parse ${tagName}`, { stdio: 'ignore' });
return true;
} catch (e) {
return false;
}
}
function getLastTagFromBase(semverArr, componentToTest) {
const baseVersion = semverArr.join('.');
if (!tagExists(baseVersion)) {
console.error('Failed to find tag for base version, ' + baseVersion);
return null;
}
let goodTag;
do {
goodTag = semverArr.join('.');
semverArr[componentToTest]++;
} while (tagExists(semverArr.join('.')));
return goodTag;
}
const semverArr = versionStr.split('.');
if (semverArr[2] > 0) {
semverArr[2]--;
return semverArr.join('.');
} else if (semverArr[1] > 0) {
semverArr[1]--;
return getLastTagFromBase(semverArr, 2);
} else {
semverArr[0]--;
return getLastTagFromBase(semverArr, 1);
}
}
function versionStringToNumber(versionStr) {
const semverRegex = /(\d+)\.(\d+)\.(\d+)/;
const match = versionStr.match(semverRegex);
if (!match) {
return 0;
}
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
}
gulp.task('generate-vscode-configuration', () => {
return new Promise((resolve, reject) => {
const buildDir = process.env['AGENT_BUILDDIRECTORY'];
if (!buildDir) {
return reject(new Error('$AGENT_BUILDDIRECTORY not set'));
}
const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
const appPath = path.join(buildDir, 'VSCode-darwin/Visual\\ Studio\\ Code\\ -\\ Insiders.app/Contents/Resources/app/bin/code');
const codeProc = cp.exec(`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`);
const timer = setTimeout(() => {
codeProc.kill();
reject(new Error('export-default-configuration process timed out'));
}, 10 * 1000);
codeProc.stdout.on('data', d => console.log(d.toString()));
codeProc.stderr.on('data', d => console.log(d.toString()));
codeProc.on('exit', () => {
clearTimeout(timer);
resolve();
});
codeProc.on('error', err => {
clearTimeout(timer);
reject(err);
});
}).catch(e => {
// Don't fail the build
console.error(e.toString());
});
});
// {{SQL CARBON EDIT}}
// Install service locally before building carbon
@@ -506,3 +641,5 @@ gulp.task('install-sqltoolsservice', () => {
var extObj = new mssqlExt.Constants();
return installService(extObj);
});

View File

@@ -56,6 +56,7 @@ function prepareDebPackage(arch) {
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@ICON@@', product.applicationName))
.pipe(rename('usr/share/applications/' + product.applicationName + '.desktop'));
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
@@ -133,6 +134,7 @@ function prepareRpmPackage(arch) {
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@ICON@@', product.applicationName))
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '.desktop'));
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
@@ -180,6 +182,50 @@ function buildRpmPackage(arch) {
'cp "' + rpmOut + '/$(ls ' + rpmOut + ')" ' + destination + '/'
]);
}
function getSnapBuildPath(arch) {
return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`;
}
function prepareSnapPackage(arch) {
const binaryDir = '../VSCode-linux-' + arch;
const destination = getSnapBuildPath(arch);
return function () {
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@ICON@@', `/usr/share/pixmaps/${product.applicationName}.png`))
.pipe(rename(`usr/share/applications/${product.applicationName}.desktop`));
const icon = gulp.src('resources/linux/code.png', { base: '.' })
.pipe(rename(`usr/share/pixmaps/${product.applicationName}.png`));
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
.pipe(rename(function (p) { p.dirname = 'usr/share/' + product.applicationName + '/' + p.dirname; }));
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@VERSION@@', packageJson.version))
.pipe(rename('snap/snapcraft.yaml'));
const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' })
.pipe(rename('electron-launch'));
const all = es.merge(desktop, icon, code, snapcraft, electronLaunch);
return all.pipe(vfs.dest(destination));
};
}
function buildSnapPackage(arch) {
const snapBuildPath = getSnapBuildPath(arch);
return shell.task([
`chmod +x ${snapBuildPath}/electron-launch`,
`cd ${snapBuildPath} && snapcraft snap`
]);
}
function getFlatpakArch(arch) {
return { x64: 'x86_64', ia32: 'i386', arm: 'arm' }[arch];
@@ -261,6 +307,12 @@ gulp.task('clean-vscode-linux-arm-deb', util.rimraf('.build/linux/deb/armhf'));
gulp.task('clean-vscode-linux-ia32-rpm', util.rimraf('.build/linux/rpm/i386'));
gulp.task('clean-vscode-linux-x64-rpm', util.rimraf('.build/linux/rpm/x86_64'));
gulp.task('clean-vscode-linux-arm-rpm', util.rimraf('.build/linux/rpm/armhf'));
gulp.task('clean-vscode-linux-ia32-snap', util.rimraf('.build/linux/snap/x64'));
gulp.task('clean-vscode-linux-x64-snap', util.rimraf('.build/linux/snap/x64'));
gulp.task('clean-vscode-linux-arm-snap', util.rimraf('.build/linux/snap/x64'));
gulp.task('clean-vscode-linux-ia32-flatpak', util.rimraf('.build/linux/flatpak/i386'));
gulp.task('clean-vscode-linux-x64-flatpak', util.rimraf('.build/linux/flatpak/x86_64'));
gulp.task('clean-vscode-linux-arm-flatpak', util.rimraf('.build/linux/flatpak/arm'));
gulp.task('vscode-linux-ia32-prepare-deb', ['clean-vscode-linux-ia32-deb'], prepareDebPackage('ia32'));
gulp.task('vscode-linux-x64-prepare-deb', ['clean-vscode-linux-x64-deb'], prepareDebPackage('x64'));
@@ -276,14 +328,16 @@ gulp.task('vscode-linux-ia32-build-rpm', ['vscode-linux-ia32-prepare-rpm'], buil
gulp.task('vscode-linux-x64-build-rpm', ['vscode-linux-x64-prepare-rpm'], buildRpmPackage('x64'));
gulp.task('vscode-linux-arm-build-rpm', ['vscode-linux-arm-prepare-rpm'], buildRpmPackage('arm'));
gulp.task('clean-vscode-linux-ia32-flatpak', util.rimraf('.build/linux/flatpak/i386'));
gulp.task('clean-vscode-linux-x64-flatpak', util.rimraf('.build/linux/flatpak/x86_64'));
gulp.task('clean-vscode-linux-arm-flatpak', util.rimraf('.build/linux/flatpak/arm'));
gulp.task('vscode-linux-ia32-prepare-snap', ['clean-vscode-linux-ia32-snap'], prepareSnapPackage('ia32'));
gulp.task('vscode-linux-x64-prepare-snap', ['clean-vscode-linux-x64-snap'], prepareSnapPackage('x64'));
gulp.task('vscode-linux-arm-prepare-snap', ['clean-vscode-linux-arm-snap'], prepareSnapPackage('arm'));
gulp.task('vscode-linux-ia32-build-snap', ['vscode-linux-ia32-prepare-snap'], buildSnapPackage('ia32'));
gulp.task('vscode-linux-x64-build-snap', ['vscode-linux-x64-prepare-snap'], buildSnapPackage('x64'));
gulp.task('vscode-linux-arm-build-snap', ['vscode-linux-arm-prepare-snap'], buildSnapPackage('arm'));
gulp.task('vscode-linux-ia32-prepare-flatpak', ['clean-vscode-linux-ia32-flatpak'], prepareFlatpak('ia32'));
gulp.task('vscode-linux-x64-prepare-flatpak', ['clean-vscode-linux-x64-flatpak'], prepareFlatpak('x64'));
gulp.task('vscode-linux-arm-prepare-flatpak', ['clean-vscode-linux-arm-flatpak'], prepareFlatpak('arm'));
gulp.task('vscode-linux-ia32-flatpak', ['vscode-linux-ia32-prepare-flatpak'], buildFlatpak('ia32'));
gulp.task('vscode-linux-x64-flatpak', ['vscode-linux-x64-prepare-flatpak'], buildFlatpak('x64'));
gulp.task('vscode-linux-arm-flatpak', ['vscode-linux-arm-prepare-flatpak'], buildFlatpak('arm'));

View File

@@ -64,7 +64,7 @@ var ModuleJsonFormat;
}
ModuleJsonFormat.is = is;
})(ModuleJsonFormat || (ModuleJsonFormat = {}));
var Line = (function () {
var Line = /** @class */ (function () {
function Line(indent) {
if (indent === void 0) { indent = 0; }
this.indent = indent;
@@ -83,7 +83,7 @@ var Line = (function () {
return Line;
}());
exports.Line = Line;
var TextModel = (function () {
var TextModel = /** @class */ (function () {
function TextModel(contents) {
this._lines = contents.split(/\r\n|\r|\n/);
}
@@ -96,7 +96,7 @@ var TextModel = (function () {
});
return TextModel;
}());
var XLF = (function () {
var XLF = /** @class */ (function () {
function XLF(project) {
this.project = project;
this.buffer = [];

View File

@@ -130,10 +130,6 @@
"name": "vs/workbench/parts/update",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/views",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/watermark",
"project": "vscode-workbench"
@@ -190,9 +186,17 @@
"name": "vs/workbench/services/textMate",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/workspace",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/decorations",
"project": "vscode-workbench"
},
{
"name": "setup_messages",
"project": "vscode-workbench"
}
]
}
}

View File

@@ -94,7 +94,7 @@ function isImportNode(node) {
return { line: position.line - 1, character: position.column };
}
nls_1.lcFrom = lcFrom;
var SingleFileServiceHost = (function () {
var SingleFileServiceHost = /** @class */ (function () {
function SingleFileServiceHost(options, filename, contents) {
var _this = this;
this.options = options;
@@ -161,7 +161,7 @@ function isImportNode(node) {
// `localize` named imports
var allLocalizeImportDeclarations = importDeclarations
.filter(function (d) { return d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports; })
.map(function (d) { return d.importClause.namedBindings.elements; })
.map(function (d) { return [].concat(d.importClause.namedBindings.elements); })
.flatten();
// `localize` read-only references
var localizeReferences = allLocalizeImportDeclarations
@@ -200,7 +200,7 @@ function isImportNode(node) {
};
}
nls_1.analyze = analyze;
var TextModel = (function () {
var TextModel = /** @class */ (function () {
function TextModel(contents) {
var regex = /\r\n|\r|\n/g;
var index = 0;

View File

@@ -227,7 +227,7 @@ module nls {
// `localize` named imports
const allLocalizeImportDeclarations = importDeclarations
.filter(d => d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports)
.map(d => (<ts.NamedImports>d.importClause.namedBindings).elements)
.map(d => [].concat((<ts.NamedImports>d.importClause.namedBindings).elements))
.flatten();
// `localize` read-only references

View File

@@ -54,7 +54,7 @@ function log() {
function createReporter() {
var errors = [];
allErrors.push(errors);
var ReportFunc = (function () {
var ReportFunc = /** @class */ (function () {
function ReportFunc(err) {
errors.push(err);
}

View File

@@ -1,59 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript");
var Lint = require("tslint");
var Rule = (function (_super) {
__extends(Rule, _super);
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
}
Rule.prototype.apply = function (sourceFile) {
var allowed = this.getOptions().ruleArguments[0];
return this.applyWithWalker(new AsyncRuleWalker(sourceFile, this.getOptions(), allowed));
};
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var AsyncRuleWalker = (function (_super) {
__extends(AsyncRuleWalker, _super);
function AsyncRuleWalker(file, opts, allowed) {
var _this = _super.call(this, file, opts) || this;
_this.allowed = allowed;
return _this;
}
AsyncRuleWalker.prototype.visitMethodDeclaration = function (node) {
this.visitFunctionLikeDeclaration(node);
};
AsyncRuleWalker.prototype.visitFunctionDeclaration = function (node) {
this.visitFunctionLikeDeclaration(node);
};
AsyncRuleWalker.prototype.visitFunctionLikeDeclaration = function (node) {
var _this = this;
var flags = ts.getCombinedModifierFlags(node);
if (!(flags & ts.ModifierFlags.Async)) {
return;
}
var path = node.getSourceFile().path;
var pathParts = path.split(/\\|\//);
if (pathParts.some(function (part) { return _this.allowed.some(function (allowed) { return part === allowed; }); })) {
return;
}
var message = "You are not allowed to use async function in this layer. Allowed layers are: [" + this.allowed + "]";
this.addFailureAtNode(node, message);
};
return AsyncRuleWalker;
}(Lint.RuleWalker));

View File

@@ -1,47 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as ts from 'typescript';
import * as Lint from 'tslint';
export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const allowed = this.getOptions().ruleArguments[0] as string[];
return this.applyWithWalker(new AsyncRuleWalker(sourceFile, this.getOptions(), allowed));
}
}
class AsyncRuleWalker extends Lint.RuleWalker {
constructor(file: ts.SourceFile, opts: Lint.IOptions, private allowed: string[]) {
super(file, opts);
}
protected visitMethodDeclaration(node: ts.MethodDeclaration): void {
this.visitFunctionLikeDeclaration(node);
}
protected visitFunctionDeclaration(node: ts.FunctionDeclaration): void {
this.visitFunctionLikeDeclaration(node);
}
private visitFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration) {
const flags = ts.getCombinedModifierFlags(node);
if (!(flags & ts.ModifierFlags.Async)) {
return;
}
const path = (node.getSourceFile() as any).path;
const pathParts = path.split(/\\|\//);
if (pathParts.some(part => this.allowed.some(allowed => part === allowed))) {
return;
}
const message = `You are not allowed to use async function in this layer. Allowed layers are: [${this.allowed}]`;
this.addFailureAtNode(node, message);
}
}

View File

@@ -16,7 +16,7 @@ var __extends = (this && this.__extends) || (function () {
Object.defineProperty(exports, "__esModule", { value: true });
var path_1 = require("path");
var Lint = require("tslint");
var Rule = (function (_super) {
var Rule = /** @class */ (function (_super) {
__extends(Rule, _super);
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
@@ -27,7 +27,7 @@ var Rule = (function (_super) {
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var ImportPatterns = (function (_super) {
var ImportPatterns = /** @class */ (function (_super) {
__extends(ImportPatterns, _super);
function ImportPatterns(file, opts) {
var _this = _super.call(this, file, opts) || this;

View File

@@ -18,7 +18,7 @@ var ts = require("typescript");
var Lint = require("tslint");
var minimatch = require("minimatch");
var path_1 = require("path");
var Rule = (function (_super) {
var Rule = /** @class */ (function (_super) {
__extends(Rule, _super);
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
@@ -36,7 +36,7 @@ var Rule = (function (_super) {
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var ImportPatterns = (function (_super) {
var ImportPatterns = /** @class */ (function (_super) {
__extends(ImportPatterns, _super);
function ImportPatterns(file, opts, _config) {
var _this = _super.call(this, file, opts) || this;

View File

@@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript");
var Lint = require("tslint");
var path_1 = require("path");
var Rule = (function (_super) {
var Rule = /** @class */ (function (_super) {
__extends(Rule, _super);
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
@@ -48,7 +48,7 @@ var Rule = (function (_super) {
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var LayeringRule = (function (_super) {
var LayeringRule = /** @class */ (function (_super) {
__extends(LayeringRule, _super);
function LayeringRule(file, config, opts) {
var _this = _super.call(this, file, opts) || this;

View File

@@ -19,7 +19,7 @@ var Lint = require("tslint");
/**
* Implementation of the no-unexternalized-strings rule.
*/
var Rule = (function (_super) {
var Rule = /** @class */ (function (_super) {
__extends(Rule, _super);
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
@@ -39,7 +39,7 @@ function isObjectLiteral(node) {
function isPropertyAssignment(node) {
return node && node.kind === ts.SyntaxKind.PropertyAssignment;
}
var NoUnexternalizedStringsRuleWalker = (function (_super) {
var NoUnexternalizedStringsRuleWalker = /** @class */ (function (_super) {
__extends(NoUnexternalizedStringsRuleWalker, _super);
function NoUnexternalizedStringsRuleWalker(file, opts) {
var _this = _super.call(this, file, opts) || this;

View File

@@ -16,7 +16,7 @@ var __extends = (this && this.__extends) || (function () {
Object.defineProperty(exports, "__esModule", { value: true });
var Lint = require("tslint");
var fs = require("fs");
var Rule = (function (_super) {
var Rule = /** @class */ (function (_super) {
__extends(Rule, _super);
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
@@ -27,7 +27,7 @@ var Rule = (function (_super) {
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var TranslationRemindRuleWalker = (function (_super) {
var TranslationRemindRuleWalker = /** @class */ (function (_super) {
__extends(TranslationRemindRuleWalker, _super);
function TranslationRemindRuleWalker(file, opts) {
return _super.call(this, file, opts) || this;

View File

@@ -67,7 +67,7 @@ function fixWin32DirectoryPermissions() {
exports.fixWin32DirectoryPermissions = fixWin32DirectoryPermissions;
function setExecutableBit(pattern) {
var setBit = es.mapSync(function (f) {
f.stat.mode = 33261;
f.stat.mode = /* 100755 */ 33261;
return f;
});
if (!pattern) {

View File

@@ -19,14 +19,15 @@ function handleDeletions() {
let watch = void 0;
if (!process.env['VSCODE_USE_LEGACY_WATCH']) {
try {
watch = require('./watch-nsfw');
} catch (err) {
console.warn('Could not load our cross platform file watcher: ' + err.toString());
console.warn('Falling back to our platform specific watcher...');
}
}
// Disabled due to https://github.com/Microsoft/vscode/issues/36214
// if (!process.env['VSCODE_USE_LEGACY_WATCH']) {
// try {
// watch = require('./watch-nsfw');
// } catch (err) {
// console.warn('Could not load our cross platform file watcher: ' + err.toString());
// console.warn('Falling back to our platform specific watcher...');
// }
// }
if (!watch) {
watch = process.platform === 'win32' ? require('./watch-win32') : require('gulp-watch');

View File

@@ -11,4 +11,4 @@ a good page describing the code editor's features is [here](https://code.visuals
This npm module contains the core editor functionality, as it comes from the [vscode repository](https://github.com/Microsoft/vscode).
## License
[Source EULA](https://github.com/Microsoft/sqlopsstudio/blob/master/LICENSE.txt)
[MIT](https://github.com/Microsoft/vscode/blob/master/LICENSE.txt)

View File

@@ -16,7 +16,7 @@ Copyright (c) Microsoft Corporation
All rights reserved.
Source EULA
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -32,7 +32,7 @@ END OF winjs NOTICES AND INFORMATION
%% string_scorer version 0.1.20 (https://github.com/joshaven/string_score)
=========================================
This software is released under the Source EULA:
This software is released under the MIT license:
Copyright (c) Joshaven Potter
@@ -60,7 +60,7 @@ END OF string_scorer NOTICES AND INFORMATION
%% chjj-marked NOTICES AND INFORMATION BEGIN HERE
=========================================
The Source EULA License
The MIT License (MIT)
Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)

View File

@@ -34,7 +34,7 @@ declare module monaco {
#include(vs/base/common/winjs.base.d.ts): TValueCallback, ProgressCallback, Promise
#include(vs/base/common/cancellation): CancellationTokenSource, CancellationToken
#include(vs/base/common/uri): URI
#include(vs/base/common/uri): URI, UriComponents
#include(vs/editor/common/standalone/standaloneBase): KeyCode, KeyMod
#include(vs/base/common/htmlContent): IMarkdownString
#include(vs/base/browser/keyboardEvent): IKeyboardEvent

View File

@@ -13,10 +13,10 @@
"url": "https://github.com/Microsoft/vscode/issues"
},
"devDependencies": {
"@types/minimist": "^1.2.0",
"@types/mocha": "^2.2.39",
"@types/semver": "^5.3.30",
"@types/sinon": "^1.16.34",
"@types/minimist": "1.2.0",
"@types/mocha": "2.2.39",
"@types/semver": "5.3.30",
"@types/sinon": "1.16.34",
"debounce": "^1.0.0",
"eslint": "^3.4.0",
"event-stream": "^3.1.7",
@@ -48,7 +48,7 @@
"sinon": "^1.17.2",
"source-map": "^0.4.4",
"tslint": "^4.3.1",
"typescript": "2.4.1",
"typescript": "2.5.2",
"typescript-formatter": "4.0.1",
"underscore": "^1.8.2",
"vinyl": "^0.4.5",

View File

@@ -19,6 +19,7 @@ function npmInstall(location, opts) {
}
}
// {{SQL CARBON EDIT}}
const protocol = [
'jsonrpc',
'types',

View File

@@ -54,7 +54,7 @@ const extensions = [
'scss',
'shaderlab',
'shellscript',
// 'sql', customized, PRs pending
'sql',
'swift',
'typescript',
'vb',

View File

@@ -22,7 +22,7 @@ function getOptions(urlString) {
headers: {
'User-Agent': 'NodeJS'
}
}
};
}
function download(url, redirectCount) {
@@ -100,7 +100,9 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar) {
result.version = 'https://github.com/' + repoId + '/commit/' + info.commitSha;
}
for (let key in grammar) {
result[key] = grammar[key];
if (!result.hasOwnProperty(key)) {
result[key] = grammar[key];
}
}
try {
@@ -116,7 +118,7 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar) {
});
}, console.error);
}
};
if (path.basename(process.argv[1]) === 'update-grammar.js') {
for (var i = 3; i < process.argv.length; i += 2) {

View File

@@ -1,14 +1,14 @@
{
"name": "code-oss-dev-build",
"name": "sqlops-oss-dev-build",
"version": "1.0.0",
"devDependencies": {
"@types/azure": "^0.9.18",
"@types/documentdb": "^1.10.1",
"@types/es6-collections": "^0.5.30",
"@types/es6-promise": "0.0.32",
"@types/azure": "0.9.19",
"@types/documentdb": "1.10.2",
"@types/es6-collections": "0.5.31",
"@types/es6-promise": "0.0.33",
"@types/mime": "0.0.29",
"@types/node": "^7.0.13",
"@types/xml2js": "^0.0.33",
"@types/node": "8.0.33",
"@types/xml2js": "0.0.33",
"azure-storage": "^2.1.0",
"decompress": "^4.2.0",
"documentdb": "^1.11.0",
@@ -16,8 +16,8 @@
"fs-extra-promise": "^1.0.1",
"mime": "^1.3.4",
"minimist": "^1.2.0",
"typescript": "2.4.1",
"vscode": "^1.0.1",
"typescript": "2.5.2",
"vscode": "^1.0.1",
"xml2js": "^0.4.17"
},
"scripts": {

View File

@@ -52,20 +52,20 @@ function isBuildSigned(quality: string, commit: string): Promise<boolean> {
});
}
async function waitForSignedBuild(quality: string, commit: string): Promise<void> {
let retries = 0;
// async function waitForSignedBuild(quality: string, commit: string): Promise<void> {
// let retries = 0;
while (retries < 180) {
if (await isBuildSigned(quality, commit)) {
return;
}
// while (retries < 180) {
// if (await isBuildSigned(quality, commit)) {
// return;
// }
await new Promise<void>(c => setTimeout(c, 10000));
retries++;
}
// await new Promise<void>(c => setTimeout(c, 10000));
// retries++;
// }
throw new Error('Timed out waiting for signed build');
}
// throw new Error('Timed out waiting for signed build');
// }
async function main(quality: string): Promise<void> {
const commit = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim();
@@ -73,10 +73,10 @@ async function main(quality: string): Promise<void> {
console.log(`Queueing signing request for '${quality}/${commit}'...`);
await queueSigningRequest(quality, commit);
console.log('Waiting on signed build...');
await waitForSignedBuild(quality, commit);
// console.log('Waiting on signed build...');
// await waitForSignedBuild(quality, commit);
console.log('Found signed build!');
// console.log('Found signed build!');
}
main(process.argv[2]).catch(err => {

View File

@@ -68,6 +68,7 @@ interface Asset {
mooncakeUrl: string;
hash: string;
sha256hash: string;
size: number;
}
function createOrUpdate(commit: string, quality: string, platform: string, type: string, release: NewDocument, asset: Asset, isUpdate: boolean): Promise<void> {
@@ -156,7 +157,7 @@ async function publish(commit: string, quality: string, platform: string, type:
console.log('Publishing...');
console.log('Quality:', quality);
console.log('Platforn:', platform);
console.log('Platform:', platform);
console.log('Type:', type);
console.log('Name:', name);
console.log('Version:', version);
@@ -165,6 +166,11 @@ async function publish(commit: string, quality: string, platform: string, type:
console.log('Is Released:', isReleased);
console.log('File:', file);
const stat = await new Promise<fs.Stats>((c, e) => fs.stat(file, (err, stat) => err ? e(err) : c(stat)));
const size = stat.size;
console.log('Size:', size);
const stream = fs.createReadStream(file);
const [sha1hash, sha256hash] = await Promise.all([hashStream('sha1', stream), hashStream('sha256', stream)]);
@@ -224,7 +230,8 @@ async function publish(commit: string, quality: string, platform: string, type:
url: `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`,
mooncakeUrl: `${process.env['MOONCAKE_CDN_URL']}/${quality}/${blobName}`,
hash: sha1hash,
sha256hash
sha256hash,
size
};
const release = {

View File

@@ -37,5 +37,19 @@ step "Run unit tests" \
step "Run integration tests" \
./scripts/test-integration.sh
# function smoketest {
# ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts"
# rm -rf $ARTIFACTS
# [[ "$VSCODE_QUALITY" == "insider" ]] && VSCODE_APPNAME="Visual Studio Code - Insiders" || VSCODE_APPNAME="Visual Studio Code"
# npm run smoketest -- --build "$AGENT_BUILDDIRECTORY/VSCode-darwin/$VSCODE_APPNAME.app" --log $ARTIFACTS
# }
# step "Run smoke test" \
# smoketest
step "Publish release" \
./build/tfs/darwin/release.sh
step "Generate and upload configuration.json" \
npm run gulp -- upload-vscode-configuration

View File

@@ -20,7 +20,7 @@ rm -rf $UNSIGNEDZIP
zip -r -X -y $UNSIGNEDZIP *)
step "Upload unsigned archive" \
node build/tfs/common/publish.js --upload-only $VSCODE_QUALITY darwin archive-unsigned VSCode-darwin-$VSCODE_QUALITY-unsigned.zip $VERSION false $UNSIGNEDZIP
node build/tfs/common/publish.js $VSCODE_QUALITY darwin archive-unsigned VSCode-darwin-$VSCODE_QUALITY-unsigned.zip $VERSION false $UNSIGNEDZIP
step "Sign build" \
node build/tfs/common/enqueue.js $VSCODE_QUALITY

View File

@@ -1,28 +0,0 @@
#!/bin/sh
. ./build/tfs/common/node.sh
. ./scripts/env.sh
. ./build/tfs/common/common.sh
export VSCODE_MIXIN_PASSWORD="$1"
VSO_PAT="$2"
echo "machine monacotools.visualstudio.com password $VSO_PAT" > ~/.netrc
step "Install dependencies" \
npm install
step "Mix in repository from vscode-distro" \
npm run gulp -- mixin
step "Install distro dependencies" \
node build/tfs/common/installDistro.js
step "Build minified & upload source maps" \
npm run gulp -- vscode-darwin-min
step "Run smoke test" \
pushd test/smoke
npm install
npm test -- --latest "$AGENT_BUILDDIRECTORY/VSCode-darwin/Visual Studio Code - Insiders.app/Contents/MacOS/Electron"
popd

View File

@@ -39,5 +39,22 @@ step "Build minified" \
step "Run unit tests" \
./scripts/test.sh --build --reporter dot
# function smoketest {
# id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword)
# sudo -i -u testuser -- sh -c 'git config --global user.name "VS Code Agent" && git config --global user.email "monacotools@microsoft.com"'
# ARTIFACTS="$AGENT_BUILDDIRECTORY/smoketest-artifacts"
# rm -rf $ARTIFACTS
# mkdir -p $ARTIFACTS
# chown -R testuser $ARTIFACTS
# ps -o pid= -u testuser | xargs sudo kill -9
# DISPLAY=:10 sudo -i -u testuser -- sh -c "cd $BUILD_SOURCESDIRECTORY/test/smoke && ./node_modules/.bin/mocha --build $AGENT_BUILDDIRECTORY/VSCode-linux-$ARCH --log $ARTIFACTS"
# # DISPLAY=:10 sudo -i -u testuser -- sh -c "cd /vso/work/1/s/test/smoke && ./node_modules/.bin/mocha --build /vso/work/1/VSCode-linux-ia32"
# }
# step "Run smoke test" \
# smoketest
step "Publish release" \
./build/tfs/linux/release.sh

View File

@@ -40,6 +40,9 @@ ADD xvfb.init /etc/init.d/xvfb
RUN chmod +x /etc/init.d/xvfb
RUN update-rc.d xvfb defaults
# dbus
RUN ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon
# nvm
ENV NVM_DIR /usr/local/nvm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
@@ -47,4 +50,4 @@ RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | b
# for libsecret
ENV PKG_CONFIG_PATH /usr/lib/i386-linux-gnu/pkgconfig
CMD (service xvfb start; export DISPLAY=:10; ./start.sh)
CMD (service xvfb start; service dbus start; export DISPLAY=:10; ./start.sh)

View File

@@ -9,6 +9,9 @@ step "Build Debian package" \
step "Build RPM package" \
npm run gulp -- "vscode-linux-$ARCH-build-rpm"
# step "Build snap package" \
# npm run gulp -- "vscode-linux-$ARCH-build-snap"
(cd $BUILD_SOURCESDIRECTORY/build/tfs/common && \
step "Install build dependencies" \
npm install --unsafe-perm)
@@ -49,6 +52,9 @@ RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
step "Publish RPM package" \
node build/tfs/common/publish.js $VSCODE_QUALITY $PLATFORM_RPM package $RPM_FILENAME $VERSION true $RPM_PATH
# SNAP_FILENAME="$(ls $REPO/.build/linux/snap/$ARCH/ | grep .snap)"
# SNAP_PATH="$REPO/.build/linux/snap/$ARCH/$SNAP_FILENAME"
if [ -z "$VSCODE_QUALITY" ]; then
echo "VSCODE_QUALITY is not set, skipping repo package publish"
else

View File

@@ -1,6 +1,6 @@
#!/bin/bash -e
# This is a VERY basic script for Create/Delete operations on repos and packages
#
#
cmd=$1
urls=urls.txt
defaultPackageFile=new_package.json
@@ -53,7 +53,7 @@ function ParseConfigFile {
fi
BailIfFileMissing "$configFile"
secretContents=$(cat "$configFile")
server=$(ParseFromJson .server)
protocol=$(ParseFromJson .protocol)
port=$(ParseFromJson .port)
@@ -135,14 +135,14 @@ function AddPackageByUrl
rm -f $tmpFile $tmpOut
Bail "File is not a valid deb/rpm package $url"
fi
rm -f $tmpFile $tmpOut
if [ -z "$pkgName" ]; then
Bail "Unable to parse package name for $url"
elif [ -z "$pkgVer" ]; then
Bail "Unable to parse package version number for $url"
fi
# Create Package .json file
escapedUrl=$(echo "$url" | sed 's/\//\\\//g' | sed 's/\&/\\\&/g')
cp $defaultPackageFile.template $defaultPackageFile
@@ -153,7 +153,7 @@ function AddPackageByUrl
# Perform Upload
AddPackage $defaultPackageFile
# Cleanup
rm -f $defaultPackageFile
rm -f $defaultPackageFile
}
# Upload multiple packages by reading urls line-by-line from the specified file

View File

@@ -1,46 +0,0 @@
#!/bin/bash
set -e
. ./build/tfs/common/node.sh
. ./scripts/env.sh
. ./build/tfs/common/common.sh
export ARCH="$1"
export VSCODE_MIXIN_PASSWORD="$2"
VSO_PAT="$3"
echo "machine monacotools.visualstudio.com password $VSO_PAT" > ~/.netrc
step "Install dependencies" \
npm install --arch=$ARCH --unsafe-perm
step "Mix in repository from vscode-distro" \
npm run gulp -- mixin
step "Get Electron" \
npm run gulp -- "electron-$ARCH"
step "Install distro dependencies" \
node build/tfs/common/installDistro.js --arch=$ARCH
step "Build minified" \
npm run gulp -- "vscode-linux-$ARCH-min"
function configureEnvironment {
id -u testuser &>/dev/null || (useradd -m testuser; chpasswd <<< testuser:testpassword)
sudo -i -u testuser git config --global user.name "VS Code Agent"
sudo -i -u testuser git config --global user.email "monacotools@microsoft.com"
chown -R testuser $AGENT_BUILDDIRECTORY
}
function runTest {
pushd test/smoke
npm install
sudo -u testuser -H xvfb-run -a -s "-screen 0 1024x768x8" npm test -- --latest "$AGENT_BUILDDIRECTORY/VSCode-linux-ia32/code-insiders"
popd
}
step "Configure environment" configureEnvironment
step "Run smoke test" runTest

View File

@@ -36,8 +36,11 @@ ADD xvfb.init /etc/init.d/xvfb
RUN chmod +x /etc/init.d/xvfb
RUN update-rc.d xvfb defaults
# dbus
RUN ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon
# nvm
ENV NVM_DIR /usr/local/nvm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
CMD (service xvfb start; export DISPLAY=:10; ./start.sh)
CMD (service xvfb start; service dbus start; export DISPLAY=:10; ./start.sh)

View File

@@ -52,4 +52,11 @@ step "Run unit tests" {
# exec { & .\scripts\test-integration.bat }
# }
# step "Run smoke test" {
# $Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts"
# Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts
# exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --log "$Artifacts" }
# }
done

View File

@@ -0,0 +1,85 @@
Param(
[string]$arch,
[string]$mixinPassword,
[string]$vsoPAT,
[string]$storageKey,
[string]$mooncakeStorageKey,
[string]$documentDbKey
)
. .\build\tfs\win32\node.ps1
. .\scripts\env.ps1
. .\build\tfs\win32\lib.ps1
# Create a _netrc file to download distro dependencies
# In order to get _netrc to work, we need a HOME variable setup
"machine monacotools.visualstudio.com password ${vsoPAT}" | Out-File "$env:HOME\_netrc" -Encoding ASCII
# Set the right architecture
$env:npm_config_arch="$arch"
step "Install dependencies" {
exec { & npm install }
}
step "Hygiene" {
exec { & npm run gulp -- hygiene }
}
$env:VSCODE_MIXIN_PASSWORD = $mixinPassword
step "Mix in repository from vscode-distro" {
exec { & npm run gulp -- mixin }
}
step "Get Electron" {
exec { & npm run gulp -- "electron-$global:arch" }
}
step "Install distro dependencies" {
exec { & node build\tfs\common\installDistro.js }
}
step "Build minified" {
exec { & npm run gulp -- "vscode-win32-$global:arch-min" }
}
step "Run unit tests" {
exec { & .\scripts\test.bat --build --reporter dot }
}
step "Run smoke test" {
$Artifacts = "$env:AGENT_BUILDDIRECTORY\smoketest-artifacts"
Remove-Item -Recurse -Force -ErrorAction Ignore $Artifacts
exec { & npm run smoketest -- --build "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch" --log "$Artifacts" }
}
step "Create archive and setup package" {
exec { & npm run gulp -- "vscode-win32-$global:arch-archive" "vscode-win32-$global:arch-setup" }
}
$Repo = "$(pwd)"
$Root = "$Repo\.."
$Exe = "$Repo\.build\win32-$arch\setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$arch\archive\VSCode-win32-$arch.zip"
$Build = "$Root\VSCode-win32-$arch"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$env:AZURE_STORAGE_ACCESS_KEY_2 = $storageKey
$env:MOONCAKE_STORAGE_ACCESS_KEY = $mooncakeStorageKey
$env:AZURE_DOCUMENTDB_MASTERKEY = $documentDbKey
$assetPlatform = if ($arch -eq "ia32") { "win32" } else { "win32-x64" }
step "Publish UNSIGNED archive" {
exec { & node build/tfs/common/publish.js $Quality "$global:assetPlatform-archive" archive-unsigned "VSCode-win32-$global:arch-$Version-unsigned.zip" $Version false $Zip }
}
step "Publish UNSIGNED setup package" {
exec { & node build/tfs/common/publish.js $Quality "$global:assetPlatform" setup-unsigned "VSCodeSetup-$global:arch-$Version-unsigned.exe" $Version false $Exe }
}
done

View File

@@ -1,47 +0,0 @@
Param(
[string]$arch,
[string]$mixinPassword,
[string]$vsoPAT
)
. .\build\tfs\win32\node.ps1
. .\scripts\env.ps1
. .\build\tfs\win32\lib.ps1
# Create a _netrc file to download distro dependencies
# In order to get _netrc to work, we need a HOME variable setup
$env:HOME = $env:USERPROFILE
"machine monacotools.visualstudio.com password ${vsoPAT}" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
# Set the right architecture
$env:npm_config_arch = "$arch"
step "Install dependencies" {
exec { & npm install }
}
$env:VSCODE_MIXIN_PASSWORD = $mixinPassword
step "Mix in repository from vscode-distro" {
exec { & npm run gulp -- mixin }
}
step "Get Electron" {
exec { & npm run gulp -- "electron-$global:arch" }
}
step "Install distro dependencies" {
exec { & node build\tfs\common\installDistro.js }
}
step "Build minified" {
exec { & npm run gulp -- "vscode-win32-$global:arch-min" }
}
step "Run smoke test" {
exec { & Push-Location test\smoke }
exec { & npm install }
exec { & npm test -- --latest "$env:AGENT_BUILDDIRECTORY\VSCode-win32-$global:arch\Code - Insiders.exe" }
exec { & Pop-Location }
}
done

View File

@@ -20,6 +20,7 @@ OutputBaseFilename=SqlOpsStudioSetup
Compression=lzma
SolidCompression=yes
AppMutex={#AppMutex}
SetupMutex={#AppMutex}setup
WizardImageFile={#RepoDir}\resources\win32\inno-big.bmp
WizardSmallImageFile={#RepoDir}\resources\win32\inno-small.bmp
SetupIconFile={#RepoDir}\resources\win32\code.ico

View File

@@ -1,13 +0,0 @@
language: node_js
sudo: false
node_js:
- "0.12"
install:
- cd jsonrpc && npm install && cd ../client && mkdir node_modules && cd node_modules && ln -s ../../jsonrpc vscode-jsonrpc && cd .. && npm install && cd ../server && mkdir node_modules && cd node_modules && ln -s ../../jsonrpc vscode-jsonrpc && cd .. && npm install && cd ..
- cd types && npm install && cd ../client && cd node_modules && ln -s ../../types vscode-languageserver-types && cd .. && npm install && cd ../server && cd node_modules && ln -s ../../types vscode-languageserver-types && cd .. && npm install && cd ..
script:
- cd jsonrpc && npm run compile && cd ../types && npm run compile && cd ../client && npm run compile && cd ../server && npm run compile && cd ..
- cd jsonrpc && npm test && cd ../types && npm test && cd ..

View File

@@ -0,0 +1,18 @@
Copyright (c) Microsoft Corporation
All rights reserved.
Source EULA
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,4 +1,4 @@
# Microsoft Data Management Protocol - Node
## License
[Source EULA](https://github.com/Microsoft/sqlopsstudio/blob/dev/license.txt)
[MIT](https://github.com/Microsoft/carbon/blob/dev/license.txt)

View File

@@ -1,4 +1,4 @@
# Microsoft Data Management Protocol - Node
## License
[Source EULA](https://github.com/Microsoft/sqlopsstudio/blob/dev/license.txt)
[MIT](https://github.com/Microsoft/carbon/blob/dev/license.txt)

View File

@@ -30,7 +30,8 @@ import {
ExpandNodeInfo, ObjectExplorerCloseSessionInfo, ObjectExplorerSession, ObjectExplorerExpandInfo,
TaskServicesProvider, ListTasksParams, ListTasksResponse, CancelTaskParams, TaskProgressInfo, TaskInfo,
AdminServicesProvider, DisasterRecoveryProvider, RestoreInfo, ExecutionPlanOptions,
RestoreConfigInfo, SerializationProvider, FileBrowserProvider, FileBrowserOpenedParams, FileBrowserExpandedParams, FileBrowserValidatedParams
SerializationProvider, FileBrowserProvider, FileBrowserOpenedParams, FileBrowserExpandedParams, FileBrowserValidatedParams,
RestoreConfigInfo, ProfilerProvider, ProfilerSessionEvents
} from 'data';
import {
@@ -63,7 +64,9 @@ import {
DefaultDatabaseInfoResponse, DefaultDatabaseInfoParams,
GetDatabaseInfoResponse, GetDatabaseInfoParams,
BackupConfigInfoResponse, FileBrowserOpenParams, FileBrowserCloseResponse,
FileBrowserCloseParams, FileBrowserExpandParams, FileBrowserValidateParams
FileBrowserCloseParams, FileBrowserExpandParams, FileBrowserValidateParams,
StartProfilingParams, StartProfilingResponse, StopProfilingParams, StopProfilingResponse,
ProfilerEventsAvailableParams
} from 'dataprotocol-languageserver-types';
@@ -126,7 +129,8 @@ import {
RestoreRequest, RestorePlanRequest, CancelRestorePlanRequest, RestoreConfigInfoRequest,
ListTasksRequest, CancelTaskRequest, TaskStatusChangedNotification, TaskCreatedNotification,
LanguageFlavorChangedNotification, DidChangeLanguageFlavorParams, FileBrowserOpenRequest, FileBrowserOpenedNotification,
FileBrowserValidateRequest, FileBrowserValidatedNotification, FileBrowserExpandRequest, FileBrowserExpandedNotification, FileBrowserCloseRequest
FileBrowserValidateRequest, FileBrowserValidatedNotification, FileBrowserExpandRequest, FileBrowserExpandedNotification, FileBrowserCloseRequest,
StartProfilingRequest, StopProfilingRequest, ProfilerEventsAvailableNotification
} from './protocol';
import * as c2p from './codeConverter';
@@ -835,6 +839,7 @@ export class LanguageClient {
this.state = ClientState.StartFailed;
this._onReadyCallbacks.reject(error);
this.error('Starting client failed', error);
Window.showErrorMessage(`Couldn't start client ${this._name}`);
});
return new Disposable(() => {
if (this.needsStop()) {
@@ -2026,53 +2031,10 @@ export class LanguageClient {
let scriptingProvider: ScriptingProvider = {
scriptAsSelect(connectionUri: string, metadata: ObjectMetadata, paramDetails: ScriptingParamDetails): Thenable<ScriptingResult> {
return self.sendRequest(ScriptingRequest.type,
self._c2p.asScriptingParams(connectionUri, ScriptOperation.Select, metadata, paramDetails), undefined).then(
self._p2c.asScriptingResult,
(error) => {
self.logFailedRequest(ScriptingRequest.type, error);
return Promise.resolve(undefined);
}
);
},
scriptAsCreate(connectionUri: string, metadata: ObjectMetadata, paramDetails: ScriptingParamDetails): Thenable<ScriptingResult> {
scriptAsOperation(connectionUri: string, operation: ScriptOperation, metadata: ObjectMetadata, paramDetails: ScriptingParamDetails): Thenable<ScriptingResult> {
return self.sendRequest(ScriptingRequest.type,
self._c2p.asScriptingParams(connectionUri, ScriptOperation.Create, metadata, paramDetails), undefined).then(
self._p2c.asScriptingResult,
(error) => {
self.logFailedRequest(ScriptingRequest.type, error);
return Promise.resolve(undefined);
}
);
},
scriptAsInsert(connectionUri: string, metadata: ObjectMetadata, paramDetails: ScriptingParamDetails): Thenable<ScriptingResult> {
return self.sendRequest(ScriptingRequest.type,
self._c2p.asScriptingParams(connectionUri, ScriptOperation.Insert, metadata, paramDetails), undefined).then(
self._p2c.asScriptingResult,
(error) => {
self.logFailedRequest(ScriptingRequest.type, error);
return Promise.resolve(undefined);
}
);
},
scriptAsUpdate(connectionUri: string, metadata: ObjectMetadata, paramDetails: ScriptingParamDetails): Thenable<ScriptingResult> {
return self.sendRequest(ScriptingRequest.type,
self._c2p.asScriptingParams(connectionUri, ScriptOperation.Update, metadata, paramDetails), undefined).then(
self._p2c.asScriptingResult,
(error) => {
self.logFailedRequest(ScriptingRequest.type, error);
return Promise.resolve(undefined);
}
);
},
scriptAsDelete(connectionUri: string, metadata: ObjectMetadata, paramDetails: ScriptingParamDetails): Thenable<ScriptingResult> {
return self.sendRequest(ScriptingRequest.type,
self._c2p.asScriptingParams(connectionUri, ScriptOperation.Delete, metadata, paramDetails), undefined).then(
self._c2p.asScriptingParams(connectionUri, operation, metadata, paramDetails), undefined).then(
self._p2c.asScriptingResult,
(error) => {
self.logFailedRequest(ScriptingRequest.type, error);
@@ -2211,12 +2173,61 @@ export class LanguageClient {
}
};
let serializationProvider: SerializationProvider = {
handle: 0,
saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Thenable<SaveResultRequestResult> {
throw new Error('NotImplemented');
let profilerProvider: ProfilerProvider = {
startSession(sessionId: string): Thenable<boolean> {
let params: StartProfilingParams = {
ownerUri: sessionId,
options: { }
};
return self.sendRequest(StartProfilingRequest.type, params, undefined).then(
(result) => {
return result;
},
(error) => {
self.logFailedRequest(StartProfilingRequest.type, error);
return Promise.reject(error);
}
);
},
stopSession(sessionId: string): Thenable<boolean> {
let params: StopProfilingParams = {
ownerUri: sessionId
};
return self.sendRequest(StopProfilingRequest.type, params, undefined).then(
(result) => {
return result;
},
(error) => {
self.logFailedRequest(StopProfilingRequest.type, error);
return Promise.reject(error);
}
);
},
pauseSession(sessionId: string): Thenable<boolean> {
return undefined;
},
connectSession(sessionId: string): Thenable<boolean> {
return undefined;
},
disconnectSession(sessionId: string): Thenable<boolean> {
return undefined;
},
registerOnSessionEventsAvailable(handler: (response: ProfilerSessionEvents) => any) {
self.onNotification(ProfilerEventsAvailableNotification.type, (params: ProfilerEventsAvailableParams) => {
handler(<ProfilerSessionEvents>{
sessionId: params.ownerUri,
events: params.events
});
});
}
}
};
this._providers.push(dataprotocol.registerProvider({
handle: -1,
@@ -2241,7 +2252,9 @@ export class LanguageClient {
taskServicesProvider: taskServicesProvider,
fileBrowserProvider: fileBrowserProvider
fileBrowserProvider: fileBrowserProvider,
profilerProvider: profilerProvider
}));
// Hook to the workspace-wide notifications that aren't routed to a specific provider

View File

@@ -34,7 +34,9 @@ import {
TaskInfo, ListTasksParams, ListTasksResponse, CancelTaskParams, TaskProgressInfo,
DefaultDatabaseInfoParams, DefaultDatabaseInfoResponse, BackupConfigInfoResponse, FileBrowserOpenParams, FileBrowserOpenedParams,
FileBrowserCloseParams, FileBrowserExpandParams, FileBrowserValidateParams,
FileBrowserCloseResponse, FileBrowserExpandedParams, FileBrowserValidatedParams
FileBrowserCloseResponse, FileBrowserExpandedParams, FileBrowserValidatedParams,
StartProfilingParams, StartProfilingResponse, StopProfilingParams, StopProfilingResponse,
ProfilerEventsAvailableParams
} from 'dataprotocol-languageserver-types';
@@ -1583,3 +1585,17 @@ export namespace FileBrowserValidatedNotification {
export namespace FileBrowserCloseRequest {
export const type: RequestType<FileBrowserCloseParams, FileBrowserCloseResponse, void> = { get method(): string { return 'filebrowser/close'; } };
}
// ------------------------------- < Profiler Events > ------------------------------------
export namespace StartProfilingRequest {
export const type: RequestType<StartProfilingParams, StartProfilingResponse, void> = { get method(): string { return 'profiler/start'; } };
}
export namespace StopProfilingRequest {
export const type: RequestType<StopProfilingParams, StopProfilingResponse, void> = { get method(): string { return 'profiler/stop'; } };
}
export namespace ProfilerEventsAvailableNotification {
export const type: NotificationType<ProfilerEventsAvailableParams> = { get method(): string { return 'profiler/eventsavailable'; } };
}

View File

@@ -1,27 +1,27 @@
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
For Microsoft vscode-languageclient
This project incorporates material from the project(s) listed below (collectively, “Third Party Code”).
Microsoft is not the original author of the Third Party Code. The original copyright notice and license
under which Microsoft received such Third Party Code are set out below. This Third Party Code is licensed
to you under their original license terms set forth below. Microsoft reserves all other rights not expressly
Microsoft is not the original author of the Third Party Code. The original copyright notice and license
under which Microsoft received such Third Party Code are set out below. This Third Party Code is licensed
to you under their original license terms set forth below. Microsoft reserves all other rights not expressly
granted, whether by implication, estoppel or otherwise.
1. DefinitelyTyped version 0.0.1 (https://github.com/borisyankov/DefinitelyTyped)
This project is licensed under the Source EULA license.
This project is licensed under the MIT license.
Copyrights are respective of each contributor listed at the beginning of each definition file.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

View File

@@ -1,4 +1,4 @@
# Microsoft Data Management Protocol - Node
## License
[Source EULA](https://github.com/Microsoft/sqlopsstudio/blob/dev/license.txt)
[MIT](https://github.com/Microsoft/carbon/blob/dev/license.txt)

View File

@@ -467,7 +467,7 @@ function createMessageConnection<T extends MessageConnection>(messageReader: Mes
eventHandlers[type.method] = handler;
},
sendRequest: <P, R, E>(type: RequestType<P, R, E>, params: P, token?: CancellationToken): any => {
sendRequest: <P, R, E>(type: RequestType<P, R, E>, params: P, token?: CancellationToken) => {
throwIfClosedOrDisposed();
let id = sequenceNumber++;

View File

@@ -108,7 +108,7 @@ export class IPCMessageWriter extends AbstractMessageWriter implements MessageWr
public write(msg: Message): void {
try {
(<any>this.process).send(<any>msg);
(this.process.send as Function)(msg);
this.errorCount = 0;
} catch (error) {
this.errorCount++;

View File

@@ -9,7 +9,7 @@ granted, whether by implication, estoppel or otherwise.
1. DefinitelyTyped version 0.0.1 (https://github.com/borisyankov/DefinitelyTyped)
This project is licensed under the Source EULA.
This project is licensed under the MIT license.
Copyrights are respective of each contributor listed at the beginning of each definition file.
Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@@ -1,4 +1,4 @@
# Microsoft Data Management Protocol - Node
## License
[Source EULA](https://github.com/Microsoft/sqlopsstudio/blob/dev/license.txt)
[MIT](https://github.com/Microsoft/carbon/blob/dev/license.txt)

View File

@@ -480,8 +480,8 @@ export interface RestoreDatabaseFileInfo {
}
export interface FileBrowserOpenParams {
ownerUri: string;
expandPath: string;
ownerUri: string;
expandPath: string;
fileFilters: string[];
changeFilter: boolean;
}
@@ -507,8 +507,8 @@ export interface FileBrowserOpenedParams {
}
export interface FileBrowserExpandParams {
ownerUri: string;
expandPath: string;
ownerUri: string;
expandPath: string;
}
export interface FileBrowserExpandedParams {
@@ -520,9 +520,9 @@ export interface FileBrowserExpandedParams {
}
export interface FileBrowserValidateParams {
ownerUri: string;
serviceType: string;
selectedFiles: string[];
ownerUri: string;
serviceType: string;
selectedFiles: string[];
}
export interface FileBrowserValidatedParams {
@@ -531,7 +531,7 @@ export interface FileBrowserValidatedParams {
}
export interface FileBrowserCloseParams {
ownerUri: string;
ownerUri: string;
}
export interface FileBrowserCloseResponse {
@@ -721,7 +721,9 @@ export enum ScriptOperation {
Create = 1,
Insert = 2,
Update = 3,
Delete = 4
Delete = 4,
Execute = 5,
Alter = 6
}
export interface ScriptOptions {
@@ -1079,6 +1081,77 @@ export class TableMetadata {
}
/**
* Parameters to start a profiler session
*/
export interface StartProfilingParams {
/**
* Session Owner URI
*/
ownerUri: string;
/**
* Session options
*/
options: {};
}
export interface StartProfilingResponse {
succeeded: string;
errorMessage: string;
}
/**
* Parameters to start a profiler session
*/
export interface StopProfilingParams {
/**
* Session Owner URI
*/
ownerUri: string;
}
export interface StopProfilingResponse {
succeeded: string;
errorMessage: string;
}
/**
* Profiler Event
*/
export interface ProfilerEvent {
/**
* Event class name
*/
name: string;
/**
* Event timestamp
*/
timestamp: string;
/**
* Event values
*/
values: {};
}
/**
* Profiler events available notification parameters
*/
export interface ProfilerEventsAvailableParams
{
/**
* Session owner URI
*/
ownerUri: string;
/**
* New profiler events available
*/
events: ProfilerEvent[];
}
/**
* Position in a text document expressed as zero-based line and character offset.
*/

View File

@@ -248,7 +248,7 @@ export function parseNumAsTimeString(value: number): string {
}
// The function is a duplicate of carbon\src\paths.js. IT would be better to import path.js but it doesn't
// The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't
// work for now because the extension is running in different process.
export function getAppDataPath() {
var platform = process.platform;
@@ -260,11 +260,5 @@ export function getAppDataPath() {
}
}
export function getDefaultLogLocation() {
var platform = process.platform;
let rootFolderName: string = '.sqlops';
if (platform === 'win32') {
rootFolderName = 'sqlops';
}
return path.join(getAppDataPath(), rootFolderName);
return path.join(getAppDataPath(), 'sqlops');
}

View File

@@ -18,5 +18,11 @@
["[", "]"],
["(", ")"],
["\"", "\""]
]
}
],
"folding": {
"markers": {
"start": "^\\s*(::\\s*|REM\\s+)#region",
"end": "^\\s*(::\\s*|REM\\s+)#endregion"
}
}
}

View File

@@ -33,19 +33,11 @@
},
{
"fileMatch": "vscode://defaultsettings/settings.json",
"url": "vscode://schemas/settings"
},
{
"fileMatch": "vscode://defaultsettings/resourceSettings.json",
"url": "vscode://schemas/settings/resource"
},
{
"fileMatch": "vscode://settings/workspaceSettings.json",
"url": "vscode://schemas/settings"
"url": "vscode://schemas/settings/default"
},
{
"fileMatch": "%APP_SETTINGS_HOME%/settings.json",
"url": "vscode://schemas/settings"
"url": "vscode://schemas/settings/user"
},
{
"fileMatch": "%APP_WORKSPACES_HOME%/*/workspace.json",
@@ -60,15 +52,15 @@
"url": "vscode://schemas/locale"
},
{
"fileMatch": "/.sqlops/settings.json",
"url": "vscode://schemas/settings"
"fileMatch": "/.vscode/settings.json",
"url": "vscode://schemas/settings/folder"
},
{
"fileMatch": "/.sqlops/launch.json",
"fileMatch": "/.vscode/launch.json",
"url": "vscode://schemas/launch"
},
{
"fileMatch": "/.sqlops/tasks.json",
"fileMatch": "/.vscode/tasks.json",
"url": "vscode://schemas/tasks"
},
{
@@ -82,6 +74,6 @@
]
},
"devDependencies": {
"@types/node": "^7.0.4"
"@types/node": "7.0.4"
}
}
}

View File

@@ -27,8 +27,8 @@ export function activate(context): void {
//settings.json suggestions
context.subscriptions.push(registerSettingsCompletions());
//extensions.json suggestions
context.subscriptions.push(registerExtensionsCompletions());
//extensions suggestions
context.subscriptions.push(...registerExtensionsCompletions());
// launch.json decorations
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => updateLaunchJsonDecorations(editor), null, context.subscriptions));
@@ -67,43 +67,69 @@ function registerSettingsCompletions(): vscode.Disposable {
});
}
function registerExtensionsCompletions(): vscode.Disposable {
interface IExtensionsContent {
recommendations: string[];
}
function registerExtensionsCompletions(): vscode.Disposable[] {
return [registerExtensionsCompletionsInExtensionsDocument(), registerExtensionsCompletionsInWorkspaceConfigurationDocument()];
}
function registerExtensionsCompletionsInExtensionsDocument(): vscode.Disposable {
return vscode.languages.registerCompletionItemProvider({ pattern: '**/extensions.json' }, {
provideCompletionItems(document, position, token) {
const location = getLocation(document.getText(), document.offsetAt(position));
const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position);
if (location.path[0] === 'recommendations') {
const config = parse(document.getText());
const alreadyEnteredExtensions = config && config.recommendations || [];
if (Array.isArray(alreadyEnteredExtensions)) {
const knownExtensionProposals = vscode.extensions.all.filter(e =>
!(e.id.startsWith('vscode.')
|| e.id === 'Microsoft.vscode-markdown'
|| alreadyEnteredExtensions.indexOf(e.id) > -1));
if (knownExtensionProposals.length) {
return knownExtensionProposals.map(e => {
const item = new vscode.CompletionItem(e.id);
const insertText = `"${e.id}"`;
item.kind = vscode.CompletionItemKind.Value;
item.insertText = insertText;
item.range = range;
item.filterText = insertText;
return item;
});
} else {
const example = new vscode.CompletionItem(localize('exampleExtension', "Example"));
example.insertText = '"vscode.csharp"';
example.kind = vscode.CompletionItemKind.Value;
example.range = range;
return [example];
}
}
const extensionsContent = <IExtensionsContent>parse(document.getText());
return provideInstalledExtensionProposals(extensionsContent, range);
}
return [];
}
});
}
function registerExtensionsCompletionsInWorkspaceConfigurationDocument(): vscode.Disposable {
return vscode.languages.registerCompletionItemProvider({ pattern: '**/*.code-workspace' }, {
provideCompletionItems(document, position, token) {
const location = getLocation(document.getText(), document.offsetAt(position));
const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position);
if (location.path[0] === 'extensions' && location.path[1] === 'recommendations') {
const extensionsContent = <IExtensionsContent>parse(document.getText())['extensions'];
return provideInstalledExtensionProposals(extensionsContent, range);
}
return [];
}
});
}
function provideInstalledExtensionProposals(extensionsContent: IExtensionsContent, range: vscode.Range): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
const alreadyEnteredExtensions = extensionsContent && extensionsContent.recommendations || [];
if (Array.isArray(alreadyEnteredExtensions)) {
const knownExtensionProposals = vscode.extensions.all.filter(e =>
!(e.id.startsWith('vscode.')
|| e.id === 'Microsoft.vscode-markdown'
|| alreadyEnteredExtensions.indexOf(e.id) > -1));
if (knownExtensionProposals.length) {
return knownExtensionProposals.map(e => {
const item = new vscode.CompletionItem(e.id);
const insertText = `"${e.id}"`;
item.kind = vscode.CompletionItemKind.Value;
item.insertText = insertText;
item.range = range;
item.filterText = insertText;
return item;
});
} else {
const example = new vscode.CompletionItem(localize('exampleExtension', "Example"));
example.insertText = '"vscode.csharp"';
example.kind = vscode.CompletionItemKind.Value;
example.range = range;
return [example];
}
}
}
function newSimpleCompletionItem(label: string, range: vscode.Range, description?: string, insertText?: string): vscode.CompletionItem {
const item = new vscode.CompletionItem(label);
item.kind = vscode.CompletionItemKind.Value;

View File

@@ -43,13 +43,13 @@ export class SettingsDocument {
private provideWindowTitleCompletionItems(location: Location, range: vscode.Range): vscode.ProviderResult<vscode.CompletionItem[]> {
const completions: vscode.CompletionItem[] = [];
completions.push(this.newSimpleCompletionItem('${activeEditorShort}', range, localize('activeEditorShort', "e.g. myFile.txt")));
completions.push(this.newSimpleCompletionItem('${activeEditorMedium}', range, localize('activeEditorMedium', "e.g. myFolder/myFile.txt")));
completions.push(this.newSimpleCompletionItem('${activeEditorLong}', range, localize('activeEditorLong', "e.g. /Users/Development/myProject/myFolder/myFile.txt")));
completions.push(this.newSimpleCompletionItem('${rootName}', range, localize('rootName', "e.g. myFolder1, myFolder2, myFolder3")));
completions.push(this.newSimpleCompletionItem('${rootPath}', range, localize('rootPath', "e.g. /Users/Development/myProject")));
completions.push(this.newSimpleCompletionItem('${folderName}', range, localize('folderName', "e.g. myFolder")));
completions.push(this.newSimpleCompletionItem('${folderPath}', range, localize('folderPath', "e.g. /Users/Development/myFolder")));
completions.push(this.newSimpleCompletionItem('${activeEditorShort}', range, localize('activeEditorShort', "the file name (e.g. myFile.txt)")));
completions.push(this.newSimpleCompletionItem('${activeEditorMedium}', range, localize('activeEditorMedium', "the path of the file relative to the workspace folder (e.g. myFolder/myFile.txt)")));
completions.push(this.newSimpleCompletionItem('${activeEditorLong}', range, localize('activeEditorLong', "the full path of the file (e.g. /Users/Development/myProject/myFolder/myFile.txt)")));
completions.push(this.newSimpleCompletionItem('${rootName}', range, localize('rootName', "name of the workspace (e.g. myFolder or myWorkspace)")));
completions.push(this.newSimpleCompletionItem('${rootPath}', range, localize('rootPath', "file path of the workspace (e.g. /Users/Development/myWorkspace)")));
completions.push(this.newSimpleCompletionItem('${folderName}', range, localize('folderName', "name of the workspace folder the file is contained in (e.g. myFolder)")));
completions.push(this.newSimpleCompletionItem('${folderPath}', range, localize('folderPath', "file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder)")));
completions.push(this.newSimpleCompletionItem('${appName}', range, localize('appName', "e.g. VS Code")));
completions.push(this.newSimpleCompletionItem('${dirty}', range, localize('dirty', "a dirty indicator if the active editor is dirty")));
completions.push(this.newSimpleCompletionItem('${separator}', range, localize('separator', "a conditional separator (' - ') that only shows when surrounded by variables with values")));

View File

@@ -5,7 +5,8 @@
"@types/node": {
"version": "6.0.78",
"from": "@types/node@>=6.0.46 <7.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.78.tgz"
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.78.tgz",
"dev": true
},
"argparse": {
"version": "1.0.9",

View File

@@ -47,6 +47,6 @@
},
"devDependencies": {
"@types/markdown-it": "0.0.2",
"@types/node": "^7.0.4"
"@types/node": "7.0.43"
}
}

View File

@@ -46,7 +46,7 @@ const _linkProvider = new class implements vscode.DocumentLinkProvider {
const offset = lookUp(match[1]);
if (offset === -1) {
console.warn(match[1]);
console.warn(`Could not find symbol for link ${match[1]}`);
continue;
}

View File

@@ -8,8 +8,7 @@ import * as path from 'path';
import { parseTree, findNodeAtLocation, Node as JsonNode } from 'jsonc-parser';
import * as nls from 'vscode-nls';
import * as MarkdownIt from 'markdown-it';
import * as parse5 from 'parse5';
import * as MarkdownItType from 'markdown-it';
import { languages, workspace, Disposable, ExtensionContext, TextDocument, Uri, Diagnostic, Range, DiagnosticSeverity, Position } from 'vscode';
@@ -33,7 +32,7 @@ enum Context {
}
interface TokenAndPosition {
token: MarkdownIt.Token;
token: MarkdownItType.Token;
begin: number;
end: number;
}
@@ -53,7 +52,7 @@ export class ExtensionLinter {
private packageJsonQ = new Set<TextDocument>();
private readmeQ = new Set<TextDocument>();
private timer: NodeJS.Timer;
private markdownIt = new MarkdownIt();
private markdownIt: MarkdownItType.MarkdownIt;
constructor(private context: ExtensionContext) {
this.disposables.push(
@@ -148,8 +147,11 @@ export class ExtensionLinter {
}
const text = document.getText();
if (!this.markdownIt) {
this.markdownIt = new (await import('markdown-it'));
}
const tokens = this.markdownIt.parse(text, {});
const tokensAndPositions = (function toTokensAndPositions(this: ExtensionLinter, tokens: MarkdownIt.Token[], begin = 0, end = text.length): TokenAndPosition[] {
const tokensAndPositions = (function toTokensAndPositions(this: ExtensionLinter, tokens: MarkdownItType.Token[], begin = 0, end = text.length): TokenAndPosition[] {
const tokensAndPositions = tokens.map<TokenAndPosition>(token => {
if (token.map) {
const tokenBegin = document.offsetAt(new Position(token.map[0], 0));
@@ -192,8 +194,9 @@ export class ExtensionLinter {
});
let svgStart: Diagnostic;
tokensAndPositions.filter(tnp => tnp.token.type === 'text' && tnp.token.content)
.map(tnp => {
for (const tnp of tokensAndPositions) {
if (tnp.token.type === 'text' && tnp.token.content) {
const parse5 = await import('parse5');
const parser = new parse5.SAXParser({ locationInfo: true });
parser.on('startTag', (name, attrs, selfClosing, location) => {
if (name === 'img') {
@@ -220,13 +223,14 @@ export class ExtensionLinter {
});
parser.write(tnp.token.content);
parser.end();
});
}
}
this.diagnosticsCollection.set(document.uri, diagnostics);
};
}
private locateToken(text: string, begin: number, end: number, token: MarkdownIt.Token, content: string) {
private locateToken(text: string, begin: number, end: number, token: MarkdownItType.Token, content: string) {
if (content) {
const tokenBegin = text.indexOf(content, begin);
if (tokenBegin !== -1) {

View File

@@ -7,13 +7,18 @@
"from": "applicationinsights@0.18.0",
"resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz"
},
"byline": {
"version": "5.0.0",
"from": "byline@latest",
"resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz"
},
"iconv-lite": {
"version": "0.4.15",
"from": "iconv-lite@0.4.15",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz"
},
"vscode-extension-telemetry": {
"version": "0.0.7",
"version": "0.0.8",
"from": "vscode-extension-telemetry@>=0.0.8 <0.0.9",
"resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz"
},

View File

@@ -36,6 +36,11 @@
"dark": "resources/icons/dark/git.svg"
}
},
{
"command": "git.close",
"title": "%command.close%",
"category": "Git"
},
{
"command": "git.refresh",
"title": "%command.refresh%",
@@ -96,6 +101,24 @@
"title": "%command.revertSelectedRanges%",
"category": "Git"
},
{
"command": "git.stageChange",
"title": "%command.stageChange%",
"category": "Git",
"icon": {
"light": "resources/icons/light/stage.svg",
"dark": "resources/icons/dark/stage.svg"
}
},
{
"command": "git.revertChange",
"title": "%command.revertChange%",
"category": "Git",
"icon": {
"light": "resources/icons/light/clean.svg",
"dark": "resources/icons/dark/clean.svg"
}
},
{
"command": "git.unstage",
"title": "%command.unstage%",
@@ -310,10 +333,18 @@
"command": "git.stageSelectedRanges",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stageChange",
"when": "false"
},
{
"command": "git.revertSelectedRanges",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.revertChange",
"when": "false"
},
{
"command": "git.unstage",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
@@ -529,6 +560,11 @@
"group": "3_commit",
"when": "config.git.enabled && scmProvider == git"
},
{
"command": "git.stageAll",
"group": "4_stage",
"when": "config.git.enabled && scmProvider == git"
},
{
"command": "git.unstageAll",
"group": "4_stage",
@@ -560,6 +596,13 @@
"when": "config.git.enabled && scmProvider == git"
}
],
"scm/sourceControl": [
{
"command": "git.close",
"group": "navigation",
"when": "config.git.enabled && scmProvider == git"
}
],
"scm/resourceGroup/context": [
{
"command": "git.stageAll",
@@ -688,7 +731,7 @@
{
"command": "git.openChange",
"group": "navigation",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme != extension"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme == file"
},
{
"command": "git.stageSelectedRanges",
@@ -705,6 +748,16 @@
"group": "2_git@3",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != merge-conflict.conflict-diff"
}
],
"scm/change/title": [
{
"command": "git.stageChange",
"when": "config.git.enabled && originalResourceScheme == git"
},
{
"command": "git.revertChange",
"when": "config.git.enabled && originalResourceScheme == git"
}
]
},
"configuration": {
@@ -784,18 +837,71 @@
"type": "boolean",
"description": "%config.enableCommitSigning%",
"default": false
},
"git.decorations.enabled": {
"type": "boolean",
"default": true,
"description": "%config.decorations.enabled%"
}
}
}
},
"colors": [
{
"id": "gitDecoration.modifiedResourceForeground",
"description": "%colors.modified%",
"defaults": {
"light": "#a76e12",
"dark": "#E2C08D",
"highContrast": "#E2C08D"
}
},
{
"id": "gitDecoration.deletedResourceForeground",
"description": "%colors.deleted%",
"defaults": {
"light": "#ad0707",
"dark": "#c74e39",
"highContrast": "#c74e39"
}
},
{
"id": "gitDecoration.untrackedResourceForeground",
"description": "%colors.untracked%",
"defaults": {
"light": "#019001",
"dark": "#73C991",
"highContrast": "#73C991"
}
},
{
"id": "gitDecoration.ignoredResourceForeground",
"description": "%colors.ignored%",
"defaults": {
"light": "#8E8E90",
"dark": "#A7A8A9",
"highContrast": "#A7A8A9"
}
},
{
"id": "gitDecoration.conflictingResourceForeground",
"description": "%colors.conflict%",
"defaults": {
"light": "#6c6cc4",
"dark": "#6c6cc4",
"highContrast": "#6c6cc4"
}
}
]
},
"dependencies": {
"byline": "^5.0.0",
"iconv-lite": "0.4.15",
"vscode-extension-telemetry": "0.0.8",
"vscode-nls": "2.0.2"
},
"devDependencies": {
"@types/mocha": "^2.2.41",
"@types/node": "^7.0.4",
"@types/mocha": "2.2.43",
"@types/node": "7.0.43",
"mocha": "^3.2.0"
}
}

View File

@@ -10,6 +10,8 @@
"command.stageAll": "Stage All Changes",
"command.stageSelectedRanges": "Stage Selected Ranges",
"command.revertSelectedRanges": "Revert Selected Ranges",
"command.stageChange": "Stage Change",
"command.revertChange": "Revert Change",
"command.unstage": "Unstage Changes",
"command.unstageAll": "Unstage All Changes",
"command.unstageSelectedRanges": "Unstage Selected Ranges",
@@ -54,5 +56,11 @@
"config.defaultCloneDirectory": "The default location where to clone a git repository",
"config.enableSmartCommit": "Commit all changes when there are no staged changes.",
"config.enableCommitSigning": "Enables commit signing with GPG.",
"config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run."
}
"config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.",
"config.decorations.enabled": "Controls if Git contributes colors and badges to the explorer and the open editors view.",
"colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.",
"colors.untracked": "Color for untracked resources.",
"colors.ignored": "Color for ignored resources.",
"colors.conflict": "Color for resources with conflicts."
}

View File

@@ -5,16 +5,23 @@
'use strict';
import { workspace, Disposable } from 'vscode';
import { workspace, Disposable, EventEmitter } from 'vscode';
import { GitErrorCodes } from './git';
import { Repository } from './repository';
import { throttle } from './decorators';
import { eventToPromise, filterEvent } from './util';
export class AutoFetcher {
private static Period = 3 * 60 * 1000 /* three minutes */;
private _onDidChange = new EventEmitter<boolean>();
private onDidChange = this._onDidChange.event;
private _enabled: boolean = false;
get enabled(): boolean { return this._enabled; }
set enabled(enabled: boolean) { this._enabled = enabled; this._onDidChange.fire(enabled); }
private disposables: Disposable[] = [];
private timer: NodeJS.Timer;
constructor(private repository: Repository) {
workspace.onDidChangeConfiguration(this.onConfiguration, this, this.disposables);
@@ -32,26 +39,41 @@ export class AutoFetcher {
}
enable(): void {
if (this.timer) {
if (this.enabled) {
return;
}
this.fetch();
this.timer = setInterval(() => this.fetch(), AutoFetcher.Period);
this.enabled = true;
this.run();
}
disable(): void {
clearInterval(this.timer);
this.enabled = false;
}
@throttle
private async fetch(): Promise<void> {
try {
await this.repository.fetch();
} catch (err) {
if (err.gitErrorCode === GitErrorCodes.AuthenticationFailed) {
this.disable();
private async run(): Promise<void> {
while (this.enabled) {
await this.repository.whenIdleAndFocused();
if (!this.enabled) {
return;
}
try {
await this.repository.fetch();
} catch (err) {
if (err.gitErrorCode === GitErrorCodes.AuthenticationFailed) {
this.disable();
}
}
if (!this.enabled) {
return;
}
const timeout = new Promise(c => setTimeout(c, AutoFetcher.Period));
const whenDisabled = eventToPromise(filterEvent(this.onDidChange, enabled => !enabled));
await Promise.race([timeout, whenDisabled]);
}
}

View File

@@ -5,11 +5,12 @@
'use strict';
import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation } from 'vscode';
import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor } from 'vscode';
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 * as path from 'path';
import * as os from 'os';
@@ -92,11 +93,13 @@ class MergeItem implements QuickPickItem {
class CreateBranchItem implements QuickPickItem {
constructor(private cc: CommandCenter) { }
get label(): string { return localize('create branch', '$(plus) Create new branch'); }
get description(): string { return ''; }
async run(repository: Repository): Promise<void> {
await commands.executeCommand('git.branch');
await this.cc.branch(repository);
}
}
@@ -169,12 +172,14 @@ export class CommandCenter {
const opts: TextDocumentShowOptions = {
preserveFocus,
preview,
viewColumn: window.activeTextEditor && window.activeTextEditor.viewColumn || ViewColumn.One
viewColumn: ViewColumn.Active
};
const activeTextEditor = window.activeTextEditor;
if (preserveSelection && activeTextEditor && activeTextEditor.document.uri.fsPath === right.fsPath) {
// Check if active text editor has same path as other editor. we cannot compare via
// URI.toString() here because the schemas can be different. Instead we just go by path.
if (preserveSelection && activeTextEditor && activeTextEditor.document.uri.path === right.path) {
opts.selection = activeTextEditor.selection;
}
@@ -257,13 +262,20 @@ export class CommandCenter {
}
@command('git.clone')
async clone(): Promise<void> {
const url = await window.showInputBox({
prompt: localize('repourl', "Repository URL"),
ignoreFocusOut: true
});
async clone(url?: string): Promise<void> {
if (!url) {
url = await window.showInputBox({
prompt: localize('repourl', "Repository URL"),
ignoreFocusOut: true
});
}
if (!url) {
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_URL' });
return;
}
@@ -278,6 +290,11 @@ export class CommandCenter {
});
if (!parentPath) {
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_directory' });
return;
}
@@ -295,14 +312,30 @@ export class CommandCenter {
const result = await window.showInformationMessage(localize('proposeopen', "Would you like to open the cloned repository?"), open);
const openFolder = result === open;
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"openFolder": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'success' }, { openFolder: openFolder ? 1 : 0 });
if (openFolder) {
commands.executeCommand('vscode.openFolder', Uri.file(repositoryPath));
}
} catch (err) {
if (/already exists and is not an empty directory/.test(err && err.stderr || '')) {
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'directory_not_empty' });
} else {
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'error' });
}
throw err;
@@ -311,25 +344,44 @@ export class CommandCenter {
@command('git.init')
async init(): Promise<void> {
const value = workspace.workspaceFolders && workspace.workspaceFolders.length > 0
? workspace.workspaceFolders[0].uri.fsPath
: os.homedir();
const homeUri = Uri.file(os.homedir());
const defaultUri = workspace.workspaceFolders && workspace.workspaceFolders.length > 0
? Uri.file(workspace.workspaceFolders[0].uri.fsPath)
: homeUri;
const path = await window.showInputBox({
placeHolder: localize('path to init', "Folder path"),
prompt: localize('provide path', "Please provide a folder path to initialize a Git repository"),
value,
ignoreFocusOut: true
const result = await window.showOpenDialog({
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
defaultUri,
openLabel: localize('init repo', "Initialize Repository")
});
if (!path) {
if (!result || result.length === 0) {
return;
}
const uri = result[0];
if (homeUri.toString().startsWith(uri.toString())) {
const yes = localize('create repo', "Initialize Repository");
const answer = await window.showWarningMessage(localize('are you sure', "This will create a Git repository in '{0}'. Are you sure you want to continue?", uri.fsPath), yes);
if (answer !== yes) {
return;
}
}
const path = uri.fsPath;
await this.git.init(path);
await this.model.tryOpenRepository(path);
}
@command('git.close', { repository: true })
async close(repository: Repository): Promise<void> {
this.model.close(repository);
}
@command('git.openFile')
async openFile(arg?: Resource | Uri, ...resourceStates: SourceControlResourceState[]): Promise<void> {
const preserveFocus = arg instanceof Resource;
@@ -364,11 +416,13 @@ export class CommandCenter {
for (const uri of uris) {
const opts: TextDocumentShowOptions = {
preserveFocus,
preview: preview,
viewColumn: activeTextEditor && activeTextEditor.viewColumn || ViewColumn.One
preview,
viewColumn: ViewColumn.Active
};
if (activeTextEditor && activeTextEditor.document.uri.fsPath === uri.fsPath) {
// Check if active text editor has same path as other editor. we cannot compare via
// URI.toString() here because the schemas can be different. Instead we just go by path.
if (activeTextEditor && activeTextEditor.document.uri.path === uri.path) {
opts.selection = activeTextEditor.selection;
}
@@ -451,12 +505,20 @@ export class CommandCenter {
}
const selection = resourceStates.filter(s => s instanceof Resource) as Resource[];
const mergeConflicts = selection.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
const merge = selection.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
const bothModified = merge.filter(s => s.type === Status.BOTH_MODIFIED);
const promises = bothModified.map(s => grep(s.resourceUri.fsPath, /^<{7}|^={7}|^>{7}/));
const unresolvedBothModified = await Promise.all<boolean>(promises);
const resolvedConflicts = bothModified.filter((s, i) => !unresolvedBothModified[i]);
const unresolvedConflicts = [
...merge.filter(s => s.type !== Status.BOTH_MODIFIED),
...bothModified.filter((s, i) => unresolvedBothModified[i])
];
if (mergeConflicts.length > 0) {
const message = mergeConflicts.length > 1
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", mergeConflicts.length)
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(mergeConflicts[0].resourceUri.fsPath));
if (unresolvedConflicts.length > 0) {
const message = unresolvedConflicts.length > 1
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", unresolvedConflicts.length)
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(unresolvedConflicts[0].resourceUri.fsPath));
const yes = localize('yes', "Yes");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
@@ -466,10 +528,8 @@ export class CommandCenter {
}
}
const workingTree = selection
.filter(s => s.resourceGroupType === ResourceGroupType.WorkingTree);
const scmResources = [...workingTree, ...mergeConflicts];
const workingTree = selection.filter(s => s.resourceGroupType === ResourceGroupType.WorkingTree);
const scmResources = [...workingTree, ...resolvedConflicts, ...unresolvedConflicts];
if (!scmResources.length) {
return;
@@ -500,14 +560,39 @@ export class CommandCenter {
await repository.add([]);
}
@command('git.stageChange')
async stageChange(uri: Uri, changes: LineChange[], index: number): Promise<void> {
const textEditor = window.visibleTextEditors.filter(e => e.document.uri.toString() === uri.toString())[0];
if (!textEditor) {
return;
}
await this._stageChanges(textEditor, [changes[index]]);
}
@command('git.stageSelectedRanges', { diff: true })
async stageSelectedRanges(diffs: LineChange[]): Promise<void> {
async stageSelectedChanges(changes: LineChange[]): Promise<void> {
const textEditor = window.activeTextEditor;
if (!textEditor) {
return;
}
const modifiedDocument = textEditor.document;
const selectedLines = toLineRanges(textEditor.selections, modifiedDocument);
const selectedChanges = changes
.map(diff => selectedLines.reduce<LineChange | null>((result, range) => result || intersectDiffWithRange(modifiedDocument, diff, range), null))
.filter(d => !!d) as LineChange[];
if (!selectedChanges.length) {
return;
}
await this._stageChanges(textEditor, selectedChanges);
}
private async _stageChanges(textEditor: TextEditor, changes: LineChange[]): Promise<void> {
const modifiedDocument = textEditor.document;
const modifiedUri = modifiedDocument.uri;
@@ -517,28 +602,48 @@ export class CommandCenter {
const originalUri = toGitUri(modifiedUri, '~');
const originalDocument = await workspace.openTextDocument(originalUri);
const selectedLines = toLineRanges(textEditor.selections, modifiedDocument);
const selectedDiffs = diffs
.map(diff => selectedLines.reduce<LineChange | null>((result, range) => result || intersectDiffWithRange(modifiedDocument, diff, range), null))
.filter(d => !!d) as LineChange[];
if (!selectedDiffs.length) {
return;
}
const result = applyLineChanges(originalDocument, modifiedDocument, selectedDiffs);
const result = applyLineChanges(originalDocument, modifiedDocument, changes);
await this.runByRepository(modifiedUri, async (repository, resource) => await repository.stage(resource, result));
}
@command('git.revertChange')
async revertChange(uri: Uri, changes: LineChange[], index: number): Promise<void> {
const textEditor = window.visibleTextEditors.filter(e => e.document.uri.toString() === uri.toString())[0];
if (!textEditor) {
return;
}
await this._revertChanges(textEditor, [...changes.slice(0, index), ...changes.slice(index + 1)]);
}
@command('git.revertSelectedRanges', { diff: true })
async revertSelectedRanges(diffs: LineChange[]): Promise<void> {
async revertSelectedRanges(changes: LineChange[]): Promise<void> {
const textEditor = window.activeTextEditor;
if (!textEditor) {
return;
}
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);
return selections.every(selection => !selection.intersection(modifiedRange));
});
if (selectedChanges.length === changes.length) {
return;
}
await this._revertChanges(textEditor, selectedChanges);
}
private async _revertChanges(textEditor: TextEditor, changes: LineChange[]): Promise<void> {
const modifiedDocument = textEditor.document;
const modifiedUri = modifiedDocument.uri;
@@ -548,19 +653,6 @@ export class CommandCenter {
const originalUri = toGitUri(modifiedUri, '~');
const originalDocument = await workspace.openTextDocument(originalUri);
const selections = textEditor.selections;
const selectedDiffs = diffs.filter(diff => {
const modifiedRange = diff.modifiedEndLineNumber === 0
? new Range(modifiedDocument.lineAt(diff.modifiedStartLineNumber - 1).range.end, modifiedDocument.lineAt(diff.modifiedStartLineNumber).range.start)
: new Range(modifiedDocument.lineAt(diff.modifiedStartLineNumber - 1).range.start, modifiedDocument.lineAt(diff.modifiedEndLineNumber - 1).range.end);
return selections.every(selection => !selection.intersection(modifiedRange));
});
if (selectedDiffs.length === diffs.length) {
return;
}
const basename = path.basename(modifiedUri.fsPath);
const message = localize('confirm revert', "Are you sure you want to revert the selected changes in {0}?", basename);
const yes = localize('revert', "Revert Changes");
@@ -570,10 +662,11 @@ export class CommandCenter {
return;
}
const result = applyLineChanges(originalDocument, modifiedDocument, selectedDiffs);
const result = applyLineChanges(originalDocument, modifiedDocument, changes);
const edit = new WorkspaceEdit();
edit.replace(modifiedUri, new Range(new Position(0, 0), modifiedDocument.lineAt(modifiedDocument.lineCount - 1).range.end), result);
workspace.applyEdit(edit);
await modifiedDocument.save();
}
@command('git.unstage')
@@ -909,7 +1002,7 @@ export class CommandCenter {
const includeTags = checkoutType === 'all' || checkoutType === 'tags';
const includeRemotes = checkoutType === 'all' || checkoutType === 'remote';
const createBranch = new CreateBranchItem();
const createBranch = new CreateBranchItem(this);
const heads = repository.refs.filter(ref => ref.type === RefType.Head)
.map(ref => new CheckoutItem(ref));
@@ -1174,6 +1267,19 @@ export class CommandCenter {
await repository.sync();
}
@command('git._syncAll')
async syncAll(): Promise<void> {
await Promise.all(this.model.repositories.map(async repository => {
const HEAD = repository.HEAD;
if (!HEAD || !HEAD.upstream) {
return;
}
await repository.sync();
}));
}
@command('git.publish', { repository: true })
async publish(repository: Repository): Promise<void> {
const remotes = repository.remotes;
@@ -1184,9 +1290,12 @@ export class CommandCenter {
}
const branchName = repository.HEAD && repository.HEAD.name || '';
const picks = repository.remotes.map(r => r.name);
const placeHolder = localize('pick remote', "Pick a remote to publish the branch '{0}' to:", branchName);
const choice = await window.showQuickPick(picks, { placeHolder });
const selectRemote = async () => {
const picks = repository.remotes.map(r => r.name);
const placeHolder = localize('pick remote', "Pick a remote to publish the branch '{0}' to:", branchName);
return await window.showQuickPick(picks, { placeHolder });
};
const choice = remotes.length === 1 ? remotes[0].name : await selectRemote();
if (!choice) {
return;
@@ -1200,27 +1309,27 @@ export class CommandCenter {
this.outputChannel.show();
}
@command('git.ignore', { repository: true })
async ignore(repository: Repository, ...resourceStates: SourceControlResourceState[]): Promise<void> {
@command('git.ignore')
async ignore(...resourceStates: SourceControlResourceState[]): Promise<void> {
if (resourceStates.length === 0 || !(resourceStates[0].resourceUri instanceof Uri)) {
const uri = window.activeTextEditor && window.activeTextEditor.document.uri;
const resource = this.getSCMResource();
if (!uri) {
if (!resource) {
return;
}
return await repository.ignore([uri]);
resourceStates = [resource];
}
const uris = resourceStates
const resources = resourceStates
.filter(s => s instanceof Resource)
.map(r => r.resourceUri);
if (!uris.length) {
if (!resources.length) {
return;
}
await repository.ignore(uris);
await this.runByRepository(resources, async (repository, resources) => repository.ignore(resources));
}
@command('git.stash', { repository: true })
@@ -1302,6 +1411,11 @@ export class CommandCenter {
});
}
/* __GDPR__
"git.command" : {
"command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryReporter.sendTelemetryEvent('git.command', { command: id });
return result.catch(async err => {
@@ -1389,7 +1503,7 @@ export class CommandCenter {
return result;
}
const tuple = result.filter(p => p[0] === repository)[0];
const tuple = result.filter(p => p.repository === repository)[0];
if (tuple) {
tuple.resources.push(resource);

View File

@@ -6,9 +6,10 @@
'use strict';
import { workspace, Uri, Disposable, Event, EventEmitter, window } from 'vscode';
import { debounce } from './decorators';
import { fromGitUri } from './uri';
import { Model, ModelChangeEvent } from './model';
import { debounce, throttle } from './decorators';
import { fromGitUri, toGitUri } from './uri';
import { Model, ModelChangeEvent, OriginalResourceChangeEvent } from './model';
import { filterEvent, eventToPromise } from './util';
interface CacheRow {
uri: Uri;
@@ -24,8 +25,8 @@ const FIVE_MINUTES = 1000 * 60 * 5;
export class GitContentProvider {
private onDidChangeEmitter = new EventEmitter<Uri>();
get onDidChange(): Event<Uri> { return this.onDidChangeEmitter.event; }
private _onDidChange = new EventEmitter<Uri>();
get onDidChange(): Event<Uri> { return this._onDidChange.event; }
private changedRepositoryRoots = new Set<string>();
private cache: Cache = Object.create(null);
@@ -34,6 +35,7 @@ export class GitContentProvider {
constructor(private model: Model) {
this.disposables.push(
model.onDidChangeRepository(this.onDidChangeRepository, this),
model.onDidChangeOriginalResource(this.onDidChangeOriginalResource, this),
workspace.registerTextDocumentContentProvider('git', this)
);
@@ -45,19 +47,33 @@ export class GitContentProvider {
this.eventuallyFireChangeEvents();
}
private onDidChangeOriginalResource({ uri }: OriginalResourceChangeEvent): void {
if (uri.scheme !== 'file') {
return;
}
this._onDidChange.fire(toGitUri(uri, '', true));
}
@debounce(1100)
private eventuallyFireChangeEvents(): void {
this.fireChangeEvents();
}
private fireChangeEvents(): void {
@throttle
private async fireChangeEvents(): Promise<void> {
if (!window.state.focused) {
const onDidFocusWindow = filterEvent(window.onDidChangeWindowState, e => e.focused);
await eventToPromise(onDidFocusWindow);
}
Object.keys(this.cache).forEach(key => {
const uri = this.cache[key].uri;
const fsPath = uri.fsPath;
for (const root of this.changedRepositoryRoots) {
if (fsPath.startsWith(root)) {
this.onDidChangeEmitter.fire(uri);
this._onDidChange.fire(uri);
return;
}
}
@@ -75,7 +91,7 @@ export class GitContentProvider {
const cacheKey = uri.toString();
const timestamp = new Date().getTime();
const cacheValue = { uri, timestamp };
const cacheValue: CacheRow = { uri, timestamp };
this.cache[cacheKey] = cacheValue;
@@ -101,7 +117,10 @@ export class GitContentProvider {
Object.keys(this.cache).forEach(key => {
const row = this.cache[key];
const isOpen = window.visibleTextEditors.some(e => e.document.uri.fsPath === row.uri.fsPath);
const { path } = fromGitUri(row.uri);
const isOpen = workspace.textDocuments
.filter(d => d.uri.scheme === 'file')
.some(d => d.uri.fsPath === path);
if (isOpen || now - row.timestamp < THREE_MINUTES) {
cache[row.uri.toString()] = row;

View File

@@ -0,0 +1,173 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { window, workspace, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider, ThemeColor } from 'vscode';
import { Repository, GitResourceGroup } from './repository';
import { Model } from './model';
import { debounce } from './decorators';
import { filterEvent } from './util';
class GitIgnoreDecorationProvider implements DecorationProvider {
private readonly _onDidChangeDecorations = new EventEmitter<Uri[]>();
readonly onDidChangeDecorations: Event<Uri[]> = this._onDidChangeDecorations.event;
private checkIgnoreQueue = new Map<string, { resolve: (status: boolean) => void, reject: (err: any) => void }>();
private disposables: Disposable[] = [];
constructor(private repository: Repository) {
this.disposables.push(
window.registerDecorationProvider(this),
filterEvent(workspace.onDidSaveTextDocument, e => e.fileName.endsWith('.gitignore'))(_ => this._onDidChangeDecorations.fire())
//todo@joh -> events when the ignore status actually changes, not only when the file changes
);
}
dispose(): void {
this.disposables.forEach(d => d.dispose());
this.checkIgnoreQueue.clear();
}
provideDecoration(uri: Uri): Promise<DecorationData | undefined> {
return new Promise<boolean>((resolve, reject) => {
this.checkIgnoreQueue.set(uri.fsPath, { resolve, reject });
this.checkIgnoreSoon();
}).then(ignored => {
if (ignored) {
return <DecorationData>{
priority: 3,
color: new ThemeColor('gitDecoration.ignoredResourceForeground')
};
}
});
}
@debounce(500)
private checkIgnoreSoon(): void {
const queue = new Map(this.checkIgnoreQueue.entries());
this.checkIgnoreQueue.clear();
this.repository.checkIgnore([...queue.keys()]).then(ignoreSet => {
for (const [key, value] of queue.entries()) {
value.resolve(ignoreSet.has(key));
}
}, err => {
console.error(err);
for (const [, value] of queue.entries()) {
value.reject(err);
}
});
}
}
class GitDecorationProvider implements DecorationProvider {
private readonly _onDidChangeDecorations = new EventEmitter<Uri[]>();
readonly onDidChangeDecorations: Event<Uri[]> = this._onDidChangeDecorations.event;
private disposables: Disposable[] = [];
private decorations = new Map<string, DecorationData>();
constructor(private repository: Repository) {
this.disposables.push(
window.registerDecorationProvider(this),
repository.onDidRunOperation(this.onDidRunOperation, this)
);
}
private onDidRunOperation(): void {
let newDecorations = new Map<string, DecorationData>();
this.collectDecorationData(this.repository.indexGroup, newDecorations);
this.collectDecorationData(this.repository.workingTreeGroup, newDecorations);
this.collectDecorationData(this.repository.mergeGroup, newDecorations);
let uris: Uri[] = [];
newDecorations.forEach((value, uriString) => {
if (this.decorations.has(uriString)) {
this.decorations.delete(uriString);
} else {
uris.push(Uri.parse(uriString));
}
});
this.decorations.forEach((value, uriString) => {
uris.push(Uri.parse(uriString));
});
this.decorations = newDecorations;
this._onDidChangeDecorations.fire(uris);
}
private collectDecorationData(group: GitResourceGroup, bucket: Map<string, DecorationData>): void {
group.resourceStates.forEach(r => {
if (r.resourceDecoration) {
bucket.set(r.original.toString(), r.resourceDecoration);
}
});
}
provideDecoration(uri: Uri): DecorationData | undefined {
return this.decorations.get(uri.toString());
}
dispose(): void {
this.disposables.forEach(d => d.dispose());
}
}
export class GitDecorations {
private configListener: Disposable;
private modelListener: Disposable[] = [];
private providers = new Map<Repository, Disposable>();
constructor(private model: Model) {
this.configListener = workspace.onDidChangeConfiguration(e => e.affectsConfiguration('git.decorations.enabled') && this.update());
this.update();
}
private update(): void {
const enabled = workspace.getConfiguration('git').get('decorations.enabled');
if (enabled) {
this.enable();
} else {
this.disable();
}
}
private enable(): void {
this.modelListener = [];
this.model.onDidOpenRepository(this.onDidOpenRepository, this, this.modelListener);
this.model.onDidCloseRepository(this.onDidCloseRepository, this, this.modelListener);
this.model.repositories.forEach(this.onDidOpenRepository, this);
}
private disable(): void {
this.modelListener.forEach(d => d.dispose());
this.providers.forEach(value => value.dispose());
this.providers.clear();
}
private onDidOpenRepository(repository: Repository): void {
const provider = new GitDecorationProvider(repository);
const ignoreProvider = new GitIgnoreDecorationProvider(repository);
this.providers.set(repository, Disposable.from(provider, ignoreProvider));
}
private onDidCloseRepository(repository: Repository): void {
const provider = this.providers.get(repository);
if (provider) {
provider.dispose();
this.providers.delete(repository);
}
}
dispose(): void {
this.configListener.dispose();
this.modelListener.forEach(d => d.dispose());
this.providers.forEach(value => value.dispose);
this.providers.clear();
}
}

View File

@@ -13,7 +13,6 @@ import { EventEmitter } from 'events';
import iconv = require('iconv-lite');
import { assign, uniqBy, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp } from './util';
const readdir = denodeify<string[]>(fs.readdir);
const readfile = denodeify<string>(fs.readFile);
export interface IGit {
@@ -66,7 +65,7 @@ function findSpecificGit(path: string): Promise<IGit> {
const buffers: Buffer[] = [];
const child = cp.spawn(path, ['--version']);
child.stdout.on('data', (b: Buffer) => buffers.push(b));
child.on('error', e);
child.on('error', cpErrorHandler(e));
child.on('exit', code => code ? e(new Error('Not found')) : c({ path, version: parseVersion(Buffer.concat(buffers).toString('utf8').trim()) }));
});
}
@@ -82,12 +81,12 @@ function findGitDarwin(): Promise<IGit> {
function getVersion(path: string) {
// make sure git executes
cp.exec('git --version', (err, stdout: Buffer) => {
cp.exec('git --version', (err, stdout) => {
if (err) {
return e('git not found');
}
return c({ path, version: parseVersion(stdout.toString('utf8').trim()) });
return c({ path, version: parseVersion(stdout.trim()) });
});
}
@@ -118,48 +117,54 @@ function findSystemGitWin32(base: string): Promise<IGit> {
return findSpecificGit(path.join(base, 'Git', 'cmd', 'git.exe'));
}
function findGitHubGitWin32(): Promise<IGit> {
const github = path.join(process.env['LOCALAPPDATA'], 'GitHub');
return readdir(github).then(children => {
const git = children.filter(child => /^PortableGit/.test(child))[0];
if (!git) {
return Promise.reject<IGit>('Not found');
}
return findSpecificGit(path.join(github, git, 'cmd', 'git.exe'));
});
}
function findGitWin32(): Promise<IGit> {
return findSystemGitWin32(process.env['ProgramW6432'])
.then(void 0, () => findSystemGitWin32(process.env['ProgramFiles(x86)']))
.then(void 0, () => findSystemGitWin32(process.env['ProgramFiles']))
.then(void 0, () => findSpecificGit('git'))
.then(void 0, () => findGitHubGitWin32());
.then(void 0, () => findSpecificGit('git'));
}
export function findGit(hint: string | undefined): Promise<IGit> {
var first = hint ? findSpecificGit(hint) : Promise.reject<IGit>(null);
return first.then(void 0, () => {
switch (process.platform) {
case 'darwin': return findGitDarwin();
case 'win32': return findGitWin32();
default: return findSpecificGit('git');
}
});
return first
.then(void 0, () => {
switch (process.platform) {
case 'darwin': return findGitDarwin();
case 'win32': return findGitWin32();
default: return findSpecificGit('git');
}
})
.then(null, () => Promise.reject(new Error('Git installation not found.')));
}
export interface IExecutionResult {
exitCode: number;
stdout: string;
stderr: string;
}
async function exec(child: cp.ChildProcess, options: any = {}): Promise<IExecutionResult> {
function cpErrorHandler(cb: (reason?: any) => void): (reason?: any) => void {
return err => {
if (/ENOENT/.test(err.message)) {
err = new GitError({
error: err,
message: 'Failed to execute git (ENOENT)',
gitErrorCode: GitErrorCodes.NotAGitRepository
});
}
cb(err);
};
}
export interface SpawnOptions extends cp.SpawnOptions {
input?: string;
encoding?: string;
log?: boolean;
}
async function exec(child: cp.ChildProcess, options: SpawnOptions = {}): Promise<IExecutionResult> {
if (!child.stdout || !child.stderr) {
throw new GitError({
message: 'Failed to get stdout or stderr from git process.'
@@ -183,7 +188,7 @@ async function exec(child: cp.ChildProcess, options: any = {}): Promise<IExecuti
const [exitCode, stdout, stderr] = await Promise.all<any>([
new Promise<number>((c, e) => {
once(child, 'error', e);
once(child, 'error', cpErrorHandler(e));
once(child, 'exit', c);
}),
new Promise<string>(c => {
@@ -246,7 +251,7 @@ export class GitError {
gitCommand: this.gitCommand,
stdout: this.stdout,
stderr: this.stderr
}, [], 2);
}, null, 2);
if (this.error) {
result += (<any>this.error).stack;
@@ -350,17 +355,17 @@ export class Git {
return path.normalize(result.stdout.trim());
}
async exec(cwd: string, args: string[], options: any = {}): Promise<IExecutionResult> {
async exec(cwd: string, args: string[], options: SpawnOptions = {}): Promise<IExecutionResult> {
options = assign({ cwd }, options || {});
return await this._exec(args, options);
}
stream(cwd: string, args: string[], options: any = {}): cp.ChildProcess {
stream(cwd: string, args: string[], options: SpawnOptions = {}): cp.ChildProcess {
options = assign({ cwd }, options || {});
return this.spawn(args, options);
}
private async _exec(args: string[], options: any = {}): Promise<IExecutionResult> {
private async _exec(args: string[], options: SpawnOptions = {}): Promise<IExecutionResult> {
const child = this.spawn(args, options);
if (options.input) {
@@ -387,7 +392,7 @@ export class Git {
return result;
}
spawn(args: string[], options: any = {}): cp.ChildProcess {
spawn(args: string[], options: SpawnOptions = {}): cp.ChildProcess {
if (!this.gitPath) {
throw new Error('git could not be found in the system.');
}
@@ -505,19 +510,19 @@ export class Repository {
}
// TODO@Joao: rename to exec
async run(args: string[], options: any = {}): Promise<IExecutionResult> {
async run(args: string[], options: SpawnOptions = {}): Promise<IExecutionResult> {
return await this.git.exec(this.repositoryRoot, args, options);
}
stream(args: string[], options: any = {}): cp.ChildProcess {
stream(args: string[], options: SpawnOptions = {}): cp.ChildProcess {
return this.git.stream(this.repositoryRoot, args, options);
}
spawn(args: string[], options: any = {}): cp.ChildProcess {
spawn(args: string[], options: SpawnOptions = {}): cp.ChildProcess {
return this.git.spawn(args, options);
}
async config(scope: string, key: string, value: any, options: any): Promise<string> {
async config(scope: string, key: string, value: any, options: SpawnOptions): Promise<string> {
const args = ['config'];
if (scope) {
@@ -883,7 +888,8 @@ export class Repository {
getStatus(limit = 5000): Promise<{ status: IFileStatus[]; didHitLimit: boolean; }> {
return new Promise<{ status: IFileStatus[]; didHitLimit: boolean; }>((c, e) => {
const parser = new GitStatusParser();
const child = this.stream(['status', '-z', '-u']);
const env = { GIT_OPTIONAL_LOCKS: '0' };
const child = this.stream(['status', '-z', '-u'], { env });
const onExit = exitCode => {
if (exitCode !== 0) {
@@ -919,7 +925,7 @@ export class Repository {
child.stderr.setEncoding('utf8');
child.stderr.on('data', raw => stderrData.push(raw as string));
child.on('error', e);
child.on('error', cpErrorHandler(e));
child.on('exit', onExit);
});
}

View File

@@ -12,6 +12,7 @@ import { findGit, Git, IGit } from './git';
import { Model } from './model';
import { CommandCenter } from './commands';
import { GitContentProvider } from './contentProvider';
import { GitDecorations } from './decorationProvider';
import { Askpass } from './askpass';
import { toDisposable } from './util';
import TelemetryReporter from 'vscode-extension-telemetry';
@@ -54,6 +55,7 @@ async function init(context: ExtensionContext, disposables: Disposable[]): Promi
disposables.push(
new CommandCenter(git, model, outputChannel, telemetryReporter),
new GitContentProvider(model),
new GitDecorations(model)
);
await checkGitVersion(info);
@@ -70,7 +72,7 @@ export function activate(context: ExtensionContext): any {
async function checkGitVersion(info: IGit): Promise<void> {
// {{SQL CARBON EDIT}}
// remove Git version check on since for Carbon
// remove Git version check for sqlops
return;
@@ -101,4 +103,4 @@ async function checkGitVersion(info: IGit): Promise<void> {
await config.update('ignoreLegacyWarning', true, true);
}
*/
}
}

View File

@@ -17,8 +17,16 @@ import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
class RepositoryPick implements QuickPickItem {
@memoize get label(): string { return path.basename(this.repository.root); }
@memoize get description(): string { return path.dirname(this.repository.root); }
@memoize get label(): string {
return path.basename(this.repository.root);
}
@memoize get description(): string {
return [this.repository.headLabel, this.repository.syncLabel]
.filter(l => !!l)
.join(' ');
}
constructor(public readonly repository: Repository) { }
}
@@ -27,10 +35,19 @@ export interface ModelChangeEvent {
uri: Uri;
}
export interface OriginalResourceChangeEvent {
repository: Repository;
uri: Uri;
}
interface OpenRepository extends Disposable {
repository: Repository;
}
function isParent(parent: string, child: string): boolean {
return child.startsWith(parent);
}
export class Model {
private _onDidOpenRepository = new EventEmitter<Repository>();
@@ -42,6 +59,9 @@ export class Model {
private _onDidChangeRepository = new EventEmitter<ModelChangeEvent>();
readonly onDidChangeRepository: Event<ModelChangeEvent> = this._onDidChangeRepository.event;
private _onDidChangeOriginalResource = new EventEmitter<OriginalResourceChangeEvent>();
readonly onDidChangeOriginalResource: Event<OriginalResourceChangeEvent> = this._onDidChangeOriginalResource.event;
private openRepositories: OpenRepository[] = [];
get repositories(): Repository[] { return this.openRepositories.map(r => r.repository); }
@@ -147,7 +167,9 @@ export class Model {
const activeRepositories = new Set<Repository>(activeRepositoriesList);
const openRepositoriesToDispose = removed
.map(folder => this.getOpenRepository(folder.uri))
.filter(r => !!r && !activeRepositories.has(r.repository)) as OpenRepository[];
.filter(r => !!r)
.filter(r => !activeRepositories.has(r!.repository))
.filter(r => !(workspace.workspaceFolders || []).some(f => isParent(f.uri.fsPath, r!.repository.root))) as OpenRepository[];
possibleRepositoryFolders.forEach(p => this.tryOpenRepository(p.uri.fsPath));
openRepositoriesToDispose.forEach(r => r.dispose());
@@ -203,10 +225,14 @@ export class Model {
const onDidDisappearRepository = filterEvent(repository.onDidChangeState, state => state === RepositoryState.Disposed);
const disappearListener = onDidDisappearRepository(() => dispose());
const changeListener = repository.onDidChangeRepository(uri => this._onDidChangeRepository.fire({ repository, uri }));
const originalResourceChangeListener = repository.onDidChangeOriginalResource(uri => this._onDidChangeOriginalResource.fire({ repository, uri }));
const dispose = () => {
disappearListener.dispose();
changeListener.dispose();
originalResourceChangeListener.dispose();
repository.dispose();
this.openRepositories = this.openRepositories.filter(e => e !== openRepository);
this._onDidCloseRepository.fire(repository);
};
@@ -216,6 +242,16 @@ export class Model {
this._onDidOpenRepository.fire(repository);
}
close(repository: Repository): void {
const openRepository = this.getOpenRepository(repository);
if (!openRepository) {
return;
}
openRepository.dispose();
}
async pickRepository(): Promise<Repository | undefined> {
if (this.openRepositories.length === 0) {
throw new Error(localize('no repositories', "There are no available repositories"));

View File

@@ -5,8 +5,8 @@
'use strict';
import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit } from 'vscode';
import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash } from './git';
import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData } from 'vscode';
import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType, GitError } from './git';
import { anyEvent, filterEvent, eventToPromise, dispose, find } from './util';
import { memoize, throttle, debounce } from './decorators';
import { toGitUri } from './uri';
@@ -171,13 +171,104 @@ export class Resource implements SourceControlResourceState {
}
get decorations(): SourceControlResourceDecorations {
const light = { iconPath: this.getIconPath('light') };
const dark = { iconPath: this.getIconPath('dark') };
// TODO@joh, still requires restart/redraw in the SCM viewlet
const decorations = workspace.getConfiguration().get<boolean>('git.decorations.enabled');
const light = !decorations ? { iconPath: this.getIconPath('light') } : undefined;
const dark = !decorations ? { iconPath: this.getIconPath('dark') } : undefined;
const tooltip = this.tooltip;
const strikeThrough = this.strikeThrough;
const faded = this.faded;
const letter = this.letter;
const color = this.color;
return { strikeThrough, faded, tooltip, light, dark };
return { strikeThrough, faded, tooltip, light, dark, letter, color, source: 'git.resource' /*todo@joh*/ };
}
get letter(): string | undefined {
switch (this.type) {
case Status.INDEX_MODIFIED:
case Status.MODIFIED:
return 'M';
case Status.INDEX_ADDED:
return 'A';
case Status.INDEX_DELETED:
case Status.DELETED:
return 'D';
case Status.INDEX_RENAMED:
return 'R';
case Status.UNTRACKED:
return 'U';
case Status.IGNORED:
return 'I';
case Status.INDEX_COPIED:
case Status.BOTH_DELETED:
case Status.ADDED_BY_US:
case Status.DELETED_BY_THEM:
case Status.ADDED_BY_THEM:
case Status.DELETED_BY_US:
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return 'C';
default:
return undefined;
}
}
get color(): ThemeColor | undefined {
switch (this.type) {
case Status.INDEX_MODIFIED:
case Status.MODIFIED:
return new ThemeColor('gitDecoration.modifiedResourceForeground');
case Status.INDEX_DELETED:
case Status.DELETED:
return new ThemeColor('gitDecoration.deletedResourceForeground');
case Status.INDEX_ADDED: // todo@joh - special color?
case Status.INDEX_RENAMED: // todo@joh - special color?
case Status.UNTRACKED:
return new ThemeColor('gitDecoration.untrackedResourceForeground');
case Status.IGNORED:
return new ThemeColor('gitDecoration.ignoredResourceForeground');
case Status.INDEX_COPIED:
case Status.BOTH_DELETED:
case Status.ADDED_BY_US:
case Status.DELETED_BY_THEM:
case Status.ADDED_BY_THEM:
case Status.DELETED_BY_US:
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return new ThemeColor('gitDecoration.conflictingResourceForeground');
default:
return undefined;
}
}
get priority(): number {
switch (this.type) {
case Status.INDEX_MODIFIED:
case Status.MODIFIED:
return 2;
case Status.IGNORED:
return 3;
case Status.INDEX_COPIED:
case Status.BOTH_DELETED:
case Status.ADDED_BY_US:
case Status.DELETED_BY_THEM:
case Status.ADDED_BY_THEM:
case Status.DELETED_BY_US:
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return 4;
default:
return 1;
}
}
get resourceDecoration(): DecorationData | undefined {
const title = this.tooltip;
const abbreviation = this.letter;
const color = this.color;
const priority = this.priority;
return { bubble: true, source: 'git.resource', title, abbreviation, color, priority };
}
constructor(
@@ -189,54 +280,34 @@ export class Resource implements SourceControlResourceState {
}
export enum Operation {
Status = 1 << 0,
Add = 1 << 1,
RevertFiles = 1 << 2,
Commit = 1 << 3,
Clean = 1 << 4,
Branch = 1 << 5,
Checkout = 1 << 6,
Reset = 1 << 7,
Fetch = 1 << 8,
Pull = 1 << 9,
Push = 1 << 10,
Sync = 1 << 11,
Show = 1 << 12,
Stage = 1 << 13,
GetCommitTemplate = 1 << 14,
DeleteBranch = 1 << 15,
Merge = 1 << 16,
Ignore = 1 << 17,
Tag = 1 << 18,
Stash = 1 << 19
Status = 'Status',
Add = 'Add',
RevertFiles = 'RevertFiles',
Commit = 'Commit',
Clean = 'Clean',
Branch = 'Branch',
Checkout = 'Checkout',
Reset = 'Reset',
Fetch = 'Fetch',
Pull = 'Pull',
Push = 'Push',
Sync = 'Sync',
Show = 'Show',
Stage = 'Stage',
GetCommitTemplate = 'GetCommitTemplate',
DeleteBranch = 'DeleteBranch',
Merge = 'Merge',
Ignore = 'Ignore',
Tag = 'Tag',
Stash = 'Stash',
CheckIgnore = 'CheckIgnore'
}
// function getOperationName(operation: Operation): string {
// switch (operation) {
// case Operation.Status: return 'Status';
// case Operation.Add: return 'Add';
// case Operation.RevertFiles: return 'RevertFiles';
// case Operation.Commit: return 'Commit';
// case Operation.Clean: return 'Clean';
// case Operation.Branch: return 'Branch';
// case Operation.Checkout: return 'Checkout';
// case Operation.Reset: return 'Reset';
// case Operation.Fetch: return 'Fetch';
// case Operation.Pull: return 'Pull';
// case Operation.Push: return 'Push';
// case Operation.Sync: return 'Sync';
// case Operation.Init: return 'Init';
// case Operation.Show: return 'Show';
// case Operation.Stage: return 'Stage';
// case Operation.GetCommitTemplate: return 'GetCommitTemplate';
// default: return 'unknown';
// }
// }
function isReadOnly(operation: Operation): boolean {
switch (operation) {
case Operation.Show:
case Operation.GetCommitTemplate:
case Operation.CheckIgnore:
return true;
default:
return false;
@@ -246,6 +317,7 @@ function isReadOnly(operation: Operation): boolean {
function shouldShowProgress(operation: Operation): boolean {
switch (operation) {
case Operation.Fetch:
case Operation.CheckIgnore:
return false;
default:
return true;
@@ -259,24 +331,36 @@ export interface Operations {
class OperationsImpl implements Operations {
constructor(private readonly operations: number = 0) {
// noop
private operations = new Map<Operation, number>();
start(operation: Operation): void {
this.operations.set(operation, (this.operations.get(operation) || 0) + 1);
}
start(operation: Operation): OperationsImpl {
return new OperationsImpl(this.operations | operation);
}
end(operation: Operation): void {
const count = (this.operations.get(operation) || 0) - 1;
end(operation: Operation): OperationsImpl {
return new OperationsImpl(this.operations & ~operation);
if (count <= 0) {
this.operations.delete(operation);
} else {
this.operations.set(operation, count);
}
}
isRunning(operation: Operation): boolean {
return (this.operations & operation) !== 0;
return this.operations.has(operation);
}
isIdle(): boolean {
return this.operations === 0;
const operations = this.operations.keys();
for (const operation of operations) {
if (!isReadOnly(operation)) {
return false;
}
}
return true;
}
}
@@ -302,6 +386,9 @@ export class Repository implements Disposable {
private _onDidChangeStatus = new EventEmitter<void>();
readonly onDidChangeStatus: Event<void> = this._onDidChangeStatus.event;
private _onDidChangeOriginalResource = new EventEmitter<Uri>();
readonly onDidChangeOriginalResource: Event<Uri> = this._onDidChangeOriginalResource.event;
private _onRunOperation = new EventEmitter<Operation>();
readonly onRunOperation: Event<Operation> = this._onRunOperation.event;
@@ -382,9 +469,7 @@ export class Repository implements Disposable {
const onRelevantGitChange = filterEvent(onRelevantRepositoryChange, uri => /\/\.git\//.test(uri.path));
onRelevantGitChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
const label = `${path.basename(repository.root)} (Git)`;
this._sourceControl = scm.createSourceControl('git', label);
this._sourceControl = scm.createSourceControl('git', 'Git', Uri.file(repository.root));
this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] };
this._sourceControl.quickDiffProvider = this;
this.disposables.push(this._sourceControl);
@@ -449,6 +534,7 @@ export class Repository implements Disposable {
async stage(resource: Uri, contents: string): Promise<void> {
const relativePath = path.relative(this.repository.root, resource.fsPath).replace(/\\/g, '/');
await this.run(Operation.Stage, () => this.repository.stage(relativePath, contents));
this._onDidChangeOriginalResource.fire(resource);
}
async revert(resources: Uri[]): Promise<void> {
@@ -534,11 +620,7 @@ export class Repository implements Disposable {
@throttle
async fetch(): Promise<void> {
try {
await this.run(Operation.Fetch, () => this.repository.fetch());
} catch (err) {
// noop
}
await this.run(Operation.Fetch, () => this.repository.fetch());
}
@throttle
@@ -584,7 +666,7 @@ export class Repository implements Disposable {
async show(ref: string, filePath: string): Promise<string> {
return await this.run(Operation.Show, async () => {
const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/');
const configFiles = workspace.getConfiguration('files');
const configFiles = workspace.getConfiguration('files', Uri.file(filePath));
const encoding = configFiles.get<string>('encoding');
return await this.repository.buffer(`${ref}:${relativePath}`, encoding);
@@ -629,13 +711,58 @@ export class Repository implements Disposable {
});
}
checkIgnore(filePaths: string[]): Promise<Set<string>> {
return this.run(Operation.CheckIgnore, () => {
return new Promise<Set<string>>((resolve, reject) => {
filePaths = filePaths.filter(filePath => !path.relative(this.root, filePath).startsWith('..'));
if (filePaths.length === 0) {
// nothing left
return resolve(new Set<string>());
}
// https://git-scm.com/docs/git-check-ignore#git-check-ignore--z
const child = this.repository.stream(['check-ignore', '-z', '--stdin'], { stdio: [null, null, null] });
child.stdin.end(filePaths.join('\0'), 'utf8');
const onExit = exitCode => {
if (exitCode === 1) {
// nothing ignored
resolve(new Set<string>());
} else if (exitCode === 0) {
// paths are separated by the null-character
resolve(new Set<string>(data.split('\0')));
} else {
reject(new GitError({ stdout: data, stderr, exitCode }));
}
};
let data = '';
const onStdoutData = (raw: string) => {
data += raw;
};
child.stdout.setEncoding('utf8');
child.stdout.on('data', onStdoutData);
let stderr: string = '';
child.stderr.setEncoding('utf8');
child.stderr.on('data', raw => stderr += raw);
child.on('error', reject);
child.on('exit', onExit);
});
});
}
private async run<T>(operation: Operation, runOperation: () => Promise<T> = () => Promise.resolve<any>(null)): Promise<T> {
if (this.state !== RepositoryState.Idle) {
throw new Error('Repository not initialized');
}
const run = async () => {
this._operations = this._operations.start(operation);
this._operations.start(operation);
this._onRunOperation.fire(operation);
try {
@@ -653,7 +780,7 @@ export class Repository implements Disposable {
throw err;
} finally {
this._operations = this._operations.end(operation);
this._operations.end(operation);
this._onDidRunOperation.fire(operation);
}
};
@@ -818,7 +945,7 @@ export class Repository implements Disposable {
await timeout(5000);
}
private async whenIdleAndFocused(): Promise<void> {
async whenIdleAndFocused(): Promise<void> {
while (true) {
if (!this.operations.isIdle()) {
await eventToPromise(this.onDidRunOperation);
@@ -835,6 +962,36 @@ export class Repository implements Disposable {
}
}
get headLabel(): string {
const HEAD = this.HEAD;
if (!HEAD) {
return '';
}
const tag = this.refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0];
const tagName = tag && tag.name;
const head = HEAD.name || tagName || (HEAD.commit || '').substr(0, 8);
return head
+ (this.workingTreeGroup.resourceStates.length > 0 ? '*' : '')
+ (this.indexGroup.resourceStates.length > 0 ? '+' : '')
+ (this.mergeGroup.resourceStates.length > 0 ? '!' : '');
}
get syncLabel(): string {
if (!this.HEAD
|| !this.HEAD.name
|| !this.HEAD.commit
|| !this.HEAD.upstream
|| !(this.HEAD.ahead || this.HEAD.behind)
) {
return '';
}
return `${this.HEAD.behind}${this.HEAD.ahead}`;
}
dispose(): void {
this.disposables = dispose(this.disposables);
}

View File

@@ -6,7 +6,7 @@
'use strict';
import { Disposable, Command, EventEmitter, Event } from 'vscode';
import { RefType, Branch } from './git';
import { Branch } from './git';
import { Repository, Operation } from './repository';
import { anyEvent, dispose } from './util';
import * as nls from 'vscode-nls';
@@ -24,20 +24,7 @@ class CheckoutStatusBar {
}
get command(): Command | undefined {
const HEAD = this.repository.HEAD;
if (!HEAD) {
return undefined;
}
const tag = this.repository.refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0];
const tagName = tag && tag.name;
const head = HEAD.name || tagName || (HEAD.commit || '').substr(0, 8);
const title = '$(git-branch) '
+ head
+ (this.repository.workingTreeGroup.resourceStates.length > 0 ? '*' : '')
+ (this.repository.indexGroup.resourceStates.length > 0 ? '+' : '')
+ (this.repository.mergeGroup.resourceStates.length > 0 ? '!' : '');
const title = `$(git-branch) ${this.repository.headLabel}`;
return {
command: 'git.checkout',
@@ -112,7 +99,7 @@ class SyncStatusBar {
if (HEAD && HEAD.name && HEAD.commit) {
if (HEAD.upstream) {
if (HEAD.ahead || HEAD.behind) {
text += `${HEAD.behind}${HEAD.ahead}`;
text += this.repository.syncLabel;
}
command = 'git.sync';
tooltip = localize('sync changes', "Synchronize Changes");

View File

@@ -8,6 +8,7 @@
import { Event } from 'vscode';
import { dirname } from 'path';
import * as fs from 'fs';
import * as byline from 'byline';
export function log(...args: any[]): void {
console.log.apply(console, ['git:', ...args]);
@@ -188,4 +189,20 @@ export function find<T>(array: T[], fn: (t: T) => boolean): T | undefined {
});
return result;
}
export async function grep(filename: string, pattern: RegExp): Promise<boolean> {
return new Promise<boolean>((c, e) => {
const fileStream = fs.createReadStream(filename, { encoding: 'utf8' });
const stream = byline(fileStream);
stream.on('data', (line: string) => {
if (pattern.test(line)) {
fileStream.close();
c(true);
}
});
stream.on('error', e);
stream.on('end', () => c(false));
});
}

View File

@@ -50,6 +50,11 @@
"scopeName": "text.git-rebase",
"path": "./syntaxes/git-rebase.tmLanguage.json"
}
]
],
"configurationDefaults": {
"[git-commit]": {
"editor.rulers": [72]
}
}
}
}

View File

@@ -82,6 +82,7 @@
{
"id": "backup-history-server-insight",
"contrib": {
"cacheId": "backup-history-server-insight",
"name": "Backup Status",
"provider": "MSSQL",
"edition": [0,1,2,3,4],

View File

@@ -6,20 +6,20 @@ SUM(ALOC.data_pages) AS data_pages,
(SUM(ALOC.total_pages)*8/1024) AS total_space_MB,
(SUM(ALOC.used_pages)*8/1024) AS used_space_MB,
(SUM(ALOC.data_pages)*8/1024) AS data_space_MB
FROM sys.Tables AS TABL
INNER JOIN sys.Indexes AS INDX
FROM sys.tables AS TABL
INNER JOIN sys.indexes AS INDX
ON TABL.object_id = INDX.object_id
INNER JOIN sys.Partitions AS PART
INNER JOIN sys.partitions AS PART
ON INDX.object_id = PART.object_id
AND INDX.index_id = PART.index_id
INNER JOIN sys.Allocation_Units AS ALOC
INNER JOIN sys.allocation_units AS ALOC
ON PART.partition_id = ALOC.container_id
WHERE
INDX.object_id > 255
AND INDX.index_id <= 1
GROUP BY TABL.name,
GROUP BY TABL.name,
INDX.object_id,
INDX.index_id,
INDX.name
ORDER BY
ORDER BY
(SUM(ALOC.total_pages)*8/1024) DESC

View File

@@ -7,11 +7,11 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out"],
"outFiles": ["${workspaceFolder}/client/out"],
"preLaunchTask": "npm"
},
{
@@ -19,10 +19,10 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/client/out/test" ],
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/client/out/test" ],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/test"],
"outFiles": ["${workspaceFolder}/client/out/test"],
"preLaunchTask": "npm"
},
{
@@ -31,7 +31,7 @@
"request": "attach",
"port": 6004,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/server/out"]
"outFiles": ["${workspaceFolder}/server/out"]
}
]

View File

@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname

View File

@@ -6,21 +6,25 @@
import * as path from 'path';
import { workspace, languages, ExtensionContext, extensions, Uri, TextDocument, ColorRange, Color } from 'vscode';
import { workspace, languages, ExtensionContext, extensions, Uri, TextDocument, ColorInformation, Color, ColorPresentation } from 'vscode';
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification } from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry';
import { ConfigurationFeature } from 'vscode-languageclient/lib/proposed';
import { DocumentColorRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
import { ConfigurationFeature } from 'vscode-languageclient/lib/configuration.proposed';
import { DocumentColorRequest, DocumentColorParams, ColorPresentationParams, ColorPresentationRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
import * as nls from 'vscode-nls';
import { hash } from './utils/hash';
let localize = nls.loadMessageBundle();
namespace VSCodeContentRequest {
export const type: RequestType<string, string, any, any> = new RequestType('vscode/content');
}
namespace SchemaContentChangeNotification {
export const type: NotificationType<string, any> = new NotificationType('json/schemaContent');
}
export interface ISchemaAssociations {
[pattern: string]: string[];
}
@@ -56,16 +60,13 @@ interface JSONSchemaSettings {
schema?: any;
}
const ColorFormat_HEX = {
opaque: '"#{red:X}{green:X}{blue:X}"',
transparent: '"#{red:X}{green:X}{blue:X}{alpha:X}"'
};
export function activate(context: ExtensionContext) {
let toDispose = context.subscriptions;
let packageInfo = getPackageInfo(context);
let telemetryReporter: TelemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
context.subscriptions.push(telemetryReporter);
toDispose.push(telemetryReporter);
// The server is implemented in node
let serverModule = context.asAbsolutePath(path.join('server', 'out', 'jsonServerMain.js'));
@@ -102,6 +103,7 @@ export function activate(context: ExtensionContext) {
client.registerFeature(new ConfigurationFeature(client));
let disposable = client.start();
toDispose.push(disposable);
client.onReady().then(() => {
client.onTelemetry(e => {
if (telemetryReporter) {
@@ -119,27 +121,48 @@ export function activate(context: ExtensionContext) {
});
});
let handleContentChange = (uri: Uri) => {
if (uri.scheme === 'vscode' && uri.authority === 'schemas') {
client.sendNotification(SchemaContentChangeNotification.type, uri.toString());
}
};
toDispose.push(workspace.onDidChangeTextDocument(e => handleContentChange(e.document.uri)));
toDispose.push(workspace.onDidCloseTextDocument(d => handleContentChange(d.uri)));
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
// register color provider
context.subscriptions.push(languages.registerColorProvider(documentSelector, {
provideDocumentColors(document: TextDocument): Thenable<ColorRange[]> {
let params = client.code2ProtocolConverter.asDocumentSymbolParams(document);
toDispose.push(languages.registerColorProvider(documentSelector, {
provideDocumentColors(document: TextDocument): Thenable<ColorInformation[]> {
let params: DocumentColorParams = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document)
};
return client.sendRequest(DocumentColorRequest.type, params).then(symbols => {
return symbols.map(symbol => {
let range = client.protocol2CodeConverter.asRange(symbol.range);
let color = new Color(symbol.color.red * 255, symbol.color.green * 255, symbol.color.blue * 255, symbol.color.alpha);
return new ColorRange(range, color, [ColorFormat_HEX]);
let color = new Color(symbol.color.red, symbol.color.green, symbol.color.blue, symbol.color.alpha);
return new ColorInformation(range, color);
});
});
},
provideColorPresentations(color: Color, context): Thenable<ColorPresentation[]> {
let params: ColorPresentationParams = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(context.document),
color: color,
range: client.code2ProtocolConverter.asRange(context.range)
};
return client.sendRequest(ColorPresentationRequest.type, params).then(presentations => {
return presentations.map(p => {
let presentation = new ColorPresentation(p.label);
presentation.textEdit = p.textEdit && client.protocol2CodeConverter.asTextEdit(p.textEdit);
presentation.additionalTextEdits = p.additionalTextEdits && client.protocol2CodeConverter.asTextEdits(p.additionalTextEdits);
return presentation;
});
});
}
}));
});
// Push the disposable to the context's subscriptions so that the
// client can be deactivated on extension deactivation
context.subscriptions.push(disposable);
languages.setLanguageConfiguration('json', {
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
indentationRules: {
@@ -184,9 +207,6 @@ function getSchemaAssociation(context: ExtensionContext): ISchemaAssociations {
function getSettings(): Settings {
let httpSettings = workspace.getConfiguration('http');
let jsonSettings = workspace.getConfiguration('json');
let schemas = [];
let settings: Settings = {
http: {
@@ -194,42 +214,70 @@ function getSettings(): Settings {
proxyStrictSSL: httpSettings.get('proxyStrictSSL')
},
json: {
format: jsonSettings.get('format'),
schemas: schemas,
format: workspace.getConfiguration('json').get('format'),
schemas: [],
}
};
let schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
let collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], rootPath?: string, fileMatchPrefix?: string) => {
for (let setting of schemaSettings) {
let url = getSchemaId(setting, rootPath);
if (!url) {
continue;
}
let schemaSetting = schemaSettingsById[url];
if (!schemaSetting) {
schemaSetting = schemaSettingsById[url] = { url, fileMatch: [] };
settings.json.schemas.push(schemaSetting);
}
let fileMatches = setting.fileMatch;
if (Array.isArray(fileMatches)) {
if (fileMatchPrefix) {
fileMatches = fileMatches.map(m => fileMatchPrefix + m);
}
schemaSetting.fileMatch.push(...fileMatches);
}
if (setting.schema) {
schemaSetting.schema = setting.schema;
}
}
};
let settingsSchemas = jsonSettings.get('schemas');
if (Array.isArray(settingsSchemas)) {
schemas.push(...settingsSchemas);
}
// merge global and folder settings. Qualify all file matches with the folder path.
let globalSettings = workspace.getConfiguration('json', null).get<JSONSchemaSettings[]>('schemas');
if (Array.isArray(globalSettings)) {
collectSchemaSettings(globalSettings, workspace.rootPath);
}
let folders = workspace.workspaceFolders;
if (folders) {
folders.forEach(folder => {
let jsonConfig = workspace.getConfiguration('json', folder.uri);
let schemaConfigInfo = jsonConfig.inspect<JSONSchemaSettings[]>('schemas');
for (let folder of folders) {
let folderUri = folder.uri;
let schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect<JSONSchemaSettings[]>('schemas');
let folderSchemas = schemaConfigInfo.workspaceFolderValue;
if (Array.isArray(folderSchemas)) {
folderSchemas.forEach(schema => {
let url = schema.url;
if (!url && schema.schema) {
url = schema.schema.id;
}
if (url && url[0] === '.') {
url = Uri.file(path.normalize(path.join(folder.uri.fsPath, url))).toString();
}
let fileMatch = schema.fileMatch;
if (fileMatch) {
fileMatch = fileMatch.map(m => folder.uri.toString() + '*' + m);
}
schemas.push({ url, fileMatch, schema: schema.schema });
});
let folderPath = folderUri.toString();
if (folderPath[folderPath.length - 1] !== '/') {
folderPath = folderPath + '/';
}
collectSchemaSettings(folderSchemas, folderUri.fsPath, folderPath + '*');
};
});
};
}
return settings;
}
function getSchemaId(schema: JSONSchemaSettings, rootPath?: string) {
let url = schema.url;
if (!url) {
if (schema.schema) {
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`;
}
} else if (rootPath && (url[0] === '.' || url[0] === '/')) {
url = Uri.file(path.normalize(path.join(rootPath, url))).toString();
}
return url;
}
function getPackageInfo(context: ExtensionContext): IPackageInfo {
let extensionPackage = require(context.asAbsolutePath('./package.json'));
if (extensionPackage) {
@@ -240,4 +288,4 @@ function getPackageInfo(context: ExtensionContext): IPackageInfo {
};
}
return null;
}
}

View File

@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
/**
* Return a hash value for an object.
*/
export function hash(obj: any, hashVal = 0): number {
switch (typeof obj) {
case 'object':
if (obj === null) {
return numberHash(349, hashVal);
} else if (Array.isArray(obj)) {
return arrayHash(obj, hashVal);
}
return objectHash(obj, hashVal);
case 'string':
return stringHash(obj, hashVal);
case 'boolean':
return booleanHash(obj, hashVal);
case 'number':
return numberHash(obj, hashVal);
case 'undefined':
return numberHash(obj, 937);
default:
return numberHash(obj, 617);
}
}
function numberHash(val: number, initialHashVal: number): number {
return (((initialHashVal << 5) - initialHashVal) + val) | 0; // hashVal * 31 + ch, keep as int32
}
function booleanHash(b: boolean, initialHashVal: number): number {
return numberHash(b ? 433 : 863, initialHashVal);
}
function stringHash(s: string, hashVal: number) {
hashVal = numberHash(149417, hashVal);
for (let i = 0, length = s.length; i < length; i++) {
hashVal = numberHash(s.charCodeAt(i), hashVal);
}
return hashVal;
}
function arrayHash(arr: any[], initialHashVal: number): number {
initialHashVal = numberHash(104579, initialHashVal);
return arr.reduce((hashVal, item) => hash(item, hashVal), initialHashVal);
}
function objectHash(obj: any, initialHashVal: number): number {
initialHashVal = numberHash(181387, initialHashVal);
return Object.keys(obj).sort().reduce((hashVal, key) => {
hashVal = stringHash(key, hashVal);
return hash(obj[key], hashVal);
}, initialHashVal);
}

View File

@@ -13,24 +13,24 @@
"resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz"
},
"vscode-jsonrpc": {
"version": "3.3.1",
"from": "vscode-jsonrpc@>=3.3.0 <4.0.0",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.3.1.tgz"
"version": "3.5.0-next.2",
"from": "vscode-jsonrpc@3.5.0-next.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0-next.2.tgz"
},
"vscode-languageclient": {
"version": "3.4.0-next.17",
"from": "vscode-languageclient@next",
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.4.0-next.17.tgz"
"version": "3.5.0-next.4",
"from": "vscode-languageclient@3.5.0-next.4",
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.5.0-next.4.tgz"
},
"vscode-languageserver-protocol": {
"version": "3.1.1",
"from": "vscode-languageserver-protocol@>=3.1.1 <4.0.0",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.1.1.tgz"
"version": "3.5.0-next.5",
"from": "vscode-languageserver-protocol@3.5.0-next.5",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0-next.5.tgz"
},
"vscode-languageserver-types": {
"version": "3.3.0",
"from": "vscode-languageserver-types@>=3.3.0 <4.0.0",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.3.0.tgz"
"version": "3.5.0-next.2",
"from": "vscode-languageserver-types@3.5.0-next.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0-next.2.tgz"
},
"vscode-nls": {
"version": "2.0.2",

View File

@@ -133,11 +133,10 @@
},
"dependencies": {
"vscode-extension-telemetry": "0.0.8",
"vscode-languageclient": "3.4.0-next.17",
"vscode-languageserver-protocol": "^3.1.1",
"vscode-languageclient": "3.5.0-next.4",
"vscode-nls": "2.0.2"
},
"devDependencies": {
"@types/node": "^6.0.51"
"@types/node": "7.0.43"
}
}

View File

@@ -8,25 +8,25 @@
"request": "attach",
"port": 6004,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
},
{
"name": "Unit Tests",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/../../../node_modules/mocha/bin/_mocha",
"program": "${workspaceFolder}/../../../node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"args": [
"--timeout",
"999999",
"--colors"
],
"cwd": "${workspaceRoot}",
"cwd": "${workspaceFolder}",
"runtimeExecutable": null,
"runtimeArgs": [],
"env": {},
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
}
]
}

View File

@@ -43,29 +43,29 @@
"resolved": "https://registry.npmjs.org/request-light/-/request-light-0.2.1.tgz"
},
"vscode-json-languageservice": {
"version": "2.0.16",
"version": "3.0.0",
"from": "vscode-json-languageservice@next",
"resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-2.0.16.tgz"
"resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.0.0.tgz"
},
"vscode-jsonrpc": {
"version": "3.3.1",
"from": "vscode-jsonrpc@>=3.3.0 <4.0.0",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.3.1.tgz"
"version": "3.5.0-next.2",
"from": "vscode-jsonrpc@3.5.0-next.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0-next.2.tgz"
},
"vscode-languageserver": {
"version": "3.4.0-next.6",
"from": "vscode-languageserver@next",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.4.0-next.6.tgz"
"version": "3.5.0-next.6",
"from": "vscode-languageserver@3.5.0-next.6",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.5.0-next.6.tgz"
},
"vscode-languageserver-protocol": {
"version": "3.1.1",
"from": "vscode-languageserver-protocol@>=3.1.1 <4.0.0",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.1.1.tgz"
"version": "3.5.0-next.5",
"from": "vscode-languageserver-protocol@3.5.0-next.5",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0-next.5.tgz"
},
"vscode-languageserver-types": {
"version": "3.3.0",
"from": "vscode-languageserver-types@>=3.0.3 <4.0.0",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.3.0.tgz"
"version": "3.5.0-next.2",
"from": "vscode-languageserver-types@3.5.0-next.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0-next.2.tgz"
},
"vscode-nls": {
"version": "2.0.2",

View File

@@ -10,13 +10,13 @@
"dependencies": {
"jsonc-parser": "^1.0.0",
"request-light": "^0.2.1",
"vscode-json-languageservice": "^2.0.16",
"vscode-languageserver": "3.4.0-next.6",
"vscode-languageserver-protocol": "^3.1.1",
"vscode-nls": "^2.0.2"
"vscode-json-languageservice": "3.0.0",
"vscode-languageserver": "3.5.0-next.6",
"vscode-nls": "^2.0.2",
"vscode-uri": "^1.0.1"
},
"devDependencies": {
"@types/node": "^6.0.51"
"@types/node": "7.0.43"
},
"scripts": {
"compile": "gulp compile-extension:json-server",

View File

@@ -10,12 +10,11 @@ import {
DocumentRangeFormattingRequest, Disposable, ServerCapabilities
} from 'vscode-languageserver';
import { DocumentColorRequest, ServerCapabilities as CPServerCapabilities } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
import { DocumentColorRequest, ServerCapabilities as CPServerCapabilities, ColorPresentationRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light';
import path = require('path');
import fs = require('fs');
import URI from './utils/uri';
import URI from 'vscode-uri';
import * as URL from 'url';
import Strings = require('./utils/strings');
import { JSONDocument, JSONSchema, LanguageSettings, getLanguageService } from 'vscode-json-languageservice';
@@ -36,6 +35,10 @@ namespace VSCodeContentRequest {
export const type: RequestType<string, string, any, any> = new RequestType('vscode/content');
}
namespace SchemaContentChangeNotification {
export const type: NotificationType<string, any> = new NotificationType('json/schemaContent');
}
// Create a connection for the server
let connection: IConnection = createConnection();
@@ -54,9 +57,7 @@ let clientDynamicRegisterSupport = false;
// After the server has started the client sends an initilize request. The server receives
// in the passed params the rootPath of the workspace plus the client capabilities.
let workspaceRoot: URI;
connection.onInitialize((params: InitializeParams): InitializeResult => {
workspaceRoot = URI.parse(params.rootPath);
function hasClientCapability(...keys: string[]) {
let c = params.capabilities;
@@ -175,6 +176,11 @@ connection.onNotification(SchemaAssociationNotification.type, associations => {
updateConfiguration();
});
// A schema has changed
connection.onNotification(SchemaContentChangeNotification.type, uri => {
languageService.resetSchema(uri);
});
function updateConfiguration() {
let languageSettings: LanguageSettings = {
validate: true,
@@ -192,19 +198,12 @@ function updateConfiguration() {
}
}
if (jsonConfigurationSettings) {
jsonConfigurationSettings.forEach(schema => {
jsonConfigurationSettings.forEach((schema, index) => {
let uri = schema.url;
if (!uri && schema.schema) {
uri = schema.schema.id;
}
if (!uri && schema.fileMatch) {
uri = 'vscode://schemas/custom/' + encodeURIComponent(schema.fileMatch.join('&'));
uri = schema.schema.id || `vscode://schemas/custom/${index}`;
}
if (uri) {
if (uri[0] === '.' && workspaceRoot) {
// workspace relative path
uri = URI.file(path.normalize(path.join(workspaceRoot.fsPath, uri))).toString();
}
languageSettings.schemas.push({ uri, fileMatch: schema.fileMatch, schema: schema.schema });
}
});
@@ -321,5 +320,14 @@ connection.onRequest(DocumentColorRequest.type, params => {
return [];
});
connection.onRequest(ColorPresentationRequest.type, params => {
let document = documents.get(params.textDocument.uri);
if (document) {
let jsonDocument = getJSONDocument(document);
return languageService.getColorPresentations(document, jsonDocument, params.color, params.range);
}
return [];
});
// Listen on the connection
connection.listen();

View File

@@ -388,11 +388,11 @@
"c": "\\u0056",
"t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json constant.character.escape.json",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
"hc_black": "constant.character: #569CD6"
}
},
{

View File

@@ -37,5 +37,8 @@
["(", ")"],
["[", "]"],
["`", "`"]
]
],
"folding": {
"offSide": true
}
}

View File

@@ -2,75 +2,189 @@
"name": "vscode-markdown",
"version": "0.2.0",
"dependencies": {
"@types/highlight.js": {
"version": "9.1.10",
"from": "@types/highlight.js@9.1.10",
"resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.1.10.tgz",
"dev": true
},
"@types/markdown-it": {
"version": "0.0.2",
"from": "@types/markdown-it@0.0.2",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.2.tgz",
"dev": true
},
"@types/node": {
"version": "7.0.43",
"from": "@types/node@7.0.43",
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.43.tgz",
"dev": true
},
"applicationinsights": {
"version": "0.18.0",
"from": "applicationinsights@0.18.0",
"from": "applicationinsights@https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz",
"resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz"
},
"argparse": {
"version": "1.0.9",
"from": "argparse@>=1.0.7 <2.0.0",
"from": "argparse@https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz"
},
"binaryextensions": {
"version": "1.0.1",
"from": "binaryextensions@1.0.1",
"resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz",
"dev": true
},
"core-util-is": {
"version": "1.0.2",
"from": "core-util-is@1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"dev": true
},
"entities": {
"version": "1.1.1",
"from": "entities@>=1.1.1 <1.2.0",
"from": "entities@https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz"
},
"escape-string-regexp": {
"version": "1.0.5",
"from": "escape-string-regexp@1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"dev": true
},
"gulp-rename": {
"version": "1.2.2",
"from": "gulp-rename@1.2.2",
"resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz",
"dev": true
},
"gulp-replace": {
"version": "0.5.4",
"from": "gulp-replace@0.5.4",
"resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.5.4.tgz",
"dev": true
},
"highlight.js": {
"version": "9.5.0",
"from": "highlight.js@>=9.3.0 <10.0.0",
"from": "highlight.js@https://registry.npmjs.org/highlight.js/-/highlight.js-9.5.0.tgz",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.5.0.tgz"
},
"inherits": {
"version": "2.0.3",
"from": "inherits@2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"dev": true
},
"isarray": {
"version": "1.0.0",
"from": "isarray@1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"dev": true
},
"istextorbinary": {
"version": "1.0.2",
"from": "istextorbinary@1.0.2",
"resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz",
"dev": true
},
"linkify-it": {
"version": "2.0.3",
"from": "linkify-it@>=2.0.0 <3.0.0",
"from": "linkify-it@https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz"
},
"markdown-it": {
"version": "8.2.2",
"from": "markdown-it@8.2.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.2.2.tgz"
"version": "8.4.0",
"from": "markdown-it@8.4.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz"
},
"markdown-it-named-headers": {
"version": "0.0.4",
"from": "markdown-it-named-headers@0.0.4",
"from": "markdown-it-named-headers@https://registry.npmjs.org/markdown-it-named-headers/-/markdown-it-named-headers-0.0.4.tgz",
"resolved": "https://registry.npmjs.org/markdown-it-named-headers/-/markdown-it-named-headers-0.0.4.tgz"
},
"mdurl": {
"version": "1.0.1",
"from": "mdurl@>=1.0.1 <1.1.0",
"from": "mdurl@https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz"
},
"object-assign": {
"version": "4.1.1",
"from": "object-assign@4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"dev": true
},
"process-nextick-args": {
"version": "1.0.7",
"from": "process-nextick-args@1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"dev": true
},
"readable-stream": {
"version": "2.3.3",
"from": "readable-stream@2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
"dev": true
},
"replacestream": {
"version": "4.0.2",
"from": "replacestream@4.0.2",
"resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.2.tgz",
"dev": true
},
"safe-buffer": {
"version": "5.1.1",
"from": "safe-buffer@5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"dev": true
},
"sprintf-js": {
"version": "1.0.3",
"from": "sprintf-js@>=1.0.2 <1.1.0",
"from": "sprintf-js@https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
},
"string": {
"version": "3.3.1",
"from": "string@>=3.0.1 <4.0.0",
"from": "string@https://registry.npmjs.org/string/-/string-3.3.1.tgz",
"resolved": "https://registry.npmjs.org/string/-/string-3.3.1.tgz"
},
"string_decoder": {
"version": "1.0.3",
"from": "string_decoder@1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"dev": true
},
"textextensions": {
"version": "1.0.2",
"from": "textextensions@1.0.2",
"resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz",
"dev": true
},
"uc.micro": {
"version": "1.0.3",
"from": "uc.micro@>=1.0.3 <2.0.0",
"from": "uc.micro@https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz"
},
"util-deprecate": {
"version": "1.0.2",
"from": "util-deprecate@1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"dev": true
},
"vscode-extension-telemetry": {
"version": "0.0.7",
"from": "vscode-extension-telemetry@>=0.0.8 <0.0.9",
"version": "0.0.8",
"from": "vscode-extension-telemetry@https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz",
"resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz"
},
"vscode-nls": {
"version": "2.0.2",
"from": "vscode-nls@>=2.0.1 <3.0.0",
"from": "vscode-nls@https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz",
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz"
},
"winreg": {
"version": "1.2.3",
"from": "winreg@1.2.3",
"from": "winreg@https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz",
"resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz"
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More