@@ -212,6 +212,7 @@ func buildMergedSourceZip(originalZipBytes []byte, desiredFiles map[string]strin
212212 header zip.FileHeader
213213 }
214214 preservedBinaryFiles := make (map [string ]preservedBinaryEntry )
215+ originalHeaders := make (map [string ]zip.FileHeader , len (archiveReader .File ))
215216 totalUncompressedBytes := int64 (0 )
216217
217218 for _ , archiveFile := range archiveReader .File {
@@ -226,6 +227,12 @@ func buildMergedSourceZip(originalZipBytes []byte, desiredFiles map[string]strin
226227 if err != nil {
227228 return nil , fmt .Errorf ("validate template source path %q: %w" , archiveFile .Name , err )
228229 }
230+ if _ , exists := originalHeaders [relativePath ]; exists {
231+ return nil , fmt .Errorf ("duplicate normalized template source path %q" , relativePath )
232+ }
233+ header := archiveFile .FileHeader
234+ header .Name = relativePath
235+ originalHeaders [relativePath ] = header
229236 if _ , exists := normalizedDesiredFiles [relativePath ]; exists {
230237 continue
231238 }
@@ -271,11 +278,9 @@ func buildMergedSourceZip(originalZipBytes []byte, desiredFiles map[string]strin
271278 return nil , fmt .Errorf ("duplicate normalized template source path %q" , relativePath )
272279 }
273280
274- header := archiveFile .FileHeader
275- header .Name = relativePath
276281 preservedBinaryFiles [relativePath ] = preservedBinaryEntry {
277282 contents : contents ,
278- header : header ,
283+ header : originalHeaders [ relativePath ] ,
279284 }
280285 }
281286
@@ -333,6 +338,26 @@ func buildMergedSourceZip(originalZipBytes []byte, desiredFiles map[string]strin
333338 }
334339
335340 if hasDesired {
341+ if originalHeader , exists := originalHeaders [sourcePath ]; exists {
342+ header := originalHeader
343+ header .Name = sourcePath
344+ // Header sizes are specific to the original contents. Reset them so
345+ // the zip writer recomputes values for the updated file bytes.
346+ header .CompressedSize64 = 0
347+ header .UncompressedSize64 = 0
348+ //nolint:staticcheck // archive/zip still consumes legacy 32-bit size fields.
349+ header .CompressedSize = 0
350+ //nolint:staticcheck // archive/zip still consumes legacy 32-bit size fields.
351+ header .UncompressedSize = 0
352+ fileWriter , err := zipWriter .CreateHeader (& header )
353+ if err != nil {
354+ return nil , fmt .Errorf ("create zip entry %q from original header: %w" , sourcePath , err )
355+ }
356+ if _ , err := fileWriter .Write ([]byte (desiredContent )); err != nil {
357+ return nil , fmt .Errorf ("write zip entry %q: %w" , sourcePath , err )
358+ }
359+ continue
360+ }
336361 fileWriter , err := zipWriter .Create (sourcePath )
337362 if err != nil {
338363 return nil , fmt .Errorf ("create zip entry %q: %w" , sourcePath , err )
0 commit comments