From 9c5cbf24fadf996167e5dca20cc93776d409fcf6 Mon Sep 17 00:00:00 2001 From: Iain Lane Date: Wed, 22 May 2024 09:29:03 +0100 Subject: [PATCH] fix: preserve mtime when zipping with the node zipper This means it's possible for code to retrieve the correct mtime, for example to return in a `Last-Modified` header. Since we have a test which verifies a checksum of a zip file created by this function, we can be sure the results are deterministic. To support this, update the test inputs to have specified mtimes. --- src/tests/util.test.ts | 40 ++++++++++++++++++++++++++++++++-------- src/utils.ts | 2 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/tests/util.test.ts b/src/tests/util.test.ts index 24feacdb..9d1c11df 100644 --- a/src/tests/util.test.ts +++ b/src/tests/util.test.ts @@ -18,15 +18,29 @@ describe('utils/findProjectRoot', () => { }); describe('utils/zip', () => { + const mtime = new Date(2024, 0, 1, 0, 0, 0, 0); + beforeEach(() => { mockFs({ - '/src': { - 'test.txt': 'lorem ipsum', - modules: { - 'module.txt': 'lorem ipsum 2', + '/src': mockFs.directory({ + mtime, + items: { + 'test.txt': mockFs.file({ + mtime, + content: 'lorem ipsum', + }), + modules: mockFs.directory({ + mtime, + items: { + 'module.txt': mockFs.file({ + mtime, + content: 'lorem ipsum 2', + }), + }, + }), }, - }, - '/dist': {}, + }), + '/dist': mockFs.directory({ mtime }), }); }); @@ -67,7 +81,17 @@ describe('utils/zip', () => { }, ]; - await zip(zipPath, filesPathList, useNativeZip); + // Check the mtimes are set correctly + const sourceStat = fs.statSync(source); + expect(sourceStat.mtime).toEqual(mtime); + + const testStat = fs.statSync('/src/test.txt'); + expect(testStat.mtime).toEqual(mtime); + + const moduleStat = fs.statSync('/src/modules/module.txt'); + expect(moduleStat.mtime).toEqual(mtime); + + await expect(zip(zipPath, filesPathList, useNativeZip)).resolves.toBeUndefined(); expect(fs.existsSync(zipPath)).toEqual(true); @@ -81,7 +105,7 @@ describe('utils/zip', () => { if (!useNativeZip) { const data = fs.readFileSync(zipPath); const fileHash = crypto.createHash('sha256').update(data).digest('base64'); - expect(fileHash).toEqual('iCZdyHJ7ON2LLwBIE6gQmRvBTzXBogSqJTMvHSenzGk='); + expect(fileHash).toEqual('PHu2gv7OIMv+lAOCXYPNd30X8/7EKYTuV7KYJjw3Qd4='); } } ); diff --git a/src/utils.ts b/src/utils.ts index f1d59cd7..e449891a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -118,7 +118,7 @@ function nodeZip(zipPath: string, filesPathList: IFiles): Promise { zipArchive.append(fs.readFileSync(file.rootPath), { name: file.localPath, mode: stats.mode, - date: new Date(0), // necessary to get the same hash when zipping the same content + date: new Date(stats.mtime), }); });