Skip to content

Commit f20c9ae

Browse files
committed
xtask-unpublished: table output
1 parent 0bffcbc commit f20c9ae

File tree

1 file changed

+64
-37
lines changed

1 file changed

+64
-37
lines changed

crates/xtask-unpublished/src/xtask.rs

+64-37
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashSet;
2+
23
use cargo::core::registry::PackageRegistry;
34
use cargo::core::QueryKind;
45
use cargo::core::Registry;
@@ -116,51 +117,77 @@ fn unpublished(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> car
116117
std::task::Poll::Pending => registry.block_until_ready()?,
117118
}
118119
};
119-
if let Some(last) = possibilities.iter().map(|s| s.version()).max() {
120-
if last != current {
121-
results.push((
122-
name.to_string(),
123-
Some(last.to_string()),
124-
current.to_string(),
125-
));
126-
} else {
127-
log::trace!("{name} {current} is published");
128-
}
129-
} else {
130-
results.push((name.to_string(), None, current.to_string()));
131-
}
120+
let (last, published) = possibilities
121+
.iter()
122+
.map(|s| s.version())
123+
.max()
124+
.map(|last| (last.to_string(), last == current))
125+
.unwrap_or(("-".to_string(), false));
126+
127+
results.push(vec![
128+
name.to_string(),
129+
last,
130+
current.to_string(),
131+
if published { "yes" } else { "no" }.to_string(),
132+
]);
132133
}
133134
}
135+
results.sort();
134136

135-
if !results.is_empty() {
136-
results.insert(
137-
0,
138-
(
139-
"name".to_owned(),
140-
Some("published".to_owned()),
141-
"current".to_owned(),
142-
),
143-
);
144-
results.insert(
145-
1,
146-
(
147-
"====".to_owned(),
148-
Some("=========".to_owned()),
149-
"=======".to_owned(),
150-
),
151-
);
152-
}
153-
for (name, last, current) in results {
154-
if let Some(last) = last {
155-
println!("{name} {last} {current}");
156-
} else {
157-
println!("{name} - {current}");
158-
}
137+
if results.is_empty() {
138+
return Ok(());
159139
}
160140

141+
results.insert(
142+
0,
143+
vec![
144+
"name".to_owned(),
145+
"crates.io".to_owned(),
146+
"local".to_owned(),
147+
"published?".to_owned(),
148+
],
149+
);
150+
151+
output_table(results);
152+
161153
Ok(())
162154
}
163155

156+
/// Outputs a markdown table like this.
157+
///
158+
/// ```text
159+
/// | name | crates.io | local | published? |
160+
/// |------------------|-----------|--------|------------|
161+
/// | cargo | 0.70.1 | 0.72.0 | no |
162+
/// | cargo-platform | 0.1.2 | 0.1.2 | yes |
163+
/// | cargo-util | - | 0.2.4 | no |
164+
/// | crates-io | 0.36.0 | 0.36.0 | yes |
165+
/// | home | - | 0.5.6 | no |
166+
/// ```
167+
fn output_table(table: Vec<Vec<String>>) {
168+
let header = table.iter().next().unwrap();
169+
let paddings = table.iter().fold(vec![0; header.len()], |mut widths, row| {
170+
for (width, field) in widths.iter_mut().zip(row) {
171+
*width = usize::max(*width, field.len());
172+
}
173+
widths
174+
});
175+
176+
let print = |row: &[_]| {
177+
for (field, pad) in row.iter().zip(&paddings) {
178+
print!("| {field:pad$} ");
179+
}
180+
println!("|");
181+
};
182+
183+
print(header);
184+
185+
paddings.iter().for_each(|fill| print!("|-{:-<fill$}-", ""));
186+
println!("|");
187+
188+
table.iter().skip(1).for_each(|r| print(r));
189+
}
190+
164191
#[test]
165192
fn verify_cli() {
166193
cli().debug_assert();

0 commit comments

Comments
 (0)