Skip to content

Commit 1c14588

Browse files
authored
Merge pull request serverless#335 from bspink/fix-zip-permissions
Preserve binary file permissions in zip
2 parents c017f71 + 68418ae commit 1c14588

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

circle.yml

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ jobs:
2323
sudo ./install.sh /usr/local
2424
# other deps
2525
- run: sudo apt -y update && sudo apt -y install python-pip python2.7 curl unzip
26+
# upgrade python3.6 pip to latest
27+
- run: sudo python3.6 -m pip install -U pip
2628
# instal pipenv
2729
- run: sudo python3.6 -m pip install pipenv pip-tools
2830
# install poetry

lib/inject.js

+6-1
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

+14-5
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

+25-2
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,23 @@ 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 = statSync('.serverless/module2/requirements/bin/flask').mode;
1587+
1588+
t.true(
1589+
zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm,
1590+
'bin/flask has retained its executable file permissions'
1591+
);
1592+
15781593
t.end();
15791594
},
15801595
{ skip: process.platform === 'win32' }
@@ -1601,6 +1616,14 @@ test(
16011616
'foobar has retained its executable file permissions'
16021617
);
16031618

1619+
const zipfiles_hello2 = listZipFilesWithMetaData('.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip');
1620+
const flaskPerm = statSync('.serverless/module2/requirements/bin/flask').mode;
1621+
1622+
t.true(
1623+
zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm,
1624+
'bin/flask has retained its executable file permissions'
1625+
);
1626+
16041627
t.end();
16051628
},
16061629
{ skip: !canUseDocker() || process.platform === 'win32' }

0 commit comments

Comments
 (0)