From 8e796d3bb679bf7c064baca79b2ee0664b90762e Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Sun, 19 Nov 2023 15:10:28 +0100 Subject: [PATCH 01/52] mv: fix issue with -T and dest ending with "/" --- src/uu/mv/src/mv.rs | 2 +- tests/by-util/test_mv.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/uu/mv/src/mv.rs b/src/uu/mv/src/mv.rs index 036024f99..f0529af7e 100644 --- a/src/uu/mv/src/mv.rs +++ b/src/uu/mv/src/mv.rs @@ -341,7 +341,7 @@ fn handle_two_paths(source: &Path, target: &Path, opts: &Options) -> UResult<()> let target_is_dir = target.is_dir(); - if path_ends_with_terminator(target) && !target_is_dir { + if path_ends_with_terminator(target) && !target_is_dir && !opts.no_target_dir { return Err(MvError::FailedToAccessNotADirectory(target.quote().to_string()).into()); } diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index c54d24ea9..571de7691 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -1158,6 +1158,32 @@ fn test_mv_overwrite_dir() { assert!(at.dir_exists(dir_b)); } +#[test] +fn test_mv_no_target_dir_with_dest_not_existing() { + let (at, mut ucmd) = at_and_ucmd!(); + let dir_a = "a"; + let dir_b = "b"; + + at.mkdir(dir_a); + ucmd.arg("-T").arg(dir_a).arg(dir_b).succeeds().no_output(); + + assert!(!at.dir_exists(dir_a)); + assert!(at.dir_exists(dir_b)); +} + +#[test] +fn test_mv_no_target_dir_with_dest_not_existing_and_ending_with_slash() { + let (at, mut ucmd) = at_and_ucmd!(); + let dir_a = "a"; + let dir_b = "b/"; + + at.mkdir(dir_a); + ucmd.arg("-T").arg(dir_a).arg(dir_b).succeeds().no_output(); + + assert!(!at.dir_exists(dir_a)); + assert!(at.dir_exists(dir_b)); +} + #[test] fn test_mv_overwrite_nonempty_dir() { let (at, mut ucmd) = at_and_ucmd!(); From 66e0835e72a72d8ff0a97213b5320fc45973ecbc Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 29 Nov 2023 09:55:55 +0100 Subject: [PATCH 02/52] fuzz the echo command --- fuzz/Cargo.toml | 7 +++ fuzz/fuzz_targets/fuzz_echo.rs | 93 ++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 fuzz/fuzz_targets/fuzz_echo.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 630af4650..b27f5b586 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -17,6 +17,7 @@ uu_date = { path = "../src/uu/date/" } uu_test = { path = "../src/uu/test/" } uu_expr = { path = "../src/uu/expr/" } uu_printf = { path = "../src/uu/printf/" } +uu_echo = { path = "../src/uu/echo/" } # Prevent this from interfering with workspaces @@ -35,6 +36,12 @@ path = "fuzz_targets/fuzz_printf.rs" test = false doc = false +[[bin]] +name = "fuzz_echo" +path = "fuzz_targets/fuzz_echo.rs" +test = false +doc = false + [[bin]] name = "fuzz_expr" path = "fuzz_targets/fuzz_expr.rs" diff --git a/fuzz/fuzz_targets/fuzz_echo.rs b/fuzz/fuzz_targets/fuzz_echo.rs new file mode 100644 index 000000000..3d8100853 --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_echo.rs @@ -0,0 +1,93 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; +use uu_echo::uumain; // Changed from uu_printf to uu_echo + +use rand::prelude::SliceRandom; +use rand::Rng; +use std::ffi::OsString; + +mod fuzz_common; +use crate::fuzz_common::CommandResult; +use crate::fuzz_common::{ + compare_result, generate_and_run_uumain, generate_random_string, run_gnu_cmd, +}; + +static CMD_PATH: &str = "/usr/bin/echo"; // Changed from "printf" to "echo" + +fn generate_echo() -> String { + let mut rng = rand::thread_rng(); + let mut echo_str = String::new(); + + // Randomly decide whether to include options + let include_n = rng.gen_bool(0.1); // 10% chance + let include_e = rng.gen_bool(0.1); // 10% chance + let include_E = rng.gen_bool(0.1); // 10% chance + // --help and --version are typically not included in fuzzing as they don't change output format + + if include_n { + echo_str.push_str("-n "); + } + if include_e { + echo_str.push_str("-e "); + } + if include_E { + echo_str.push_str("-E "); + } + + // Add a random string + echo_str.push_str(&generate_random_string(rng.gen_range(1..=10))); + + // Include escape sequences if -e is enabled + if include_e { + // Add a 10% chance of including an escape sequence + if rng.gen_bool(0.1) { + echo_str.push_str(&generate_escape_sequence(&mut rng)); // This function should handle echo-specific sequences + } + } + + echo_str +} + +// You should also modify the generate_escape_sequence function to include echo-specific sequences +fn generate_escape_sequence(rng: &mut impl Rng) -> String { + let escape_sequences = [ + "\\\\", "\\a", "\\b", "\\c", "\\e", "\\f", "\\n", "\\r", "\\t", "\\v", + "\\0NNN", // You can randomly generate NNN + "\\xHH", // You can randomly generate HH + // ... other sequences + ]; + escape_sequences.choose(rng).unwrap().to_string() +} + +fuzz_target!(|_data: &[u8]| { + let echo_input = generate_echo(); // Changed from generate_printf to generate_echo + let mut args = vec![OsString::from("echo")]; // Changed from "printf" to "echo" + args.extend(echo_input.split_whitespace().map(OsString::from)); + let rust_result = generate_and_run_uumain(&args, uumain); // uumain function from uu_echo + + let gnu_result = match run_gnu_cmd(CMD_PATH, &args[1..], false) { + Ok(result) => result, + Err(error_result) => { + eprintln!("Failed to run GNU command:"); + eprintln!("Stderr: {}", error_result.stderr); + eprintln!("Exit Code: {}", error_result.exit_code); + CommandResult { + stdout: String::new(), + stderr: error_result.stderr, + exit_code: error_result.exit_code, + } + } + }; + + compare_result( + "echo", + &format!("{:?}", &args[1..]), + &rust_result.stdout, + &gnu_result.stdout, + &rust_result.stderr, + &gnu_result.stderr, + rust_result.exit_code, + gnu_result.exit_code, + false, // Set to true if you want to fail on stderr diff + ); +}); From 420df3db3d14f89c1b11278fc485aac7fd1d9745 Mon Sep 17 00:00:00 2001 From: Laurent Cheylus Date: Wed, 29 Nov 2023 17:44:50 +0100 Subject: [PATCH 03/52] Add support in uucore for OpenBSD - uucore/src/lib/features/fs.rs: add target_os = OpenBSD when needed - uucore/src/lib/features/fsext.rs: implement FsUsage::new for OpenBSD - fixes uutils/coreutils#5448 - initial code by n1000 https://github.com/n1000/coreutils/tree/openbsd_compile_fixes Signed-off-by: Laurent Cheylus --- src/uucore/src/lib/features/fs.rs | 5 +++- src/uucore/src/lib/features/fsext.rs | 39 ++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/uucore/src/lib/features/fs.rs b/src/uucore/src/lib/features/fs.rs index de4c0b08d..94ca82c80 100644 --- a/src/uucore/src/lib/features/fs.rs +++ b/src/uucore/src/lib/features/fs.rs @@ -115,6 +115,7 @@ impl FileInformation { not(target_os = "android"), not(target_os = "freebsd"), not(target_os = "netbsd"), + not(target_os = "openbsd"), not(target_os = "illumos"), not(target_os = "solaris"), not(target_arch = "aarch64"), @@ -130,6 +131,7 @@ impl FileInformation { target_os = "android", target_os = "freebsd", target_os = "netbsd", + target_os = "openbsd", target_os = "illumos", target_os = "solaris", target_arch = "aarch64", @@ -146,13 +148,14 @@ impl FileInformation { #[cfg(unix)] pub fn inode(&self) -> u64 { #[cfg(all( - not(any(target_os = "freebsd", target_os = "netbsd")), + not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")), target_pointer_width = "64" ))] return self.0.st_ino; #[cfg(any( target_os = "freebsd", target_os = "netbsd", + target_os = "openbsd", not(target_pointer_width = "64") ))] return self.0.st_ino.into(); diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 8b1c42de6..93fedb44b 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -497,7 +497,10 @@ impl FsUsage { #[cfg(unix)] pub fn new(statvfs: StatFs) -> Self { { - #[cfg(all(not(target_os = "freebsd"), target_pointer_width = "64"))] + #[cfg(all( + not(any(target_os = "freebsd", target_os = "openbsd")), + target_pointer_width = "64" + ))] return Self { blocksize: statvfs.f_bsize as u64, // or `statvfs.f_frsize` ? blocks: statvfs.f_blocks, @@ -507,7 +510,10 @@ impl FsUsage { files: statvfs.f_files, ffree: statvfs.f_ffree, }; - #[cfg(all(not(target_os = "freebsd"), not(target_pointer_width = "64")))] + #[cfg(all( + not(any(target_os = "freebsd", target_os = "openbsd")), + not(target_pointer_width = "64") + ))] return Self { blocksize: statvfs.f_bsize as u64, // or `statvfs.f_frsize` ? blocks: statvfs.f_blocks.into(), @@ -530,6 +536,19 @@ impl FsUsage { files: statvfs.f_files, ffree: statvfs.f_ffree.try_into().unwrap(), }; + #[cfg(target_os = "openbsd")] + return Self { + blocksize: statvfs.f_bsize.into(), + blocks: statvfs.f_blocks, + bfree: statvfs.f_bfree, + bavail: statvfs.f_bavail.try_into().unwrap(), + bavail_top_bit_set: ((std::convert::TryInto::::try_into(statvfs.f_bavail) + .unwrap()) + & (1u64.rotate_right(1))) + != 0, + files: statvfs.f_files, + ffree: statvfs.f_ffree, + }; } } #[cfg(not(unix))] @@ -617,6 +636,7 @@ impl FsMeta for StatFs { not(target_vendor = "apple"), not(target_os = "android"), not(target_os = "freebsd"), + not(target_os = "openbsd"), not(target_os = "illumos"), not(target_os = "solaris"), not(target_arch = "s390x"), @@ -630,6 +650,7 @@ impl FsMeta for StatFs { target_arch = "s390x", target_vendor = "apple", target_os = "android", + target_os = "openbsd", not(target_pointer_width = "64") ) ))] @@ -655,11 +676,19 @@ impl FsMeta for StatFs { return self.f_bfree.into(); } fn avail_blocks(&self) -> u64 { - #[cfg(all(not(target_os = "freebsd"), target_pointer_width = "64"))] + #[cfg(all( + not(target_os = "freebsd"), + not(target_os = "openbsd"), + target_pointer_width = "64" + ))] return self.f_bavail; - #[cfg(all(not(target_os = "freebsd"), not(target_pointer_width = "64")))] + #[cfg(all( + not(target_os = "freebsd"), + not(target_os = "openbsd"), + not(target_pointer_width = "64") + ))] return self.f_bavail.into(); - #[cfg(target_os = "freebsd")] + #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] return self.f_bavail.try_into().unwrap(); } fn total_file_nodes(&self) -> u64 { From 4d5c034eb10d0a07098abb75ddd5771b6d444c05 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 29 Nov 2023 14:11:43 +0100 Subject: [PATCH 04/52] Run the echo fuzzer in the CI --- .github/workflows/fuzzing.yml | 1 + fuzz/fuzz_targets/fuzz_echo.rs | 21 ++++++++------------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/fuzzing.yml b/.github/workflows/fuzzing.yml index 2274f6905..cc1547c87 100644 --- a/.github/workflows/fuzzing.yml +++ b/.github/workflows/fuzzing.yml @@ -42,6 +42,7 @@ jobs: - { name: fuzz_date, should_pass: false } - { name: fuzz_expr, should_pass: true } - { name: fuzz_printf, should_pass: false } + - { name: fuzz_echo, should_pass: false } - { name: fuzz_parse_glob, should_pass: true } - { name: fuzz_parse_size, should_pass: true } - { name: fuzz_parse_time, should_pass: true } diff --git a/fuzz/fuzz_targets/fuzz_echo.rs b/fuzz/fuzz_targets/fuzz_echo.rs index 3d8100853..826fd6da3 100644 --- a/fuzz/fuzz_targets/fuzz_echo.rs +++ b/fuzz/fuzz_targets/fuzz_echo.rs @@ -1,6 +1,6 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use uu_echo::uumain; // Changed from uu_printf to uu_echo +use uu_echo::uumain; use rand::prelude::SliceRandom; use rand::Rng; @@ -12,7 +12,7 @@ use crate::fuzz_common::{ compare_result, generate_and_run_uumain, generate_random_string, run_gnu_cmd, }; -static CMD_PATH: &str = "/usr/bin/echo"; // Changed from "printf" to "echo" +static CMD_PATH: &str = "echo"; fn generate_echo() -> String { let mut rng = rand::thread_rng(); @@ -22,7 +22,6 @@ fn generate_echo() -> String { let include_n = rng.gen_bool(0.1); // 10% chance let include_e = rng.gen_bool(0.1); // 10% chance let include_E = rng.gen_bool(0.1); // 10% chance - // --help and --version are typically not included in fuzzing as they don't change output format if include_n { echo_str.push_str("-n "); @@ -41,29 +40,25 @@ fn generate_echo() -> String { if include_e { // Add a 10% chance of including an escape sequence if rng.gen_bool(0.1) { - echo_str.push_str(&generate_escape_sequence(&mut rng)); // This function should handle echo-specific sequences + echo_str.push_str(&generate_escape_sequence(&mut rng)); } } echo_str } -// You should also modify the generate_escape_sequence function to include echo-specific sequences fn generate_escape_sequence(rng: &mut impl Rng) -> String { let escape_sequences = [ - "\\\\", "\\a", "\\b", "\\c", "\\e", "\\f", "\\n", "\\r", "\\t", "\\v", - "\\0NNN", // You can randomly generate NNN - "\\xHH", // You can randomly generate HH - // ... other sequences + "\\\\", "\\a", "\\b", "\\c", "\\e", "\\f", "\\n", "\\r", "\\t", "\\v", "\\0NNN", "\\xHH", ]; escape_sequences.choose(rng).unwrap().to_string() } fuzz_target!(|_data: &[u8]| { - let echo_input = generate_echo(); // Changed from generate_printf to generate_echo - let mut args = vec![OsString::from("echo")]; // Changed from "printf" to "echo" + let echo_input = generate_echo(); + let mut args = vec![OsString::from("echo")]; args.extend(echo_input.split_whitespace().map(OsString::from)); - let rust_result = generate_and_run_uumain(&args, uumain); // uumain function from uu_echo + let rust_result = generate_and_run_uumain(&args, uumain); let gnu_result = match run_gnu_cmd(CMD_PATH, &args[1..], false) { Ok(result) => result, @@ -88,6 +83,6 @@ fuzz_target!(|_data: &[u8]| { &gnu_result.stderr, rust_result.exit_code, gnu_result.exit_code, - false, // Set to true if you want to fail on stderr diff + true, ); }); From 13a4c9114c4574ee8d14ffe0bb6b326ad203375d Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 2 Dec 2023 10:28:45 +0100 Subject: [PATCH 05/52] create datastructures for colors --- src/uucore/src/lib/features.rs | 2 + src/uucore/src/lib/features/colors.rs | 225 ++++++++++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 src/uucore/src/lib/features/colors.rs diff --git a/src/uucore/src/lib/features.rs b/src/uucore/src/lib/features.rs index 1d0d43782..a28e8a7bf 100644 --- a/src/uucore/src/lib/features.rs +++ b/src/uucore/src/lib/features.rs @@ -6,6 +6,8 @@ #[cfg(feature = "backup-control")] pub mod backup_control; +#[cfg(feature = "colors")] +pub mod colors; #[cfg(feature = "encoding")] pub mod encoding; #[cfg(feature = "format")] diff --git a/src/uucore/src/lib/features/colors.rs b/src/uucore/src/lib/features/colors.rs new file mode 100644 index 000000000..58b0b7570 --- /dev/null +++ b/src/uucore/src/lib/features/colors.rs @@ -0,0 +1,225 @@ +// This file is part of the uutils coreutils package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +/* The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the + * slackware version of dircolors) are recognized but ignored. + * Global config options can be specified before TERM or COLORTERM entries + * below are TERM or COLORTERM entries, which can be glob patterns, which + * restrict following config to systems with matching environment variables. + * COLORTERM ?* +*/ + +static TERMS: &[&str] = &[ + "Eterm", + "ansi", + "*color*", + "con[0-9]*x[0-9]*", + "cons25", + "console", + "cygwin", + "*direct*", + "dtterm", + "gnome", + "hurd", + "jfbterm", + "konsole", + "kterm", + "linux", + "linux-c", + "mlterm", + "putty", + "rxvt*", + "screen*", + "st", + "terminator", + "tmux*", + "vt100", + "xterm*", +]; + +/* +# Below are the color init strings for the basic file types. +# One can use codes for 256 or more colors supported by modern terminals. +# The default color codes use the capabilities of an 8 color terminal +# with some additional attributes as per the following codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +#NORMAL 00 # no color code at all +#FILE 00 # regular file: use no color at all +*/ +static FILE_TYPES: &[(&str, &str)] = &[ + ("RESET", "0"), // reset to "normal" color + ("DIR", "01;34"), // directory + ("LINK", "01;36"), // symbolic link + ("MULTIHARDLINK", "00"), // regular file with more than one link + ("FIFO", "40;33"), // pipe + ("SOCK", "01;35"), // socket + ("DOOR", "01;35"), // door + ("BLK", "40;33;01"), // block device driver + ("CHR", "40;33;01"), // character device driver + ("ORPHAN", "40;31;01"), // symlink to nonexistent file, or non-stat'able file + ("MISSING", "00"), // ... and the files they point to + ("SETUID", "37;41"), // file that is setuid (u+s) + ("SETGID", "30;43"), // file that is setgid (g+s) + ("CAPABILITY", "00"), // file with capability + ("STICKY_OTHER_WRITABLE", "30;42"), // dir that is sticky and other-writable (+t,o+w) + ("OTHER_WRITABLE", "34;42"), // dir that is other-writable (o+w) and not sticky + ("STICKY", "37;44"), // dir with the sticky bit set (+t) and not other-writable + ("EXEC", "01;32"), // files with execute permission +]; + +/* +# List any file extensions like '.gz' or '.tar' that you would like ls +# to color below. Put the extension, a space, and the color init string. +# (and any comments you want to add after a '#') +*/ +static FILE_COLORS: &[(&str, &str)] = &[ + // Executables (Windows) + (".cmd", "01;32"), + (".exe", "01;32"), + (".com", "01;32"), + (".btm", "01;32"), + (".bat", "01;32"), + (".sh", "01;32"), + (".csh", "01;32"), + // Archives or compressed + (".tar", "01;31"), + (".tgz", "01;31"), + (".arc", "01;31"), + (".arj", "01;31"), + (".taz", "01;31"), + (".lha", "01;31"), + (".lz4", "01;31"), + (".lzh", "01;31"), + (".lzma", "01;31"), + (".tlz", "01;31"), + (".txz", "01;31"), + (".tzo", "01;31"), + (".t7z", "01;31"), + (".zip", "01;31"), + (".z", "01;31"), + (".dz", "01;31"), + (".gz", "01;31"), + (".lrz", "01;31"), + (".lz", "01;31"), + (".lzo", "01;31"), + (".xz", "01;31"), + (".zst", "01;31"), + (".tzst", "01;31"), + (".bz2", "01;31"), + (".bz", "01;31"), + (".tbz", "01;31"), + (".tbz2", "01;31"), + (".tz", "01;31"), + (".deb", "01;31"), + (".rpm", "01;31"), + (".jar", "01;31"), + (".war", "01;31"), + (".ear", "01;31"), + (".sar", "01;31"), + (".rar", "01;31"), + (".alz", "01;31"), + (".ace", "01;31"), + (".zoo", "01;31"), + (".cpio", "01;31"), + (".7z", "01;31"), + (".rz", "01;31"), + (".cab", "01;31"), + (".wim", "01;31"), + (".swm", "01;31"), + (".dwm", "01;31"), + (".esd", "01;31"), + // Image formats + (".avif", "01;35"), + (".jpg", "01;35"), + (".jpeg", "01;35"), + (".mjpg", "01;35"), + (".mjpeg", "01;35"), + (".gif", "01;35"), + (".bmp", "01;35"), + (".pbm", "01;35"), + (".pgm", "01;35"), + (".ppm", "01;35"), + (".tga", "01;35"), + (".xbm", "01;35"), + (".xpm", "01;35"), + (".tif", "01;35"), + (".tiff", "01;35"), + (".png", "01;35"), + (".svg", "01;35"), + (".svgz", "01;35"), + (".mng", "01;35"), + (".pcx", "01;35"), + (".mov", "01;35"), + (".mpg", "01;35"), + (".mpeg", "01;35"), + (".m2v", "01;35"), + (".mkv", "01;35"), + (".webm", "01;35"), + (".webp", "01;35"), + (".ogm", "01;35"), + (".mp4", "01;35"), + (".m4v", "01;35"), + (".mp4v", "01;35"), + (".vob", "01;35"), + (".qt", "01;35"), + (".nuv", "01;35"), + (".wmv", "01;35"), + (".asf", "01;35"), + (".rm", "01;35"), + (".rmvb", "01;35"), + (".flc", "01;35"), + (".avi", "01;35"), + (".fli", "01;35"), + (".flv", "01;35"), + (".gl", "01;35"), + (".dl", "01;35"), + (".xcf", "01;35"), + (".xwd", "01;35"), + (".yuv", "01;35"), + (".cgm", "01;35"), + (".emf", "01;35"), + (".ogv", "01;35"), + (".ogx", "01;35"), + // Audio formats + (".aac", "00;36"), + (".au", "00;36"), + (".flac", "00;36"), + (".m4a", "00;36"), + (".mid", "00;36"), + (".midi", "00;36"), + (".mka", "00;36"), + (".mp3", "00;36"), + (".mpc", "00;36"), + (".ogg", "00;36"), + (".ra", "00;36"), + (".wav", "00;36"), + (".oga", "00;36"), + (".opus", "00;36"), + (".spx", "00;36"), + (".xspf", "00;36"), + // Backup files + ("*~", "00;90"), + ("*#", "00;90"), + (".bak", "00;90"), + (".old", "00;90"), + (".orig", "00;90"), + (".part", "00;90"), + (".rej", "00;90"), + (".swp", "00;90"), + (".tmp", "00;90"), + (".dpkg-dist", "00;90"), + (".dpkg-old", "00;90"), + (".ucf-dist", "00;90"), + (".ucf-new", "00;90"), + (".ucf-old", "00;90"), + (".rpmnew", "00;90"), + (".rpmorig", "00;90"), + (".rpmsave", "00;90"), +]; From 0e8c171c80ab35f4d16a2613700648ec059ebaa5 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 2 Dec 2023 11:00:55 +0100 Subject: [PATCH 06/52] dircolors: move the FILE_ATTRIBUTE_CODES datastructures and use it --- src/uu/dircolors/Cargo.toml | 2 +- src/uu/dircolors/src/dircolors.rs | 43 +-- src/uucore/Cargo.toml | 1 + src/uucore/src/lib/features/colors.rs | 458 +++++++++++++++----------- src/uucore/src/lib/lib.rs | 2 + 5 files changed, 273 insertions(+), 233 deletions(-) diff --git a/src/uu/dircolors/Cargo.toml b/src/uu/dircolors/Cargo.toml index 6099b5a84..66ee792f8 100644 --- a/src/uu/dircolors/Cargo.toml +++ b/src/uu/dircolors/Cargo.toml @@ -16,7 +16,7 @@ path = "src/dircolors.rs" [dependencies] clap = { workspace = true } -uucore = { workspace = true } +uucore = { workspace = true, features = ["colors"] } [[bin]] name = "dircolors" diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index 2e3087d81..58228ddeb 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -12,6 +12,7 @@ use std::io::{BufRead, BufReader}; use std::path::Path; use clap::{crate_version, Arg, ArgAction, Command}; +use uucore::colors::FILE_ATTRIBUTE_CODES; use uucore::display::Quotable; use uucore::error::{UResult, USimpleError, UUsageError}; use uucore::{help_about, help_section, help_usage}; @@ -276,7 +277,6 @@ enum ParseState { Pass, } -use std::collections::HashMap; use uucore::{format_usage, parse_glob}; #[allow(clippy::cognitive_complexity)] @@ -294,45 +294,6 @@ where OutputFmt::Unknown => unreachable!(), } - let mut table: HashMap<&str, &str> = HashMap::with_capacity(48); - table.insert("normal", "no"); - table.insert("norm", "no"); - table.insert("file", "fi"); - table.insert("reset", "rs"); - table.insert("dir", "di"); - table.insert("lnk", "ln"); - table.insert("link", "ln"); - table.insert("symlink", "ln"); - table.insert("orphan", "or"); - table.insert("missing", "mi"); - table.insert("fifo", "pi"); - table.insert("pipe", "pi"); - table.insert("sock", "so"); - table.insert("blk", "bd"); - table.insert("block", "bd"); - table.insert("chr", "cd"); - table.insert("char", "cd"); - table.insert("door", "do"); - table.insert("exec", "ex"); - table.insert("left", "lc"); - table.insert("leftcode", "lc"); - table.insert("right", "rc"); - table.insert("rightcode", "rc"); - table.insert("end", "ec"); - table.insert("endcode", "ec"); - table.insert("suid", "su"); - table.insert("setuid", "su"); - table.insert("sgid", "sg"); - table.insert("setgid", "sg"); - table.insert("sticky", "st"); - table.insert("other_writable", "ow"); - table.insert("owr", "ow"); - table.insert("sticky_other_writable", "tw"); - table.insert("owt", "tw"); - table.insert("capability", "ca"); - table.insert("multihardlink", "mh"); - table.insert("clrtoeol", "cl"); - let term = env::var("TERM").unwrap_or_else(|_| "none".to_owned()); let term = term.as_str(); @@ -384,7 +345,7 @@ where } } else if lower == "options" || lower == "color" || lower == "eightbit" { // Slackware only. Ignore - } else if let Some(s) = table.get(lower.as_str()) { + } else if let Some(s) = FILE_ATTRIBUTE_CODES.get(lower.as_str()) { if *fmt == OutputFmt::Display { result.push_str(format!("\x1b[{val}m{s}\t{val}\x1b[0m\n").as_str()); } else { diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index b43445b4a..44f8bb2d1 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -72,6 +72,7 @@ windows-sys = { workspace = true, optional = true, default-features = false, fea default = [] # * non-default features backup-control = [] +colors = [] encoding = ["data-encoding", "data-encoding-macro", "z85", "thiserror"] entries = ["libc"] fs = ["dunce", "libc", "winapi-util", "windows-sys"] diff --git a/src/uucore/src/lib/features/colors.rs b/src/uucore/src/lib/features/colors.rs index 58b0b7570..69be16ba2 100644 --- a/src/uucore/src/lib/features/colors.rs +++ b/src/uucore/src/lib/features/colors.rs @@ -3,6 +3,9 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +use once_cell::sync::Lazy; +use std::collections::HashMap; + /* The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the * slackware version of dircolors) are recognized but ignored. * Global config options can be specified before TERM or COLORTERM entries @@ -11,33 +14,41 @@ * COLORTERM ?* */ -static TERMS: &[&str] = &[ - "Eterm", - "ansi", - "*color*", - "con[0-9]*x[0-9]*", - "cons25", - "console", - "cygwin", - "*direct*", - "dtterm", - "gnome", - "hurd", - "jfbterm", - "konsole", - "kterm", - "linux", - "linux-c", - "mlterm", - "putty", - "rxvt*", - "screen*", - "st", - "terminator", - "tmux*", - "vt100", - "xterm*", -]; +pub static TERMS: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + [ + "Eterm", + "ansi", + "*color*", + "con[0-9]*x[0-9]*", + "cons25", + "console", + "cygwin", + "*direct*", + "dtterm", + "gnome", + "hurd", + "jfbterm", + "konsole", + "kterm", + "linux", + "linux-c", + "mlterm", + "putty", + "rxvt*", + "screen*", + "st", + "terminator", + "tmux*", + "vt100", + "xterm*", + ] + .iter() + .for_each(|&term| { + m.insert(term, ""); + }); + m +}); /* # Below are the color init strings for the basic file types. @@ -53,173 +64,238 @@ static TERMS: &[&str] = &[ #NORMAL 00 # no color code at all #FILE 00 # regular file: use no color at all */ -static FILE_TYPES: &[(&str, &str)] = &[ - ("RESET", "0"), // reset to "normal" color - ("DIR", "01;34"), // directory - ("LINK", "01;36"), // symbolic link - ("MULTIHARDLINK", "00"), // regular file with more than one link - ("FIFO", "40;33"), // pipe - ("SOCK", "01;35"), // socket - ("DOOR", "01;35"), // door - ("BLK", "40;33;01"), // block device driver - ("CHR", "40;33;01"), // character device driver - ("ORPHAN", "40;31;01"), // symlink to nonexistent file, or non-stat'able file - ("MISSING", "00"), // ... and the files they point to - ("SETUID", "37;41"), // file that is setuid (u+s) - ("SETGID", "30;43"), // file that is setgid (g+s) - ("CAPABILITY", "00"), // file with capability - ("STICKY_OTHER_WRITABLE", "30;42"), // dir that is sticky and other-writable (+t,o+w) - ("OTHER_WRITABLE", "34;42"), // dir that is other-writable (o+w) and not sticky - ("STICKY", "37;44"), // dir with the sticky bit set (+t) and not other-writable - ("EXEC", "01;32"), // files with execute permission -]; +// FILE_TYPES with Lazy initialization +pub static FILE_TYPES: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + [ + ("RESET", "0"), // reset to "normal" color + ("DIR", "01;34"), // directory + ("LINK", "01;36"), // symbolic link + ("MULTIHARDLINK", "00"), // regular file with more than one link + ("FIFO", "40;33"), // pipe + ("SOCK", "01;35"), // socket + ("DOOR", "01;35"), // door + ("BLK", "40;33;01"), // block device driver + ("CHR", "40;33;01"), // character device driver + ("ORPHAN", "40;31;01"), // symlink to nonexistent file, or non-stat'able file + ("MISSING", "00"), // ... and the files they point to + ("SETUID", "37;41"), // file that is setuid (u+s) + ("SETGID", "30;43"), // file that is setgid (g+s) + ("CAPABILITY", "00"), // file with capability + ("STICKY_OTHER_WRITABLE", "30;42"), // dir that is sticky and other-writable (+t,o+w) + ("OTHER_WRITABLE", "34;42"), // dir that is other-writable (o+w) and not sticky + ("STICKY", "37;44"), // dir with the sticky bit set (+t) and not other-writable + ("EXEC", "01;32"), // files with execute permission + ] + .iter() + .for_each(|&(k, v)| { + m.insert(k, v); + }); + m +}); /* # List any file extensions like '.gz' or '.tar' that you would like ls # to color below. Put the extension, a space, and the color init string. # (and any comments you want to add after a '#') */ -static FILE_COLORS: &[(&str, &str)] = &[ - // Executables (Windows) - (".cmd", "01;32"), - (".exe", "01;32"), - (".com", "01;32"), - (".btm", "01;32"), - (".bat", "01;32"), - (".sh", "01;32"), - (".csh", "01;32"), - // Archives or compressed - (".tar", "01;31"), - (".tgz", "01;31"), - (".arc", "01;31"), - (".arj", "01;31"), - (".taz", "01;31"), - (".lha", "01;31"), - (".lz4", "01;31"), - (".lzh", "01;31"), - (".lzma", "01;31"), - (".tlz", "01;31"), - (".txz", "01;31"), - (".tzo", "01;31"), - (".t7z", "01;31"), - (".zip", "01;31"), - (".z", "01;31"), - (".dz", "01;31"), - (".gz", "01;31"), - (".lrz", "01;31"), - (".lz", "01;31"), - (".lzo", "01;31"), - (".xz", "01;31"), - (".zst", "01;31"), - (".tzst", "01;31"), - (".bz2", "01;31"), - (".bz", "01;31"), - (".tbz", "01;31"), - (".tbz2", "01;31"), - (".tz", "01;31"), - (".deb", "01;31"), - (".rpm", "01;31"), - (".jar", "01;31"), - (".war", "01;31"), - (".ear", "01;31"), - (".sar", "01;31"), - (".rar", "01;31"), - (".alz", "01;31"), - (".ace", "01;31"), - (".zoo", "01;31"), - (".cpio", "01;31"), - (".7z", "01;31"), - (".rz", "01;31"), - (".cab", "01;31"), - (".wim", "01;31"), - (".swm", "01;31"), - (".dwm", "01;31"), - (".esd", "01;31"), - // Image formats - (".avif", "01;35"), - (".jpg", "01;35"), - (".jpeg", "01;35"), - (".mjpg", "01;35"), - (".mjpeg", "01;35"), - (".gif", "01;35"), - (".bmp", "01;35"), - (".pbm", "01;35"), - (".pgm", "01;35"), - (".ppm", "01;35"), - (".tga", "01;35"), - (".xbm", "01;35"), - (".xpm", "01;35"), - (".tif", "01;35"), - (".tiff", "01;35"), - (".png", "01;35"), - (".svg", "01;35"), - (".svgz", "01;35"), - (".mng", "01;35"), - (".pcx", "01;35"), - (".mov", "01;35"), - (".mpg", "01;35"), - (".mpeg", "01;35"), - (".m2v", "01;35"), - (".mkv", "01;35"), - (".webm", "01;35"), - (".webp", "01;35"), - (".ogm", "01;35"), - (".mp4", "01;35"), - (".m4v", "01;35"), - (".mp4v", "01;35"), - (".vob", "01;35"), - (".qt", "01;35"), - (".nuv", "01;35"), - (".wmv", "01;35"), - (".asf", "01;35"), - (".rm", "01;35"), - (".rmvb", "01;35"), - (".flc", "01;35"), - (".avi", "01;35"), - (".fli", "01;35"), - (".flv", "01;35"), - (".gl", "01;35"), - (".dl", "01;35"), - (".xcf", "01;35"), - (".xwd", "01;35"), - (".yuv", "01;35"), - (".cgm", "01;35"), - (".emf", "01;35"), - (".ogv", "01;35"), - (".ogx", "01;35"), - // Audio formats - (".aac", "00;36"), - (".au", "00;36"), - (".flac", "00;36"), - (".m4a", "00;36"), - (".mid", "00;36"), - (".midi", "00;36"), - (".mka", "00;36"), - (".mp3", "00;36"), - (".mpc", "00;36"), - (".ogg", "00;36"), - (".ra", "00;36"), - (".wav", "00;36"), - (".oga", "00;36"), - (".opus", "00;36"), - (".spx", "00;36"), - (".xspf", "00;36"), - // Backup files - ("*~", "00;90"), - ("*#", "00;90"), - (".bak", "00;90"), - (".old", "00;90"), - (".orig", "00;90"), - (".part", "00;90"), - (".rej", "00;90"), - (".swp", "00;90"), - (".tmp", "00;90"), - (".dpkg-dist", "00;90"), - (".dpkg-old", "00;90"), - (".ucf-dist", "00;90"), - (".ucf-new", "00;90"), - (".ucf-old", "00;90"), - (".rpmnew", "00;90"), - (".rpmorig", "00;90"), - (".rpmsave", "00;90"), -]; +pub static FILE_COLORS: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + [ + // Executables (Windows) + (".cmd", "01;32"), + (".exe", "01;32"), + (".com", "01;32"), + (".btm", "01;32"), + (".bat", "01;32"), + (".sh", "01;32"), + (".csh", "01;32"), + // Archives or compressed + (".tar", "01;31"), + (".tgz", "01;31"), + (".arc", "01;31"), + (".arj", "01;31"), + (".taz", "01;31"), + (".lha", "01;31"), + (".lz4", "01;31"), + (".lzh", "01;31"), + (".lzma", "01;31"), + (".tlz", "01;31"), + (".txz", "01;31"), + (".tzo", "01;31"), + (".t7z", "01;31"), + (".zip", "01;31"), + (".z", "01;31"), + (".dz", "01;31"), + (".gz", "01;31"), + (".lrz", "01;31"), + (".lz", "01;31"), + (".lzo", "01;31"), + (".xz", "01;31"), + (".zst", "01;31"), + (".tzst", "01;31"), + (".bz2", "01;31"), + (".bz", "01;31"), + (".tbz", "01;31"), + (".tbz2", "01;31"), + (".tz", "01;31"), + (".deb", "01;31"), + (".rpm", "01;31"), + (".jar", "01;31"), + (".war", "01;31"), + (".ear", "01;31"), + (".sar", "01;31"), + (".rar", "01;31"), + (".alz", "01;31"), + (".ace", "01;31"), + (".zoo", "01;31"), + (".cpio", "01;31"), + (".7z", "01;31"), + (".rz", "01;31"), + (".cab", "01;31"), + (".wim", "01;31"), + (".swm", "01;31"), + (".dwm", "01;31"), + (".esd", "01;31"), + // Image formats + (".avif", "01;35"), + (".jpg", "01;35"), + (".jpeg", "01;35"), + (".mjpg", "01;35"), + (".mjpeg", "01;35"), + (".gif", "01;35"), + (".bmp", "01;35"), + (".pbm", "01;35"), + (".pgm", "01;35"), + (".ppm", "01;35"), + (".tga", "01;35"), + (".xbm", "01;35"), + (".xpm", "01;35"), + (".tif", "01;35"), + (".tiff", "01;35"), + (".png", "01;35"), + (".svg", "01;35"), + (".svgz", "01;35"), + (".mng", "01;35"), + (".pcx", "01;35"), + (".mov", "01;35"), + (".mpg", "01;35"), + (".mpeg", "01;35"), + (".m2v", "01;35"), + (".mkv", "01;35"), + (".webm", "01;35"), + (".webp", "01;35"), + (".ogm", "01;35"), + (".mp4", "01;35"), + (".m4v", "01;35"), + (".mp4v", "01;35"), + (".vob", "01;35"), + (".qt", "01;35"), + (".nuv", "01;35"), + (".wmv", "01;35"), + (".asf", "01;35"), + (".rm", "01;35"), + (".rmvb", "01;35"), + (".flc", "01;35"), + (".avi", "01;35"), + (".fli", "01;35"), + (".flv", "01;35"), + (".gl", "01;35"), + (".dl", "01;35"), + (".xcf", "01;35"), + (".xwd", "01;35"), + (".yuv", "01;35"), + (".cgm", "01;35"), + (".emf", "01;35"), + (".ogv", "01;35"), + (".ogx", "01;35"), + // Audio formats + (".aac", "00;36"), + (".au", "00;36"), + (".flac", "00;36"), + (".m4a", "00;36"), + (".mid", "00;36"), + (".midi", "00;36"), + (".mka", "00;36"), + (".mp3", "00;36"), + (".mpc", "00;36"), + (".ogg", "00;36"), + (".ra", "00;36"), + (".wav", "00;36"), + (".oga", "00;36"), + (".opus", "00;36"), + (".spx", "00;36"), + (".xspf", "00;36"), + // Backup files + ("*~", "00;90"), + ("*#", "00;90"), + (".bak", "00;90"), + (".old", "00;90"), + (".orig", "00;90"), + (".part", "00;90"), + (".rej", "00;90"), + (".swp", "00;90"), + (".tmp", "00;90"), + (".dpkg-dist", "00;90"), + (".dpkg-old", "00;90"), + (".ucf-dist", "00;90"), + (".ucf-new", "00;90"), + (".ucf-old", "00;90"), + (".rpmnew", "00;90"), + (".rpmorig", "00;90"), + (".rpmsave", "00;90"), + ] + .iter() + .for_each(|&(k, v)| { + m.insert(k, v); + }); + m +}); + +pub static FILE_ATTRIBUTE_CODES: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + [ + ("normal", "no"), + ("norm", "no"), + ("file", "fi"), + ("reset", "rs"), + ("dir", "di"), + ("lnk", "ln"), + ("link", "ln"), + ("symlink", "ln"), + ("orphan", "or"), + ("missing", "mi"), + ("fifo", "pi"), + ("pipe", "pi"), + ("sock", "so"), + ("blk", "bd"), + ("block", "bd"), + ("chr", "cd"), + ("char", "cd"), + ("door", "do"), + ("exec", "ex"), + ("left", "lc"), + ("leftcode", "lc"), + ("right", "rc"), + ("rightcode", "rc"), + ("end", "ec"), + ("endcode", "ec"), + ("suid", "su"), + ("setuid", "su"), + ("sgid", "sg"), + ("setgid", "sg"), + ("sticky", "st"), + ("other_writable", "ow"), + ("owr", "ow"), + ("sticky_other_writable", "tw"), + ("owt", "tw"), + ("capability", "ca"), + ("multihardlink", "mh"), + ("clrtoeol", "cl"), + ] + .iter() + .for_each(|&(k, v)| { + m.insert(k, v); + }); + m +}); diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index af8668ef0..426b4216c 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -35,6 +35,8 @@ pub use crate::parser::shortcut_value_parser; // * feature-gated modules #[cfg(feature = "backup-control")] pub use crate::features::backup_control; +#[cfg(feature = "colors")] +pub use crate::features::colors; #[cfg(feature = "encoding")] pub use crate::features::encoding; #[cfg(feature = "format")] From 5d19f79cd0b791bf28c9c8d9d8f4fd61817f6026 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 2 Dec 2023 12:57:38 +0100 Subject: [PATCH 07/52] dircolors should use the datastructures when printing --- src/uu/dircolors/src/dircolors.rs | 119 ++++++++++++++++++++++---- src/uucore/src/lib/features/colors.rs | 89 +++++++------------ 2 files changed, 134 insertions(+), 74 deletions(-) diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index 58228ddeb..43e35c3d2 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -12,7 +12,7 @@ use std::io::{BufRead, BufReader}; use std::path::Path; use clap::{crate_version, Arg, ArgAction, Command}; -use uucore::colors::FILE_ATTRIBUTE_CODES; +use uucore::colors::{FILE_ATTRIBUTE_CODES, FILE_COLORS, FILE_TYPES}; use uucore::display::Quotable; use uucore::error::{UResult, USimpleError, UUsageError}; use uucore::{help_about, help_section, help_usage}; @@ -58,6 +58,89 @@ pub fn guess_syntax() -> OutputFmt { } } +fn get_colors_format_strings(fmt: &OutputFmt) -> (String, String) { + let prefix = match fmt { + OutputFmt::Shell => "LS_COLORS='".to_string(), + OutputFmt::CShell => "setenv LS_COLORS '".to_string(), + OutputFmt::Display => String::new(), + OutputFmt::Unknown => unreachable!(), + }; + + let suffix = match fmt { + OutputFmt::Shell => "';\nexport LS_COLORS".to_string(), + OutputFmt::CShell => "'".to_string(), + OutputFmt::Display => String::new(), + OutputFmt::Unknown => unreachable!(), + }; + + (prefix, suffix) +} + +pub fn generate_type_output(fmt: &OutputFmt) -> String { + match fmt { + OutputFmt::Display => FILE_TYPES + .iter() + .map(|&(_, key, val)| format!("\x1b[{}m{}\t{}\x1b[0m", val, key, val)) + .collect::>() + .join("\n"), + _ => { + // Existing logic for other formats + FILE_TYPES + .iter() + .map(|&(_, v1, v2)| format!("{}={}", v1, v2)) + .collect::>() + .join(":") + } + } +} + +enum ExtensionFormat { + StarDot, // Format as ".*ext" + Dot, // Format as ".ext" + NoDot, // Format as "ext" +} + +fn generate_ls_colors(fmt: &OutputFmt, format: ExtensionFormat, sep: &str) -> String { + match fmt { + OutputFmt::Display => { + let mut display_parts = vec![]; + let type_output = generate_type_output(fmt); + display_parts.push(type_output); + for &(extension, code) in FILE_COLORS.iter() { + display_parts.push(format!("\x1b[{}m*{}\t{}\x1b[0m", code, extension, code)); + } + display_parts.join("\n") + } + _ => { + // existing logic for other formats + let mut parts = vec![]; + for &(extension, code) in FILE_COLORS.iter() { + let formatted_extension = match format { + ExtensionFormat::StarDot => format!("*{}", extension), + ExtensionFormat::Dot => extension.to_string(), + ExtensionFormat::NoDot => { + if extension.starts_with('.') { + extension[1..].to_string() + } else { + extension.to_string() + } + } + }; + parts.push(format!("{}={}", formatted_extension, code)); + } + let (prefix, suffix) = get_colors_format_strings(&fmt); + let ls_colors = parts.join(sep); + format!( + "{}{}:{}:{}", + prefix, + generate_type_output(&fmt), + ls_colors, + suffix + ) + } + } +} + #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { let args = args.collect_ignore(); @@ -126,7 +209,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let result; if files.is_empty() { - result = parse(INTERNAL_DB.lines(), &out_format, ""); + println!( + "{}", + generate_ls_colors(&out_format, ExtensionFormat::StarDot, ":") + ); + + return Ok(()); } else if files.len() > 1 { return Err(UUsageError::new( 1, @@ -287,12 +375,9 @@ where { // 1790 > $(dircolors | wc -m) let mut result = String::with_capacity(1790); - match fmt { - OutputFmt::Shell => result.push_str("LS_COLORS='"), - OutputFmt::CShell => result.push_str("setenv LS_COLORS '"), - OutputFmt::Display => (), - OutputFmt::Unknown => unreachable!(), - } + let (prefix, suffix) = get_colors_format_strings(&fmt); + + result.push_str(&prefix); let term = env::var("TERM").unwrap_or_else(|_| "none".to_owned()); let term = term.as_str(); @@ -331,6 +416,7 @@ where state = ParseState::Continue; } if state != ParseState::Pass { + let search_key = lower.as_str(); if key.starts_with('.') { if *fmt == OutputFmt::Display { result.push_str(format!("\x1b[{val}m*{key}\t{val}\x1b[0m\n").as_str()); @@ -345,7 +431,10 @@ where } } else if lower == "options" || lower == "color" || lower == "eightbit" { // Slackware only. Ignore - } else if let Some(s) = FILE_ATTRIBUTE_CODES.get(lower.as_str()) { + } else if let Some((_, s)) = FILE_ATTRIBUTE_CODES + .iter() + .find(|&&(key, _)| key == search_key) + { if *fmt == OutputFmt::Display { result.push_str(format!("\x1b[{val}m{s}\t{val}\x1b[0m\n").as_str()); } else { @@ -363,15 +452,11 @@ where } } - match fmt { - OutputFmt::Shell => result.push_str("';\nexport LS_COLORS"), - OutputFmt::CShell => result.push('\''), - OutputFmt::Display => { - // remove latest "\n" - result.pop(); - } - OutputFmt::Unknown => unreachable!(), + if fmt == &OutputFmt::Display { + // remove latest "\n" + result.pop(); } + result.push_str(&suffix); Ok(result) } diff --git a/src/uucore/src/lib/features/colors.rs b/src/uucore/src/lib/features/colors.rs index 69be16ba2..96ca6d456 100644 --- a/src/uucore/src/lib/features/colors.rs +++ b/src/uucore/src/lib/features/colors.rs @@ -4,19 +4,15 @@ // file that was distributed with this source code. use once_cell::sync::Lazy; -use std::collections::HashMap; /* The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the * slackware version of dircolors) are recognized but ignored. * Global config options can be specified before TERM or COLORTERM entries * below are TERM or COLORTERM entries, which can be glob patterns, which * restrict following config to systems with matching environment variables. - * COLORTERM ?* */ - -pub static TERMS: Lazy> = Lazy::new(|| { - let mut m = HashMap::new(); - [ +pub static TERMS: Lazy> = Lazy::new(|| { + vec![ "Eterm", "ansi", "*color*", @@ -43,11 +39,6 @@ pub static TERMS: Lazy> = Lazy::new(|| { "vt100", "xterm*", ] - .iter() - .for_each(|&term| { - m.insert(term, ""); - }); - m }); /* @@ -64,34 +55,27 @@ pub static TERMS: Lazy> = Lazy::new(|| { #NORMAL 00 # no color code at all #FILE 00 # regular file: use no color at all */ -// FILE_TYPES with Lazy initialization -pub static FILE_TYPES: Lazy> = Lazy::new(|| { - let mut m = HashMap::new(); - [ - ("RESET", "0"), // reset to "normal" color - ("DIR", "01;34"), // directory - ("LINK", "01;36"), // symbolic link - ("MULTIHARDLINK", "00"), // regular file with more than one link - ("FIFO", "40;33"), // pipe - ("SOCK", "01;35"), // socket - ("DOOR", "01;35"), // door - ("BLK", "40;33;01"), // block device driver - ("CHR", "40;33;01"), // character device driver - ("ORPHAN", "40;31;01"), // symlink to nonexistent file, or non-stat'able file - ("MISSING", "00"), // ... and the files they point to - ("SETUID", "37;41"), // file that is setuid (u+s) - ("SETGID", "30;43"), // file that is setgid (g+s) - ("CAPABILITY", "00"), // file with capability - ("STICKY_OTHER_WRITABLE", "30;42"), // dir that is sticky and other-writable (+t,o+w) - ("OTHER_WRITABLE", "34;42"), // dir that is other-writable (o+w) and not sticky - ("STICKY", "37;44"), // dir with the sticky bit set (+t) and not other-writable - ("EXEC", "01;32"), // files with execute permission +pub static FILE_TYPES: Lazy> = Lazy::new(|| { + vec![ + ("RESET", "rs", "0"), // reset to "normal" color + ("DIR", "di", "01;34"), // directory + ("LINK", "ln", "01;36"), // symbolic link + ("MULTIHARDLINK", "mh", "00"), // regular file with more than one link + ("FIFO", "pi", "40;33"), // pipe + ("SOCK", "so", "01;35"), // socket + ("DOOR", "do", "01;35"), // door + ("BLK", "bd", "40;33;01"), // block device driver + ("CHR", "cd", "40;33;01"), // character device driver + ("ORPHAN", "or", "40;31;01"), // symlink to nonexistent file, or non-stat'able file + ("MISSING", "mi", "00"), // ... and the files they point to + ("SETUID", "su", "37;41"), // file that is setuid (u+s) + ("SETGID", "sg", "30;43"), // file that is setgid (g+s) + ("CAPABILITY", "ca", "00"), // file with capability + ("STICKY_OTHER_WRITABLE", "tw", "30;42"), // dir that is sticky and other-writable (+t,o+w) + ("OTHER_WRITABLE", "ow", "34;42"), // dir that is other-writable (o+w) and not sticky + ("STICKY", "st", "37;44"), // dir with the sticky bit set (+t) and not other-writable + ("EXEC", "ex", "01;32"), // files with execute permission ] - .iter() - .for_each(|&(k, v)| { - m.insert(k, v); - }); - m }); /* @@ -99,9 +83,9 @@ pub static FILE_TYPES: Lazy> = Lazy::new(|| { # to color below. Put the extension, a space, and the color init string. # (and any comments you want to add after a '#') */ -pub static FILE_COLORS: Lazy> = Lazy::new(|| { - let mut m = HashMap::new(); - [ +pub static FILE_COLORS: Lazy> = Lazy::new(|| { + vec![ + /* // Executables (Windows) (".cmd", "01;32"), (".exe", "01;32"), @@ -109,7 +93,7 @@ pub static FILE_COLORS: Lazy> = Lazy::new(|| { (".btm", "01;32"), (".bat", "01;32"), (".sh", "01;32"), - (".csh", "01;32"), + (".csh", "01;32"),*/ // Archives or compressed (".tar", "01;31"), (".tgz", "01;31"), @@ -207,6 +191,7 @@ pub static FILE_COLORS: Lazy> = Lazy::new(|| { (".yuv", "01;35"), (".cgm", "01;35"), (".emf", "01;35"), + // https://wiki.xiph.org/MIME_Types_and_File_Extensions (".ogv", "01;35"), (".ogx", "01;35"), // Audio formats @@ -222,13 +207,14 @@ pub static FILE_COLORS: Lazy> = Lazy::new(|| { (".ogg", "00;36"), (".ra", "00;36"), (".wav", "00;36"), + // https://wiki.xiph.org/MIME_Types_and_File_Extensions (".oga", "00;36"), (".opus", "00;36"), (".spx", "00;36"), (".xspf", "00;36"), // Backup files - ("*~", "00;90"), - ("*#", "00;90"), + ("~", "00;90"), + ("#", "00;90"), (".bak", "00;90"), (".old", "00;90"), (".orig", "00;90"), @@ -245,16 +231,10 @@ pub static FILE_COLORS: Lazy> = Lazy::new(|| { (".rpmorig", "00;90"), (".rpmsave", "00;90"), ] - .iter() - .for_each(|&(k, v)| { - m.insert(k, v); - }); - m }); -pub static FILE_ATTRIBUTE_CODES: Lazy> = Lazy::new(|| { - let mut m = HashMap::new(); - [ +pub static FILE_ATTRIBUTE_CODES: Lazy> = Lazy::new(|| { + vec![ ("normal", "no"), ("norm", "no"), ("file", "fi"), @@ -293,9 +273,4 @@ pub static FILE_ATTRIBUTE_CODES: Lazy> = Lazy::new(|| { ("multihardlink", "mh"), ("clrtoeol", "cl"), ] - .iter() - .for_each(|&(k, v)| { - m.insert(k, v); - }); - m }); From e4b875043429ac78f4ae4b2824caea3e8d180244 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 2 Dec 2023 15:06:09 +0100 Subject: [PATCH 08/52] dircolors -p: generate it dynamically --- src/uu/dircolors/src/colors.rs | 225 --------------------- src/uu/dircolors/src/dircolors.rs | 65 +++++- tests/fixtures/dircolors/internal.expected | 60 ++---- 3 files changed, 75 insertions(+), 275 deletions(-) delete mode 100644 src/uu/dircolors/src/colors.rs diff --git a/src/uu/dircolors/src/colors.rs b/src/uu/dircolors/src/colors.rs deleted file mode 100644 index c0a981db8..000000000 --- a/src/uu/dircolors/src/colors.rs +++ /dev/null @@ -1,225 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. -// spell-checker:ignore (ToDO) EIGHTBIT ETERM MULTIHARDLINK cpio dtterm jfbterm konsole kterm mlterm rmvb rxvt stat'able svgz tmux webm xspf COLORTERM tzst avif tzst mjpg mjpeg webp dpkg rpmnew rpmorig rpmsave - -pub const INTERNAL_DB: &str = r#"# Configuration file for dircolors, a utility to help you set the -# LS_COLORS environment variable used by GNU ls with the --color option. -# Copyright (C) 1996-2022 Free Software Foundation, Inc. -# Copying and distribution of this file, with or without modification, -# are permitted provided the copyright notice and this notice are preserved. -# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the -# slackware version of dircolors) are recognized but ignored. -# Global config options can be specified before TERM or COLORTERM entries -# Below are TERM or COLORTERM entries, which can be glob patterns, which -# restrict following config to systems with matching environment variables. -COLORTERM ?* -TERM Eterm -TERM ansi -TERM *color* -TERM con[0-9]*x[0-9]* -TERM cons25 -TERM console -TERM cygwin -TERM *direct* -TERM dtterm -TERM gnome -TERM hurd -TERM jfbterm -TERM konsole -TERM kterm -TERM linux -TERM linux-c -TERM mlterm -TERM putty -TERM rxvt* -TERM screen* -TERM st -TERM terminator -TERM tmux* -TERM vt100 -TERM xterm* -# Below are the color init strings for the basic file types. -# One can use codes for 256 or more colors supported by modern terminals. -# The default color codes use the capabilities of an 8 color terminal -# with some additional attributes as per the following codes: -# Attribute codes: -# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed -# Text color codes: -# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white -# Background color codes: -# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white -#NORMAL 00 # no color code at all -#FILE 00 # regular file: use no color at all -RESET 0 # reset to "normal" color -DIR 01;34 # directory -LINK 01;36 # symbolic link. (If you set this to 'target' instead of a - # numerical value, the color is as for the file pointed to.) -MULTIHARDLINK 00 # regular file with more than one link -FIFO 40;33 # pipe -SOCK 01;35 # socket -DOOR 01;35 # door -BLK 40;33;01 # block device driver -CHR 40;33;01 # character device driver -ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... -MISSING 00 # ... and the files they point to -SETUID 37;41 # file that is setuid (u+s) -SETGID 30;43 # file that is setgid (g+s) -CAPABILITY 00 # file with capability (very expensive to lookup) -STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) -OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky -STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable -# This is for files with execute permission: -EXEC 01;32 -# List any file extensions like '.gz' or '.tar' that you would like ls -# to color below. Put the extension, a space, and the color init string. -# (and any comments you want to add after a '#') -# If you use DOS-style suffixes, you may want to uncomment the following: -#.cmd 01;32 # executables (bright green) -#.exe 01;32 -#.com 01;32 -#.btm 01;32 -#.bat 01;32 -# Or if you want to color scripts even if they do not have the -# executable bit actually set. -#.sh 01;32 -#.csh 01;32 - # archives or compressed (bright red) -.tar 01;31 -.tgz 01;31 -.arc 01;31 -.arj 01;31 -.taz 01;31 -.lha 01;31 -.lz4 01;31 -.lzh 01;31 -.lzma 01;31 -.tlz 01;31 -.txz 01;31 -.tzo 01;31 -.t7z 01;31 -.zip 01;31 -.z 01;31 -.dz 01;31 -.gz 01;31 -.lrz 01;31 -.lz 01;31 -.lzo 01;31 -.xz 01;31 -.zst 01;31 -.tzst 01;31 -.bz2 01;31 -.bz 01;31 -.tbz 01;31 -.tbz2 01;31 -.tz 01;31 -.deb 01;31 -.rpm 01;31 -.jar 01;31 -.war 01;31 -.ear 01;31 -.sar 01;31 -.rar 01;31 -.alz 01;31 -.ace 01;31 -.zoo 01;31 -.cpio 01;31 -.7z 01;31 -.rz 01;31 -.cab 01;31 -.wim 01;31 -.swm 01;31 -.dwm 01;31 -.esd 01;31 -# image formats -.avif 01;35 -.jpg 01;35 -.jpeg 01;35 -.mjpg 01;35 -.mjpeg 01;35 -.gif 01;35 -.bmp 01;35 -.pbm 01;35 -.pgm 01;35 -.ppm 01;35 -.tga 01;35 -.xbm 01;35 -.xpm 01;35 -.tif 01;35 -.tiff 01;35 -.png 01;35 -.svg 01;35 -.svgz 01;35 -.mng 01;35 -.pcx 01;35 -.mov 01;35 -.mpg 01;35 -.mpeg 01;35 -.m2v 01;35 -.mkv 01;35 -.webm 01;35 -.webp 01;35 -.ogm 01;35 -.mp4 01;35 -.m4v 01;35 -.mp4v 01;35 -.vob 01;35 -.qt 01;35 -.nuv 01;35 -.wmv 01;35 -.asf 01;35 -.rm 01;35 -.rmvb 01;35 -.flc 01;35 -.avi 01;35 -.fli 01;35 -.flv 01;35 -.gl 01;35 -.dl 01;35 -.xcf 01;35 -.xwd 01;35 -.yuv 01;35 -.cgm 01;35 -.emf 01;35 -# https://wiki.xiph.org/MIME_Types_and_File_Extensions -.ogv 01;35 -.ogx 01;35 -# audio formats -.aac 00;36 -.au 00;36 -.flac 00;36 -.m4a 00;36 -.mid 00;36 -.midi 00;36 -.mka 00;36 -.mp3 00;36 -.mpc 00;36 -.ogg 00;36 -.ra 00;36 -.wav 00;36 -# https://wiki.xiph.org/MIME_Types_and_File_Extensions -.oga 00;36 -.opus 00;36 -.spx 00;36 -.xspf 00;36 -# backup files -*~ 00;90 -*# 00;90 -.bak 00;90 -.old 00;90 -.orig 00;90 -.part 00;90 -.rej 00;90 -.swp 00;90 -.tmp 00;90 -.dpkg-dist 00;90 -.dpkg-old 00;90 -.ucf-dist 00;90 -.ucf-new 00;90 -.ucf-old 00;90 -.rpmnew 00;90 -.rpmorig 00;90 -.rpmsave 00;90 -# Subsequent TERM or COLORTERM entries, can be used to add / override -# config specific to those matching environment variables."#; diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index 43e35c3d2..338bf83e5 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -10,9 +10,10 @@ use std::env; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::Path; +use std::fmt::Write; use clap::{crate_version, Arg, ArgAction, Command}; -use uucore::colors::{FILE_ATTRIBUTE_CODES, FILE_COLORS, FILE_TYPES}; +use uucore::colors::{FILE_ATTRIBUTE_CODES, FILE_COLORS, FILE_TYPES, TERMS}; use uucore::display::Quotable; use uucore::error::{UResult, USimpleError, UUsageError}; use uucore::{help_about, help_section, help_usage}; @@ -29,9 +30,6 @@ const USAGE: &str = help_usage!("dircolors.md"); const ABOUT: &str = help_about!("dircolors.md"); const AFTER_HELP: &str = help_section!("after help", "dircolors.md"); -mod colors; -use self::colors::INTERNAL_DB; - #[derive(PartialEq, Eq, Debug)] pub enum OutputFmt { Shell, @@ -181,7 +179,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { ), )); } - println!("{INTERNAL_DB}"); + + println!("{}", generate_dircolors_config()); return Ok(()); } @@ -222,6 +221,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { )); } else if files[0].eq("-") { let fin = BufReader::new(std::io::stdin()); + // For example, for echo "owt 40;33"|dircolors -b - result = parse(fin.lines().map_while(Result::ok), &out_format, files[0]); } else { let path = Path::new(files[0]); @@ -368,7 +368,7 @@ enum ParseState { use uucore::{format_usage, parse_glob}; #[allow(clippy::cognitive_complexity)] -fn parse(lines: T, fmt: &OutputFmt, fp: &str) -> Result +fn parse(user_input: T, fmt: &OutputFmt, fp: &str) -> Result where T: IntoIterator, T::Item: Borrow, @@ -384,7 +384,7 @@ where let mut state = ParseState::Global; - for (num, line) in lines.into_iter().enumerate() { + for (num, line) in user_input.into_iter().enumerate() { let num = num + 1; let line = line.borrow().purify(); if line.is_empty() { @@ -396,13 +396,12 @@ where let (key, val) = line.split_two(); if val.is_empty() { return Err(format!( - "{}:{}: invalid line; missing second token", + "{}:{}: invalid line; missing second token", fp.maybe_quote(), num )); } let lower = key.to_lowercase(); - if lower == "term" || lower == "colorterm" { if term.fnmatch(val) { state = ParseState::Matched; @@ -417,6 +416,7 @@ where } if state != ParseState::Pass { let search_key = lower.as_str(); + if key.starts_with('.') { if *fmt == OutputFmt::Display { result.push_str(format!("\x1b[{val}m*{key}\t{val}\x1b[0m\n").as_str()); @@ -482,6 +482,53 @@ fn escape(s: &str) -> String { result } + +pub fn generate_dircolors_config() -> String { + let mut config = String::new(); + + // Adding the complete header comments as in the original file + writeln!(config, "# Configuration file for dircolors, a utility to help you set the").unwrap(); + writeln!(config, "# LS_COLORS environment variable used by GNU ls with the --color option.").unwrap(); + writeln!(config, "# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the").unwrap(); + writeln!(config, "# slackware version of dircolors) are recognized but ignored.").unwrap(); + writeln!(config, "# Global config options can be specified before TERM or COLORTERM entries").unwrap(); + writeln!(config, "# Below are TERM or COLORTERM entries, which can be glob patterns, which").unwrap(); + writeln!(config, "# restrict following config to systems with matching environment variables.").unwrap(); + writeln!(config, "COLORTERM ?*").unwrap(); + for term in TERMS.iter() { + writeln!(config, "TERM {}", term).unwrap(); + } + + // Adding file types and their color codes with header + writeln!(config, "# Below are the color init strings for the basic file types.").unwrap(); + writeln!(config, "# One can use codes for 256 or more colors supported by modern terminals.").unwrap(); + writeln!(config, "# The default color codes use the capabilities of an 8 color terminal").unwrap(); + writeln!(config, "# with some additional attributes as per the following codes:").unwrap(); + writeln!(config, "# Attribute codes:").unwrap(); + writeln!(config, "# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed").unwrap(); + writeln!(config, "# Text color codes:").unwrap(); + writeln!(config, "# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white").unwrap(); + writeln!(config, "# Background color codes:").unwrap(); + writeln!(config, "# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white").unwrap(); + writeln!(config, "#NORMAL 00 # no color code at all").unwrap(); + writeln!(config, "#FILE 00 # regular file: use no color at all").unwrap(); + + for (name, _, code) in FILE_TYPES.iter() { + writeln!(config, "{} {}", name, code).unwrap(); + } + + writeln!(config, "# List any file extensions like '.gz' or '.tar' that you would like ls").unwrap(); + writeln!(config, "# to color below. Put the extension, a space, and the color init string.").unwrap(); + + for (ext, color) in FILE_COLORS.iter() { + writeln!(config, "{} {}", ext, color).unwrap(); + } + writeln!(config, "# Subsequent TERM or COLORTERM entries, can be used to add / override").unwrap(); + write!(config, "# config specific to those matching environment variables.").unwrap(); + + config +} + #[cfg(test)] mod tests { use super::escape; diff --git a/tests/fixtures/dircolors/internal.expected b/tests/fixtures/dircolors/internal.expected index 7bc91ef47..933e70bc4 100644 --- a/tests/fixtures/dircolors/internal.expected +++ b/tests/fixtures/dircolors/internal.expected @@ -1,8 +1,5 @@ # Configuration file for dircolors, a utility to help you set the # LS_COLORS environment variable used by GNU ls with the --color option. -# Copyright (C) 1996-2022 Free Software Foundation, Inc. -# Copying and distribution of this file, with or without modification, -# are permitted provided the copyright notice and this notice are preserved. # The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the # slackware version of dircolors) are recognized but ignored. # Global config options can be specified before TERM or COLORTERM entries @@ -46,40 +43,26 @@ TERM xterm* # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white #NORMAL 00 # no color code at all #FILE 00 # regular file: use no color at all -RESET 0 # reset to "normal" color -DIR 01;34 # directory -LINK 01;36 # symbolic link. (If you set this to 'target' instead of a - # numerical value, the color is as for the file pointed to.) -MULTIHARDLINK 00 # regular file with more than one link -FIFO 40;33 # pipe -SOCK 01;35 # socket -DOOR 01;35 # door -BLK 40;33;01 # block device driver -CHR 40;33;01 # character device driver -ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... -MISSING 00 # ... and the files they point to -SETUID 37;41 # file that is setuid (u+s) -SETGID 30;43 # file that is setgid (g+s) -CAPABILITY 00 # file with capability (very expensive to lookup) -STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) -OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky -STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable -# This is for files with execute permission: +RESET 0 +DIR 01;34 +LINK 01;36 +MULTIHARDLINK 00 +FIFO 40;33 +SOCK 01;35 +DOOR 01;35 +BLK 40;33;01 +CHR 40;33;01 +ORPHAN 40;31;01 +MISSING 00 +SETUID 37;41 +SETGID 30;43 +CAPABILITY 00 +STICKY_OTHER_WRITABLE 30;42 +OTHER_WRITABLE 34;42 +STICKY 37;44 EXEC 01;32 # List any file extensions like '.gz' or '.tar' that you would like ls # to color below. Put the extension, a space, and the color init string. -# (and any comments you want to add after a '#') -# If you use DOS-style suffixes, you may want to uncomment the following: -#.cmd 01;32 # executables (bright green) -#.exe 01;32 -#.com 01;32 -#.btm 01;32 -#.bat 01;32 -# Or if you want to color scripts even if they do not have the -# executable bit actually set. -#.sh 01;32 -#.csh 01;32 - # archives or compressed (bright red) .tar 01;31 .tgz 01;31 .arc 01;31 @@ -126,7 +109,6 @@ EXEC 01;32 .swm 01;31 .dwm 01;31 .esd 01;31 -# image formats .avif 01;35 .jpg 01;35 .jpeg 01;35 @@ -176,10 +158,8 @@ EXEC 01;32 .yuv 01;35 .cgm 01;35 .emf 01;35 -# https://wiki.xiph.org/MIME_Types_and_File_Extensions .ogv 01;35 .ogx 01;35 -# audio formats .aac 00;36 .au 00;36 .flac 00;36 @@ -192,14 +172,12 @@ EXEC 01;32 .ogg 00;36 .ra 00;36 .wav 00;36 -# https://wiki.xiph.org/MIME_Types_and_File_Extensions .oga 00;36 .opus 00;36 .spx 00;36 .xspf 00;36 -# backup files -*~ 00;90 -*# 00;90 +~ 00;90 +# 00;90 .bak 00;90 .old 00;90 .orig 00;90 From 1a4ca7e65dc6991f8584c6f03d493bace427ff2d Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 2 Dec 2023 15:18:20 +0100 Subject: [PATCH 09/52] fix clippy warnings --- src/uu/dircolors/src/dircolors.rs | 143 +++++++++++++++++--------- src/uucore/src/lib/features/colors.rs | 2 +- 2 files changed, 98 insertions(+), 47 deletions(-) diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index 338bf83e5..28d74775d 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -7,10 +7,10 @@ use std::borrow::Borrow; use std::env; +use std::fmt::Write; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::Path; -use std::fmt::Write; use clap::{crate_version, Arg, ArgAction, Command}; use uucore::colors::{FILE_ATTRIBUTE_CODES, FILE_COLORS, FILE_TYPES, TERMS}; @@ -92,13 +92,7 @@ pub fn generate_type_output(fmt: &OutputFmt) -> String { } } -enum ExtensionFormat { - StarDot, // Format as ".*ext" - Dot, // Format as ".ext" - NoDot, // Format as "ext" -} - -fn generate_ls_colors(fmt: &OutputFmt, format: ExtensionFormat, sep: &str) -> String { +fn generate_ls_colors(fmt: &OutputFmt, sep: &str) -> String { match fmt { OutputFmt::Display => { let mut display_parts = vec![]; @@ -113,25 +107,15 @@ fn generate_ls_colors(fmt: &OutputFmt, format: ExtensionFormat, sep: &str) -> St // existing logic for other formats let mut parts = vec![]; for &(extension, code) in FILE_COLORS.iter() { - let formatted_extension = match format { - ExtensionFormat::StarDot => format!("*{}", extension), - ExtensionFormat::Dot => extension.to_string(), - ExtensionFormat::NoDot => { - if extension.starts_with('.') { - extension[1..].to_string() - } else { - extension.to_string() - } - } - }; + let formatted_extension = format!("*{}", extension); parts.push(format!("{}={}", formatted_extension, code)); } - let (prefix, suffix) = get_colors_format_strings(&fmt); + let (prefix, suffix) = get_colors_format_strings(fmt); let ls_colors = parts.join(sep); format!( "{}{}:{}:{}", prefix, - generate_type_output(&fmt), + generate_type_output(fmt), ls_colors, suffix ) @@ -208,10 +192,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let result; if files.is_empty() { - println!( - "{}", - generate_ls_colors(&out_format, ExtensionFormat::StarDot, ":") - ); + println!("{}", generate_ls_colors(&out_format, ":")); return Ok(()); } else if files.len() > 1 { @@ -373,9 +354,8 @@ where T: IntoIterator, T::Item: Borrow, { - // 1790 > $(dircolors | wc -m) let mut result = String::with_capacity(1790); - let (prefix, suffix) = get_colors_format_strings(&fmt); + let (prefix, suffix) = get_colors_format_strings(fmt); result.push_str(&prefix); @@ -482,34 +462,89 @@ fn escape(s: &str) -> String { result } - pub fn generate_dircolors_config() -> String { let mut config = String::new(); // Adding the complete header comments as in the original file - writeln!(config, "# Configuration file for dircolors, a utility to help you set the").unwrap(); - writeln!(config, "# LS_COLORS environment variable used by GNU ls with the --color option.").unwrap(); - writeln!(config, "# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the").unwrap(); - writeln!(config, "# slackware version of dircolors) are recognized but ignored.").unwrap(); - writeln!(config, "# Global config options can be specified before TERM or COLORTERM entries").unwrap(); - writeln!(config, "# Below are TERM or COLORTERM entries, which can be glob patterns, which").unwrap(); - writeln!(config, "# restrict following config to systems with matching environment variables.").unwrap(); + writeln!( + config, + "# Configuration file for dircolors, a utility to help you set the" + ) + .unwrap(); + writeln!( + config, + "# LS_COLORS environment variable used by GNU ls with the --color option." + ) + .unwrap(); + writeln!( + config, + "# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the" + ) + .unwrap(); + writeln!( + config, + "# slackware version of dircolors) are recognized but ignored." + ) + .unwrap(); + writeln!( + config, + "# Global config options can be specified before TERM or COLORTERM entries" + ) + .unwrap(); + writeln!( + config, + "# Below are TERM or COLORTERM entries, which can be glob patterns, which" + ) + .unwrap(); + writeln!( + config, + "# restrict following config to systems with matching environment variables." + ) + .unwrap(); writeln!(config, "COLORTERM ?*").unwrap(); for term in TERMS.iter() { writeln!(config, "TERM {}", term).unwrap(); } // Adding file types and their color codes with header - writeln!(config, "# Below are the color init strings for the basic file types.").unwrap(); - writeln!(config, "# One can use codes for 256 or more colors supported by modern terminals.").unwrap(); - writeln!(config, "# The default color codes use the capabilities of an 8 color terminal").unwrap(); - writeln!(config, "# with some additional attributes as per the following codes:").unwrap(); + writeln!( + config, + "# Below are the color init strings for the basic file types." + ) + .unwrap(); + writeln!( + config, + "# One can use codes for 256 or more colors supported by modern terminals." + ) + .unwrap(); + writeln!( + config, + "# The default color codes use the capabilities of an 8 color terminal" + ) + .unwrap(); + writeln!( + config, + "# with some additional attributes as per the following codes:" + ) + .unwrap(); writeln!(config, "# Attribute codes:").unwrap(); - writeln!(config, "# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed").unwrap(); + writeln!( + config, + "# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed" + ) + .unwrap(); writeln!(config, "# Text color codes:").unwrap(); - writeln!(config, "# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white").unwrap(); + writeln!( + config, + "# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white" + ) + .unwrap(); writeln!(config, "# Background color codes:").unwrap(); - writeln!(config, "# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white").unwrap(); + writeln!( + config, + "# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white" + ) + .unwrap(); writeln!(config, "#NORMAL 00 # no color code at all").unwrap(); writeln!(config, "#FILE 00 # regular file: use no color at all").unwrap(); @@ -517,14 +552,30 @@ pub fn generate_dircolors_config() -> String { writeln!(config, "{} {}", name, code).unwrap(); } - writeln!(config, "# List any file extensions like '.gz' or '.tar' that you would like ls").unwrap(); - writeln!(config, "# to color below. Put the extension, a space, and the color init string.").unwrap(); + writeln!( + config, + "# List any file extensions like '.gz' or '.tar' that you would like ls" + ) + .unwrap(); + writeln!( + config, + "# to color below. Put the extension, a space, and the color init string." + ) + .unwrap(); for (ext, color) in FILE_COLORS.iter() { writeln!(config, "{} {}", ext, color).unwrap(); } - writeln!(config, "# Subsequent TERM or COLORTERM entries, can be used to add / override").unwrap(); - write!(config, "# config specific to those matching environment variables.").unwrap(); + writeln!( + config, + "# Subsequent TERM or COLORTERM entries, can be used to add / override" + ) + .unwrap(); + write!( + config, + "# config specific to those matching environment variables." + ) + .unwrap(); config } diff --git a/src/uucore/src/lib/features/colors.rs b/src/uucore/src/lib/features/colors.rs index 96ca6d456..81d117a50 100644 --- a/src/uucore/src/lib/features/colors.rs +++ b/src/uucore/src/lib/features/colors.rs @@ -2,7 +2,7 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. - +// cSpell:disable use once_cell::sync::Lazy; /* The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the From 0ea1a7cd88c2a6d02ff4c1e69f5a9fa70c9bc135 Mon Sep 17 00:00:00 2001 From: Nathan Houghton Date: Sat, 21 Oct 2023 20:22:25 -0700 Subject: [PATCH 10/52] tests/cp, tests/test: Don't attempt to set sticky file bit on FreeBSD On FreeBSD (and OpenBSD), only the superuser can set the file sticky bit. --- tests/by-util/test_cp.rs | 20 +++++++++++++++----- tests/by-util/test_test.rs | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 36bca68b0..37bec5222 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -13,7 +13,7 @@ use std::os::unix::fs; #[cfg(unix)] use std::os::unix::fs::MetadataExt; -#[cfg(all(unix, not(target_os = "freebsd")))] +#[cfg(unix)] use std::os::unix::fs::PermissionsExt; #[cfg(windows)] use std::os::windows::fs::symlink_file; @@ -2381,13 +2381,18 @@ fn test_copy_symlink_force() { } #[test] -#[cfg(all(unix, not(target_os = "freebsd")))] +#[cfg(unix)] fn test_no_preserve_mode() { use std::os::unix::prelude::MetadataExt; use uucore::mode::get_umask; - const PERMS_ALL: u32 = 0o7777; + const PERMS_ALL: u32 = if cfg!(target_os = "freebsd") { + // Only the superuser can set the sticky bit on a file. + 0o6777 + } else { + 0o7777 + }; let (at, mut ucmd) = at_and_ucmd!(); at.touch("file"); @@ -2407,11 +2412,16 @@ fn test_no_preserve_mode() { } #[test] -#[cfg(all(unix, not(target_os = "freebsd")))] +#[cfg(unix)] fn test_preserve_mode() { use std::os::unix::prelude::MetadataExt; - const PERMS_ALL: u32 = 0o7777; + const PERMS_ALL: u32 = if cfg!(target_os = "freebsd") { + // Only the superuser can set the sticky bit on a file. + 0o6777 + } else { + 0o7777 + }; let (at, mut ucmd) = at_and_ucmd!(); at.touch("file"); diff --git a/tests/by-util/test_test.rs b/tests/by-util/test_test.rs index 922d854c6..b91bc727d 100644 --- a/tests/by-util/test_test.rs +++ b/tests/by-util/test_test.rs @@ -553,7 +553,7 @@ fn test_nonexistent_file_is_not_symlink() { } #[test] -// FixME: freebsd fails with 'chmod: sticky_file: Inappropriate file type or format' +// Only the superuser is allowed to set the sticky bit on files on FreeBSD. // Windows has no concept of sticky bit #[cfg(not(any(windows, target_os = "freebsd")))] fn test_file_is_sticky() { From f4141100836ff382b1e217b96c278e1d47e01b74 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Dec 2023 12:49:28 +0000 Subject: [PATCH 11/52] chore(deps): update vmactions/freebsd-vm action to v1.0.3 --- .github/workflows/freebsd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index 02c0137e7..5261d103c 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -39,7 +39,7 @@ jobs: - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.3 - name: Prepare, build and test - uses: vmactions/freebsd-vm@v1.0.2 + uses: vmactions/freebsd-vm@v1.0.3 with: usesh: true sync: rsync @@ -131,7 +131,7 @@ jobs: - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.3 - name: Prepare, build and test - uses: vmactions/freebsd-vm@v1.0.2 + uses: vmactions/freebsd-vm@v1.0.3 with: usesh: true sync: rsync From 49fb72ed21ddcb709426159b1336edded3778164 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Sun, 3 Dec 2023 14:07:03 +0100 Subject: [PATCH 12/52] du: disable test on Android --- tests/by-util/test_du.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index c07de2851..10f32caf5 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -441,6 +441,7 @@ fn test_du_inodes() { } } +#[cfg(not(target_os = "android"))] #[test] fn test_du_inodes_with_count_links() { let ts = TestScenario::new(util_name!()); From a6d15d67caf13c86aa2973ea45a7ed7758c8f50b Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 1 Dec 2023 15:15:44 +0100 Subject: [PATCH 13/52] ls: cleanup "spell-checker:ignore" entries --- src/uu/ls/src/ls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index cba9cdf53..6e7fe405b 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) cpio svgz webm somegroup nlink rmvb xspf tabsize dired subdired dtype +// spell-checker:ignore (ToDO) somegroup nlink tabsize dired subdired dtype use clap::{ builder::{NonEmptyStringValueParser, ValueParser}, From c77d389f5b93399bdeb6007f24d745c94e64f454 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 1 Dec 2023 16:19:13 +0100 Subject: [PATCH 14/52] ls: improve some var names related to block sizes --- src/uu/ls/src/ls.rs | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 6e7fe405b..3745cfc9d 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -741,14 +741,14 @@ impl Config { let mut needs_color = extract_color(options); - let cmd_line_bs = options.get_one::(options::size::BLOCK_SIZE); - let opt_si = cmd_line_bs.is_some() + let opt_block_size = options.get_one::(options::size::BLOCK_SIZE); + let opt_si = opt_block_size.is_some() && options .get_one::(options::size::BLOCK_SIZE) .unwrap() .eq("si") || options.get_flag(options::size::SI); - let opt_hr = (cmd_line_bs.is_some() + let opt_hr = (opt_block_size.is_some() && options .get_one::(options::size::BLOCK_SIZE) .unwrap() @@ -756,9 +756,9 @@ impl Config { || options.get_flag(options::size::HUMAN_READABLE); let opt_kb = options.get_flag(options::size::KIBIBYTES); - let bs_env_var = std::env::var_os("BLOCK_SIZE"); - let ls_bs_env_var = std::env::var_os("LS_BLOCK_SIZE"); - let pc_env_var = std::env::var_os("POSIXLY_CORRECT"); + let env_var_block_size = std::env::var_os("BLOCK_SIZE"); + let env_var_ls_block_size = std::env::var_os("LS_BLOCK_SIZE"); + let env_var_posixly_correct = std::env::var_os("POSIXLY_CORRECT"); let size_format = if opt_si { SizeFormat::Decimal @@ -768,13 +768,13 @@ impl Config { SizeFormat::Bytes }; - let raw_bs = if let Some(cmd_line_bs) = cmd_line_bs { - OsString::from(cmd_line_bs) + let raw_block_size = if let Some(opt_block_size) = opt_block_size { + OsString::from(opt_block_size) } else if !opt_kb { - if let Some(ls_bs_env_var) = ls_bs_env_var { - ls_bs_env_var - } else if let Some(bs_env_var) = bs_env_var { - bs_env_var + if let Some(env_var_ls_block_size) = env_var_ls_block_size { + env_var_ls_block_size + } else if let Some(env_var_block_size) = env_var_block_size { + env_var_block_size } else { OsString::from("") } @@ -782,15 +782,17 @@ impl Config { OsString::from("") }; - let block_size: Option = if !opt_si && !opt_hr && !raw_bs.is_empty() { - match parse_size_u64(&raw_bs.to_string_lossy()) { + let block_size: Option = if !opt_si && !opt_hr && !raw_block_size.is_empty() { + match parse_size_u64(&raw_block_size.to_string_lossy()) { Ok(size) => Some(size), Err(_) => { - show!(LsError::BlockSizeParseError(cmd_line_bs.unwrap().clone())); + show!(LsError::BlockSizeParseError( + opt_block_size.unwrap().clone() + )); None } } - } else if let Some(pc) = pc_env_var { + } else if let Some(pc) = env_var_posixly_correct { if pc.as_os_str() == OsStr::new("true") || pc == OsStr::new("1") { Some(POSIXLY_CORRECT_BLOCK_SIZE) } else { From 51fc2d7564b29de22936e8ca4a73883aeca77662 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 1 Dec 2023 16:27:05 +0100 Subject: [PATCH 15/52] ls: ignore value of POSIXLY_CORRECT --- src/uu/ls/src/ls.rs | 10 +++------- tests/by-util/test_ls.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 3745cfc9d..f645e31d3 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -20,7 +20,7 @@ use std::os::windows::fs::MetadataExt; use std::{ cmp::Reverse, error::Error, - ffi::{OsStr, OsString}, + ffi::OsString, fmt::{Display, Write as FmtWrite}, fs::{self, DirEntry, FileType, Metadata, ReadDir}, io::{stdout, BufWriter, ErrorKind, Stdout, Write}, @@ -792,12 +792,8 @@ impl Config { None } } - } else if let Some(pc) = env_var_posixly_correct { - if pc.as_os_str() == OsStr::new("true") || pc == OsStr::new("1") { - Some(POSIXLY_CORRECT_BLOCK_SIZE) - } else { - None - } + } else if env_var_posixly_correct.is_some() { + Some(POSIXLY_CORRECT_BLOCK_SIZE) } else { None }; diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 19a3f5578..fcd57170d 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -3828,3 +3828,30 @@ fn test_ls_cf_output_should_be_delimited_by_tab() { .succeeds() .stdout_is("a2345/\tb/\n"); } + +#[cfg(all(unix, feature = "dd"))] +#[test] +fn test_posixly_correct() { + let scene = TestScenario::new(util_name!()); + + scene + .ccmd("dd") + .arg("if=/dev/zero") + .arg("of=file") + .arg("bs=1024") + .arg("count=1") + .succeeds(); + + scene + .ucmd() + .arg("-s") + .succeeds() + .stdout_contains_line("total 4"); + + scene + .ucmd() + .arg("-s") + .env("POSIXLY_CORRECT", "some_value") + .succeeds() + .stdout_contains_line("total 8"); +} From cf853df2dcf4309049ad3a0ff3ab531aabcb86ec Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Mon, 4 Dec 2023 14:48:25 +0100 Subject: [PATCH 16/52] ls: remove "#[allow(unused_variables)]" --- src/uu/ls/src/ls.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index cba9cdf53..626e17ca1 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -2946,7 +2946,6 @@ fn classify_file(path: &PathData, out: &mut BufWriter) -> Option { /// /// Note that non-unicode sequences in symlink targets are dealt with using /// [`std::path::Path::to_string_lossy`]. -#[allow(unused_variables)] #[allow(clippy::cognitive_complexity)] fn display_file_name( path: &PathData, From d4b22a192d9c4af1ed2b92c0b0197a790536e981 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 19:09:30 +0000 Subject: [PATCH 17/52] chore(deps): update vmactions/freebsd-vm action to v1.0.4 --- .github/workflows/freebsd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index 5261d103c..27537cf6d 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -39,7 +39,7 @@ jobs: - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.3 - name: Prepare, build and test - uses: vmactions/freebsd-vm@v1.0.3 + uses: vmactions/freebsd-vm@v1.0.4 with: usesh: true sync: rsync @@ -131,7 +131,7 @@ jobs: - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.3 - name: Prepare, build and test - uses: vmactions/freebsd-vm@v1.0.3 + uses: vmactions/freebsd-vm@v1.0.4 with: usesh: true sync: rsync From 9ef43191ff28af359989848dc65548aa253e4337 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 4 Dec 2023 21:20:47 +0100 Subject: [PATCH 18/52] Document that \0NNN and \xHH need more work --- fuzz/fuzz_targets/fuzz_echo.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/fuzz/fuzz_targets/fuzz_echo.rs b/fuzz/fuzz_targets/fuzz_echo.rs index 826fd6da3..fda7fd727 100644 --- a/fuzz/fuzz_targets/fuzz_echo.rs +++ b/fuzz/fuzz_targets/fuzz_echo.rs @@ -51,6 +51,7 @@ fn generate_escape_sequence(rng: &mut impl Rng) -> String { let escape_sequences = [ "\\\\", "\\a", "\\b", "\\c", "\\e", "\\f", "\\n", "\\r", "\\t", "\\v", "\\0NNN", "\\xHH", ]; + // \0NNN and \xHH need more work escape_sequences.choose(rng).unwrap().to_string() } From f5776bc511ec0fbe5dac93af190ef8a3c8d610be Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 4 Dec 2023 22:40:18 +0100 Subject: [PATCH 19/52] fix comment Co-authored-by: Terts Diepraam --- src/uucore/src/lib/features/colors.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/uucore/src/lib/features/colors.rs b/src/uucore/src/lib/features/colors.rs index 81d117a50..1f55db5a7 100644 --- a/src/uucore/src/lib/features/colors.rs +++ b/src/uucore/src/lib/features/colors.rs @@ -78,11 +78,11 @@ pub static FILE_TYPES: Lazy> = L ] }); -/* -# List any file extensions like '.gz' or '.tar' that you would like ls -# to color below. Put the extension, a space, and the color init string. -# (and any comments you want to add after a '#') -*/ +/// Colors for file types +/// +/// List any file extensions like '.gz' or '.tar' that you would like ls +/// to color below. Put the extension, a space, and the color init string. +/// (and any comments you want to add after a '#') pub static FILE_COLORS: Lazy> = Lazy::new(|| { vec![ /* From dabbcff9fbbbce7c0ec692431f73fb17657c8199 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 3 Dec 2023 10:34:33 +0100 Subject: [PATCH 20/52] dircolors: manage the --print-ls-colors pipe option --- src/uu/dircolors/src/dircolors.rs | 17 +++++++++++++---- tests/by-util/test_dircolors.rs | 10 ++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index 28d74775d..cf8ed6292 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -9,6 +9,7 @@ use std::borrow::Borrow; use std::env; use std::fmt::Write; use std::fs::File; +use std::io::IsTerminal; use std::io::{BufRead, BufReader}; use std::path::Path; @@ -192,9 +193,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let result; if files.is_empty() { - println!("{}", generate_ls_colors(&out_format, ":")); - - return Ok(()); + // Check if data is being piped into the program + if std::io::stdin().is_terminal() { + // No data piped, use default behavior + println!("{}", generate_ls_colors(&out_format, ":")); + return Ok(()); + } else { + // Data is piped, process the input from stdin + let fin = BufReader::new(std::io::stdin()); + result = parse(fin.lines().map_while(Result::ok), &out_format, "-"); + } } else if files.len() > 1 { return Err(UUsageError::new( 1, @@ -376,7 +384,8 @@ where let (key, val) = line.split_two(); if val.is_empty() { return Err(format!( - "{}:{}: invalid line; missing second token", + // The double space is what GNU is doing + "{}:{}: invalid line; missing second token", fp.maybe_quote(), num )); diff --git a/tests/by-util/test_dircolors.rs b/tests/by-util/test_dircolors.rs index d4fa0a3b0..e3752fcde 100644 --- a/tests/by-util/test_dircolors.rs +++ b/tests/by-util/test_dircolors.rs @@ -159,6 +159,16 @@ fn test_quoting() { .no_stderr(); } +#[test] +fn test_print_ls_colors() { + new_ucmd!() + .pipe_in("OWT 40;33\n") + .args(&["--print-ls-colors"]) + .succeeds() + .stdout_is("\x1B[40;33mtw\t40;33\x1B[0m\n") + .no_stderr(); +} + #[test] fn test_extra_operand() { new_ucmd!() From 3e354109076eb1f806715e0d5c89006fd2a1a12a Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 4 Dec 2023 22:47:42 +0100 Subject: [PATCH 21/52] dircolors: fix comments --- src/uucore/src/lib/features/colors.rs | 512 +++++++++++++------------- 1 file changed, 250 insertions(+), 262 deletions(-) diff --git a/src/uucore/src/lib/features/colors.rs b/src/uucore/src/lib/features/colors.rs index 1f55db5a7..81d2fd3f3 100644 --- a/src/uucore/src/lib/features/colors.rs +++ b/src/uucore/src/lib/features/colors.rs @@ -3,274 +3,262 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. // cSpell:disable -use once_cell::sync::Lazy; -/* The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the - * slackware version of dircolors) are recognized but ignored. - * Global config options can be specified before TERM or COLORTERM entries - * below are TERM or COLORTERM entries, which can be glob patterns, which - * restrict following config to systems with matching environment variables. -*/ -pub static TERMS: Lazy> = Lazy::new(|| { - vec![ - "Eterm", - "ansi", - "*color*", - "con[0-9]*x[0-9]*", - "cons25", - "console", - "cygwin", - "*direct*", - "dtterm", - "gnome", - "hurd", - "jfbterm", - "konsole", - "kterm", - "linux", - "linux-c", - "mlterm", - "putty", - "rxvt*", - "screen*", - "st", - "terminator", - "tmux*", - "vt100", - "xterm*", - ] -}); +/// The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the +/// slackware version of dircolors) are recognized but ignored. +/// Global config options can be specified before TERM or COLORTERM entries +/// below are TERM or COLORTERM entries, which can be glob patterns, which +/// restrict following config to systems with matching environment variables. +pub static TERMS: &[&str] = &[ + "Eterm", + "ansi", + "*color*", + "con[0-9]*x[0-9]*", + "cons25", + "console", + "cygwin", + "*direct*", + "dtterm", + "gnome", + "hurd", + "jfbterm", + "konsole", + "kterm", + "linux", + "linux-c", + "mlterm", + "putty", + "rxvt*", + "screen*", + "st", + "terminator", + "tmux*", + "vt100", + "xterm*", +]; -/* -# Below are the color init strings for the basic file types. -# One can use codes for 256 or more colors supported by modern terminals. -# The default color codes use the capabilities of an 8 color terminal -# with some additional attributes as per the following codes: -# Attribute codes: -# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed -# Text color codes: -# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white -# Background color codes: -# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white -#NORMAL 00 # no color code at all -#FILE 00 # regular file: use no color at all -*/ -pub static FILE_TYPES: Lazy> = Lazy::new(|| { - vec![ - ("RESET", "rs", "0"), // reset to "normal" color - ("DIR", "di", "01;34"), // directory - ("LINK", "ln", "01;36"), // symbolic link - ("MULTIHARDLINK", "mh", "00"), // regular file with more than one link - ("FIFO", "pi", "40;33"), // pipe - ("SOCK", "so", "01;35"), // socket - ("DOOR", "do", "01;35"), // door - ("BLK", "bd", "40;33;01"), // block device driver - ("CHR", "cd", "40;33;01"), // character device driver - ("ORPHAN", "or", "40;31;01"), // symlink to nonexistent file, or non-stat'able file - ("MISSING", "mi", "00"), // ... and the files they point to - ("SETUID", "su", "37;41"), // file that is setuid (u+s) - ("SETGID", "sg", "30;43"), // file that is setgid (g+s) - ("CAPABILITY", "ca", "00"), // file with capability - ("STICKY_OTHER_WRITABLE", "tw", "30;42"), // dir that is sticky and other-writable (+t,o+w) - ("OTHER_WRITABLE", "ow", "34;42"), // dir that is other-writable (o+w) and not sticky - ("STICKY", "st", "37;44"), // dir with the sticky bit set (+t) and not other-writable - ("EXEC", "ex", "01;32"), // files with execute permission - ] -}); +/// Below are the color init strings for the basic file types. +/// One can use codes for 256 or more colors supported by modern terminals. +/// The default color codes use the capabilities of an 8 color terminal +/// with some additional attributes as per the following codes: +/// Attribute codes: +/// 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +/// Text color codes: +/// 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +/// Background color codes: +/// 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +/// #NORMAL 00 /// no color code at all +/// #FILE 00 /// regular file: use no color at all +pub static FILE_TYPES: &[(&str, &str, &str)] = &[ + ("RESET", "rs", "0"), // reset to "normal" color + ("DIR", "di", "01;34"), // directory + ("LINK", "ln", "01;36"), // symbolic link + ("MULTIHARDLINK", "mh", "00"), // regular file with more than one link + ("FIFO", "pi", "40;33"), // pipe + ("SOCK", "so", "01;35"), // socket + ("DOOR", "do", "01;35"), // door + ("BLK", "bd", "40;33;01"), // block device driver + ("CHR", "cd", "40;33;01"), // character device driver + ("ORPHAN", "or", "40;31;01"), // symlink to nonexistent file, or non-stat'able file + ("MISSING", "mi", "00"), // ... and the files they point to + ("SETUID", "su", "37;41"), // file that is setuid (u+s) + ("SETGID", "sg", "30;43"), // file that is setgid (g+s) + ("CAPABILITY", "ca", "00"), // file with capability + ("STICKY_OTHER_WRITABLE", "tw", "30;42"), // dir that is sticky and other-writable (+t,o+w) + ("OTHER_WRITABLE", "ow", "34;42"), // dir that is other-writable (o+w) and not sticky + ("STICKY", "st", "37;44"), // dir with the sticky bit set (+t) and not other-writable + ("EXEC", "ex", "01;32"), // files with execute permission +]; /// Colors for file types /// /// List any file extensions like '.gz' or '.tar' that you would like ls /// to color below. Put the extension, a space, and the color init string. /// (and any comments you want to add after a '#') -pub static FILE_COLORS: Lazy> = Lazy::new(|| { - vec![ - /* - // Executables (Windows) - (".cmd", "01;32"), - (".exe", "01;32"), - (".com", "01;32"), - (".btm", "01;32"), - (".bat", "01;32"), - (".sh", "01;32"), - (".csh", "01;32"),*/ - // Archives or compressed - (".tar", "01;31"), - (".tgz", "01;31"), - (".arc", "01;31"), - (".arj", "01;31"), - (".taz", "01;31"), - (".lha", "01;31"), - (".lz4", "01;31"), - (".lzh", "01;31"), - (".lzma", "01;31"), - (".tlz", "01;31"), - (".txz", "01;31"), - (".tzo", "01;31"), - (".t7z", "01;31"), - (".zip", "01;31"), - (".z", "01;31"), - (".dz", "01;31"), - (".gz", "01;31"), - (".lrz", "01;31"), - (".lz", "01;31"), - (".lzo", "01;31"), - (".xz", "01;31"), - (".zst", "01;31"), - (".tzst", "01;31"), - (".bz2", "01;31"), - (".bz", "01;31"), - (".tbz", "01;31"), - (".tbz2", "01;31"), - (".tz", "01;31"), - (".deb", "01;31"), - (".rpm", "01;31"), - (".jar", "01;31"), - (".war", "01;31"), - (".ear", "01;31"), - (".sar", "01;31"), - (".rar", "01;31"), - (".alz", "01;31"), - (".ace", "01;31"), - (".zoo", "01;31"), - (".cpio", "01;31"), - (".7z", "01;31"), - (".rz", "01;31"), - (".cab", "01;31"), - (".wim", "01;31"), - (".swm", "01;31"), - (".dwm", "01;31"), - (".esd", "01;31"), - // Image formats - (".avif", "01;35"), - (".jpg", "01;35"), - (".jpeg", "01;35"), - (".mjpg", "01;35"), - (".mjpeg", "01;35"), - (".gif", "01;35"), - (".bmp", "01;35"), - (".pbm", "01;35"), - (".pgm", "01;35"), - (".ppm", "01;35"), - (".tga", "01;35"), - (".xbm", "01;35"), - (".xpm", "01;35"), - (".tif", "01;35"), - (".tiff", "01;35"), - (".png", "01;35"), - (".svg", "01;35"), - (".svgz", "01;35"), - (".mng", "01;35"), - (".pcx", "01;35"), - (".mov", "01;35"), - (".mpg", "01;35"), - (".mpeg", "01;35"), - (".m2v", "01;35"), - (".mkv", "01;35"), - (".webm", "01;35"), - (".webp", "01;35"), - (".ogm", "01;35"), - (".mp4", "01;35"), - (".m4v", "01;35"), - (".mp4v", "01;35"), - (".vob", "01;35"), - (".qt", "01;35"), - (".nuv", "01;35"), - (".wmv", "01;35"), - (".asf", "01;35"), - (".rm", "01;35"), - (".rmvb", "01;35"), - (".flc", "01;35"), - (".avi", "01;35"), - (".fli", "01;35"), - (".flv", "01;35"), - (".gl", "01;35"), - (".dl", "01;35"), - (".xcf", "01;35"), - (".xwd", "01;35"), - (".yuv", "01;35"), - (".cgm", "01;35"), - (".emf", "01;35"), - // https://wiki.xiph.org/MIME_Types_and_File_Extensions - (".ogv", "01;35"), - (".ogx", "01;35"), - // Audio formats - (".aac", "00;36"), - (".au", "00;36"), - (".flac", "00;36"), - (".m4a", "00;36"), - (".mid", "00;36"), - (".midi", "00;36"), - (".mka", "00;36"), - (".mp3", "00;36"), - (".mpc", "00;36"), - (".ogg", "00;36"), - (".ra", "00;36"), - (".wav", "00;36"), - // https://wiki.xiph.org/MIME_Types_and_File_Extensions - (".oga", "00;36"), - (".opus", "00;36"), - (".spx", "00;36"), - (".xspf", "00;36"), - // Backup files - ("~", "00;90"), - ("#", "00;90"), - (".bak", "00;90"), - (".old", "00;90"), - (".orig", "00;90"), - (".part", "00;90"), - (".rej", "00;90"), - (".swp", "00;90"), - (".tmp", "00;90"), - (".dpkg-dist", "00;90"), - (".dpkg-old", "00;90"), - (".ucf-dist", "00;90"), - (".ucf-new", "00;90"), - (".ucf-old", "00;90"), - (".rpmnew", "00;90"), - (".rpmorig", "00;90"), - (".rpmsave", "00;90"), - ] -}); +pub static FILE_COLORS: &[(&str, &str)] = &[ + /* + // Executables (Windows) + (".cmd", "01;32"), + (".exe", "01;32"), + (".com", "01;32"), + (".btm", "01;32"), + (".bat", "01;32"), + (".sh", "01;32"), + (".csh", "01;32"),*/ + // Archives or compressed + (".tar", "01;31"), + (".tgz", "01;31"), + (".arc", "01;31"), + (".arj", "01;31"), + (".taz", "01;31"), + (".lha", "01;31"), + (".lz4", "01;31"), + (".lzh", "01;31"), + (".lzma", "01;31"), + (".tlz", "01;31"), + (".txz", "01;31"), + (".tzo", "01;31"), + (".t7z", "01;31"), + (".zip", "01;31"), + (".z", "01;31"), + (".dz", "01;31"), + (".gz", "01;31"), + (".lrz", "01;31"), + (".lz", "01;31"), + (".lzo", "01;31"), + (".xz", "01;31"), + (".zst", "01;31"), + (".tzst", "01;31"), + (".bz2", "01;31"), + (".bz", "01;31"), + (".tbz", "01;31"), + (".tbz2", "01;31"), + (".tz", "01;31"), + (".deb", "01;31"), + (".rpm", "01;31"), + (".jar", "01;31"), + (".war", "01;31"), + (".ear", "01;31"), + (".sar", "01;31"), + (".rar", "01;31"), + (".alz", "01;31"), + (".ace", "01;31"), + (".zoo", "01;31"), + (".cpio", "01;31"), + (".7z", "01;31"), + (".rz", "01;31"), + (".cab", "01;31"), + (".wim", "01;31"), + (".swm", "01;31"), + (".dwm", "01;31"), + (".esd", "01;31"), + // Image formats + (".avif", "01;35"), + (".jpg", "01;35"), + (".jpeg", "01;35"), + (".mjpg", "01;35"), + (".mjpeg", "01;35"), + (".gif", "01;35"), + (".bmp", "01;35"), + (".pbm", "01;35"), + (".pgm", "01;35"), + (".ppm", "01;35"), + (".tga", "01;35"), + (".xbm", "01;35"), + (".xpm", "01;35"), + (".tif", "01;35"), + (".tiff", "01;35"), + (".png", "01;35"), + (".svg", "01;35"), + (".svgz", "01;35"), + (".mng", "01;35"), + (".pcx", "01;35"), + (".mov", "01;35"), + (".mpg", "01;35"), + (".mpeg", "01;35"), + (".m2v", "01;35"), + (".mkv", "01;35"), + (".webm", "01;35"), + (".webp", "01;35"), + (".ogm", "01;35"), + (".mp4", "01;35"), + (".m4v", "01;35"), + (".mp4v", "01;35"), + (".vob", "01;35"), + (".qt", "01;35"), + (".nuv", "01;35"), + (".wmv", "01;35"), + (".asf", "01;35"), + (".rm", "01;35"), + (".rmvb", "01;35"), + (".flc", "01;35"), + (".avi", "01;35"), + (".fli", "01;35"), + (".flv", "01;35"), + (".gl", "01;35"), + (".dl", "01;35"), + (".xcf", "01;35"), + (".xwd", "01;35"), + (".yuv", "01;35"), + (".cgm", "01;35"), + (".emf", "01;35"), + // https://wiki.xiph.org/MIME_Types_and_File_Extensions + (".ogv", "01;35"), + (".ogx", "01;35"), + // Audio formats + (".aac", "00;36"), + (".au", "00;36"), + (".flac", "00;36"), + (".m4a", "00;36"), + (".mid", "00;36"), + (".midi", "00;36"), + (".mka", "00;36"), + (".mp3", "00;36"), + (".mpc", "00;36"), + (".ogg", "00;36"), + (".ra", "00;36"), + (".wav", "00;36"), + // https://wiki.xiph.org/MIME_Types_and_File_Extensions + (".oga", "00;36"), + (".opus", "00;36"), + (".spx", "00;36"), + (".xspf", "00;36"), + // Backup files + ("~", "00;90"), + ("#", "00;90"), + (".bak", "00;90"), + (".old", "00;90"), + (".orig", "00;90"), + (".part", "00;90"), + (".rej", "00;90"), + (".swp", "00;90"), + (".tmp", "00;90"), + (".dpkg-dist", "00;90"), + (".dpkg-old", "00;90"), + (".ucf-dist", "00;90"), + (".ucf-new", "00;90"), + (".ucf-old", "00;90"), + (".rpmnew", "00;90"), + (".rpmorig", "00;90"), + (".rpmsave", "00;90"), +]; -pub static FILE_ATTRIBUTE_CODES: Lazy> = Lazy::new(|| { - vec![ - ("normal", "no"), - ("norm", "no"), - ("file", "fi"), - ("reset", "rs"), - ("dir", "di"), - ("lnk", "ln"), - ("link", "ln"), - ("symlink", "ln"), - ("orphan", "or"), - ("missing", "mi"), - ("fifo", "pi"), - ("pipe", "pi"), - ("sock", "so"), - ("blk", "bd"), - ("block", "bd"), - ("chr", "cd"), - ("char", "cd"), - ("door", "do"), - ("exec", "ex"), - ("left", "lc"), - ("leftcode", "lc"), - ("right", "rc"), - ("rightcode", "rc"), - ("end", "ec"), - ("endcode", "ec"), - ("suid", "su"), - ("setuid", "su"), - ("sgid", "sg"), - ("setgid", "sg"), - ("sticky", "st"), - ("other_writable", "ow"), - ("owr", "ow"), - ("sticky_other_writable", "tw"), - ("owt", "tw"), - ("capability", "ca"), - ("multihardlink", "mh"), - ("clrtoeol", "cl"), - ] -}); +pub static FILE_ATTRIBUTE_CODES: &[(&str, &str)] = &[ + ("normal", "no"), + ("norm", "no"), + ("file", "fi"), + ("reset", "rs"), + ("dir", "di"), + ("lnk", "ln"), + ("link", "ln"), + ("symlink", "ln"), + ("orphan", "or"), + ("missing", "mi"), + ("fifo", "pi"), + ("pipe", "pi"), + ("sock", "so"), + ("blk", "bd"), + ("block", "bd"), + ("chr", "cd"), + ("char", "cd"), + ("door", "do"), + ("exec", "ex"), + ("left", "lc"), + ("leftcode", "lc"), + ("right", "rc"), + ("rightcode", "rc"), + ("end", "ec"), + ("endcode", "ec"), + ("suid", "su"), + ("setuid", "su"), + ("sgid", "sg"), + ("setgid", "sg"), + ("sticky", "st"), + ("other_writable", "ow"), + ("owr", "ow"), + ("sticky_other_writable", "tw"), + ("owt", "tw"), + ("capability", "ca"), + ("multihardlink", "mh"), + ("clrtoeol", "cl"), +]; From 1c9413e185c8eb16175761b929a373578f0607e3 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 4 Dec 2023 22:51:08 +0100 Subject: [PATCH 22/52] bring back the old format --- src/uucore/src/lib/features/colors.rs | 4 ++-- tests/fixtures/dircolors/internal.expected | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/uucore/src/lib/features/colors.rs b/src/uucore/src/lib/features/colors.rs index 81d2fd3f3..e0de8b1e3 100644 --- a/src/uucore/src/lib/features/colors.rs +++ b/src/uucore/src/lib/features/colors.rs @@ -204,8 +204,8 @@ pub static FILE_COLORS: &[(&str, &str)] = &[ (".spx", "00;36"), (".xspf", "00;36"), // Backup files - ("~", "00;90"), - ("#", "00;90"), + ("*~", "00;90"), + ("*#", "00;90"), (".bak", "00;90"), (".old", "00;90"), (".orig", "00;90"), diff --git a/tests/fixtures/dircolors/internal.expected b/tests/fixtures/dircolors/internal.expected index 933e70bc4..e151973f2 100644 --- a/tests/fixtures/dircolors/internal.expected +++ b/tests/fixtures/dircolors/internal.expected @@ -176,8 +176,8 @@ EXEC 01;32 .opus 00;36 .spx 00;36 .xspf 00;36 -~ 00;90 -# 00;90 +*~ 00;90 +*# 00;90 .bak 00;90 .old 00;90 .orig 00;90 From b0fdb1edef1a197c95faf83ffbb325190dfee9c3 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 4 Dec 2023 23:25:13 +0100 Subject: [PATCH 23/52] Rest of the comments --- src/uu/dircolors/src/dircolors.rs | 154 +++++++++--------------------- tests/by-util/test_dircolors.rs | 2 + 2 files changed, 46 insertions(+), 110 deletions(-) diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index cf8ed6292..41e640b2a 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -7,9 +7,8 @@ use std::borrow::Borrow; use std::env; -use std::fmt::Write; use std::fs::File; -use std::io::IsTerminal; +//use std::io::IsTerminal; use std::io::{BufRead, BufReader}; use std::path::Path; @@ -99,16 +98,20 @@ fn generate_ls_colors(fmt: &OutputFmt, sep: &str) -> String { let mut display_parts = vec![]; let type_output = generate_type_output(fmt); display_parts.push(type_output); - for &(extension, code) in FILE_COLORS.iter() { - display_parts.push(format!("\x1b[{}m*{}\t{}\x1b[0m", code, extension, code)); + for &(extension, code) in FILE_COLORS { + let prefix = if extension.starts_with('*') { "" } else { "*" }; + let formatted_extension = + format!("\x1b[{}m{}{}\t{}\x1b[0m", code, prefix, extension, code); + display_parts.push(formatted_extension); } display_parts.join("\n") } _ => { // existing logic for other formats let mut parts = vec![]; - for &(extension, code) in FILE_COLORS.iter() { - let formatted_extension = format!("*{}", extension); + for &(extension, code) in FILE_COLORS { + let prefix = if extension.starts_with('*') { "" } else { "*" }; + let formatted_extension = format!("{}{}", prefix, extension); parts.push(format!("{}={}", formatted_extension, code)); } let (prefix, suffix) = get_colors_format_strings(fmt); @@ -193,6 +196,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let result; if files.is_empty() { + println!("{}", generate_ls_colors(&out_format, ":")); + return Ok(()); + /* // Check if data is being piped into the program if std::io::stdin().is_terminal() { // No data piped, use default behavior @@ -203,6 +209,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let fin = BufReader::new(std::io::stdin()); result = parse(fin.lines().map_while(Result::ok), &out_format, "-"); } + */ } else if files.len() > 1 { return Err(UUsageError::new( 1, @@ -474,117 +481,44 @@ fn escape(s: &str) -> String { pub fn generate_dircolors_config() -> String { let mut config = String::new(); - // Adding the complete header comments as in the original file - writeln!( - config, - "# Configuration file for dircolors, a utility to help you set the" - ) - .unwrap(); - writeln!( - config, - "# LS_COLORS environment variable used by GNU ls with the --color option." - ) - .unwrap(); - writeln!( - config, - "# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the" - ) - .unwrap(); - writeln!( - config, - "# slackware version of dircolors) are recognized but ignored." - ) - .unwrap(); - writeln!( - config, - "# Global config options can be specified before TERM or COLORTERM entries" - ) - .unwrap(); - writeln!( - config, - "# Below are TERM or COLORTERM entries, which can be glob patterns, which" - ) - .unwrap(); - writeln!( - config, - "# restrict following config to systems with matching environment variables." - ) - .unwrap(); - writeln!(config, "COLORTERM ?*").unwrap(); - for term in TERMS.iter() { - writeln!(config, "TERM {}", term).unwrap(); + config.push_str("# Configuration file for dircolors, a utility to help you set the\n"); + config.push_str("# LS_COLORS environment variable used by GNU ls with the --color option.\n"); + config.push_str("# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the\n"); + config.push_str("# slackware version of dircolors) are recognized but ignored.\n"); + config.push_str("# Global config options can be specified before TERM or COLORTERM entries\n"); + config.push_str("# Below are TERM or COLORTERM entries, which can be glob patterns, which\n"); + config + .push_str("# restrict following config to systems with matching environment variables.\n"); + config.push_str("COLORTERM ?*\n"); + for term in TERMS { + config.push_str(&format!("TERM {}\n", term)); } - // Adding file types and their color codes with header - writeln!( - config, - "# Below are the color init strings for the basic file types." - ) - .unwrap(); - writeln!( - config, - "# One can use codes for 256 or more colors supported by modern terminals." - ) - .unwrap(); - writeln!( - config, - "# The default color codes use the capabilities of an 8 color terminal" - ) - .unwrap(); - writeln!( - config, - "# with some additional attributes as per the following codes:" - ) - .unwrap(); - writeln!(config, "# Attribute codes:").unwrap(); - writeln!( - config, - "# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed" - ) - .unwrap(); - writeln!(config, "# Text color codes:").unwrap(); - writeln!( - config, - "# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white" - ) - .unwrap(); - writeln!(config, "# Background color codes:").unwrap(); - writeln!( - config, - "# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white" - ) - .unwrap(); - writeln!(config, "#NORMAL 00 # no color code at all").unwrap(); - writeln!(config, "#FILE 00 # regular file: use no color at all").unwrap(); + config.push_str("# Below are the color init strings for the basic file types.\n"); + config.push_str("# One can use codes for 256 or more colors supported by modern terminals.\n"); + config.push_str("# The default color codes use the capabilities of an 8 color terminal\n"); + config.push_str("# with some additional attributes as per the following codes:\n"); + config.push_str("# Attribute codes:\n"); + config.push_str("# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed\n"); + config.push_str("# Text color codes:\n"); + config.push_str("# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white\n"); + config.push_str("# Background color codes:\n"); + config.push_str("# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white\n"); + config.push_str("#NORMAL 00 # no color code at all\n"); + config.push_str("#FILE 00 # regular file: use no color at all\n"); - for (name, _, code) in FILE_TYPES.iter() { - writeln!(config, "{} {}", name, code).unwrap(); + for (name, _, code) in FILE_TYPES { + config.push_str(&format!("{} {}\n", name, code)); } - writeln!( - config, - "# List any file extensions like '.gz' or '.tar' that you would like ls" - ) - .unwrap(); - writeln!( - config, - "# to color below. Put the extension, a space, and the color init string." - ) - .unwrap(); + config.push_str("# List any file extensions like '.gz' or '.tar' that you would like ls\n"); + config.push_str("# to color below. Put the extension, a space, and the color init string.\n"); - for (ext, color) in FILE_COLORS.iter() { - writeln!(config, "{} {}", ext, color).unwrap(); + for (ext, color) in FILE_COLORS { + config.push_str(&format!("{} {}\n", ext, color)); } - writeln!( - config, - "# Subsequent TERM or COLORTERM entries, can be used to add / override" - ) - .unwrap(); - write!( - config, - "# config specific to those matching environment variables." - ) - .unwrap(); + config.push_str("# Subsequent TERM or COLORTERM entries, can be used to add / override\n"); + config.push_str("# config specific to those matching environment variables."); config } diff --git a/tests/by-util/test_dircolors.rs b/tests/by-util/test_dircolors.rs index e3752fcde..4a256352c 100644 --- a/tests/by-util/test_dircolors.rs +++ b/tests/by-util/test_dircolors.rs @@ -159,6 +159,7 @@ fn test_quoting() { .no_stderr(); } +/* #[test] fn test_print_ls_colors() { new_ucmd!() @@ -168,6 +169,7 @@ fn test_print_ls_colors() { .stdout_is("\x1B[40;33mtw\t40;33\x1B[0m\n") .no_stderr(); } +*/ #[test] fn test_extra_operand() { From 2fcfec6490f87af117a03ccd77ebf487192d548c Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 5 Dec 2023 21:50:38 +0100 Subject: [PATCH 24/52] fuzz seq --- .github/workflows/fuzzing.yml | 1 + fuzz/Cargo.toml | 8 +++- fuzz/fuzz_targets/fuzz_seq.rs | 78 +++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 fuzz/fuzz_targets/fuzz_seq.rs diff --git a/.github/workflows/fuzzing.yml b/.github/workflows/fuzzing.yml index 623a03f65..eed2ae2fc 100644 --- a/.github/workflows/fuzzing.yml +++ b/.github/workflows/fuzzing.yml @@ -47,6 +47,7 @@ jobs: - { name: fuzz_expr, should_pass: true } - { name: fuzz_printf, should_pass: false } - { name: fuzz_echo, should_pass: false } + - { name: fuzz_seq, should_pass: false } - { name: fuzz_parse_glob, should_pass: true } - { name: fuzz_parse_size, should_pass: true } - { name: fuzz_parse_time, should_pass: true } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index b27f5b586..c98f105ad 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -18,7 +18,7 @@ uu_test = { path = "../src/uu/test/" } uu_expr = { path = "../src/uu/expr/" } uu_printf = { path = "../src/uu/printf/" } uu_echo = { path = "../src/uu/echo/" } - +uu_seq = { path = "../src/uu/seq/" } # Prevent this from interfering with workspaces [workspace] @@ -42,6 +42,12 @@ path = "fuzz_targets/fuzz_echo.rs" test = false doc = false +[[bin]] +name = "fuzz_seq" +path = "fuzz_targets/fuzz_seq.rs" +test = false +doc = false + [[bin]] name = "fuzz_expr" path = "fuzz_targets/fuzz_expr.rs" diff --git a/fuzz/fuzz_targets/fuzz_seq.rs b/fuzz/fuzz_targets/fuzz_seq.rs new file mode 100644 index 000000000..2e4ff1a46 --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_seq.rs @@ -0,0 +1,78 @@ +// This file is part of the uutils coreutils package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +// spell-checker:ignore parens + +#![no_main] +use libfuzzer_sys::fuzz_target; +use uu_seq::uumain; + +use rand::Rng; +use std::ffi::OsString; + +mod fuzz_common; +use crate::fuzz_common::CommandResult; +use crate::fuzz_common::{ + compare_result, generate_and_run_uumain, generate_random_string, run_gnu_cmd, +}; +static CMD_PATH: &str = "seq"; + +fn generate_seq() -> String { + let mut rng = rand::thread_rng(); + + // Generate 1 to 3 numbers for seq arguments + let arg_count = rng.gen_range(1..=3); + let mut args = Vec::new(); + + for _ in 0..arg_count { + if rng.gen_ratio(1, 100) { + // 1% chance to add a random string + args.push(generate_random_string(rng.gen_range(1..=10))); + } else { + // 99% chance to add a numeric value + match rng.gen_range(0..=3) { + 0 => args.push(rng.gen_range(-10000..=10000).to_string()), // Large or small integers + 1 => args.push(rng.gen_range(-100.0..100.0).to_string()), // Floating-point numbers + 2 => args.push(rng.gen_range(-100..0).to_string()), // Negative integers + _ => args.push(rng.gen_range(1..=100).to_string()), // Regular integers + } + } + } + + args.join(" ") +} + +fuzz_target!(|_data: &[u8]| { + let seq = generate_seq(); + let mut args = vec![OsString::from("seq")]; + args.extend(seq.split_whitespace().map(OsString::from)); + + let rust_result = generate_and_run_uumain(&args, uumain); + + let gnu_result = match run_gnu_cmd(CMD_PATH, &args[1..], false) { + Ok(result) => result, + Err(error_result) => { + eprintln!("Failed to run GNU command:"); + eprintln!("Stderr: {}", error_result.stderr); + eprintln!("Exit Code: {}", error_result.exit_code); + CommandResult { + stdout: String::new(), + stderr: error_result.stderr, + exit_code: error_result.exit_code, + } + } + }; + + compare_result( + "seq", + &format!("{:?}", &args[1..]), + &rust_result.stdout, + &gnu_result.stdout, + &rust_result.stderr, + &gnu_result.stderr, + rust_result.exit_code, + gnu_result.exit_code, + false, // Set to true if you want to fail on stderr diff + ); +}); From 97ec99cf28d7b699e7d89793bad93f7ca0976053 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 6 Dec 2023 21:14:59 +0100 Subject: [PATCH 25/52] use a single push_str Co-authored-by: Terts Diepraam --- src/uu/dircolors/src/dircolors.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index 41e640b2a..91544dc73 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -481,14 +481,17 @@ fn escape(s: &str) -> String { pub fn generate_dircolors_config() -> String { let mut config = String::new(); - config.push_str("# Configuration file for dircolors, a utility to help you set the\n"); - config.push_str("# LS_COLORS environment variable used by GNU ls with the --color option.\n"); - config.push_str("# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the\n"); - config.push_str("# slackware version of dircolors) are recognized but ignored.\n"); - config.push_str("# Global config options can be specified before TERM or COLORTERM entries\n"); - config.push_str("# Below are TERM or COLORTERM entries, which can be glob patterns, which\n"); - config - .push_str("# restrict following config to systems with matching environment variables.\n"); + config.push_str( + "\ + # Configuration file for dircolors, a utility to help you set the\n\ + # LS_COLORS environment variable used by GNU ls with the --color option.\n\ + # The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the\n\ + # slackware version of dircolors) are recognized but ignored.\n\ + # Global config options can be specified before TERM or COLORTERM entries\n\ + # Below are TERM or COLORTERM entries, which can be glob patterns, which\n\ + # restrict following config to systems with matching environment variables.\n\ + ", + ); config.push_str("COLORTERM ?*\n"); for term in TERMS { config.push_str(&format!("TERM {}\n", term)); From bd667efa7b1daf9a38edc5272c3bdab8e5743f56 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 6 Dec 2023 21:15:43 +0100 Subject: [PATCH 26/52] simplify the declaration Co-authored-by: Terts Diepraam --- src/uu/dircolors/src/dircolors.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index 91544dc73..fa523451b 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -497,18 +497,22 @@ pub fn generate_dircolors_config() -> String { config.push_str(&format!("TERM {}\n", term)); } - config.push_str("# Below are the color init strings for the basic file types.\n"); - config.push_str("# One can use codes for 256 or more colors supported by modern terminals.\n"); - config.push_str("# The default color codes use the capabilities of an 8 color terminal\n"); - config.push_str("# with some additional attributes as per the following codes:\n"); - config.push_str("# Attribute codes:\n"); - config.push_str("# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed\n"); - config.push_str("# Text color codes:\n"); - config.push_str("# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white\n"); - config.push_str("# Background color codes:\n"); - config.push_str("# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white\n"); - config.push_str("#NORMAL 00 # no color code at all\n"); - config.push_str("#FILE 00 # regular file: use no color at all\n"); + config.push_str( + "\ + # Below are the color init strings for the basic file types.\n\ + # One can use codes for 256 or more colors supported by modern terminals.\n\ + # The default color codes use the capabilities of an 8 color terminal\n\ + # with some additional attributes as per the following codes:\n\ + # Attribute codes:\n\ + # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed\n\ + # Text color codes:\n\ + # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white\n\ + # Background color codes:\n\ + # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white\n\ + #NORMAL 00 # no color code at all\n\ + #FILE 00 # regular file: use no color at all\n\ + ", + ); for (name, _, code) in FILE_TYPES { config.push_str(&format!("{} {}\n", name, code)); From f99987bb35aade972e187ad3b7df6b039f5b72c2 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 6 Dec 2023 21:19:59 +0100 Subject: [PATCH 27/52] fix rustfmt --- src/uu/dircolors/src/dircolors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/dircolors/src/dircolors.rs b/src/uu/dircolors/src/dircolors.rs index fa523451b..ecca9d160 100644 --- a/src/uu/dircolors/src/dircolors.rs +++ b/src/uu/dircolors/src/dircolors.rs @@ -481,7 +481,7 @@ fn escape(s: &str) -> String { pub fn generate_dircolors_config() -> String { let mut config = String::new(); - config.push_str( + config.push_str( "\ # Configuration file for dircolors, a utility to help you set the\n\ # LS_COLORS environment variable used by GNU ls with the --color option.\n\ From 5a32ab8004304fe5434bf42e1faf066a58b95736 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 6 Dec 2023 15:35:38 +0100 Subject: [PATCH 28/52] ls: implement --hyperlink --- Cargo.lock | 1 + Cargo.toml | 1 + src/uu/hostname/Cargo.toml | 2 +- src/uu/ls/Cargo.toml | 1 + src/uu/ls/src/ls.rs | 50 ++++++++++++++++++++++++++++++++++++-- tests/by-util/test_ls.rs | 30 +++++++++++++++++++++++ 6 files changed, 82 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf638b421..5060da441 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2618,6 +2618,7 @@ dependencies = [ "chrono", "clap", "glob", + "hostname", "lscolors", "number_prefix", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 14e700ee0..13b997008 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -284,6 +284,7 @@ fundu = "2.0.0" gcd = "2.3" glob = "0.3.1" half = "2.3" +hostname = "0.3" indicatif = "0.17" itertools = "0.12.0" libc = "0.2.150" diff --git a/src/uu/hostname/Cargo.toml b/src/uu/hostname/Cargo.toml index a9b033d12..1fe101709 100644 --- a/src/uu/hostname/Cargo.toml +++ b/src/uu/hostname/Cargo.toml @@ -16,7 +16,7 @@ path = "src/hostname.rs" [dependencies] clap = { workspace = true } -hostname = { version = "0.3", features = ["set"] } +hostname = { workspace = true, features = ["set"] } uucore = { workspace = true, features = ["wide"] } [target.'cfg(target_os = "windows")'.dependencies] diff --git a/src/uu/ls/Cargo.toml b/src/uu/ls/Cargo.toml index 96cf7df1a..a82a1f37e 100644 --- a/src/uu/ls/Cargo.toml +++ b/src/uu/ls/Cargo.toml @@ -31,6 +31,7 @@ uucore = { workspace = true, features = [ ] } once_cell = { workspace = true } selinux = { workspace = true, optional = true } +hostname = { workspace = true } [[bin]] name = "ls" diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index c6b10677c..deb8aac3d 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -155,6 +155,7 @@ pub mod options { pub static GROUP_DIRECTORIES_FIRST: &str = "group-directories-first"; pub static ZERO: &str = "zero"; pub static DIRED: &str = "dired"; + pub static HYPERLINK: &str = "hyperlink"; } const DEFAULT_TERM_WIDTH: u16 = 80; @@ -418,6 +419,7 @@ pub struct Config { group_directories_first: bool, line_ending: LineEnding, dired: bool, + hyperlink: bool, } // Fields that can be removed or added to the long format @@ -566,6 +568,25 @@ fn extract_color(options: &clap::ArgMatches) -> bool { } } +/// Extracts the hyperlink option to use based on the options provided. +/// +/// # Returns +/// +/// A boolean representing whether to hyperlink files. +fn extract_hyperlink(options: &clap::ArgMatches) -> bool { + let hyperlink = options + .get_one::(options::HYPERLINK) + .unwrap() + .as_str(); + + match hyperlink { + "always" | "yes" | "force" => true, + "auto" | "tty" | "if-tty" => std::io::stdout().is_terminal(), + "never" | "no" | "none" => false, + _ => unreachable!("should be handled by clap"), + } +} + /// Extracts the quoting style to use based on the options provided. /// /// # Arguments @@ -736,10 +757,9 @@ impl Config { } let sort = extract_sort(options); - let time = extract_time(options); - let mut needs_color = extract_color(options); + let hyperlink = extract_hyperlink(options); let opt_block_size = options.get_one::(options::size::BLOCK_SIZE); let opt_si = opt_block_size.is_some() @@ -1020,6 +1040,7 @@ impl Config { group_directories_first: options.get_flag(options::GROUP_DIRECTORIES_FIRST), line_ending: LineEnding::from_zero_flag(options.get_flag(options::ZERO)), dired, + hyperlink, }) } } @@ -1154,6 +1175,19 @@ pub fn uu_app() -> Command { .help("generate output designed for Emacs' dired (Directory Editor) mode") .action(ArgAction::SetTrue), ) + .arg( + Arg::new(options::HYPERLINK) + .long(options::HYPERLINK) + .help("hyperlink file names WHEN") + .value_parser([ + "always", "yes", "force", "auto", "tty", "if-tty", "never", "no", "none", + ]) + .require_equals(true) + .num_args(0..=1) + .default_missing_value("always") + .default_value("never") + .value_name("WHEN"), + ) // The next four arguments do not override with the other format // options, see the comment in Config::from for the reason. // Ideally, they would use Arg::override_with, with their own name @@ -2959,6 +2993,18 @@ fn display_file_name( // infer it because the color codes mess up term_grid's width calculation. let mut width = name.width(); + if config.hyperlink { + let hostname = hostname::get().unwrap_or(OsString::from("")); + let hostname = hostname.to_string_lossy(); + + let absolute_path = fs::canonicalize(&path.p_buf).unwrap_or_default(); + let absolute_path = absolute_path.to_string_lossy(); + + // TODO encode path + // \x1b = ESC, \x07 = BEL + name = format!("\x1b]8;;file://{hostname}{absolute_path}\x07{name}\x1b]8;;\x07"); + } + if let Some(ls_colors) = &config.color { let md = path.md(out); name = if md.is_some() { diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index fcd57170d..8bc2b75ac 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -3855,3 +3855,33 @@ fn test_posixly_correct() { .succeeds() .stdout_contains_line("total 8"); } + +#[test] +fn test_ls_hyperlink() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let file = "a.txt"; + + at.touch(file); + + let path = at.root_dir_resolved(); + let separator = std::path::MAIN_SEPARATOR_STR; + + let result = scene.ucmd().arg("--hyperlink").succeeds(); + assert!(result.stdout_str().contains("\x1b]8;;file://")); + assert!(result + .stdout_str() + .contains(&format!("{path}{separator}{file}\x07{file}\x1b]8;;\x07"))); + + let result = scene.ucmd().arg("--hyperlink=always").succeeds(); + assert!(result.stdout_str().contains("\x1b]8;;file://")); + assert!(result + .stdout_str() + .contains(&format!("{path}{separator}{file}\x07{file}\x1b]8;;\x07"))); + + scene + .ucmd() + .arg("--hyperlink=never") + .succeeds() + .stdout_is(format!("{file}\n")); +} From 09999427ccfb822918fc6969e16d0fc656087ff1 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Thu, 7 Dec 2023 10:02:29 +0100 Subject: [PATCH 29/52] du: merge imports --- src/uu/du/src/du.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index dc03a64f2..989e663e4 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -3,35 +3,30 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -use chrono::prelude::DateTime; -use chrono::Local; -use clap::ArgAction; -use clap::{crate_version, Arg, ArgMatches, Command}; +use chrono::{DateTime, Local}; +use clap::{crate_version, Arg, ArgAction, ArgMatches, Command}; use glob::Pattern; use std::collections::HashSet; use std::env; -use std::fs; -use std::fs::File; +use std::error::Error; +use std::fmt::Display; #[cfg(not(windows))] use std::fs::Metadata; -use std::io::BufRead; -use std::io::BufReader; +use std::fs::{self, File}; +use std::io::{BufRead, BufReader}; #[cfg(not(windows))] use std::os::unix::fs::MetadataExt; #[cfg(windows)] use std::os::windows::fs::MetadataExt; #[cfg(windows)] use std::os::windows::io::AsRawHandle; -use std::path::Path; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::mpsc; use std::thread; use std::time::{Duration, UNIX_EPOCH}; -use std::{error::Error, fmt::Display}; use uucore::display::{print_verbatim, Quotable}; -use uucore::error::FromIo; -use uucore::error::{UError, UResult, USimpleError}; +use uucore::error::{FromIo, UError, UResult, USimpleError}; use uucore::line_ending::LineEnding; use uucore::parse_glob; use uucore::parse_size::{parse_size_u64, ParseSizeError}; From 6cae19156926ef0ca68e1e3657dd51e2066d4e8b Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Thu, 7 Dec 2023 11:06:04 +0100 Subject: [PATCH 30/52] du: remove ArgMatches from StatPrinter --- src/uu/du/src/du.rs | 165 ++++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 81 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 989e663e4..26e697abb 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -87,6 +87,18 @@ struct Options { count_links: bool, inodes: bool, verbose: bool, + threshold: Option, + apparent_size: bool, + // TODO: the size conversion fields should be unified + si: bool, + bytes: bool, + human_readable: bool, + block_size_1k: bool, + block_size_1m: bool, + block_size: u64, + time: Option