Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a4fa526

Browse filesBrowse files
fs: add directory autodetection to fsPromises.symlink()
PR-URL: #42894 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 50aac70 commit a4fa526
Copy full SHA for a4fa526

File tree

Expand file treeCollapse file tree

3 files changed

+39
-4
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+39
-4
lines changed
Open diff view settings
Collapse file

‎doc/api/fs.md‎

Copy file name to clipboardExpand all lines: doc/api/fs.md
+12-3Lines changed: 12 additions & 3 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1463,18 +1463,27 @@ changes:
14631463
14641464
<!-- YAML
14651465
added: v10.0.0
1466+
changes:
1467+
- version: REPLACEME
1468+
pr-url: https://github.com/nodejs/node/pull/42894
1469+
description: If the `type` argument is `null` or omitted, Node.js will
1470+
autodetect `target` type and automatically
1471+
select `dir` or `file`.
1472+
14661473
-->
14671474
14681475
* `target` {string|Buffer|URL}
14691476
* `path` {string|Buffer|URL}
1470-
* `type` {string} **Default:** `'file'`
1477+
* `type` {string|null} **Default:** `null`
14711478
* Returns: {Promise} Fulfills with `undefined` upon success.
14721479
14731480
Creates a symbolic link.
14741481
14751482
The `type` argument is only used on Windows platforms and can be one of `'dir'`,
1476-
`'file'`, or `'junction'`. Windows junction points require the destination path
1477-
to be absolute. When using `'junction'`, the `target` argument will
1483+
`'file'`, or `'junction'`. If the `type` argument is not a string, Node.js will
1484+
autodetect `target` type and use `'file'` or `'dir'`. If the `target` does not
1485+
exist, `'file'` will be used. Windows junction points require the destination
1486+
path to be absolute. When using `'junction'`, the `target` argument will
14781487
automatically be normalized to absolute path.
14791488
14801489
### `fsPromises.truncate(path[, len])`
Collapse file

‎lib/internal/fs/promises.js‎

Copy file name to clipboardExpand all lines: lib/internal/fs/promises.js
+12-1Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ const {
117117
const getDirectoryEntriesPromise = promisify(getDirents);
118118
const validateRmOptionsPromise = promisify(validateRmOptions);
119119

120+
const isWindows = process.platform === 'win32';
121+
120122
let cpPromises;
121123
function lazyLoadCpPromises() {
122124
return cpPromises ??= require('internal/fs/cp/cp').cpFn;
@@ -714,7 +716,16 @@ async function readlink(path, options) {
714716
}
715717

716718
async function symlink(target, path, type_) {
717-
const type = (typeof type_ === 'string' ? type_ : null);
719+
let type = (typeof type_ === 'string' ? type_ : null);
720+
if (isWindows && type === null) {
721+
try {
722+
const absoluteTarget = pathModule.resolve(`${path}`, '..', `${target}`);
723+
type = (await stat(absoluteTarget)).isDirectory() ? 'dir' : 'file';
724+
} catch {
725+
// Default to 'file' if path is invalid or file does not exist
726+
type = 'file';
727+
}
728+
}
718729
target = getValidatedPath(target, 'target');
719730
path = getValidatedPath(path);
720731
return binding.symlink(preprocessSymlinkDestination(target, type, path),
Collapse file

‎test/parallel/test-fs-symlink-dir.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-fs-symlink-dir.js
+15Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ if (!common.canCreateSymLink())
1212
const assert = require('assert');
1313
const path = require('path');
1414
const fs = require('fs');
15+
const fsPromises = fs.promises;
1516

1617
const tmpdir = require('../common/tmpdir');
1718
tmpdir.refresh();
@@ -36,11 +37,18 @@ function testAsync(target, path) {
3637
}));
3738
}
3839

40+
async function testPromises(target, path) {
41+
await fsPromises.symlink(target, path);
42+
fs.readdirSync(path);
43+
}
44+
3945
for (const linkTarget of linkTargets) {
4046
fs.mkdirSync(path.resolve(tmpdir.path, linkTarget));
4147
for (const linkPath of linkPaths) {
4248
testSync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-sync`);
4349
testAsync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-async`);
50+
testPromises(linkTarget, `${linkPath}-${path.basename(linkTarget)}-promises`)
51+
.then(common.mustCall());
4452
}
4553
}
4654

@@ -57,10 +65,17 @@ for (const linkTarget of linkTargets) {
5765
}));
5866
}
5967

68+
async function testPromises(target, path) {
69+
await fsPromises.symlink(target, path);
70+
assert(!fs.existsSync(path));
71+
}
72+
6073
for (const linkTarget of linkTargets.map((p) => p + '-broken')) {
6174
for (const linkPath of linkPaths) {
6275
testSync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-sync`);
6376
testAsync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-async`);
77+
testPromises(linkTarget, `${linkPath}-${path.basename(linkTarget)}-promises`)
78+
.then(common.mustCall());
6479
}
6580
}
6681
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.