diff --git a/.travis.yml b/.travis.yml index 84626a54..3c1b6b2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,8 @@ deploy: skip_cleanup: true api_key: secure: T/yqCIeqLifteriv8D3CnehNFzSBP309GZqeUfyx8Q+xSQEttA9Enxl+Qw9GkdedYTN4J56iucHIac6CwcvKSKIXqk80CeSEW0BNxZs5wIgv4rRMMy/GAX0NBWKNOkoGlH8M6VyQcM7eY2iGAn1EX755PHalk6rWwfsauRANOQyb2DXQBan5C0YUnogq2qcW1xkIwlXH7l0Ekbtego0f6QPv0rSyOcL1LKm6xk0Aq+xLNKJkT6TSL6xYpkPlZLjnql09Nspkqs6NehWlft2n09bHqAtjNnWw9OYCvxp8mdHeTE5uShuEqYPzdYU5LVFoE7wElI8uqS66noaA18ytZYGw2IrY6GZcn+wtR6WyM2+YXl2HclL1/Fs6Vn8+zwq2IBZchBNv3KJSn1dxiqLlD/s6YQyni17x/9FhtFoNUvsbY5zSC1xrnNQBQWFg0TRnoC9rPR+7hQtT1+5+CvRxpvcNWnPuA22919PFE79ejJulPmsnyF+YLs9c6APJgOpOO1f6fKt5Mcb02dubPqGcQ9NbqUUNTl4IUvEtjG0LnFAgEGerxAcsdnUTxzBVf0LJLlhRKW1BigUTbRwfUJL1DN0mWg9cg7fL5VqrogvNq3uRguxOsYr+bcHDbimQSAY3No3fAkTTqQSJh56Dx57/Un18KxuOTiRB9de1RtiudsI= - file: packages/server/cli-$TRAVIS_OS_NAME + file_glob: true + file: packages/server/cli-* on: repo: codercom/vscode-online branch: master diff --git a/build/tasks.ts b/build/tasks.ts index 6c72324a..761a3979 100644 --- a/build/tasks.ts +++ b/build/tasks.ts @@ -33,7 +33,7 @@ const buildServerBinaryPackage = register("build:server:binary:package", async ( } await buildServerBinaryCopy(); await dependencyNexeBinary(); - const resp = await runner.execute("npm", ["run", "build:nexe"]); + const resp = await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build:nexe"]); if (resp.exitCode !== 0) { throw new Error(`Failed to package binary: ${resp.stderr}`); } @@ -133,7 +133,7 @@ const buildServerBinaryCopy = register("build:server:binary:copy", async (runner const buildServerBundle = register("build:server:bundle", async (runner) => { const cliPath = path.join(pkgsPath, "server"); runner.cwd = cliPath; - await runner.execute("npm", ["run", "build"]); + await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]); }); const buildBootstrapFork = register("build:bootstrap-fork", async (runner) => { @@ -142,7 +142,7 @@ const buildBootstrapFork = register("build:bootstrap-fork", async (runner) => { const vscodePkgPath = path.join(pkgsPath, "vscode"); runner.cwd = vscodePkgPath; - await runner.execute("npm", ["run", "build:bootstrap-fork"]); + await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build:bootstrap-fork"]); }); const buildAppBrowser = register("build:app:browser", async (runner) => { @@ -151,7 +151,7 @@ const buildAppBrowser = register("build:app:browser", async (runner) => { const appPath = path.join(pkgsPath, "app/browser"); runner.cwd = appPath; fse.removeSync(path.join(appPath, "out")); - await runner.execute("npm", ["run", "build"]); + await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]); }); const buildWeb = register("build:web", async (runner) => { @@ -161,7 +161,7 @@ const buildWeb = register("build:web", async (runner) => { const webPath = path.join(pkgsPath, "web"); runner.cwd = webPath; fse.removeSync(path.join(webPath, "out")); - await runner.execute("npm", ["run", "build"]); + await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]); }); const extDirPath = path.join("lib", "vscode-default-extensions"); @@ -169,8 +169,24 @@ const copyForDefaultExtensions = register("build:copy-vscode", async (runner) => if (!fs.existsSync(defaultExtensionsPath)) { await ensureClean(); await ensureInstalled(); - fse.removeSync(extDirPath); - fse.copySync(vscodePath, extDirPath); + await new Promise((resolve, reject): void => { + fse.remove(extDirPath, (err) => { + if (err) { + return reject(err); + } + + resolve(); + }); + }); + await new Promise((resolve, reject): void => { + fse.copy(vscodePath, extDirPath, (err) => { + if (err) { + return reject(err); + } + + resolve(); + }); + }); } }); @@ -178,7 +194,7 @@ const buildDefaultExtensions = register("build:default-extensions", async (runne if (!fs.existsSync(defaultExtensionsPath)) { await copyForDefaultExtensions(); runner.cwd = extDirPath; - const resp = await runner.execute("npx", ["gulp", "vscode-linux-x64"]); + const resp = await runner.execute(isWin ? "npx.cmd" : "npx", [isWin ? "gulp.cmd" : "gulp", "vscode-linux-x64"]); if (resp.exitCode !== 0) { throw new Error(`Failed to build default extensions: ${resp.stderr}`); } diff --git a/package.json b/package.json index e0e4aa41..3c7f2b33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@coder/vscode-remote", - "repository": "https://github.com/codercom/vscode-remote", + "name": "@coder/code-server", + "repository": "https://github.com/codercom/code-server", "author": "Coder", "license": "MIT", "description": "Run VS Code remotely.", diff --git a/packages/app/browser/package.json b/packages/app/browser/package.json index c0789252..68c633c8 100644 --- a/packages/app/browser/package.json +++ b/packages/app/browser/package.json @@ -1,8 +1,8 @@ { "name": "@coder/app", "scripts": { - "start": "../../../node_modules/.bin/webpack-dev-server --config ./webpack.config.js", - "build": "../../../node_modules/.bin/webpack --config ./webpack.config.js" + "start": "node ../../../node_modules/webpack-dev-server/bin/webpack-dev-server.js --config ./webpack.config.js", + "build": "node ../../../node_modules/webpack/bin/webpack.js --config ./webpack.config.js" }, "dependencies": { "@material/checkbox": "^0.44.1", diff --git a/packages/app/browser/src/app.html b/packages/app/browser/src/app.html index 16850c35..a47b6078 100644 --- a/packages/app/browser/src/app.html +++ b/packages/app/browser/src/app.html @@ -9,7 +9,8 @@
- <- Back

AWS Cloud

+ <- Back
+

Enter server password

diff --git a/packages/ide/src/fill/os.ts b/packages/ide/src/fill/os.ts index 1966a2b6..f9c8008c 100644 --- a/packages/ide/src/fill/os.ts +++ b/packages/ide/src/fill/os.ts @@ -34,6 +34,7 @@ class OS { case OperatingSystem.Mac: this._platform = "darwin"; break; default: this._platform = "linux"; break; } + process.platform = this._platform; } public release(): string { diff --git a/packages/ide/src/fill/path.js b/packages/ide/src/fill/path.js new file mode 100644 index 00000000..1fcfd11a --- /dev/null +++ b/packages/ide/src/fill/path.js @@ -0,0 +1,518 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +var os = require('os'); +var util = require('util'); +var isWindows = os.platform() === "win32"; + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + + +if (isWindows) { + // Regex to split a windows path into three parts: [*, device, slash, + // tail] windows-only + var splitDeviceRe = + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + + // Regex to split the tail part of the above into [*, dir, basename, ext] + var splitTailRe = + /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; + + // Function to split a filename into [root, dir, basename, ext] + // windows version + var splitPath = function(filename) { + // Separate device+slash from tail + var result = splitDeviceRe.exec(filename), + device = (result[1] || '') + (result[2] || ''), + tail = result[3] || ''; + // Split the tail into dir, basename and extension + var result2 = splitTailRe.exec(tail), + dir = result2[1], + basename = result2[2], + ext = result2[3]; + return [device, dir, basename, ext]; + }; + + var normalizeUNCRoot = function(device) { + return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\'); + }; + + // path.resolve([from ...], to) + // windows version + exports.resolve = function() { + var resolvedDevice = '', + resolvedTail = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1; i--) { + var path; + if (i >= 0) { + path = arguments[i]; + } else if (!resolvedDevice) { + path = process.cwd(); + } else { + // Windows has the concept of drive-specific current working + // directories. If we've resolved a drive letter but not yet an + // absolute path, get cwd for that drive. We're sure the device is not + // an unc path at this points, because unc paths are always absolute. + path = process.env['=' + resolvedDevice]; + // Verify that a drive-local cwd was found and that it actually points + // to our drive. If not, default to the drive's root. + if (!path || path.substr(0, 3).toLowerCase() !== + resolvedDevice.toLowerCase() + '\\') { + path = resolvedDevice + '\\'; + } + } + + // Skip empty and invalid entries + if (!util.isString(path)) { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + var result = splitDeviceRe.exec(path), + device = result[1] || '', + isUnc = device && device.charAt(1) !== ':', + isAbsolute = exports.isAbsolute(path), + tail = result[3]; + + if (device && + resolvedDevice && + device.toLowerCase() !== resolvedDevice.toLowerCase()) { + // This path points to another device so it is not applicable + continue; + } + + if (!resolvedDevice) { + resolvedDevice = device; + } + if (!resolvedAbsolute) { + resolvedTail = tail + '\\' + resolvedTail; + resolvedAbsolute = isAbsolute; + } + + if (resolvedDevice && resolvedAbsolute) { + break; + } + } + + // Convert slashes to backslashes when `resolvedDevice` points to an UNC + // root. Also squash multiple slashes into a single one where appropriate. + if (isUnc) { + resolvedDevice = normalizeUNCRoot(resolvedDevice); + } + + // At this point the path should be resolved to a full absolute path, + // but handle relative paths to be safe (might happen when process.cwd() + // fails) + + // Normalize the tail path + + function f(p) { + return !!p; + } + + resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/).filter(f), + !resolvedAbsolute).join('\\'); + + return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || + '.'; + }; + + // windows version + exports.normalize = function(path) { + var result = splitDeviceRe.exec(path), + device = result[1] || '', + isUnc = device && device.charAt(1) !== ':', + isAbsolute = exports.isAbsolute(path), + tail = result[3], + trailingSlash = /[\\\/]$/.test(tail); + + // If device is a drive letter, we'll normalize to lower case. + if (device && device.charAt(1) === ':') { + device = device[0].toLowerCase() + device.substr(1); + } + + // Normalize the tail path + tail = normalizeArray(tail.split(/[\\\/]+/).filter(function(p) { + return !!p; + }), !isAbsolute).join('\\'); + + if (!tail && !isAbsolute) { + tail = '.'; + } + if (tail && trailingSlash) { + tail += '\\'; + } + + // Convert slashes to backslashes when `device` points to an UNC root. + // Also squash multiple slashes into a single one where appropriate. + if (isUnc) { + device = normalizeUNCRoot(device); + } + + return device + (isAbsolute ? '\\' : '') + tail; + }; + + // windows version + exports.isAbsolute = function(path) { + var result = splitDeviceRe.exec(path), + device = result[1] || '', + isUnc = !!device && device.charAt(1) !== ':'; + // UNC paths are always absolute + return !!result[2] || isUnc; + }; + + // windows version + exports.join = function() { + function f(p) { + if (!util.isString(p)) { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + } + + var paths = Array.prototype.filter.call(arguments, f); + var joined = paths.join('\\'); + + // Make sure that the joined path doesn't start with two slashes, because + // normalize() will mistake it for an UNC path then. + // + // This step is skipped when it is very clear that the user actually + // intended to point at an UNC path. This is assumed when the first + // non-empty string arguments starts with exactly two slashes followed by + // at least one more non-slash character. + // + // Note that for normalize() to treat a path as an UNC path it needs to + // have at least 2 components, so we don't filter for that here. + // This means that the user can use join to construct UNC paths from + // a server name and a share name; for example: + // path.join('//server', 'share') -> '\\\\server\\share\') + if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) { + joined = joined.replace(/^[\\\/]{2,}/, '\\'); + } + + return exports.normalize(joined); + }; + + // path.relative(from, to) + // it will solve the relative path from 'from' to 'to', for instance: + // from = 'C:\\orandea\\test\\aaa' + // to = 'C:\\orandea\\impl\\bbb' + // The output of the function should be: '..\\..\\impl\\bbb' + // windows version + exports.relative = function(from, to) { + from = exports.resolve(from); + to = exports.resolve(to); + + // windows is not case sensitive + var lowerFrom = from.toLowerCase(); + var lowerTo = to.toLowerCase(); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end + 1); + } + + var toParts = trim(to.split('\\')); + + var lowerFromParts = trim(lowerFrom.split('\\')); + var lowerToParts = trim(lowerTo.split('\\')); + + var length = Math.min(lowerFromParts.length, lowerToParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (lowerFromParts[i] !== lowerToParts[i]) { + samePartsLength = i; + break; + } + } + + if (samePartsLength == 0) { + return to; + } + + var outputParts = []; + for (var i = samePartsLength; i < lowerFromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('\\'); + }; + + exports.sep = '\\'; + exports.delimiter = ';'; + +} else /* posix */ { + + // Split a filename into [root, dir, basename, ext], unix version + // 'root' is just a slash, or nothing. + var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); + }; + + // path.resolve([from ...], to) + // posix version + exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (!util.isString(path)) { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }; + + // path.normalize(path) + // posix version + exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = path[path.length - 1] === '/', + segments = path.split('/'), + nonEmptySegments = []; + + // Normalize the path + for (var i = 0; i < segments.length; i++) { + if (segments[i]) { + nonEmptySegments.push(segments[i]); + } + } + path = normalizeArray(nonEmptySegments, !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; + }; + + // posix version + exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; + }; + + // posix version + exports.join = function() { + var path = ''; + for (var i = 0; i < arguments.length; i++) { + var segment = arguments[i]; + if (!util.isString(segment)) { + throw new TypeError('Arguments to path.join must be strings'); + } + if (segment) { + if (!path) { + path += segment; + } else { + path += '/' + segment; + } + } + } + return exports.normalize(path); + }; + + + // path.relative(from, to) + // posix version + exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); + }; + + exports.sep = '/'; + exports.delimiter = ':'; +} + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + + +exports.exists = util.deprecate(function(path, callback) { + require('fs').exists(path, callback); +}, 'path.exists is now called `fs.exists`.'); + + +exports.existsSync = util.deprecate(function(path) { + return require('fs').existsSync(path); +}, 'path.existsSync is now called `fs.existsSync`.'); + + +if (isWindows) { + exports._makeLong = function(path) { + // Note: this will *probably* throw somewhere. + if (!util.isString(path)) + return path; + + if (!path) { + return ''; + } + + var resolvedPath = exports.resolve(path); + + if (/^[a-zA-Z]\:\\/.test(resolvedPath)) { + // path is local filesystem path, which needs to be converted + // to long UNC path. + return '\\\\?\\' + resolvedPath; + } else if (/^\\\\[^?.]/.test(resolvedPath)) { + // path is network UNC path, which needs to be converted + // to long UNC path. + return '\\\\?\\UNC\\' + resolvedPath.substring(2); + } + + return path; + }; +} else { + exports._makeLong = function(path) { + return path; + }; +} + +exports.posix = exports; \ No newline at end of file diff --git a/packages/protocol/src/common/helpers.ts b/packages/protocol/src/common/helpers.ts index 6b82345e..5aee5f02 100644 --- a/packages/protocol/src/common/helpers.ts +++ b/packages/protocol/src/common/helpers.ts @@ -34,7 +34,7 @@ export class EvalHelper { // their locations. public modules = { spdlog: require("spdlog") as typeof import("spdlog"), - pty: require("node-pty-prebuilt") as typeof import("node-pty-prebuilt"), + pty: require("node-pty-prebuilt") as typeof import("node-pty"), }; /** diff --git a/packages/runner/src/runner.ts b/packages/runner/src/runner.ts index 0f80acdb..f057aa1b 100644 --- a/packages/runner/src/runner.ts +++ b/packages/runner/src/runner.ts @@ -43,7 +43,6 @@ const execute = (command: string, args: string[] = [], options: cp.SpawnOptions, export type TaskFunction = (runner: Runner) => void | Promise; export interface Runner { - cwd: string; execute(command: string, args?: string[], env?: object): Promise; } @@ -84,6 +83,7 @@ export const run = (name: string = process.argv[2]): void | Promise => { let cwd: string = process.cwd(); const log = logger.named(name); const timer = time(Number.MAX_SAFE_INTEGER); + let outputTimer: NodeJS.Timer | undefined; log.info("Starting..."); const prom = task.func({ set cwd(path: string) { @@ -99,7 +99,19 @@ export const run = (name: string = process.argv[2]): void | Promise => { if (prom) { activated.set(name, prom); + + const doOutput = (): void => { + outputTimer = setTimeout(() => { + log.info("Still running..."); + doOutput(); + }, 60 * 1000 * 5); + }; + doOutput(); + prom.then(() => { + if (outputTimer) { + clearTimeout(outputTimer); + } log.info("Completed!", field("time", timer)); }).catch((ex) => { activated.delete(name); diff --git a/packages/server/package.json b/packages/server/package.json index 317b7ff8..e4e5faf1 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -5,7 +5,7 @@ "files": [], "scripts": { "start": "node --max-old-space-size=32384 --require ts-node/register --require tsconfig-paths/register src/cli.ts", - "build": "rm -rf ./out && export CLI=true && UV_THREADPOOL_SIZE=100 node --max-old-space-size=32384 ../../node_modules/webpack/bin/webpack.js --config ./webpack.config.js", + "build": "rm -rf ./out && cross-env CLI=true UV_THREADPOOL_SIZE=100 node --max-old-space-size=32384 ../../node_modules/webpack/bin/webpack.js --config ./webpack.config.js", "build:nexe": "node scripts/nexe.js" }, "dependencies": { diff --git a/packages/server/src/cli.ts b/packages/server/src/cli.ts index aed92fc1..1532f627 100644 --- a/packages/server/src/cli.ts +++ b/packages/server/src/cli.ts @@ -45,7 +45,7 @@ export class Entry extends Command { } const { args, flags } = this.parse(Entry); - const dataDir = flags["data-dir"] || path.join(os.homedir(), ".vscode-remote"); + const dataDir = flags["data-dir"] || path.join(os.homedir(), ".code-server"); const workingDir = args["workdir"]; setupNativeModules(dataDir); @@ -112,9 +112,9 @@ export class Entry extends Command { } } - logger.info("\u001B[1mvscode-remote v1.0.0"); + logger.info("\u001B[1mcode-server v1.0.0"); // TODO: fill in appropriate doc url - logger.info("Additional documentation: https://coder.com/docs"); + logger.info("Additional documentation: http://github.com/codercom/code-server"); logger.info("Initializing", field("data-dir", dataDir), field("working-dir", workingDir), field("log-dir", logDir)); const sharedProcess = new SharedProcess(dataDir, builtInExtensionsDir); const sendSharedProcessReady = (socket: WebSocket): void => { diff --git a/packages/server/src/modules.ts b/packages/server/src/modules.ts index dc1f5d80..b87b2595 100644 --- a/packages/server/src/modules.ts +++ b/packages/server/src/modules.ts @@ -13,13 +13,13 @@ export const setup = (dataDirectory: string): void => { try { fs.mkdirSync(currentDir); } catch (ex) { - if (ex.code !== "EEXIST" && ex.code !== "EISDIR") { + if (ex.code !== "EEXIST" && ex.code !== "EISDIR" && ex.code !== "ENOENT") { throw ex; } } return currentDir; - }, path.sep); + }); // Might need path.sep here for linux. Having it for windows causes an error because \C:\Users ... const unpackModule = (moduleName: string): void => { const memFile = path.join(isCli ? buildDir! : path.join(__dirname, ".."), "build/dependencies", moduleName); @@ -37,12 +37,13 @@ export const setup = (dataDirectory: string): void => { unpackModule("pty.node"); unpackModule("spdlog.node"); unpackModule("rg"); - const nodePtyUtils = require("../../protocol/node_modules/node-pty-prebuilt/lib/utils") as typeof import("../../protocol/node_modules/node-pty-prebuilt/src/utils"); + // const nodePtyUtils = require("../../protocol/node_modules/node-pty-prebuilt/lib/utils") as typeof import("../../protocol/node_modules/node-pty-prebuilt/src/utils"); // tslint:disable-next-line:no-any - nodePtyUtils.loadNative = (modName: string): any => { - return (typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require)(path.join(dataDirectory, "dependencies", modName + ".node")); - }; + // nodePtyUtils.loadNative = (modName: string): any => { + // return (typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require)(path.join(dataDirectory, "dependencies", modName + ".node")); + // }; (global).RIPGREP_LOCATION = path.join(dataDirectory, "dependencies", "rg"); + (global).NODEPTY_LOCATION = path.join(dataDirectory, "dependencies", "pty.node"); // tslint:disable-next-line:no-any (global).SPDLOG_LOCATION = path.join(dataDirectory, "dependencies", "spdlog.node"); // tslint:disable-next-line:no-unused-expression diff --git a/packages/server/src/vscode/sharedProcess.ts b/packages/server/src/vscode/sharedProcess.ts index 3b9f3f58..db01528f 100644 --- a/packages/server/src/vscode/sharedProcess.ts +++ b/packages/server/src/vscode/sharedProcess.ts @@ -23,7 +23,7 @@ export type SharedProcessEvent = { }; export class SharedProcess { - public readonly socketPath: string = path.join(os.tmpdir(), `.vscode-remote${Math.random().toString()}`); + public readonly socketPath: string = os.platform() === "win32" ? path.join("\\\\?\\pipe", os.tmpdir(), `.code-server${Math.random().toString()}`) : path.join(os.tmpdir(), `.code-server${Math.random().toString()}`); private _state: SharedProcessState = SharedProcessState.Stopped; private activeProcess: ChildProcess | undefined; private ipcHandler: StdioIpcHandler | undefined; diff --git a/packages/server/webpack.config.js b/packages/server/webpack.config.js index b260577d..0df82de3 100644 --- a/packages/server/webpack.config.js +++ b/packages/server/webpack.config.js @@ -31,7 +31,7 @@ module.exports = merge( entry: "./packages/server/src/cli.ts", plugins: [ new webpack.DefinePlugin({ - "process.env.BUILD_DIR": `"${__dirname}"`, + "process.env.BUILD_DIR": `"${__dirname.replace(/\\/g, "\\\\")}"`, "process.env.CLI": `"${process.env.CLI ? "true" : "false"}"`, }), ], diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 637b451c..73deee1c 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -3,7 +3,7 @@ "description": "VS Code implementation of the browser-based IDE client.", "main": "src/index.ts", "scripts": { - "build:bootstrap-fork": "UV_THREADPOOL_SIZE=100 node --max-old-space-size=32384 ../../node_modules/webpack/bin/webpack.js --config ./webpack.bootstrap.config.js" + "build:bootstrap-fork": "cross-env UV_THREADPOOL_SIZE=100 node --max-old-space-size=32384 ../../node_modules/webpack/bin/webpack.js --config ./webpack.bootstrap.config.js" }, "dependencies": { "iconv-lite": "^0.4.24", diff --git a/packages/vscode/src/fill/css.js b/packages/vscode/src/fill/css.js index e878fc7c..9519b515 100644 --- a/packages/vscode/src/fill/css.js +++ b/packages/vscode/src/fill/css.js @@ -2,5 +2,5 @@ module.exports = function(source) { if (this.resourcePath.endsWith(".ts")) { this.resourcePath = this.resourcePath.replace(".ts", ".css"); } - return `module.exports = require("${this.resourcePath}");`; + return `module.exports = require("${this.resourcePath.replace(/\\/g, "\\\\")}");`; }; diff --git a/packages/vscode/src/fill/platform.ts b/packages/vscode/src/fill/platform.ts index 6aa9ff04..efe98c75 100644 --- a/packages/vscode/src/fill/platform.ts +++ b/packages/vscode/src/fill/platform.ts @@ -20,6 +20,7 @@ if (platform.language === "en-US") { (platform as any).isLinux = os.platform() === "linux"; (platform as any).isWindows = os.platform() === "win32"; (platform as any).isMacintosh = os.platform() === "darwin"; +(platform as any).platform = os.platform() === "linux" ? platform.Platform.Linux : os.platform() === "win32" ? platform.Platform.Windows : platform.Platform.Mac; // This is used for keybindings, and in one place to choose between \r\n and \n // (which we change to use platform.isWindows instead). diff --git a/packages/vscode/src/fill/product.ts b/packages/vscode/src/fill/product.ts index 305b728a..3be2971e 100644 --- a/packages/vscode/src/fill/product.ts +++ b/packages/vscode/src/fill/product.ts @@ -1,9 +1,9 @@ import { IProductConfiguration } from "vs/platform/node/product"; const product = { - nameShort: "VSCode", - nameLong: "VSCode Remote", - dataFolderName: ".vscode-remote", + nameShort: "code-server", + nameLong: "code-server", + dataFolderName: ".code-server", extensionsGallery: { serviceUrl: "https://marketplace.visualstudio.com/_apis/public/gallery", cacheUrl: "https://vscode.blob.core.windows.net/gallery/index", diff --git a/packages/vscode/src/vscode-coder.svg b/packages/vscode/src/vscode-coder.svg new file mode 100644 index 00000000..d938d39e --- /dev/null +++ b/packages/vscode/src/vscode-coder.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/vscode/src/vscode.scss b/packages/vscode/src/vscode.scss index e4f56481..4e335adb 100644 --- a/packages/vscode/src/vscode.scss +++ b/packages/vscode/src/vscode.scss @@ -41,3 +41,10 @@ min-width: -moz-fit-content; } } + +.window-appicon { + background-image: url(./vscode-coder.svg) !important; + background-size: 56px !important; + width: 56px !important; + margin-right: 4px; +} diff --git a/packages/vscode/webpack.bootstrap.config.js b/packages/vscode/webpack.bootstrap.config.js index 6796b4a9..df3f6a23 100644 --- a/packages/vscode/webpack.bootstrap.config.js +++ b/packages/vscode/webpack.bootstrap.config.js @@ -36,12 +36,12 @@ module.exports = merge( loader: "ignore-loader", }], }, { - test: /(\/vs\/code\/electron-main\/)|(\/test\/)|(OSSREADME\.json$)|(\.(test\.ts|test\.js|d\.ts|qwoff|node|html|txt|exe|wuff|md|sh|scpt|less)$)/, + test: /((\\|\/)vs(\\|\/)code(\\|\/)electron-main(\\|\/))|((\\|\/)test(\\|\/))|(OSSREADME\.json$)|(\.(test\.ts|test\.js|d\.ts|qwoff|node|html|txt|exe|wuff|md|sh|scpt|less)$)/, use: [{ loader: "ignore-loader", }], }], - noParse: /\/test\/|\.test\.jsx?|\.test\.tsx?|tsconfig.+\.json$/, + noParse: /(\\|\/)test(\\|\/)|\.test\.jsx?|\.test\.tsx?|tsconfig.+\.json$/, }, resolve: { alias: { diff --git a/packages/web/package.json b/packages/web/package.json index 79f23c79..e7293329 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,6 +1,6 @@ { "name": "@coder/web", "scripts": { - "build": "UV_THREADPOOL_SIZE=100 node --max-old-space-size=32384 ../../node_modules/webpack/bin/webpack.js --config ./webpack.config.js" + "build": "cross-env UV_THREADPOOL_SIZE=100 node --max-old-space-size=32384 ../../node_modules/webpack/bin/webpack.js --config ./webpack.config.js" } } \ No newline at end of file diff --git a/packages/web/webpack.config.js b/packages/web/webpack.config.js index 0346b070..5472ee6a 100644 --- a/packages/web/webpack.config.js +++ b/packages/web/webpack.config.js @@ -48,7 +48,7 @@ module.exports = merge( // path.posix and path.parse are undefined (among other things possibly). // Also if we don't provide the full path, the code in vscode will import // from vscode's node_modules which is the wrong version. - "path": path.join(root, "node_modules", "path-browserify"), + "path": path.join(fills, "path.js"), "crypto": "crypto-browserify", "http": "http-browserify", diff --git a/scripts/build.sh b/scripts/build.sh index 3d954fee..7cb6f1c2 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,4 +1,5 @@ #!/bin/bash set -e +npm install -g cross-env yarn task build:server:binary diff --git a/scripts/install-packages.ts b/scripts/install-packages.ts index c674f9ae..c32d7cee 100644 --- a/scripts/install-packages.ts +++ b/scripts/install-packages.ts @@ -7,45 +7,48 @@ import { logger, field } from "../packages/logger"; /** * Install dependencies for a single package. */ -const doInstall = (pkg: string, path: string): void => { +const doInstall = (pkg: string, path: string): Promise => { logger.info(`Installing "${pkg}" dependencies...`); - exec("yarn", { - cwd: path, - maxBuffer: 1024 * 1024 * 10, - }, (error, stdout, stderr) => { - if (error) { - logger.error( - `Failed to install "${pkg}" dependencies`, - field("error", error), - field("stdout", stdout), - field("stderr", stderr), - ); - process.exit(1); - } - logger.info(`Successfully grabbed \"${pkg}\" dependencies!`); + return new Promise((resolve): void => { + exec("yarn --network-concurrency 1", { + cwd: path, + maxBuffer: 1024 * 1024 * 10, + }, (error, stdout, stderr) => { + if (error) { + logger.error( + `Failed to install "${pkg}" dependencies`, + field("error", error), + field("stdout", stdout), + field("stderr", stderr), + ); + process.exit(1); + } + + logger.info(`Successfully grabbed \"${pkg}\" dependencies!`); + resolve(); + }); }); }; /** * Install dependencies for all packages. */ -const handlePackages = (dir: string): void => { - readdirSync(dir).forEach((pkg) => { +const handlePackages = async (dir: string): Promise => { + const dirs = readdirSync(dir); + for (let i = 0; i < dirs.length; i++) { + const pkg = dirs[i]; const pkgDir = join(dir, pkg); const pkgJsonPath = join(pkgDir, "package.json"); if (existsSync(pkgJsonPath)) { - doInstall(pkg, pkgDir); + const ip = doInstall(pkg, pkgDir); + if (os.platform() === "win32") { + await ip; + } } - }); + } }; -if (os.platform() === "win32") { - execSync("yarn", { - cwd: resolve(__dirname, "..", "packages", "vscode"), - maxBuffer: 1024 * 1024 * 10, - }); -} - -handlePackages(resolve(__dirname, "..", "packages")); -handlePackages(resolve(__dirname, "..", "packages", "app")); +handlePackages(resolve(__dirname, "..", "packages")).then(() => { + return handlePackages(resolve(__dirname, "..", "packages", "app")); +}); diff --git a/scripts/vscode.patch b/scripts/vscode.patch index aa56dffc..47286e43 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -282,7 +282,7 @@ index 605c1209e1..e8131513de 100644 - platform.isMacintosh + browser.isMacintosh diff --git a/src/vs/loader.js b/src/vs/loader.js -index 4eddcab3a0..5d80768406 100644 +index 4eddcab3a0..abda3c04f9 100644 --- a/src/vs/loader.js +++ b/src/vs/loader.js @@ -671,4 +671,4 @@ var AMDLoader; @@ -294,15 +294,20 @@ index 4eddcab3a0..5d80768406 100644 + this._vm = require('vm'); + this._path = require('path'); + this._crypto = require('crypto'); -@@ -736,0 +737,7 @@ var AMDLoader; +@@ -736,0 +737,12 @@ var AMDLoader; + const context = require.context("../", true, /.*/); + if (scriptSrc.indexOf("file:///") !== -1) { + const vsSrc = scriptSrc.split("file:///")[1].split(".js")[0]; -+ if (vsSrc && vsSrc.startsWith("vs/")) { ++ if (this._env.isWindows) { ++ const vsSrcSplit = vsSrc.split(":/"); ++ vsSrcSplit.shift(); ++ vsSrc = vsSrcSplit.join(":/"); ++ } ++ if (vsSrc && vsSrc.startsWith("vs/")) { + scriptSrc = `node|./${vsSrc}`; + } + } -@@ -741 +748 @@ var AMDLoader; +@@ -741 +753 @@ var AMDLoader; - moduleExports_1 = nodeRequire(pieces[1]); + moduleExports_1 = context(pieces[1]); diff --git a/src/vs/platform/clipboard/electron-browser/clipboardService.ts b/src/vs/platform/clipboard/electron-browser/clipboardService.ts diff --git a/scripts/webpack.general.config.js b/scripts/webpack.general.config.js index caf23326..9fcafa2f 100644 --- a/scripts/webpack.general.config.js +++ b/scripts/webpack.general.config.js @@ -45,7 +45,7 @@ module.exports = (options = {}) => ({ type: "javascript/auto", }, { // Fixes spdlog. - test: /spdlog\/index\.js/, + test: /spdlog(\\|\/)index\.js/, loader: "string-replace-loader", options: { multiple: [{ @@ -56,7 +56,7 @@ module.exports = (options = {}) => ({ }, }, { // This is required otherwise it attempts to require("package.json") - test: /@oclif\/command\/lib\/index\.js/, + test: /@oclif(\\|\/)command(\\|\/)lib(\\|\/)index\.js/, loader: "string-replace-loader", options: { multiple: [{ @@ -66,7 +66,7 @@ module.exports = (options = {}) => ({ }], }, }, { - test: /node\-pty\/lib\/index\.js/, + test: /node\-pty\-prebuilt(\\|\/)lib(\\|\/)index\.js/, loader: "string-replace-loader", options: { multiple: [{ @@ -75,6 +75,16 @@ module.exports = (options = {}) => ({ flags: "g", }], }, + }, { + test: /node\-pty\-prebuilt(\\|\/)lib(\\|\/)windowsPtyAgent\.js/, + loader: "string-replace-loader", + options: { + multiple: [{ + search: "var pty = .*;", + replace: "var pty = __non_webpack_require__(global.NODEPTY_LOCATION);", + flags: "g", + }], + }, }], }, resolve: {