From c57f7ffc3ffb8ab828b9032ce6effb477dc5cc30 Mon Sep 17 00:00:00 2001 From: Loilo Date: Fri, 6 Apr 2018 10:17:04 +0200 Subject: [PATCH] Allow dead symlinks for source/destination, fixes #829 --- src/ln.js | 21 +++++++++++++++++++-- test/ln.js | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/ln.js b/src/ln.js index 867cc775..f1f4a73f 100644 --- a/src/ln.js +++ b/src/ln.js @@ -39,7 +39,15 @@ function _ln(options, source, dest) { dest = path.join(dest, path.basename(sourcePath)); } - if (fs.existsSync(dest)) { + var destinationExists; + try { + fs.lstatSync(dest); + destinationExists = true; + } catch (err) { + destinationExists = false; + } + + if (destinationExists) { if (!options.force) { common.error('Destination file exists', { continue: true }); } @@ -51,7 +59,16 @@ function _ln(options, source, dest) { var isWindows = process.platform === 'win32'; var linkType = isWindows ? 'file' : null; var resolvedSourcePath = isAbsolute ? sourcePath : path.resolve(process.cwd(), path.dirname(dest), source); - if (!fs.existsSync(resolvedSourcePath)) { + + var resolvedSourceExists; + try { + fs.lstatSync(resolvedSourcePath); + resolvedSourceExists = true; + } catch (err) { + resolvedSourceExists = false; + } + + if (!resolvedSourceExists) { common.error('Source file does not exist', { continue: true }); } else if (isWindows && common.statFollowLinks(resolvedSourcePath).isDirectory()) { linkType = 'junction'; diff --git a/test/ln.js b/test/ln.js index fee55652..2f00f5a9 100644 --- a/test/ln.js +++ b/test/ln.js @@ -157,6 +157,15 @@ test('Inside existing directory', t => { ); }); +test('Link to dead source links', t => { + shell.cd(t.context.tmp); + const result = shell.ln('-s', 'badlink', 'link-to-dead-link'); + t.is(result.code, 0); + t.falsy(result.stderr); + t.falsy(shell.error()); + fs.lstatSync('link-to-dead-link'); +}); + test('-f option', t => { const result = shell.ln('-f', `${t.context.tmp}/file1.js`, `${t.context.tmp}/file2.js`); t.is(result.code, 0); @@ -181,6 +190,18 @@ test('-sf option', t => { }); }); +test('Override dead destination links with -sf', t => { + shell.cd(t.context.tmp); + const result = shell.ln('-sf', 'file1.txt', 'badlink'); + t.is(result.code, 0); + t.falsy(result.stderr); + t.falsy(shell.error()); + t.is( + fs.readFileSync('file1.txt').toString(), + fs.readFileSync('badlink').toString() + ); +}); + test('Abspath regression', t => { utils.skipOnWinForEPERM(shell.ln.bind(shell, '-sf', 'file1', path.resolve(`${t.context.tmp}/abspath`)), () => { t.truthy(fs.existsSync(`${t.context.tmp}/abspath`));