1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Merge pull request #4756 from Joining7943/tail-refactor-and-fix-input

`tail`: Refactor `paths::Input::from` and `Settings::inputs`
This commit is contained in:
Sylvestre Ledru 2023-07-03 14:09:57 +02:00 committed by GitHub
commit 7a7842b5b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 38 deletions

View file

@ -7,12 +7,11 @@
use crate::paths::Input; use crate::paths::Input;
use crate::{parse, platform, Quotable}; use crate::{parse, platform, Quotable};
use clap::crate_version; use clap::{crate_version, value_parser};
use clap::{Arg, ArgAction, ArgMatches, Command}; use clap::{Arg, ArgAction, ArgMatches, Command};
use fundu::{DurationParser, SaturatingInto}; use fundu::{DurationParser, SaturatingInto};
use is_terminal::IsTerminal; use is_terminal::IsTerminal;
use same_file::Handle; use same_file::Handle;
use std::collections::VecDeque;
use std::ffi::OsString; use std::ffi::OsString;
use std::time::Duration; use std::time::Duration;
use uucore::error::{UResult, USimpleError, UUsageError}; use uucore::error::{UResult, USimpleError, UUsageError};
@ -141,7 +140,8 @@ pub struct Settings {
pub use_polling: bool, pub use_polling: bool,
pub verbose: bool, pub verbose: bool,
pub presume_input_pipe: bool, pub presume_input_pipe: bool,
pub inputs: VecDeque<Input>, /// `FILE(s)` positional arguments
pub inputs: Vec<Input>,
} }
impl Default for Settings { impl Default for Settings {
@ -173,11 +173,11 @@ impl Settings {
} }
settings.mode = FilterMode::from_obsolete_args(args); settings.mode = FilterMode::from_obsolete_args(args);
let input = if let Some(name) = name { let input = if let Some(name) = name {
Input::from(&name) Input::from(name)
} else { } else {
Input::default() Input::default()
}; };
settings.inputs.push_back(input); settings.inputs.push(input);
settings settings
} }
@ -285,19 +285,13 @@ impl Settings {
} }
} }
let mut inputs: VecDeque<Input> = matches settings.inputs = matches
.get_many::<String>(options::ARG_FILES) .get_many::<OsString>(options::ARG_FILES)
.map(|v| v.map(|string| Input::from(&string)).collect()) .map(|v| v.map(Input::from).collect())
.unwrap_or_default(); .unwrap_or_else(|| vec![Input::default()]);
// apply default and add '-' to inputs if none is present settings.verbose =
if inputs.is_empty() { settings.inputs.len() > 1 && !matches.get_flag(options::verbosity::QUIET);
inputs.push_front(Input::default());
}
settings.verbose = inputs.len() > 1 && !matches.get_flag(options::verbosity::QUIET);
settings.inputs = inputs;
Ok(settings) Ok(settings)
} }
@ -593,6 +587,7 @@ pub fn uu_app() -> Command {
Arg::new(options::ARG_FILES) Arg::new(options::ARG_FILES)
.action(ArgAction::Append) .action(ArgAction::Append)
.num_args(1..) .num_args(1..)
.value_parser(value_parser!(OsString))
.value_hint(clap::ValueHint::FilePath), .value_hint(clap::ValueHint::FilePath),
) )
} }

View file

@ -10,7 +10,6 @@ use crate::follow::files::{FileHandling, PathData};
use crate::paths::{Input, InputKind, MetadataExtTail, PathExtTail}; use crate::paths::{Input, InputKind, MetadataExtTail, PathExtTail};
use crate::{platform, text}; use crate::{platform, text};
use notify::{RecommendedWatcher, RecursiveMode, Watcher, WatcherKind}; use notify::{RecommendedWatcher, RecursiveMode, Watcher, WatcherKind};
use std::collections::VecDeque;
use std::io::BufRead; use std::io::BufRead;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::mpsc::{self, channel, Receiver}; use std::sync::mpsc::{self, channel, Receiver};
@ -270,7 +269,7 @@ impl Observer {
self.follow_name() && self.retry self.follow_name() && self.retry
} }
fn init_files(&mut self, inputs: &VecDeque<Input>) -> UResult<()> { fn init_files(&mut self, inputs: &Vec<Input>) -> UResult<()> {
if let Some(watcher_rx) = &mut self.watcher_rx { if let Some(watcher_rx) = &mut self.watcher_rx {
for input in inputs { for input in inputs {
match input.kind() { match input.kind() {

View file

@ -20,6 +20,28 @@ pub enum InputKind {
Stdin, Stdin,
} }
#[cfg(unix)]
impl From<&OsStr> for InputKind {
fn from(value: &OsStr) -> Self {
if value == OsStr::new("-") {
Self::Stdin
} else {
Self::File(PathBuf::from(value))
}
}
}
#[cfg(not(unix))]
impl From<&OsStr> for InputKind {
fn from(value: &OsStr) -> Self {
if value == OsStr::new(text::DASH) {
Self::Stdin
} else {
Self::File(PathBuf::from(value))
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Input { pub struct Input {
kind: InputKind, kind: InputKind,
@ -27,22 +49,13 @@ pub struct Input {
} }
impl Input { impl Input {
pub fn from<T: AsRef<OsStr>>(string: &T) -> Self { pub fn from<T: AsRef<OsStr>>(string: T) -> Self {
let kind = if string.as_ref() == Path::new(text::DASH) { let string = string.as_ref();
InputKind::Stdin
} else {
InputKind::File(PathBuf::from(string.as_ref()))
};
let kind = string.into();
let display_name = match kind { let display_name = match kind {
InputKind::File(_) => string.as_ref().to_string_lossy().to_string(), InputKind::File(_) => string.to_string_lossy().to_string(),
InputKind::Stdin => { InputKind::Stdin => text::STDIN_HEADER.to_string(),
if cfg!(unix) {
text::STDIN_HEADER.to_string()
} else {
string.as_ref().to_string_lossy().to_string()
}
}
}; };
Self { kind, display_name } Self { kind, display_name }

View file

@ -145,12 +145,8 @@ fn test_stdin_redirect_offset() {
} }
#[test] #[test]
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))] // FIXME: for currently not working platforms #[cfg(all(not(target_vendor = "apple")))] // FIXME: for currently not working platforms
fn test_stdin_redirect_offset2() { fn test_stdin_redirect_offset2() {
// FIXME: windows: Failed because of difference in printed header. See below.
// actual : ==> - <==
// expected: ==> standard input <==
// like test_stdin_redirect_offset but with multiple files // like test_stdin_redirect_offset but with multiple files
let ts = TestScenario::new(util_name!()); let ts = TestScenario::new(util_name!());