Skip to content

Commit

Permalink
Merge pull request #24 from stuartleeks/sl/devcontainers
Browse files Browse the repository at this point in the history
Add support for devcontainers
  • Loading branch information
Tyriar authored Jul 10, 2020
2 parents 77d008d + f3dfca2 commit b8c85c5
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 5 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ The context menu also works in [WSL remotes](https://marketplace.visualstudio.co

Opening the terminal when in a [SSH remote](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) workspace will ssh into the remote in Windows Terminal.

**Dev container support**

Opening the terminal when in a [devcontainer remote](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) workspaces will `docker exec` into the remote in Windows Terminal.

**Several commands for launching WT**

See the Feature Contributions tab for a full list of commands that can be setup with [custom keybindings](https://code.visualstudio.com/docs/getstarted/keybindings).
Expand Down
12 changes: 12 additions & 0 deletions src/docker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { exec } from 'child_process';

export function runDockerCommand(command: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
exec(`docker ${command}`, (err, stdout, stderr) => {
if (err) {
reject(err);
}
resolve(stdout.trim());
});
});
}
30 changes: 25 additions & 5 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as vscode from 'vscode';
import { getSettingsContents } from './settings';
import { spawn } from 'child_process';
import * as path from 'path';
import { getSettingsContents, getVscodeQuality } from './settings';
import { exec, spawn } from 'child_process';
import { convertWslPathToWindows } from './wsl';
import { stat } from 'fs';
import { runDockerCommand } from './docker';
import { readFile, stat, appendFile } from 'fs';
import { promisify } from 'util';
import { dirname } from 'path';
import { detectInstallation } from './installation';
import { IWTProfile, IWTInstallation } from './interfaces';
import { resolveSSHHostName } from './ssh';
Expand Down Expand Up @@ -67,6 +68,25 @@ async function openWindowsTerminal(profile: IWTProfile, uri?: vscode.Uri) {
} else {
args.push('ssh', '-t', remoteMachine, `cd ${uri.path} && ${shellScript(OS.UNIXLIKE)}`);
}
} else if (uri.authority.startsWith('dev-container+')) {
// The authority after the '+' is a hex-encoded string for the base path of the project on the host
const hexString = uri.authority.split('+')[1];
const hexValues = new Array(hexString.length / 2);
for (let i = 0; i < hexValues.length; i++) {
const current = hexString.slice(2 * i, 2 * i + 2);
hexValues[i] = parseInt(current, 16);
}
const hostPath = String.fromCharCode(...hexValues);

// devcontainers are labelled based on stable/insider version, so find that to add to the filter
const quality = await getVscodeQuality();
const containerID = await runDockerCommand(`ps --filter label=vsch.local.folder=${hostPath} --filter "label=vsch.quality=${quality}" --format "{{.ID}}" --no-trunc`);
if (containerID === '') {
return;
}

const containerFolder = path.dirname(uri.path);
args.push('docker', 'exec', '-it', '--workdir', containerFolder, containerID, 'bash');
} else {
let cwd = uri.fsPath;
if (uri.authority) {
Expand All @@ -78,7 +98,7 @@ async function openWindowsTerminal(profile: IWTProfile, uri?: vscode.Uri) {
}
}
if (await isFile(cwd)) {
cwd = dirname(cwd);
cwd = path.dirname(cwd);
}
args.push('-d', cwd);
}
Expand Down
10 changes: 10 additions & 0 deletions src/settings.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as vscode from 'vscode';
import * as path from 'path';
import * as jsoncParser from 'jsonc-parser';
import { promisify } from 'util';
import { readFile, exists } from 'fs';
Expand All @@ -16,3 +18,11 @@ export async function getSettingsContents(settingsPath: string): Promise<IWTSett

return jsoncParser.parse(rawString) as IWTSettings;
}

const readLocalFile = promisify(readFile);
export async function getVscodeQuality(): Promise<String> {
const jsonPath = path.join(vscode.env.appRoot, 'product.json');
const raw = await readLocalFile(jsonPath, 'utf8');
const json = JSON.parse(raw);
return json.quality;
}

0 comments on commit b8c85c5

Please # to comment.