Browse Source

Merge pull request #169 from reggi/feature/ensurelink

suppress ensureLink & ensureSymlink dest exists error
ci/travis-osximage
JP Richardson 9 years ago
parent
commit
9a28bac8d9
  1. 35
      lib/ensure/__tests__/link.test.js
  2. 70
      lib/ensure/__tests__/symlink.test.js
  3. 30
      lib/ensure/link.js
  4. 28
      lib/ensure/symlink.js

35
lib/ensure/__tests__/link.test.js

@ -34,7 +34,7 @@ describe('fse-ensure-link', function () {
[['../foo.txt', './link.txt'], 'file-error', 'file-error'], [['../foo.txt', './link.txt'], 'file-error', 'file-error'],
[['../dir-foo/foo.txt', './link.txt'], 'file-error', 'file-error'], [['../dir-foo/foo.txt', './link.txt'], 'file-error', 'file-error'],
// error is thrown if destination path exists // error is thrown if destination path exists
[['./foo.txt', './dir-foo/foo.txt'], 'file-error', 'file-error'], [['./foo.txt', './dir-foo/foo.txt'], 'file-error', 'file-dest-exists'],
[[path.resolve(path.join(TEST_DIR, './foo.txt')), './link.txt'], 'file-success', 'file-success'], [[path.resolve(path.join(TEST_DIR, './foo.txt')), './link.txt'], 'file-success', 'file-success'],
[[path.resolve(path.join(TEST_DIR, './dir-foo/foo.txt')), './link.txt'], 'file-success', 'file-success'], [[path.resolve(path.join(TEST_DIR, './dir-foo/foo.txt')), './link.txt'], 'file-success', 'file-success'],
[[path.resolve(path.join(TEST_DIR, './missing.txt')), './link.txt'], 'file-error', 'file-error'], [[path.resolve(path.join(TEST_DIR, './missing.txt')), './link.txt'], 'file-error', 'file-error'],
@ -107,6 +107,23 @@ describe('fse-ensure-link', function () {
}) })
} }
function fileDestExists (args, fn) {
var srcpath = args[0]
var dstpath = args[1]
var should = util.format('should do nothing using src `%s` and dst `%s`', srcpath, dstpath)
it(should, function (done) {
var destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
var callback = function (err) {
if (err) return done(err)
var destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
assert.equal(destinationContentBefore, destinationContentAfter)
return done()
}
args.push(callback)
return fn.apply(null, args)
})
}
function fileSuccessSync (args, fn) { function fileSuccessSync (args, fn) {
var srcpath = args[0] var srcpath = args[0]
var dstpath = args[1] var dstpath = args[1]
@ -144,6 +161,18 @@ describe('fse-ensure-link', function () {
}) })
} }
function fileDestExistsSync (args, fn) {
var srcpath = args[0]
var dstpath = args[1]
var should = util.format('should do nothing using src `%s` and dst `%s`', srcpath, dstpath)
it(should, function () {
var destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
fn.apply(null, args)
var destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
assert.equal(destinationContentBefore, destinationContentAfter)
})
}
describe('fs.link()', function () { describe('fs.link()', function () {
var fn = fs.link var fn = fs.link
tests.forEach(function (test) { tests.forEach(function (test) {
@ -152,6 +181,7 @@ describe('fse-ensure-link', function () {
// var newBehavior = test[2] // var newBehavior = test[2]
if (nativeBehavior === 'file-success') fileSuccess(args, fn) if (nativeBehavior === 'file-success') fileSuccess(args, fn)
if (nativeBehavior === 'file-error') fileError(args, fn) if (nativeBehavior === 'file-error') fileError(args, fn)
if (nativeBehavior === 'file-dest-exists') fileDestExists(args, fn)
}) })
}) })
@ -163,6 +193,7 @@ describe('fse-ensure-link', function () {
var newBehavior = test[2] var newBehavior = test[2]
if (newBehavior === 'file-success') fileSuccess(args, fn) if (newBehavior === 'file-success') fileSuccess(args, fn)
if (newBehavior === 'file-error') fileError(args, fn) if (newBehavior === 'file-error') fileError(args, fn)
if (newBehavior === 'file-dest-exists') fileDestExists(args, fn)
}) })
}) })
@ -174,6 +205,7 @@ describe('fse-ensure-link', function () {
// var newBehavior = test[2] // var newBehavior = test[2]
if (nativeBehavior === 'file-success') fileSuccessSync(args, fn) if (nativeBehavior === 'file-success') fileSuccessSync(args, fn)
if (nativeBehavior === 'file-error') fileErrorSync(args, fn) if (nativeBehavior === 'file-error') fileErrorSync(args, fn)
if (nativeBehavior === 'file-dest-exists') fileDestExists(args, fn)
}) })
}) })
@ -185,6 +217,7 @@ describe('fse-ensure-link', function () {
var newBehavior = test[2] var newBehavior = test[2]
if (newBehavior === 'file-success') fileSuccessSync(args, fn) if (newBehavior === 'file-success') fileSuccessSync(args, fn)
if (newBehavior === 'file-error') fileErrorSync(args, fn) if (newBehavior === 'file-error') fileErrorSync(args, fn)
if (newBehavior === 'file-dest-exists') fileDestExistsSync(args, fn)
}) })
}) })

