start-command 0.24.6 → 0.24.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # start-command
2
2
 
3
+ ## 0.24.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 1eef620: fix: display `bash -c "..."` commands with quotes in command line output (issue #91)
8
+
9
+ When a command like `bash -i -c nvm --version` was passed to Docker isolation,
10
+ the displayed command line was missing quotes around the `-c` script argument,
11
+ making the output misleading (showing `bash -i -c nvm --version` instead of
12
+ `bash -i -c "nvm --version"`).
13
+
14
+ A new `buildDisplayCommand()` helper is added in `shell-utils.js` that quotes
15
+ any space-containing `-c` script arguments so the displayed command accurately
16
+ reflects how it was interpreted. Shell command helpers are extracted from
17
+ `isolation.js` into a new `shell-utils.js` module to keep file sizes within limits.
18
+
3
19
  ## 0.24.6
4
20
 
5
21
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "start-command",
3
- "version": "0.24.6",
3
+ "version": "0.24.7",
4
4
  "description": "Gamification of coding, execute any command with ability to auto-report issues on GitHub",
5
5
  "main": "src/bin/cli.js",
6
6
  "exports": {
@@ -214,29 +214,12 @@ function getShellInteractiveFlag(shellPath) {
214
214
  const shellName = shellPath.split('/').pop();
215
215
  return shellName === 'bash' || shellName === 'zsh' ? '-i' : null;
216
216
  }
217
- const SHELL_NAMES = ['bash', 'zsh', 'sh', 'fish', 'ksh', 'csh', 'tcsh', 'dash'];
218
- /** True if command is a bare shell invocation (no -c); avoids bash-inside-bash (issue #84). */
219
- function isInteractiveShellCommand(command) {
220
- const parts = command.trim().split(/\s+/);
221
- return SHELL_NAMES.includes(path.basename(parts[0])) && !parts.includes('-c');
222
- }
223
- /** True if command is a shell invocation with -c (e.g. `bash -i -c "cmd"`); avoids double-wrapping (issue #91). */
224
- function isShellInvocationWithArgs(command) {
225
- const parts = command.trim().split(/\s+/);
226
- return SHELL_NAMES.includes(path.basename(parts[0])) && parts.includes('-c');
227
- }
228
- /** Build argv for shell-with-c command; everything after -c is one argument (reverses commandArgs.join(' ')). */
229
- function buildShellWithArgsCmdArgs(command) {
230
- const parts = command.trim().split(/\s+/);
231
- const cIdx = parts.indexOf('-c');
232
- if (cIdx === -1) {
233
- return parts;
234
- }
235
- const scriptArg = parts.slice(cIdx + 1).join(' ');
236
- return scriptArg.length > 0
237
- ? [...parts.slice(0, cIdx + 1), scriptArg]
238
- : parts.slice(0, cIdx + 1);
239
- }
217
+ const {
218
+ isInteractiveShellCommand,
219
+ isShellInvocationWithArgs,
220
+ buildShellWithArgsCmdArgs,
221
+ buildDisplayCommand,
222
+ } = require('./shell-utils');
240
223
 
241
224
  /** Returns true if the current process has a TTY attached. */
242
225
  function hasTTY() {
@@ -764,7 +747,7 @@ function runInDocker(command, options = {}) {
764
747
  : detectShellInEnvironment('docker', options, options.shell);
765
748
  const shellInteractiveFlag = getShellInteractiveFlag(shellToUse);
766
749
 
767
- console.log(outputBlocks.createCommandLine(command));
750
+ console.log(outputBlocks.createCommandLine(buildDisplayCommand(command)));
768
751
  console.log();
769
752
 
770
753
  try {
@@ -974,6 +957,7 @@ module.exports = {
974
957
  isInteractiveShellCommand,
975
958
  isShellInvocationWithArgs,
976
959
  buildShellWithArgsCmdArgs,
960
+ buildDisplayCommand,
977
961
  detectShellInEnvironment,
978
962
  runInScreen,
979
963
  runInTmux,
@@ -0,0 +1,47 @@
1
+ /** Shell command detection and argument-building utilities for start-command */
2
+
3
+ const path = require('path');
4
+
5
+ const SHELL_NAMES = ['bash', 'zsh', 'sh', 'fish', 'ksh', 'csh', 'tcsh', 'dash'];
6
+
7
+ /** True if command is a bare shell invocation (no -c); avoids bash-inside-bash (issue #84). */
8
+ function isInteractiveShellCommand(command) {
9
+ const parts = command.trim().split(/\s+/);
10
+ return SHELL_NAMES.includes(path.basename(parts[0])) && !parts.includes('-c');
11
+ }
12
+
13
+ /** True if command is a shell invocation with -c (e.g. `bash -i -c "cmd"`); avoids double-wrapping (issue #91). */
14
+ function isShellInvocationWithArgs(command) {
15
+ const parts = command.trim().split(/\s+/);
16
+ return SHELL_NAMES.includes(path.basename(parts[0])) && parts.includes('-c');
17
+ }
18
+
19
+ /** Build argv for shell-with-c command; everything after -c is one argument (reverses commandArgs.join(' ')). */
20
+ function buildShellWithArgsCmdArgs(command) {
21
+ const parts = command.trim().split(/\s+/);
22
+ const cIdx = parts.indexOf('-c');
23
+ if (cIdx === -1) {
24
+ return parts;
25
+ }
26
+ const scriptArg = parts.slice(cIdx + 1).join(' ');
27
+ return scriptArg.length > 0
28
+ ? [...parts.slice(0, cIdx + 1), scriptArg]
29
+ : parts.slice(0, cIdx + 1);
30
+ }
31
+
32
+ /** Build a display string for a command, quoting arguments that contain spaces (issue #91). */
33
+ function buildDisplayCommand(command) {
34
+ if (!isShellInvocationWithArgs(command)) {
35
+ return command;
36
+ }
37
+ const argv = buildShellWithArgsCmdArgs(command);
38
+ return argv.map((arg) => (arg.includes(' ') ? `"${arg}"` : arg)).join(' ');
39
+ }
40
+
41
+ module.exports = {
42
+ SHELL_NAMES,
43
+ isInteractiveShellCommand,
44
+ isShellInvocationWithArgs,
45
+ buildShellWithArgsCmdArgs,
46
+ buildDisplayCommand,
47
+ };
@@ -34,6 +34,7 @@ const {
34
34
  isInteractiveShellCommand,
35
35
  isShellInvocationWithArgs,
36
36
  buildShellWithArgsCmdArgs,
37
+ buildDisplayCommand,
37
38
  } = require('../src/lib/isolation');
38
39
 
39
40
  // Helper: mirrors the attached-mode command-args construction logic in runInDocker.
@@ -258,3 +259,38 @@ describe('isShellInvocationWithArgs is mutually exclusive with isInteractiveShel
258
259
  });
259
260
  }
260
261
  });
262
+
263
+ describe('buildDisplayCommand (issue #91 display fix)', () => {
264
+ it('should quote the -c script argument when it contains spaces', () => {
265
+ assert.strictEqual(
266
+ buildDisplayCommand('bash -i -c nvm --version'),
267
+ 'bash -i -c "nvm --version"'
268
+ );
269
+ });
270
+
271
+ it('should quote the -c script argument for plain "bash -c echo hello"', () => {
272
+ assert.strictEqual(
273
+ buildDisplayCommand('bash -c echo hello'),
274
+ 'bash -c "echo hello"'
275
+ );
276
+ });
277
+
278
+ it('should not double-quote if script has no spaces', () => {
279
+ assert.strictEqual(buildDisplayCommand('bash -c ls'), 'bash -c ls');
280
+ });
281
+
282
+ it('should return command unchanged for non-shell-with-args commands', () => {
283
+ assert.strictEqual(buildDisplayCommand('nvm --version'), 'nvm --version');
284
+ });
285
+
286
+ it('should return command unchanged for bare shell invocations', () => {
287
+ assert.strictEqual(buildDisplayCommand('bash -i'), 'bash -i');
288
+ });
289
+
290
+ it('should handle zsh -c with spaces', () => {
291
+ assert.strictEqual(
292
+ buildDisplayCommand('zsh -c echo hello world'),
293
+ 'zsh -c "echo hello world"'
294
+ );
295
+ });
296
+ });