Skip to content

Commit 6b33e31

Browse files
authored
fix: fix broken pipe error during search (#699)
Fixes #687 See Misterio77/flavours#16 and rust-lang/rust#46016 for more context.
1 parent 3f447f4 commit 6b33e31

File tree

1 file changed

+72
-35
lines changed

1 file changed

+72
-35
lines changed

src/cli/search.rs

+72-35
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::borrow::Cow;
2+
use std::io::{self, Write};
23
use std::{cmp::Ordering, path::PathBuf};
34

45
use clap::Parser;
@@ -80,6 +81,7 @@ where
8081
}
8182

8283
pub async fn execute(args: Args) -> miette::Result<()> {
84+
let stdout = io::stdout();
8385
let project = Project::load_or_else_discover(args.manifest_path.as_deref()).ok();
8486

8587
let channel_config = ChannelConfig::default();
@@ -116,20 +118,22 @@ pub async fn execute(args: Args) -> miette::Result<()> {
116118

117119
let limit = args.limit;
118120

119-
search_package_by_wildcard(package_name, &package_name_filter, repo_data, limit).await?;
121+
search_package_by_wildcard(package_name, &package_name_filter, repo_data, limit, stdout)
122+
.await?;
120123
}
121124
// If package name filter doesn't contain * (wildcard), it will search and display specific package info (if any package is found)
122125
else {
123126
let package_name = PackageName::try_from(package_name_filter).into_diagnostic()?;
124-
search_exact_package(package_name, repo_data).await?;
127+
search_exact_package(package_name, repo_data, stdout).await?;
125128
}
126129

127130
Ok(())
128131
}
129132

