Add io cycle detection with clircle

This commit is contained in:
Niklas Mohrin 2020-11-08 22:23:43 +01:00 committed by David Peter
parent 6d75540d4e
commit 31793cfa62
4 changed files with 63 additions and 10 deletions

44
Cargo.lock generated
View File

@ -99,6 +99,7 @@ dependencies = [
"assert_cmd",
"atty",
"clap",
"clircle",
"console",
"content_inspector",
"dirs",
@ -244,6 +245,17 @@ dependencies = [
"vec_map",
]
[[package]]
name = "clircle"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c9ae10f655554a2dd1ed8ad4e36203f5d7ceae3dc4aecdb8b1f2391bcd1e43"
dependencies = [
"nix",
"serde",
"winapi",
]
[[package]]
name = "console"
version = "0.13.0"
@ -492,9 +504,9 @@ dependencies = [
[[package]]
name = "git2"
version = "0.13.12"
version = "0.13.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca6f1a0238d7f8f8fd5ee642f4ebac4dbc03e03d1f78fbe7a3ede35dcf7e2224"
checksum = "1e094214efbc7fdbbdee952147e493b00e99a4e52817492277e98967ae918165"
dependencies = [
"bitflags",
"libc",
@ -511,9 +523,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "globset"
version = "0.4.6"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120"
dependencies = [
"aho-corasick",
"bstr",
@ -587,15 +599,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.78"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa7087f49d294270db4e1928fc110c976cd4b9e5a16348e0a1df09afa99e6c98"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "libgit2-sys"
version = "0.12.14+1.1.0"
version = "0.12.13+1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f25af58e6495f7caf2919d08f212de550cfa3ed2f5e744988938ea292b9f549"
checksum = "069eea34f76ec15f2822ccf78fe0cdb8c9016764d0a12865278585a74dbdeae5"
dependencies = [
"cc",
"libc",
@ -667,6 +679,18 @@ dependencies = [
"autocfg",
]
[[package]]
name = "nix"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85db2feff6bf70ebc3a4793191517d5f0331100a2f10f9bf93b5e5214f32b7b7"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
]
[[package]]
name = "normalize-line-endings"
version = "0.3.0"
@ -1011,9 +1035,9 @@ dependencies = [
[[package]]
name = "serde_yaml"
version = "0.8.14"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7"
checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5"
dependencies = [
"dtoa",
"linked-hash-map",

View File

@ -51,6 +51,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
semver = "0.11"
path_abs = { version = "0.5", default-features = false }
clircle = "0.1.3"
[dependencies.git2]
version = "0.13"

View File

@ -13,6 +13,7 @@ use crate::output::OutputType;
#[cfg(feature = "paging")]
use crate::paging::PagingMode;
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
use std::convert::TryFrom;
pub struct Controller<'a> {
config: &'a Config<'a>,
@ -66,6 +67,14 @@ impl<'b> Controller<'b> {
}
let attached_to_pager = output_type.is_pager();
let rw_cycle_detected = !attached_to_pager && {
let identifiers: Vec<_> = inputs
.iter()
.flat_map(clircle::Identifier::try_from)
.collect();
clircle::stdout_among_inputs(&identifiers)
};
let writer = output_type.handle()?;
let mut no_errors: bool = true;
@ -78,6 +87,11 @@ impl<'b> Controller<'b> {
}
};
if rw_cycle_detected {
print_error(&"The output file is also an input!".into(), writer);
return Ok(false);
}
for (index, input) in inputs.into_iter().enumerate() {
match input.open(io::stdin().lock()) {
Err(error) => {

View File

@ -1,6 +1,8 @@
use std::convert::TryFrom;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::io::{self, BufRead, BufReader, Read};
use std::path::Path;
use content_inspector::{self, ContentType};
@ -192,6 +194,18 @@ impl<'a> Input<'a> {
}
}
impl TryFrom<&'_ Input<'_>> for clircle::Identifier {
type Error = ();
fn try_from(input: &Input) -> std::result::Result<clircle::Identifier, ()> {
match input.kind {
InputKind::OrdinaryFile(ref path) => Self::try_from(Path::new(path)).map_err(|_| ()),
InputKind::StdIn => Self::try_from(clircle::Stdio::Stdin).map_err(|_| ()),
InputKind::CustomReader(_) => Err(()),
}
}
}
pub(crate) struct InputReader<'a> {
inner: Box<dyn BufRead + 'a>,
pub(crate) first_line: Vec<u8>,