Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: require Node 10.12 #89

Merged
merged 24 commits into from
Mar 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a2701a6
build: replace Travis CI with GitHub Actions
malept Mar 25, 2020
75d039f
refactor: remove use of temp module
malept Mar 25, 2020
3cdf195
test: don't resolve tmpdir to real path
malept Mar 25, 2020
6e082ce
test: don't check for the exact tmp dir
malept Mar 25, 2020
a528bd6
test: do not run symlink test on Windows
malept Mar 25, 2020
3ff24f3
feat: drop use of mkdirp
malept Mar 25, 2020
1c8252a
docs: update badges
malept Mar 25, 2020
42780ca
build(deps): upgrade debug to ^4.1.1
malept Mar 25, 2020
aa8b83d
build(deps-dev): upgrade rimraf to ^3.0.2
malept Mar 25, 2020
c46e3f9
build(deps-dev): upgrade standard to ^14.3.3
malept Mar 25, 2020
de3c72c
refactor: remove use of deprecated fs.exists
malept Mar 25, 2020
944af5b
build(deps): upgrade concat-stream to ^2.0.0
malept Mar 25, 2020
c207520
test: add nyc for code coverage
malept Mar 25, 2020
4b7465f
test: add test for onEntry option
malept Mar 25, 2020
d5bc940
test: disable another symlink test on win32
malept Mar 25, 2020
49368f5
refactor: use const/let instead of var
malept Mar 25, 2020
7840e43
refactor: use octal literals
malept Mar 25, 2020
6a4e86e
refactor: use String.prototype.startsWith
malept Mar 25, 2020
b8121dc
test: test the symlink's link
malept Mar 25, 2020
50280ac
test: assert readlink error doesn't exist
malept Mar 25, 2020
2589902
chore: fix lint warning
malept Mar 25, 2020
6c95b13
test: fix plan
malept Mar 25, 2020
a2b80d1
docs: note Node version requirement in the readme
malept Mar 25, 2020
e5fdad4
docs: fix dir description
malept Mar 25, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

on:
push:
branches:
- master
tags:
- v[0-9]+.[0-9]+.[0-9]+*
pull_request:

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, macOS-latest, ubuntu-latest]
node-version: [10.x, 12.x]

steps:
- name: Fix git checkout line endings
run: git config --global core.autocrlf input
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Get yarn cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/package.json') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install
run: yarn
- name: Lint
run: yarn lint
- name: Test
run: yarn coverage
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.DS_Store
.nyc_output
node_modules
package-lock.json
yarn.lock
9 changes: 0 additions & 9 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if (!source) {
process.exit(1)
}