70
lib/ensure/__tests__/symlink.test.js

@ -34,6 +34,8 @@ describe('fse-ensure-symlink', function () {
[['./foo.txt', './alpha/beta/gamma/symlink.txt'], 'file-error', 'file-success'], [['./foo.txt', './alpha/beta/gamma/symlink.txt'], 'file-error', 'file-success'],
[['./missing.txt', './symlink.txt'], 'file-broken', 'file-error'], [['./missing.txt', './symlink.txt'], 'file-broken', 'file-error'],
[['./missing.txt', './missing-dir/symlink.txt'], 'file-error', 'file-error'], [['./missing.txt', './missing-dir/symlink.txt'], 'file-error', 'file-error'],
// error is thrown if destination path exists
[['./foo.txt', './dir-foo/foo.txt'], 'file-error', 'file-dest-exists'],
[['./dir-foo', './symlink-dir-foo'], 'dir-success', 'dir-success'], [['./dir-foo', './symlink-dir-foo'], 'dir-success', 'dir-success'],
[['../dir-bar', './dir-foo/symlink-dir-bar'], 'dir-success', 'dir-success'], [['../dir-bar', './dir-foo/symlink-dir-bar'], 'dir-success', 'dir-success'],
[['./dir-bar', './dir-foo/symlink-dir-bar'], 'dir-broken', 'dir-success'], [['./dir-bar', './dir-foo/symlink-dir-bar'], 'dir-broken', 'dir-success'],
@ -45,6 +47,8 @@ describe('fse-ensure-symlink', function () {
[['./dir-foo', './alpha/beta/dir-foo'], 'dir-error', 'dir-success'], [['./dir-foo', './alpha/beta/dir-foo'], 'dir-error', 'dir-success'],
[['./dir-foo', './alpha/beta/gamma/dir-foo'], 'dir-error', 'dir-success'], [['./dir-foo', './alpha/beta/gamma/dir-foo'], 'dir-error', 'dir-success'],
[['./missing', './dir-foo/symlink-dir-missing'], 'dir-broken', 'dir-error'], [['./missing', './dir-foo/symlink-dir-missing'], 'dir-broken', 'dir-error'],
// error is thrown if destination path exists
[['./dir-foo', './real-alpha/real-beta'], 'dir-error', 'dir-dest-exists'],
[[path.resolve(path.join(TEST_DIR, './foo.txt')), './symlink.txt'], 'file-success', 'file-success'], [[path.resolve(path.join(TEST_DIR, './foo.txt')), './symlink.txt'], 'file-success', 'file-success'],
[[path.resolve(path.join(TEST_DIR, './dir-foo/foo.txt')), './symlink.txt'], 'file-success', 'file-success'], [[path.resolve(path.join(TEST_DIR, './dir-foo/foo.txt')), './symlink.txt'], 'file-success', 'file-success'],
[[path.resolve(path.join(TEST_DIR, './missing.txt')), './symlink.txt'], 'file-broken', 'file-error'], [[path.resolve(path.join(TEST_DIR, './missing.txt')), './symlink.txt'], 'file-broken', 'file-error'],
@ -141,6 +145,23 @@ describe('fse-ensure-symlink', function () {
}) })
} }
function fileDestExists (args, fn) {
var srcpath = args[0]
var dstpath = args[1]
var should = util.format('should do nothing using src `%s` and dst `%s`', srcpath, dstpath)
it(should, function (done) {
var destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
var callback = function (err) {
if (err) return done(err)
var destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
assert.equal(destinationContentBefore, destinationContentAfter)
return done()
}
args.push(callback)
return fn.apply(null, args)
})
}
function dirSuccess (args, fn) { function dirSuccess (args, fn) {
var srcpath = args[0] var srcpath = args[0]
var dstpath = args[1] var dstpath = args[1]
@ -206,6 +227,23 @@ describe('fse-ensure-symlink', function () {
}) })
} }
function dirDestExists (args, fn) {
var srcpath = args[0]
var dstpath = args[1]
var should = util.format('should do nothing using src `%s` and dst `%s`', srcpath, dstpath)
it(should, function (done) {
var destinationContentBefore = fs.readdirSync(dstpath)
var callback = function (err) {
if (err) return done(err)
var destinationContentAfter = fs.readdirSync(dstpath)
assert.deepEqual(destinationContentBefore, destinationContentAfter)
return done()
}
args.push(callback)
return fn.apply(null, args)
})
}
function fileSuccessSync (args, fn) { function fileSuccessSync (args, fn) {
var srcpath = args[0] var srcpath = args[0]
var dstpath = args[1] var dstpath = args[1]
@ -261,6 +299,18 @@ describe('fse-ensure-symlink', function () {
}) })
} }
function fileDestExistsSync (args, fn) {
var srcpath = args[0]
var dstpath = args[1]
var should = util.format('should do nothing using src `%s` and dst `%s`', srcpath, dstpath)
it(should, function () {
var destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
fn.apply(null, args)
var destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
assert.equal(destinationContentBefore, destinationContentAfter)
})
}
function dirSuccessSync (args, fn) { function dirSuccessSync (args, fn) {
var srcpath = args[0] var srcpath = args[0]
var dstpath = args[1] var dstpath = args[1]
@ -316,6 +366,18 @@ describe('fse-ensure-symlink', function () {
}) })
} }
function dirDestExistsSync (args, fn) {
var srcpath = args[0]
var dstpath = args[1]
var should = util.format('should do nothing using src `%s` and dst `%s`', srcpath, dstpath)
it(should, function () {
var destinationContentBefore = fs.readdirSync(dstpath)
fn.apply(null, args)
var destinationContentAfter = fs.readdirSync(dstpath)
assert.deepEqual(destinationContentBefore, destinationContentAfter)
})
}
describe('fs.symlink()', function () { describe('fs.symlink()', function () {
var fn = fs.symlink var fn = fs.symlink
tests.forEach(function (test) { tests.forEach(function (test) {
@ -325,10 +387,12 @@ describe('fse-ensure-symlink', function () {
if (nativeBehavior === 'file-success') fileSuccess(args, fn) if (nativeBehavior === 'file-success') fileSuccess(args, fn)
if (nativeBehavior === 'file-broken') fileBroken(args, fn) if (nativeBehavior === 'file-broken') fileBroken(args, fn)
if (nativeBehavior === 'file-error') fileError(args, fn) if (nativeBehavior === 'file-error') fileError(args, fn)
if (nativeBehavior === 'file-dest-exists') fileDestExists(args, fn)
args.push('dir') args.push('dir')
if (nativeBehavior === 'dir-success') dirSuccess(args, fn) if (nativeBehavior === 'dir-success') dirSuccess(args, fn)
if (nativeBehavior === 'dir-broken') dirBroken(args, fn) if (nativeBehavior === 'dir-broken') dirBroken(args, fn)
if (nativeBehavior === 'dir-error') dirError(args, fn) if (nativeBehavior === 'dir-error') dirError(args, fn)
if (nativeBehavior === 'dir-dest-exists') dirDestExists(args, fn)
}) })
}) })
@ -341,9 +405,11 @@ describe('fse-ensure-symlink', function () {
if (newBehavior === 'file-success') fileSuccess(args, fn) if (newBehavior === 'file-success') fileSuccess(args, fn)
if (newBehavior === 'file-broken') fileBroken(args, fn) if (newBehavior === 'file-broken') fileBroken(args, fn)
if (newBehavior === 'file-error') fileError(args, fn) if (newBehavior === 'file-error') fileError(args, fn)
if (newBehavior === 'file-dest-exists') fileDestExists(args, fn)
if (newBehavior === 'dir-success') dirSuccess(args, fn) if (newBehavior === 'dir-success') dirSuccess(args, fn)
if (newBehavior === 'dir-broken') dirBroken(args, fn) if (newBehavior === 'dir-broken') dirBroken(args, fn)
if (newBehavior === 'dir-error') dirError(args, fn) if (newBehavior === 'dir-error') dirError(args, fn)
if (newBehavior === 'dir-dest-exists') dirDestExists(args, fn)
}) })
}) })
@ -356,10 +422,12 @@ describe('fse-ensure-symlink', function () {
if (nativeBehavior === 'file-success') fileSuccessSync(args, fn) if (nativeBehavior === 'file-success') fileSuccessSync(args, fn)
if (nativeBehavior === 'file-broken') fileBrokenSync(args, fn) if (nativeBehavior === 'file-broken') fileBrokenSync(args, fn)
if (nativeBehavior === 'file-error') fileErrorSync(args, fn) if (nativeBehavior === 'file-error') fileErrorSync(args, fn)
if (nativeBehavior === 'file-dest-exists') fileDestExistsSync(args, fn)
args.push('dir') args.push('dir')
if (nativeBehavior === 'dir-success') dirSuccessSync(args, fn) if (nativeBehavior === 'dir-success') dirSuccessSync(args, fn)
if (nativeBehavior === 'dir-broken') dirBrokenSync(args, fn) if (nativeBehavior === 'dir-broken') dirBrokenSync(args, fn)
if (nativeBehavior === 'dir-error') dirErrorSync(args, fn) if (nativeBehavior === 'dir-error') dirErrorSync(args, fn)
if (nativeBehavior === 'dir-dest-exists') dirDestExistsSync(args, fn)
}) })
}) })
@ -372,9 +440,11 @@ describe('fse-ensure-symlink', function () {
if (newBehavior === 'file-success') fileSuccessSync(args, fn) if (newBehavior === 'file-success') fileSuccessSync(args, fn)
if (newBehavior === 'file-broken') fileBrokenSync(args, fn) if (newBehavior === 'file-broken') fileBrokenSync(args, fn)
if (newBehavior === 'file-error') fileErrorSync(args, fn) if (newBehavior === 'file-error') fileErrorSync(args, fn)
if (newBehavior === 'file-dest-exists') fileDestExistsSync(args, fn)
if (newBehavior === 'dir-success') dirSuccessSync(args, fn) if (newBehavior === 'dir-success') dirSuccessSync(args, fn)
if (newBehavior === 'dir-broken') dirBrokenSync(args, fn) if (newBehavior === 'dir-broken') dirBrokenSync(args, fn)
if (newBehavior === 'dir-error') dirErrorSync(args, fn) if (newBehavior === 'dir-error') dirErrorSync(args, fn)
if (newBehavior === 'dir-dest-exists') dirDestExistsSync(args, fn)
}) })
}) })

