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 ...@@ -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 on systems`: asks for an app and target systems.
- `Run app preset`: asks for an app and `main`, `russian`, or `all`. - `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. - `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. - `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. - `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 ## Favorites
Pinned commands can be added to workspace settings: Pinned commands can be added to workspace settings:
...@@ -73,4 +77,5 @@ Important settings: ...@@ -73,4 +77,5 @@ Important settings:
- `epmDockerTest.defaultMode`: `auto`, `local`, or `remote`. - `epmDockerTest.defaultMode`: `auto`, `local`, or `remote`.
- `epmDockerTest.latest`: pass `--latest`. - `epmDockerTest.latest`: pass `--latest`.
- `epmDockerTest.parallelJobs`: pass `-j N` when greater than `1`. - `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. - `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) { ...@@ -28,6 +28,8 @@ function activate(context) {
vscode.commands.registerCommand('epmDockerTest.runApp', runApp), vscode.commands.registerCommand('epmDockerTest.runApp', runApp),
vscode.commands.registerCommand('epmDockerTest.runPreset', runPreset), vscode.commands.registerCommand('epmDockerTest.runPreset', runPreset),
vscode.commands.registerCommand('epmDockerTest.runExec', runExec), 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.rerunLast', rerunLast),
vscode.commands.registerCommand('epmDockerTest.openLogs', openLogs), vscode.commands.registerCommand('epmDockerTest.openLogs', openLogs),
vscode.commands.registerCommand('epmDockerTest.refresh', () => provider.refresh()), vscode.commands.registerCommand('epmDockerTest.refresh', () => provider.refresh()),
...@@ -78,6 +80,10 @@ class ActionsProvider { ...@@ -78,6 +80,10 @@ class ActionsProvider {
commandItem('Run app on systems', 'epmDockerTest.runApp', undefined, new vscode.ThemeIcon('run')), 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 app preset', 'epmDockerTest.runPreset', undefined, new vscode.ThemeIcon('list-selection')),
commandItem('Run exec command', 'epmDockerTest.runExec', undefined, new vscode.ThemeIcon('terminal')), 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('Rerun last command', 'epmDockerTest.rerunLast', undefined, new vscode.ThemeIcon('debug-restart')),
commandItem('Open log folder', 'epmDockerTest.openLogs', undefined, new vscode.ThemeIcon('folder-opened')), commandItem('Open log folder', 'epmDockerTest.openLogs', undefined, new vscode.ThemeIcon('folder-opened')),
commandItem('Configure', 'epmDockerTest.configure', undefined, new vscode.ThemeIcon('settings-gear')) commandItem('Configure', 'epmDockerTest.configure', undefined, new vscode.ThemeIcon('settings-gear'))
...@@ -98,11 +104,19 @@ function commandItem(label, command, argument, iconPath) { ...@@ -98,11 +104,19 @@ function commandItem(label, command, argument, iconPath) {
return item; 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() { async function runQuick() {
const choice = await vscode.window.showQuickPick([ const choice = await vscode.window.showQuickPick([
{ label: '$(run) Run app on systems', command: 'epmDockerTest.runApp' }, { label: '$(run) Run app on systems', command: 'epmDockerTest.runApp' },
{ label: '$(list-selection) Run app preset', command: 'epmDockerTest.runPreset' }, { label: '$(list-selection) Run app preset', command: 'epmDockerTest.runPreset' },
{ label: '$(terminal) Run exec command', command: 'epmDockerTest.runExec' }, { 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: '$(debug-restart) Rerun last command', command: 'epmDockerTest.rerunLast' },
{ label: '$(folder-opened) Open log folder', command: 'epmDockerTest.openLogs' } { label: '$(folder-opened) Open log folder', command: 'epmDockerTest.openLogs' }
], { ], {
...@@ -202,6 +216,50 @@ async function runExec() { ...@@ -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() { async function rerunLast() {
const command = getWorkspaceState('lastCommand', lastRun); const command = getWorkspaceState('lastCommand', lastRun);
if (!command) { if (!command) {
...@@ -389,6 +447,41 @@ function findScript(workspaceFolder) { ...@@ -389,6 +447,41 @@ function findScript(workspaceFolder) {
return candidates.find((candidate) => fs.existsSync(candidate)); 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) { function resolveWorkspacePath(value) {
const expanded = expandHome(value); const expanded = expandHome(value);
if (path.isAbsolute(expanded)) { if (path.isAbsolute(expanded)) {
......
...@@ -17,7 +17,9 @@ ...@@ -17,7 +17,9 @@
"onCommand:epmDockerTest.runApp", "onCommand:epmDockerTest.runApp",
"onCommand:epmDockerTest.runPreset", "onCommand:epmDockerTest.runPreset",
"onCommand:epmDockerTest.runExec", "onCommand:epmDockerTest.runExec",
"onCommand:epmDockerTest.rerunLast" "onCommand:epmDockerTest.rerunLast",
"onCommand:epmDockerTest.runLocalPlay",
"onCommand:epmDockerTest.runLocalPlayLatest"
], ],
"main": "./extension.js", "main": "./extension.js",
"contributes": { "contributes": {
...@@ -39,6 +41,14 @@ ...@@ -39,6 +41,14 @@
"title": "EPM Docker Test: Run Exec Command" "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", "command": "epmDockerTest.rerunLast",
"title": "EPM Docker Test: Rerun Last Command" "title": "EPM Docker Test: Rerun Last Command"
}, },
...@@ -143,6 +153,11 @@ ...@@ -143,6 +153,11 @@
"default": "", "default": "",
"description": "Optional --log-root value." "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": { "epmDockerTest.additionalArgs": {
"type": "array", "type": "array",
"default": [], "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