Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(gatsby): ensure that writing node manifests to disk does not break on Windows #33853

Merged
merged 7 commits into from
Nov 12, 2021
57 changes: 57 additions & 0 deletions packages/gatsby/src/utils/__tests__/node-manifest.ts
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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