Files
gitea-upload-artifact/scripts/replace-isghes.js
Christopher Homberger 8818363695 v7
2026-04-13 12:21:16 +02:00

221 lines
5.7 KiB
JavaScript

#!/usr/bin/env node
import {promises as fs} from 'node:fs';
import path from 'node:path';
function getEndOfLine(source) {
return source.includes('\r\n') ? '\r\n' : '\n';
}
function findMatchingBrace(source, openBraceIndex) {
let depth = 0;
let inSingleQuote = false;
let inDoubleQuote = false;
let inTemplate = false;
let inLineComment = false;
let inBlockComment = false;
for (let i = openBraceIndex; i < source.length; i += 1) {
const char = source[i];
const nextChar = source[i + 1];
if (inLineComment) {
if (char === '\n') {
inLineComment = false;
}
continue;
}
if (inBlockComment) {
if (char === '*' && nextChar === '/') {
inBlockComment = false;
i += 1;
}
continue;
}
if (inSingleQuote) {
if (char === '\\') {
i += 1;
continue;
}
if (char === "'") {
inSingleQuote = false;
}
continue;
}
if (inDoubleQuote) {
if (char === '\\') {
i += 1;
continue;
}
if (char === '"') {
inDoubleQuote = false;
}
continue;
}
if (inTemplate) {
if (char === '\\') {
i += 1;
continue;
}
if (char === '`') {
inTemplate = false;
}
continue;
}
if (char === '/' && nextChar === '/') {
inLineComment = true;
i += 1;
continue;
}
if (char === '/' && nextChar === '*') {
inBlockComment = true;
i += 1;
continue;
}
if (char === "'") {
inSingleQuote = true;
continue;
}
if (char === '"') {
inDoubleQuote = true;
continue;
}
if (char === '`') {
inTemplate = true;
continue;
}
if (char === '{') {
depth += 1;
continue;
}
if (char === '}') {
depth -= 1;
if (depth === 0) {
return i;
}
}
}
return -1;
}
function buildReplacement(source, startIndex) {
const eol = getEndOfLine(source);
const lineStart = source.lastIndexOf('\n', startIndex - 1) + 1;
const indent = source.slice(lineStart, startIndex).match(/^[\t ]*/)?.[0] ?? '';
const bodyIndent = `${indent} `;
return `function isGhes() {${eol}${bodyIndent}return false;${eol}${indent}}`;
}
function replaceIsGhesFunctions(source) {
const signature = /function\s+isGhes\s*\(\s*\)\s*\{/g;
const ranges = [];
let match;
while ((match = signature.exec(source)) !== null) {
const start = match.index;
const openBraceIndex = start + match[0].lastIndexOf('{');
const closeBraceIndex = findMatchingBrace(source, openBraceIndex);
if (closeBraceIndex < 0) {
throw new Error(`Failed to find closing brace for isGhes() at index ${start}`);
}
ranges.push({start, endExclusive: closeBraceIndex + 1});
signature.lastIndex = closeBraceIndex + 1;
}
if (ranges.length === 0) {
return {updatedSource: source, replacements: 0};
}
let updatedSource = source;
for (let i = ranges.length - 1; i >= 0; i -= 1) {
const {start, endExclusive} = ranges[i];
const replacement = buildReplacement(source, start);
updatedSource =
updatedSource.slice(0, start) +
replacement +
updatedSource.slice(endExclusive);
}
return {updatedSource, replacements: ranges.length};
}
async function* walkJsFiles(dir) {
const entries = await fs.readdir(dir, {withFileTypes: true});
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
yield* walkJsFiles(fullPath);
continue;
}
if (entry.isFile() && fullPath.endsWith('.js')) {
yield fullPath;
}
}
}
async function main() {
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');
const targetArg = args.find(arg => !arg.startsWith('--'));
const targetDir = path.resolve(targetArg ?? 'dist');
const stats = await fs.stat(targetDir).catch(() => null);
if (!stats || !stats.isDirectory()) {
throw new Error(`Target directory does not exist: ${targetDir}`);
}
let filesScanned = 0;
let filesUpdated = 0;
let totalReplacements = 0;
for await (const filePath of walkJsFiles(targetDir)) {
filesScanned += 1;
const source = await fs.readFile(filePath, 'utf8');
const {updatedSource, replacements} = replaceIsGhesFunctions(source);
if (replacements === 0) {
continue;
}
totalReplacements += replacements;
if (updatedSource !== source) {
filesUpdated += 1;
if (!dryRun) {
await fs.writeFile(filePath, updatedSource, 'utf8');
}
}
}
if (dryRun) {
console.log(
`Dry run complete: scanned ${filesScanned} file(s), would update ${filesUpdated} file(s), replacing ${totalReplacements} isGhes() function(s).`
);
return;
}
console.log(
`Done: scanned ${filesScanned} file(s), updated ${filesUpdated} file(s), replaced ${totalReplacements} isGhes() function(s).`
);
}
main().catch(error => {
console.error(error instanceof Error ? error.message : String(error));
process.exitCode = 1;
});