Skip to content

Commit f9a44de

Browse files
committed
Preserve binary file permissions in zip
1 parent 081dcd7 commit f9a44de

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

lib/inject.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ function injectRequirements(requirementsPath, packagePath, options) {
3737
!noDeploy.has(relativeFile.split(/([-\\/]|\.py$|\.pyc$)/, 1)[0])
3838
)
3939
.map(([file, relativeFile]) =>
40-
zipFile(zip, relativeFile, fse.readFileAsync(file))
40+
Promise.all([file, relativeFile, fse.statAsync(file)])
41+
)
42+
.map(([file, relativeFile, fileStat]) =>
43+
zipFile(zip, relativeFile, fse.readFileAsync(file), {
44+
unixPermissions: fileStat.mode
45+
})
4146
)
4247
.then(() => writeZip(zip, packagePath))
4348
);

lib/zipTree.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,23 @@ function writeZip(zip, targetPath) {
6060
* @param {string} zipPath the target path in the zip.
6161
* @param {Promise} bufferPromise a promise providing a nodebuffer.
6262
* @return {Promise} a promise providing the JSZip object.
63+
* @param {object} fileOpts an object with the opts to save for the file in the zip.
6364
*/
64-
function zipFile(zip, zipPath, bufferPromise) {
65+
function zipFile(zip, zipPath, bufferPromise, fileOpts) {
6566
return bufferPromise
6667
.then(buffer =>
67-
zip.file(zipPath, buffer, {
68-
// necessary to get the same hash when zipping the same content
69-
date: new Date(0)
70-
})
68+
zip.file(
69+
zipPath,
70+
buffer,
71+
Object.assign(
72+
{},
73+
{
74+
// necessary to get the same hash when zipping the same content
75+
date: new Date(0)
76+
},
77+
fileOpts
78+
)
79+
)
7180
)
7281
.then(() => zip);
7382
}

test.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
readFileSync,
1010
copySync,
1111
writeFileSync,
12+
statSync,
1213
pathExistsSync
1314
} = require('fs-extra');
1415
const { quote } = require('shell-quote');
@@ -875,6 +876,12 @@ test(
875876
'foobar has retained its executable file permissions'
876877
);
877878

879+
const flaskPerm = statSync('.serverless/requirements/bin/flask').mode;
880+
t.true(
881+
zipfiles_with_metadata['bin/flask'].unixPermissions === flaskPerm,
882+
'bin/flask has retained its executable file permissions'
883+
);
884+
878885
t.end();
879886
},
880887
{ skip: process.platform === 'win32' }
@@ -1566,15 +1573,25 @@ test(
15661573
npm(['i', path]);
15671574
sls(['package']);
15681575

1569-
const zipfiles_hello = listZipFilesWithMetaData('.serverless/hello1.zip');
1576+
const zipfiles_hello1 = listZipFilesWithMetaData('.serverless/hello1.zip');
15701577

15711578
t.true(
1572-
zipfiles_hello['module1/foobar'].unixPermissions
1579+
zipfiles_hello1['module1/foobar'].unixPermissions
15731580
.toString(8)
15741581
.slice(3, 6) === perm,
15751582
'foobar has retained its executable file permissions'
15761583
);
15771584

1585+
const zipfiles_hello2 = listZipFilesWithMetaData('.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip');
1586+
const flaskPerm = '755';
1587+
1588+
t.true(
1589+
zipfiles_hello2['bin/flask'].unixPermissions
1590+
.toString(8)
1591+
.slice(3, 6) === flaskPerm,
1592+
'bin/flask has retained its executable file permissions'
1593+
);
1594+
15781595
t.end();
15791596
},
15801597
{ skip: process.platform === 'win32' }
@@ -1601,6 +1618,16 @@ test(
16011618
'foobar has retained its executable file permissions'
16021619
);
16031620

1621+
const zipfiles_hello2 = listZipFilesWithMetaData('.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip');
1622+
const flaskPerm = '755';
1623+
1624+
t.true(
1625+
zipfiles_hello2['bin/flask'].unixPermissions
1626+
.toString(8)
1627+
.slice(3, 6) === flaskPerm,
1628+
'bin/flask has retained its executable file permissions'
1629+
);
1630+
16041631
t.end();
16051632
},
16061633
{ skip: !canUseDocker() || process.platform === 'win32' }

0 commit comments

Comments
 (0)