Skip to content

Commit 1c12a15

Browse files
abetomoDeviaVir
authored andcommitted
Bugfixed that mode of file changes when zip is created (motdotla#335)
* Add archiver.js * Fix to use `archiver` instead of `node-zip` We want to keep file mode. * Add test of file mode * Fix to test mode in non-Windows * Modify the file used for testing * Modify the file used for testing * Modify archive.files's key archive.files's key is a slash delimiter regardless of platform. * Modify archive.files's name archive.files's name is a slash delimiter regardless of platform. * Modify path delimiter archive.files's name is a slash delimiter regardless of platform. * Modify to Arrow function and modify of variable declaration * Fix to get mode from file
1 parent e640633 commit 1c12a15

5 files changed

Lines changed: 259 additions & 38 deletions

File tree

lib/main.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
'use strict'
22

33
const path = require('path')
4+
const os = require('os')
45
const aws = require('aws-sdk')
56
const exec = require('child_process').exec
67
const execSync = require('child_process').execSync
78
const execFile = require('child_process').execFile
89
const fs = require('fs-extra')
910
const packageJson = require(path.join(__dirname, '..', 'package.json'))
1011
const minimatch = require('minimatch')
11-
const zip = new (require('node-zip'))()
12+
const archiver = require('archiver')
1213
const dotenv = require('dotenv')
1314
const proxy = require('proxy-agent')
1415
const ScheduleEvents = require(path.join(__dirname, 'schedule_events'))
@@ -373,23 +374,41 @@ Lambda.prototype._postInstallScript = (program, codeDirectory) => {
373374
}
374375

375376
Lambda.prototype._zip = (program, codeDirectory) => {
376-
const options = {
377-
type: 'nodebuffer',
378-
compression: 'DEFLATE'
379-
}
380-
381377
console.log('=> Zipping repo. This might take up to 30 seconds')
378+
379+
const tmpZipFile = path.join(os.tmpdir(), +(new Date()) + '.zip')
380+
const output = fs.createWriteStream(tmpZipFile)
381+
const archive = archiver('zip', {
382+
zlib: { level: 9 } // Sets the compression level.
383+
})
382384
return new Promise((resolve) => {
385+
output.on('close', () => {
386+
const contents = fs.readFileSync(tmpZipFile)
387+
fs.unlinkSync(tmpZipFile)
388+
resolve(contents)
389+
})
390+
archive.pipe(output)
383391
fs.walk(codeDirectory)
384392
.on('data', (file) => {
385-
if (!file.stats.isDirectory()) {
386-
const content = fs.readFileSync(file.path)
387-
const filePath = file.path.replace(path.join(codeDirectory, path.sep), '')
388-
zip.file(filePath, content)
393+
if (file.stats.isDirectory()) return
394+
395+
const filePath = file.path.replace(path.join(codeDirectory, path.sep), '')
396+
if (file.stats.isSymbolicLink()) {
397+
// # archiver.js
398+
// Implementation supporting symlink has been done,
399+
// but it seems that release has not been done yet
389400
}
401+
402+
archive.append(
403+
fs.createReadStream(file.path),
404+
{
405+
name: filePath,
406+
stats: file.stats
407+
}
408+
)
390409
})
391410
.on('end', () => {
392-
resolve(zip.generate(options))
411+
archive.finalize()
393412
})
394413
})
395414
}

package-lock.json

Lines changed: 76 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"standard": "^10.0.2"
3737
},
3838
"dependencies": {
39+
"archiver": "^1.3.0",
3940
"aws-sdk": "^2.76.0",
4041
"commander": "^2.10.0",
4142
"dotenv": "^0.4.0",

test/main.js

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -522,20 +522,33 @@ describe('lib/main', function () {
522522
})
523523
})
524524

525-
it('zips the file and has an index.js file', function () {
525+
it('Compress the file. `index.js` and `bin/node-lambda` are included and the permission is also preserved.', function () {
526526
_timeout({ this: this, sec: 30 }) // give it time to zip
527527

528528
return lambda._zip(program, codeDirectory).then((data) => {
529+
const indexJsStat = fs.lstatSync('index.js')
530+
const binNodeLambdaStat = fs.lstatSync(path.join('bin', 'node-lambda'))
531+
529532
const archive = new Zip(data)
530-
const contents = Object.keys(archive.files).map((k) => {
531-
return archive.files[k].name.toString()
532-
})
533-
assert.include(contents, 'index.js')
533+
assert.include(archive.files['index.js'].name, 'index.js')
534+
assert.include(archive.files['bin/node-lambda'].name, 'bin/node-lambda')
535+
536+
if (process.platform !== 'win32') {
537+
assert.equal(
538+
archive.files['index.js'].unixPermissions,
539+
indexJsStat.mode
540+
)
541+
assert.equal(
542+
archive.files['bin/node-lambda'].unixPermissions,
543+
binNodeLambdaStat.mode
544+
)
545+
}
534546
})
535547
})
536548
})
537549

538550
describe('_archive', () => {
551+
// archive.files's name is a slash delimiter regardless of platform.
539552
it('installs and zips with an index.js file and node_modules/aws-sdk', function (done) {
540553
_timeout({ this: this, sec: 30 }) // give it time to zip
541554

@@ -546,17 +559,15 @@ describe('lib/main', function () {
546559
return archive.files[k].name.toString()
547560
})
548561
assert.include(contents, 'index.js')
549-
assert.include(contents, path.join('node_modules', 'aws-sdk', 'lib', 'aws.js'))
562+
assert.include(contents, 'node_modules/aws-sdk/lib/aws.js')
550563
done()
551564
})
552565
})
553566

554567
it('packages a prebuilt module without installing', function (done) {
555568
_timeout({ this: this, sec: 30 }) // give it time to zip
556-
var buildDir = '.build_' + Date.now()
557-
after(function () {
558-
fs.removeSync(buildDir)
559-
})
569+
let buildDir = '.build_' + Date.now()
570+
after(() => fs.removeSync(buildDir))
560571

561572
fs.mkdirSync(buildDir)
562573
fs.mkdirSync(path.join(buildDir, 'd'))
@@ -566,17 +577,17 @@ describe('lib/main', function () {
566577
fs.writeFileSync(path.join(buildDir, 'd', 'testb'), '...')
567578

568579
program.prebuiltDirectory = buildDir
569-
lambda._archive(program, function (err, data) {
580+
lambda._archive(program, (err, data) => {
570581
assert.isNull(err)
571-
var archive = new Zip(data)
572-
var contents = Object.keys(archive.files).map(function (k) {
582+
const archive = new Zip(data)
583+
const contents = Object.keys(archive.files).map((k) => {
573584
return archive.files[k].name.toString()
574585
});
575586
[
576587
'testa',
577-
path.join('d', 'testb'),
578-
path.join('node_modules', 'a')
579-
].forEach(function (needle) {
588+
'd/testb',
589+
'node_modules/a'
590+
].forEach((needle) => {
580591
assert.include(contents, needle, `Target: "${needle}"`)
581592
})
582593
done()
@@ -640,7 +651,7 @@ describe('lib/main', function () {
640651
return archive.files[k].name.toString()
641652
})
642653
assert.include(contents, 'index.js')
643-
assert.include(contents, path.join('node_modules', 'aws-sdk', 'lib', 'aws.js'))
654+
assert.include(contents, 'node_modules/aws-sdk/lib/aws.js')
644655
done()
645656
})
646657
})

0 commit comments

Comments
 (0)