Skip to content

Commit 5c23abb

Browse files
committed
updates based on comments feedback
1 parent ea77f6c commit 5c23abb

File tree

5 files changed

+68
-44
lines changed

5 files changed

+68
-44
lines changed
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
#! /bin/bash
22
# Bash script
33
python $BUNDLED_DEBUGPY_PATH --listen 0 --wait-for-client $@
4-
echo "Executed: python $BUNDLED_DEBUGPY_PATH --listen 0 --wait-for-client $@"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
@echo off
22
:: Bat script
3-
python %BUNDLED_DEBUGPY_PATH% --listen 0 --wait-for-client %*
3+
python %BUNDLED_DEBUGPY_PATH% --listen 0 --wait-for-client %*

src/extension/extensionInit.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ export async function registerDebugger(context: IExtensionContext): Promise<IExt
248248
window.activeTextEditor?.document.languageId === 'python',
249249
);
250250

251-
registerNoConfigDebug(context);
251+
context.subscriptions.push(
252+
await registerNoConfigDebug(context.environmentVariableCollection, context.extensionPath),
253+
);
252254

253255
return buildApi();
254256
}

src/extension/noConfigDebugInit.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,61 @@
33

44
import * as fs from 'fs';
55
import * as path from 'path';
6-
import { IExtensionContext } from './common/types';
7-
import { DebugSessionOptions, RelativePattern } from 'vscode';
6+
import * as crypto from 'crypto';
7+
import * as os from 'os';
8+
import { DebugSessionOptions, Disposable, GlobalEnvironmentVariableCollection, RelativePattern } from 'vscode';
89
import { createFileSystemWatcher, debugStartDebugging } from './utils';
9-
import { traceError, traceVerbose } from './common/log/logging';
10+
import { traceError, traceLog, traceVerbose } from './common/log/logging';
1011

