forked from sourcemeta/jsonschema
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommand_fmt.cc
More file actions
117 lines (103 loc) · 4.07 KB
/
command_fmt.cc
File metadata and controls
117 lines (103 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <sourcemeta/core/json.h>
#include <sourcemeta/core/jsonschema.h>
#include <fstream> // std::ofstream
#include <iostream> // std::cerr, std::cout
#include <sstream> // std::ostringstream
#include <utility> // std::move
#include <vector> // std::vector
#include "command.h"
#include "error.h"
#include "input.h"
#include "logger.h"
#include "resolver.h"
#include "utils.h"
auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
-> void {
const bool output_json{options.contains("json")};
bool result{true};
std::vector<std::string> failed_files;
const auto indentation{parse_indentation(options)};
for (const auto &entry : for_each_json(options)) {
const auto &path{entry.local_path_or_throw("fmt")};
if (entry.yaml) {
throw YAMLInputError{"This command does not support YAML input files yet",
path};
}
if (options.contains("check")) {
LOG_VERBOSE(options) << "Checking: " << path.string() << "\n";
} else {
LOG_VERBOSE(options) << "Formatting: " << path.string() << "\n";
}
try {
const auto configuration_path{find_configuration(path)};
const auto &configuration{
read_configuration(options, configuration_path, path)};
const auto dialect{default_dialect(options, configuration)};
const auto &custom_resolver{
resolver(options, options.contains("http"), dialect, configuration)};
std::ostringstream expected;
if (options.contains("keep-ordering")) {
sourcemeta::core::prettify(entry.second, expected, indentation);
} else {
auto copy = entry.second;
sourcemeta::core::format(copy, sourcemeta::core::schema_walker,
custom_resolver, dialect);
sourcemeta::core::prettify(copy, expected, indentation);
}
expected << "\n";
std::ifstream current_stream{path};
std::ostringstream current;
current << current_stream.rdbuf();
if (options.contains("check")) {
if (current.str() == expected.str()) {
LOG_VERBOSE(options) << "ok: " << path.string() << "\n";
} else if (output_json) {
failed_files.push_back(path.string());
result = false;
} else {
std::cerr << "fail: " << path.string() << "\n";
result = false;
}
} else {
if (current.str() != expected.str()) {
std::ofstream output{path};
output << expected.str();
}
}
} catch (const sourcemeta::core::SchemaRelativeMetaschemaResolutionError
&error) {
throw FileError<
sourcemeta::core::SchemaRelativeMetaschemaResolutionError>(path,
error);
} catch (const sourcemeta::core::SchemaResolutionError &error) {
throw FileError<sourcemeta::core::SchemaResolutionError>(path, error);
} catch (const sourcemeta::core::SchemaUnknownBaseDialectError &) {
throw FileError<sourcemeta::core::SchemaUnknownBaseDialectError>(path);
} catch (const sourcemeta::core::SchemaError &error) {
throw FileError<sourcemeta::core::SchemaError>(path, error.what());
}
}
if (options.contains("check") && output_json) {
auto output_json_object{sourcemeta::core::JSON::make_object()};
output_json_object.assign("valid", sourcemeta::core::JSON{result});
if (!result) {
auto errors_array{sourcemeta::core::JSON::make_array()};
for (auto &file_path : failed_files) {
errors_array.push_back(sourcemeta::core::JSON{std::move(file_path)});
}
output_json_object.assign("errors", sourcemeta::core::JSON{errors_array});
}
sourcemeta::core::prettify(output_json_object, std::cout, indentation);
std::cout << "\n";
}
if (!result) {
if (!output_json) {
std::cerr << "\nRun the `fmt` command without `--check/-c` to fix the "
"formatting"
<< "\n";
}
// Report a different exit code for formatting check failures, to
// distinguish them from other errors
throw Fail{2};
}
}