Commit b3745b1b authored by Ivan Mazhukin's avatar Ivan Mazhukin

add local epm play actions

parent 89a9aedc
......@@ -38,9 +38,13 @@ The same VSIX can be installed from the VS Code command `Extensions: Install fro
- `Run app on systems`: asks for an app and target systems.
- `Run app preset`: asks for an app and `main`, `russian`, or `all`.
- `Run exec command`: asks for a shell command and target systems or preset.
- `./bin/epm play <app>`: runs a local play command outside Docker.
- `./bin/epm play --latest <app>`: runs a local latest play command outside Docker.
- `Rerun last command`: repeats the last generated command.
- `Open log folder`: opens `${XDG_STATE_HOME:-$HOME/.local/state}/epm-docker-test` or the configured log root.
For local `epm play` commands, the app name is inferred from the active editor when the file is in `play.d`, `pack.d`, or `repack.d`. The extension first checks simple shell variables such as `PRODUCT=rstudio` or `PKGNAME=rstudio`, then falls back to the file name without extension.
## Favorites
Pinned commands can be added to workspace settings:
......@@ -73,4 +77,5 @@ Important settings:
- `epmDockerTest.defaultMode`: `auto`, `local`, or `remote`.
- `epmDockerTest.latest`: pass `--latest`.
- `epmDockerTest.parallelJobs`: pass `-j N` when greater than `1`.
- `epmDockerTest.localEpmRoot`: local eepm tree for outside-container `./bin/epm play` commands.
- `epmDockerTest.eepmDir`, `epmDockerTest.eepmSource`, `epmDockerTest.remoteHost`, `epmDockerTest.remoteUser`, `epmDockerTest.builderUser`, `epmDockerTest.builderPath`, `epmDockerTest.logRoot`: map to the same script options.
......@@ -28,6 +28,8 @@ function activate(context) {
vscode.commands.registerCommand('epmDockerTest.runApp', runApp),
vscode.commands.registerCommand('epmDockerTest.runPreset', runPreset),
vscode.commands.registerCommand('epmDockerTest.runExec', runExec),
vscode.commands.registerCommand('epmDockerTest.runLocalPlay', () => runLocalPlay(false)),
vscode.commands.registerCommand('epmDockerTest.runLocalPlayLatest', () => runLocalPlay(true)),
vscode.commands.registerCommand('epmDockerTest.rerunLast', rerunLast),
vscode.commands.registerCommand('epmDockerTest.openLogs', openLogs),
vscode.commands.registerCommand('epmDockerTest.refresh', () => provider.refresh()),
......@@ -78,6 +80,10 @@ class ActionsProvider {
commandItem('Run app on systems', 'epmDockerTest.runApp', undefined, new vscode.ThemeIcon('run')),
commandItem('Run app preset', 'epmDockerTest.runPreset', undefined, new vscode.ThemeIcon('list-selection')),
commandItem('Run exec command', 'epmDockerTest.runExec', undefined, new vscode.ThemeIcon('terminal')),
separatorItem('Local EPM'),
commandItem('./bin/epm play <app>', 'epmDockerTest.runLocalPlay', undefined, new vscode.ThemeIcon('play')),
commandItem('./bin/epm play --latest <app>', 'epmDockerTest.runLocalPlayLatest', undefined, new vscode.ThemeIcon('cloud-download')),
separatorItem('Tools'),
commandItem('Rerun last command', 'epmDockerTest.rerunLast', undefined, new vscode.ThemeIcon('debug-restart')),
commandItem('Open log folder', 'epmDockerTest.openLogs', undefined, new vscode.ThemeIcon('folder-opened')),
commandItem('Configure', 'epmDockerTest.configure', undefined, new vscode.ThemeIcon('settings-gear'))
......@@ -98,11 +104,19 @@ function commandItem(label, command, argument, iconPath) {
return item;
}
function separatorItem(label) {
const item = new vscode.TreeItem(`----- ${label} -----`, vscode.TreeItemCollapsibleState.None);
item.iconPath = new vscode.ThemeIcon('dash');
return item;
}
async function runQuick() {
const choice = await vscode.window.showQuickPick([
{ label: '$(run) Run app on systems', command: 'epmDockerTest.runApp' },
{ label: '$(list-selection) Run app preset', command: 'epmDockerTest.runPreset' },
{ label: '$(terminal) Run exec command', command: 'epmDockerTest.runExec' },
{ label: '$(play) Local ./bin/epm play', command: 'epmDockerTest.runLocalPlay' },
{ label: '$(cloud-download) Local ./bin/epm play --latest', command: 'epmDockerTest.runLocalPlayLatest' },
{ label: '$(debug-restart) Rerun last command', command: 'epmDockerTest.rerunLast' },
{ label: '$(folder-opened) Open log folder', command: 'epmDockerTest.openLogs' }
], {
......@@ -202,6 +216,50 @@ async function runExec() {
}
}
async function runLocalPlay(latest) {
const eepmRoot = resolveWorkspacePath(getConfig().get('localEpmRoot', '/home/vano/eter/static2/eepm'));
const epm = path.join(eepmRoot, 'bin', 'epm');
if (!fs.existsSync(epm)) {
vscode.window.showErrorMessage(`Could not find local epm: ${epm}`);
return;
}
const inferred = inferAppFromActiveEditor(eepmRoot);
const fallback = getWorkspaceState('lastLocalApp', getWorkspaceState('lastApp', ''));
const app = await vscode.window.showInputBox({
title: latest ? 'Local epm play --latest' : 'Local epm play',
prompt: inferred
? `Application name inferred from ${inferred.source}`
: 'Application name for local ./bin/epm play',
value: inferred?.app || fallback,
placeHolder: 'rstudio'
});
if (!app) {
return;
}
await setWorkspaceState('lastLocalApp', app);
const args = ['play'];
if (latest) {
args.push('--latest');
}
args.push(app);
const command = [
'cd',
shellQuote(eepmRoot),
'&&',
'./bin/epm',
...args.map(shellQuote)
].join(' ');
lastRun = command;
await setWorkspaceState('lastCommand', command);
sendToTerminal(command);
}
async function rerunLast() {
const command = getWorkspaceState('lastCommand', lastRun);
if (!command) {
......@@ -389,6 +447,41 @@ function findScript(workspaceFolder) {
return candidates.find((candidate) => fs.existsSync(candidate));
}
function inferAppFromActiveEditor(eepmRoot) {
const editor = vscode.window.activeTextEditor;
const filePath = editor?.document?.uri?.scheme === 'file' ? editor.document.uri.fsPath : undefined;
if (!filePath) {
return undefined;
}
const dirName = path.basename(path.dirname(filePath));
if (!['play.d', 'pack.d', 'repack.d'].includes(dirName)) {
return undefined;
}
const baseName = path.basename(filePath, path.extname(filePath));
const parsed = inferAppFromFileContent(filePath);
const app = parsed || baseName;
const relative = path.relative(eepmRoot, filePath);
const source = relative && !relative.startsWith('..') ? relative : filePath;
return { app, source };
}
function inferAppFromFileContent(filePath) {
try {
const text = fs.readFileSync(filePath, 'utf8').slice(0, 8192);
for (const variable of ['PRODUCT', 'PKGNAME', 'APP', 'APPNAME']) {
const match = text.match(new RegExp(`^${variable}=(["']?)([A-Za-z0-9._+-]+)\\1\\s*$`, 'm'));
if (match) {
return match[2];
}
}
} catch {
return undefined;
}
return undefined;
}
function resolveWorkspacePath(value) {
const expanded = expandHome(value);
if (path.isAbsolute(expanded)) {
......
......@@ -17,7 +17,9 @@
"onCommand:epmDockerTest.runApp",
"onCommand:epmDockerTest.runPreset",
"onCommand:epmDockerTest.runExec",
"onCommand:epmDockerTest.rerunLast"
"onCommand:epmDockerTest.rerunLast",
"onCommand:epmDockerTest.runLocalPlay",
"onCommand:epmDockerTest.runLocalPlayLatest"
],
"main": "./extension.js",
"contributes": {
......@@ -39,6 +41,14 @@
"title": "EPM Docker Test: Run Exec Command"
},
{
"command": "epmDockerTest.runLocalPlay",
"title": "EPM Docker Test: Local epm play"
},
{
"command": "epmDockerTest.runLocalPlayLatest",
"title": "EPM Docker Test: Local epm play --latest"
},
{
"command": "epmDockerTest.rerunLast",
"title": "EPM Docker Test: Rerun Last Command"
},
......@@ -143,6 +153,11 @@
"default": "",
"description": "Optional --log-root value."
},
"epmDockerTest.localEpmRoot": {
"type": "string",
"default": "/home/vano/eter/static2/eepm",
"description": "Path to the local eepm tree used by local ./bin/epm play commands."
},
"epmDockerTest.additionalArgs": {
"type": "array",
"default": [],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment