|
@@ -1,3 +1,22 @@
|
|
|
+/*
|
|
|
+ * Copyright (C) 2024 Puter Technologies Inc.
|
|
|
+ *
|
|
|
+ * This file is part of Puter.
|
|
|
+ *
|
|
|
+ * Puter is free software: you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU Affero General Public License as published
|
|
|
+ * by the Free Software Foundation, either version 3 of the License, or
|
|
|
+ * (at your option) any later version.
|
|
|
+ *
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ * GNU Affero General Public License for more details.
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU Affero General Public License
|
|
|
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
+ */
|
|
|
+
|
|
|
const levenshtein = require('js-levenshtein');
|
|
|
const DiffMatchPatch = require('diff-match-patch');
|
|
|
const dmp = new DiffMatchPatch();
|
|
@@ -307,6 +326,153 @@ const cmd_check_fn = async () => {
|
|
|
t.printTable();
|
|
|
};
|
|
|
|
|
|
+const cmd_sync_fn = async () => {
|
|
|
+ const comment_parser = CommentParser();
|
|
|
+ const desired_header = fs.readFileSync(
|
|
|
+ path_.join(__dirname, '../../doc/license_header.txt'),
|
|
|
+ 'utf-8',
|
|
|
+ );
|
|
|
+ const license_checker = LicenseChecker({
|
|
|
+ comment_parser,
|
|
|
+ desired_header,
|
|
|
+ });
|
|
|
+
|
|
|
+ const counts = {
|
|
|
+ ok: 0,
|
|
|
+ missing: 0,
|
|
|
+ conflict: 0,
|
|
|
+ error: 0,
|
|
|
+ unsupported: 0,
|
|
|
+ };
|
|
|
+
|
|
|
+ const walk_iterator = walk({
|
|
|
+ excludes: EXCLUDE_LISTS.NOT_SOURCE,
|
|
|
+ }, '.');
|
|
|
+ for await ( const value of walk_iterator ) {
|
|
|
+ if ( value.is_dir ) continue;
|
|
|
+
|
|
|
+ process.stdout.write(value.path + ' ... ');
|
|
|
+
|
|
|
+ if ( ! license_checker.supports({ filename: value.name }) ) {
|
|
|
+ process.stdout.write(`\x1B[37;1mUNSUPPORTED\x1B[0m\n`);
|
|
|
+ counts.unsupported++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ const source = fs.readFileSync(value.path, 'utf-8');
|
|
|
+ const diff_info = await license_checker.compare({
|
|
|
+ filename: value.name,
|
|
|
+ source,
|
|
|
+ })
|
|
|
+ if ( ! diff_info ) {
|
|
|
+ counts.error++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if ( ! diff_info.has_header ) {
|
|
|
+ if ( false ) fs.writeFileSync(
|
|
|
+ value.path,
|
|
|
+ comment_parser.output_comment({
|
|
|
+ style: 'block',
|
|
|
+ filename: value.name,
|
|
|
+ text: desired_header,
|
|
|
+ }) +
|
|
|
+ '\n' +
|
|
|
+ source
|
|
|
+ );
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if ( diff_info ) {
|
|
|
+ if ( diff_info.distance !== 0 ) {
|
|
|
+ counts.conflict++;
|
|
|
+ process.stdout.write(`\x1B[31;1mCONFLICT\x1B[0m\n`);
|
|
|
+ } else {
|
|
|
+ counts.ok++;
|
|
|
+ process.stdout.write(`\x1B[32;1mOK\x1B[0m\n`);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.log('NO COMMENT');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const { Table } = require('console-table-printer');
|
|
|
+ const t = new Table({
|
|
|
+ columns: [
|
|
|
+ {
|
|
|
+ title: 'License Header',
|
|
|
+ name: 'situation', alignment: 'left', color: 'white_bold' },
|
|
|
+ {
|
|
|
+ title: 'Number of Files',
|
|
|
+ name: 'count', alignment: 'right' },
|
|
|
+ ],
|
|
|
+ colorMap: {
|
|
|
+ green: '\x1B[32;1m',
|
|
|
+ yellow: '\x1B[33;1m',
|
|
|
+ red: '\x1B[31;1m',
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log('');
|
|
|
+
|
|
|
+ if ( counts.error > 0 ) {
|
|
|
+ console.log(`\x1B[31;1mTHERE WERE SOME ERRORS!\x1B[0m`);
|
|
|
+ console.log('check the log above for the stack trace');
|
|
|
+ console.log('');
|
|
|
+ t.addRow({ situation: 'error', count: counts.error },
|
|
|
+ { color: 'red' });
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(dedent(`
|
|
|
+ \x1B[31;1mAny text below is mostly lies!\x1B[0m
|
|
|
+ This tool is still being developed and most of what's
|
|
|
+ described is "the plan" rather than a thing that will
|
|
|
+ actually happen.
|
|
|
+ \x1B[31;1m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\x1B[0m
|
|
|
+ `));
|
|
|
+
|
|
|
+ if ( counts.conflict ) {
|
|
|
+ console.log(dedent(`
|
|
|
+ \x1B[37;1mIt looks like you have some conflicts!\x1B[0m
|
|
|
+ Run the following command to update license headers:
|
|
|
+
|
|
|
+ \x1B[36;1maddlicense sync\x1B[0m
|
|
|
+
|
|
|
+ This will begin an interactive license update.
|
|
|
+ Any time the license doesn't quite match you will
|
|
|
+ be given the option to replace it or skip the file.
|
|
|
+ \x1B[90mSee \`addlicense help sync\` for other options.\x1B[0m
|
|
|
+
|
|
|
+ You will also be able to choose
|
|
|
+ "remember for headers matching this one"
|
|
|
+ if you know the same issue will come up later.
|
|
|
+ `));
|
|
|
+ } else if ( counts.missing ) {
|
|
|
+ console.log(dedent(`
|
|
|
+ \x1B[37;1mSome missing license headers!\x1B[0m
|
|
|
+ Run the following command to add the missing license headers:
|
|
|
+
|
|
|
+ \x1B[36;1maddlicense sync\x1B[0m
|
|
|
+ `));
|
|
|
+ } else {
|
|
|
+ console.log(dedent(`
|
|
|
+ \x1B[37;1mNo action to perform!\x1B[0m
|
|
|
+ Run the following command to do absolutely nothing:
|
|
|
+
|
|
|
+ \x1B[36;1maddlicense sync\x1B[0m
|
|
|
+ `));
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('');
|
|
|
+
|
|
|
+ t.addRow({ situation: 'ok', count: counts.ok },
|
|
|
+ { color: 'green' });
|
|
|
+ t.addRow({ situation: 'missing', count: counts.missing },
|
|
|
+ { color: 'yellow' });
|
|
|
+ t.addRow({ situation: 'conflict', count: counts.conflict },
|
|
|
+ { color: 'red' });
|
|
|
+ t.addRow({ situation: 'unsupported', count: counts.unsupported });
|
|
|
+ t.printTable();
|
|
|
+};
|
|
|
+
|
|
|
const main = async () => {
|
|
|
const { program } = require('commander');
|
|
|
const helptext = dedent(`
|
|
@@ -343,9 +509,7 @@ const main = async () => {
|
|
|
.description('synchronize files with license header rules')
|
|
|
.option('-n, --non-interactive', 'disable prompting')
|
|
|
.action(() => {
|
|
|
- console.log('called sync');
|
|
|
- console.log(program.opts());
|
|
|
- console.log(cmd_sync.opts());
|
|
|
+ run_command({ cmd: cmd_sync, cmd_fn: cmd_sync_fn })
|
|
|
})
|
|
|
program.parse(process.argv);
|
|
|
|