1- import {
2- LogOutputChannel ,
3- ProgressLocation ,
4- ShellExecution ,
5- Task ,
6- TaskPanelKind ,
7- TaskRevealKind ,
8- TaskScope ,
9- tasks ,
10- window ,
11- } from 'vscode' ;
1+ import { LogOutputChannel , ProgressLocation , ShellExecution , Task , TaskPanelKind , TaskRevealKind , TaskScope } from 'vscode' ;
122import { PythonEnvironmentApi } from '../../api' ;
133import { spawnProcess } from '../../common/childProcess.apis' ;
144import { UvInstallStrings } from '../../common/localize' ;
155import { traceError , traceInfo , traceLog } from '../../common/logging' ;
166import { getGlobalPersistentState } from '../../common/persistentState' ;
17- import { executeTask } from '../../common/tasks.apis' ;
7+ import { executeTask , onDidEndTaskProcess } from '../../common/tasks.apis' ;
188import { EventNames } from '../../common/telemetry/constants' ;
199import { sendTelemetryEvent } from '../../common/telemetry/sender' ;
2010import { createDeferred } from '../../common/utils/deferred' ;
2111import { isWindows } from '../../common/utils/platformUtils' ;
22- import { showInformationMessage } from '../../common/window.apis' ;
12+ import { showErrorMessage , showInformationMessage , withProgress } from '../../common/window.apis' ;
2313import { isUvInstalled , resetUvInstallationCache } from './helpers' ;
2414
2515const UV_INSTALL_PYTHON_DONT_ASK_KEY = 'python-envs:uv:UV_INSTALL_PYTHON_DONT_ASK' ;
@@ -72,6 +62,9 @@ async function getUvInstallCommand(): Promise<{ executable: string; args: string
7262 } ;
7363}
7464
65+ // Timeout for task completion (5 minutes)
66+ const TASK_TIMEOUT_MS = 5 * 60 * 1000 ;
67+
7568/**
7669 * Runs a shell command as a visible VS Code task and waits for completion.
7770 * @param name Task name displayed in the UI
@@ -92,20 +85,29 @@ async function runTaskAndWait(name: string, executable: string, args: string[]):
9285
9386 const deferred = createDeferred < boolean > ( ) ;
9487
95- const disposable = tasks . onDidEndTaskProcess ( ( e ) => {
88+ const disposable = onDidEndTaskProcess ( ( e ) => {
9689 if ( e . execution . task === task ) {
97- disposable . dispose ( ) ;
9890 deferred . resolve ( e . exitCode === 0 ) ;
9991 }
10092 } ) ;
10193
94+ // Set up timeout to prevent indefinite waiting
95+ const timeoutId = setTimeout ( ( ) => {
96+ if ( ! deferred . completed ) {
97+ traceError ( `Task "${ name } " timed out after ${ TASK_TIMEOUT_MS / 1000 } seconds` ) ;
98+ deferred . resolve ( false ) ;
99+ }
100+ } , TASK_TIMEOUT_MS ) ;
101+
102102 try {
103103 await executeTask ( task ) ;
104104 return await deferred . promise ;
105105 } catch ( err ) {
106- disposable . dispose ( ) ;
107106 traceError ( `Task "${ name } " failed:` , err ) ;
108107 return false ;
108+ } finally {
109+ clearTimeout ( timeoutId ) ;
110+ disposable . dispose ( ) ;
109111 }
110112}
111113
@@ -218,7 +220,7 @@ export async function installPythonWithUv(api: PythonEnvironmentApi, log?: LogOu
218220
219221 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_STARTED , undefined , { uvAlreadyInstalled : uvInstalled } ) ;
220222
221- return await window . withProgress (
223+ return await withProgress (
222224 {
223225 location : ProgressLocation . Notification ,
224226 title : UvInstallStrings . installingPython ,
@@ -232,7 +234,7 @@ export async function installPythonWithUv(api: PythonEnvironmentApi, log?: LogOu
232234 const uvSuccess = await installUv ( log ) ;
233235 if ( ! uvSuccess ) {
234236 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_FAILED , undefined , { stage : 'uvInstall' } ) ;
235- window . showErrorMessage ( UvInstallStrings . uvInstallFailed ) ;
237+ showErrorMessage ( UvInstallStrings . uvInstallFailed ) ;
236238 return false ;
237239 }
238240 }
@@ -241,7 +243,7 @@ export async function installPythonWithUv(api: PythonEnvironmentApi, log?: LogOu
241243 const pythonSuccess = await installPythonViaUv ( log ) ;
242244 if ( ! pythonSuccess ) {
243245 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_FAILED , undefined , { stage : 'pythonInstall' } ) ;
244- window . showErrorMessage ( UvInstallStrings . installFailed ) ;
246+ showErrorMessage ( UvInstallStrings . installFailed ) ;
245247 return false ;
246248 }
247249
@@ -250,7 +252,7 @@ export async function installPythonWithUv(api: PythonEnvironmentApi, log?: LogOu
250252 await api . refreshEnvironments ( undefined ) ;
251253
252254 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_COMPLETED ) ;
253- window . showInformationMessage ( UvInstallStrings . installComplete ) ;
255+ showInformationMessage ( UvInstallStrings . installComplete ) ;
254256
255257 return true ;
256258 } ,
0 commit comments