Skip to content

Commit 98fa4b9

Browse files
Merge offline VSIX work to master (#435)
This checkin cherry-pick's commit 8b2cda1 into master. As part of this, I changed the versions for debugger components in install.ts to match what the master branch was installing already. Original description: commit 8b2cda1 Author: Chuck Ries <[email protected]> Date: Mon Jun 6 14:41:53 2016 -0700 Implement task to create offline VSIX's This implements a gulp task that creates platform specific vsix's that do not require the secondary download/installation steps. 1. Refactor coreclr-debug/main.ts into activation.ts and install.ts 2. Remove VS Code specific modules from install.ts so that it can be called from gulp 3. Refactor omnisharpDownload.ts so that it has no VS Code dependencies and can be called from gulp task. 4. Create packaging gulp task that will perform the download of the debugger and omnisharp in place, package the extension, and clean it up. This repeats for as many platforms as we need to ship.
1 parent dda3815 commit 98fa4b9

File tree

14 files changed

+660
-492
lines changed

14 files changed

+660
-492
lines changed

.vscodeignore

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,9 @@ src/**
55
**/*.map
66

77
.vscode/**
8-
.omnisharp/**
98

109
**/.nyc_output/**
1110
**/coverage/**
1211

13-
coreclr-debug/debugAdapters/**
14-
coreclr-debug/bin/**
15-
coreclr-debug/obj/**
16-
coreclr-debug/project.lock.json
17-
coreclr-debug/install.log
1812
+RuntimeLicenses/dependencies/*
13+
coreclr-debug/install.log

gulpfile.js

Lines changed: 128 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,142 @@
55

66
'use strict';
77

8+
const fs = require('fs');
9+
const path = require('path');
810
const del = require('del');
911
const gulp = require('gulp');
12+
const gulpUtil = require('gulp-util');
1013
const tslint = require('gulp-tslint');
1114
const vsce = require('vsce');
12-
//const omnisharpDownload = require('./out/omnisharpDownload');
15+
const debugUtil = require('./out/coreclr-debug/util.js');
16+
const debugInstall = require('./out/coreclr-debug/install.js');
17+
const fs_extra = require('fs-extra-promise');
18+
const omnisharpDownload = require('./out/omnisharpDownload');
19+
const child_process = require('child_process');
20+
21+
const OmniSharpVersion = omnisharpDownload.OmniSharpVersion;
22+
23+
/// used in offline packaging run so does not clean .vsix
24+
function clean() {
25+
cleanDebugger();
26+
return cleanOmnisharp();
27+
}
28+
29+
gulp.task('clean', ['omnisharp:clean', 'debugger:clean', 'package:clean'], () => {
30+
31+
});
32+
33+
/// Omnisharp Tasks
34+
function installOmnisharp(omnisharpAssetName) {
35+
const logFunction = (message) => { console.log(message); };
36+
return omnisharpDownload.downloadOmnisharp(logFunction, omnisharpAssetName);
37+
}
38+
39+
function cleanOmnisharp() {
40+
return del('.omnisharp');
41+
}
1342

1443
gulp.task('omnisharp:clean', () => {
15-
return del('.omnisharp');
44+
return cleanOmnisharp();
45+
});
46+
47+
gulp.task('omnisharp:install', ['omnisharp:clean'], () => {
48+
var asset = gulpUtil.env.asset || omnisharpDownload.getOmnisharpAssetName();
49+
return installOmnisharp(asset);
50+
});
51+
52+
/// Debugger Tasks
53+
function getDebugInstaller() {
54+
return new debugInstall.DebugInstaller(new debugUtil.CoreClrDebugUtil(path.resolve('.')), true);
55+
}
56+
57+
function installDebugger(runtimeId) {
58+
return getDebugInstaller().install(runtimeId);
59+
}
60+
61+
function cleanDebugger() {
62+
try {
63+
getDebugInstaller().clean();
64+
console.log('Cleaned Succesfully');
65+
} catch (error) {
66+
console.error(error);
67+
}
68+
}
69+
70+
gulp.task('debugger:install', ['debugger:clean'], () => {
71+
installDebugger(gulp.env.runtimeId).then(() => {
72+
console.log('Installed Succesfully');
73+
}).catch((error) => {
74+
console.error(error);
75+
});
76+
});
77+
78+
gulp.task('debugger:clean', () => {
79+
cleanDebugger();
80+
});
81+
82+
/// Packaging Tasks
83+
function doPackageSync(packageName) {
84+
85+
var vsceArgs = [];
86+
vsceArgs.push(path.join(__dirname, 'node_modules', 'vsce', 'out', 'vsce'))
87+
vsceArgs.push('package'); // package command
88+
89+
if (packageName !== undefined) {
90+
vsceArgs.push('-o');
91+
vsceArgs.push(packageName);
92+
}
93+
94+
var proc = child_process.spawnSync('node', vsceArgs);
95+
if (proc.error) {
96+
console.error(proc.error.toString());
97+
}
98+
}
99+
100+
function doOfflinePackage(runtimeId, omnisharpAsset, packageName) {
101+
return clean().then(() => {
102+
return installDebugger(runtimeId);
103+
}).then(() => {
104+
return installOmnisharp(omnisharpAsset);
105+
}).then(() => {
106+
doPackageSync(packageName + '-' + runtimeId + '.vsix');
107+
});
108+
}
109+
110+
gulp.task('package:clean', () => {
111+
return del('*.vsix');
112+
});
113+
114+
gulp.task('package:online', ['clean'], () => {
115+
doPackageSync();
16116
});
17117

18-
//TODO: decouple omnisharpDownload (specifically proxy.ts) from vscode
19-
// gulp.task('omnisharp:fetch', ['omnisharp:clean'], () => {
20-
// return omnisharpDownload.downloadOmnisharp();
21-
// });
118+
gulp.task('package:offline', ['clean'], () => {
119+
var json = JSON.parse(fs.readFileSync('package.json'));
120+
var name = json.name;
121+
var version = json.version;
122+
var packageName = name + '.' + version;
22123

124+
var packages = [];
125+
packages.push({rid: 'win7-x64', omni: `omnisharp-${OmniSharpVersion}-win-x64-net451.zip`});
126+
packages.push({rid: 'osx.10.11-x64', omni: `omnisharp-${OmniSharpVersion}-osx-x64-netcoreapp1.0.tar.gz`});
127+
packages.push({rid: 'centos.7-x64', omni: `omnisharp-${OmniSharpVersion}-centos-x64-netcoreapp1.0.tar.gz`});
128+
packages.push({rid: 'debian.8-x64', omni: `omnisharp-${OmniSharpVersion}-debian-x64-netcoreapp1.0.tar.gz`});
129+
packages.push({rid: 'rhel.7.2-x64', omni: `omnisharp-${OmniSharpVersion}-rhel-x64-netcoreapp1.0.tar.gz`});
130+
packages.push({rid: 'ubuntu.14.04-x64', omni: `omnisharp-${OmniSharpVersion}-ubuntu-x64-netcoreapp1.0.tar.gz`});
131+
132+
var promise = Promise.resolve();
133+
134+
packages.forEach(pair => {
135+
promise = promise.then(() => {
136+
return doOfflinePackage(pair.rid, pair.omni, packageName);
137+
})
138+
});
139+
140+
return promise;
141+
});
142+
143+
/// Misc Tasks
23144
const allTypeScript = [
24145
'src/**/*.ts',
25146
'!**/*.d.ts',
@@ -29,7 +150,7 @@ const allTypeScript = [
29150
const lintReporter = (output, file, options) => {
30151
//emits: src/helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’
31152
var relativeBase = file.base.substring(file.cwd.length + 1).replace('\\', '/');
32-
output.forEach(function(e) {
153+
output.forEach(e => {
33154
var message = relativeBase + e.name + ':' + (e.startPosition.line + 1) + ':' + (e.startPosition.character + 1) + ': ' + e.failure;
34155
console.log('[tslint] ' + message);
35156
});
@@ -44,10 +165,4 @@ gulp.task('tslint', () => {
44165
summarizeFailureOutput: false,
45166
emitError: false
46167
}))
47-
});
48-
49-
// gulp.task('omnisharp', ['omnisharp:fetch']);
50-
51-
gulp.task('package', () => {
52-
vsce(['', '', 'package']);
53168
});

src/coreclr-debug/activate.ts

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
'use strict';
6+
7+
import * as vscode from 'vscode';
8+
import * as child_process from 'child_process';
9+
import * as fs from 'fs';
10+
import * as path from 'path';
11+
import TelemetryReporter from 'vscode-extension-telemetry';
12+
import { CoreClrDebugUtil } from './util';
13+
import * as debugInstall from './install';
14+
15+
let _reporter: TelemetryReporter = null;
16+
let _channel: vscode.OutputChannel = null;
17+
let _util: CoreClrDebugUtil = null;
18+
19+
export function activate(context: vscode.ExtensionContext, reporter: TelemetryReporter) {
20+
_reporter = reporter;
21+
_channel = vscode.window.createOutputChannel('coreclr-debug');
22+
_util = new CoreClrDebugUtil(context.extensionPath, _channel);
23+
24+
if (CoreClrDebugUtil.existsSync(_util.installCompleteFilePath())) {
25+
console.log('.NET Core Debugger tools already installed');
26+
return;
27+
}
28+
29+
if (!isOnPath('dotnet')) {
30+
const getDotNetMessage = "Get .NET CLI tools";
31+
vscode.window.showErrorMessage("The .NET CLI tools cannot be located. .NET Core debugging will not be enabled. Make sure .NET CLI tools are installed and are on the path.",
32+
getDotNetMessage).then(value => {
33+
if (value === getDotNetMessage) {
34+
let open = require('open');
35+
open("http://dotnet.github.io/getting-started/");
36+
}
37+
});
38+
39+
return;
40+
}
41+
42+
let installer = new debugInstall.DebugInstaller(_util);
43+
_util.createInstallLog();
44+
45+
let runtimeId = getPlatformRuntimeId();
46+
47+
let statusBarMessage = vscode.window.setStatusBarMessage("Downloading and configuring the .NET Core Debugger...");
48+
49+
let installStage = "installBegin";
50+
let installError = "";
51+
52+
writeInstallBeginFile().then(() => {
53+
return installer.install(runtimeId);
54+
}).then(() => {
55+
installStage = "completeSuccess";
56+
statusBarMessage.dispose();
57+
vscode.window.setStatusBarMessage('Successfully installed .NET Core Debugger.');
58+
})
59+
.catch((error: debugInstall.InstallError) => {
60+
const viewLogMessage = "View Log";
61+
vscode.window.showErrorMessage('Error while installing .NET Core Debugger.', viewLogMessage).then(value => {
62+
if (value === viewLogMessage) {
63+
_channel.show(vscode.ViewColumn.Three);
64+
}
65+
});
66+
statusBarMessage.dispose();
67+
68+
installStage = error.installStage;
69+
installError = error.installError;
70+
}).then(() => {
71+
// log telemetry and delete install begin file
72+
logTelemetry('Acquisition', {installStage: installStage, installError: installError});
73+
try {
74+
deleteInstallBeginFile();
75+
} catch (err) {
76+
// if this throws there's really nothing we can do
77+
}
78+
_util.closeInstallLog();
79+
});
80+
}
81+
82+
function logTelemetry(eventName: string, properties?: {[prop: string]: string}): void {
83+
if (_reporter !== null) {
84+
_reporter.sendTelemetryEvent('coreclr-debug/' + eventName, properties);
85+
}
86+
}
87+
88+
function writeInstallBeginFile() : Promise<void> {
89+
return CoreClrDebugUtil.writeEmptyFile(_util.installBeginFilePath());
90+
}
91+
92+
function deleteInstallBeginFile() {
93+
if (CoreClrDebugUtil.existsSync(_util.installBeginFilePath())) {
94+
fs.unlinkSync(_util.installBeginFilePath());
95+
}
96+
}
97+
98+
// Determines if the specified command is in one of the directories in the PATH environment variable.
99+
function isOnPath(command : string) : boolean {
100+
let pathValue = process.env['PATH'];
101+
if (!pathValue) {
102+
return false;
103+
}
104+
let fileName = command;
105+
if (process.platform == 'win32') {
106+
// on Windows, add a '.exe', and the path is semi-colon seperatode
107+
fileName = fileName + ".exe";
108+
}
109+
110+
let pathSegments: string[] = pathValue.split(path.delimiter);
111+
for (let segment of pathSegments) {
112+
if (segment.length === 0 || !path.isAbsolute(segment)) {
113+
continue;
114+
}
115+
116+
const segmentPath = path.join(segment, fileName);
117+
118+
try {
119+
if (CoreClrDebugUtil.existsSync(segmentPath)) {
120+
return true;
121+
}
122+
} catch (err) {
123+
// any error from existsSync can be treated as the command not being on the path
124+
continue;
125+
}
126+
}
127+
128+
return false;
129+
}
130+
131+
function getPlatformRuntimeId() : string {
132+
switch (process.platform) {
133+
case 'win32':
134+
return 'win7-x64';
135+
case 'darwin':
136+
return getDotnetRuntimeId();
137+
case 'linux':
138+
return getDotnetRuntimeId();
139+
default:
140+
_util.log('Error: Unsupported platform ' + process.platform);
141+
throw Error('Unsupported platform ' + process.platform);
142+
}
143+
}
144+
145+
function getDotnetRuntimeId(): string {
146+
_util.log("Starting 'dotnet --info'");
147+
148+
const cliVersionErrorMessage = "Ensure that .NET Core CLI Tools version >= 1.0.0-beta-002173 is installed. Run 'dotnet --version' to see what version is installed.";
149+
150+
let child = child_process.spawnSync('dotnet', ['--info'], { cwd: _util.coreClrDebugDir() });
151+
152+
if (child.stderr.length > 0) {
153+
_util.log('Error: ' + child.stderr.toString());
154+
}
155+
const out = child.stdout.toString();
156+
if (out.length > 0) {
157+
_util.log(out);
158+
}
159+
160+
if (child.status !== 0) {
161+
const message = `Error: 'dotnet --info' failed with error ${child.status}`;
162+
_util.log(message);
163+
_util.log(cliVersionErrorMessage);
164+
throw new Error(message);
165+
}
166+
167+
if (out.length === 0) {
168+
const message = "Error: 'dotnet --info' provided no output";
169+
_util.log(message);
170+
_util.log(cliVersionErrorMessage);
171+
throw new Error(message);
172+
}
173+
174+
let lines = out.split('\n');
175+
let ridLine = lines.filter(value => {
176+
return value.trim().startsWith('RID:');
177+
});
178+
179+
if (ridLine.length < 1) {
180+
_util.log("Error: Cannot find 'RID' property");
181+
_util.log(cliVersionErrorMessage);
182+
throw new Error('Cannot obtain Runtime ID from dotnet cli');
183+
}
184+
185+
let rid = ridLine[0].split(':')[1].trim();
186+
187+
if (!rid) {
188+
_util.log("Error: Unable to parse 'RID' property.");
189+
_util.log(cliVersionErrorMessage);
190+
throw new Error('Unable to determine Runtime ID');
191+
}
192+
193+
return rid;
194+
}

0 commit comments

Comments
 (0)