1112
/**
1213
* Registers the configuration-less debugging setup for the extension.
1314
*
1415
* This function sets up environment variables and a file system watcher to
1516
* facilitate debugging without requiring a pre-configured launch.json file.
1617
*
17-
* @param context - The extension context which provides access to the environment variable collection and subscriptions.
18+
* @param envVarCollection - The collection of environment variables to be modified.
19+
* @param extPath - The path to the extension directory.
1820
*
1921
* Environment Variables:
2022
* - `DEBUGPY_ADAPTER_ENDPOINTS`: Path to the file containing the debugger adapter endpoint.
2123
* - `BUNDLED_DEBUGPY_PATH`: Path to the bundled debugpy library.
2224
* - `PATH`: Appends the path to the noConfigScripts directory.
2325
*/
24-
export async function registerNoConfigDebug(context: IExtensionContext): Promise<void> {
25-
const collection = context.environmentVariableCollection;
26+
export async function registerNoConfigDebug(
27+
envVarCollection: GlobalEnvironmentVariableCollection,
28+
extPath: string,
29+
): Promise<Disposable> {
30+
const collection = envVarCollection;
31+
32+
// create a temp directory for the noConfigDebugAdapterEndpoints
33+
// file path format: tempDir/noConfigDebugAdapterEndpoints-<randomString>/debuggerAdapterEndpoint.txt
34+
const randomSuffix = crypto.randomBytes(10).toString('hex');
35+
const tempDirName = `noConfigDebugAdapterEndpoints-${randomSuffix}`;
36+
let tempDirPath = path.join(os.tmpdir(), tempDirName);
37+
try {
38+
traceLog('Attempting to use temp directory for noConfigDebugAdapterEndpoints, dir name:', tempDirName);
39+
await fs.promises.mkdir(tempDirPath, { recursive: true });
40+
} catch (error) {
41+
// Handle the error when accessing the temp directory
42+
traceError('Error accessing temp directory:', error, ' Attempt to use extension root dir instead');
43+
// Make new temp directory in extension root dird
44+
tempDirPath = path.join(extPath, '.temp');
45+
await fs.promises.mkdir(tempDirPath, { recursive: true });
46+
}
47+
const tempFilePath = path.join(tempDirPath, 'debuggerAdapterEndpoint.txt');
2648

2749
// Add env vars for DEBUGPY_ADAPTER_ENDPOINTS, BUNDLED_DEBUGPY_PATH, and PATH
28-
const debugAdapterEndpointDir = path.join(context.extensionPath, 'noConfigDebugAdapterEndpoints');
29-
const debuggerAdapterEndpointPath = path.join(debugAdapterEndpointDir, 'debuggerAdapterEndpoint.txt');
30-
collection.replace('DEBUGPY_ADAPTER_ENDPOINTS', debuggerAdapterEndpointPath);
50+
collection.replace('DEBUGPY_ADAPTER_ENDPOINTS', tempFilePath);
3151

32-
const noConfigScriptsDir = path.join(context.extensionPath, 'bundled', 'scripts', 'noConfigScripts');
52+
const noConfigScriptsDir = path.join(extPath, 'bundled', 'scripts', 'noConfigScripts');
3353
const pathSeparator = process.platform === 'win32' ? ';' : ':';
3454
collection.append('PATH', `${pathSeparator}${noConfigScriptsDir}`);
3555

36-
const bundledDebugPath = path.join(context.extensionPath, 'bundled', 'libs', 'debugpy');
56+
const bundledDebugPath = path.join(extPath, 'bundled', 'libs', 'debugpy');
3757
collection.replace('BUNDLED_DEBUGPY_PATH', bundledDebugPath);
3858

3959
// create file system watcher for the debuggerAdapterEndpointFolder for when the communication port is written
40-
const fileSystemWatcher = createFileSystemWatcher(new RelativePattern(debugAdapterEndpointDir, '**/*'));
60+
const fileSystemWatcher = createFileSystemWatcher(new RelativePattern(tempDirPath, '**/*'));
4161
const fileCreationEvent = fileSystemWatcher.onDidCreate(async (uri) => {
4262
const filePath = uri.fsPath;
4363
fs.readFile(filePath, (err, data) => {
@@ -87,6 +107,10 @@ export async function registerNoConfigDebug(context: IExtensionContext): Promise
87107
});
88108
JSON.parse;
89109
});
90-
context.subscriptions.push(fileCreationEvent);
91-
context.subscriptions.push(fileSystemWatcher);
110+
return Promise.resolve(
111+
new Disposable(() => {
112+
fileSystemWatcher.dispose();
113+
fileCreationEvent.dispose();
114+
}),
115+
);
92116
}

src/test/unittest/noConfigDebugInit.unit.test.ts

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,44 @@ import { DebugConfiguration, DebugSessionOptions, RelativePattern, Uri } from 'v
1010
import * as utils from '../../extension/utils';
1111
import { assert } from 'console';
1212
import * as fs from 'fs';
13+
import * as os from 'os';
14+
import * as crypto from 'crypto';
1315

1416
suite('setup for no-config debug scenario', function () {
1517
let envVarCollectionReplaceStub: sinon.SinonStub;
1618
let envVarCollectionAppendStub: sinon.SinonStub;
1719
let context: TypeMoq.IMock<IExtensionContext>;
18-
let debugAdapterEndpointDir: string;
19-
let debuggerAdapterEndpointPath: string;
2020
let noConfigScriptsDir: string;
2121
let bundledDebugPath: string;
2222
let DEBUGPY_ADAPTER_ENDPOINTS = 'DEBUGPY_ADAPTER_ENDPOINTS';
2323
let BUNDLED_DEBUGPY_PATH = 'BUNDLED_DEBUGPY_PATH';
24+
let tempDirPath: string;
2425

2526
const testDataDir = path.join(__dirname, 'testData');
2627
const testFilePath = path.join(testDataDir, 'debuggerAdapterEndpoint.txt');
27-
suiteSetup(() => {
28-
// create file called testData/debuggerAdapterEndpoint.txt
29-
if (!fs.existsSync(testDataDir)) {
30-
fs.mkdirSync(testDataDir);
31-
}
32-
fs.writeFileSync(testFilePath, JSON.stringify({ client: { port: 5678 } }));
33-
});
3428
setup(() => {
35-
context = TypeMoq.Mock.ofType<IExtensionContext>();
36-
37-
context.setup((c) => (c as any).extensionPath).returns(() => 'fake/extension/path');
38-
context.setup((c) => c.subscriptions).returns(() => []);
39-
debugAdapterEndpointDir = path.join(context.object.extensionPath, 'noConfigDebugAdapterEndpoints');
40-
debuggerAdapterEndpointPath = path.join(debugAdapterEndpointDir, 'debuggerAdapterEndpoint.txt');
41-
noConfigScriptsDir = path.join(context.object.extensionPath, 'bundled/scripts/noConfigScripts');
42-
bundledDebugPath = path.join(context.object.extensionPath, 'bundled/libs/debugpy');
29+
try {
30+
context = TypeMoq.Mock.ofType<IExtensionContext>();
31+
32+
const randomSuffix = '1234567899';
33+
const tempDirName = `noConfigDebugAdapterEndpoints-${randomSuffix}`;
34+
tempDirPath = path.join(os.tmpdir(), tempDirName);
35+
context.setup((c) => (c as any).extensionPath).returns(() => 'fake/extension/path');
36+
context.setup((c) => c.subscriptions).returns(() => []);
37+
noConfigScriptsDir = path.join(context.object.extensionPath, 'bundled/scripts/noConfigScripts');
38+
bundledDebugPath = path.join(context.object.extensionPath, 'bundled/libs/debugpy');
39+
40+
// Stub crypto.randomBytes with proper typing
41+
let randomBytesStub = sinon.stub(crypto, 'randomBytes');
42+
// Provide a valid Buffer object
43+
randomBytesStub.callsFake((_size: number) => Buffer.from('1234567899', 'hex'));
44+
} catch (error) {
45+
console.error('Error in setup:', error);
46+
}
4347
});
4448
teardown(() => {
4549
sinon.restore();
4650
});
47-
suiteTeardown(() => {
48-
if (fs.existsSync(testDataDir)) {
49-
fs.rmSync(testDataDir, { recursive: true, force: true });
50-
}
51-
});
5251

5352
test('should add environment variables for DEBUGPY_ADAPTER_ENDPOINTS, BUNDLED_DEBUGPY_PATH, and PATH', async () => {
5453
const environmentVariableCollectionMock = TypeMoq.Mock.ofType<any>();
@@ -60,7 +59,7 @@ suite('setup for no-config debug scenario', function () {
6059
.setup((x) => x.replace(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
6160
.callback((key, value) => {
6261
if (key === DEBUGPY_ADAPTER_ENDPOINTS) {
63-
assert(value === debuggerAdapterEndpointPath);
62+
assert(value.includes('noConfigDebugAdapterEndpoints-1234567899'));
6463
} else if (key === BUNDLED_DEBUGPY_PATH) {
6564
assert(value === bundledDebugPath);
6665
}
@@ -80,7 +79,7 @@ suite('setup for no-config debug scenario', function () {
8079
setupFileSystemWatchers();
8180

8281
// run init for no config debug
83-
await registerNoConfigDebug(context.object);
82+
await registerNoConfigDebug(context.object.environmentVariableCollection, context.object.extensionPath);
8483

8584
// assert that functions called right number of times
8685
sinon.assert.calledTwice(envVarCollectionReplaceStub);
@@ -94,11 +93,11 @@ suite('setup for no-config debug scenario', function () {
9493
let createFileSystemWatcherFunct = setupFileSystemWatchers();
9594

9695
// Act
97-
await registerNoConfigDebug(context.object);
96+
await registerNoConfigDebug(context.object.environmentVariableCollection, context.object.extensionPath);
9897

9998
// Assert
10099
sinon.assert.calledOnce(createFileSystemWatcherFunct);
101-
const expectedPattern = new RelativePattern(debugAdapterEndpointDir, '**/*');
100+
const expectedPattern = new RelativePattern(tempDirPath, '**/*');
102101
sinon.assert.calledWith(createFileSystemWatcherFunct, expectedPattern);
103102
});
104103

@@ -127,7 +126,7 @@ suite('setup for no-config debug scenario', function () {
127126
const debugStub = sinon.stub(utils, 'debugStartDebugging').resolves(true);
128127

129128
// Act
130-
await registerNoConfigDebug(context.object);
129+
await registerNoConfigDebug(context.object.environmentVariableCollection, context.object.extensionPath);
131130

132131
// Assert
133132
sinon.assert.calledOnce(debugStub);

0 commit comments

Comments
 (0)