@@ -60,9 +60,12 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
6060 private readonly dotnetExecutable : string ;
6161 private globalResolver : GlobalInstallerResolver | null ;
6262
63- private acquisitionPromises : { [ installKeys : string ] : Promise < string > | undefined } ;
63+ private acquisitionPromises : { [ installKey : string ] : Promise < string > | undefined } ;
6464 private extensionContext : IVSCodeExtensionContext ;
6565
66+ // @member usingNoInstallInvoker - Only use this for test when using the No Install Invoker to fake the worker into thinking a path is on disk.
67+ protected usingNoInstallInvoker = false ;
68+
6669 constructor ( protected readonly context : IAcquisitionWorkerContext , private readonly utilityContext : IUtilityContext , extensionContext : IVSCodeExtensionContext ) {
6770 const dotnetExtension = os . platform ( ) === 'win32' ? '.exe' : '' ;
6871 this . dotnetExecutable = `dotnet${ dotnetExtension } ` ;
@@ -79,8 +82,14 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
7982
8083 this . removeFolderRecursively ( this . context . installDirectoryProvider . getStoragePath ( ) ) ;
8184
82- await this . context . extensionState . update ( this . installingVersionsKey , [ ] ) ;
83- await this . context . extensionState . update ( this . installedVersionsKey , [ ] ) ;
85+ // This does not uninstall global things yet, so don't remove their keys.
86+ const installingVersions = this . context . extensionState . get < string [ ] > ( this . installingVersionsKey , [ ] ) ;
87+ const remainingInstallingVersions = installingVersions . filter ( x => this . isGlobalInstallKey ( x ) ) ;
88+ await this . context . extensionState . update ( this . installingVersionsKey , remainingInstallingVersions ) ;
89+
90+ const installedVersions = this . context . extensionState . get < string [ ] > ( this . installedVersionsKey , [ ] ) ;
91+ const remainingInstalledVersions = installedVersions . filter ( x => this . isGlobalInstallKey ( x ) ) ;
92+ await this . context . extensionState . update ( this . installedVersionsKey , remainingInstalledVersions ) ;
8493
8594 this . context . eventStream . post ( new DotnetUninstallAllCompleted ( ) ) ;
8695 }
@@ -100,6 +109,11 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
100109 return this . acquire ( await installerResolver . getFullySpecifiedVersion ( ) , false , installerResolver ) ;
101110 }
102111
112+ private isGlobalInstallKey ( installKey : string ) : boolean
113+ {
114+ return installKey . toLowerCase ( ) . includes ( 'global' ) ;
115+ }
116+
103117 /**
104118 *
105119 * @remarks this is simply a wrapper around the acquire function.
@@ -109,7 +123,15 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
109123 return this . acquire ( version , true , undefined , invoker ) ;
110124 }
111125
112- public async acquireStatus ( version : string , installRuntime : boolean , architecture ? : string ) : Promise < IDotnetAcquireResult | undefined > {
126+ /**
127+ *
128+ * @param version The version of the runtime or sdk to check
129+ * @param installRuntime Whether this is a local runtime status check or a local SDK status check.
130+ * @param architecture The architecture of the install. Undefined means it will be the default arch, which is the node platform arch.
131+ * @returns The result of the install with the path to dotnet if installed, else undefined.
132+ */
133+ public async acquireStatus ( version : string , installRuntime : boolean , architecture ? : string ) : Promise < IDotnetAcquireResult | undefined >
134+ {
113135 const installKey = DotnetCoreAcquisitionWorker . getInstallKeyCustomArchitecture ( version , architecture ? architecture : this . installingArchitecture )
114136
115137 const existingAcquisitionPromise = this . acquisitionPromises [ installKey ] ;
@@ -129,7 +151,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
129151 installedVersions = await this . managePreinstalledVersion ( dotnetInstallDir , installedVersions ) ;
130152 }
131153
132- if ( installedVersions . includes ( installKey ) && fs . existsSync ( dotnetPath ) )
154+ if ( installedVersions . includes ( installKey ) && ( fs . existsSync ( dotnetPath ) || this . usingNoInstallInvoker ) )
133155 {
134156 // Requested version has already been installed.
135157 this . context . eventStream . post ( new DotnetAcquisitionStatusResolved ( installKey , version ) ) ;
@@ -170,6 +192,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
170192 Debugging . log ( `The Acquisition Worker has Determined a Global Install was requested.` , this . context . eventStream ) ;
171193
172194 acquisitionPromise = this . acquireGlobalCore ( globalInstallerResolver , installKey ) . catch ( ( error : Error ) => {
195+ this . removeVersionFromExtensionState ( this . installingVersionsKey , installKey ) ;
173196 delete this . acquisitionPromises [ installKey ] ;
174197 throw new Error ( `.NET Acquisition Failed: ${ error . message } ` ) ;
175198 } ) ;
@@ -179,11 +202,14 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
179202 Debugging . log ( `The Acquisition Worker has Determined a Local Install was requested.` , this . context . eventStream ) ;
180203
181204 acquisitionPromise = this . acquireLocalCore ( version , installRuntime , installKey , localInvoker ! ) . catch ( ( error : Error ) => {
205+ this . removeVersionFromExtensionState ( this . installingVersionsKey , installKey ) ;
182206 delete this . acquisitionPromises [ installKey ] ;
183207 throw new Error ( `.NET Acquisition Failed: ${ error . message } ` ) ;
184208 } ) ;
185209 }
186210
211+ // Put this promise into the list so we can let other requests run at the same time
212+ // Allows us to return the end result of this current request for any following duplicates while we are still running.
187213 this . acquisitionPromises [ installKey ] = acquisitionPromise ;
188214 return acquisitionPromise . then ( ( res ) => ( { dotnetPath : res } ) ) ;
189215 }
@@ -229,7 +255,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
229255 installedVersions = await this . managePreinstalledVersion ( dotnetInstallDir , installedVersions ) ;
230256 }
231257
232- if ( installedVersions . includes ( installKey ) && fs . existsSync ( dotnetPath ) ) {
258+ if ( installedVersions . includes ( installKey ) && ( fs . existsSync ( dotnetPath ) || this . usingNoInstallInvoker ) ) {
233259 // Version requested has already been installed.
234260 this . context . installationValidator . validateDotnetInstall ( installKey , dotnetPath ) ;
235261 this . context . eventStream . post ( new DotnetAcquisitionAlreadyInstalled ( installKey ,
@@ -261,6 +287,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
261287 await this . removeVersionFromExtensionState ( this . installingVersionsKey , installKey ) ;
262288 await this . addVersionToExtensionState ( this . installedVersionsKey , installKey ) ;
263289
290+ delete this . acquisitionPromises [ installKey ] ;
264291 return dotnetPath ;
265292 }
266293
@@ -280,7 +307,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
280307 }
281308 if ( uninstallLocalSDK )
282309 {
283- await this . uninstallRuntimeOrSDK ( installKey ) ;
310+ await this . uninstallLocalRuntimeOrSDK ( installKey ) ;
284311 }
285312 }
286313 }
@@ -330,6 +357,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
330357 await this . addVersionToExtensionState ( this . installedVersionsKey , installKey ) ;
331358
332359 this . context . eventStream . post ( new DotnetGlobalAcquisitionCompletionEvent ( `The version ${ installKey } completed successfully.` ) ) ;
360+ delete this . acquisitionPromises [ installKey ] ;
333361 return installedSDKPath ;
334362 }
335363
@@ -366,7 +394,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
366394 if ( legacyInstall . includes ( version ) )
367395 {
368396 this . context . eventStream . post ( new DotnetLegacyInstallRemovalRequestEvent ( `Trying to remove legacy install: ${ legacyInstall } of ${ version } .` ) ) ;
369- await this . uninstallRuntimeOrSDK ( legacyInstall ) ;
397+ await this . uninstallLocalRuntimeOrSDK ( legacyInstall ) ;
370398 }
371399 }
372400 }
@@ -398,7 +426,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
398426 {
399427 this . context . eventStream . post ( new DotnetInstallGraveyardEvent (
400428 `Attempting to remove .NET at ${ installKey } again, as it was left in the graveyard.` ) ) ;
401- await this . uninstallRuntimeOrSDK ( installKey ) ;
429+ await this . uninstallLocalRuntimeOrSDK ( installKey ) ;
402430 }
403431 }
404432
@@ -425,7 +453,13 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker
425453 await this . context . extensionState . update ( this . installPathsGraveyardKey , graveyard ) ;
426454 }
427455
428- public async uninstallRuntimeOrSDK ( installKey : string ) {
456+ public async uninstallLocalRuntimeOrSDK ( installKey : string )
457+ {
458+ if ( this . isGlobalInstallKey ( installKey ) )
459+ {
460+ return ;
461+ }
462+
429463 try
430464 {
431465 delete this . acquisitionPromises [ installKey ] ;
0 commit comments