mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-28 18:41:14 +00:00
tools: Rate limit operation and fix strange buffer issues
Slightly relaxes the necessary amount of memory, as we are no longer loading everything all at once. Also for unknown reasons git interferes with other git processes running in the same repository only on Linux. This causes Linux runs of this tool to have strange issues detecting the authors, as git just quits with a success error code. Fun.
This commit is contained in:
parent
a091b08259
commit
c9ff7093d4
1 changed files with 401 additions and 369 deletions
|
@ -11,416 +11,448 @@ const OS = require("os");
|
||||||
const SECTION_START = "AUTOGENERATED COPYRIGHT HEADER START";
|
const SECTION_START = "AUTOGENERATED COPYRIGHT HEADER START";
|
||||||
const SECTION_END = "AUTOGENERATED COPYRIGHT HEADER END";
|
const SECTION_END = "AUTOGENERATED COPYRIGHT HEADER END";
|
||||||
const IGNORED = [
|
const IGNORED = [
|
||||||
".git",
|
/^\.git$/gi,
|
||||||
"cmake/clang",
|
/^cmake\/clang$/gi,
|
||||||
"cmake/version",
|
/^cmake\/version$/gi,
|
||||||
"third-party",
|
/^third-party$/gi,
|
||||||
]
|
]
|
||||||
|
|
||||||
let abortAllWork = false;
|
let abortAllWork = false;
|
||||||
|
class RateLimiter {
|
||||||
|
constructor(limit = undefined) {
|
||||||
|
const OS = require("node:os");
|
||||||
|
this._limit = limit;
|
||||||
|
if (!this._limit) {
|
||||||
|
this._limit = Math.ceil(Math.max(2, OS.cpus().length / 3 * 2));
|
||||||
|
}
|
||||||
|
this._cur = this._limit;
|
||||||
|
this._pend = 0;
|
||||||
|
this._locks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(runner) {
|
||||||
|
// Use Promises to spin-lock this execution path until there is a free slot.
|
||||||
|
this._pend += 1;
|
||||||
|
while (true) {
|
||||||
|
if (this._cur > 0) {
|
||||||
|
this._cur -= 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
await Promise.race(this._locks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._pend -= 1;
|
||||||
|
|
||||||
|
let data = {};
|
||||||
|
data.pri = new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
if (runner.constructor.name == "AsyncFunction") {
|
||||||
|
runner().then((res) => {
|
||||||
|
resolve(res);
|
||||||
|
}, (err) => {
|
||||||
|
reject(err);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resolve(runner());
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
reject(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
data.sec = data.pri.finally(() => {
|
||||||
|
// Remove this promise from the locks list.
|
||||||
|
let idx = this._locks.indexOf(data.pri);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this._locks.splice(idx, 1);
|
||||||
|
}
|
||||||
|
let idx2 = this._locks.indexOf(data.sec);
|
||||||
|
if (idx2 >= 0) {
|
||||||
|
this._locks.splice(idx2, 1);
|
||||||
|
}
|
||||||
|
this._cur += 1;
|
||||||
|
//console.log(`Avail: ${this._cur} / ${this._limit}; Pending: ${this._pend}`)
|
||||||
|
});
|
||||||
|
this._locks.push(data.sec);
|
||||||
|
return await data.sec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let gitRL = new RateLimiter(1);
|
||||||
|
let workRL = new RateLimiter();
|
||||||
|
|
||||||
async function isIgnored(path) {
|
async function isIgnored(path) {
|
||||||
let rpath = PATH.relative(process.cwd(), path).replaceAll(PATH.sep, PATH.posix.sep);
|
let rpath = PATH.relative(process.cwd(), path).replaceAll(PATH.sep, PATH.posix.sep);
|
||||||
for (let ignore of IGNORED) {
|
for (let ignore of IGNORED) {
|
||||||
if (ignore instanceof RegExp) {
|
if (ignore instanceof RegExp) {
|
||||||
if (ignore.global) {
|
if (ignore.global) {
|
||||||
if (!rpath.matchAll(ignore).done) {
|
let matches = rpath.matchAll(ignore);
|
||||||
return true;
|
for (let match of matches) {
|
||||||
}
|
return true;
|
||||||
} else {
|
}
|
||||||
if (rpath.match(ignore) !== null) {
|
} else {
|
||||||
return true;
|
if (rpath.match(ignore) !== null) {
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
} else if (rpath.startsWith(ignore)) {
|
}
|
||||||
return true;
|
} else if (rpath.startsWith(ignore)) {
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await new Promise((resolve, reject) => {
|
return await gitRL.run(async () => {
|
||||||
try {
|
return await new Promise((resolve, reject) => {
|
||||||
let proc = CHILD_PROCESS.spawn("git", [
|
try {
|
||||||
"check-ignore",
|
let proc = CHILD_PROCESS.spawn("git", [
|
||||||
path
|
"check-ignore",
|
||||||
], {
|
path
|
||||||
"cwd": PROCESS.cwd(),
|
], {
|
||||||
"encoding": "utf8",
|
"cwd": PROCESS.cwd(),
|
||||||
});
|
"encoding": "utf8",
|
||||||
proc.stdout.on('data', (data) => {
|
});
|
||||||
})
|
proc.stdout.on('data', (data) => {
|
||||||
proc.on('close', (code) => {
|
})
|
||||||
resolve(code == 0);
|
proc.on('close', (code) => {
|
||||||
});
|
resolve(code == 0);
|
||||||
proc.on('exit', (code) => {
|
});
|
||||||
resolve(code == 0);
|
proc.on('exit', (code) => {
|
||||||
});
|
resolve(code == 0);
|
||||||
} catch (ex) {
|
});
|
||||||
reject(ex);
|
} catch (ex) {
|
||||||
}
|
reject(ex);
|
||||||
});
|
}
|
||||||
/* Sync alternative
|
});
|
||||||
try {
|
});
|
||||||
return CHILD_PROCESS.spawnSync("git", [
|
|
||||||
"check-ignore",
|
|
||||||
path
|
|
||||||
], {
|
|
||||||
"cwd": PROCESS.cwd(),
|
|
||||||
"encoding": "utf8"
|
|
||||||
}).status == 0;
|
|
||||||
} catch (ex) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function git_retrieveAuthors(file) {
|
async function git_retrieveAuthors(file) {
|
||||||
// git --no-pager log --date-order --reverse "--format=format:%aI|%aN <%aE>" -- file
|
// git --no-pager log --date-order --reverse "--format=format:%aI|%aN <%aE>" -- file
|
||||||
let lines = await new Promise((resolve, reject) => {
|
let lines = await gitRL.run(async () => {
|
||||||
try {
|
return await new Promise((resolve, reject) => {
|
||||||
let lines = "";
|
try {
|
||||||
let proc = CHILD_PROCESS.spawn("git", [
|
let chunks = [];
|
||||||
"--no-pager",
|
let proc = CHILD_PROCESS.spawn("git", [
|
||||||
"log",
|
"--no-pager",
|
||||||
"--date-order",
|
"log",
|
||||||
"--reverse",
|
"--date-order",
|
||||||
"--format=format:%aI|%aN <%aE>",
|
"--reverse",
|
||||||
"--",
|
"--format=format:%aI|%aN <%aE>",
|
||||||
file
|
"--",
|
||||||
], {
|
file
|
||||||
"cwd": PROCESS.cwd(),
|
], {
|
||||||
"encoding": "utf8",
|
"cwd": PROCESS.cwd(),
|
||||||
});
|
"encoding": "utf8",
|
||||||
proc.stdout.on('data', (data) => {
|
});
|
||||||
lines += data.toString();
|
proc.stdout.on('data', (chunk) => {
|
||||||
})
|
chunks.push(chunk);
|
||||||
proc.on('close', (code) => {
|
});
|
||||||
resolve(lines);
|
proc.stdout.on('close', () => {
|
||||||
});
|
let chunk = proc.stdout.read();
|
||||||
proc.on('exit', (code) => {
|
if (chunk) {
|
||||||
resolve(lines);
|
chunks.push(chunk);
|
||||||
});
|
}
|
||||||
} catch (ex) {
|
});
|
||||||
reject(ex);
|
proc.on('exit', (code) => {
|
||||||
}
|
// Merge all data into one buffer.
|
||||||
});
|
let length = 0;
|
||||||
|
for (let chunk of chunks) {
|
||||||
|
length += chunk.byteLength;
|
||||||
|
}
|
||||||
|
let buf = Buffer.alloc(length);
|
||||||
|
length = 0;
|
||||||
|
for (let chunk of chunks) {
|
||||||
|
if (!(chunk instanceof Buffer)) {
|
||||||
|
chunk = Buffer.from(chunk);
|
||||||
|
}
|
||||||
|
chunk.copy(buf, length, 0);
|
||||||
|
length += chunk.byteLength;
|
||||||
|
}
|
||||||
|
|
||||||
lines = lines.split(lines.indexOf("\r\n") >= 0 ? "\r\n" : "\n");
|
if (code == 0) {
|
||||||
let authors = new Map();
|
if (buf) {
|
||||||
for (let line of lines) {
|
resolve(buf.toString());
|
||||||
let [date, name] = line.split("|");
|
} else {
|
||||||
|
reject(code);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
reject(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
let author = authors.get(name);
|
lines = lines.split(lines.indexOf("\r\n") >= 0 ? "\r\n" : "\n");
|
||||||
if (author) {
|
let authors = new Map();
|
||||||
author.to = new Date(date)
|
for (let line of lines) {
|
||||||
} else {
|
let [date, name] = line.split("|");
|
||||||
authors.set(name, {
|
|
||||||
from: new Date(date),
|
|
||||||
to: new Date(date),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return authors;
|
|
||||||
|
|
||||||
/* Sync Variant
|
let author = authors.get(name);
|
||||||
try {
|
if (author) {
|
||||||
let data = await CHILD_PROCESS
|
author.to = new Date(date)
|
||||||
let lines = data.stdout.toString().split("\n");
|
} else {
|
||||||
let authors = new Map();
|
authors.set(name, {
|
||||||
for (let line of lines) {
|
from: new Date(date),
|
||||||
let [date, name] = line.split("|");
|
to: new Date(date),
|
||||||
|
})
|
||||||
let author = authors.get(name);
|
}
|
||||||
if (author) {
|
}
|
||||||
author.to = new Date(date)
|
return authors;
|
||||||
} else {
|
|
||||||
authors.set(name, {
|
|
||||||
from: new Date(date),
|
|
||||||
to: new Date(date),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return authors;
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(ex);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateCopyright(file) {
|
async function generateCopyright(file) {
|
||||||
let authors = await git_retrieveAuthors(file)
|
let authors = await git_retrieveAuthors(file)
|
||||||
let lines = [];
|
let lines = [];
|
||||||
for (let entry of authors) {
|
for (let entry of authors) {
|
||||||
let from = entry[1].from.getUTCFullYear();
|
let from = entry[1].from.getUTCFullYear();
|
||||||
let to = entry[1].to.getUTCFullYear();
|
let to = entry[1].to.getUTCFullYear();
|
||||||
lines.push(`Copyright (C) ${from != to ? `${from}-${to}` : to} ${entry[0]}`);
|
lines.push(`Copyright (C) ${from != to ? `${from}-${to}` : to} ${entry[0]}`);
|
||||||
}
|
}
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeHeader(file, copyright) {
|
function makeHeader(file, copyright) {
|
||||||
let file_name = PATH.basename(file).toLocaleLowerCase();
|
let file_name = PATH.basename(file).toLocaleLowerCase();
|
||||||
let file_exts = file_name.substring(file_name.indexOf("."));
|
let file_exts = file_name.substring(file_name.indexOf("."));
|
||||||
|
|
||||||
let styles = {
|
let styles = {
|
||||||
"#": {
|
"#": {
|
||||||
files: [
|
files: [
|
||||||
"cmakelists.txt"
|
"cmakelists.txt"
|
||||||
], exts: [
|
], exts: [
|
||||||
".clang-tidy",
|
".clang-tidy",
|
||||||
".clang-format",
|
".clang-format",
|
||||||
".cmake",
|
".cmake",
|
||||||
".editorconfig",
|
".editorconfig",
|
||||||
".gitignore",
|
".gitignore",
|
||||||
".gitmodules",
|
".gitmodules",
|
||||||
".yml",
|
".yml",
|
||||||
],
|
],
|
||||||
prepend: [
|
prepend: [
|
||||||
`# ${SECTION_START}`,
|
`# ${SECTION_START}`,
|
||||||
],
|
],
|
||||||
append: [
|
append: [
|
||||||
`# ${SECTION_END}`,
|
`# ${SECTION_END}`,
|
||||||
],
|
],
|
||||||
prefix: "# ",
|
prefix: "# ",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
},
|
},
|
||||||
";": {
|
";": {
|
||||||
files: [
|
files: [
|
||||||
""
|
""
|
||||||
], exts: [
|
], exts: [
|
||||||
".iss",
|
".iss",
|
||||||
".iss.in",
|
".iss.in",
|
||||||
],
|
],
|
||||||
prepend: [
|
prepend: [
|
||||||
`; ${SECTION_START}`,
|
`; ${SECTION_START}`,
|
||||||
],
|
],
|
||||||
append: [
|
append: [
|
||||||
`; ${SECTION_END}`,
|
`; ${SECTION_END}`,
|
||||||
],
|
],
|
||||||
prefix: "; ",
|
prefix: "; ",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
},
|
},
|
||||||
"//": {
|
"//": {
|
||||||
files: [
|
files: [
|
||||||
], exts: [
|
], exts: [
|
||||||
".c",
|
".c",
|
||||||
".c.in",
|
".c.in",
|
||||||
".cpp",
|
".cpp",
|
||||||
".cpp.in",
|
".cpp.in",
|
||||||
".h",
|
".h",
|
||||||
".h.in",
|
".h.in",
|
||||||
".hpp",
|
".hpp",
|
||||||
".hpp.in",
|
".hpp.in",
|
||||||
".js",
|
".js",
|
||||||
".rc",
|
".rc",
|
||||||
".rc.in",
|
".rc.in",
|
||||||
".effect"
|
".effect"
|
||||||
],
|
],
|
||||||
prepend: [
|
prepend: [
|
||||||
`// ${SECTION_START}`,
|
`// ${SECTION_START}`,
|
||||||
],
|
],
|
||||||
append: [
|
append: [
|
||||||
`// ${SECTION_END}`,
|
`// ${SECTION_END}`,
|
||||||
],
|
],
|
||||||
prefix: "// ",
|
prefix: "// ",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
},
|
},
|
||||||
"<!---->": {
|
"<!---->": {
|
||||||
files: [
|
files: [
|
||||||
], exts: [
|
], exts: [
|
||||||
".htm",
|
".htm",
|
||||||
".htm.in",
|
".htm.in",
|
||||||
".html",
|
".html",
|
||||||
".html.in",
|
".html.in",
|
||||||
".xml",
|
".xml",
|
||||||
".xml.in",
|
".xml.in",
|
||||||
".plist",
|
".plist",
|
||||||
".plist.in",
|
".plist.in",
|
||||||
".pkgproj",
|
".pkgproj",
|
||||||
".pkgproj.in",
|
".pkgproj.in",
|
||||||
],
|
],
|
||||||
prepend: [
|
prepend: [
|
||||||
`<!-- ${SECTION_START} -->`,
|
`<!-- ${SECTION_START} -->`,
|
||||||
],
|
],
|
||||||
append: [
|
append: [
|
||||||
`<!-- ${SECTION_END} -->`,
|
`<!-- ${SECTION_END} -->`,
|
||||||
],
|
],
|
||||||
prefix: "<!-- ",
|
prefix: "<!-- ",
|
||||||
suffix: " -->",
|
suffix: " -->",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let key in styles) {
|
for (let key in styles) {
|
||||||
let style = [key, styles[key]];
|
let style = [key, styles[key]];
|
||||||
if (style[1].files.includes(file_name)
|
if (style[1].files.includes(file_name)
|
||||||
|| style[1].files.includes(file)
|
|| style[1].files.includes(file)
|
||||||
|| style[1].exts.includes(file_exts)) {
|
|| style[1].exts.includes(file_exts)) {
|
||||||
let header = [];
|
let header = [];
|
||||||
header.push(...style[1].prepend);
|
header.push(...style[1].prepend);
|
||||||
for (let line of copyright) {
|
for (let line of copyright) {
|
||||||
header.push(`${style[1].prefix}${line}${style[1].suffix}`);
|
header.push(`${style[1].prefix}${line}${style[1].suffix}`);
|
||||||
}
|
}
|
||||||
header.push(...style[1].append);
|
header.push(...style[1].append);
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Unrecognized file format.")
|
throw new Error("Unrecognized file format.")
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addCopyright(file) {
|
async function updateFile(file) {
|
||||||
try {
|
await workRL.run(async () => {
|
||||||
if (abortAllWork) {
|
try {
|
||||||
return;
|
if (abortAllWork) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Async/Promises
|
// Copyright information.
|
||||||
// Copyright information.
|
let copyright = await generateCopyright(file);
|
||||||
let copyright = await generateCopyright(file);
|
let header = undefined;
|
||||||
let header = undefined;
|
try {
|
||||||
try {
|
header = makeHeader(file, copyright);
|
||||||
header = makeHeader(file, copyright);
|
} catch (ex) {
|
||||||
} catch (ex) {
|
console.log(`Skipping file '${file}'...`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`Updating file '${file}'...`);
|
console.log(`Updating file '${file}'...`);
|
||||||
|
|
||||||
// File contents.
|
// File contents.
|
||||||
let content = await FSPROMISES.readFile(file);
|
let content = await FSPROMISES.readFile(file);
|
||||||
let eol = (content.indexOf("\r\n") != -1 ? OS.EOL : "\n");
|
let eol = (content.indexOf("\r\n") != -1 ? OS.EOL : "\n");
|
||||||
let insert = Buffer.from(header.join(eol) + eol);
|
let insert = Buffer.from(header.join(eol) + eol);
|
||||||
|
|
||||||
// Find the starting point.
|
// Find the starting point.
|
||||||
let startHeader = content.indexOf(SECTION_START);
|
let startHeader = content.indexOf(SECTION_START);
|
||||||
startHeader = content.lastIndexOf(eol, startHeader);
|
startHeader = content.lastIndexOf(eol, startHeader);
|
||||||
startHeader += Buffer.from(eol).byteLength;
|
startHeader += Buffer.from(eol).byteLength;
|
||||||
|
|
||||||
// Find the ending point.
|
// Find the ending point.
|
||||||
let endHeader = content.indexOf(SECTION_END);
|
let endHeader = content.indexOf(SECTION_END);
|
||||||
endHeader = content.indexOf(eol, endHeader);
|
endHeader = content.indexOf(eol, endHeader);
|
||||||
endHeader += Buffer.from(eol).byteLength;
|
endHeader += Buffer.from(eol).byteLength;
|
||||||
|
|
||||||
if (abortAllWork) {
|
if (abortAllWork) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fd = await FSPROMISES.open(file, "w");
|
let fd = await FSPROMISES.open(file, "w");
|
||||||
let fp = [];
|
let fp = [];
|
||||||
if ((startHeader >= 0) && (endHeader >= 0)) {
|
if ((startHeader >= 0) && (endHeader >= 0)) {
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
if (startHeader > 0) {
|
if (startHeader > 0) {
|
||||||
fd.write(content, 0, startHeader, 0);
|
fd.write(content, 0, startHeader, 0);
|
||||||
pos += startHeader;
|
pos += startHeader;
|
||||||
}
|
}
|
||||||
fd.write(insert, 0, undefined, pos);
|
fd.write(insert, 0, undefined, pos);
|
||||||
pos += insert.byteLength;
|
pos += insert.byteLength;
|
||||||
fd.write(content, endHeader, undefined, pos);
|
fd.write(content, endHeader, undefined, pos);
|
||||||
} else {
|
} else {
|
||||||
fd.write(insert, 0, undefined, 0);
|
fd.write(insert, 0, undefined, 0);
|
||||||
fd.write(content, 0, undefined, insert.byteLength);
|
fd.write(content, 0, undefined, insert.byteLength);
|
||||||
}
|
}
|
||||||
await fd.close();
|
await fd.close();
|
||||||
|
} catch (ex) {
|
||||||
/* Sync variant (slow!)
|
console.error(`Error processing '${file}'!: ${ex}`);
|
||||||
let content = FS.readFileSync(file);
|
abortAllWork = true;
|
||||||
let eol = (content.indexOf("\r\n") != -1 ? OS.EOL : "\n");
|
PROCESS.exitCode = 1;
|
||||||
|
return;
|
||||||
let copyright = await generateCopyright(file);
|
}
|
||||||
let header = makeHeader(file, copyright);
|
});
|
||||||
let insert = Buffer.from(header.join(eol) + eol);
|
|
||||||
|
|
||||||
let startHeader = content.indexOf(header[0]);
|
|
||||||
let endHeader = content.indexOf(header[header.length - 1], startHeader + 1);
|
|
||||||
endHeader += header[header.length - 1].length + eol.length;
|
|
||||||
|
|
||||||
let fd = FS.openSync(file, "w+");
|
|
||||||
if ((startHeader >= 0) && (endHeader >= 0)) {
|
|
||||||
let pos = 0;
|
|
||||||
if (startHeader > 0) {
|
|
||||||
FS.writeSync(fd, content, 0, startHeader, 0);
|
|
||||||
pos += startHeader;
|
|
||||||
}
|
|
||||||
FS.writeSync(fd, insert, 0, undefined, pos);
|
|
||||||
pos += insert.byteLength;
|
|
||||||
FS.writeSync(fd, content, endHeader, undefined, pos);
|
|
||||||
} else {
|
|
||||||
FS.writeSync(fd, insert, 0, undefined, 0);
|
|
||||||
FS.writeSync(fd, content, 0, undefined, insert.byteLength);
|
|
||||||
}
|
|
||||||
FS.close(fd, (err) => {
|
|
||||||
if (err)
|
|
||||||
throw err;
|
|
||||||
})*/
|
|
||||||
} catch (ex) {
|
|
||||||
console.error(`Error processing '${file}'!: ${ex}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addCopyrights(path) {
|
async function scanPath(path) {
|
||||||
if (abortAllWork) {
|
// Abort here if the user aborted the process, or if the path is ignored.
|
||||||
return;
|
if (abortAllWork) {
|
||||||
}
|
return;
|
||||||
if (await isIgnored(path)) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
|
||||||
let files = await FSPROMISES.readdir(path, { "withFileTypes": true });
|
await workRL.run(async () => {
|
||||||
for (let file of files) {
|
let files = await FSPROMISES.readdir(path, { "withFileTypes": true });
|
||||||
if (abortAllWork) {
|
for (let file of files) {
|
||||||
break;
|
if (abortAllWork) {
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
let fullname = PATH.join(path, file.name);
|
let fullname = PATH.join(path, file.name);
|
||||||
if (await isIgnored(fullname)) {
|
if (await isIgnored(fullname)) {
|
||||||
console.log(`Ignoring path '${fullname}'...`);
|
console.log(`Ignoring path '${fullname}'...`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
//console.log(`Scanning path '${fullname}'...`);
|
console.log(`Scanning path '${fullname}'...`);
|
||||||
promises.push(addCopyrights(fullname));
|
promises.push(scanPath(fullname));
|
||||||
} else {
|
} else {
|
||||||
promises.push(addCopyright(fullname));
|
promises.push(updateFile(fullname));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
PROCESS.on("SIGINT", (ev) => {
|
PROCESS.on("SIGINT", () => {
|
||||||
abortAllWork = true;
|
abortAllWork = true;
|
||||||
console.log("Sanely aborting all pending work...");
|
PROCESS.exitCode = 1;
|
||||||
})
|
console.log("Sanely aborting all pending work...");
|
||||||
|
})
|
||||||
|
|
||||||
let path = PATH.resolve(PROCESS.argv[2]);
|
let path = PATH.resolve(PROCESS.argv[2]);
|
||||||
|
|
||||||
{ // Bootstrap to actually be in the directory where '.git' is.
|
{ // Bootstrap to actually be in the directory where '.git' is.
|
||||||
let is_git_directory = false;
|
let is_git_directory = false;
|
||||||
while (!is_git_directory) {
|
while (!is_git_directory) {
|
||||||
if (abortAllWork) {
|
if (abortAllWork) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = await FSPROMISES.readdir(PROCESS.cwd());
|
let entries = await FSPROMISES.readdir(PROCESS.cwd());
|
||||||
if (entries.includes(".git")) {
|
if (entries.includes(".git")) {
|
||||||
console.log(`Found .git at '${process.cwd()}'.`);
|
console.log(`Found .git at '${process.cwd()}'.`);
|
||||||
is_git_directory = true;
|
is_git_directory = true;
|
||||||
} else {
|
} else {
|
||||||
PROCESS.chdir(PATH.resolve(PATH.join(PROCESS.cwd(), "..")));
|
PROCESS.chdir(PATH.resolve(PATH.join(PROCESS.cwd(), "..")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path = PATH.normalize(PATH.relative(process.cwd(), path));
|
path = PATH.normalize(PATH.relative(process.cwd(), path));
|
||||||
}
|
}
|
||||||
|
|
||||||
let pathStat = await FSPROMISES.stat(path);
|
if (!await isIgnored(path)) {
|
||||||
if (pathStat.isDirectory()) {
|
if ((await FSPROMISES.stat(path)).isDirectory()) {
|
||||||
await addCopyrights(path);
|
console.log(`Scanning path '${path}'...`);
|
||||||
} else {
|
await scanPath(path);
|
||||||
await addCopyright(path);
|
} else {
|
||||||
}
|
await updateFile(path);
|
||||||
console.log("Done");
|
}
|
||||||
|
} else {
|
||||||
|
console.log(`Ignoring path '${path}'...`);
|
||||||
|
}
|
||||||
|
console.log("Done");
|
||||||
})();
|
})();
|
||||||
|
|
Loading…
Reference in a new issue