-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
path: fix posix.relative returns different results #13738
Changes from all commits
466faeb
0864e8e
acfdb47
8d604e1
c8bbf22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -431,6 +431,39 @@ added: v0.11.15 | |
The `path.posix` property provides access to POSIX specific implementations | ||
of the `path` methods. | ||
|
||
*Note*: Be careful when using the following functions directly on Windows. | ||
|
||
### path.posix.resolve([...path]) | ||
If after processing all given `path` segments an absolute path has not yet | ||
been generated, `path.posix.resolve` will throw [`UNSUPPORTED_PLATFORM`] error. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps:
Then include a short snippet about why... Same with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: *Note*: Care should be taken when using `path.posix.resolve()` on Windows due to the fact that resolve will use `process.cwd()` verbatim, and so the output will be a concatenation of Windows and POSIX style paths. |
||
### path.posix.relative(from, to) | ||
If `from` and `to` are both relative path, `path.posix.relative` will use the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please include the |
||
path `/fakepath/` as the current working path to generate the result. | ||
|
||
For example | ||
|
||
``` | ||
path.posix.relative('a/b/c', '../../x'); | ||
|
||
// 'from' will be '/fakepath/a/b/c' | ||
// 'to' will be '/fakepath/../../x', then will be normalized to '/x' | ||
// Returns: '../../../../x' | ||
``` | ||
|
||
If one of `from` and `to` is relative path, `path.posix.relative` will use the | ||
other absolute path as the current working path to generate the result. | ||
|
||
For example | ||
|
||
``` | ||
path.posix.relative('/a/b/c', '../../x'); | ||
|
||
// 'from' will be '/a/b/c' | ||
// 'to' will be '/a/b/c/../../x', then will be normalized to '/a/x' | ||
// Returns: '../../x' | ||
``` | ||
|
||
## path.relative(from, to) | ||
<!-- YAML | ||
added: v0.5.0 | ||
|
@@ -551,6 +584,39 @@ added: v0.11.15 | |
The `path.win32` property provides access to Windows-specific implementations | ||
of the `path` methods. | ||
|
||
*Note*: Be careful when using the following functions directly on POSIX. | ||
|
||
### path.win32.resolve([...path]) | ||
If after processing all given `path` segments an absolute path has not yet | ||
been generated, `path.win32.resolve` will throw [`UNSUPPORTED_PLATFORM`] error. | ||
|
||
### path.win32.relative(from, to) | ||
If `from` and `to` are both relative path, `path.win32.relative` will use the | ||
path `c:\\fakepath\\` as the current working path to generate the result. | ||
|
||
For example | ||
|
||
``` | ||
path.win32.relative('a\\b\\c', '..\\..\\x'); | ||
|
||
// 'from' will be 'c:\\fakepath\\a\\b\\c' | ||
// 'to' will be 'c:\\fakepath\\..\\..\\x', then will be normalized to 'c:\\x' | ||
// Returns: '..\\..\\..\\..\\x' | ||
``` | ||
|
||
If one of `from` and `to` is relative path, `path.win32.relative` will use the | ||
other absolute path as the current working path to generate the result. | ||
|
||
For example | ||
|
||
``` | ||
path.win32.relative('c:\\a\\b\\c', '..\\..\\x'); | ||
|
||
// 'from' will be 'c:\\a\\b\\c' | ||
// 'to' will be 'c:\\a\\b\\c\\..\\..\\x', then will be normalized to 'c:\\a\\x' | ||
// Returns: '..\\..\\x' | ||
``` | ||
|
||
[`TypeError`]: errors.html#errors_class_typeerror | ||
[`path.parse()`]: #path_path_parse_path | ||
[`path.posix`]: #path_path_posix | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,18 @@ function assertPath(path) { | |
} | ||
} | ||
|
||
function assertWindowsPlatform(platform) { | ||
// throw an error if direct use the function on *nix platform | ||
if (platform !== 'win32') | ||
throw new errors.Error('ERR_UNSUPPORTED_PLATFORM'); | ||
} | ||
|
||
function assertPosixPlatform(platform) { | ||
// throw an error if direct use the function on windows platform | ||
if (platform === 'win32') | ||
throw new errors.Error('ERR_UNSUPPORTED_PLATFORM'); | ||
} | ||
|
||
// Resolves . and .. elements in a path with directory names | ||
function normalizeStringWin32(path, allowAboveRoot) { | ||
var res = ''; | ||
|
@@ -187,6 +199,10 @@ const win32 = { | |
path = arguments[i]; | ||
} else if (!resolvedDevice) { | ||
path = process.cwd(); | ||
|
||
// If you use the current working directory, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. // If the current working directory is used ... |
||
// it is necessary to check whether the current platform support. | ||
assertWindowsPlatform(process.platform); | ||
} else { | ||
// Windows has the concept of drive-specific current working | ||
// directories. If we've resolved a drive letter but not yet an | ||
|
@@ -201,6 +217,10 @@ const win32 = { | |
path.slice(0, 3).toLowerCase() !== | ||
resolvedDevice.toLowerCase() + '\\') { | ||
path = resolvedDevice + '\\'; | ||
} else { | ||
// If you use the current working directory, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. // The the current working directory is used... |
||
// it is necessary to check whether the current platform support. | ||
assertWindowsPlatform(process.platform); | ||
} | ||
} | ||
|
||
|
@@ -562,8 +582,38 @@ const win32 = { | |
if (from === to) | ||
return ''; | ||
|
||
var fromOrig = win32.resolve(from); | ||
var toOrig = win32.resolve(to); | ||
var fromOrig; | ||
var toOrig; | ||
var isFromAbsolute = true; | ||
var isToAbsolute = true; | ||
|
||
try { | ||
fromOrig = win32.resolve(from); | ||
} catch (err) { | ||
if (err.code === 'ERR_UNSUPPORTED_PLATFORM') | ||
isFromAbsolute = false; | ||
} | ||
try { | ||
toOrig = win32.resolve(to); | ||
} catch (err) { | ||
if (err.code === 'ERR_UNSUPPORTED_PLATFORM') | ||
isToAbsolute = false; | ||
} | ||
|
||
if (process.platform !== 'win32') { | ||
if (!isFromAbsolute && !isToAbsolute) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like you can do this separately for if (isFromAbsolute) ...
else ...
if (isToAbsolute) ...
else ... Or maybe I'm wrong? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because need to know both type of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok 👍 |
||
from = 'c:\\fakepath\\' + from; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. store the surrogate in a
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👌 |
||
to = 'c:\\fakepath\\' + to; | ||
fromOrig = win32.resolve(from); | ||
toOrig = win32.resolve(to); | ||
} else if (isFromAbsolute && !isToAbsolute) { | ||
to = from + '\\' + to; | ||
toOrig = win32.resolve(to); | ||
} else if (!isFromAbsolute && isToAbsolute) { | ||
from = to + '\\' + from; | ||
fromOrig = win32.resolve(from); | ||
} | ||
} | ||
|
||
if (fromOrig === toOrig) | ||
return ''; | ||
|
@@ -1174,6 +1224,11 @@ const posix = { | |
resolvedAbsolute = path.charCodeAt(0) === 47/*/*/; | ||
} | ||
|
||
// If you use the current working directory, | ||
// it is necessary to check whether the current platform support. | ||
if (cwd) | ||
assertPosixPlatform(process.platform); | ||
|
||
// At this point the path should be resolved to a full absolute path, but | ||
// handle relative paths to be safe (might happen when process.cwd() fails) | ||
|
||
|
@@ -1249,8 +1304,35 @@ const posix = { | |
if (from === to) | ||
return ''; | ||
|
||
from = posix.resolve(from); | ||
to = posix.resolve(to); | ||
var isFromAbsolute = true; | ||
var isToAbsolute = true; | ||
try { | ||
from = posix.resolve(from); | ||
} catch (err) { | ||
if (err.code === 'ERR_UNSUPPORTED_PLATFORM') | ||
isFromAbsolute = false; | ||
} | ||
try { | ||
to = posix.resolve(to); | ||
} catch (err) { | ||
if (err.code === 'ERR_UNSUPPORTED_PLATFORM') | ||
isToAbsolute = false; | ||
} | ||
|
||
if (process.platform === 'win32') { | ||
if (!isFromAbsolute && !isToAbsolute) { | ||
from = '/fakepath/' + from; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wrap (same as above) |
||
to = '/fakepath/' + to; | ||
from = posix.resolve(from); | ||
to = posix.resolve(to); | ||
} else if (isFromAbsolute && !isToAbsolute) { | ||
to = from + '/' + to; | ||
to = posix.resolve(to); | ||
} else if (!isFromAbsolute && isToAbsolute) { | ||
from = to + '/' + from; | ||
from = posix.resolve(from); | ||
} | ||
} | ||
|
||
if (from === to) | ||
return ''; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This note should be moved into the bodies of each of the API sections. Sitting above it, it is far more likely that the Note will become disconnected...