extract(source, {dir: dest}, function (err, results) {
extract(source, { dir: dest }, function (err, results) {
if (err) {
console.error('error!', err)
process.exit(1)
Expand Down
78 changes: 41 additions & 37 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
var fs = require('fs')
var path = require('path')
var yauzl = require('yauzl')
var mkdirp = require('mkdirp')
var concat = require('concat-stream')
var debug = require('debug')('extract-zip')
const fs = require('fs')
const path = require('path')
const yauzl = require('yauzl')
const concat = require('concat-stream')
const debug = require('debug')('extract-zip')

module.exports = function (zipPath, opts, cb) {
debug('creating target directory', opts.dir)
Expand All @@ -12,7 +11,7 @@ module.exports = function (zipPath, opts, cb) {
return cb(new Error('Target directory is expected to be absolute'))
}

mkdirp(opts.dir, function (err) {
fs.mkdir(opts.dir, { recursive: true }, function (err) {
if (err) return cb(err)

fs.realpath(opts.dir, function (err, canonicalDir) {
Expand All @@ -27,10 +26,10 @@ module.exports = function (zipPath, opts, cb) {
function openZip () {
debug('opening', zipPath, 'with opts', opts)

yauzl.open(zipPath, {lazyEntries: true}, function (err, zipfile) {
yauzl.open(zipPath, { lazyEntries: true }, function (err, zipfile) {
if (err) return cb(err)

var cancelled = false
let cancelled = false

zipfile.on('error', function (err) {
if (err) {
Expand All @@ -48,36 +47,38 @@ module.exports = function (zipPath, opts, cb) {
})

zipfile.on('entry', function (entry) {
/* istanbul ignore if */
if (cancelled) {
debug('skipping entry', entry.fileName, {cancelled: cancelled})
debug('skipping entry', entry.fileName, { cancelled: cancelled })
return
}

debug('zipfile entry', entry.fileName)

if (/^__MACOSX\//.test(entry.fileName)) {
// dir name starts with __MACOSX/
if (entry.fileName.startsWith('__MACOSX/')) {
zipfile.readEntry()
return
}

var destDir = path.dirname(path.join(opts.dir, entry.fileName))
const destDir = path.dirname(path.join(opts.dir, entry.fileName))

mkdirp(destDir, function (err) {
fs.mkdir(destDir, { recursive: true }, function (err) {
/* istanbul ignore if */
if (err) {
cancelled = true
zipfile.close()
return cb(err)
}

fs.realpath(destDir, function (err, canonicalDestDir) {
/* istanbul ignore if */
if (err) {
cancelled = true
zipfile.close()
return cb(err)
}

var relativeDestDir = path.relative(opts.dir, canonicalDestDir)
const relativeDestDir = path.relative(opts.dir, canonicalDestDir)

if (relativeDestDir.split(path.sep).indexOf('..') !== -1) {
cancelled = true
Expand All @@ -100,25 +101,26 @@ module.exports = function (zipPath, opts, cb) {
})

function extractEntry (entry, done) {
/* istanbul ignore if */
if (cancelled) {
debug('skipping entry extraction', entry.fileName, {cancelled: cancelled})
debug('skipping entry extraction', entry.fileName, { cancelled: cancelled })
return setImmediate(done)
}

if (opts.onEntry) {
opts.onEntry(entry, zipfile)
}

var dest = path.join(opts.dir, entry.fileName)
const dest = path.join(opts.dir, entry.fileName)

// convert external file attr int into a fs stat mode int
var mode = (entry.externalFileAttributes >> 16) & 0xFFFF
let mode = (entry.externalFileAttributes >> 16) & 0xFFFF
// check if it's a symlink or dir (using stat mode constants)
var IFMT = 61440
var IFDIR = 16384
var IFLNK = 40960
var symlink = (mode & IFMT) === IFLNK
var isDir = (mode & IFMT) === IFDIR
const IFMT = 61440
const IFDIR = 16384
const IFLNK = 40960
const symlink = (mode & IFMT) === IFLNK
let isDir = (mode & IFMT) === IFDIR

// Failsafe, borrowed from jsZip
if (!isDir && entry.fileName.slice(-1) === '/') {
Expand All @@ -127,35 +129,35 @@ module.exports = function (zipPath, opts, cb) {

// check for windows weird way of specifying a directory
// https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
var madeBy = entry.versionMadeBy >> 8
const madeBy = entry.versionMadeBy >> 8
if (!isDir) isDir = (madeBy === 0 && entry.externalFileAttributes === 16)

// if no mode then default to default modes
if (mode === 0) {
if (isDir) {
if (opts.defaultDirMode) mode = parseInt(opts.defaultDirMode, 10)
if (!mode) mode = 493 // Default to 0755
if (!mode) mode = 0o755
} else {
if (opts.defaultFileMode) mode = parseInt(opts.defaultFileMode, 10)
if (!mode) mode = 420 // Default to 0644
if (!mode) mode = 0o644
}
}

debug('extracting entry', { filename: entry.fileName, isDir: isDir, isSymlink: symlink })

// reverse umask first (~)
var umask = ~process.umask()
const umask = ~process.umask()
// & with processes umask to override invalid perms
var procMode = mode & umask
const procMode = mode & umask

// always ensure folders are created
var destDir = dest
if (!isDir) destDir = path.dirname(dest)
const destDir = isDir ? dest : path.dirname(dest)

debug('mkdirp', {dir: destDir})
mkdirp(destDir, function (err) {
debug('mkdirp', { dir: destDir })
fs.mkdir(destDir, { recursive: true }, function (err) {
/* istanbul ignore if */
if (err) {
debug('mkdirp error', destDir, {error: err})
debug('mkdirp error', destDir, { error: err })
cancelled = true
return done(err)
}
Expand All @@ -164,29 +166,31 @@ module.exports = function (zipPath, opts, cb) {

debug('opening read stream', dest)
zipfile.openReadStream(entry, function (err, readStream) {
/* istanbul ignore if */
if (err) {
debug('openReadStream error', err)
cancelled = true
return done(err)
}

readStream.on('error', function (err) {
/* istanbul ignore next */
console.log('read err', err)
})

if (symlink) writeSymlink()
else writeStream()

function writeStream () {
var writeStream = fs.createWriteStream(dest, {mode: procMode})
const writeStream = fs.createWriteStream(dest, { mode: procMode })
readStream.pipe(writeStream)

writeStream.on('finish', function () {
done()
})

writeStream.on('error', function (err) {
debug('write error', {error: err})
writeStream.on('error', /* istanbul ignore next */ function (err) {
debug('write error', { error: err })
cancelled = true
return done(err)
})
Expand All @@ -195,7 +199,7 @@ module.exports = function (zipPath, opts, cb) {
// AFAICT the content of the symlink file itself is the symlink target filename string
function writeSymlink () {
readStream.pipe(concat(function (data) {
var link = data.toString()
const link = data.toString()
debug('creating symlink', link, dest)
fs.symlink(link, dest, function (err) {
if (err) cancelled = true
Expand Down
20 changes: 12 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
"extract-zip": "cli.js"
},
"scripts": {
"test": "standard && node test/test.js"
"coverage": "nyc node test/test.js",
"lint": "standard",
"test": "node test/test.js"
},
"files": [
"*.js"
Expand All @@ -20,17 +22,19 @@
"zip",
"extract"
],
"engines": {
"node": ">= 10.12.0"
},
"dependencies": {
"concat-stream": "^1.6.2",
"debug": "^2.6.9",
"mkdirp": "^0.5.4",
"concat-stream": "^2.0.0",
"debug": "^4.1.1",
"yauzl": "^2.10.0"
},
"devDependencies": {
"rimraf": "^2.2.8",
"standard": "^5.2.2",
"tape": "^4.2.0",
"temp": "^0.8.3"
"nyc": "^15.0.0",
"rimraf": "^3.0.2",
"standard": "^14.3.3",
"tape": "^4.2.0"
},
"directories": {
"test": "test"
Expand Down
12 changes: 7 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ Unzip written in pure JavaScript. Extracts a zip into a directory. Available as

Uses the [`yauzl`](http://npmjs.org/yauzl) ZIP parser.

[![NPM](https://nodei.co/npm/extract-zip.png?global=true)](https://nodei.co/npm/extract-zip/)
[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
[![Build Status](https://travis-ci.org/maxogden/extract-zip.svg?branch=master)](https://travis-ci.org/maxogden/extract-zip)
[![NPM](https://nodei.co/npm/extract-zip.png?global=true)](https://npm.im/extract-zip)
[![Uses JS Standard Style](https://cdn.jsdelivr.net/gh/standard/standard/badge.svg)](https://github.com/standard/standard)
[![Build Status](https://github.com/maxogden/extract-zip/workflows/CI/badge.svg)](https://github.com/maxogden/extract-zip/actions?query=workflow%3ACI)

## Installation

Make sure you have Node 10 or greater installed.

Get the library:

```
Expand All @@ -26,14 +28,14 @@ npm install extract-zip -g

```js
var extract = require('extract-zip')
extract(sourcePath, {dir: targetPath}, function (err) {
extract(source, {dir: target}, function (err) {
// extraction is complete. make sure to handle the err
})
```

### Options

- `dir` - defaults to `process.cwd()`
- `dir` (required) - the path to the directory where the extracted files are written
- `defaultDirMode` - integer - Directory Mode (permissions) will default to `493` (octal `0755` in integer)
- `defaultFileMode` - integer - File Mode (permissions) will default to `420` (octal `0644` in integer)
- `onEntry` - function - if present, will be called with `(entry, zipfile)`, entry is every entry from the zip file forwarded from the `entry` event from yauzl. `zipfile` is the `yauzl` instance
Expand Down
Loading