Skip to content

Commit

Permalink
Add dest parameter to filter option in copy and copySync
Browse files Browse the repository at this point in the history
  • Loading branch information
manidlou committed Feb 22, 2017
1 parent 5ff2fc8 commit 8923097
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 43 deletions.
16 changes: 16 additions & 0 deletions docs/copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,19 @@ fs.copy('/tmp/mydir', '/tmp/mynewdir', function (err) {
console.log('success!')
}) // copies directory, even if it has subdirectories or files
```

**Using filter function**

```js
var fs = require('fs-extra')

var filterFunc = function (src, dest) {
// your logic here
// it will be copied if return true
}

fs.copy('/tmp/mydir', '/tmp/mynewdir', { filter: filterFunc }, function (err) {
if (err) return console.error(err)
console.log('success!')
})
```
92 changes: 75 additions & 17 deletions lib/copy-sync/__tests__/copy-sync-dir.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,32 @@ describe('+ copySync()', () => {
assert.strictEqual(link, 'destination')
})

it('should should apply filter recursively', () => {
describe('> when the destination dir does not exist', () => {
it('should create the destination directory and copy the file', () => {
const src = path.join(TEST_DIR, 'data/')
fs.mkdirSync(src)

const d1 = 'file1'
const d2 = 'file2'

fs.writeFileSync(path.join(src, 'f1.txt'), d1)
fs.writeFileSync(path.join(src, 'f2.txt'), d2)

const dest = path.join(TEST_DIR, 'this/path/does/not/exist/outputDir')

fs.copySync(src, dest)

const o1 = fs.readFileSync(path.join(dest, 'f1.txt'), 'utf8')
const o2 = fs.readFileSync(path.join(dest, 'f2.txt'), 'utf8')

assert.strictEqual(d1, o1)
assert.strictEqual(d2, o2)
})
})
})

describe('> when filter is used', () => {
it('should should apply filter recursively', done => {
const FILES = 2
// Don't match anything that ends with a digit higher than 0:
const filter = s => /(0|\D)$/i.test(s)
Expand Down Expand Up @@ -104,9 +129,10 @@ describe('+ copySync()', () => {
assert(!fs.existsSync(path.join(destSub, j.toString())))
}
}
done()
})

it('should apply the filter to directory names', () => {
it('should apply the filter to directory names', done => {
const IGNORE = 'ignore'
const filter = p => !~p.indexOf(IGNORE)

Expand All @@ -121,29 +147,61 @@ describe('+ copySync()', () => {

assert(!fs.existsSync(path.join(dest, IGNORE)), 'directory was not ignored')
assert(!fs.existsSync(path.join(dest, IGNORE, 'file')), 'file was not ignored')
done()
})

describe('> when the destination dir does not exist', () => {
it('should create the destination directory and copy the file', () => {
const src = path.join(TEST_DIR, 'data/')
fs.mkdirSync(src)
it('should apply filter when it is applied only to dest', done => {
const timeCond = new Date().getTime()

const d1 = 'file1'
const d2 = 'file2'
const filter = (s, d) => fs.statSync(d).birthtime.getTime() < timeCond

fs.writeFileSync(path.join(src, 'f1.txt'), d1)
fs.writeFileSync(path.join(src, 'f2.txt'), d2)
const subdir = path.join(src, 'subdir')
fs.mkdirsSync(subdir)

const dest = path.join(TEST_DIR, 'this/path/does/not/exist/outputDir')
const dest = path.join(TEST_DIR, 'dest')

fs.copySync(src, dest)
setTimeout(() => {
fs.mkdirsSync(dest)
try {
fs.copySync(src, dest, filter)
} catch (err) {
assert.ifError(err)
}
assert(!fs.existsSync(path.join(dest, 'subdir')))
done()
}, 1000)
})

const o1 = fs.readFileSync(path.join(dest, 'f1.txt'), 'utf8')
const o2 = fs.readFileSync(path.join(dest, 'f2.txt'), 'utf8')
it('should apply filter when it is applied to both src and dest', done => {
const timeCond = new Date().getTime()
const filter = (s, d) => s.split('.').pop() !== 'css' && fs.statSync(path.dirname(d)).birthtime.getTime() > timeCond

assert.strictEqual(d1, o1)
assert.strictEqual(d2, o2)
})
const dest = path.join(TEST_DIR, 'dest')

const srcFile1 = path.join(TEST_DIR, '1.html')
const srcFile2 = path.join(TEST_DIR, '2.css')
const srcFile3 = path.join(TEST_DIR, '3.jade')

fs.writeFileSync(srcFile1, '')
fs.writeFileSync(srcFile2, '')
fs.writeFileSync(srcFile3, '')

const destFile1 = path.join(dest, 'dest1.html')
const destFile2 = path.join(dest, 'dest2.css')
const destFile3 = path.join(dest, 'dest3.jade')

setTimeout(() => {
fs.mkdirsSync(dest)

fs.copySync(srcFile1, destFile1, filter)
fs.copySync(srcFile2, destFile2, filter)
fs.copySync(srcFile3, destFile3, filter)

assert(fs.existsSync(destFile1))
assert(!fs.existsSync(destFile2))
assert(fs.existsSync(destFile3))
done()
}, 1000)
})
})
})
4 changes: 2 additions & 2 deletions lib/copy-sync/copy-sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ function copySync (src, dest, options) {

if (options.filter instanceof RegExp) {
console.warn('Warning: fs-extra: Passing a RegExp filter is deprecated, use a function')
performCopy = options.filter.test(src)
} else if (typeof options.filter === 'function') performCopy = options.filter(src)
performCopy = options.filter.test(src, dest)
} else if (typeof options.filter === 'function') performCopy = options.filter(src, dest)

if (stats.isFile() && performCopy) {
if (!destFolderExists) mkdir.mkdirsSync(destFolder)
Expand Down
178 changes: 156 additions & 22 deletions lib/copy/__tests__/copy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,6 @@ describe('fs-extra', () => {
})
})

it('should only copy files allowed by filter fn', done => {
const srcFile1 = path.join(TEST_DIR, '1.css')
fs.writeFileSync(srcFile1, '')
const destFile1 = path.join(TEST_DIR, 'dest1.css')
const filter = s => s.split('.').pop() !== 'css'
fse.copy(srcFile1, destFile1, filter, () => {
assert(!fs.existsSync(destFile1))
done()
})
})

it('accepts options object in place of filter', done => {
const srcFile1 = path.join(TEST_DIR, '1.jade')
fs.writeFileSync(srcFile1, '')
const destFile1 = path.join(TEST_DIR, 'dest1.jade')
const options = { filter: s => /.html$|.css$/i.test(s) }
fse.copy(srcFile1, destFile1, options, () => {
assert(!fs.existsSync(destFile1))
done()
})
})

it('should copy to a destination file with two \'$\' characters in name (eg: TEST_fs-extra_$$_copy)', done => {
const fileSrc = path.join(TEST_DIR, 'TEST_fs-extra_src')
const fileDest = path.join(TEST_DIR, 'TEST_fs-extra_$$_copy')
Expand Down Expand Up @@ -192,5 +170,161 @@ describe('fs-extra', () => {
})
})
})

describe('> when filter is used', () => {
it('should only copy files allowed by filter fn', done => {
const srcFile1 = path.join(TEST_DIR, '1.css')
fs.writeFileSync(srcFile1, '')
const destFile1 = path.join(TEST_DIR, 'dest1.css')
const filter = s => s.split('.').pop() !== 'css'

fse.copy(srcFile1, destFile1, filter, err => {
assert(!err)
assert(!fs.existsSync(destFile1))
done()
})
})

it('accepts options object in place of filter', done => {
const srcFile1 = path.join(TEST_DIR, '1.jade')
fs.writeFileSync(srcFile1, '')
const destFile1 = path.join(TEST_DIR, 'dest1.jade')
const options = { filter: s => /.html$|.css$/i.test(s) }

fse.copy(srcFile1, destFile1, options, (err) => {
assert(!err)
assert(!fs.existsSync(destFile1))
done()
})
})

it('should should apply filter recursively', done => {
const FILES = 2
// Don't match anything that ends with a digit higher than 0:
const filter = s => /(0|\D)$/i.test(s)

const src = path.join(TEST_DIR, 'src')
fse.mkdirsSync(src)

for (let i = 0; i < FILES; ++i) {
fs.writeFileSync(path.join(src, i.toString()), crypto.randomBytes(SIZE))
}

const subdir = path.join(src, 'subdir')
fse.mkdirsSync(subdir)

for (let i = 0; i < FILES; ++i) {
fs.writeFileSync(path.join(subdir, i.toString()), crypto.randomBytes(SIZE))
}
const dest = path.join(TEST_DIR, 'dest')
fse.copy(src, dest, filter, err => {
assert(!err)

assert(fs.existsSync(dest))
assert(FILES > 1)

for (let i = 0; i < FILES; ++i) {
if (i === 0) {
assert(fs.existsSync(path.join(dest, i.toString())))
} else {
assert(!fs.existsSync(path.join(dest, i.toString())))
}
}

const destSub = path.join(dest, 'subdir')

for (let j = 0; j < FILES; ++j) {
if (j === 0) {
assert(fs.existsSync(path.join(destSub, j.toString())))
} else {
assert(!fs.existsSync(path.join(destSub, j.toString())))
}
}
done()
})
})

it('should apply the filter to directory names', done => {
const IGNORE = 'ignore'
const filter = p => !~p.indexOf(IGNORE)

const src = path.join(TEST_DIR, 'src')
fse.mkdirsSync(src)

const ignoreDir = path.join(src, IGNORE)
fse.mkdirsSync(ignoreDir)

fse.writeFileSync(path.join(ignoreDir, 'file'), crypto.randomBytes(SIZE))

const dest = path.join(TEST_DIR, 'dest')

fse.copySync(src, dest, filter)

assert(!fs.existsSync(path.join(dest, IGNORE)), 'directory was not ignored')
assert(!fs.existsSync(path.join(dest, IGNORE, 'file')), 'file was not ignored')
done()
})

it('should apply filter when it is applied only to dest', done => {
const timeCond = new Date().getTime()

const filter = (s, d) => fs.statSync(d).birthtime.getTime() < timeCond

const src = path.join(TEST_DIR, 'src')
fse.mkdirsSync(src)
const subdir = path.join(src, 'subdir')
fse.mkdirsSync(subdir)

const dest = path.join(TEST_DIR, 'dest')

setTimeout(() => {
fse.mkdirsSync(dest)

fse.copy(src, dest, filter, err => {
assert(!err)
assert(!fs.existsSync(path.join(dest, 'subdir')))
done()
})
}, 1000)
})

it('should apply filter when it is applied to both src and dest', done => {
const timeCond = new Date().getTime()
const filter = (s, d) => s.split('.').pop() !== 'css' && fs.statSync(path.dirname(d)).birthtime.getTime() > timeCond

const dest = path.join(TEST_DIR, 'dest')
setTimeout(() => {
fse.mkdirsSync(dest)

const srcFile1 = path.join(TEST_DIR, '1.html')
const srcFile2 = path.join(TEST_DIR, '2.css')
const srcFile3 = path.join(TEST_DIR, '3.jade')

fse.writeFileSync(srcFile1, '')
fse.writeFileSync(srcFile2, '')
fse.writeFileSync(srcFile3, '')

const destFile1 = path.join(dest, 'dest1.html')
const destFile2 = path.join(dest, 'dest2.css')
const destFile3 = path.join(dest, 'dest3.jade')

fse.copy(srcFile1, destFile1, filter, err => {
assert(!err)
assert(fs.existsSync(destFile1))

fse.copy(srcFile2, destFile2, filter, err => {
assert(!err)
assert(!fs.existsSync(destFile2))

fse.copy(srcFile3, destFile3, filter, err => {
assert(!err)
assert(fs.existsSync(destFile3))
done()
})
})
})
}, 1000)
})
})
})
})
4 changes: 2 additions & 2 deletions lib/copy/ncp.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ function ncp (source, dest, options, callback) {
if (filter) {
if (filter instanceof RegExp) {
console.warn('Warning: fs-extra: Passing a RegExp filter is deprecated, use a function')
if (!filter.test(source)) {
if (!filter.test(source, dest)) {
return doneOne(true)
}
} else if (typeof filter === 'function') {
if (!filter(source)) {
if (!filter(source, dest)) {
return doneOne(true)
}
}
Expand Down

0 comments on commit 8923097

Please sign in to comment.