diff --git a/packages/yarnpkg-fslib/sources/path.ts b/packages/yarnpkg-fslib/sources/path.ts index ec2a3857ed1c..1c734404a6ee 100644 --- a/packages/yarnpkg-fslib/sources/path.ts +++ b/packages/yarnpkg-fslib/sources/path.ts @@ -88,6 +88,7 @@ export interface ConvertUtils { const WINDOWS_PATH_REGEXP = /^[a-zA-Z]:.*$/; const PORTABLE_PATH_REGEXP = /^\/[a-zA-Z]:.*$/; +const UNC_PORTABLE_PATH_REGEXP = /^\/\/.*$/; // Path should look like "/N:/berry/scripts/plugin-pack.js" // And transform to "N:\berry\scripts\plugin-pack.js" @@ -95,8 +96,14 @@ function fromPortablePath(p: Path): NativePath { if (process.platform !== 'win32') return p as NativePath; - return p.match(PORTABLE_PATH_REGEXP) ? p.substring(1).replace(/\//g, `\\`) : p; -} + if (!(p.match(PORTABLE_PATH_REGEXP) || p.match(UNC_PORTABLE_PATH_REGEXP))) + return p as NativePath; + + if (p.match(PORTABLE_PATH_REGEXP)) + p = p.substring(1); + + return p.replace(/\//g, `\\`); +}; // Path should look like "N:/berry/scripts/plugin-pack.js" // And transform to "/N:/berry/scripts/plugin-pack.js" diff --git a/packages/yarnpkg-fslib/tests/npath.test.ts b/packages/yarnpkg-fslib/tests/npath.test.ts index 22ce6374392a..96607bcdfc65 100644 --- a/packages/yarnpkg-fslib/tests/npath.test.ts +++ b/packages/yarnpkg-fslib/tests/npath.test.ts @@ -75,6 +75,36 @@ describe(`Portable paths`, () => { const outputPath = `/C:`; expect(npath.toPortablePath(inputPath)).toEqual(outputPath); }); + + it(`should support UNC Windows paths (//[server]/[sharename]/)`, () => { + const inputPath = '\\\\Server01\\user\\docs\\Letter.txt'; + const outputPath = `//Server01/user/docs/Letter.txt`; + expect(npath.toPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should support Long UNC Windows paths (//?/[server]/[sharename]/)`, () => { + const inputPath = '\\\\?\\Server01\\user\\docs\\Letter.txt'; + const outputPath = `//?/Server01/user/docs/Letter.txt`; + expect(npath.toPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should support Long UNC Windows paths (//?/UNC/[server]/[sharename]/)`, () => { + const inputPath = '\\\\?\\UNC\\Server01\\user\\docs\\Letter.txt'; + const outputPath = `//?/UNC/Server01/user/docs/Letter.txt`; + expect(npath.toPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should support Long UNC Windows paths (//?/[drive_spec]:/)`, () => { + const inputPath = '\\\\?\\C:\\user\\docs\\Letter.txt'; + const outputPath = `//?/C:/user/docs/Letter.txt`; + expect(npath.toPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should support Long UNC Windows paths with dot (//./[physical_device]/)`, () => { + const inputPath = '\\\\.\\PhysicalDevice\\user\\docs\\Letter.txt'; + const outputPath = `//./PhysicalDevice/user/docs/Letter.txt`; + expect(npath.toPortablePath(inputPath)).toEqual(outputPath); + }); } }); @@ -127,6 +157,36 @@ describe(`Portable paths`, () => { const outputPath = `C:`; expect(npath.fromPortablePath(inputPath)).toEqual(outputPath); }); + + it(`should transform back UNC Windows paths (//[server]/[sharename]/)`, () => { + const inputPath = `//Server01/user/docs/Letter.txt`; + const outputPath = '\\\\Server01\\user\\docs\\Letter.txt'; + expect(npath.fromPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should transform back Long UNC Windows paths (//?/[server]/[sharename]/)`, () => { + const inputPath = `//?/Server01/user/docs/Letter.txt`; + const outputPath = '\\\\?\\Server01\\user\\docs\\Letter.txt'; + expect(npath.fromPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should transform back Long UNC Windows paths (//?/UNC/[server]/[sharename]/)`, () => { + const inputPath = `//?/UNC/Server01/user/docs/Letter.txt`; + const outputPath = '\\\\?\\UNC\\Server01\\user\\docs\\Letter.txt'; + expect(npath.fromPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should transform back Long UNC Windows paths (//?/[drive_spec]:/)`, () => { + const inputPath = `//?/C:/user/docs/Letter.txt`; + const outputPath = '\\\\?\\C:\\user\\docs\\Letter.txt'; + expect(npath.fromPortablePath(inputPath)).toEqual(outputPath); + }); + + it(`should transform back Long UNC Windows paths with dot (//./[physical_device]/)`, () => { + const inputPath = `//./PhysicalDevice/user/docs/Letter.txt`; + const outputPath = '\\\\.\\PhysicalDevice\\user\\docs\\Letter.txt'; + expect(npath.fromPortablePath(inputPath)).toEqual(outputPath); + }); } }); });