cli: Handle broken pipe in `cob show`
When piping the output in for eg. `head -n 1`, the `head` utility might close down the pipe at some point, yielding a broken pipe error. We catch that and simply return if that's the case.
This commit is contained in:
parent
7616dcb793
commit
5fe3d5a7ab
|
|
@ -1,4 +1,6 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Write;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
|
@ -10,7 +12,9 @@ use radicle::identity::Identity;
|
||||||
use radicle::issue::cache::Issues;
|
use radicle::issue::cache::Issues;
|
||||||
use radicle::patch::cache::Patches;
|
use radicle::patch::cache::Patches;
|
||||||
use radicle::prelude::RepoId;
|
use radicle::prelude::RepoId;
|
||||||
|
use radicle::storage::git;
|
||||||
use radicle::storage::ReadStorage;
|
use radicle::storage::ReadStorage;
|
||||||
|
use radicle::Profile;
|
||||||
use radicle_cob::object::collaboration::list;
|
use radicle_cob::object::collaboration::list;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
|
|
@ -227,37 +231,16 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
} => {
|
} => {
|
||||||
let repo = storage.repository(repo)?;
|
let repo = storage.repository(repo)?;
|
||||||
|
|
||||||
if type_name == cob::patch::TYPENAME.clone() {
|
match show(revs, &repo, type_name, &profile) {
|
||||||
let patches = term::cob::patches(&profile, &repo)?;
|
Err(e) => {
|
||||||
for oid in revs {
|
if let Some(err) = e.downcast_ref::<io::Error>() {
|
||||||
let oid = &oid.resolve(&repo.backend)?;
|
if err.kind() == io::ErrorKind::BrokenPipe {
|
||||||
let Some(patch) = patches.get(oid)? else {
|
return Ok(());
|
||||||
anyhow::bail!(cob::store::Error::NotFound(type_name, *oid))
|
}
|
||||||
};
|
}
|
||||||
serde_json::to_writer(std::io::stdout(), &patch)?;
|
return Err(e);
|
||||||
println!()
|
|
||||||
}
|
}
|
||||||
} else if type_name == cob::issue::TYPENAME.clone() {
|
Ok(()) => {}
|
||||||
let issues = term::cob::issues(&profile, &repo)?;
|
|
||||||
for oid in revs {
|
|
||||||
let oid = &oid.resolve(&repo.backend)?;
|
|
||||||
let Some(issue) = issues.get(oid)? else {
|
|
||||||
anyhow::bail!(cob::store::Error::NotFound(type_name, *oid))
|
|
||||||
};
|
|
||||||
serde_json::to_writer(std::io::stdout(), &issue)?;
|
|
||||||
println!()
|
|
||||||
}
|
|
||||||
} else if type_name == cob::identity::TYPENAME.clone() {
|
|
||||||
for oid in revs {
|
|
||||||
let oid = &oid.resolve(&repo.backend)?;
|
|
||||||
let Some(cob) = cob::get::<Identity, _>(&repo, &type_name, oid)? else {
|
|
||||||
anyhow::bail!(cob::store::Error::NotFound(type_name, *oid))
|
|
||||||
};
|
|
||||||
serde_json::to_writer(std::io::stdout(), &cob.object)?;
|
|
||||||
println!()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
anyhow::bail!("the type name '{type_name}' is unknown");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -265,6 +248,49 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show(
|
||||||
|
revs: Vec<Rev>,
|
||||||
|
repo: &git::Repository,
|
||||||
|
type_name: cob::TypeName,
|
||||||
|
profile: &Profile,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
let mut stdout = std::io::stdout();
|
||||||
|
|
||||||
|
if type_name == cob::patch::TYPENAME.clone() {
|
||||||
|
let patches = term::cob::patches(&profile, repo)?;
|
||||||
|
for oid in revs {
|
||||||
|
let oid = &oid.resolve(&repo.backend)?;
|
||||||
|
let Some(patch) = patches.get(oid)? else {
|
||||||
|
anyhow::bail!(cob::store::Error::NotFound(type_name, *oid));
|
||||||
|
};
|
||||||
|
serde_json::to_writer(&stdout, &patch)?;
|
||||||
|
stdout.write_all(b"\n")?;
|
||||||
|
}
|
||||||
|
} else if type_name == cob::issue::TYPENAME.clone() {
|
||||||
|
let issues = term::cob::issues(&profile, repo)?;
|
||||||
|
for oid in revs {
|
||||||
|
let oid = &oid.resolve(&repo.backend)?;
|
||||||
|
let Some(issue) = issues.get(oid)? else {
|
||||||
|
anyhow::bail!(cob::store::Error::NotFound(type_name, *oid))
|
||||||
|
};
|
||||||
|
serde_json::to_writer(&stdout, &issue)?;
|
||||||
|
stdout.write_all(b"\n")?;
|
||||||
|
}
|
||||||
|
} else if type_name == cob::identity::TYPENAME.clone() {
|
||||||
|
for oid in revs {
|
||||||
|
let oid = &oid.resolve(&repo.backend)?;
|
||||||
|
let Some(cob) = cob::get::<Identity, _>(repo, &type_name, oid)? else {
|
||||||
|
anyhow::bail!(cob::store::Error::NotFound(type_name, *oid));
|
||||||
|
};
|
||||||
|
serde_json::to_writer(&stdout, &cob.object)?;
|
||||||
|
stdout.write_all(b"\n")?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
anyhow::bail!("the type name '{type_name}' is unknown");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn print_op_pretty(op: Op<Vec<u8>>) -> anyhow::Result<()> {
|
fn print_op_pretty(op: Op<Vec<u8>>) -> anyhow::Result<()> {
|
||||||
let time = DateTime::<Utc>::from(
|
let time = DateTime::<Utc>::from(
|
||||||
std::time::UNIX_EPOCH + std::time::Duration::from_secs(op.timestamp.as_secs()),
|
std::time::UNIX_EPOCH + std::time::Duration::from_secs(op.timestamp.as_secs()),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue