Skip to content

Commit

Permalink
fix(gatsby): ensure that writing node manifests to disk does not brea…
Browse files Browse the repository at this point in the history
…k on Windows (#33853) (#34020)

* fix: ensure that writing node manifests to disk does not break on Windows

* refactor: use joinPath helper when creating node manifest file name

* feat: replace all invalid Windows file path chars when creating node manifest files

* test: use joinPath helper in node manifest tests

* feat: only replace special windows chars in the manifest filename

* feat: do not use negative look behind for Windows hard drive name

* test: add tests for windows node manifest file name character replacing

(cherry picked from commit f525ce0)

Co-authored-by: Matt Ehlinger <ehlinger.matt@gmail.com>
  • Loading branch information
GatsbyJS Bot and veryspry committed Nov 18, 2021
1 parent 9694010 commit 1589bd8
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
57 changes: 57 additions & 0 deletions packages/gatsby/src/utils/__tests__/node-manifest.ts
Expand Up @@ -12,6 +12,10 @@ import {
processNodeManifests,
} from "../node-manifest"

function itWindows(name: string, fn: () => void): void {
return process.platform === `win32` ? it(name, fn) : xit(name, fn)
}

jest.mock(`fs-extra`, () => {
return {
ensureDir: jest.fn(),
Expand Down Expand Up @@ -342,4 +346,57 @@ describe(`processNodeManifests`, () => {
await testProcessNodeManifests()
process.env.NODE_ENV = `test`
})

itWindows(`replaces reserved Windows characters with a dash`, async () => {
const nodes = [
{ id: `1`, usePageContextId: true },
{ id: `2`, useOwnerNodeId: true },
{ id: `3`, useQueryTracking: true },
]
mockGetNodes(
new Map(nodes.map(node => [`${node.id}`, { id: `${node.id}` }]))
)

store.getState.mockImplementation(() => {
return {
...storeState,
pages: new Map([
[
`/test`,
{
path: `/test`,
context: { id: `1` },
},
],
[
`/test-2`,
{
path: `/test-2`,
context: { id: `2` },
},
],
]),
nodeManifests: [
{
pluginName: `test`,
node: { id: `1` },
// A manifest id containing all of the reserved windows characters that we check
// for and replace
manifestId: `\\*"<>/:?|`,
},
],
queries: {
byNode: new Map([
[`1`, new Set([`/test`, `/test-2`])],
[`2`, new Set([`/test`, `/test-2`])],
]),
},
}
})

await processNodeManifests()
const nodeManifestFileName = path.basename(fs.writeJSON.mock.calls[0][0])

expect(nodeManifestFileName).toEqual(`---------.json`)
})
})
22 changes: 21 additions & 1 deletion packages/gatsby/src/utils/node-manifest.ts
Expand Up @@ -278,13 +278,33 @@ export async function processNodeManifest(

const gatsbySiteDirectory = store.getState().program.directory

let fileNameBase = inputManifest.manifestId

/**
* Windows has a handful of special/reserved characters that are not valid in a file path
* @reference https://superuser.com/questions/358855/what-characters-are-safe-in-cross-platform-file-names-for-linux-windows-and-os
*
* The two exceptions to the list linked above are
* - the colon that is part of the hard disk partition name at the beginning of a file path (i.e. C:)
* - backslashes. We don't want to replace backslashes because those are used to delineate what the actual file path is
*
* During local development, node manifests can be written to disk but are generally unused as they are only used
* for Content Sync which runs in Gatsby Cloud. Gatsby cloud is a Linux environment in which these special chars are valid in
* filepaths. To avoid errors on Windows, we replace all instances of the special chars in the filepath (with the exception of the
* hard disk partition name) with "-" to ensure that local Windows development setups do not break when attempting
* to write one of these manifests to disk.
*/
if (process.platform === `win32`) {
fileNameBase = fileNameBase.replace(/:|\/|\*|\?|"|<|>|\||\\/g, `-`)
}

// write out the manifest file
const manifestFilePath = path.join(
gatsbySiteDirectory,
`public`,
`__node-manifests`,
inputManifest.pluginName,
`${inputManifest.manifestId}.json`
`${fileNameBase}.json`
)

const manifestFileDir = path.dirname(manifestFilePath)
Expand Down

0 comments on commit 1589bd8

Please sign in to comment.