@@ -22,6 +22,7 @@ import { LambdaFunctionNodeDecorationProvider } from '../explorer/lambdaFunction
2222import path from 'path'
2323import { telemetry } from '../../shared/telemetry/telemetry'
2424import { ToolkitError } from '../../shared/errors'
25+ import { getFunctionWithCredentials } from '../../shared/clients/lambdaClient'
2526
2627const localize = nls . loadMessageBundle ( )
2728
@@ -84,7 +85,7 @@ export async function promptForSync(lambda: LambdaFunction, projectUri: vscode.U
8485 }
8586}
8687
87- async function confirmOutdatedChanges ( prompt : string ) : Promise < boolean > {
88+ export async function confirmOutdatedChanges ( prompt : string ) : Promise < boolean > {
8889 return await showConfirmationMessage ( {
8990 prompt,
9091 confirm : localize ( 'AWS.lambda.upload.overwrite' , 'Overwrite' ) ,
@@ -128,28 +129,62 @@ export async function deployFromTemp(lambda: LambdaFunction, projectUri: vscode.
128129 } )
129130}
130131
132+ export async function deleteFilesInFolder ( location : string ) {
133+ const entries = await fs . readdir ( location )
134+ await Promise . all (
135+ entries . map ( ( entry ) => fs . delete ( path . join ( location , entry [ 0 ] ) , { recursive : true , force : true } ) )
136+ )
137+ }
138+
131139export async function editLambdaCommand ( functionNode : LambdaFunctionNode ) {
132140 const region = functionNode . regionCode
133141 const functionName = functionNode . configuration . FunctionName !
134- return await editLambda ( { name : functionName , region, configuration : functionNode . configuration } )
142+ return await editLambda ( { name : functionName , region, configuration : functionNode . configuration } , 'explorer' )
135143}
136144
137- export async function editLambda ( lambda : LambdaFunction , onActivation ?: boolean ) {
145+ export async function overwriteChangesForEdit ( lambda : LambdaFunction , downloadLocation : string ) {
146+ try {
147+ // Clear directory contents instead of deleting to avoid Windows EBUSY errors
148+ if ( await fs . existsDir ( downloadLocation ) ) {
149+ await deleteFilesInFolder ( downloadLocation )
150+ } else {
151+ await fs . mkdir ( downloadLocation )
152+ }
153+
154+ await downloadLambdaInLocation ( lambda , 'local' , downloadLocation )
155+
156+ // Watching for updates, then setting info, then removing the badges must be done in this order
157+ // This is because the files creating can throw the watcher, which sometimes leads to changes being marked as undeployed
158+ watchForUpdates ( lambda , vscode . Uri . file ( downloadLocation ) )
159+
160+ await setFunctionInfo ( lambda , {
161+ lastDeployed : globals . clock . Date . now ( ) ,
162+ undeployed : false ,
163+ sha : lambda . configuration ! . CodeSha256 ,
164+ handlerFile : getLambdaDetails ( lambda . configuration ! ) . fileName ,
165+ } )
166+ await LambdaFunctionNodeDecorationProvider . getInstance ( ) . removeBadge (
167+ vscode . Uri . file ( downloadLocation ) ,
168+ vscode . Uri . from ( { scheme : 'lambda' , path : `${ lambda . region } /${ lambda . name } ` } )
169+ )
170+ } catch {
171+ throw new ToolkitError ( 'Failed to download Lambda function' , { code : 'failedDownload' } )
172+ }
173+ }
174+
175+ export async function editLambda ( lambda : LambdaFunction , source ?: 'workspace' | 'explorer' ) {
138176 return await telemetry . lambda_quickEditFunction . run ( async ( ) => {
139- telemetry . record ( { source : onActivation ? 'workspace' : 'explorer' } )
177+ telemetry . record ( { source } )
140178 const downloadLocation = getTempLocation ( lambda . name , lambda . region )
141- const downloadLocationName = vscode . workspace . asRelativePath ( downloadLocation , true )
142179
143180 // We don't want to do anything if the folder already exists as a workspace folder, it means it's already being edited
144- if (
145- vscode . workspace . workspaceFolders ?. some ( ( folder ) => folder . uri . fsPath === downloadLocation && ! onActivation )
146- ) {
181+ if ( vscode . workspace . workspaceFolders ?. some ( ( folder ) => folder . uri . fsPath === downloadLocation ) ) {
147182 return downloadLocation
148183 }
149184
150185 const prompt = localize (
151186 'AWS.lambda.download.confirmOutdatedSync' ,
152- 'There are changes to your Function in the cloud since you last edited locally, do you want to overwrite your local changes?'
187+ 'There are changes to your function in the cloud since you last edited locally, do you want to overwrite your local changes?'
153188 )
154189
155190 // We want to overwrite changes in the following cases:
@@ -169,37 +204,9 @@ export async function editLambda(lambda: LambdaFunction, onActivation?: boolean)
169204 ( ! ( await compareCodeSha ( lambda ) ) ? await confirmOutdatedChanges ( prompt ) : false )
170205
171206 if ( overwriteChanges ) {
172- try {
173- // Clear directory contents instead of deleting to avoid Windows EBUSY errors
174- if ( await fs . existsDir ( downloadLocation ) ) {
175- const entries = await fs . readdir ( downloadLocation )
176- await Promise . all (
177- entries . map ( ( entry ) =>
178- fs . delete ( path . join ( downloadLocation , entry [ 0 ] ) , { recursive : true , force : true } )
179- )
180- )
181- } else {
182- await fs . mkdir ( downloadLocation )
183- }
184-
185- await downloadLambdaInLocation ( lambda , downloadLocationName , downloadLocation )
186-
187- // Watching for updates, then setting info, then removing the badges must be done in this order
188- // This is because the files creating can throw the watcher, which sometimes leads to changes being marked as undeployed
189- watchForUpdates ( lambda , vscode . Uri . file ( downloadLocation ) )
190- await setFunctionInfo ( lambda , {
191- lastDeployed : globals . clock . Date . now ( ) ,
192- undeployed : false ,
193- sha : lambda . configuration ! . CodeSha256 ,
194- } )
195- await LambdaFunctionNodeDecorationProvider . getInstance ( ) . removeBadge (
196- vscode . Uri . file ( downloadLocation ) ,
197- vscode . Uri . from ( { scheme : 'lambda' , path : `${ lambda . region } /${ lambda . name } ` } )
198- )
199- } catch {
200- throw new ToolkitError ( 'Failed to download Lambda function' , { code : 'failedDownload' } )
201- }
202- } else {
207+ await overwriteChangesForEdit ( lambda , downloadLocation )
208+ } else if ( source === 'explorer' ) {
209+ // If the source is the explorer, we want to open, otherwise we just wait to open in the workspace
203210 const lambdaLocation = path . join ( downloadLocation , getLambdaDetails ( lambda . configuration ! ) . fileName )
204211 await openLambdaFile ( lambdaLocation )
205212 watchForUpdates ( lambda , vscode . Uri . file ( downloadLocation ) )
@@ -212,22 +219,24 @@ export async function editLambda(lambda: LambdaFunction, onActivation?: boolean)
212219export async function openLambdaFolderForEdit ( name : string , region : string ) {
213220 const downloadLocation = getTempLocation ( name , region )
214221
215- if (
216- vscode . workspace . workspaceFolders ?. some ( ( workspaceFolder ) =>
217- workspaceFolder . uri . fsPath . toLowerCase ( ) . startsWith ( downloadLocation . toLowerCase ( ) )
218- )
219- ) {
220- // If the folder already exists in the workspace, show that folder
221- await vscode . commands . executeCommand ( 'workbench.action.focusSideBar' )
222- await vscode . commands . executeCommand ( 'workbench.view.explorer' )
223- } else {
224- await fs . mkdir ( downloadLocation )
225-
226- await vscode . commands . executeCommand ( 'vscode.openFolder' , vscode . Uri . file ( downloadLocation ) , {
227- newWindow : true ,
228- noRecentEntry : true ,
229- } )
230- }
222+ // Do all authentication work before opening workspace to avoid race condition
223+ const getFunctionOutput = await getFunctionWithCredentials ( region , name )
224+ const configuration = getFunctionOutput . Configuration
225+
226+ // Download and set up Lambda code before opening workspace
227+ await editLambda (
228+ {
229+ name,
230+ region,
231+ configuration : configuration as any ,
232+ } ,
233+ 'workspace'
234+ )
235+
236+ await vscode . commands . executeCommand ( 'vscode.openFolder' , vscode . Uri . file ( downloadLocation ) , {
237+ newWindow : true ,
238+ noRecentEntry : true ,
239+ } )
231240}
232241
233242export async function getReadme ( ) : Promise < string > {
0 commit comments