1 | #!/usr/bin/env node
|
2 |
|
3 | "use strict";
|
4 |
|
5 | const fs = require("fs");
|
6 | const path = require("path");
|
7 | const yargs = require("yargs");
|
8 | const glob = require("../lib/glob");
|
9 | const normalize = require("../lib/normalize");
|
10 | const metalint = require("../lib/index");
|
11 | const SEVERITY = require("../lib/severity");
|
12 |
|
13 | const argv = yargs.options({
|
14 | "c": {
|
15 | "alias": "config",
|
16 | "default": ".metalint/metalint.json",
|
17 | "requiresArg": true,
|
18 | "type": "string"
|
19 | },
|
20 | "f": {
|
21 | "alias": "formatter",
|
22 | "requiresArg": true,
|
23 | "type": "string"
|
24 | },
|
25 | "l": {
|
26 | "alias": "level",
|
27 | "requiresArg": true,
|
28 | "type": "string"
|
29 | },
|
30 | "o": {
|
31 | "alias": "output",
|
32 | "requiresArg": true,
|
33 | "type": "string"
|
34 | },
|
35 | "p": {
|
36 | "alias": "patterns",
|
37 | "requiresArg": true,
|
38 | "type": "array"
|
39 | },
|
40 | "help": {
|
41 | "alias": "help",
|
42 | "type": "boolean"
|
43 | },
|
44 | "version": {
|
45 | "alias": "version",
|
46 | "type": "boolean"
|
47 | }
|
48 | }).help(false).version(false).parse();
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | const check = function (files, checkers, root, reporters) {
|
63 | return metalint(files, checkers, root).then(function (results) {
|
64 | let severity = null;
|
65 | for (const [file, notices] of Object.entries(results)) {
|
66 |
|
67 | if (null !== notices) {
|
68 | for (const notice of notices) {
|
69 | if (null === severity || severity > notice.severity) {
|
70 | severity = notice.severity;
|
71 | }
|
72 | }
|
73 | }
|
74 |
|
75 |
|
76 | for (const reporter of reporters) {
|
77 | reporter.notify(file, notices);
|
78 | }
|
79 | }
|
80 |
|
81 | const sweepers = reporters.map(function (reporter) {
|
82 | reporter.finalize(severity);
|
83 |
|
84 | return new Promise(function (resolve) {
|
85 | reporter.writer.write("", resolve);
|
86 | });
|
87 | });
|
88 |
|
89 | return Promise.all(sweepers).then(() => severity);
|
90 | });
|
91 | };
|
92 |
|
93 | if (argv.help) {
|
94 | process.stdout.write(fs.readFileSync(path.join(__dirname,
|
95 | "/../help/index.txt")));
|
96 | process.exit(0);
|
97 | }
|
98 | if (argv.version) {
|
99 | const manifest = JSON.parse(fs.readFileSync(path.join(__dirname,
|
100 | "/../package.json"),
|
101 | "utf-8"));
|
102 | process.stdout.write("Metalint " + manifest.version + "\n");
|
103 | process.exit(0);
|
104 | }
|
105 |
|
106 | let root = process.cwd();
|
107 |
|
108 |
|
109 | while (!fs.existsSync(path.join(root, argv.config))) {
|
110 |
|
111 | if (path.join(root, "..") === root) {
|
112 | process.stderr.write("metalint: no such config file.\n");
|
113 | process.exit(10);
|
114 | }
|
115 | root = path.join(root, "..");
|
116 | }
|
117 |
|
118 | let config = JSON.parse(fs.readFileSync(path.join(root, argv.config), "utf-8"));
|
119 | try {
|
120 | config = normalize(config, root,
|
121 | path.dirname(path.join(root, argv.config)),
|
122 | argv);
|
123 | } catch (exc) {
|
124 | process.stderr.write("metalint: " + exc.message);
|
125 | process.exit(11);
|
126 | }
|
127 |
|
128 | const files = glob.walk(argv._, config.patterns, root);
|
129 |
|
130 | check(files, config.checkers, root, config.reporters).then(function (severity) {
|
131 | let code;
|
132 | switch (severity) {
|
133 | case SEVERITY.FATAL: code = 2; break;
|
134 | case SEVERITY.ERROR: code = 1; break;
|
135 | default: code = 0;
|
136 | }
|
137 | process.exit(code);
|
138 | }).catch(function (exc) {
|
139 | process.stderr.write("metalint: " + exc.message + "\n");
|
140 | process.stderr.write(exc.stack + "\n");
|
141 | process.exit(12);
|
142 | });
|