Fix CRLF and submodules with auto-generated copyright headers

We no longer add another character to the file every time it is committed, and instead now properly handle CRLF. Additionally submodules are no longer updated when they shouldn't be, without requiring a manual config edit.
This commit is contained in:
Michael Fabian 'Xaymar' Dirks
2024-07-05 15:19:18 +02:00
parent af243a8ce8
commit 22c7614e7c
14 changed files with 108 additions and 33 deletions
+85 -27
View File
@@ -1,8 +1,6 @@
// AUTOGENERATED COPYRIGHT HEADER START
// Copyright (C) NaN-NaN undefined
// Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
// AUTOGENERATED COPYRIGHT HEADER END
const ignoreList = [
/^\.git$/gi,
/^cmake\/clang$/gi,
@@ -39,6 +37,10 @@ const formatStyleList = {
], exts: [
".iss",
".iss.in",
".bb",
".b3d",
".b2d",
".bpl"
],
prepend: [
`; ${sectionStart}`,
@@ -111,6 +113,7 @@ const PATH = require("node:path");
const FS = require("node:fs");
const FSPROMISES = require("node:fs/promises");
const OS = require("os");
const READLINE = require('node:readline');
if (!debug)
console.debug = function() {}
@@ -191,11 +194,12 @@ class RateLimiter {
}
let abortAllWork = false;
let gitRL = new RateLimiter(1);
let gitRL = new RateLimiter(3);
let workRL = new RateLimiter();
let gitCurrentFiles;
let gitUserName;
let gitUserMail;
let gitSubmodules;
let gitDate = (new Date()).toISOString();
/** Run a process asynchronously, returning an array of messages.
@@ -265,6 +269,8 @@ async function runProcessAsync(path, args, options) {
async function git_isIgnored(path) {
console.debug(arguments.callee.name, Array.from(arguments));
let rpath = PATH.relative(process.cwd(), path).replaceAll(PATH.sep, PATH.posix.sep);
// Check manual ignore list.
for (let ignore of ignoreList) {
if (ignore instanceof RegExp) {
if (ignore.global) {
@@ -282,6 +288,15 @@ async function git_isIgnored(path) {
}
}
// Check if this happens to be (in) a submodule.
let modules = await git_subModules()
for (let module of modules) {
if (rpath.startsWith(module)) {
return true;
}
}
// Finally check if git ignores this file.
let result = await gitRL.queue(runProcessAsync, "git", ["check-ignore", path], {});
return (result[0] == 0)
}
@@ -299,6 +314,31 @@ async function git_getCurrentAuthor() {
return commitFormat.replace("%aI", gitDate).replace("%aN", gitUserName).replace("%aE", gitUserMail);
}
async function git_subModules() {
if (!gitSubmodules) {
gitSubmodules = new Set();
let gitmodules = PATH.join(process.cwd(), ".gitmodules");
if ((await FSPROMISES.stat(gitmodules)).isFile()) {
let gmfs = FS.createReadStream(gitmodules);
const rl = READLINE.createInterface({
input: gmfs,
crlfDelay: Infinity
});
for await(const line of rl) {
let parts = line.trim().split("=");
if (parts.length > 1) {
if(parts[0].trim() == "path") {
gitSubmodules.add(parts[1].trim());
}
}
}
}
}
return gitSubmodules;
}
async function git_isInCurrentCommit(file) {
console.debug(arguments.callee.name, Array.from(arguments));
if (!gitCurrentFiles) {
@@ -444,39 +484,46 @@ async function updateFile(file) {
}
console.log(`Updating file '${file}'...`);
// ToDo: Do we actually need to read the file first, or can we use the same rw stream?
// File contents.
let content = await FSPROMISES.readFile(file);
let eol = (content.indexOf("\r\n") != -1 ? OS.EOL : "\n");
let insert = Buffer.from(header.join(eol) + eol);
let contentBuf = await FSPROMISES.readFile(file);
let eol = contentBuf.indexOf("\r\n") != -1 ? "\r\n" : "\n";
let headerBuf = Buffer.from(header.join(eol) + eol, "utf8");
// Find the starting point.
let startHeader = content.indexOf(sectionStart);
startHeader = content.lastIndexOf(eol, startHeader);
startHeader += Buffer.from(eol).byteLength;
let startHeader = contentBuf.indexOf(Buffer.from(header[0], "utf8"));
if (startHeader != -1) {
//startHeader = contentBuf.lastIndexOf(eolBuf, startHeader);
//startHeader += eolb.byteLength;
}
console.log(sectionStart, startHeader);
// Find the ending point.
let endHeader = content.indexOf(sectionEnd);
endHeader = content.indexOf(eol, endHeader);
endHeader += Buffer.from(eol).byteLength;
let endHeader = contentBuf.lastIndexOf(Buffer.from(header[header.length - 1], "utf8"));
if (endHeader != -1) {
endHeader += Buffer.from(header[header.length - 1], "utf8").byteLength;
endHeader += Buffer.byteLength(eol, "utf8");
}
console.log(sectionEnd, endHeader);
// Last check for early-exit here.
if (abortAllWork) {
return;
}
let fd = await FSPROMISES.open(file, "w");
let fp = [];
if ((startHeader >= 0) && (endHeader > startHeader)) {
if (startHeader == -1 || (endHeader < startHeader)) {
fd.write(headerBuf, 0, null, 0);
fd.write(contentBuf, 0, null, headerBuf.byteLength);
} else {
let pos = 0;
if (startHeader > 0) {
fd.write(content, 0, startHeader, 0);
fd.write(contentBuf, 0, startHeader - Buffer.byteLength(eol, "utf8").byteLength, 0);
pos += startHeader;
}
fd.write(insert, 0, undefined, pos);
pos += insert.byteLength;
fd.write(content, endHeader, undefined, pos);
} else {
fd.write(insert, 0, undefined, 0);
fd.write(content, 0, undefined, insert.byteLength);
fd.write(headerBuf, 0, null, pos); pos += headerBuf.byteLength;
fd.write(contentBuf, endHeader, null, pos);
}
await fd.close();
} catch (ex) {
@@ -490,11 +537,14 @@ async function updateFile(file) {
async function scanPath(path) {
console.debug(arguments.callee.name, Array.from(arguments));
// Abort here if the user aborted the process, or if the path is ignored.
if (abortAllWork) {
return;
}
console.log(`Scanning path '${path}'...`);
let promises = [];
await workRL.queue(async () => {
@@ -511,7 +561,6 @@ async function scanPath(path) {
}
if (file.isDirectory()) {
console.log(`Scanning path '${fullname}'...`);
promises.push(scanPath(fullname));
} else {
promises.push(updateFile(fullname));
@@ -535,6 +584,7 @@ async function scanPath(path) {
console.debug(root_path, PROCESS.argv, PROCESS.execArgv);
var args = PROCESS.argv.slice(2);
let promises = new Array();
while (args.length > 0) {
// Try to place ourselves where git actually is.
while (!is_git_directory) {
@@ -543,7 +593,7 @@ async function scanPath(path) {
}
let entries = await FSPROMISES.readdir(PROCESS.cwd());
if (entries.includes(".git")) {
if (entries.includes(".git") && ((await FSPROMISES.stat(PATH.join(PROCESS.cwd(), ".git"))).isDirectory())) {
console.log(`Found .git at '${process.cwd()}'.`);
is_git_directory = true;
} else {
@@ -558,6 +608,12 @@ async function scanPath(path) {
return;
}
if (abortAllWork) {
return;
}
git_getCurrentAuthor();
// Then proceed with normal work.
let path = PATH.normalize(PATH.relative(process.cwd(), PATH.resolve(root_path, args[0])));
@@ -567,15 +623,17 @@ async function scanPath(path) {
if (await git_isIgnored(path)) {
console.log(`Ignoring path '${path}'...`);
} else if(pathStat.isDirectory()) {
console.log(`Scanning path '${path}'...`);
await scanPath(path);
//await scanPath(path);
promises.push(scanPath(path));
} else {
await updateFile(path);
//await updateFile(path);
promises.push(updateFile(path));
}
}
// Slice off the first argument and continue.
args = args.slice(1);
}
await Promise.all(promises);
console.log("Done");
})();