chore: import upstream snapshot with attribution
i18n - Build Validation / Validate i18n Builds (24) (push) Has been cancelled
CI - Node.js / Lint (24) (push) Has been cancelled
CI - Node.js / Build (24) (push) Has been cancelled
CI - Node.js / Test (24) (push) Has been cancelled
CI - Node.js / Test - Upcoming Changes (24) (push) Has been cancelled
CI - Node.js / Test - i18n (italian, 24) (push) Has been cancelled
CI - Node.js / Test - i18n (portuguese, 24) (push) Has been cancelled
CD - Docker - GHCR Images / Build and Push Images (push) Has been cancelled
i18n - Build Validation / Validate i18n Builds (24) (push) Has been cancelled
CI - Node.js / Lint (24) (push) Has been cancelled
CI - Node.js / Build (24) (push) Has been cancelled
CI - Node.js / Test (24) (push) Has been cancelled
CI - Node.js / Test - Upcoming Changes (24) (push) Has been cancelled
CI - Node.js / Test - i18n (italian, 24) (push) Has been cancelled
CI - Node.js / Test - i18n (portuguese, 24) (push) Has been cancelled
CD - Docker - GHCR Images / Build and Push Images (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import { exec } from 'child_process';
|
||||
import { readFile, readdir, stat, writeFile } from 'fs/promises';
|
||||
import { join, sep } from 'path';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const asyncExec = promisify(exec);
|
||||
|
||||
const loadDirectory = async (path: string): Promise<string[]> => {
|
||||
const files: string[] = [];
|
||||
const status = await stat(path);
|
||||
if (status.isDirectory()) {
|
||||
const filesInDir = await readdir(path);
|
||||
for (const file of filesInDir) {
|
||||
files.push(...(await loadDirectory(join(path, file))));
|
||||
}
|
||||
} else {
|
||||
files.push(path);
|
||||
}
|
||||
return files.filter(f => !f.includes('DS_Store'));
|
||||
};
|
||||
|
||||
const syncChallenges = async () => {
|
||||
const block = process.env.FCC_BLOCK;
|
||||
const ignore = ['.markdownlint.yaml', '_meta', 'english'];
|
||||
const basePath = join(process.cwd(), 'curriculum', 'challenges');
|
||||
const allLangs = await readdir(basePath);
|
||||
const filtered = allLangs.filter(lang => !ignore.includes(lang));
|
||||
// these will be paths
|
||||
const english = await loadDirectory(join(basePath, 'english'));
|
||||
for (const path of english) {
|
||||
await Promise.all(
|
||||
filtered.map(async lang => {
|
||||
if (block && !path.includes(block)) {
|
||||
return;
|
||||
}
|
||||
const targetPath = path.replace('english', lang);
|
||||
// we swallow the error here to detect if the file doesn't exist
|
||||
const status = await stat(targetPath).catch(() => null);
|
||||
if (!status) {
|
||||
const targetDir = targetPath.split(sep);
|
||||
targetDir.pop();
|
||||
console.log(`Syncing ${path.split('/english/')[1]}`);
|
||||
await asyncExec(
|
||||
`mkdir -p ${targetDir.join(sep)} && cp ${path} ${targetPath}`
|
||||
);
|
||||
}
|
||||
const englishContent = await readFile(path, 'utf-8');
|
||||
if (path.endsWith('LICENSE.txt')) {
|
||||
await writeFile(targetPath, englishContent, 'utf-8');
|
||||
return;
|
||||
}
|
||||
const langContent = await readFile(targetPath, 'utf-8');
|
||||
const engLines = englishContent.split('\n');
|
||||
const engId = engLines.find(l => l.startsWith('id'));
|
||||
const engSlug = engLines.find(l => l.startsWith('dashedName'));
|
||||
const langLines = langContent.split('\n');
|
||||
const langId = langLines.find(l => l.startsWith('id'));
|
||||
const langSlug = langLines.find(
|
||||
l => l.startsWith('dashedName') || l.startsWith('certification:')
|
||||
);
|
||||
if (!langSlug) {
|
||||
throw new Error(
|
||||
`Missing dashedName for ${targetPath}. Please add it so that it matches the English version.`
|
||||
);
|
||||
}
|
||||
if (!langId) {
|
||||
throw new Error(
|
||||
`Missing id for ${targetPath}. Please add it so that it matches the English version.`
|
||||
);
|
||||
}
|
||||
if (engId && engId !== langId) {
|
||||
langLines.splice(langLines.indexOf(langId), 1, engId);
|
||||
console.log(`Updating ID for ${targetPath}`);
|
||||
await writeFile(targetPath, langLines.join('\n'), 'utf-8');
|
||||
}
|
||||
if (engSlug && engSlug !== langSlug) {
|
||||
langLines.splice(langLines.indexOf(langSlug), 1, engSlug);
|
||||
console.log(`Updating dashed name for ${targetPath}`);
|
||||
await writeFile(targetPath, langLines.join('\n'), 'utf-8');
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
for (const lang of filtered) {
|
||||
const langPath = join(process.cwd(), 'curriculum', 'challenges', lang);
|
||||
const langFiles = await loadDirectory(langPath);
|
||||
for (const path of langFiles) {
|
||||
if (block && !path.includes(block)) {
|
||||
continue;
|
||||
}
|
||||
const engPath = path.replace(lang, 'english');
|
||||
// we don't want an error, only need to know that the file exists
|
||||
const existsEnglish = await stat(engPath).catch(() => null);
|
||||
if (!existsEnglish) {
|
||||
console.log(`Unlinking ${path.split(`/${lang}/`)[1]}`);
|
||||
await asyncExec(`rm ${path}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void (async () => {
|
||||
await syncChallenges();
|
||||
})();
|
||||
Reference in New Issue
Block a user