ls: align --ignore behavior with that of GNU ls

This commit is contained in:
Ackerley Tng 2022-07-31 09:46:11 -07:00
parent 0f98bd01e1
commit d84803b72f
2 changed files with 83 additions and 13 deletions

View file

@ -14,7 +14,7 @@ use clap::{
builder::{NonEmptyStringValueParser, ValueParser},
crate_version, Arg, Command,
};
use glob::Pattern;
use glob::{MatchOptions, Pattern};
use lscolors::LsColors;
use number_prefix::NumberPrefix;
use once_cell::unsync::OnceCell;
@ -41,6 +41,7 @@ use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
use unicode_width::UnicodeWidthStr;
#[cfg(unix)]
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
use uucore::parse_glob;
use uucore::quoting_style::{escape_name, QuotingStyle};
use uucore::{
display::Quotable,
@ -765,7 +766,7 @@ impl Config {
.into_iter()
.flatten()
{
match Pattern::new(pattern) {
match parse_glob::from_str(pattern) {
Ok(p) => {
ignore_patterns.push(p);
}
@ -779,7 +780,7 @@ impl Config {
.into_iter()
.flatten()
{
match Pattern::new(pattern) {
match parse_glob::from_str(pattern) {
Ok(p) => {
ignore_patterns.push(p);
}
@ -1877,16 +1878,18 @@ fn should_display(entry: &DirEntry, config: &Config) -> bool {
return false;
}
// check if explicitly ignored
for pattern in &config.ignore_patterns {
if pattern.matches(entry.file_name().to_str().unwrap()) {
return false;
};
continue;
}
// else default to display
true
// check if it is among ignore_patterns
let options = MatchOptions {
// setting require_literal_leading_dot to match behavior in GNU ls
require_literal_leading_dot: true,
require_literal_separator: false,
case_sensitive: true,
};
let file_name = entry.file_name().into_string().unwrap();
!config
.ignore_patterns
.iter()
.any(|p| p.matches_with(&file_name, options))
}
fn enter_directory(

View file

@ -2681,6 +2681,73 @@ fn test_ls_ignore_backups() {
.stdout_does_not_contain(".somehiddenbackup~");
}
// This test fails on windows, see details at #3985
#[cfg(not(windows))]
#[test]
fn test_ls_ignore_explicit_period() {
// In ls ignore patterns, leading periods must be explicitly specified
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.touch(".hidden.yml");
at.touch("regular.yml");
scene
.ucmd()
.arg("-a")
.arg("--ignore")
.arg("?hidden.yml")
.succeeds()
.stdout_contains(".hidden.yml")
.stdout_contains("regular.yml");
scene
.ucmd()
.arg("-a")
.arg("--ignore")
.arg("*.yml")
.succeeds()
.stdout_contains(".hidden.yml")
.stdout_does_not_contain("regular.yml");
// Leading period is explicitly specified
scene
.ucmd()
.arg("-a")
.arg("--ignore")
.arg(".*.yml")
.succeeds()
.stdout_does_not_contain(".hidden.yml")
.stdout_contains("regular.yml");
}
// This test fails on windows, see details at #3985
#[cfg(not(windows))]
#[test]
fn test_ls_ignore_negation() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.touch("apple");
at.touch("boy");
scene
.ucmd()
.arg("--ignore")
.arg("[!a]*")
.succeeds()
.stdout_contains("apple")
.stdout_does_not_contain("boy");
scene
.ucmd()
.arg("--ignore")
.arg("[^a]*")
.succeeds()
.stdout_contains("apple")
.stdout_does_not_contain("boy");
}
#[test]
fn test_ls_directory() {
let scene = TestScenario::new(util_name!());