@@ -467,35 +467,42 @@ export class ExtensionsScanner extends Disposable {
467467 return null ;
468468 }
469469
470- async extractUserExtension ( extensionKey : ExtensionKey , zipPath : string , metadata : Metadata , token : CancellationToken ) : Promise < ILocalExtension > {
470+ async extractUserExtension ( extensionKey : ExtensionKey , zipPath : string , metadata : Metadata , removeIfExists : boolean , token : CancellationToken ) : Promise < ILocalExtension > {
471471 await this . cleanUpGeneratedFoldersPromise . catch ( ( ) => undefined ) ;
472472
473473 const folderName = extensionKey . toString ( ) ;
474474 const tempPath = path . join ( this . extensionsScannerService . userExtensionsLocation . fsPath , `.${ generateUuid ( ) } ` ) ;
475475 const extensionPath = path . join ( this . extensionsScannerService . userExtensionsLocation . fsPath , folderName ) ;
476476
477- try {
478- await pfs . Promises . rm ( extensionPath ) ;
479- } catch ( error ) {
480- throw new ExtensionManagementError ( nls . localize ( 'errorDeleting' , "Unable to delete the existing folder '{0}' while installing the extension '{1}'. Please delete the folder manually and try again" , extensionPath , extensionKey . id ) , ExtensionManagementErrorCode . Delete ) ;
477+ let exists = await this . fileService . exists ( URI . file ( extensionPath ) ) ;
478+
479+ if ( exists && removeIfExists ) {
480+ try {
481+ await pfs . Promises . rm ( extensionPath ) ;
482+ } catch ( error ) {
483+ throw new ExtensionManagementError ( nls . localize ( 'errorDeleting' , "Unable to delete the existing folder '{0}' while installing the extension '{1}'. Please delete the folder manually and try again" , extensionPath , extensionKey . id ) , ExtensionManagementErrorCode . Delete ) ;
484+ }
485+ exists = false ;
481486 }
482487
483- await this . extractAtLocation ( extensionKey , zipPath , tempPath , token ) ;
484- await this . extensionsScannerService . updateMetadata ( URI . file ( tempPath ) , metadata ) ;
488+ if ( ! exists ) {
489+ await this . extractAtLocation ( extensionKey , zipPath , tempPath , token ) ;
490+ await this . extensionsScannerService . updateMetadata ( URI . file ( tempPath ) , metadata ) ;
485491
486- try {
487- this . _onExtract . fire ( URI . file ( extensionPath ) ) ;
488- await this . rename ( extensionKey , tempPath , extensionPath , Date . now ( ) + ( 2 * 60 * 1000 ) /* Retry for 2 minutes */ ) ;
489- this . logService . info ( 'Renamed to' , extensionPath ) ;
490- } catch ( error ) {
491492 try {
492- await pfs . Promises . rm ( tempPath ) ;
493- } catch ( e ) { /* ignore */ }
494- if ( error . code === 'ENOTEMPTY' ) {
495- this . logService . info ( `Rename failed because extension was installed by another source. So ignoring renaming.` , extensionKey . id ) ;
496- } else {
497- this . logService . info ( `Rename failed because of ${ getErrorMessage ( error ) } . Deleted from extracted location` , tempPath ) ;
498- throw error ;
493+ this . _onExtract . fire ( URI . file ( extensionPath ) ) ;
494+ await this . rename ( extensionKey , tempPath , extensionPath , Date . now ( ) + ( 2 * 60 * 1000 ) /* Retry for 2 minutes */ ) ;
495+ this . logService . info ( 'Renamed to' , extensionPath ) ;
496+ } catch ( error ) {
497+ try {
498+ await pfs . Promises . rm ( tempPath ) ;
499+ } catch ( e ) { /* ignore */ }
500+ if ( error . code === 'ENOTEMPTY' ) {
501+ this . logService . info ( `Rename failed because extension was installed by another source. So ignoring renaming.` , extensionKey . id ) ;
502+ } else {
503+ this . logService . info ( `Rename failed because of ${ getErrorMessage ( error ) } . Deleted from extracted location` , tempPath ) ;
504+ throw error ;
505+ }
499506 }
500507 }
501508
@@ -776,11 +783,11 @@ abstract class InstallExtensionTask extends AbstractExtensionTask<ILocalExtensio
776783 return local ;
777784 }
778785
779- protected async extractExtension ( { zipPath, key, metadata } : InstallableExtension , token : CancellationToken ) : Promise < ILocalExtension > {
786+ protected async extractExtension ( { zipPath, key, metadata } : InstallableExtension , removeIfExists : boolean , token : CancellationToken ) : Promise < ILocalExtension > {
780787 let local = await this . unsetIfUninstalled ( key ) ;
781788 if ( ! local ) {
782789 this . logService . trace ( 'Extracting extension...' , key . id ) ;
783- local = await this . extensionsScanner . extractUserExtension ( key , zipPath , metadata , token ) ;
790+ local = await this . extensionsScanner . extractUserExtension ( key , zipPath , metadata , removeIfExists , token ) ;
784791 this . logService . info ( 'Extracting extension completed.' , key . id ) ;
785792 }
786793 return local ;
@@ -863,7 +870,7 @@ export class InstallGalleryExtensionTask extends InstallExtensionTask {
863870 try {
864871 this . _verificationStatus = verificationStatus ;
865872 this . validateManifest ( location . fsPath ) ;
866- const local = await this . extractExtension ( { zipPath : location . fsPath , key : ExtensionKey . create ( this . gallery ) , metadata } , token ) ;
873+ const local = await this . extractExtension ( { zipPath : location . fsPath , key : ExtensionKey . create ( this . gallery ) , metadata } , false , token ) ;
867874 return [ local , metadata ] ;
868875 } catch ( error ) {
869876 try {
@@ -945,7 +952,7 @@ class InstallVSIXTask extends InstallExtensionTask {
945952 }
946953 }
947954
948- const local = await this . extractExtension ( { zipPath : path . resolve ( this . location . fsPath ) , key : extensionKey , metadata } , token ) ;
955+ const local = await this . extractExtension ( { zipPath : path . resolve ( this . location . fsPath ) , key : extensionKey , metadata } , true , token ) ;
949956 return [ local , metadata ] ;
950957 }
951958
0 commit comments