Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/uu/tail/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ tail-usage = tail [FLAG]... [FILE]...

# Help messages
tail-help-bytes = Number of bytes to print
tail-help-debug = indicate which --follow implementation is used
tail-help-follow = Print the file as it grows
tail-help-lines = Number of lines to print
tail-help-pid = With -f, terminate after process ID, PID dies
Expand Down Expand Up @@ -70,3 +71,7 @@ tail-giving-up-on-this-name = ; giving up on this name
tail-stdin-header = standard input
tail-no-files-remaining = no files remaining
tail-become-inaccessible = has become inaccessible

# Debug messages
tail-debug-using-notification-mode = using notification mode
tail-debug-using-polling-mode = using polling mode
10 changes: 10 additions & 0 deletions src/uu/tail/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub mod options {
pub const MAX_UNCHANGED_STATS: &str = "max-unchanged-stats";
pub const ARG_FILES: &str = "files";
pub const PRESUME_INPUT_PIPE: &str = "-presume-input-pipe"; // NOTE: three hyphens is correct
pub const DEBUG: &str = "debug";
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -139,6 +140,7 @@ pub struct Settings {
pub use_polling: bool,
pub verbose: bool,
pub presume_input_pipe: bool,
pub debug: bool,
/// `FILE(s)` positional arguments
pub inputs: Vec<Input>,
}
Expand All @@ -155,6 +157,7 @@ impl Default for Settings {
use_polling: Default::default(),
verbose: Default::default(),
presume_input_pipe: Default::default(),
debug: Default::default(),
inputs: Vec::default(),
}
}
Expand Down Expand Up @@ -223,6 +226,7 @@ impl Settings {
mode: FilterMode::from(matches)?,
verbose: matches.get_flag(options::verbosity::VERBOSE),
presume_input_pipe: matches.get_flag(options::PRESUME_INPUT_PIPE),
debug: matches.get_flag(options::DEBUG),
..Default::default()
};

Expand Down Expand Up @@ -543,6 +547,12 @@ pub fn uu_app() -> Command {
.overrides_with(options::FOLLOW_RETRY)
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::DEBUG)
.long(options::DEBUG)
.help(translate!("tail-help-debug"))
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::PRESUME_INPUT_PIPE)
.long("presume-input-pipe")
Expand Down
10 changes: 10 additions & 0 deletions src/uu/tail/src/tail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ fn uu_tail(settings: &Settings) -> UResult<()> {
let mut observer = Observer::from(settings);

observer.start(settings)?;

// Print debug info about the follow implementation being used
if settings.debug && settings.follow.is_some() {
if observer.use_polling {
show_error!("{}", translate!("tail-debug-using-polling-mode"));
} else {
show_error!("{}", translate!("tail-debug-using-notification-mode"));
}
}

// Do an initial tail print of each path's content.
// Add `path` and `reader` to `files` map if `--follow` is selected.
for input in &settings.inputs.clone() {
Expand Down
36 changes: 36 additions & 0 deletions tests/by-util/test_tail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5065,3 +5065,39 @@ fn test_follow_stdout_pipe_close() {
child.close_stdout();
child.delay(2000).make_assertion().is_not_alive();
}

#[test]
fn test_debug_flag_with_polling() {
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
at.touch("f");

let mut child = ts
.ucmd()
.args(&["--debug", "-f", "--use-polling", "f"])
.run_no_wait();

child.make_assertion_with_delay(500).is_alive();
child
.kill()
.make_assertion()
.with_all_output()
.stderr_contains("tail: using polling mode");
}

#[test]
#[cfg(target_os = "linux")]
fn test_debug_flag_with_inotify() {
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
at.touch("f");

let mut child = ts.ucmd().args(&["--debug", "-f", "f"]).run_no_wait();

child.make_assertion_with_delay(500).is_alive();
child
.kill()
.make_assertion()
.with_all_output()
.stderr_contains("tail: using notification mode");
}
Loading