30
lib/ensure/link.js

@ -10,18 +10,20 @@ function createLink (srcpath, dstpath, callback) {
}) })
} }
fs.lstat(srcpath, function (err, stat) { fs.exists(dstpath, function (destinationExists) {
if (err) { if (destinationExists) return callback(null)
err.message = err.message.replace('lstat', 'ensureLink') fs.lstat(srcpath, function (err, stat) {
return callback(err) if (err) {
} err.message = err.message.replace('lstat', 'ensureLink')
return callback(err)
var dir = path.dirname(dstpath) }
fs.exists(dir, function (dirExists) { var dir = path.dirname(dstpath)
if (dirExists) return makeLink(srcpath, dstpath) fs.exists(dir, function (dirExists) {
mkdir.mkdirs(dir, function (err) { if (dirExists) return makeLink(srcpath, dstpath)
if (err) return callback(err) mkdir.mkdirs(dir, function (err) {
makeLink(srcpath, dstpath) if (err) return callback(err)
makeLink(srcpath, dstpath)
})
}) })
}) })
}) })
@ -29,6 +31,9 @@ function createLink (srcpath, dstpath, callback) {
function createLinkSync (srcpath, dstpath, callback) { function createLinkSync (srcpath, dstpath, callback) {
var destinationExists = fs.existsSync(dstpath)
if (destinationExists) return undefined
try { try {
fs.lstatSync(srcpath) fs.lstatSync(srcpath)
} catch (err) { } catch (err) {
@ -40,6 +45,7 @@ function createLinkSync (srcpath, dstpath, callback) {
var dirExists = fs.existsSync(dir) var dirExists = fs.existsSync(dir)
if (dirExists) return fs.linkSync(srcpath, dstpath) if (dirExists) return fs.linkSync(srcpath, dstpath)
mkdir.mkdirsSync(dir) mkdir.mkdirsSync(dir)
return fs.linkSync(srcpath, dstpath) return fs.linkSync(srcpath, dstpath)
} }

28
lib/ensure/symlink.js

@ -15,17 +15,21 @@ var symlinkTypeSync = _symlinkType.symlinkTypeSync
function createSymlink (srcpath, dstpath, type, callback) { function createSymlink (srcpath, dstpath, type, callback) {
callback = (typeof type === 'function') ? type : callback callback = (typeof type === 'function') ? type : callback
type = (typeof type === 'function') ? false : type type = (typeof type === 'function') ? false : type
symlinkPaths(srcpath, dstpath, function (err, relative) {
if (err) return callback(err) fs.exists(dstpath, function (destinationExists) {
srcpath = relative.toDst if (destinationExists) return callback(null)
symlinkType(relative.toCwd, type, function (err, type) { symlinkPaths(srcpath, dstpath, function (err, relative) {
if (err) return callback(err) if (err) return callback(err)
var dir = path.dirname(dstpath) srcpath = relative.toDst
fs.exists(dir, function (dirExists) { symlinkType(relative.toCwd, type, function (err, type) {
if (dirExists) return fs.symlink(srcpath, dstpath, type, callback) if (err) return callback(err)
mkdirs(dir, function (err) { var dir = path.dirname(dstpath)
if (err) return callback(err) fs.exists(dir, function (dirExists) {
fs.symlink(srcpath, dstpath, type, callback) if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
mkdirs(dir, function (err) {
if (err) return callback(err)
fs.symlink(srcpath, dstpath, type, callback)
})
}) })
}) })
}) })
@ -35,6 +39,10 @@ function createSymlink (srcpath, dstpath, type, callback) {
function createSymlinkSync (srcpath, dstpath, type, callback) { function createSymlinkSync (srcpath, dstpath, type, callback) {
callback = (typeof type === 'function') ? type : callback callback = (typeof type === 'function') ? type : callback
type = (typeof type === 'function') ? false : type type = (typeof type === 'function') ? false : type
var destinationExists = fs.existsSync(dstpath)
if (destinationExists) return undefined
var relative = symlinkPathsSync(srcpath, dstpath) var relative = symlinkPathsSync(srcpath, dstpath)
srcpath = relative.toDst srcpath = relative.toDst
type = symlinkTypeSync(relative.toCwd, type) type = symlinkTypeSync(relative.toCwd, type)

Loading…
Cancel
Save