on master help sign in
do not take stdin lock when stdin is not used
92ba42arhysd
src/controller.rs+86−63
@@ -1,4 +1,4 @@
1−use std::io::{self, Write};
1+use std::io::{self, BufRead, Read, Write};
2
2
3use crate::assets::HighlightingAssets;
3use crate::assets::HighlightingAssets;
4use crate::config::{Config, VisibleLines};
4use crate::config::{Config, VisibleLines};
@@ -14,7 +14,20 @@ use crate::output::OutputType;
14use crate::paging::PagingMode;
14use crate::paging::PagingMode;
15use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
15use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
16
16
17−use clircle::Clircle;
17+use clircle::{Clircle, Identifier};
18+
19+struct DummyStdin;
20+impl Read for DummyStdin {
21+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
22+ Ok(buf.len())
23+ }
24+}
25+impl BufRead for DummyStdin {
26+ fn fill_buf(&mut self) -> io::Result<&[u8]> {
27+ Ok(&[])
28+ }
29+ fn consume(&mut self, _amt: usize) {}
30+}
18
31
19pub struct Controller<'a> {
32pub struct Controller<'a> {
20 config: &'a Config<'a>,
33 config: &'a Config<'a>,
@@ -87,72 +100,82 @@ impl<'b> Controller<'b> {
87 };
100 };
88
101
89 for (index, input) in inputs.into_iter().enumerate() {
102 for (index, input) in inputs.into_iter().enumerate() {
90− match input.open(io::stdin().lock(), stdout_identifier.as_ref()) {
103+ let identifier = stdout_identifier.as_ref();
104+ let is_first = index == 0;
105+ let result = if input.is_stdin() {
106+ self.print_input(input, writer, io::stdin().lock(), identifier, is_first)
107+ } else {
108+ // Use dummy stdin since stdin is actually not used (#1902)
109+ self.print_input(input, writer, DummyStdin, identifier, is_first)
110+ };
91− Err(error) => {
111+ if let Err(error) = result {
92− print_error(&error, writer);
112+ print_error(&error, writer);
93− no_errors = false;
113+ no_errors = false;
94− }
95− Ok(mut opened_input) => {
96− #[cfg(feature = "git")]
97− let line_changes = if self.config.visible_lines.diff_mode()
98− || (!self.config.loop_through && self.config.style_components.changes())
99− {
100− match opened_input.kind {
101− crate::input::OpenedInputKind::OrdinaryFile(ref path) => {
102− let diff = get_git_diff(path);
103−
104− // Skip files without Git modifications
105− if self.config.visible_lines.diff_mode()
106− && diff
107− .as_ref()
108− .map(|changes| changes.is_empty())
109− .unwrap_or(false)
110− {
111− continue;
112− }
113−
114− diff
115− }
116− _ if self.config.visible_lines.diff_mode() => {
117− // Skip non-file inputs in diff mode
118− continue;
119− }
114+ }
120− _ => None,
121− }
122− } else {
123− None
124− };
115+ }
125
116
126− let mut printer: Box<dyn Printer> = if self.config.loop_through {
117+ Ok(no_errors)
127− Box::new(SimplePrinter::new(self.config))
118+ }
128− } else {
119+
129− Box::new(InteractivePrinter::new(
120+ fn print_input<'a, R: BufRead>(
130− self.config,
121+ &self,
131− self.assets,
122+ input: Input,
132− &mut opened_input,
123+ writer: &mut dyn Write,
133− #[cfg(feature = "git")]
124+ stdin: R,
134− &line_changes,
125+ stdout_identifier: Option<&Identifier>,
135− )?)
126+ is_first: bool,
136− };
127+ ) -> Result<()> {
137−
128+ let mut opened_input = input.open(stdin, stdout_identifier)?;
138− let result = self.print_file(
129+ #[cfg(feature = "git")]
139− &mut *printer,
130+ let line_changes = if self.config.visible_lines.diff_mode()
140− writer,
131+ || (!self.config.loop_through && self.config.style_components.changes())
141− &mut opened_input,
132+ {
142− index != 0,
133+ match opened_input.kind {
143− #[cfg(feature = "git")]
134+ crate::input::OpenedInputKind::OrdinaryFile(ref path) => {
144− &line_changes,
135+ let diff = get_git_diff(path);
145− );
136+
146−
137+ // Skip files without Git modifications
147− if let Err(error) = result {
138+ if self.config.visible_lines.diff_mode()
148− print_error(&error, writer);
139+ && diff
149− no_errors = false;
140+ .as_ref()
141+ .map(|changes| changes.is_empty())
142+ .unwrap_or(false)
143+ {
144+ return Ok(());
150 }
145 }
146+
147+ diff
151 }
148 }
149+ _ if self.config.visible_lines.diff_mode() => {
150+ // Skip non-file inputs in diff mode
151+ return Ok(());
152+ }
153+ _ => None,
152 }
154 }
153− }
155+ } else {
156+ None
157+ };
154
158
155− Ok(no_errors)
159+ let mut printer: Box<dyn Printer> = if self.config.loop_through {
160+ Box::new(SimplePrinter::new(self.config))
161+ } else {
162+ Box::new(InteractivePrinter::new(
163+ self.config,
164+ self.assets,
165+ &mut opened_input,
166+ #[cfg(feature = "git")]
167+ &line_changes,
168+ )?)
169+ };
170+
171+ self.print_file(
172+ &mut *printer,
173+ writer,
174+ &mut opened_input,
175+ !is_first,
176+ #[cfg(feature = "git")]
177+ &line_changes,
178+ )
156 }
179 }
157
180
158 fn print_file(
181 fn print_file(