Skip to content

Commit

Permalink
BREAKING: Refactor lib/copy/ncp.js
Browse files Browse the repository at this point in the history
- Fix #233 - First argument passed to callback should be an Error
  object, not an array.
- Fix #272 - Should error when options.clobber is false and the
  destination exists.
- Remove options.limit, it is no longer needed with graceful-fs.
  • Loading branch information
RyanZim committed Oct 27, 2016
1 parent 2e7f755 commit 3da22b5
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 31 deletions.
3 changes: 1 addition & 2 deletions lib/copy/__tests__/ncp/broken-symlink.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ describe('ncp broken symlink', function () {

it('should return an error when dereference=true', function (done) {
ncp(src, out, {dereference: true}, function (err) {
assert.equal(err.length, 1)
assert.equal(err[0].code, 'ENOENT')
assert.equal(err.code, 'ENOENT')
done()
})
})
Expand Down
2 changes: 1 addition & 1 deletion lib/copy/__tests__/ncp/ncp-error-perm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('ncp / error / dest-permission', function () {

ncp(src, subdest, function (err) {
assert(err)
assert.equal(err[0].code, 'EACCES')
assert.equal(err.code, 'EACCES')
done()
})
})
Expand Down
15 changes: 12 additions & 3 deletions lib/copy/__tests__/ncp/ncp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var rimraf = require('rimraf')
var readDirFiles = require('read-dir-files').read // temporary, will remove
var ncp = require('../../ncp')

/* global after, before, describe, it */
/* eslint-env mocha */

var fixturesDir = path.join(__dirname, 'fixtures')

Expand Down Expand Up @@ -88,10 +88,19 @@ describe('ncp', function () {
})

describe('when using clobber=false', function () {
it('the copy is completed successfully', function (cb) {
beforeEach(function (done) {
rimraf(out, done)
})
it('works', function (cb) {
ncp(src, out, {clobber: false}, function (err) {
assert.ifError(err)
cb()
})
})
it('errors if files exist', function (cb) {
ncp(src, out, function () {
ncp(src, out, {clobber: false}, function (err) {
assert.ifError(err)
assert(err)
cb()
})
})
Expand Down
38 changes: 13 additions & 25 deletions lib/copy/ncp.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,15 @@ function ncp (source, dest, options, callback) {

var filter = options.filter
var transform = options.transform
var clobber = options.clobber !== false
var clobber = options.clobber !== false // default true
var dereference = options.dereference
var preserveTimestamps = options.preserveTimestamps === true

var errs = null

var started = 0
var finished = 0
var running = 0
// this is pretty useless now that we're using graceful-fs
// consider removing
var limit = options.limit || 512

var errored = false

startCopy(currentPath)

Expand All @@ -49,11 +46,6 @@ function ncp (source, dest, options, callback) {

function getStats (source) {
var stat = dereference ? fs.stat : fs.lstat
if (running >= limit) {
return setImmediate(function () {
getStats(source)
})
}
running++
stat(source, function (err, stats) {
if (err) return onError(err)
Expand Down Expand Up @@ -89,7 +81,11 @@ function ncp (source, dest, options, callback) {
copyFile(file, target)
})
} else {
doneOne()
var err = new Error('EEXIST: ' + target + ' already exists.')
err.code = 'EEXIST'
err.errno = -17
err.path = target
onError(err)
}
}
})
Expand Down Expand Up @@ -133,7 +129,7 @@ function ncp (source, dest, options, callback) {
}

function onDir (dir) {
var target = dir.name.replace(currentPath, targetPath)
var target = dir.name.replace(currentPath, targetPath.replace('$', '$$$$')) // escapes '$' with '$$'
isWritable(target, function (writable) {
if (writable) {
return mkDir(dir, target)
Expand Down Expand Up @@ -214,27 +210,19 @@ function ncp (source, dest, options, callback) {
}

function onError (err) {
if (options.stopOnError) {
// ensure callback is defined & called only once:
if (!errored && callback !== undefined) {
errored = true
return callback(err)
} else if (!errs && options.errs) {
errs = fs.createWriteStream(options.errs)
} else if (!errs) {
errs = []
}
if (typeof errs.write === 'undefined') {
errs.push(err)
} else {
errs.write(err.stack + '\n\n')
}
return doneOne()
}

function doneOne (skipped) {
if (!skipped) running--
finished++
if ((started === finished) && (running === 0)) {
if (callback !== undefined) {
return errs ? callback(errs) : callback(null)
return callback(null)
}
}
}
Expand Down

0 comments on commit 3da22b5

Please sign in to comment.