Add dir and vdir utils (based on ls)

Fix issue #3163

They are basically ls with some different options.
This commit is contained in:
gmnsii 2022-04-15 08:30:40 -07:00 committed by GitHub
parent 02bd97a00d
commit c2e214bd99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 950 additions and 619 deletions

View file

@ -179,3 +179,4 @@ Smigle00
anonymousknight
kwantam
nicoo
gmnsii

View file

@ -93,6 +93,7 @@ rollup
sed
selinuxenabled
sestatus
vdir
wslpath
xargs

22
Cargo.lock generated
View file

@ -368,6 +368,7 @@ dependencies = [
"uu_date",
"uu_dd",
"uu_df",
"uu_dir",
"uu_dircolors",
"uu_dirname",
"uu_du",
@ -445,6 +446,7 @@ dependencies = [
"uu_unlink",
"uu_uptime",
"uu_users",
"uu_vdir",
"uu_wc",
"uu_who",
"uu_whoami",
@ -2376,6 +2378,16 @@ dependencies = [
"uucore",
]
[[package]]
name = "uu_dir"
version = "0.0.13"
dependencies = [
"clap 3.1.8",
"selinux",
"uu_ls",
"uucore",
]
[[package]]
name = "uu_dircolors"
version = "0.0.13"
@ -3127,6 +3139,16 @@ dependencies = [
"uucore",
]
[[package]]
name = "uu_vdir"
version = "0.0.13"
dependencies = [
"clap 3.1.8",
"selinux",
"uu_ls",
"uucore",
]
[[package]]
name = "uu_wc"
version = "0.0.13"

View file

@ -45,6 +45,7 @@ feat_common_core = [
"cut",
"date",
"df",
"dir",
"dircolors",
"dirname",
"dd",
@ -100,6 +101,7 @@ feat_common_core = [
"unexpand",
"uniq",
"unlink",
"vdir",
"wc",
"yes",
]
@ -276,6 +278,7 @@ cut = { optional=true, version="0.0.13", package="uu_cut", path="src/uu/cut
date = { optional=true, version="0.0.13", package="uu_date", path="src/uu/date" }
dd = { optional=true, version="0.0.13", package="uu_dd", path="src/uu/dd" }
df = { optional=true, version="0.0.13", package="uu_df", path="src/uu/df" }
dir = { optional=true, version="0.0.13", package="uu_dir", path="src/uu/dir" }
dircolors= { optional=true, version="0.0.13", package="uu_dircolors", path="src/uu/dircolors" }
dirname = { optional=true, version="0.0.13", package="uu_dirname", path="src/uu/dirname" }
du = { optional=true, version="0.0.13", package="uu_du", path="src/uu/du" }
@ -352,6 +355,7 @@ uniq = { optional=true, version="0.0.13", package="uu_uniq", path="src/uu/un
unlink = { optional=true, version="0.0.13", package="uu_unlink", path="src/uu/unlink" }
uptime = { optional=true, version="0.0.13", package="uu_uptime", path="src/uu/uptime" }
users = { optional=true, version="0.0.13", package="uu_users", path="src/uu/users" }
vdir = { optional=true, version="0.0.13", package="uu_vdir", path="src/uu/vdir" }
wc = { optional=true, version="0.0.13", package="uu_wc", path="src/uu/wc" }
who = { optional=true, version="0.0.13", package="uu_who", path="src/uu/who" }
whoami = { optional=true, version="0.0.13", package="uu_whoami", path="src/uu/whoami" }

View file

@ -65,6 +65,7 @@ PROGS := \
date \
dd \
df \
dir \
dircolors \
dirname \
echo \
@ -118,6 +119,7 @@ PROGS := \
tsort \
unexpand \
uniq \
vdir \
wc \
whoami \
yes

25
src/uu/dir/Cargo.toml Normal file
View file

@ -0,0 +1,25 @@
[package]
name = "uu_dir"
version = "0.0.13"
authors = ["uutils developers"]
license = "MIT"
description = "shortcut to ls -C -b"
homepage = "https://github.com/uutils/coreutils"
repository = "https://github.com/uutils/coreutils/tree/main/src/uu/ls"
keywords = ["coreutils", "uutils", "cross-platform", "cli", "utility"]
categories = ["command-line-utilities"]
edition = "2021"
[lib]
path = "src/dir.rs"
[dependencies]
clap = { version = "3.1", features = ["wrap_help", "cargo", "env"] }
uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore", features = ["entries", "fs"] }
selinux = { version="0.2", optional = true }
uu_ls = {path="../ls"}
[[bin]]
name = "dir"
path = "src/main.rs"

1
src/uu/dir/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../../LICENSE

70
src/uu/dir/src/dir.rs Normal file
View file

@ -0,0 +1,70 @@
// * This file is part of the uutils coreutils package.
// *
// * (c) gmnsii <gmnsii@protonmail.com>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.
use clap::Command;
use std::path::Path;
use uu_ls::quoting_style::{Quotes, QuotingStyle};
use uu_ls::{options, Config, Format};
use uucore::error::UResult;
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let command = uu_ls::uu_app();
let matches = command.get_matches_from(args);
let mut default_quoting_style = false;
let mut default_format_style = false;
// We check if any options on formatting or quoting style have been given.
// If not, we will use dir default formatting and quoting style options
if !matches.is_present(options::QUOTING_STYLE)
&& !matches.is_present(options::quoting::C)
&& !matches.is_present(options::quoting::ESCAPE)
&& !matches.is_present(options::quoting::LITERAL)
{
default_quoting_style = true;
}
if !matches.is_present(options::FORMAT)
&& !matches.is_present(options::format::ACROSS)
&& !matches.is_present(options::format::COLUMNS)
&& !matches.is_present(options::format::COMMAS)
&& !matches.is_present(options::format::LONG)
&& !matches.is_present(options::format::LONG_NO_GROUP)
&& !matches.is_present(options::format::LONG_NO_OWNER)
&& !matches.is_present(options::format::LONG_NUMERIC_UID_GID)
&& !matches.is_present(options::format::ONE_LINE)
{
default_format_style = true;
}
let mut config = Config::from(&matches)?;
if default_quoting_style {
config.quoting_style = QuotingStyle::C {
quotes: Quotes::None,
};
}
if default_format_style {
config.format = Format::Columns;
}
let locs = matches
.values_of_os(options::PATHS)
.map(|v| v.map(Path::new).collect())
.unwrap_or_else(|| vec![Path::new(".")]);
uu_ls::list(locs, &config)
}
// To avoid code duplication, we reuse ls uu_app function which has the same
// arguments. However, coreutils won't compile if one of the utils is missing
// an uu_app function, so we need this dummy one.
pub fn uu_app<'a>() -> Command<'a> {
Command::new(uucore::util_name())
}

1
src/uu/dir/src/main.rs Normal file
View file

@ -0,0 +1 @@
uucore::bin!(uu_dir);

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ use std::ffi::OsStr;
const SPECIAL_SHELL_CHARS_START: &[char] = &['~', '#'];
const SPECIAL_SHELL_CHARS: &str = "`$&*()|[]{};\\'\"<>?! ";
pub(super) enum QuotingStyle {
pub enum QuotingStyle {
Shell {
escape: bool,
always_quote: bool,
@ -21,7 +21,7 @@ pub(super) enum QuotingStyle {
}
#[derive(Clone, Copy)]
pub(super) enum Quotes {
pub enum Quotes {
None,
Single,
Double,

25
src/uu/vdir/Cargo.toml Normal file
View file

@ -0,0 +1,25 @@
[package]
name = "uu_vdir"
version = "0.0.13"
authors = ["uutils developers"]
license = "MIT"
description = "shortcut to ls -l -b"
homepage = "https://github.com/uutils/coreutils"
repository = "https://github.com/uutils/coreutils/tree/main/src/uu/ls"
keywords = ["coreutils", "uutils", "cross-platform", "cli", "utility"]
categories = ["command-line-utilities"]
edition = "2021"
[lib]
path = "src/vdir.rs"
[dependencies]
clap = { version = "3.1", features = ["wrap_help", "cargo", "env"] }
uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore", features = ["entries", "fs"] }
selinux = { version="0.2", optional = true }
uu_ls = {path="../ls"}
[[bin]]
name = "vdir"
path = "src/main.rs"

1
src/uu/vdir/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../../LICENSE

1
src/uu/vdir/src/main.rs Normal file
View file

@ -0,0 +1 @@
uucore::bin!(uu_vdir);

68
src/uu/vdir/src/vdir.rs Normal file
View file

@ -0,0 +1,68 @@
// * This file is part of the uutils coreutils package.
// *
// * (c) gmnsii <gmnsii@protonmail.com>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.
use clap::Command;
use std::path::Path;
use uu_ls::quoting_style::{Quotes, QuotingStyle};
use uu_ls::{options, Config, Format};
use uucore::error::UResult;
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let command = uu_ls::uu_app();
let matches = command.get_matches_from(args);
let mut default_quoting_style = false;
let mut default_format_style = false;
// We check if any options on formatting or quoting style have been given.
// If not, we will use dir default formatting and quoting style options
if !matches.is_present(options::QUOTING_STYLE)
&& !matches.is_present(options::quoting::C)
&& !matches.is_present(options::quoting::ESCAPE)
&& !matches.is_present(options::quoting::LITERAL)
{
default_quoting_style = true;
}
if !matches.is_present(options::FORMAT)
&& !matches.is_present(options::format::ACROSS)
&& !matches.is_present(options::format::COLUMNS)
&& !matches.is_present(options::format::COMMAS)
&& !matches.is_present(options::format::LONG)
&& !matches.is_present(options::format::LONG_NO_GROUP)
&& !matches.is_present(options::format::LONG_NO_OWNER)
&& !matches.is_present(options::format::LONG_NUMERIC_UID_GID)
&& !matches.is_present(options::format::ONE_LINE)
{
default_format_style = true;
}
let mut config = Config::from(&matches)?;
if default_quoting_style {
config.quoting_style = QuotingStyle::C {
quotes: Quotes::None,
};
}
if default_format_style {
config.format = Format::Long;
}
let locs = matches
.values_of_os(options::PATHS)
.map(|v| v.map(Path::new).collect())
.unwrap_or_else(|| vec![Path::new(".")]);
uu_ls::list(locs, &config)
}
// To avoid code duplication, we reuse ls uu_app function which has the same
// arguments. However, coreutils won't compile if one of the utils is missing
// an uu_app function, so we need this dummy one.
pub fn uu_app<'a>() -> Command<'a> {
Command::new(uucore::util_name())
}

55
tests/by-util/test_dir.rs Normal file
View file

@ -0,0 +1,55 @@
#[cfg(not(windows))]
extern crate libc;
extern crate regex;
#[cfg(not(windows))]
extern crate tempfile;
#[cfg(unix)]
extern crate unix_socket;
use self::regex::Regex;
use crate::common::util::*;
/*
* As dir use the same functions than ls, we don't have to retest them here.
* We just test the default and the long output
*/
#[test]
fn test_dir() {
new_ucmd!().succeeds();
}
#[test]
fn test_default_output() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
at.touch("some-file1");
scene.ucmd().succeeds().stdout_contains("some-file1");
scene
.ucmd()
.succeeds()
.stdout_does_not_match(&Regex::new("[rwx][^some-file1]").unwrap());
}
#[test]
fn test_long_output() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
at.touch("some-file1");
scene
.ucmd()
.arg("-l")
.succeeds()
.stdout_contains("some-file1");
scene
.ucmd()
.arg("-l")
.succeeds()
.stdout_matches(&Regex::new("[rwx][^some-file1]").unwrap());
}

View file

@ -0,0 +1,55 @@
#[cfg(not(windows))]
extern crate libc;
extern crate regex;
#[cfg(not(windows))]
extern crate tempfile;
#[cfg(unix)]
extern crate unix_socket;
use self::regex::Regex;
use crate::common::util::*;
/*
* As vdir use the same functions than ls, we don't have to retest them here.
* We just test the default and the column output
*/
#[test]
fn test_vdir() {
new_ucmd!().succeeds();
}
#[test]
fn test_default_output() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
at.touch("some-file1");
scene.ucmd().succeeds().stdout_contains("some-file1");
scene
.ucmd()
.succeeds()
.stdout_matches(&Regex::new("[rwx][^some-file1]").unwrap());
}
#[test]
fn test_column_output() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
at.touch("some-file1");
scene
.ucmd()
.arg("-C")
.succeeds()
.stdout_contains("some-file1");
scene
.ucmd()
.arg("-C")
.succeeds()
.stdout_does_not_match(&Regex::new("[rwx][^some-file1]").unwrap());
}

View file

@ -180,7 +180,7 @@ sed -i -e "s~ sed -n \"1s/'\\\/'/'OPT'/p\" < err >> pat || framework_failure_~
# see issue #3331 (clap limitation).
# Upstream returns 1 for most of the program. We do for cp, truncate & pr
# So, keep it as it
sed -i -e "s/rcexp=1$/rcexp=2\n case \"\$prg\" in chcon|dir|runcon|vdir) return;; esac/" -e "s/rcexp=125 ;;/rcexp=2 ;;\ncp|truncate|pr) rcexp=1;;/" tests/misc/usage_vs_getopt.sh
sed -i -e "s/rcexp=1$/rcexp=2\n case \"\$prg\" in chcon|runcon) return;; esac/" -e "s/rcexp=125 ;;/rcexp=2 ;;\ncp|truncate|pr) rcexp=1;;/" tests/misc/usage_vs_getopt.sh
# GNU has option=[SUFFIX], clap is <SUFFIX>
sed -i -e "s/cat opts/sed -i -e \"s| <.\*>$||g\" opts/" tests/misc/usage_vs_getopt.sh
# Strip empty lines for the diff - see https://github.com/uutils/coreutils/issues/3370