windows: fix normalization of UNC paths
This commit is contained in:
parent
a25ebb1997
commit
bc9388342f
38
lib/path.js
38
lib/path.js
@ -59,7 +59,7 @@ if (isWindows) {
|
|||||||
// Regex to split a windows path into three parts: [*, device, slash,
|
// Regex to split a windows path into three parts: [*, device, slash,
|
||||||
// tail] windows-only
|
// tail] windows-only
|
||||||
var splitDeviceRe =
|
var splitDeviceRe =
|
||||||
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/;
|
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
|
||||||
|
|
||||||
// Regex to split the tail part of the above into [*, dir, basename, ext]
|
// Regex to split the tail part of the above into [*, dir, basename, ext]
|
||||||
var splitTailRe =
|
var splitTailRe =
|
||||||
@ -80,6 +80,10 @@ if (isWindows) {
|
|||||||
return [device, dir, basename, ext];
|
return [device, dir, basename, ext];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var normalizeUNCRoot = function(device) {
|
||||||
|
return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\');
|
||||||
|
}
|
||||||
|
|
||||||
// path.resolve([from ...], to)
|
// path.resolve([from ...], to)
|
||||||
// windows version
|
// windows version
|
||||||
exports.resolve = function() {
|
exports.resolve = function() {
|
||||||
@ -138,8 +142,11 @@ if (isWindows) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace slashes (in UNC share name) by backslashes
|
// Convert slashes to backslashes when `resolvedDevice` points to an UNC
|
||||||
resolvedDevice = resolvedDevice.replace(/\//g, '\\');
|
// root. Also squash multiple slashes into a single one where appropriate.
|
||||||
|
if (isUnc) {
|
||||||
|
resolvedDevice = normalizeUNCRoot(resolvedDevice);
|
||||||
|
}
|
||||||
|
|
||||||
// At this point the path should be resolved to a full absolute path,
|
// 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()
|
// but handle relative paths to be safe (might happen when process.cwd()
|
||||||
@ -180,7 +187,10 @@ if (isWindows) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert slashes to backslashes when `device` points to an UNC root.
|
// Convert slashes to backslashes when `device` points to an UNC root.
|
||||||
device = device.replace(/\//g, '\\');
|
// Also squash multiple slashes into a single one where appropriate.
|
||||||
|
if (isUnc) {
|
||||||
|
device = normalizeUNCRoot(device);
|
||||||
|
}
|
||||||
|
|
||||||
return device + (isAbsolute ? '\\' : '') + tail;
|
return device + (isAbsolute ? '\\' : '') + tail;
|
||||||
};
|
};
|
||||||
@ -194,11 +204,21 @@ if (isWindows) {
|
|||||||
var paths = Array.prototype.filter.call(arguments, f);
|
var paths = Array.prototype.filter.call(arguments, f);
|
||||||
var joined = paths.join('\\');
|
var joined = paths.join('\\');
|
||||||
|
|
||||||
// Make sure that the joined path doesn't start with two slashes
|
// Make sure that the joined path doesn't start with two slashes, because
|
||||||
// - it will be mistaken for an unc path by normalize() -
|
// normalize() will mistake it for an UNC path then.
|
||||||
// unless the paths[0] also starts with two slashes
|
//
|
||||||
if (/^[\\\/]{2}/.test(joined) && !/^[\\\/]{2}/.test(paths[0])) {
|
// This step is skipped when it is very clear that the user actually
|
||||||
joined = joined.substr(1);
|
// intended to point at an UNC path. This is assumed when the first
|
||||||
|
// non-empty string arguments starts with exactly two slashes followed by
|
||||||
|
// at least one more non-slash character.
|
||||||
|
//
|
||||||
|
// Note that for normalize() to treat a path as an UNC path it needs to
|
||||||
|
// have at least 2 components, so we don't filter for that here.
|
||||||
|
// This means that the user can use join to construct UNC paths from
|
||||||
|
// a server name and a share name; for example:
|
||||||
|
// path.join('//server', 'share') -> '\\\\server\\share\')
|
||||||
|
if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) {
|
||||||
|
joined = joined.replace(/^[\\\/]{2,}/, '\\');
|
||||||
}
|
}
|
||||||
|
|
||||||
return exports.normalize(joined);
|
return exports.normalize(joined);
|
||||||
|
@ -172,9 +172,67 @@ var joinTests =
|
|||||||
[[' ', '.'], ' '],
|
[[' ', '.'], ' '],
|
||||||
[[' ', '/'], ' /'],
|
[[' ', '/'], ' /'],
|
||||||
[[' ', ''], ' '],
|
[[' ', ''], ' '],
|
||||||
|
[['/', 'foo'], '/foo'],
|
||||||
|
[['/', '/foo'], '/foo'],
|
||||||
|
[['/', '//foo'], '/foo'],
|
||||||
|
[['/', '', '/foo'], '/foo'],
|
||||||
|
[['', '/', 'foo'], '/foo'],
|
||||||
|
[['', '/', '/foo'], '/foo'],
|
||||||
// filtration of non-strings.
|
// filtration of non-strings.
|
||||||
[['x', true, 7, 'y', null, {}], 'x/y']
|
[['x', true, 7, 'y', null, {}], 'x/y']
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Windows-specific join tests
|
||||||
|
if (isWindows) {
|
||||||
|
joinTests = joinTests.concat(
|
||||||
|
[// UNC path expected
|
||||||
|
[['//foo/bar'], '//foo/bar/'],
|
||||||
|
[['\\/foo/bar'], '//foo/bar/'],
|
||||||
|
[['\\\\foo/bar'], '//foo/bar/'],
|
||||||
|
// UNC path expected - server and share separate
|
||||||
|
[['//foo', 'bar'], '//foo/bar/'],
|
||||||
|
[['//foo/', 'bar'], '//foo/bar/'],
|
||||||
|
[['//foo', '/bar'], '//foo/bar/'],
|
||||||
|
// UNC path expected - questionable
|
||||||
|
[['//foo', '', 'bar'], '//foo/bar/'],
|
||||||
|
[['//foo/', '', 'bar'], '//foo/bar/'],
|
||||||
|
[['//foo/', '', '/bar'], '//foo/bar/'],
|
||||||
|
// UNC path expected - even more questionable
|
||||||
|
[['', '//foo', 'bar'], '//foo/bar/'],
|
||||||
|
[['', '//foo/', 'bar'], '//foo/bar/'],
|
||||||
|
[['', '//foo/', '/bar'], '//foo/bar/'],
|
||||||
|
// No UNC path expected (no double slash in first component)
|
||||||
|
[['\\', 'foo/bar'], '/foo/bar'],
|
||||||
|
[['\\', '/foo/bar'], '/foo/bar'],
|
||||||
|
[['', '/', '/foo/bar'], '/foo/bar'],
|
||||||
|
// No UNC path expected (no non-slashes in first component - questionable)
|
||||||
|
[['//', 'foo/bar'], '/foo/bar'],
|
||||||
|
[['//', '/foo/bar'], '/foo/bar'],
|
||||||
|
[['\\\\', '/', '/foo/bar'], '/foo/bar'],
|
||||||
|
[['//'], '/'],
|
||||||
|
// No UNC path expected (share name missing - questionable).
|
||||||
|
[['//foo'], '/foo'],
|
||||||
|
[['//foo/'], '/foo/'],
|
||||||
|
[['//foo', '/'], '/foo/'],
|
||||||
|
[['//foo', '', '/'], '/foo/'],
|
||||||
|
// No UNC path expected (too many leading slashes - questionable)
|
||||||
|
[['///foo/bar'], '/foo/bar'],
|
||||||
|
[['////foo', 'bar'], '/foo/bar'],
|
||||||
|
[['\\\\\\/foo/bar'], '/foo/bar'],
|
||||||
|
// Drive-relative vs drive-absolute paths. This merely describes the
|
||||||
|
// status quo, rather than being obviously right
|
||||||
|
[['c:'], 'c:.'],
|
||||||
|
[['c:.'], 'c:.'],
|
||||||
|
[['c:', ''], 'c:.'],
|
||||||
|
[['', 'c:'], 'c:.'],
|
||||||
|
[['c:.', '/'], 'c:./'],
|
||||||
|
[['c:.', 'file'], 'c:file'],
|
||||||
|
[['c:', '/'], 'c:/'],
|
||||||
|
[['c:', 'file'], 'c:/file']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the join tests.
|
||||||
joinTests.forEach(function(test) {
|
joinTests.forEach(function(test) {
|
||||||
var actual = path.join.apply(path, test[0]);
|
var actual = path.join.apply(path, test[0]);
|
||||||
var expected = isWindows ? test[1].replace(/\//g, '\\') : test[1];
|
var expected = isWindows ? test[1].replace(/\//g, '\\') : test[1];
|
||||||
@ -215,7 +273,13 @@ if (isWindows) {
|
|||||||
[['c:/ignore', 'c:/some/file'], 'c:\\some\\file'],
|
[['c:/ignore', 'c:/some/file'], 'c:\\some\\file'],
|
||||||
[['d:/ignore', 'd:some/dir//'], 'd:\\ignore\\some\\dir'],
|
[['d:/ignore', 'd:some/dir//'], 'd:\\ignore\\some\\dir'],
|
||||||
[['.'], process.cwd()],
|
[['.'], process.cwd()],
|
||||||
[['//server/share', '..', 'relative\\'], '\\\\server\\share\\relative']];
|
[['//server/share', '..', 'relative\\'], '\\\\server\\share\\relative'],
|
||||||
|
[['c:/', '//'], 'c:\\'],
|
||||||
|
[['c:/', '//dir'], 'c:\\dir'],
|
||||||
|
[['c:/', '//server/share'], '\\\\server\\share\\'],
|
||||||
|
[['c:/', '//server//share'], '\\\\server\\share\\'],
|
||||||
|
[['c:/', '///some//dir'], 'c:\\some\\dir']
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
// Posix
|
// Posix
|
||||||
var resolveTests =
|
var resolveTests =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user