88import  *  as  workspaceInstance  from  '@gitpod/gitpod-protocol/lib/workspace-instance' ; 
99import  *  as  grpc  from  '@grpc/grpc-js' ; 
1010import  *  as  fs  from  'fs' ; 
11+ import  *  as  os  from  'os' ; 
12+ import  *  as  uuid  from  'uuid' ; 
1113import  {  GitpodPluginModel ,  GitpodExtensionContext ,  setupGitpodContext ,  registerTasks ,  registerIpcHookCli  }  from  'gitpod-shared' ; 
1214import  {  GetTokenRequest  }  from  '@gitpod/supervisor-api-grpc/lib/token_pb' ; 
1315import  {  PortsStatus ,  ExposedPortInfo ,  PortsStatusRequest ,  PortsStatusResponse ,  PortAutoExposure ,  PortVisibility ,  OnPortExposedAction  }  from  '@gitpod/supervisor-api-grpc/lib/status_pb' ; 
@@ -19,7 +21,9 @@ import * as path from 'path';
1921import  {  URL  }  from  'url' ; 
2022import  *  as  util  from  'util' ; 
2123import  *  as  vscode  from  'vscode' ; 
22- import  {  ThrottledDelayer  }  from  './async' ; 
24+ import  {  ThrottledDelayer  }  from  './util/async' ; 
25+ import  {  download  }  from  './util/download' ; 
26+ import  {  getManifest  }  from  './util/extensionManagmentUtill' ; 
2327
2428let  gitpodContext : GitpodExtensionContext  |  undefined ; 
2529export  async  function  activate ( context : vscode . ExtensionContext )  { 
@@ -185,7 +189,7 @@ export function registerAuth(context: GitpodExtensionContext): void {
185189			if  ( ! userResponse . ok )  { 
186190				throw  new  Error ( `Getting GitHub account info failed: ${ userResponse . statusText }  ) ; 
187191			} 
188- 			const  user :  {  id : string ,  login : string  }   =   await   userResponse . json ( ) ; 
192+ 			const  user   =   await   ( userResponse . json ( )   as   Promise < {  id : string ,  login : string  } > ) ; 
189193			return  { 
190194				id : user . id , 
191195				accountName : user . login 
@@ -774,7 +778,7 @@ interface IOpenVSXQueryResult {
774778	extensions : IOpenVSXExtensionsMetadata [ ] ; 
775779} 
776780
777- async  function  validateExtensions ( extensionsToValidate : {  id : string ,  version ?: string  } [ ] ,  token : vscode . CancellationToken )  { 
781+ async  function  validateExtensions ( extensionsToValidate : {  id : string ,  version ?: string  } [ ] ,  linkToValidate :  string [ ] ,   token : vscode . CancellationToken )  { 
778782	const  allUserExtensions  =  vscode . extensions . all . filter ( ext  =>  ! ext . packageJSON [ 'isBuiltin' ]  &&  ! ext . packageJSON [ 'isUserBuiltin' ] ) ; 
779783
780784	const  lookup  =  new  Set < string > ( extensionsToValidate . map ( ( {  id } )  =>  id ) ) ; 
@@ -795,7 +799,8 @@ async function validateExtensions(extensionsToValidate: { id: string, version?:
795799			return  { 
796800				extensions : [ ] , 
797801				missingMachined : [ ] , 
798- 				uninstalled : [ ] 
802+ 				uninstalled : [ ] , 
803+ 				links : [ ] 
799804			} ; 
800805		} 
801806	} 
@@ -806,21 +811,21 @@ async function validateExtensions(extensionsToValidate: { id: string, version?:
806811			`${ process . env . VSX_REGISTRY_URL  ||  'https://open-vsx.org' }  , 
807812			{ 
808813				method : 'POST' , 
809- 				timeout : 5000 , 
810814				headers : { 
811815					'Content-Type' : 'application/json' , 
812816					'Accept' : 'application/json' 
813817				} , 
814818				body : JSON . stringify ( { 
815819					extensionId : id 
816- 				} ) 
820+ 				} ) , 
821+ 				timeout : 2000 
817822			} 
818823		) . then ( resp  =>  { 
819824			if  ( ! resp . ok )  { 
820825				console . error ( 'Failed to query open-vsx while validating gitpod.yml' ) ; 
821826				return  undefined ; 
822827			} 
823- 			return  resp . json ( ) ; 
828+ 			return  resp . json ( )   as   Promise < IOpenVSXQueryResult > ; 
824829		} ,  e  =>  { 
825830			console . error ( 'Fetch failed while querying open-vsx' ,  e ) ; 
826831			return  undefined ; 
@@ -837,17 +842,40 @@ async function validateExtensions(extensionsToValidate: { id: string, version?:
837842			return  { 
838843				extensions : [ ] , 
839844				missingMachined : [ ] , 
840- 				uninstalled : [ ] 
845+ 				uninstalled : [ ] , 
846+ 				links : [ ] 
841847			} ; 
842848		} 
843849	} 
844850
845- 	// TODO: validate links 
851+ 	const  links  =  new  Set < string > ( ) ; 
852+ 	for  ( const  link  of  linkToValidate )  { 
853+ 		const  downloadPath  =  path . join ( os . tmpdir ( ) ,  uuid . v4 ( ) ) ; 
854+ 		try  { 
855+ 			await  download ( link ,  downloadPath ,  token ,  10000 ) ; 
856+ 			const  manifest  =  await  getManifest ( downloadPath ) ; 
857+ 			if  ( manifest . engines ?. vscode )  { 
858+ 				links . add ( link ) ; 
859+ 			} 
860+ 		}  catch  ( error )  { 
861+ 			console . error ( 'Failed to validate vsix url' ,  error ) ; 
862+ 		} 
863+ 
864+ 		if  ( token . isCancellationRequested )  { 
865+ 			return  { 
866+ 				extensions : [ ] , 
867+ 				missingMachined : [ ] , 
868+ 				uninstalled : [ ] , 
869+ 				links : [ ] 
870+ 			} ; 
871+ 		} 
872+ 	} 
846873
847874	return  { 
848875		extensions : [ ...validatedExtensions ] , 
849876		missingMachined : [ ...missingMachined ] , 
850- 		uninstalled : [ ...uninstalled ] 
877+ 		uninstalled : [ ...uninstalled ] , 
878+ 		links : [ ...links ] 
851879	} ; 
852880} 
853881
@@ -926,10 +954,7 @@ export function registerExtensionManagement(context: GitpodExtensionContext): vo
926954			} 
927955			try  { 
928956				const  toLink  =  new  Map < string ,  vscode . Range > ( ) ; 
929- 				const  toFind  =  new  Map < string ,  { 
930- 					version ?: string , 
931- 					range : vscode . Range 
932- 				} > ( ) ; 
957+ 				const  toFind  =  new  Map < string ,  {  version ?: string ,  range : vscode . Range  } > ( ) ; 
933958				let  document : vscode . TextDocument  |  undefined ; 
934959				try  { 
935960					document  =  await  vscode . workspace . openTextDocument ( gitpodFileUri ) ; 
@@ -994,7 +1019,8 @@ export function registerExtensionManagement(context: GitpodExtensionContext): vo
9941019					} 
9951020
9961021					const  extensionsToValidate  =  [ ...toFind . entries ( ) ] . map ( ( [ id ,  {  version } ] )  =>  ( {  id,  version } ) ) ; 
997- 					const  result  =  await  validateExtensions ( extensionsToValidate ,  token ) ; 
1022+ 					const  linksToValidate  =  [ ...toLink . keys ( ) ] ; 
1023+ 					const  result  =  await  validateExtensions ( extensionsToValidate ,  linksToValidate ,  token ) ; 
9981024
9991025					if  ( token . isCancellationRequested )  { 
10001026						return ; 
@@ -1016,14 +1042,14 @@ export function registerExtensionManagement(context: GitpodExtensionContext): vo
10161042						pushDiagnostic ( diagnostic ) ; 
10171043					} 
10181044
1019- 					//  for (const link of result.links) {
1020- 					//  	toLink.delete(link);
1021- 					//  }
1022- 					//  for (const [link, range] of toLink) {
1023- 					//  	const diagnostic = new vscode.Diagnostic(range, link + invalidVSIXLinkMessageSuffix, vscode.DiagnosticSeverity.Error);
1024- 					//  	diagnostic.source = 'gitpod';
1025- 					//  	pushDiagnostic(diagnostic);
1026- 					//  }
1045+ 					for  ( const  link  of  result . links )  { 
1046+ 						toLink . delete ( link ) ; 
1047+ 					} 
1048+ 					for  ( const  [ link ,  range ]  of  toLink )  { 
1049+ 						const  diagnostic  =  new  vscode . Diagnostic ( range ,  link  +  invalidVSIXLinkMessageSuffix ,  vscode . DiagnosticSeverity . Error ) ; 
1050+ 						diagnostic . source  =  'gitpod' ; 
1051+ 						pushDiagnostic ( diagnostic ) ; 
1052+ 					} 
10271053
10281054					for  ( const  id  of  result . missingMachined )  { 
10291055						const  diagnostic  =  new  vscode . Diagnostic ( new  vscode . Range ( new  vscode . Position ( 0 ,  0 ) ,  new  vscode . Position ( 0 ,  1 ) ) ,  id  +  missingExtensionMessageSuffix ,  vscode . DiagnosticSeverity . Warning ) ; 
@@ -1158,13 +1184,9 @@ export function registerExtensionManagement(context: GitpodExtensionContext): vo
11581184			return  codeActions ; 
11591185		} 
11601186	} ) ) ; 
1187+ 
11611188	validateGitpodFile ( ) ; 
11621189	context . subscriptions . push ( gitpodDiagnostics ) ; 
1163- 	context . subscriptions . push ( vscode . workspace . onDidChangeTextDocument ( e  =>  { 
1164- 		if  ( e . document . uri . toString ( )  ===  gitpodFileUri . toString ( ) )  { 
1165- 			validateGitpodFile ( ) ; 
1166- 		} 
1167- 	} ) ) ; 
11681190	const  gitpodFileWatcher  =  vscode . workspace . createFileSystemWatcher ( gitpodFileUri . fsPath ) ; 
11691191	context . subscriptions . push ( gitpodFileWatcher ) ; 
11701192	context . subscriptions . push ( gitpodFileWatcher . onDidCreate ( ( )  =>  validateGitpodFile ( ) ) ) ; 
0 commit comments