Skip to content

Commit

Permalink
fix(gatsby-cli): normalize case of windows drive letter (#20437)
Browse files Browse the repository at this point in the history
This PR ensures that the current working directory on Windows always has an uppercase drive letter (i.e., C: vs. c:).
  • Loading branch information
vladar authored and wardpeet committed Jan 14, 2020
1 parent ba136ac commit 3e9bf07
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
7 changes: 7 additions & 0 deletions packages/gatsby-cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
#!/usr/bin/env node

import "@babel/polyfill"
import os from "os"
import semver from "semver"
import util from "util"
import createCli from "./create-cli"
import report from "./reporter"
import pkg from "../package.json"
import updateNotifier from "update-notifier"
import ensureWindowsDriveLetterIsUppercase from "./util/ensure-windows-drive-letter-is-uppercase"

const useJsonLogger = process.argv.slice(2).some(arg => arg.includes(`json`))

if (useJsonLogger) {
process.env.GATSBY_LOGGER = `json`
}

// Ensure stable runs on Windows when started from different shells (i.e. c:\dir vs C:\dir)
if (os.platform() === `win32`) {
ensureWindowsDriveLetterIsUppercase()
}

// Check if update is available
updateNotifier({ pkg }).notify({ isGlobal: true })

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const { tmpdir } = require(`os`)
const report = require(`../reporter`)

/**
* This function ensures that the current working directory on Windows
* always has an uppercase drive letter (i.e., C: vs. c:).
*
* Why?
* 1. Different utils like "true-case-path", "normalize-path", "slash" treat Windows
* drive letter differently. "true-case-path" will uppercase, others usually don't care.
* As a result path normalization produces different results depending on current cwd (c: vs. C:)
* which manifests in weird bugs that are very hard to debug.
*
* We can't control community plugins or site code, so everything should be working
* even with a different set of libraries.
*
* Related: https://github.com/Profiscience/true-case-path/issues/3
*
* 2. Builds save some paths in a cache. If you run the first build from "c:" shell
* and then the next one from "C:" shell, you may get a bunch of webpack warnings
* because it expects module paths to be case-sensitive.
*/
module.exports = function ensureWindowsDriveLetterIsUppercase() {
const cwd = process.cwd()
const normalizedCwd = driveLetterToUpperCase(cwd)

if (cwd !== normalizedCwd) {
try {
// When cwd is "c:\dir" then command "cd C:\dir" won't do anything
// You have to change the dir twice to actually change the casing of the path
process.chdir(tmpdir())
process.chdir(normalizedCwd)
} catch {
// rollback
process.chdir(cwd)
}

if (normalizedCwd !== process.cwd()) {
report.warn(
report.stripIndent(`
Your working directory has a lower case drive letter:
"${cwd}".
---^
For solid development experience, we recommend switching it to upper case:
cd "C:\\"
cd "${normalizedCwd}"
(Windows requires two directory switches to change the case of the drive letter)
`)
)
}
}
}

function driveLetterToUpperCase(path) {
const segments = path.split(`:\\`)
return segments.length > 1
? segments.shift().toUpperCase() + `:\\` + segments.join(`:\\`)
: path
}

0 comments on commit 3e9bf07

Please sign in to comment.