From 16396b8a281c5cb01128466804e8df9464576850 Mon Sep 17 00:00:00 2001 From: Michael Greenberg Date: Thu, 2 May 2024 18:38:31 -0400 Subject: [PATCH] Minor tweaks (#71) * satisfy clippy, cleanup format strings and formatting * build on macos-latest * update workflow versions --- .github/workflows/build.yml | 16 +++--- src/bin/ffs.rs | 14 ++--- src/bin/pack.rs | 69 ++++++++++++------------- src/bin/unpack.rs | 23 ++++----- src/config.rs | 100 +++++++++++++++--------------------- src/format.rs | 59 ++++++++++----------- src/fs.rs | 29 +++++------ 7 files changed, 142 insertions(+), 168 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c2484ef..ae5b44a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: fail-fast: false matrix: os: - - macos-11 + - macos-latest - ubuntu-latest runs-on: ${{ matrix.os }} @@ -30,7 +30,7 @@ jobs: fi - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Build ffs/pack/unpack and run unit tests run: | @@ -46,7 +46,7 @@ jobs: run: PATH="$(pwd)/target/release:$PATH" ./run_tests.sh unpack - name: Upload macOS release build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: contains(matrix.os, 'macos') with: name: ffs.macos @@ -56,7 +56,7 @@ jobs: target/release/unpack - name: Upload Linux release build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: contains(matrix.os, 'ubuntu') with: name: ffs.linux @@ -80,10 +80,10 @@ jobs: fi - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Download binaries - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 - name: Install R uses: r-lib/actions/setup-r@v2 @@ -103,7 +103,7 @@ jobs: done - name: Upload Linux benchmark data - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: contains(matrix.os, 'ubuntu') with: name: benchmarks.linux @@ -116,7 +116,7 @@ jobs: steps: - name: Download binaries - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 - name: Rename binaries run: | diff --git a/src/bin/ffs.rs b/src/bin/ffs.rs index 4cef077..8bac0a8 100644 --- a/src/bin/ffs.rs +++ b/src/bin/ffs.rs @@ -34,14 +34,14 @@ fn main() { Format::Json => { let fs: FS = FS::new(config); - info!("mounting on {:?} with options {:?}", mount, options); + info!("mounting on {} with options {options:?}", mount.display()); match fuser::mount2(fs, &mount, &options) { Ok(()) => { info!("unmounted"); 0 } Err(e) => { - error!("I/O error: {}", e); + error!("I/O error: {e}"); ERROR_STATUS_FUSE } } @@ -49,14 +49,14 @@ fn main() { Format::Toml => { let fs: FS = FS::new(config); - info!("mounting on {:?} with options {:?}", mount, options); + info!("mounting on {} with options {options:?}", mount.display()); match fuser::mount2(fs, &mount, &options) { Ok(()) => { info!("unmounted"); 0 } Err(e) => { - error!("I/O error: {}", e); + error!("I/O error: {e}"); ERROR_STATUS_FUSE } } @@ -64,14 +64,14 @@ fn main() { Format::Yaml => { let fs: FS = FS::new(config); - info!("mounting on {:?} with options {:?}", mount, options); + info!("mounting on {} with options {options:?}", mount.display()); match fuser::mount2(fs, &mount, &options) { Ok(()) => { info!("unmounted"); 0 } Err(e) => { - error!("I/O error: {}", e); + error!("I/O error: {e}"); ERROR_STATUS_FUSE } } @@ -81,7 +81,7 @@ fn main() { if cleanup_mount { if mount.exists() { if let Err(e) = std::fs::remove_dir(&mount) { - warn!("Unable to clean up mountpoint '{}': {}", mount.display(), e); + warn!("Unable to clean up mountpoint '{}': {e}", mount.display()); } } else { warn!( diff --git a/src/bin/pack.rs b/src/bin/pack.rs index 452d8a4..d705d35 100644 --- a/src/bin/pack.rs +++ b/src/bin/pack.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use std::str; use std::str::FromStr; -use tracing::{debug, error, info, warn}; +use tracing::{error, info, warn}; use ffs::config::Config; use ffs::config::Symlink; @@ -40,6 +40,12 @@ pub struct Pack { regex: Regex, } +impl Default for Pack { + fn default() -> Self { + Self::new() + } +} + impl Pack { pub fn new() -> Self { Self { @@ -75,7 +81,7 @@ impl Pack { let mut link_follower = path.clone(); while link_follower.is_symlink() { if link_trail.contains(&link_follower) { - error!("Symlink loop detected at {:?}.", link_follower); + error!("Symlink loop detected at {}.", link_follower.display()); std::process::exit(ERROR_STATUS_FUSE); } link_trail.push(link_follower.clone()); @@ -92,8 +98,8 @@ impl Pack { // Err(_) => { // // Cannot call xattr::get on ._ file // warn!( - // "._ files, like {:?}, prevent xattr calls. It will be encoded in base64.", - // link_follower + // "._ files, like {}, prevent xattr calls. It will be encoded in base64.", + // link_follower.display() // ); // path_type = b"bytes".to_vec() // } @@ -130,8 +136,8 @@ impl Pack { { // the symlink is broken, so don't pack this file. warn!( - "The symlink at the end of the chain starting from '{:?}' is broken.", - path + "The symlink at the end of the chain starting from '{}' is broken.", + path.display() ); for link in link_trail { let symlink_map_data = &self.symlinks[&link]; @@ -150,16 +156,16 @@ impl Pack { let canonicalized = link_follower.canonicalize()?; if path.starts_with(&canonicalized) { error!( - "The symlink {:?} points to some ancestor directory: {:?}, causing an infinite loop.", - path, canonicalized + "The symlink {} points to some ancestor directory: {}, causing an infinite loop.", + path.display(), canonicalized.display(), ); std::process::exit(ERROR_STATUS_FUSE); } if !config.allow_symlink_escape && !canonicalized.starts_with(config.mount.as_ref().unwrap()) { - warn!("The symlink {:?} points to some file outside of the directory being packed. \ - Specify --allow-symlink-escape to allow pack to follow this symlink.", path); + warn!("The symlink {} points to some file outside of the directory being packed. \ + Specify --allow-symlink-escape to allow pack to follow this symlink.", path.display()); return Ok(None); } } @@ -170,14 +176,14 @@ impl Pack { // none of the symlinks on the chain have an xattr. Use the actual file's xattr if path_type.is_empty() { let canonicalized = path.canonicalize()?; - path_type = match xattr::get(&canonicalized, "user.type") { + path_type = match xattr::get(canonicalized, "user.type") { Ok(Some(xattr_type)) if config.allow_xattr => xattr_type, Ok(_) => b"auto".to_vec(), Err(_) => { // Cannot call xattr::get on ._ file warn!( - "._ files, like {:?}, prevent xattr calls. It will be encoded in base64.", - path + "._ files, like {}, prevent xattr calls. It will be encoded in base64.", + path.display(), ); b"bytes".to_vec() } @@ -191,19 +197,18 @@ impl Pack { if path.is_dir() && (path_type == "auto" || path_type != "named" && path_type != "list") { if path_type != "auto" { warn!( - "Unknown directory type '{}'. Possible types are 'named' or 'list'. \ - Resolving type automatically.", - path_type + "Unknown directory type '{path_type}'. Possible types are 'named' or 'list'. \ + Resolving type automatically." ); } let all_files_begin_with_num = fs::read_dir(path.clone())? .map(|res| res.map(|e| e.path())) .map(|e| e.unwrap().file_name().unwrap().to_str().unwrap().to_owned()) .all(|filename| { - filename.chars().nth(0).unwrap().is_digit(10) + filename.chars().nth(0).unwrap().is_ascii_digit() || filename.len() > 1 && filename.chars().nth(0).unwrap() == '-' - && filename.chars().nth(1).unwrap().is_digit(10) + && filename.chars().nth(1).unwrap().is_ascii_digit() }); if all_files_begin_with_num { path_type = "list" @@ -212,8 +217,6 @@ impl Pack { }; } - info!("type of {:?} is {}", path, path_type); - // return the value based on determined type match path_type { "named" => { @@ -227,11 +230,11 @@ impl Pack { for child in &children { let child_name = child.file_name().unwrap().to_str().unwrap(); if config.ignored_file(child_name) { - warn!("skipping ignored file {:?}", child_name); + warn!("skipping ignored file {}", child.display()); continue; } let name: String; - match xattr::get(&child, "user.original_name") { + match xattr::get(child, "user.original_name") { Ok(Some(original_name)) if config.allow_xattr => { let old_name = str::from_utf8(&original_name).unwrap(); if !config.valid_name(old_name) { @@ -250,14 +253,14 @@ impl Pack { } } self.depth += 1; - let value = self.pack(child.clone(), &config)?; + let value = self.pack(child.clone(), config)?; self.depth -= 1; if let Some(value) = value { entries.insert(name, value); } } - Ok(Some(V::from_named_dir(entries, &config))) + Ok(Some(V::from_named_dir(entries, config))) } "list" => { let mut numbers_filenames_paths = fs::read_dir(path.clone())? @@ -296,23 +299,21 @@ impl Pack { .collect::>(); numbers_filenames_paths.sort(); - info!("parsed numbers and filenames {:?}", numbers_filenames_paths); - let mut entries = Vec::with_capacity(numbers_filenames_paths.len()); for (_, filename, child) in numbers_filenames_paths { if config.ignored_file(&filename) { - warn!("skipping ignored file {:?}", child); + warn!("skipping ignored file {}", child.display()); continue; } self.depth += 1; - let value = self.pack(child, &config)?; + let value = self.pack(child, config)?; self.depth -= 1; if let Some(value) = value { entries.push(value); } } - Ok(Some(V::from_list_dir(entries, &config))) + Ok(Some(V::from_list_dir(entries, config))) } typ => { if let Ok(t) = Typ::from_str(typ) { @@ -325,14 +326,13 @@ impl Pack { if config.add_newlines && contents.ends_with('\n') { contents.truncate(contents.len() - 1); } - Ok(Some(V::from_string(t, contents, &config))) + Ok(Some(V::from_string(t, contents, config))) } - Ok(_) | Err(_) => Ok(Some(V::from_bytes(contents, &config))), + Ok(_) | Err(_) => Ok(Some(V::from_bytes(contents, config))), } } else { error!( - "This error should never be called. Received undetected and unknown type '{}' for file '{}'", - typ, + "Received undetected and unknown type '{typ}' for file '{}'", path.display() ); std::process::exit(ERROR_STATUS_FUSE); @@ -344,12 +344,11 @@ impl Pack { fn main() -> std::io::Result<()> { let config = Config::from_pack_args(); - debug!("received config: {:?}", config); let mount = match &config.mount { Some(mount) => mount, None => { - error!("Cannot pack unspecified directory."); + error!("You must specify a directory to pack."); std::process::exit(ERROR_STATUS_CLI); } }; diff --git a/src/bin/unpack.rs b/src/bin/unpack.rs index 5dcd137..d36fa15 100644 --- a/src/bin/unpack.rs +++ b/src/bin/unpack.rs @@ -1,5 +1,5 @@ use fuser::FileType; -use tracing::{debug, error, info, warn}; +use tracing::{error, info, warn}; use std::collections::VecDeque; use std::fs; @@ -33,11 +33,11 @@ where .open(&path)?; // write `s` into that file - f.write(s.as_bytes())?; + f.write_all(s.as_bytes())?; // set metadata according to `t` if config.allow_xattr { - xattr::set(&path, "user.type", format!("{}", t).as_bytes())?; + xattr::set(&path, "user.type", t.to_string().as_bytes())?; } } format::Node::Bytes(b) => { @@ -52,7 +52,7 @@ where // set metadata to bytes if config.allow_xattr { - xattr::set(&path, "user.type", format!("{}", Typ::Bytes).as_bytes())?; + xattr::set(&path, "user.type", Typ::Bytes.to_string().as_bytes())?; } } format::Node::List(vs) => { @@ -71,9 +71,9 @@ where for (i, child) in vs.into_iter().enumerate() { // TODO(mmg) 2021-06-08 ability to add prefixes let name = if config.pad_element_names { - format!("{:0width$}", i, width = width) + format!("{i:0width$}") } else { - format!("{}", i) + format!("{i}") }; let child_path = path.join(name); @@ -108,7 +108,7 @@ where } ffs::config::Munge::Filter => { // TODO(mmg) 2023-03-06 support logging - warn!("skipping '{}'", field); + warn!("skipping '{field}'"); continue; } } @@ -135,12 +135,11 @@ where fn main() -> std::io::Result<()> { let config = Config::from_unpack_args(); - debug!("received config: {:?}", config); let mount = match &config.mount { Some(mount) => mount.clone(), None => { - error!("Directory not specified"); + error!("You must specify a directory to unpack."); std::process::exit(ERROR_STATUS_CLI); } }; @@ -154,7 +153,7 @@ fn main() -> std::io::Result<()> { } }; - let result = match &config.input_format { + match &config.input_format { Format::Json => { let value = JsonValue::from_reader(reader); if value.kind() == FileType::Directory { @@ -182,7 +181,5 @@ fn main() -> std::io::Result<()> { std::process::exit(ERROR_STATUS_FUSE); } } - }; - - result + } } diff --git a/src/config.rs b/src/config.rs index 4c8f27f..6a74ca1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -133,7 +133,7 @@ impl Config { } else if shell == "zsh" { clap::Shell::Zsh } else { - eprintln!("Can't generate completions for '{}'.", shell); + eprintln!("Can't generate completions for '{shell}'."); std::process::exit(ERROR_STATUS_CLI); }; cli::ffs().gen_completions_to("ffs", shell, &mut std::io::stdout()); @@ -172,7 +172,7 @@ impl Config { Some(s) => match str::parse(s) { Ok(munge) => munge, Err(_) => { - warn!("Invalid `--munge` mode '{}', using 'rename'.", s); + warn!("Invalid `--munge` mode '{s}', using 'rename'."); Munge::Rename } }, @@ -183,9 +183,8 @@ impl Config { Ok(filemode) => filemode, Err(e) => { error!( - "Couldn't parse `--mode {}`: {}.", - args.value_of("FILEMODE").unwrap(), - e + "Couldn't parse `--mode {}`: {e}.", + args.value_of("FILEMODE").unwrap() ); std::process::exit(ERROR_STATUS_CLI) } @@ -207,9 +206,8 @@ impl Config { Ok(filemode) => filemode, Err(e) => { error!( - "Couldn't parse `--dirmode {}`: {}.", - args.value_of("DIRMODE").unwrap(), - e + "Couldn't parse `--dirmode {}`: {e}.", + args.value_of("DIRMODE").unwrap() ); std::process::exit(ERROR_STATUS_CLI) } @@ -223,8 +221,7 @@ impl Config { Err(e) => { let euid = unsafe { libc::geteuid() }; warn!( - "Couldn't parse '{}' as a uid ({}), defaulting to effective uid ({})", - uid_string, e, euid + "Couldn't parse '{uid_string}' as a uid ({e}), defaulting to effective uid ({euid})" ); config.uid = euid; } @@ -237,8 +234,7 @@ impl Config { Err(e) => { let egid = unsafe { libc::getegid() }; warn!( - "Couldn't parse '{}' as a gid ({}), defaulting to effective gid ({})", - gid_string, e, egid + "Couldn't parse '{gid_string}' as a gid ({e}), defaulting to effective gid ({egid})" ); config.gid = egid; } @@ -272,8 +268,7 @@ impl Config { match e { format::ParseFormatError::NoSuchFormat(s) => { warn!( - "Unrecognized format '{}', inferring from {}.", - s, + "Unrecognized format '{s}', inferring from {}.", output.display(), ) } @@ -323,10 +318,9 @@ impl Config { } // If the mountpoint can't be created, give up and tell the user about --mount. if let Err(e) = std::fs::create_dir(&mount_dir) { - error!("Couldn't create mountpoint '{}': {}. Use `--mount MOUNT` to specify a mountpoint.", - mount_dir.display(), - e - ); + error!("Couldn't create mountpoint '{}': {e}. Use `--mount MOUNT` to specify a mountpoint.", + mount_dir.display(), + ); std::process::exit(ERROR_STATUS_FUSE); } // We did it! @@ -426,9 +420,8 @@ impl Config { // If the mountpoint can't be created, give up and tell the user about --mount. if let Err(e) = std::fs::create_dir(&mount_dir) { error!( - "Couldn't create mountpoint '{}': {}. Use `--mount MOUNT` to specify a mountpoint.", - mount_dir.display(), - e + "Couldn't create mountpoint '{}': {e}. Use `--mount MOUNT` to specify a mountpoint.", + mount_dir.display() ); std::process::exit(ERROR_STATUS_FUSE); } @@ -473,11 +466,15 @@ impl Config { .and_then(|s| s.parse::()) { Ok(format) => format, - Err(_) => { - warn!( - "Unrecognized format {}, defaulting to JSON.", - input_source.display() - ); + Err(e) => { + match e { + format::ParseFormatError::NoFormatProvided => { + warn!("No extension detected, defaulting to JSON.") + } + format::ParseFormatError::NoSuchFormat(s) => { + warn!("Unrecognized extension {s}, defaulting to JSON.") + } + }; Format::Json } }, @@ -501,10 +498,7 @@ impl Config { Err(e) => { match e { format::ParseFormatError::NoSuchFormat(s) => { - warn!( - "Unrecognized format '{}', inferring from input and output.", - s - ) + warn!("Unrecognized format '{s}', inferring from input and output.") } format::ParseFormatError::NoFormatProvided => { debug!("Inferring output format from input.") @@ -519,8 +513,8 @@ impl Config { Ok(format) => format, Err(_) => { warn!( - "Unrecognized format {}, defaulting to input format '{}'.", - s, config.input_format + "Unrecognized format {s}, defaulting to input format '{}'.", + config.input_format ); config.input_format } @@ -560,7 +554,7 @@ impl Config { } else if shell == "zsh" { clap::Shell::Zsh } else { - eprintln!("Can't generate completions for '{}'.", shell); + eprintln!("Can't generate completions for '{shell}'."); std::process::exit(ERROR_STATUS_CLI); }; cli::unpack().gen_completions_to("unpack", shell, &mut std::io::stdout()); @@ -597,7 +591,7 @@ impl Config { Some(s) => match str::parse(s) { Ok(munge) => munge, Err(_) => { - warn!("Invalid `--munge` mode '{}', using 'rename'.", s); + warn!("Invalid `--munge` mode '{s}', using 'rename'."); Munge::Rename } }, @@ -623,7 +617,7 @@ impl Config { // infer and create mountpoint from filename as possible config.mount = match args.value_of("INTO") { Some(mount_point) => { - match std::fs::create_dir(&mount_point) { + match std::fs::create_dir(mount_point) { Ok(_) => Some(PathBuf::from(mount_point)), Err(_) => { // if dir is empty then we can use it @@ -633,10 +627,7 @@ impl Config { Some(PathBuf::from(mount_point)) } else { // dir exists but is not empty - error!( - "Directory `{}` already exists and is not empty.", - mount_point - ); + error!("Directory `{mount_point}` already exists and is not empty."); std::process::exit(ERROR_STATUS_FUSE); } } @@ -670,9 +661,8 @@ impl Config { // If the mountpoint can't be created, give up and tell the user about --mount. if let Err(e) = std::fs::create_dir(&mount_dir) { error!( - "Couldn't create directory '{}': {}. Use `--into DIRECTORY` to specify a directory.", - mount_dir.display(), - e + "Couldn't create directory '{}': {e}. Use `--into DIRECTORY` to specify a directory.", + mount_dir.display() ); std::process::exit(ERROR_STATUS_FUSE); } @@ -701,7 +691,7 @@ impl Config { Err(e) => { match e { format::ParseFormatError::NoSuchFormat(s) => { - warn!("Unrecognized format '{}', inferring from input.", s) + warn!("Unrecognized format '{s}', inferring from input.") } format::ParseFormatError::NoFormatProvided => { debug!("Inferring format from input.") @@ -750,7 +740,7 @@ impl Config { } else if shell == "zsh" { clap::Shell::Zsh } else { - eprintln!("Can't generate completions for '{}'.", shell); + eprintln!("Can't generate completions for '{shell}'."); std::process::exit(ERROR_STATUS_CLI); }; cli::pack().gen_completions_to("pack", shell, &mut std::io::stdout()); @@ -794,10 +784,7 @@ impl Config { Some(s) => match str::parse(s) { Ok(depth) => Some(depth), Err(_) => { - error!( - "Invalid `--max-depth` '{}', must be a non-negative integer.", - s - ); + error!("Invalid `--max-depth` '{s}', must be a non-negative integer."); std::process::exit(ERROR_STATUS_CLI); } }, @@ -810,7 +797,7 @@ impl Config { Some(s) => match str::parse(s) { Ok(munge) => munge, Err(_) => { - warn!("Invalid `--munge` mode '{}', using 'rename'.", s); + warn!("Invalid `--munge` mode '{s}', using 'rename'."); Munge::Rename } }, @@ -866,10 +853,7 @@ impl Config { Err(e) => { match e { format::ParseFormatError::NoSuchFormat(s) => { - warn!( - "Unrecognized format '{}', inferring from input and output.", - s - ) + warn!("Unrecognized format '{s}', inferring from input and output.") } format::ParseFormatError::NoFormatProvided => { debug!("Inferring output format from input.") @@ -884,8 +868,8 @@ impl Config { Ok(format) => format, Err(_) => { warn!( - "Unrecognized format {}, defaulting to input format '{}'.", - s, config.input_format + "Unrecognized format {s}, defaulting to input format '{}'.", + config.input_format ); config.input_format } @@ -915,7 +899,7 @@ impl Config { } else if s == ".." { "_..".into() } else { - s.replace("\0", "_NUL_").replace("/", "_SLASH_") + s.replace('\0', "_NUL_").replace('/', "_SLASH_") } } @@ -956,8 +940,8 @@ impl Config { Input::Stdin => Some(Box::new(std::io::stdin())), Input::File(file) => { let fmt = self.input_format; - let file = std::fs::File::open(&file).unwrap_or_else(|e| { - error!("Unable to open {} for {} input: {}", file.display(), fmt, e); + let file = std::fs::File::open(file).unwrap_or_else(|e| { + error!("Unable to open {} for {fmt} input: {e}", file.display()); std::process::exit(ERROR_STATUS_FUSE); }); Some(Box::new(file)) diff --git a/src/format.rs b/src/format.rs index 8fab512..0ad694d 100644 --- a/src/format.rs +++ b/src/format.rs @@ -18,9 +18,9 @@ macro_rules! time_ns { let msg = $msg; let elapsed = start.elapsed().as_nanos(); if $timing { - eprintln!("{},{}", msg, elapsed); + eprintln!("{msg},{elapsed}"); } else { - info!("{} ({}ns)", msg, elapsed); + info!("{msg} ({elapsed}ns)"); } v }}; @@ -226,8 +226,8 @@ pub mod json { match self { Value::Null => Node::String(Typ::Null, "".into()), // always empty - Value::Bool(b) => Node::String(Typ::Boolean, format!("{}{}", b, nl)), - Value::Number(n) => Node::String(Typ::Float, format!("{}{}", n, nl)), + Value::Bool(b) => Node::String(Typ::Boolean, format!("{b}{nl}")), + Value::Number(n) => Node::String(Typ::Float, format!("{n}{nl}")), Value::String(s) => { if config.try_decode_base64 { if let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(&s) { @@ -263,7 +263,7 @@ pub mod json { } else if contents == "false" { Value::Bool(false) } else { - debug!("string '{}' tagged as boolean", contents); + debug!("string '{contents}' tagged as boolean"); Value::String(contents) } } @@ -273,7 +273,7 @@ pub mod json { if let Ok(n) = serde_json::Number::from_str(&contents) { Value::Number(n) } else { - debug!("string '{}' tagged as float", contents); + debug!("string '{contents}' tagged as float"); Value::String(contents) } } @@ -281,7 +281,7 @@ pub mod json { if let Ok(n) = serde_json::Number::from_str(&contents) { Value::Number(n) } else { - debug!("string '{}' tagged as float", contents); + debug!("string '{contents}' tagged as float"); Value::String(contents) } } @@ -289,7 +289,7 @@ pub mod json { if contents.is_empty() { Value::Null } else { - debug!("string '{}' tagged as null", contents); + debug!("string '{contents}' tagged as null"); Value::String(contents) } } @@ -354,7 +354,7 @@ pub mod toml { | Toml::Float(_) | Toml::Integer(_) | Toml::String(_) => 1, - Toml::Array(vs) => vs.iter().map(|v| toml_size(v)).sum::() + 1, + Toml::Array(vs) => vs.iter().map(toml_size).sum::() + 1, Toml::Table(fvs) => fvs.iter().map(|(_, v)| toml_size(v)).sum::() + 1, } } @@ -375,10 +375,10 @@ pub mod toml { let nl = if config.add_newlines { "\n" } else { "" }; match self.0 { - Toml::Boolean(b) => Node::String(Typ::Boolean, format!("{}{}", b, nl)), + Toml::Boolean(b) => Node::String(Typ::Boolean, format!("{b}{nl}")), Toml::Datetime(s) => Node::String(Typ::Datetime, s.to_string()), - Toml::Float(n) => Node::String(Typ::Float, format!("{}{}", n, nl)), - Toml::Integer(n) => Node::String(Typ::Integer, format!("{}{}", n, nl)), + Toml::Float(n) => Node::String(Typ::Float, format!("{n}{nl}")), + Toml::Integer(n) => Node::String(Typ::Integer, format!("{n}{nl}")), Toml::String(s) => { if config.try_decode_base64 { if let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(&s) { @@ -418,7 +418,7 @@ pub mod toml { } else if contents == "false" { Toml::Boolean(false) } else { - debug!("string '{}' tagged as boolean", contents); + debug!("string '{contents}' tagged as boolean"); Toml::String(contents) } } @@ -426,10 +426,7 @@ pub mod toml { Typ::Datetime => match str::parse(&contents) { Ok(datetime) => Toml::Datetime(datetime), Err(e) => { - debug!( - "string '{}' tagged as datetime, didn't parse: {}", - contents, e - ); + debug!("string '{contents}' tagged as datetime, didn't parse: {e}"); Toml::String(contents) } }, @@ -437,7 +434,7 @@ pub mod toml { if let Ok(n) = f64::from_str(&contents) { Toml::Float(n) } else { - debug!("string '{}' tagged as float", contents); + debug!("string '{contents}' tagged as float"); Toml::String(contents) } } @@ -445,7 +442,7 @@ pub mod toml { if let Ok(n) = i64::from_str(&contents) { Toml::Integer(n) } else { - debug!("string '{}' tagged as float", contents); + debug!("string '{contents}' tagged as float"); Toml::String(contents) } } @@ -453,7 +450,7 @@ pub mod toml { if contents.is_empty() { Toml::String(contents) } else { - debug!("string '{}' tagged as null", contents); + debug!("string '{contents}' tagged as null"); Toml::String(contents) } } @@ -537,18 +534,18 @@ pub mod yaml { | Yaml::Null | Yaml::BadValue | Yaml::Alias(_) => 1, - Yaml::Array(vs) => vs.iter().map(|v| yaml_size(v)).sum::() + 1, + Yaml::Array(vs) => vs.iter().map(yaml_size).sum::() + 1, Yaml::Hash(fvs) => fvs.iter().map(|(_, v)| yaml_size(v)).sum::() + 1, } } fn yaml_key_to_string(v: Yaml) -> String { match v { - Yaml::Boolean(b) => format!("{}", b), + Yaml::Boolean(b) => format!("{b}"), Yaml::Real(s) => s, - Yaml::Integer(n) => format!("{}", n), + Yaml::Integer(n) => format!("{n}"), Yaml::String(s) => s, - Yaml::Alias(n) => format!("alias{}", n), + Yaml::Alias(n) => format!("alias{n}"), Yaml::Array(vs) => { let mut hasher = std::collections::hash_map::DefaultHasher::new(); vs.hash(&mut hasher); @@ -581,9 +578,9 @@ pub mod yaml { match self.0 { Yaml::Null => Node::String(Typ::Null, "".into()), - Yaml::Boolean(b) => Node::String(Typ::Boolean, format!("{}{}", b, nl)), + Yaml::Boolean(b) => Node::String(Typ::Boolean, format!("{b}{nl}")), Yaml::Real(s) => Node::String(Typ::Float, s + nl), - Yaml::Integer(n) => Node::String(Typ::Integer, format!("{}{}", n, nl)), + Yaml::Integer(n) => Node::String(Typ::Integer, format!("{n}{nl}")), Yaml::String(s) => { if config.try_decode_base64 { if let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(&s) { @@ -600,7 +597,7 @@ pub mod yaml { .collect(), ), // ??? 2021-06-21 support aliases w/hard links? - Yaml::Alias(n) => Node::Bytes(format!("alias{}{}", n, nl).into_bytes()), + Yaml::Alias(n) => Node::Bytes(format!("alias{n}{nl}").into_bytes()), Yaml::BadValue => Node::Bytes("bad YAML value".into()), } } @@ -628,7 +625,7 @@ pub mod yaml { } else if contents == "false" { Value(Yaml::Boolean(false)) } else { - debug!("string '{}' tagged as boolean", contents); + debug!("string '{contents}' tagged as boolean"); Value(Yaml::String(contents)) } } @@ -638,7 +635,7 @@ pub mod yaml { if let Ok(_n) = f64::from_str(&contents) { Value(Yaml::Real(contents)) } else { - debug!("string '{}' tagged as float", contents); + debug!("string '{contents}' tagged as float"); Value(Yaml::String(contents)) } } @@ -646,7 +643,7 @@ pub mod yaml { if let Ok(n) = i64::from_str(&contents) { Value(Yaml::Integer(n)) } else { - debug!("string '{}' tagged as float", contents); + debug!("string '{contents}' tagged as float"); Value(Yaml::String(contents)) } } @@ -654,7 +651,7 @@ pub mod yaml { if contents.is_empty() { Value(Yaml::Null) } else { - debug!("string '{}' tagged as null", contents); + debug!("string '{contents}' tagged as null"); Value(Yaml::String(contents)) } } diff --git a/src/fs.rs b/src/fs.rs index 675b240..5223bfc 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -167,9 +167,9 @@ where for (i, child) in vs.into_iter().enumerate() { // TODO 2021-06-08 ability to add prefixes let name = if self.config.pad_element_names { - format!("{:0width$}", i, width = width) + format!("{i:0width$}") } else { - format!("{}", i) + format!("{i}") }; let kind = child.kind(); @@ -216,7 +216,7 @@ where nfield } Munge::Filter => { - warn!("skipping '{}'", field); + warn!("skipping '{field}'"); continue; } } @@ -234,8 +234,7 @@ where ); let original_name = if original != nfield { info!( - "renamed {} to {} (inode {} with parent {})", - original, nfield, child_id, inum + "renamed {original} to {nfield} (inode {child_id} with parent {inum})" ); Some(original) } else { @@ -281,8 +280,7 @@ where None => return Ok(()), }; - while !worklist.is_empty() { - let node = worklist.pop().unwrap(); + while let Some(node) = worklist.pop() { if let Some(nodes) = self.resolve_node(node)? { worklist.extend(nodes); } @@ -353,7 +351,7 @@ where let v = time_ns!("reading", V::from_reader(reader), config.timing); if v.kind() != FileType::Directory { - error!("The root of the filesystem must be a directory, but '{}' only generates a single file.", v); + error!("The root of the filesystem must be a directory, but '{v}' only generates a single file."); std::process::exit(ERROR_STATUS_FUSE); } @@ -513,7 +511,7 @@ where files.sort_unstable_by(|(name1, _), (name2, _)| name1.cmp(name2)); for (name, DirEntry { inum, .. }) in files.iter() { if self.config.ignored_file(name) { - warn!("skipping ignored file '{}'", name); + warn!("skipping ignored file '{name}'"); continue; } let v = self.as_value(*inum); @@ -533,7 +531,7 @@ where ) in files.iter() { if self.config.ignored_file(name) { - warn!("skipping ignored file '{}'", name); + warn!("skipping ignored file '{name}'"); continue; } let v = self.as_value(*inum); @@ -577,7 +575,7 @@ where files.sort_unstable_by(|(name1, _), (name2, _)| name1.cmp(name2)); for (name, inum) in files { if self.config.ignored_file(&name) { - warn!("skipping ignored file '{}'", name); + warn!("skipping ignored file '{name}'"); continue; } let v = self.as_other_value(inum); @@ -594,7 +592,7 @@ where .collect::>(); for (name, inum, original_name) in files.iter() { if self.config.ignored_file(name) { - warn!("skipping ignored file '{}'", name); + warn!("skipping ignored file '{name}'"); continue; } let v = self.as_other_value(*inum); @@ -1001,7 +999,7 @@ where } if let Some(size) = size { - info!("truncate() to {}", size); + info!("truncate() to {size}"); match self.get_mut(ino) { Ok(inode) => match &mut inode.entry { @@ -1286,7 +1284,6 @@ where for (i, entry) in dot_entries .into_iter() .chain(entries) - .into_iter() .enumerate() .skip(offset as usize) { @@ -1338,7 +1335,7 @@ where // make sure we have a good file type let file_type = mode & libc::S_IFMT as u32; - if !vec![libc::S_IFREG as u32, libc::S_IFDIR as u32].contains(&file_type) { + if ![libc::S_IFREG as u32, libc::S_IFDIR as u32].contains(&file_type) { warn!( "mknod only supports regular files and directories; got {:o}", mode @@ -1894,7 +1891,7 @@ where }; // extend the vector - let extra_bytes = (offset + length as i64) - contents.len() as i64; + let extra_bytes = (offset + length) - contents.len() as i64; if extra_bytes > 0 { contents.resize(contents.len() + extra_bytes as usize, 0); }