Skip to content

Commit

Permalink
Merge branch 'main' into tail_notify
Browse files Browse the repository at this point in the history
  • Loading branch information
jhscheer committed Jun 6, 2022
2 parents beb2b7c + fc5aedf commit e9076f0
Show file tree
Hide file tree
Showing 12 changed files with 298 additions and 67 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 19 additions & 2 deletions src/uu/df/src/df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ struct Options {
/// types will *not* be listed.
exclude: Option<Vec<String>>,

/// Whether to sync before operating.
sync: bool,

/// Whether to show a final row comprising the totals for each column.
show_total: bool,

Expand All @@ -104,6 +107,7 @@ impl Default for Options {
header_mode: Default::default(),
include: Default::default(),
exclude: Default::default(),
sync: Default::default(),
show_total: Default::default(),
columns: vec![
Column::Source,
Expand Down Expand Up @@ -178,6 +182,7 @@ impl Options {
Ok(Self {
show_local_fs: matches.is_present(OPT_LOCAL),
show_all_fs: matches.is_present(OPT_ALL),
sync: matches.is_present(OPT_SYNC),
block_size: read_block_size(matches).map_err(|e| match e {
ParseSizeError::InvalidSuffix(s) => OptionsError::InvalidSuffix(s),
ParseSizeError::SizeTooBig(_) => OptionsError::BlockSizeTooLarge(
Expand Down Expand Up @@ -325,9 +330,21 @@ fn filter_mount_list(vmi: Vec<MountInfo>, opt: &Options) -> Vec<MountInfo> {

/// Get all currently mounted filesystems.
///
/// `opt` excludes certain filesystems from consideration; see
/// `opt` excludes certain filesystems from consideration and allows for the synchronization of filesystems before running; see
/// [`Options`] for more information.
fn get_all_filesystems(opt: &Options) -> Vec<Filesystem> {
// Run a sync call before any operation if so instructed.
if opt.sync {
#[cfg(not(windows))]
unsafe {
#[cfg(not(target_os = "android"))]
uucore::libc::sync();
#[cfg(target_os = "android")]
uucore::libc::syscall(uucore::libc::SYS_sync);
}
}

// The list of all mounted filesystems.
//
// Filesystems excluded by the command-line options are
Expand Down Expand Up @@ -559,7 +576,7 @@ pub fn uu_app<'a>() -> Command<'a> {
Arg::new(OPT_SYNC)
.long("sync")
.overrides_with_all(&[OPT_NO_SYNC, OPT_SYNC])
.help("invoke sync before getting usage info"),
.help("invoke sync before getting usage info (non-windows only)"),
)
.arg(
Arg::new(OPT_TYPE)
Expand Down
14 changes: 8 additions & 6 deletions src/uu/dircolors/src/dircolors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,15 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let result;
if files.is_empty() {
result = parse(INTERNAL_DB.lines(), &out_format, "");
} else if files.len() > 1 {
return Err(UUsageError::new(
1,
format!("extra operand {}", files[1].quote()),
));
} else if files[0].eq("-") {
let fin = BufReader::new(std::io::stdin());
result = parse(fin.lines().filter_map(Result::ok), &out_format, files[0]);
} else {
if files.len() > 1 {
return Err(UUsageError::new(
1,
format!("extra operand {}", files[1].quote()),
));
}
match File::open(files[0]) {
Ok(f) => {
let fin = BufReader::new(f);
Expand Down
97 changes: 75 additions & 22 deletions src/uu/expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@
extern crate uucore;

use clap::{crate_version, Arg, ArgMatches, Command};
use std::error::Error;
use std::fmt;
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::num::IntErrorKind;
use std::str::from_utf8;
use unicode_width::UnicodeWidthChar;
use uucore::display::Quotable;
use uucore::error::{FromIo, UResult};
use uucore::error::{FromIo, UError, UResult};
use uucore::format_usage;

static ABOUT: &str = "Convert tabs in each FILE to spaces, writing to standard output.
Expand Down Expand Up @@ -57,6 +60,38 @@ fn is_space_or_comma(c: char) -> bool {
c == ' ' || c == ','
}

/// Errors that can occur when parsing a `--tabs` argument.
#[derive(Debug)]
enum ParseError {
InvalidCharacter(String),
SpecifierNotAtStartOfNumber(String, String),
TabSizeCannotBeZero,
TabSizeTooLarge(String),
TabSizesMustBeAscending,
}

impl Error for ParseError {}
impl UError for ParseError {}

impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::InvalidCharacter(s) => {
write!(f, "tab size contains invalid character(s): {}", s.quote())
}
Self::SpecifierNotAtStartOfNumber(specifier, s) => write!(
f,
"{} specifier not at start of number: {}",
specifier.quote(),
s.quote(),
),
Self::TabSizeCannotBeZero => write!(f, "tab size cannot be 0"),
Self::TabSizeTooLarge(s) => write!(f, "tab stop is too large {}", s.quote()),
Self::TabSizesMustBeAscending => write!(f, "tab sizes must be ascending"),
}
}
}

/// Parse a list of tabstops from a `--tabs` argument.
///
/// This function returns both the vector of numbers appearing in the
Expand All @@ -65,14 +100,14 @@ fn is_space_or_comma(c: char) -> bool {
/// in the list. This mode defines the strategy to use for computing the
/// number of spaces to use for columns beyond the end of the tab stop
/// list specified here.
fn tabstops_parse(s: &str) -> (RemainingMode, Vec<usize>) {
fn tabstops_parse(s: &str) -> Result<(RemainingMode, Vec<usize>), ParseError> {
// Leading commas and spaces are ignored.
let s = s.trim_start_matches(is_space_or_comma);

// If there were only commas and spaces in the string, just use the
// default tabstops.
if s.is_empty() {
return (RemainingMode::None, vec![DEFAULT_TABSTOP]);
return Ok((RemainingMode::None, vec![DEFAULT_TABSTOP]));
}

let mut nums = vec![];
Expand All @@ -89,23 +124,41 @@ fn tabstops_parse(s: &str) -> (RemainingMode, Vec<usize>) {
}
_ => {
// Parse a number from the byte sequence.
let num = from_utf8(&bytes[i..]).unwrap().parse::<usize>().unwrap();
let s = from_utf8(&bytes[i..]).unwrap();
match s.parse::<usize>() {
Ok(num) => {
// Tab size must be positive.
if num == 0 {
return Err(ParseError::TabSizeCannotBeZero);
}

// Tab size must be positive.
if num == 0 {
crash!(1, "tab size cannot be 0");
}
// Tab sizes must be ascending.
if let Some(last_stop) = nums.last() {
if *last_stop >= num {
return Err(ParseError::TabSizesMustBeAscending);
}
}

// Tab sizes must be ascending.
if let Some(last_stop) = nums.last() {
if *last_stop >= num {
crash!(1, "tab sizes must be ascending");
// Append this tab stop to the list of all tabstops.
nums.push(num);
break;
}
}
Err(e) => {
if *e.kind() == IntErrorKind::PosOverflow {
return Err(ParseError::TabSizeTooLarge(s.to_string()));
}

// Append this tab stop to the list of all tabstops.
nums.push(num);
break;
let s = s.trim_start_matches(char::is_numeric);
if s.starts_with('/') || s.starts_with('+') {
return Err(ParseError::SpecifierNotAtStartOfNumber(
s[0..1].to_string(),
s.to_string(),
));
} else {
return Err(ParseError::InvalidCharacter(s.to_string()));
}
}
}
}
}
}
Expand All @@ -115,7 +168,7 @@ fn tabstops_parse(s: &str) -> (RemainingMode, Vec<usize>) {
if nums.is_empty() {
nums = vec![DEFAULT_TABSTOP];
}
(remaining_mode, nums)
Ok((remaining_mode, nums))
}

struct Options {
Expand All @@ -131,9 +184,9 @@ struct Options {
}

impl Options {
fn new(matches: &ArgMatches) -> Self {
fn new(matches: &ArgMatches) -> Result<Self, ParseError> {
let (remaining_mode, tabstops) = match matches.values_of(options::TABS) {
Some(s) => tabstops_parse(&s.collect::<Vec<&str>>().join(",")),
Some(s) => tabstops_parse(&s.collect::<Vec<&str>>().join(","))?,
None => (RemainingMode::None, vec![DEFAULT_TABSTOP]),
};

Expand All @@ -158,22 +211,22 @@ impl Options {
None => vec!["-".to_owned()],
};

Self {
Ok(Self {
files,
tabstops,
tspaces,
iflag,
uflag,
remaining_mode,
}
})
}
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().get_matches_from(args);

expand(&Options::new(&matches)).map_err_context(|| "failed to write output".to_string())
expand(&Options::new(&matches)?).map_err_context(|| "failed to write output".to_string())
}

pub fn uu_app<'a>() -> Command<'a> {
Expand Down
31 changes: 13 additions & 18 deletions src/uu/ls/src/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2505,9 +2505,12 @@ fn display_file_name(
let mut width = name.width();

if let Some(ls_colors) = &config.color {
if let Ok(metadata) = path.p_buf.symlink_metadata() {
name = color_name(ls_colors, &path.p_buf, &name, &metadata, config);
}
name = color_name(
name,
&path.p_buf,
path.p_buf.symlink_metadata().ok().as_ref(),
ls_colors,
);
}

if config.format != Format::Long && !more_info.is_empty() {
Expand Down Expand Up @@ -2588,11 +2591,10 @@ fn display_file_name(
};

name.push_str(&color_name(
ls_colors,
escape_name(target.as_os_str(), &config.quoting_style),
&target_data.p_buf,
&target.to_string_lossy(),
&target_metadata,
config,
Some(&target_metadata),
ls_colors,
));
}
} else {
Expand Down Expand Up @@ -2623,19 +2625,12 @@ fn display_file_name(
}
}

fn color_name(
ls_colors: &LsColors,
path: &Path,
name: &str,
md: &Metadata,
config: &Config,
) -> String {
match ls_colors.style_for_path_with_metadata(path, Some(md)) {
fn color_name(name: String, path: &Path, md: Option<&Metadata>, ls_colors: &LsColors) -> String {
match ls_colors.style_for_path_with_metadata(path, md) {
Some(style) => {
let p = escape_name(OsStr::new(&name), &config.quoting_style);
return style.to_ansi_term_style().paint(p).to_string();
return style.to_ansi_term_style().paint(name).to_string();
}
None => escape_name(OsStr::new(&name), &config.quoting_style),
None => name,
}
}

Expand Down
42 changes: 38 additions & 4 deletions src/uu/mktemp/src/mktemp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (paths) GPGHome
// spell-checker:ignore (paths) GPGHome findxs

use clap::{crate_version, Arg, ArgMatches, Command};
use uucore::display::{println_verbatim, Quotable};
Expand Down Expand Up @@ -205,22 +205,38 @@ struct Params {
suffix: String,
}

/// Find the start and end indices of the last contiguous block of Xs.
///
/// If no contiguous block of at least three Xs could be found, this
/// function returns `None`.
///
/// # Examples
///
/// ```rust,ignore
/// assert_eq!(find_last_contiguous_block_of_xs("XXX_XXX"), Some((4, 7)));
/// assert_eq!(find_last_contiguous_block_of_xs("aXbXcX"), None);
/// ```
fn find_last_contiguous_block_of_xs(s: &str) -> Option<(usize, usize)> {
let j = s.rfind("XXX")? + 3;
let i = s[..j].rfind(|c| c != 'X').map_or(0, |i| i + 1);
Some((i, j))
}

impl Params {
fn from(options: Options) -> Result<Self, MkTempError> {
// Get the start and end indices of the randomized part of the template.
//
// For example, if the template is "abcXXXXyz", then `i` is 3 and `j` is 7.
let i = match options.template.find("XXX") {
let (i, j) = match find_last_contiguous_block_of_xs(&options.template) {
None => {
let s = match options.suffix {
None => options.template,
Some(s) => format!("{}{}", options.template, s),
};
return Err(MkTempError::TooFewXs(s));
}
Some(i) => i,
Some(indices) => indices,
};
let j = options.template.rfind("XXX").unwrap() + 3;

// Combine the directory given as an option and the prefix of the template.
//
Expand Down Expand Up @@ -450,3 +466,21 @@ fn exec(dir: &str, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> U

println_verbatim(path).map_err_context(|| "failed to print directory name".to_owned())
}

#[cfg(test)]
mod tests {
use crate::find_last_contiguous_block_of_xs as findxs;

#[test]
fn test_find_last_contiguous_block_of_xs() {
assert_eq!(findxs("XXX"), Some((0, 3)));
assert_eq!(findxs("XXX_XXX"), Some((4, 7)));
assert_eq!(findxs("XXX_XXX_XXX"), Some((8, 11)));
assert_eq!(findxs("aaXXXbb"), Some((2, 5)));
assert_eq!(findxs(""), None);
assert_eq!(findxs("X"), None);
assert_eq!(findxs("XX"), None);
assert_eq!(findxs("aXbXcX"), None);
assert_eq!(findxs("aXXbXXcXX"), None);
}
}
Loading

0 comments on commit e9076f0

Please sign in to comment.