diff --git a/scripts/apply-patches.mjs b/scripts/apply-patches.mjs index 94e64be..06c345b 100644 --- a/scripts/apply-patches.mjs +++ b/scripts/apply-patches.mjs @@ -1,23 +1,39 @@ import {spawnSync} from 'node:child_process'; -import {readFileSync} from 'node:fs'; -import {dirname, resolve} from 'node:path'; +import {mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {dirname, join, resolve} from 'node:path'; import {fileURLToPath} from 'node:url'; const patchDir = resolve(dirname(fileURLToPath(import.meta.url)), '../patches'); const source = resolve(process.argv[2] || 'fluxer-src'); -const names = readFileSync(resolve(patchDir, 'series'), 'utf8').split(/\r?\n/).filter(Boolean); +const names = readFileSync(resolve(patchDir, 'series'), 'utf8') + .replace(/^\uFEFF/, '').split(/\r?\n/).filter(Boolean); if (!names.length) throw new Error('The patch series is empty'); -const patches = names.map((name) => { +for (const name of names) { if (!/^[0-9]{4}-[a-z0-9-]+\.patch$/.test(name)) throw new Error(`Invalid patch name: ${name}`); - return resolve(patchDir, name); -}); -function apply(...options) { - const result = spawnSync('git', ['-C', source, 'apply', '--whitespace=error-all', ...options, ...patches], { - stdio: 'inherit', - }); - if (result.error) throw result.error; - if (result.status !== 0) throw new Error(`git apply ${options.join(' ')} failed (${result.status})`); } -apply('--check'); -if (!process.argv.includes('--check')) apply(); -console.log(`Validated ${patches.length} GSCORD patches${process.argv.includes('--check') ? '' : ' and applied them'}.`); + +// Windows checkout or an editor may supply CRLF despite .gitattributes. +// Normalize copies, retaining the original patch files and meaningful whitespace. +const temporaryDir = mkdtempSync(join(tmpdir(), 'gscord-patches-')); +try { + const patches = names.map((name) => { + const text = readFileSync(resolve(patchDir, name), 'utf8') + .replace(/^\uFEFF/, '').replace(/\r\n/g, '\n'); + const target = join(temporaryDir, name); + writeFileSync(target, text, 'utf8'); + return target; + }); + function apply(...options) { + const result = spawnSync('git', ['-C', source, 'apply', '--whitespace=error-all', ...options, ...patches], { + stdio: 'inherit', + }); + if (result.error) throw result.error; + if (result.status !== 0) throw new Error(`git apply ${options.join(' ')} failed (${result.status})`); + } + apply('--check'); + if (!process.argv.includes('--check')) apply(); + console.log(`Validated ${patches.length} GSCORD patches${process.argv.includes('--check') ? '' : ' and applied them'}.`); +} finally { + rmSync(temporaryDir, {recursive: true, force: true}); +}