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"); })();