UNPKG

4.63 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3"use strict";
4
5const fs = require("fs");
6const path = require("path");
7const yargs = require("yargs");
8const glob = require("../lib/glob");
9const normalize = require("../lib/normalize");
10const metalint = require("../lib/index");
11const SEVERITY = require("../lib/severity");
12
13const 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 * Vérifie (en appelant des linters) une liste de fichiers.
52 *
53 * @param {Array.<string>} files La liste des fichiers.
54 * @param {Array.<object>} checkers La liste des vérifications faites sur les
55 * fichiers.
56 * @param {string} root L’adresse du répertoire où se trouve le
57 * dossier <code>.metalint/</code>.
58 * @param {object} reporters La liste des rapporteurs utilisés pour
59 * afficher les résultats.
60 * @returns {Promise.<number>} La sévérité la plus élévée des résultats.
61 */
62const 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 // Déterminer la sévérité la plus élévée des résultats.
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 // Afficher les notifications avec chaque rapporteur.
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 // Attendre que les textes soient écrits.
84 return new Promise(function (resolve) {
85 reporter.writer.write("", resolve);
86 });
87 });
88 // Attendre tous les rapporteurs.
89 return Promise.all(sweepers).then(() => severity);
90 });
91};
92
93if (argv.help) {
94 process.stdout.write(fs.readFileSync(path.join(__dirname,
95 "/../help/index.txt")));
96 process.exit(0);
97}
98if (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
106let root = process.cwd();
107// Rechercher le fichier de configuration dans le répertoire courant, puis les
108// parents.
109while (!fs.existsSync(path.join(root, argv.config))) {
110 // Si on est remonté à la racine.
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
118let config = JSON.parse(fs.readFileSync(path.join(root, argv.config), "utf-8"));
119try {
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
128const files = glob.walk(argv._, config.patterns, root);
129
130check(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});