|
14 | 14 | const fs = require('fs'); |
15 | 15 | const path = require('path'); |
16 | 16 |
|
| 17 | +/** |
| 18 | + * Safely rename directory (works across filesystems in Docker) |
| 19 | + * Uses copy + delete instead of rename to avoid EXDEV errors |
| 20 | + */ |
| 21 | +function safeRenameSync(oldPath, newPath) { |
| 22 | + if (!fs.existsSync(oldPath)) { |
| 23 | + return; |
| 24 | + } |
| 25 | + |
| 26 | + try { |
| 27 | + // Try native rename first (faster if on same filesystem) |
| 28 | + fs.renameSync(oldPath, newPath); |
| 29 | + } catch (err) { |
| 30 | + if (err.code === 'EXDEV') { |
| 31 | + // Cross-device error - use copy + delete approach |
| 32 | + copyDirSync(oldPath, newPath); |
| 33 | + fs.rmSync(oldPath, { recursive: true, force: true }); |
| 34 | + } else { |
| 35 | + throw err; |
| 36 | + } |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +/** |
| 41 | + * Recursively copy directory |
| 42 | + */ |
| 43 | +function copyDirSync(src, dest) { |
| 44 | + fs.mkdirSync(dest, { recursive: true }); |
| 45 | + const entries = fs.readdirSync(src, { withFileTypes: true }); |
| 46 | + |
| 47 | + for (const entry of entries) { |
| 48 | + const srcPath = path.join(src, entry.name); |
| 49 | + const destPath = path.join(dest, entry.name); |
| 50 | + |
| 51 | + if (entry.isDirectory()) { |
| 52 | + copyDirSync(srcPath, destPath); |
| 53 | + } else { |
| 54 | + fs.copyFileSync(srcPath, destPath); |
| 55 | + } |
| 56 | + } |
| 57 | +} |
| 58 | + |
17 | 59 | // Load environment variables from .env.local |
18 | 60 | const envPath = path.join(__dirname, '..', '.env.local'); |
19 | 61 | if (fs.existsSync(envPath)) { |
@@ -41,15 +83,15 @@ langDirs.forEach(langDir => { |
41 | 83 | // FAQ is enabled - ensure route is active (faq/ not _faq/) |
42 | 84 | if (fs.existsSync(disabledFaqPath)) { |
43 | 85 | console.log(` Enabling FAQ routes: ${langDir}/_faq → ${langDir}/faq`); |
44 | | - fs.renameSync(disabledFaqPath, faqPath); |
| 86 | + safeRenameSync(disabledFaqPath, faqPath); |
45 | 87 | } else if (fs.existsSync(faqPath)) { |
46 | 88 | console.log(` FAQ routes already enabled: ${langDir}/faq`); |
47 | 89 | } |
48 | 90 | } else { |
49 | 91 | // FAQ is disabled - ensure route is inactive (faq/ → _faq/) |
50 | 92 | if (fs.existsSync(faqPath)) { |
51 | 93 | console.log(` Disabling FAQ routes: ${langDir}/faq → ${langDir}/_faq`); |
52 | | - fs.renameSync(faqPath, disabledFaqPath); |
| 94 | + safeRenameSync(faqPath, disabledFaqPath); |
53 | 95 | } else if (fs.existsSync(disabledFaqPath)) { |
54 | 96 | console.log(` FAQ routes already disabled: ${langDir}/_faq`); |
55 | 97 | } |
|
0 commit comments