Skip to content

Add Zip Args #32

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,19 @@ zip.zipSync(inPath, outPath)

## api

### `zip.zip(inPath, outPath, [callback])`
### `zip.zip(inPath, outPath, [callback], [args])`

Zip the folder at `inPath` and save it to a .zip file at `outPath`. If a `callback`
is passed, then it is called with an `Error` or `null`.
is passed, then it is called with an `Error` or `null`. The optional `args` object:
```js
{
level: number,
incBase: boolean
}
```
controls compression level (restricted to 0-9) and inclusion of the base folder of given inPath argument. Compression level 0 is no compression, 6 is default, and 9 is optimal compression; optimal is default for Windows.

### `zip.zipSync(inPath, outPath)`
### `zip.zipSync(inPath, outPath, [args])`

Sync version of `zip.zip`.

Expand Down
80 changes: 45 additions & 35 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,84 +6,83 @@ module.exports = {
unzipSync: unzipSync
}

var cp = require('child_process')
var fs = require('fs')
var os = require('os')
var path = require('path')
const cp = require('child_process')
const fs = require('fs')
const os = require('os')
const path = require('path')

function zip (inPath, outPath, cb) {
function zip (inPath, outPath, cb, args = { level: 6, incBase: false }) {
if (!cb) cb = function () {}
if (process.platform === 'win32') {
fs.stat(inPath, function (err, stats) {
if (err) return cb(err)
if (stats.isFile()) {
copyToTemp()
} else {
doZip()
prepare()
}
})
} else {
doZip()
prepare()
}

// Windows zip command cannot zip files, only directories. So move the file into
// a temporary directory before zipping.
function copyToTemp () {
fs.readFile(inPath, function (err, inFile) {
if (err) return cb(err)
var tmpPath = path.join(os.tmpdir(), 'cross-zip-' + Date.now())
const tmpPath = path.join(os.tmpdir(), 'cross-zip-' + Date.now())
fs.mkdir(tmpPath, function (err) {
if (err) return cb(err)
fs.writeFile(path.join(tmpPath, path.basename(inPath)), inFile, function (err) {
if (err) return cb(err)
inPath = tmpPath
doZip()
prepare()
})
})
})
}

// Windows zip command does not overwrite existing files. So do it manually first.
function doZip () {
function prepare () {
if (process.platform === 'win32') {
fs.rmdir(outPath, { recursive: true, maxRetries: 3 }, doZip2)
} else {
doZip2()
fs.rmdirSync(outPath, { recursive: true, maxRetries: 3 })
}
execute(args)
}

function doZip2 () {
var opts = {
function execute (args) {
const opts = {
cwd: path.dirname(inPath),
maxBuffer: Infinity
}
cp.execFile(getZipCommand(), getZipArgs(inPath, outPath), opts, function (err) {
cp.execFile(getZipCommand(), getZipArgs(inPath, outPath, args), opts, function (err) {
cb(err)
})
}
}

function zipSync (inPath, outPath) {
function zipSync (inPath, outPath, args) {
if (process.platform === 'win32') {
if (fs.statSync(inPath).isFile()) {
var inFile = fs.readFileSync(inPath)
var tmpPath = path.join(os.tmpdir(), 'cross-zip-' + Date.now())
const inFile = fs.readFileSync(inPath)
const tmpPath = path.join(os.tmpdir(), 'cross-zip-' + Date.now())
fs.mkdirSync(tmpPath)
fs.writeFileSync(path.join(tmpPath, path.basename(inPath)), inFile)
inPath = tmpPath
}
fs.rmdirSync(outPath, { recursive: true, maxRetries: 3 })
}
var opts = {
const opts = {
cwd: path.dirname(inPath),
maxBuffer: Infinity
}
cp.execFileSync(getZipCommand(), getZipArgs(inPath, outPath), opts)
cp.execFileSync(getZipCommand(), getZipArgs(inPath, outPath, args), opts)
}

function unzip (inPath, outPath, cb) {
if (!cb) cb = function () {}
var opts = {
const opts = {
maxBuffer: Infinity
}
cp.execFile(getUnzipCommand(), getUnzipArgs(inPath, outPath), opts, function (err) {
Expand All @@ -92,7 +91,7 @@ function unzip (inPath, outPath, cb) {
}

function unzipSync (inPath, outPath) {
var opts = {
const opts = {
maxBuffer: Infinity
}
cp.execFileSync(getUnzipCommand(), getUnzipArgs(inPath, outPath), opts)
Expand All @@ -114,22 +113,33 @@ function getUnzipCommand () {
}
}

function quotePath (pathToTransform) {
return '"' + pathToTransform + '"'
}
function getZipArgs (inPath, outPath, args) {
let lvl = args?.level
lvl = parseInt(lvl)
lvl = isNaN(lvl) ? 6 : lvl
lvl = Math.max(0, Math.min(lvl, 9)) // Constrain to 0-9 range

const incBase = args?.incBase ? 1 : 0

function getZipArgs (inPath, outPath) {
if (process.platform === 'win32') {
if (!lvl) {
lvl = 2 // NoCompression
} else if (lvl < 4) {
lvl = 1 // Fastest
} else {
lvl = 0 // Optimal (default)
}

return [
'-nologo',
'-noprofile',
'-command', '& { param([String]$myInPath, [String]$myOutPath); Add-Type -A "System.IO.Compression.FileSystem"; [IO.Compression.ZipFile]::CreateFromDirectory($myInPath, $myOutPath); exit !$? }',
'-myInPath', quotePath(inPath),
'-myOutPath', quotePath(outPath)
'-command', `& { Add-Type -A "System.IO.Compression.FileSystem"; \`
[IO.Compression.ZipFile]::CreateFromDirectory("${inPath}", "${outPath}", ${lvl}, ${incBase}); \`
exit !$? }`
]
} else {
var fileName = path.basename(inPath)
return ['-r', '-y', outPath, fileName]
const fileName = path.basename(inPath)
return [`-${lvl}`, '-r', '-y', outPath, fileName]
}
}

Expand All @@ -138,9 +148,9 @@ function getUnzipArgs (inPath, outPath) {
return [
'-nologo',
'-noprofile',
'-command', '& { param([String]$myInPath, [String]$myOutPath); Add-Type -A "System.IO.Compression.FileSystem"; [IO.Compression.ZipFile]::ExtractToDirectory($myInPath, $myOutPath); exit !$? }',
'-myInPath', quotePath(inPath),
'-myOutPath', quotePath(outPath)
'-command', `& { Add-Type -A "System.IO.Compression.FileSystem"; \`
[IO.Compression.ZipFile]::ExtractToDirectory("${inPath}", "${outPath}"); \`
exit !$? }`
]
} else {
return ['-o', inPath, '-d', outPath]
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
{
"name": "cross-zip",
"description": "Cross-platform .zip file creation",
"version": "4.0.0",
"version": "4.1.0",
"author": {
"name": "Feross Aboukhadijeh",
"email": "feross@feross.org",
"url": "https://feross.org"
},
"contributors": [{
"name": "Robert Brisita",
"url": "https://github.com/rbrisita"
}],
"bugs": {
"url": "https://github.com/feross/cross-zip/issues"
},
Expand Down
46 changes: 26 additions & 20 deletions test/unzip.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
var fs = require('fs')
var path = require('path')
var test = require('tape')
var zip = require('../')
const fs = require('fs')
const path = require('path')
const test = require('tape')
const zip = require('../')

var filePath = path.join(__dirname, 'content', 'file.txt')
var fileZipPath = path.join(__dirname, 'content', 'file.txt.zip')
var tmpPath = path.join(__dirname, 'tmp')
const filePath = path.join(__dirname, 'content', 'file.txt')
const fileZipPath = path.join(__dirname, 'content', 'file.txt.zip')
const tmpPath = path.join(__dirname, 'tmp')

fs.mkdirSync(tmpPath, { recursive: true })

test('unzipSync', function (t) {
var tmpFilePath = path.join(tmpPath, 'file.txt')
fs.rmdirSync(tmpFilePath, { recursive: true })
const tmpFilePath = path.join(tmpPath, 'file.txt')
try {
fs.rmSync(tmpFilePath, { recursive: true })
} catch (err) {
if (err.code !== 'ENOENT') {
t.error(err)
}
}
zip.unzipSync(fileZipPath, tmpPath)

var tmpFile = fs.readFileSync(tmpFilePath)
var file = fs.readFileSync(filePath)
const tmpFile = fs.readFileSync(tmpFilePath)
const file = fs.readFileSync(filePath)

t.deepEqual(tmpFile, file)
t.end()
Expand All @@ -24,15 +30,15 @@ test('unzipSync', function (t) {
test('unzip', function (t) {
t.plan(3)

var tmpFilePath = path.join(tmpPath, 'file.txt')
fs.rmdir(tmpFilePath, { recursive: true }, function (err) {
const tmpFilePath = path.join(tmpPath, 'file.txt')
fs.rm(tmpFilePath, { recursive: true }, function (err) {
t.error(err)

zip.unzip(fileZipPath, tmpPath, function (err) {
t.error(err)

var tmpFile = fs.readFileSync(tmpFilePath)
var file = fs.readFileSync(filePath)
const tmpFile = fs.readFileSync(tmpFilePath)
const file = fs.readFileSync(filePath)

t.deepEqual(tmpFile, file)
})
Expand All @@ -42,20 +48,20 @@ test('unzip', function (t) {
test('unzip from a folder with a space in it', function (t) {
t.plan(4)

var zipSpacePath = path.join(tmpPath, 'folder space', path.basename(fileZipPath))
const zipSpacePath = path.join(tmpPath, 'folder space', path.basename(fileZipPath))
fs.mkdirSync(path.dirname(zipSpacePath), { recursive: true })
fs.copyFileSync(fileZipPath, zipSpacePath)

var tmpFilePath = path.join(tmpPath, 'file.txt')
fs.rmdir(tmpFilePath, { recursive: true }, function (err) {
const tmpFilePath = path.join(tmpPath, 'file.txt')
fs.rm(tmpFilePath, { recursive: true }, function (err) {
t.error(err)

zip.unzip(zipSpacePath, tmpPath, function (err) {
t.error(err)

t.ok(fs.existsSync(tmpFilePath), 'extracted file should exist')
var tmpFile = fs.readFileSync(tmpFilePath)
var file = fs.readFileSync(filePath)
const tmpFile = fs.readFileSync(tmpFilePath)
const file = fs.readFileSync(filePath)

t.deepEqual(tmpFile, file)
})
Expand Down
Loading