diff --git a/package-lock.json b/package-lock.json index 24be0ec..8d01659 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "esbuild": "^0.25.10", "eslint": "^9.0.0", "mocha": "^11.7.4", - "ovsx": "^0.9.0", + "ovsx": "^0.10.6", "sinon": "^21.0.0", "tsx": "^4.20.6", "typescript": "^5.9.3" @@ -1680,9 +1680,9 @@ "license": "MIT" }, "node_modules/@textlint/linter-formatter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -2317,15 +2317,15 @@ } }, "node_modules/@vscode/vsce/node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -2341,11 +2341,11 @@ } }, "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/brace-expansion": "^5.0.0" }, @@ -4216,9 +4216,9 @@ "optional": true }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -4902,9 +4902,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -5050,13 +5050,13 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", + "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", "dev": true, "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^1.4.2", "safe-buffer": "^5.0.1" } }, diff --git a/src/shared/utils/ddev-utils.ts b/src/shared/utils/ddev-utils.ts index 35159d4..1ed3570 100644 --- a/src/shared/utils/ddev-utils.ts +++ b/src/shared/utils/ddev-utils.ts @@ -83,10 +83,7 @@ export class DdevUtils { */ public static isToolInstalled(toolName: string, workspacePath: string): boolean { try { - execSync(`ddev exec ${toolName} --version`, { - cwd: workspacePath, - stdio: 'ignore' - }); + this.execDdev(`${toolName} --version`, workspacePath); return true; } catch (error) { return false; @@ -112,10 +109,7 @@ export class DdevUtils { // Try to run the tool try { - execSync(`ddev exec ${toolName} --version`, { - cwd: workspacePath, - stdio: 'ignore' - }); + this.execDdev(`${toolName} --version`, workspacePath); return { isValid: true @@ -188,7 +182,11 @@ export class DdevUtils { */ public static execDdev(command: string, workspacePath: string, allowedExitCodes: number[] = [0]): string { try { - return execSync(`ddev exec ${command}`, { + // Wrap command in bash -c to allow setting environment variables (specifically disabling Xdebug) + // This fixes issues where Xdebug causes the command to hang or run slowly + // We use single quotes for the bash command and escape any single quotes in the original command + const escapedCommand = command.replace(/'/g, "'\\''"); + return execSync(`ddev exec bash -c 'XDEBUG_MODE=off ${escapedCommand}'`, { cwd: workspacePath, encoding: 'utf-8' }); diff --git a/src/test/ddev-utils.test.ts b/src/test/ddev-utils.test.ts index 7759a9e..e77c136 100644 --- a/src/test/ddev-utils.test.ts +++ b/src/test/ddev-utils.test.ts @@ -138,4 +138,28 @@ suite('DdevUtils Test Suite', () => { assert.ok(result.userMessage?.includes('phpstan is not installed')); assert.ok(result.userMessage?.includes('phpstan/phpstan')); }); + + test('execDdev wraps command with XDEBUG_MODE=off', () => { + execSyncStub.returns('output'); + + const result = DdevUtils.execDdev('phpstan analyze', '/test/workspace'); + + assert.strictEqual(result, 'output'); + assert.strictEqual(execSyncStub.calledOnce, true); + const callArgs = execSyncStub.firstCall.args; + assert.ok(callArgs[0].includes("XDEBUG_MODE=off")); + assert.ok(callArgs[0].includes("bash -c")); + assert.ok(callArgs[0].includes("'XDEBUG_MODE=off phpstan analyze'")); + }); + + test('execDdev escapes single quotes in command', () => { + execSyncStub.returns('output'); + + const result = DdevUtils.execDdev("echo 'hello'", '/test/workspace'); + + assert.strictEqual(result, 'output'); + const callArgs = execSyncStub.firstCall.args; + // Should be: ddev exec bash -c 'XDEBUG_MODE=off echo '\''hello'\''' + assert.ok(callArgs[0].includes("'XDEBUG_MODE=off echo '\\''hello'\\'''")); + }); });