Skip to content

Commit

Permalink
Allow dead symlinks for source/destination, fixes #829
Browse files Browse the repository at this point in the history
  • Loading branch information
loilo committed Apr 6, 2018
1 parent 946ab48 commit c57f7ff
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/ln.js
Expand Up @@ -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 });
}
Expand All @@ -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';
Expand Down
21 changes: 21 additions & 0 deletions test/ln.js
Expand Up @@ -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);
Expand All @@ -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`));
Expand Down

0 comments on commit c57f7ff

Please sign in to comment.