@@ -47,8 +47,13 @@ const IGNORE_PATTERNS = [
4747    '**/target/**' ,  // Maven/Gradle builds 
4848] 
4949
50- const  MAX_UNCOMPRESSED_SRC_SIZE_MB  =  250  // 250 MB limit per language per workspace folder 
51- const  MAX_UNCOMPRESSED_SRC_SIZE_BYTES  =  MAX_UNCOMPRESSED_SRC_SIZE_MB  *  1024  *  1024  // Convert to bytes 
50+ interface  FileSizeDetails  { 
51+     includedFileCount : number 
52+     includedSize : number 
53+     skippedFileCount : number 
54+     skippedSize : number 
55+ } 
56+ const  MAX_UNCOMPRESSED_SRC_SIZE_BYTES  =  2  *  1024  *  1024  *  1024  // 2 GB 
5257
5358export  class  ArtifactManager  { 
5459    private  workspace : Workspace 
@@ -81,6 +86,12 @@ export class ArtifactManager {
8186
8287    async  addNewDirectories ( newDirectories : URI [ ] ) : Promise < FileMetadata [ ] >  { 
8388        let  zipFileMetadata : FileMetadata [ ]  =  [ ] 
89+         const  fileSizeDetails : FileSizeDetails  =  { 
90+             includedFileCount : 0 , 
91+             includedSize : 0 , 
92+             skippedFileCount : 0 , 
93+             skippedSize : 0 , 
94+         } 
8495
8596        for  ( const  directory  of  newDirectories )  { 
8697            const  workspaceFolder  =  this . workspaceFolders . find ( ws  =>  directory . path . startsWith ( URI . parse ( ws . uri ) . path ) ) 
@@ -95,7 +106,12 @@ export class ArtifactManager {
95106                const  relativePath  =  path . relative ( workspacePath ,  directory . path ) 
96107
97108                const  filesByLanguage  =  await  this . processDirectory ( workspaceFolder ,  directory . path ,  relativePath ) 
98-                 zipFileMetadata  =  await  this . processFilesByLanguage ( workspaceFolder ,  filesByLanguage ,  relativePath ) 
109+                 zipFileMetadata  =  await  this . processFilesByLanguage ( 
110+                     workspaceFolder , 
111+                     fileSizeDetails , 
112+                     filesByLanguage , 
113+                     relativePath 
114+                 ) 
99115            }  catch  ( error )  { 
100116                this . logging . warn ( `Error processing new directory ${ directory . path }  : ${ error }  ` ) 
101117            } 
@@ -286,9 +302,12 @@ export class ArtifactManager {
286302        return  filesMetadata 
287303    } 
288304
289-     cleanup ( preserveDependencies : boolean  =  false )  { 
305+     cleanup ( preserveDependencies : boolean  =  false ,   workspaceFolders ?:  WorkspaceFolder [ ] )  { 
290306        try  { 
291-             this . workspaceFolders . forEach ( workspaceToRemove  =>  { 
307+             if  ( workspaceFolders  ===  undefined )  { 
308+                 workspaceFolders  =  this . workspaceFolders 
309+             } 
310+             workspaceFolders . forEach ( workspaceToRemove  =>  { 
292311                const  workspaceDirPath  =  path . join ( this . tempDirPath ,  workspaceToRemove . name ) 
293312
294313                if  ( preserveDependencies )  { 
@@ -430,43 +449,50 @@ export class ArtifactManager {
430449
431450    private  async  createZipForLanguage ( 
432451        workspaceFolder : WorkspaceFolder , 
452+         fileSizeDetails : FileSizeDetails , 
433453        language : CodewhispererLanguage , 
434454        files : FileMetadata [ ] , 
435455        subDirectory : string  =  '' 
436-     ) : Promise < FileMetadata >  { 
456+     ) : Promise < FileMetadata   |   undefined >  { 
437457        const  zipDirectoryPath  =  path . join ( this . tempDirPath ,  workspaceFolder . name ,  subDirectory ) 
438458        this . createFolderIfNotExist ( zipDirectoryPath ) 
439459
440460        const  zipPath  =  path . join ( zipDirectoryPath ,  `${ language }  .zip` ) 
441461
442-         let  currentSize  =  0 
443462        let  skippedSize  =  0 
444463        let  skippedFiles  =  0 
445464        const  filesToInclude : FileMetadata [ ]  =  [ ] 
446465
447466        // Don't add files to the zip if the total size of uncompressed source code would go over the limit 
448467        // Currently there is no ordering on the files. If the first file added to the zip is equal to the limit, only it will be added and no other files will be added 
449468        for  ( const  file  of  files )  { 
450-             if  ( currentSize  +  file . contentLength  <=  MAX_UNCOMPRESSED_SRC_SIZE_BYTES )  { 
469+             if  ( fileSizeDetails . includedSize  +  file . contentLength  <=  MAX_UNCOMPRESSED_SRC_SIZE_BYTES )  { 
451470                filesToInclude . push ( file ) 
452-                 currentSize  +=  file . contentLength 
471+                 fileSizeDetails . includedSize  +=  file . contentLength 
472+                 fileSizeDetails . includedFileCount  +=  1 
453473            }  else  { 
454474                skippedSize  +=  file . contentLength 
455475                skippedFiles  +=  1 
476+                 fileSizeDetails . skippedSize  +=  file . contentLength 
477+                 fileSizeDetails . skippedFileCount  +=  1 
456478            } 
457479        } 
458480
459-         const  zipBuffer  =  await  this . createZipBuffer ( filesToInclude ) 
460-         await  fs . promises . writeFile ( zipPath ,  zipBuffer ) 
461- 
462-         const  stats  =  fs . statSync ( zipPath ) 
463- 
464481        if  ( skippedFiles  >  0 )  { 
465482            this . log ( 
466483                `Skipped ${ skippedFiles }   ${ language }   files of total size ${ skippedSize }   bytes due to exceeding the maximum zip size` 
467484            ) 
468485        } 
469486
487+         if  ( filesToInclude . length  ===  0 )  { 
488+             return  undefined 
489+         } 
490+ 
491+         const  zipBuffer  =  await  this . createZipBuffer ( filesToInclude ) 
492+         await  fs . promises . writeFile ( zipPath ,  zipBuffer ) 
493+ 
494+         const  stats  =  fs . statSync ( zipPath ) 
495+ 
470496        return  { 
471497            filePath : zipPath , 
472498            relativePath : path . join ( workspaceFolder . name ,  subDirectory ,  `files.zip` ) , 
@@ -569,18 +595,35 @@ export class ArtifactManager {
569595    private  async  processWorkspaceFolders ( workspaceFolders : WorkspaceFolder [ ] ) : Promise < FileMetadata [ ] >  { 
570596        const  startTime  =  performance . now ( ) 
571597        let  zipFileMetadata : FileMetadata [ ]  =  [ ] 
598+         const  fileSizeDetails : FileSizeDetails  =  { 
599+             includedFileCount : 0 , 
600+             includedSize : 0 , 
601+             skippedFileCount : 0 , 
602+             skippedSize : 0 , 
603+         } 
572604
573605        for  ( const  workspaceFolder  of  workspaceFolders )  { 
574606            const  workspacePath  =  URI . parse ( workspaceFolder . uri ) . path 
575607
576608            try  { 
577609                const  filesByLanguage  =  await  this . processDirectory ( workspaceFolder ,  workspacePath ) 
578-                 const  fileMetadata  =  await  this . processFilesByLanguage ( workspaceFolder ,  filesByLanguage ) 
610+                 const  fileMetadata  =  await  this . processFilesByLanguage ( 
611+                     workspaceFolder , 
612+                     fileSizeDetails , 
613+                     filesByLanguage 
614+                 ) 
579615                zipFileMetadata . push ( ...fileMetadata ) 
580616            }  catch  ( error )  { 
581617                this . logging . warn ( `Error processing workspace folder ${ workspacePath }  : ${ error }  ` ) 
582618            } 
583619        } 
620+         if  ( fileSizeDetails . skippedFileCount  >  0 )  { 
621+             this . logging . warn ( 
622+                 `Skipped ${ fileSizeDetails . skippedFileCount }   files (total size: `  + 
623+                     `${ fileSizeDetails . skippedSize }   bytes) due to exceeding the maximum artifact size` 
624+             ) 
625+         } 
626+ 
584627        const  totalTime  =  performance . now ( )  -  startTime 
585628        this . log ( `Creating workspace source code artifacts took: ${ totalTime . toFixed ( 2 ) }  ms` ) 
586629
@@ -589,22 +632,31 @@ export class ArtifactManager {
589632
590633    private  async  processFilesByLanguage ( 
591634        workspaceFolder : WorkspaceFolder , 
635+         fileSizeDetails : FileSizeDetails , 
592636        filesByLanguage : Map < CodewhispererLanguage ,  FileMetadata [ ] > , 
593637        relativePath ?: string 
594638    ) : Promise < FileMetadata [ ] >  { 
595639        const  zipFileMetadata : FileMetadata [ ]  =  [ ] 
596640        await  this . updateWorkspaceFiles ( workspaceFolder ,  filesByLanguage ) 
597- 
598641        for  ( const  [ language ,  files ]  of  filesByLanguage . entries ( ) )  { 
599-             // Genrate  java .classpath and .project files 
642+             // Generate  java .classpath and .project files 
600643            const  processedFiles  = 
601644                language  ===  'java'  ? await  this . processJavaProjectConfig ( workspaceFolder ,  files )  : files 
602645
603-             const  zipMetadata  =  await  this . createZipForLanguage ( workspaceFolder ,  language ,  processedFiles ,  relativePath ) 
604-             this . log ( 
605-                 `Created zip for language ${ language }   out of ${ processedFiles . length }   files in ${ workspaceFolder . name }  ` 
646+             const  zipMetadata  =  await  this . createZipForLanguage ( 
647+                 workspaceFolder , 
648+                 fileSizeDetails , 
649+                 language , 
650+                 processedFiles , 
651+                 relativePath 
606652            ) 
607-             zipFileMetadata . push ( zipMetadata ) 
653+ 
654+             if  ( zipMetadata )  { 
655+                 this . log ( 
656+                     `Created zip for language ${ language }   out of ${ processedFiles . length }   files in ${ workspaceFolder . name }  ` 
657+                 ) 
658+                 zipFileMetadata . push ( zipMetadata ) 
659+             } 
608660        } 
609661        return  zipFileMetadata 
610662    } 
0 commit comments