130-
async fn search_exact_package(
133+
async fn search_exact_package<W: Write>(
131134
package_name: PackageName,
132135
repo_data: Vec<SparseRepoData>,
136+
out: W,
133137
) -> miette::Result<()> {
134138
let package_name_search = package_name.clone();
135139
let packages = await_in_progress(
@@ -150,101 +154,126 @@ async fn search_exact_package(
150154

151155
let package = packages.last();
152156
if let Some(package) = package {
153-
print_package_info(package);
157+
if let Err(e) = print_package_info(package, out) {
158+
if e.kind() != std::io::ErrorKind::BrokenPipe {
159+
return Err(e).into_diagnostic();
160+
}
161+
}
154162
}
155163

156164
Ok(())
157165
}
158166

159-
fn print_package_info(package: &RepoDataRecord) {
160-
println!();
167+
fn print_package_info<W: Write>(package: &RepoDataRecord, mut out: W) -> io::Result<()> {
168+
writeln!(out)?;
161169

162170
let package = package.clone();
163171
let package_name = package.package_record.name.as_source();
164172
let build = &package.package_record.build;
165173
let package_info = format!("{} {}", console::style(package_name), console::style(build));
166-
println!("{}", package_info);
167-
println!("{}\n", "-".repeat(package_info.chars().count()));
174+
writeln!(out, "{}", package_info)?;
175+
writeln!(out, "{}\n", "-".repeat(package_info.chars().count()))?;
168176

169-
println!(
177+
writeln!(
178+
out,
170179
"{:19} {:19}",
171180
console::style("Name"),
172181
console::style(package_name)
173-
);
182+
)?;
174183

175-
println!(
184+
writeln!(
185+
out,
176186
"{:19} {:19}",
177187
console::style("Version"),
178188
console::style(package.package_record.version)
179-
);
189+
)?;
180190

181-
println!(
191+
writeln!(
192+
out,
182193
"{:19} {:19}",
183194
console::style("Build"),
184195
console::style(build)
185-
);
196+
)?;
186197

187198
let size = match package.package_record.size {
188199
Some(size) => size.to_string(),
189200
None => String::from("Not found."),
190201
};
191-
println!("{:19} {:19}", console::style("Size"), console::style(size));
202+
writeln!(
203+
out,
204+
"{:19} {:19}",
205+
console::style("Size"),
206+
console::style(size)
207+
)?;
192208

193209
let license = match package.package_record.license {
194210
Some(license) => license,
195211
None => String::from("Not found."),
196212
};
197-
println!(
213+
writeln!(
214+
out,
198215
"{:19} {:19}",
199216
console::style("License"),
200217
console::style(license)
201-
);
218+
)?;
202219

203-
println!(
220+
writeln!(
221+
out,
204222
"{:19} {:19}",
205223
console::style("Subdir"),
206224
console::style(package.package_record.subdir)
207-
);
225+
)?;
208226

209-
println!(
227+
writeln!(
228+
out,
210229
"{:19} {:19}",
211230
console::style("File Name"),
212231
console::style(package.file_name)
213-
);
232+
)?;
214233

215-
println!(
234+
writeln!(
235+
out,
216236
"{:19} {:19}",
217237
console::style("URL"),
218238
console::style(package.url)
219-
);
239+
)?;
220240

221241
let md5 = match package.package_record.md5 {
222242
Some(md5) => format!("{:x}", md5),
223243
None => "Not available".to_string(),
224244
};
225-
println!("{:19} {:19}", console::style("MD5"), console::style(md5));
245+
writeln!(
246+
out,
247+
"{:19} {:19}",
248+
console::style("MD5"),
249+
console::style(md5)
250+
)?;
226251

227252
let sha256 = match package.package_record.sha256 {
228253
Some(sha256) => format!("{:x}", sha256),
229254
None => "Not available".to_string(),
230255
};
231-
println!(
256+
writeln!(
257+
out,
232258
"{:19} {:19}",
233259
console::style("SHA256"),
234260
console::style(sha256),
235-
);
261+
)?;
236262

237-
println!("\nDependencies:");
263+
writeln!(out, "\nDependencies:")?;
238264
for dependency in package.package_record.depends {
239-
println!(" - {}", dependency);
265+
writeln!(out, " - {}", dependency)?;
240266
}
267+
268+
Ok(())
241269
}
242270

243-
async fn search_package_by_wildcard(
271+
async fn search_package_by_wildcard<W: Write>(
244272
package_name: PackageName,
245273
package_name_filter: &str,
246274
repo_data: Vec<SparseRepoData>,
247275
limit: usize,
276+
out: W,
248277
) -> miette::Result<()> {
249278
let wildcard_pattern = Regex::new(&format!("^{}$", &package_name_filter.replace('*', ".*")))
250279
.expect("Expect only characters and/or * (wildcard).");
@@ -301,18 +330,23 @@ async fn search_package_by_wildcard(
301330
let _ = packages.split_off(limit);
302331
}
303332

304-
print_matching_packages(packages);
333+
if let Err(e) = print_matching_packages(packages, out) {
334+
if e.kind() != std::io::ErrorKind::BrokenPipe {
335+
return Err(e).into_diagnostic();
336+
}
337+
}
305338

306339
Ok(())
307340
}
308341

309-
fn print_matching_packages(packages: Vec<RepoDataRecord>) {
310-
println!(
342+
fn print_matching_packages<W: Write>(packages: Vec<RepoDataRecord>, mut out: W) -> io::Result<()> {
343+
writeln!(
344+
out,
311345
"{:40} {:19} {:19}",
312346
console::style("Package").bold(),
313347
console::style("Version").bold(),
314348
console::style("Channel").bold(),
315-
);
349+
)?;
316350

317351
for package in packages {
318352
// TODO: change channel fetch logic to be more robust
@@ -324,11 +358,14 @@ fn print_matching_packages(packages: Vec<RepoDataRecord>) {
324358
let package_name = package.package_record.name;
325359
let version = package.package_record.version.as_str();
326360

327-
println!(
361+
writeln!(
362+
out,
328363
"{:40} {:19} {:19}",
329364
console::style(package_name.as_source()).cyan().bright(),
330365
console::style(version),
331366
console::style(channel_name),
332-
);
367+
)?;
333368
}
369+
370+
Ok(())
334371
}

0 commit comments

Comments
 (0)