Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.

Commit f7d687c

Browse files
committed
Merge branch 'json_out'
2 parents 6d3a8f6 + 2251332 commit f7d687c

File tree

4 files changed

+314
-20
lines changed

4 files changed

+314
-20
lines changed

README.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ Options:
107107
Do not activate the `default` feature
108108
--compact Only output the suggested version on stdout for
109109
further processing
110+
-j, --json Output a JSON-formatted description of all collected
111+
data on stdout.
110112
-s, --stable-path PATH
111113
use local path as stable/old crate
112114
-c, --current-path PATH
@@ -142,6 +144,92 @@ cargo semver | tee semver_out
142144
Make sure you do the above with access to a nightly toolchain. Check your CI provider's
143145
documentation on how to do that.
144146

147+
### JSON output
148+
149+
By passing the `-j` flag, all output on standard out is formatted as a machine-readable
150+
JSON blob. This can be useful for integration with other tools, and always generates all
151+
possible output (ignoring other output-related flags). The output format is defined as
152+
follows:
153+
154+
The top level object contains the keys `old_version`, `new_version` and `changes`. The
155+
former two hold a version number in the format `major.minor.patch`, the latter an object
156+
describing changes between the crate versions, which contains two arrays in the keys
157+
`path_changes` and `changes`.
158+
159+
The `path_changes` array contains objects describing item additions and removals, which
160+
have the following keys:
161+
162+
* `name`: The name of the item.
163+
* `def_span`: An object describing the location of the item in one of the crates.
164+
* `additions`: An array of spans that describe locations where the item has been added.
165+
* `removals`: An array of spans that describe locations where the item has been removed.
166+
167+
An example object might look like this:
168+
169+
```json
170+
{
171+
"name": "NFT_META_CGROUP",
172+
"def_span": {
173+
"file": "/path/to/libc-0.2.48/src/unix/notbsd/linux/other/mod.rs",
174+
"line_lo": 776,
175+
"line_hi": 776,
176+
"col_lo": 0,
177+
"col_hi": 40
178+
},
179+
"additions": [
180+
{
181+
"file": "/path/to/libc-0.2.48/src/lib.rs",
182+
"line_lo": 195,
183+
"line_hi": 195,
184+
"col_lo": 16,
185+
"col_hi": 23
186+
}
187+
],
188+
"removals": []
189+
}
190+
```
191+
192+
193+
The `changes` array contains objects describing all other changes, which have the
194+
following keys:
195+
196+
* `name`: The name of the item
197+
* `max_category`: the most severe change category for this item, as a string.
198+
* Possible values are `Patch`, `NonBreaking`, `TechnicallyBreaking`, and `Breaking`.
199+
* `new_span`: an object describing the location of the item in the new crate (see example).
200+
* `changes`: an array of 2-element sequences containing an error message and an optional
201+
sub-span (`null` if none is present)
202+
203+
An example object might look like this:
204+
205+
```json
206+
{
207+
"name": "<new::util::enumerate::Enumerate<T> as new::prelude::Stream>",
208+
"max_category": "TechnicallyBreaking",
209+
"new_span": {
210+
"file": "/path/to/tokio-0.1.17/src/util/enumerate.rs",
211+
"line_lo": 46,
212+
"line_hi": 63,
213+
"col_lo": 0,
214+
"col_hi": 1
215+
},
216+
"changes": [
217+
[
218+
"trait impl generalized or newly added",
219+
null
220+
]
221+
]
222+
}
223+
```
224+
225+
For reference, all objects describing spans have the same keys:
226+
227+
* `file`: A file name.
228+
* `line_lo`: The line the span starts on.
229+
* `line_hi`: The line the span ends on.
230+
* `col_lo`: The column the span starts on.
231+
* `col_hi`: The column the span ends on.
232+
145233
## Functionality
146234

147235
The guideline used to implement semver compatibility is the [API evolution

src/bin/cargo_semver.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> {
107107

108108
let explain = matches.opt_present("e");
109109
let compact = matches.opt_present("compact");
110+
let json = matches.opt_present("json");
110111

111112
// Obtain WorkInfo for the "current"
112113
let current = if let Some(name_and_version) = matches.opt_str("C") {
@@ -122,6 +123,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> {
122123
};
123124
let name = current.package.name().to_owned();
124125

126+
// TODO: JSON output here
125127
if matches.opt_present("show-public") {
126128
let (current_rlib, current_deps_output) =
127129
current.rlib_and_dep_output(config, &name, true, matches)?;
@@ -224,6 +226,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> {
224226
.env("RUST_SEMVER_CRATE_VERSION", stable_version)
225227
.env("RUST_SEMVER_VERBOSE", format!("{}", explain))
226228
.env("RUST_SEMVER_COMPACT", format!("{}", compact))
229+
.env("RUST_SEMVER_JSON", format!("{}", json))
227230
.env(
228231
"RUST_SEMVER_API_GUIDELINES",
229232
if matches.opt_present("a") {
@@ -308,6 +311,11 @@ mod cli {
308311
"compact",
309312
"Only output the suggested version on stdout for further processing",
310313
);
314+
opts.optflag(
315+
"j",
316+
"json",
317+
"Output a JSON-formatted description of all collected data on stdout.",
318+
);
311319
opts.optopt(
312320
"s",
313321
"stable-path",

src/bin/rust_semverver.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ fn main() {
4646
env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string());
4747
let compact =
4848
env::var("RUST_SEMVER_COMPACT") == Ok("true".to_string());
49+
let json =
50+
env::var("RUST_SEMVER_JSON") == Ok("true".to_string());
4951
let api_guidelines =
5052
env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string());
5153
let version = if let Ok(ver) = env::var("RUST_SEMVER_CRATE_VERSION") {
@@ -81,7 +83,11 @@ fn main() {
8183
if let [(_, old_def_id), (_, new_def_id)] = *crates.as_slice() {
8284
debug!("running semver analysis");
8385
let changes = run_analysis(tcx, old_def_id, new_def_id);
84-
changes.output(tcx.sess, &version, verbose, compact, api_guidelines);
86+
if json {
87+
changes.output_json(tcx.sess, &version);
88+
} else {
89+
changes.output(tcx.sess, &version, verbose, compact, api_guidelines);
90+
}
8591
} else {
8692
tcx.sess.err("could not find `old` and `new` crates");
8793
}

0 commit comments

Comments
 (0)