From 22c7614e7c3f819c2976c907c611ed78c1630445 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Fri, 5 Jul 2024 15:19:18 +0200 Subject: [PATCH] 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. --- .clang-format | 1 - .clang-tidy | 1 - .editorconfig | 1 - .gitignore | 3 + .gitmodules | 3 + CMakeLists.txt | 2 +- code_compiler/CMakeLists.txt | 2 +- tests/.gitignore | 1 - tests/001.bb | 3 + tests/002.bb | 3 + tests/003.bb | 3 + tests/004-incl.bb | 3 + tests/004.bb | 3 + tools/copyright.js | 112 ++++++++++++++++++++++++++--------- 14 files changed, 108 insertions(+), 33 deletions(-) diff --git a/.clang-format b/.clang-format index 81e5d9b..00cafef 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,4 @@ # AUTOGENERATED COPYRIGHT HEADER START -# Copyright (C) NaN-NaN undefined # Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks # AUTOGENERATED COPYRIGHT HEADER END diff --git a/.clang-tidy b/.clang-tidy index 0fa8fe8..20bc191 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,4 @@ # AUTOGENERATED COPYRIGHT HEADER START -# Copyright (C) NaN-NaN undefined # Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks # AUTOGENERATED COPYRIGHT HEADER END diff --git a/.editorconfig b/.editorconfig index bc99ea4..d1c9bf4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,4 @@ # AUTOGENERATED COPYRIGHT HEADER START -# Copyright (C) NaN-NaN undefined # Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks # AUTOGENERATED COPYRIGHT HEADER END diff --git a/.gitignore b/.gitignore index ab5cf1c..a01f889 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# AUTOGENERATED COPYRIGHT HEADER START +# Copyright (C) 2017-2024 Michael Fabian 'Xaymar' Dirks +# AUTOGENERATED COPYRIGHT HEADER END # Build Directories /build /build32 diff --git a/.gitmodules b/.gitmodules index 3050801..6eb97d7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +# AUTOGENERATED COPYRIGHT HEADER START +# Copyright (C) 2017-2024 Michael Fabian 'Xaymar' Dirks +# AUTOGENERATED COPYRIGHT HEADER END [submodule "cmake/cmake-version"] path = cmake/cmake-version url = https://github.com/Xaymar/cmake-version.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 002d01f..fb4642f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -## AUTOGENERATED COPYRIGHT HEADER START +# AUTOGENERATED COPYRIGHT HEADER START # Copyright (C) 2017-2024 Michael Fabian 'Xaymar' Dirks # AUTOGENERATED COPYRIGHT HEADER END cmake_minimum_required(VERSION 3.26...3.29.2 FATAL_ERROR) diff --git a/code_compiler/CMakeLists.txt b/code_compiler/CMakeLists.txt index 905ed8a..0a0c2af 100644 --- a/code_compiler/CMakeLists.txt +++ b/code_compiler/CMakeLists.txt @@ -1,4 +1,4 @@ -## AUTOGENERATED COPYRIGHT HEADER START +# AUTOGENERATED COPYRIGHT HEADER START # Copyright (C) 2017-2024 Michael Fabian 'Xaymar' Dirks # AUTOGENERATED COPYRIGHT HEADER END project(code_compiler diff --git a/tests/.gitignore b/tests/.gitignore index eacc18b..7973735 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,5 +1,4 @@ # AUTOGENERATED COPYRIGHT HEADER START -# Copyright (C) NaN-NaN undefined # Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks # AUTOGENERATED COPYRIGHT HEADER END /stranded2 diff --git a/tests/001.bb b/tests/001.bb index 7f7cf48..2d735c7 100644 --- a/tests/001.bb +++ b/tests/001.bb @@ -1,3 +1,6 @@ +; AUTOGENERATED COPYRIGHT HEADER START +; Copyright (C) 2017 Michael Fabian 'Xaymar' Dirks +; AUTOGENERATED COPYRIGHT HEADER END ; Ein simpler Lexer Test Local Variable = 1.0 Local Variable2$ = "Hallo Welt" diff --git a/tests/002.bb b/tests/002.bb index 0af54d9..54e8be8 100644 --- a/tests/002.bb +++ b/tests/002.bb @@ -1,3 +1,6 @@ +; AUTOGENERATED COPYRIGHT HEADER START +; Copyright (C) 2017 Michael Fabian 'Xaymar' Dirks +; AUTOGENERATED COPYRIGHT HEADER END Graphics 800,600,32,2 SetBuffer BackBuffer() diff --git a/tests/003.bb b/tests/003.bb index 7f6ac74..31f0605 100644 --- a/tests/003.bb +++ b/tests/003.bb @@ -1,3 +1,6 @@ +; AUTOGENERATED COPYRIGHT HEADER START +; Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks +; AUTOGENERATED COPYRIGHT HEADER END Local iValue = 1, iValue2 = 1.2, iValue3 = "Hello World" ; iValue should be 1 ; iValue2 should be 1, and print a warning diff --git a/tests/004-incl.bb b/tests/004-incl.bb index cd1825b..915362b 100644 --- a/tests/004-incl.bb +++ b/tests/004-incl.bb @@ -1 +1,4 @@ +; AUTOGENERATED COPYRIGHT HEADER START +; Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks +; AUTOGENERATED COPYRIGHT HEADER END Local iValue = 2 \ No newline at end of file diff --git a/tests/004.bb b/tests/004.bb index 245d07a..dc74dd8 100644 --- a/tests/004.bb +++ b/tests/004.bb @@ -1,3 +1,6 @@ +; AUTOGENERATED COPYRIGHT HEADER START +; Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks +; AUTOGENERATED COPYRIGHT HEADER END Include "004-incl.bb" ; Should be parsed as: ; Include(String("test.bb")) diff --git a/tools/copyright.js b/tools/copyright.js index 67689a2..3c27b06 100644 --- a/tools/copyright.js +++ b/tools/copyright.js @@ -1,8 +1,6 @@ // AUTOGENERATED COPYRIGHT HEADER START -// Copyright (C) NaN-NaN undefined // Copyright (C) 2024 Michael Fabian 'Xaymar' Dirks // 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"); })();