8000 Allow dead symlinks for source/destination, fixes #829 · shelljs/shelljs@c57f7ff · GitHub
[go: up one dir, main page]

Skip to content

Commit c57f7ff

Browse files
committed
Allow dead symlinks for source/destination, fixes #829
1 parent 946ab48 commit c57f7ff

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

src/ln.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,15 @@ function _ln(options, source, dest) {
3939
dest = path.join(dest, path.basename(sourcePath));
4040
}
4141

42-
if (fs.existsSync(dest)) {
42+
var destinationExists;
43+
try {
44+
fs.lstatSync(dest);
45+
destinationExists = true;
46+
} catch (err) {
47+
destinationExists = false;
48+
}
49+
50+
if (destinationExists) {
4351
if (!options.force) {
4452
common.error('Destination file exists', { continue: true });
4553
}
@@ -51,7 +59,16 @@ function _ln(options, source, dest) {
5159
var isWindows = process.platform === 'win32';
5260
var linkType = isWindows ? 'file' : null;
5361
var resolvedSourcePath = isAbsolute ? sourcePath : path.resolve(process.cwd(), path.dirname(dest), source);
54-
if (!fs.existsSync(resolvedSourcePath)) {
62+
63+
var resolvedSourceExists;
64+
try {
65+
fs.lstatSync(resolvedSourcePath);
66+
resolvedSourceExists = true;
67+
} catch (err) {
68+
resolvedSourceExists = false;
69+
}
70+
71+
if (!resolvedSourceExists) {
5572
common.error('Source file does not exist', { continue: true });
5673
} else if (isWindows && common.statFollowLinks(resolvedSourcePath).isDirectory()) {
5774
linkType = 'junction';

test/ln.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ test('Inside existing directory', t => {
157157
);
158158
});
159159

160+
test('Link to dead source links', t => {
161+
shell.cd(t.context.tmp);
162+
const result = shell.ln('-s', 'badlink', 'link-to-dead-link');
163+
t.is(result.code, 0);
164+
t.falsy(result.stderr);
165+
t.falsy(shell.error());
166+
fs.lstatSync('link-to-dead-link');
167+
});
168+
160169
test('-f option', t => {
161170
const result = shell.ln('-f', `${t.context.tmp}/file1.js`, `${t.context.tmp}/file2.js`);
162171
t.is(result.code, 0);
@@ -181,6 +190,18 @@ test('-sf option', t => {
181190
});
182191
});
183192

193+
test('Override dead destination links with -sf', t => {
194+
shell.cd(t.context.tmp);
195+
const result = shell.ln('-sf', 'file1.txt', 'badlink');
196+
t.is(result.code, 0);
197+
t.falsy(result.stderr);
198+
t.falsy(shell.error());
199+
t.is(
200+
fs.readFileSync('file1.txt').toString(),
201+
fs.readFileSync('badlink').toString()
202+
);
203+
});
204+
184205
test('Abspath regression', t => {
185206
utils.skipOnWinForEPERM(shell.ln.bind(shell, '-sf', 'file1', path.resolve(`${t.context.tmp}/abspath`)), () => {
186207
t.truthy(fs.existsSync(`${t.context.tmp}/abspath`));

0 commit comments

Comments
 (0)
0