From 0f2f8efdde82f08e043a4f1a301ae099aa7ee5f8 Mon Sep 17 00:00:00 2001 From: Jason Ginchereau Date: Wed, 14 Sep 2016 15:07:49 -0700 Subject: [PATCH] path: fallback to process cwd when resolving drive cwd The `path.resolve()` function when given just a drive letter such as "C:" tries to get a drive-specific CWD, but that isn't available in cases when the process is not launched via cmd.exe and the process CWD has not been explicitly set on that drive. This change adds a fallback to the process CWD, if the process CWD happens to be on the resolved drive letter. If the process CWD is on another drive, then a drive-specific CWD cannot be resolved and defaults to the drive's root as before. Based on experimentation, the fixed behavior matches that of other similar path resolution implementations on Windows I checked: .NET's `System.IO.Path.GetFullPath()` and Python's `os.path.abspath()`. In the automated path test cases the issue doesn't occur when the tests are run normally from cmd.exe. But it did cause an assertion when running the tests from PowerShell, that is fixed by this change. PR-URL: https://github.com/nodejs/node/pull/8541 Fixes: https://github.com/nodejs/node/issues/7215 Reviewed-By: Bartosz Sosnowski Reviewed-By: James M Snell --- lib/path.js | 8 +++++--- test/fixtures/path-resolve.js | 4 ++++ test/parallel/test-path.js | 12 ++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/path-resolve.js diff --git a/lib/path.js b/lib/path.js index f2fb19edd9..3ed587e0e0 100644 --- a/lib/path.js +++ b/lib/path.js @@ -169,10 +169,12 @@ const win32 = { } else { // Windows has the concept of drive-specific current working // directories. If we've resolved a drive letter but not yet an - // absolute path, get cwd for that drive. We're sure the device is not + // absolute path, get cwd for that drive, or the process cwd if + // the drive cwd is not available. We're sure the device is not // a UNC path at this points, because UNC paths are always absolute. - path = process.env['=' + resolvedDevice]; - // Verify that a drive-local cwd was found and that it actually points + path = process.env['=' + resolvedDevice] || process.cwd(); + + // Verify that a cwd was found and that it actually points // to our drive. If not, default to the drive's root. if (path === undefined || path.slice(0, 3).toLowerCase() !== diff --git a/test/fixtures/path-resolve.js b/test/fixtures/path-resolve.js new file mode 100644 index 0000000000..00eb3d3691 --- /dev/null +++ b/test/fixtures/path-resolve.js @@ -0,0 +1,4 @@ +// Tests resolving a path in the context of a spawned process. +// See https://github.com/nodejs/node/issues/7215 +var path = require('path'); +console.log(path.resolve(process.argv[2])); diff --git a/test/parallel/test-path.js b/test/parallel/test-path.js index 2c6d1e8f02..0a12b5ce92 100644 --- a/test/parallel/test-path.js +++ b/test/parallel/test-path.js @@ -1,6 +1,7 @@ 'use strict'; const common = require('../common'); const assert = require('assert'); +const child = require('child_process'); const path = require('path'); const f = __filename; @@ -444,6 +445,17 @@ resolveTests.forEach(function(test) { }); assert.strictEqual(failures.length, 0, failures.join('')); +if (common.isWindows) { + // Test resolving the current Windows drive letter from a spawned process. + // See https://github.com/nodejs/node/issues/7215 + const currentDriveLetter = path.parse(process.cwd()).root.substring(0, 2); + const resolveFixture = path.join(common.fixturesDir, 'path-resolve.js'); + var spawnResult = child.spawnSync( + process.argv[0], [resolveFixture, currentDriveLetter]); + var resolvedPath = spawnResult.stdout.toString().trim(); + assert.equal(resolvedPath.toLowerCase(), process.cwd().toLowerCase()); +} + // path.isAbsolute tests assert.strictEqual(path.win32.isAbsolute('/'), true);