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

[WIP] Rewrite lib/copy/ncp.js #374

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/copy/__tests__/async/copy-gh-89.test.js
Expand Up @@ -22,7 +22,7 @@ describe('copy / gh #89', () => {
fse.remove(TEST_DIR, done)
})

it('should...', done => {
it('should copy successfully', done => {
const A = path.join(TEST_DIR, 'A')
const B = path.join(TEST_DIR, 'B')
fs.mkdirSync(A)
Expand Down
61 changes: 61 additions & 0 deletions lib/copy/__tests__/copy-broken-symlink.test.js
@@ -0,0 +1,61 @@
'use strict'

const fs = require('fs')
const os = require('os')
const fse = require(process.cwd())
const path = require('path')
const assert = require('assert')
const copy = require('../copy')

/* global afterEach, beforeEach, describe, it */

describe('copy() - broken symlink', () => {
const TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'copy-broken-symlinks')
const src = path.join(TEST_DIR, 'src')
const out = path.join(TEST_DIR, 'out')

beforeEach(done => {
fse.emptyDir(TEST_DIR, err => {
assert.ifError(err)
createFixtures(src, done)
})
})

afterEach(done => fse.remove(TEST_DIR, done))

it('should copy broken symlinks by default', done => {
copy(src, out, err => {
assert.ifError(err)
assert.equal(fs.readlinkSync(path.join(out, 'broken-symlink')), path.join(src, 'does-not-exist'))
done()
})
})

it('should throw an error when dereference=true', done => {
copy(src, out, {dereference: true}, err => {
assert.strictEqual(err.code, 'ENOENT')
done()
})
})
})

function createFixtures (srcDir, callback) {
fs.mkdir(srcDir, err => {
let brokenFile
let brokenFileLink

if (err) return callback(err)

try {
brokenFile = path.join(srcDir, 'does-not-exist')
brokenFileLink = path.join(srcDir, 'broken-symlink')
fs.writeFileSync(brokenFile, 'does not matter')
fs.symlinkSync(brokenFile, brokenFileLink, 'file')
} catch (err) {
callback(err)
}

// break the symlink now
fse.remove(brokenFile, callback)
})
}
10 changes: 5 additions & 5 deletions lib/copy/__tests__/copy-permissions.test.js
Expand Up @@ -12,7 +12,7 @@ const o777 = parseInt('777', 8)
const o666 = parseInt('666', 8)
const o444 = parseInt('444', 8)

describe('copy', () => {
describe('+ copy() - permissions', () => {
let TEST_DIR

beforeEach(done => {
Expand Down Expand Up @@ -89,10 +89,10 @@ describe('copy', () => {
const newf2stats = fs.lstatSync(path.join(permDir, 'dest/somedir/f2.bin'))
const newd2stats = fs.lstatSync(path.join(permDir, 'dest/crazydir'))

assert.strictEqual(newf1stats.mode, f1stats.mode)
assert.strictEqual(newd1stats.mode, d1stats.mode)
assert.strictEqual(newf2stats.mode, f2stats.mode)
assert.strictEqual(newd2stats.mode, d2stats.mode)
assert.strictEqual(newf1stats.mode, f1stats.mode, 'f1 mode')
assert.strictEqual(newd1stats.mode, d1stats.mode, 'd1 mode')
assert.strictEqual(newf2stats.mode, f2stats.mode, 'f2 mode')
assert.strictEqual(newd2stats.mode, d2stats.mode, 'd2 mode')

assert.strictEqual(newf1stats.gid, f1stats.gid)
assert.strictEqual(newd1stats.gid, d1stats.gid)
Expand Down
6 changes: 3 additions & 3 deletions lib/copy/__tests__/copy-preserve-time.test.js
Expand Up @@ -9,7 +9,7 @@ const assert = require('assert')

/* global beforeEach, describe, it */

describe('copy', () => {
describe('+ copy() - preserve time', () => {
let TEST_DIR

beforeEach(done => {
Expand All @@ -21,7 +21,7 @@ describe('copy', () => {
const SRC_FIXTURES_DIR = path.join(__dirname, '/fixtures')
const FILES = ['a-file', path.join('a-folder', 'another-file'), path.join('a-folder', 'another-folder', 'file3')]

describe('> when modified option is turned off', () => {
describe('>> when modified option is turned off', () => {
it('should have different timestamps on copy', done => {
const from = path.join(SRC_FIXTURES_DIR)
const to = path.join(TEST_DIR)
Expand All @@ -33,7 +33,7 @@ describe('copy', () => {
})
})

describe('> when modified option is turned on', () => {
describe('>> when modified option is turned on', () => {
it('should have the same timestamps on copy', done => {
const from = path.join(SRC_FIXTURES_DIR)
const to = path.join(TEST_DIR)
Expand Down
192 changes: 192 additions & 0 deletions lib/copy/__tests__/copy-prevent-copying-identical.test.js
@@ -0,0 +1,192 @@
'use strict'

const assert = require('assert')
const os = require('os')
const path = require('path')
const fs = require(process.cwd())
const klawSync = require('klaw-sync')

/* global beforeEach, afterEach, describe, it */

describe('+ copySync() - prevent copying identical files and dirs', () => {
let TEST_DIR = ''
let src = ''
let dest = ''

beforeEach(done => {
TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'copy-sync-prevent-copying-identical')
fs.emptyDir(TEST_DIR, done)
})

afterEach(done => fs.remove(TEST_DIR, done))

it('should return an error if src and dest are the same', done => {
const fileSrc = path.join(TEST_DIR, 'TEST_fs-extra_copy_sync')
const fileDest = path.join(TEST_DIR, 'TEST_fs-extra_copy_sync')

fs.copy(fileSrc, fileDest, err => {
assert.equal(err.message, 'Source and destination must not be the same.')
done()
})
})

// src is directory:
// src is regular, dest is symlink
// src is symlink, dest is regular
// src is symlink, dest is symlink

describe('> when the source is a directory', () => {
describe(`>> when src is regular and dest is a symlink that points to src`, () => {
it('should not copy and return', done => {
src = path.join(TEST_DIR, 'src')
fs.mkdirsSync(src)
const subdir = path.join(TEST_DIR, 'src', 'subdir')
fs.mkdirsSync(subdir)
fs.writeFileSync(path.join(subdir, 'file.txt'), 'some data')

const destLink = path.join(TEST_DIR, 'dest-symlink')
fs.symlinkSync(src, destLink, 'dir')

const oldlen = klawSync(src).length

fs.copy(src, destLink, err => {
assert.ifError(err)

const newlen = klawSync(src).length
assert.strictEqual(newlen, oldlen)
const link = fs.readlinkSync(destLink)
assert.strictEqual(link, src)
done()
})
})
})

describe(`>> when src is a symlink that points to a regular dest`, () => {
it('should not copy and return', done => {
dest = path.join(TEST_DIR, 'dest')
fs.mkdirsSync(dest)
const subdir = path.join(TEST_DIR, 'dest', 'subdir')
fs.mkdirsSync(subdir)
fs.writeFileSync(path.join(subdir, 'file.txt'), 'some data')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be changed to use fs.outputFileSync().


const srcLink = path.join(TEST_DIR, 'src-symlink')
fs.symlinkSync(dest, srcLink, 'dir')

const oldlen = klawSync(dest).length

fs.copy(srcLink, dest, err => {
assert.ifError(err)

// assert nothing copied
const newlen = klawSync(dest).length
assert.strictEqual(newlen, oldlen)
const link = fs.readlinkSync(srcLink)
assert.strictEqual(link, dest)
done()
})
})
})

describe('>> when src and dest are symlinks that point to the exact same path', () => {
it('should not copy and return', done => {
src = path.join(TEST_DIR, 'src')
fs.mkdirsSync(src)
const srcLink = path.join(TEST_DIR, 'src_symlink')
fs.symlinkSync(src, srcLink, 'dir')
const destLink = path.join(TEST_DIR, 'dest_symlink')
fs.symlinkSync(src, destLink, 'dir')

const srclenBefore = klawSync(srcLink).length
const destlenBefore = klawSync(destLink).length

fs.copy(srcLink, destLink, err => {
assert.ifError(err)

const srclenAfter = klawSync(srcLink).length
assert.strictEqual(srclenAfter, srclenBefore, 'src length should not change')
const destlenAfter = klawSync(destLink).length
assert.strictEqual(destlenAfter, destlenBefore, 'dest length should not change')

const srcln = fs.readlinkSync(srcLink)
assert.strictEqual(srcln, src)
const destln = fs.readlinkSync(destLink)
assert.strictEqual(destln, src)
done()
})
})
})
})

// src is file:
// src is regular, dest is symlink
// src is symlink, dest is regular
// src is symlink, dest is symlink

describe('> when the source is a file', () => {
describe(`>> when src is regular and dest is a symlink that points to src`, () => {
it('should not copy and return', done => {
src = path.join(TEST_DIR, 'src', 'somefile.txt')
fs.ensureFileSync(src)
fs.writeFileSync(src, 'some data')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. It will be changed to use fs.outputFileSync() instead.


const destLink = path.join(TEST_DIR, 'dest-symlink')
fs.symlinkSync(src, destLink, 'file')

fs.copy(src, destLink, err => {
assert.ifError(err)

const link = fs.readlinkSync(destLink)
assert.strictEqual(link, src)
assert(fs.readFileSync(link, 'utf8'), 'some data')
done()
})
})
})

describe(`>> when src is a symlink that points to a regular dest`, () => {
it('should not copy and return', done => {
dest = path.join(TEST_DIR, 'dest', 'somefile.txt')
fs.ensureFileSync(dest)
fs.writeFileSync(dest, 'some data')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.


const srcLink = path.join(TEST_DIR, 'src-symlink')
fs.symlinkSync(dest, srcLink, 'file')

fs.copy(srcLink, dest, err => {
assert.ifError(err)

const link = fs.readlinkSync(srcLink)
assert.strictEqual(link, dest)
assert(fs.readFileSync(link, 'utf8'), 'some data')
done()
})
})
})

describe('>> when src and dest are symlinks that point to the exact same path', () => {
it('should not copy and return', done => {
src = path.join(TEST_DIR, 'src', 'srcfile.txt')
fs.ensureFileSync(src)
fs.writeFileSync(src, 'src data')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.


const srcLink = path.join(TEST_DIR, 'src_symlink')
fs.symlinkSync(src, srcLink, 'file')

const destLink = path.join(TEST_DIR, 'dest_symlink')
fs.symlinkSync(src, destLink, 'file')

fs.copy(srcLink, destLink, err => {
assert.ifError(err)

const srcln = fs.readlinkSync(srcLink)
assert.strictEqual(srcln, src)
const destln = fs.readlinkSync(destLink)
assert.strictEqual(destln, src)
assert(fs.readFileSync(srcln, 'utf8'), 'src data')
assert(fs.readFileSync(destln, 'utf8'), 'src data')
done()
})
})
})
})
})