diff --git a/Cargo.lock b/Cargo.lock index 225b06ba..2f1e5414 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -919,6 +919,19 @@ name = "camino" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +dependencies = [ + "serde", +] + +[[package]] +name = "camino-tempfile" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb905055fa81e4d427f919b2cd0d76a998267de7d225ea767a1894743a5263c2" +dependencies = [ + "camino", + "tempfile", +] [[package]] name = "cast" @@ -1395,6 +1408,7 @@ dependencies = [ "anyhow", "arrayref", "built", + "camino-tempfile", "cfg-if", "cpclib-asm", "cpclib-basic", @@ -1417,7 +1431,6 @@ dependencies = [ "path-absolutize", "pretty_assertions", "serde", - "tempfile", "time", ] @@ -1431,7 +1444,7 @@ dependencies = [ "beef", "build-deps", "built", - "camino", + "camino-tempfile", "cc", "cfg-if", "chardetng", @@ -1468,7 +1481,6 @@ dependencies = [ "serde", "smartstring", "substring", - "tempfile", "velcro", ] @@ -1498,7 +1510,7 @@ version = "0.8.2" dependencies = [ "build-deps", "built", - "camino", + "camino-tempfile", "const_format", "cpclib-asm", "cpclib-common", @@ -1511,7 +1523,6 @@ dependencies = [ "pretty_assertions", "regex", "serial_test", - "tempfile", "test-generator", "time", ] @@ -1521,8 +1532,6 @@ name = "cpclib-bdasm" version = "0.8.2" dependencies = [ "built", - "camino", - "clap 4.5.13", "const_format", "cpclib-asm", "cpclib-common", @@ -1538,7 +1547,7 @@ dependencies = [ "assert_cmd", "build-deps", "built", - "camino", + "camino-tempfile", "cpclib-asm", "cpclib-basm", "cpclib-common", @@ -1555,7 +1564,6 @@ dependencies = [ "serde_yaml", "serial_test", "shlex", - "tempfile", "test-generator", "thiserror", "topologic", @@ -1568,6 +1576,7 @@ dependencies = [ "bitfield", "bitflags 2.6.0", "bitvec", + "camino", "clap 4.5.13", "itertools 0.12.1", "num", @@ -1615,7 +1624,7 @@ version = "0.8.1" dependencies = [ "arrayref", "built", - "camino", + "camino-tempfile", "cfg-if", "cpclib-common", "cpclib-tokens", @@ -1629,7 +1638,6 @@ dependencies = [ "matches", "serde", "simple_logger", - "tempfile", "thiserror", ] @@ -1654,11 +1662,11 @@ version = "0.8.1" dependencies = [ "anyhow", "built", + "camino-tempfile", "cpclib", "crossbeam-channel", "exitcode", "notify", - "tempfile", ] [[package]] @@ -1677,6 +1685,7 @@ name = "cpclib-sna" version = "0.8.1" dependencies = [ "built", + "camino-tempfile", "cfg-if", "comfy-table", "cpclib-common", @@ -1688,7 +1697,6 @@ dependencies = [ "rustyline", "serde", "similar-asserts", - "tempfile", ] [[package]] @@ -1716,6 +1724,7 @@ name = "cpclib-visual-bndbuild" version = "0.4.0" dependencies = [ "built", + "camino", "cpclib-bndbuild", "cpclib-common", "eframe 0.28.1", @@ -1750,6 +1759,7 @@ version = "0.8.0" dependencies = [ "arrayref", "built", + "camino-tempfile", "cfg-if", "cpclib-common", "cpclib-disc", @@ -1762,7 +1772,6 @@ dependencies = [ "matches", "path-absolutize", "serde", - "tempfile", "ureq", ] @@ -1773,6 +1782,7 @@ dependencies = [ "anyhow", "arrayref", "built", + "camino-tempfile", "cfg-if", "cpclib-common", "cpclib-disc", @@ -1792,7 +1802,6 @@ dependencies = [ "rustyline-derive", "serde", "subprocess", - "tempfile", "term_grid", "termize", "time", diff --git a/Cargo.toml b/Cargo.toml index 35fe9d75..7e7cbf47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,6 +84,7 @@ bitflags = "2.6.0" bitvec = "1.0.1" built = { version = "0.7.4", features = ["chrono"] } camino = "1.1.7" +camino-tempfile = "1.1.1" cc = "1.1.7" cfg-if = "1.0.0" chardetng = { version = "0.1.17", features = ["multithreading"] } @@ -155,7 +156,6 @@ strsim = "0.11.1" subprocess = { version = "0.2.9" } substring = "1.4.5" syn = "2.0.72" -tempfile = "3.10.1" term_grid = { version = "0.2.0" } termize = { version = "0.1.1" } test-generator = "0.3.1" diff --git a/cpclib-asm/Cargo.toml b/cpclib-asm/Cargo.toml index abb8e96f..fca2143c 100644 --- a/cpclib-asm/Cargo.toml +++ b/cpclib-asm/Cargo.toml @@ -24,7 +24,7 @@ cpclib-image.workspace = true arrayref.workspace = true assert_matches.workspace = true -camino.workspace = true +camino-tempfile.workspace = true cfg-if.workspace = true choice_nocase.workspace = true codespan-reporting.workspace = true @@ -47,7 +47,6 @@ rust-embed = { workspace = true, features = ["compression", "debug-embed"] } serde = { workspace = true, features = ["derive"] } smartstring.workspace = true substring.workspace = true -tempfile.workspace = true velcro.workspace = true rayon-cond = {version="0.3.0", optional= true} diff --git a/cpclib-asm/src/assembler/file.rs b/cpclib-asm/src/assembler/file.rs index f0a5cbdc..df7a02b0 100644 --- a/cpclib-asm/src/assembler/file.rs +++ b/cpclib-asm/src/assembler/file.rs @@ -2,7 +2,7 @@ use std::collections::VecDeque; use std::fs::File; use std::io::Read; -use camino::{Utf8Path, Utf8PathBuf}; +use cpclib_common::camino::{Utf8Path, Utf8PathBuf}; use cpclib_disc::amsdos::AmsdosHeader; use either::Either; diff --git a/cpclib-asm/src/assembler/mod.rs b/cpclib-asm/src/assembler/mod.rs index dbe16e5e..bf2c7cd1 100644 --- a/cpclib-asm/src/assembler/mod.rs +++ b/cpclib-asm/src/assembler/mod.rs @@ -27,9 +27,9 @@ use std::ops::{Deref, Neg}; use std::sync::{Arc, RwLock}; use std::time::Instant; -use camino::{Utf8Path, Utf8PathBuf}; use cpclib_basic::*; use cpclib_common::bitvec::prelude::BitVec; +use cpclib_common::camino::{Utf8Path, Utf8PathBuf}; use cpclib_common::itertools::Itertools; use cpclib_common::smallvec::SmallVec; use cpclib_common::smol_str::SmolStr; @@ -1746,11 +1746,11 @@ impl Env { self.sna_version } - pub fn save_sna>(&self, fname: P) -> Result<(), std::io::Error> { + pub fn save_sna>(&self, fname: P) -> Result<(), std::io::Error> { self.sna().save(fname, self.sna_version()) } - pub fn save_cpr>(&self, fname: P) -> Result<(), AssemblerError> { + pub fn save_cpr>(&self, fname: P) -> Result<(), AssemblerError> { let cpr_asm = self.cpr.as_ref().unwrap(); let cpr = cpr_asm.build_cpr()?; cpr.save(fname) diff --git a/cpclib-asm/src/assembler/processed_token.rs b/cpclib-asm/src/assembler/processed_token.rs index 45952744..f0274ee3 100644 --- a/cpclib-asm/src/assembler/processed_token.rs +++ b/cpclib-asm/src/assembler/processed_token.rs @@ -4,7 +4,7 @@ use std::fmt::{Debug, Formatter}; use std::ops::Deref; use std::sync::Arc; -use camino::Utf8PathBuf; +use cpclib_common::camino::Utf8PathBuf; use cpclib_common::itertools::Itertools; #[cfg(all(not(target_arch = "wasm32"), feature = "rayon"))] use cpclib_common::rayon::prelude::*; diff --git a/cpclib-asm/src/assembler/report.rs b/cpclib-asm/src/assembler/report.rs index 34279141..b236573d 100644 --- a/cpclib-asm/src/assembler/report.rs +++ b/cpclib-asm/src/assembler/report.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use std::time::Instant; -use camino::Utf8PathBuf; +use cpclib_common::camino::Utf8PathBuf; use cpclib_common::itertools::Itertools; use super::Env; diff --git a/cpclib-asm/src/assembler/save_command.rs b/cpclib-asm/src/assembler/save_command.rs index 0b7ec027..f74243b0 100644 --- a/cpclib-asm/src/assembler/save_command.rs +++ b/cpclib-asm/src/assembler/save_command.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use camino::Utf8PathBuf; +use cpclib_common::camino::Utf8PathBuf; use cpclib_disc::amsdos::{AmsdosFile, AmsdosFileName}; use cpclib_disc::disc::Disc; use cpclib_disc::edsk::Head; diff --git a/cpclib-asm/src/implementation/listing.rs b/cpclib-asm/src/implementation/listing.rs index 67b49f39..41cdaefe 100644 --- a/cpclib-asm/src/implementation/listing.rs +++ b/cpclib-asm/src/implementation/listing.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use std::collections::HashMap; use std::fmt; -use camino::Utf8Path; +use cpclib_common::camino::Utf8Path; use cpclib_tokens::tokens::*; use crate::error::*; diff --git a/cpclib-asm/src/lib.rs b/cpclib-asm/src/lib.rs index 2fa41493..967b58a0 100644 --- a/cpclib-asm/src/lib.rs +++ b/cpclib-asm/src/lib.rs @@ -13,6 +13,7 @@ #![feature(slice_take)] #![feature(write_all_vectored)] +// mod rewrite; /// Implementation of various behavior for the tokens of cpclib_tokens pub mod implementation; diff --git a/cpclib-asm/src/parser/context.rs b/cpclib-asm/src/parser/context.rs index 0bcd3387..85a4a6a3 100644 --- a/cpclib-asm/src/parser/context.rs +++ b/cpclib-asm/src/parser/context.rs @@ -1,10 +1,10 @@ use std::borrow::{Borrow, Cow}; use std::collections::HashSet; use std::ops::Deref; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::{LazyLock, RwLock}; -use camino::{Utf8Path, Utf8PathBuf}; +use cpclib_common::camino::{Utf8Path, Utf8PathBuf}; use cpclib_common::winnow::BStr; use either::Either; use regex::Regex; @@ -356,12 +356,11 @@ impl ParserOptions { return Ok(current_path); } else { - let glob = - GlobBuilder::new(current_path.as_path().as_str()) - .case_insensitive(true) - .literal_separator(true) - .build() - .unwrap(); + let glob = GlobBuilder::new(current_path.as_path().as_str()) + .case_insensitive(true) + .literal_separator(true) + .build() + .unwrap(); let matcher = glob.compile_matcher(); for entry in std::fs::read_dir(search).unwrap() { @@ -487,7 +486,11 @@ impl ParserContext { #[inline] pub fn set_current_filename>(&mut self, file: P) { let file = file.into(); - self.current_filename = Some(file.canonicalize().map(|p| Utf8PathBuf::from_path_buf(p).unwrap()).unwrap_or(file)) + self.current_filename = Some( + file.canonicalize() + .map(|p| Utf8PathBuf::from_path_buf(p).unwrap()) + .unwrap_or(file) + ) } #[inline] diff --git a/cpclib-asm/src/progress.rs b/cpclib-asm/src/progress.rs index fdc46968..7e941a27 100644 --- a/cpclib-asm/src/progress.rs +++ b/cpclib-asm/src/progress.rs @@ -1,7 +1,7 @@ use core::time::Duration; use std::sync::{Arc, LazyLock, Mutex, MutexGuard}; -use camino::Utf8Path; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; #[cfg(feature = "indicatif")] use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; diff --git a/cpclib-basic/build.rs b/cpclib-basic/build.rs index 39c3a39e..d8f91cb9 100644 --- a/cpclib-basic/build.rs +++ b/cpclib-basic/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cpclib-basic/src/bin/locomotive.rs b/cpclib-basic/src/bin/locomotive.rs index 8ef79f74..182be1c8 100644 --- a/cpclib-basic/src/bin/locomotive.rs +++ b/cpclib-basic/src/bin/locomotive.rs @@ -14,7 +14,6 @@ use std::fs::File; use std::io::{Read, Write}; -use std::path::PathBuf; use cpclib_basic::{binary_parser, BasicProgram}; use cpclib_common::clap; @@ -32,7 +31,7 @@ fn main() -> std::io::Result<()> { .short('b') .help("Amstrad basic file") .action(ArgAction::Set) - .value_parser(clap::value_parser!(PathBuf)) + .value_parser(cpclib_common::utf8pathbuf_value_parser(true)) .required_unless_present("BASIC_SOURCE") ) .arg( diff --git a/cpclib-basm/Cargo.toml b/cpclib-basm/Cargo.toml index f52a36fc..5607b3cf 100644 --- a/cpclib-basm/Cargo.toml +++ b/cpclib-basm/Cargo.toml @@ -20,7 +20,6 @@ cpclib-xfer = {workspace=true, default-features=false, optional=true} cpclib-disc.workspace = true -camino.workspace = true const_format.workspace = true diff = "0.1.13" parking_lot.workspace = true @@ -28,7 +27,7 @@ time.workspace = true [dev-dependencies] test-generator.workspace = true -tempfile.workspace = true +camino-tempfile.workspace = true pretty_assertions.workspace = true criterion.workspace = true globset.workspace = true diff --git a/cpclib-basm/src/lib.rs b/cpclib-basm/src/lib.rs index bd363486..09e5be16 100644 --- a/cpclib-basm/src/lib.rs +++ b/cpclib-basm/src/lib.rs @@ -7,13 +7,13 @@ use std::io::Write; use std::str::FromStr; use std::sync::LazyLock; -use camino::Utf8Path; use cpclib_asm::assembler::file::get_filename; use cpclib_asm::preamble::file::read_source; use cpclib_asm::preamble::symbols_output::SymbolOutputFormat; use cpclib_asm::preamble::*; use cpclib_asm::progress::{normalize, Progress}; use cpclib_asm::AssemblingOptionFlags; +use cpclib_common::camino::Utf8Path; use cpclib_common::clap; use cpclib_common::clap::builder::{PossibleValue, PossibleValuesParser}; use cpclib_common::clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint}; diff --git a/cpclib-basm/tests/rasm_tests.rs b/cpclib-basm/tests/rasm_tests.rs index fa48766e..8abf230a 100644 --- a/cpclib-basm/tests/rasm_tests.rs +++ b/cpclib-basm/tests/rasm_tests.rs @@ -386,11 +386,13 @@ fn assemble_failure(code: &str, verify: VerifyOutput) { } fn test_assemble(code: &str, success: bool, verify: VerifyOutput) { - let input_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let input_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let input_fname = input_file.path().as_os_str().to_str().unwrap(); std::fs::write(input_fname, code).unwrap(); - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); let res = Command::new("../target/debug/basm") diff --git a/cpclib-basm/tests/real_tests.rs b/cpclib-basm/tests/real_tests.rs index d131b266..c4eb93b1 100644 --- a/cpclib-basm/tests/real_tests.rs +++ b/cpclib-basm/tests/real_tests.rs @@ -55,7 +55,8 @@ fn command_for_generated_test( } fn specific_test(folder: &str, fname: &str) { - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); let res = Command::new("../target/debug/basm") @@ -87,10 +88,12 @@ fn expect_warning_but_success(real_fname: &str) { let fname = &real_fname["cpclib-basm/tests/asm/".len()..]; - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); - let listing_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let listing_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let listing_fname = listing_file.path().as_os_str().to_str().unwrap(); let content = std::fs::read_to_string(dbg!(&real_fname["cpclib-basm/".len()..])) @@ -131,7 +134,8 @@ fn expect_warning_but_success(real_fname: &str) { dbg!(&content); if !content.is_empty() { - let input_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let input_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let input_fname = input_file.path().as_os_str().to_str().unwrap(); std::fs::write(input_fname, content).unwrap(); @@ -179,10 +183,12 @@ fn expect_one_line_success(real_fname: &str) { let fname = &real_fname["cpclib-basm/tests/asm/".len()..]; - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); - let listing_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let listing_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let listing_fname = listing_file.path().as_os_str().to_str().unwrap(); let content = std::fs::read_to_string(dbg!(&real_fname["cpclib-basm/".len()..])) @@ -223,7 +229,8 @@ fn expect_one_line_success(real_fname: &str) { dbg!(&content); if !content.is_empty() { - let input_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let input_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let input_fname = input_file.path().as_os_str().to_str().unwrap(); std::fs::write(input_fname, content).unwrap(); @@ -262,10 +269,12 @@ fn expect_several_empty_lines_success(real_fname: &str) { let fname = &real_fname["cpclib-basm/tests/asm/".len()..]; - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); - let listing_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let listing_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let listing_fname = listing_file.path().as_os_str().to_str().unwrap(); let content = std::fs::read_to_string(dbg!(&real_fname["cpclib-basm/".len()..])) @@ -281,7 +290,8 @@ fn expect_several_empty_lines_success(real_fname: &str) { eprintln!("{}", &content); - let input_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let input_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let input_fname = input_file.path().as_os_str().to_str().unwrap(); std::fs::write(input_fname, content).unwrap(); @@ -316,10 +326,12 @@ fn expect_listing_success(fname: &str) { manual_cleanup(); - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); - let listing_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let listing_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let listing_fname = listing_file.path().as_os_str().to_str().unwrap(); let res = Command::new("../target/debug/basm") @@ -355,10 +367,12 @@ fn expect_symbols_success(fname: &str) { let sym_gt = &fname["cpclib-basm/tests/asm/".len()..]; let fname = sym_gt.replace(".sym", ".asm"); - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); - let symbol_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let symbol_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let symbol_fname = symbol_file.path().as_os_str().to_str().unwrap(); let res = Command::new("../target/debug/basm") @@ -399,7 +413,8 @@ fn expect_success(fname: &str) { let fname = &fname["cpclib-basm/tests/asm/".len()..]; - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); let res = command_for_generated_test(fname, output_fname); @@ -412,7 +427,7 @@ fn expect_success(fname: &str) { { // control with an equivalent file let equiv_output_file = - tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let equiv_output_fname = equiv_output_file.path().as_os_str().to_str().unwrap(); let res_equiv = command_for_generated_test(&equiv_fname, equiv_output_fname); @@ -451,7 +466,8 @@ fn expect_failure(fname: &str) { let fname = &fname["cpclib-basm/tests/asm/".len()..]; - let output_file = tempfile::NamedTempFile::new().expect("Unable to build temporary file"); + let output_file = + camino_tempfile::NamedUtf8TempFile::new().expect("Unable to build temporary file"); let output_fname = output_file.path().as_os_str().to_str().unwrap(); let res = command_for_generated_test(fname, output_fname); diff --git a/cpclib-bdasm/Cargo.toml b/cpclib-bdasm/Cargo.toml index 1b1de8ea..31e40803 100644 --- a/cpclib-bdasm/Cargo.toml +++ b/cpclib-bdasm/Cargo.toml @@ -18,10 +18,8 @@ independent = true cpclib-common.workspace = true cpclib-asm.workspace = true cpclib-disc.workspace = true -clap.workspace = true const_format.workspace = true time = "0.3.36" -camino.workspace = true [features] hfe = ["cpclib-disc/hfe", "cpclib-asm/hfe"] diff --git a/cpclib-bdasm/build.rs b/cpclib-bdasm/build.rs index 39c3a39e..d8f91cb9 100644 --- a/cpclib-bdasm/build.rs +++ b/cpclib-bdasm/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cpclib-bdasm/src/main.rs b/cpclib-bdasm/src/main.rs index 57446efb..47d51b3a 100644 --- a/cpclib-bdasm/src/main.rs +++ b/cpclib-bdasm/src/main.rs @@ -6,10 +6,10 @@ use std::collections::HashMap; use std::fs::File; use std::io::Read; -use camino::Utf8PathBuf; -use clap; use clap::{Arg, ArgAction, Command}; use cpclib_asm::preamble::*; +use cpclib_common::camino::Utf8PathBuf; +use cpclib_common::clap; use cpclib_common::smol_str::SmolStr; use cpclib_common::winnow::error::ParseError; use cpclib_common::winnow::Parser; diff --git a/cpclib-bndbuild/Cargo.toml b/cpclib-bndbuild/Cargo.toml index c638219d..51d9ecb4 100644 --- a/cpclib-bndbuild/Cargo.toml +++ b/cpclib-bndbuild/Cargo.toml @@ -16,7 +16,6 @@ homepage.workspace = true exclude = ["examples", "tests/dummy", "*.gif"] [dependencies] -camino.workspace = true dot-writer = "0.1.3" lazy-regex = "3.2.0" minijinja = "2.1.1" @@ -47,7 +46,7 @@ build-deps = "0.1.4" [dev-dependencies] test-generator = "0.3.1" serial_test = "3.1.1" -tempfile = {workspace = true} +camino-tempfile = {workspace = true} [[bin]] name = "bndbuild" diff --git a/cpclib-bndbuild/build.rs b/cpclib-bndbuild/build.rs index e079bac9..89437c3d 100644 --- a/cpclib-bndbuild/build.rs +++ b/cpclib-bndbuild/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { build_deps::rerun_if_changed_paths("tests/valid/*.yml").unwrap(); build_deps::rerun_if_changed_paths("tests/invalid/*.yml").unwrap(); diff --git a/cpclib-bndbuild/src/builder.rs b/cpclib-bndbuild/src/builder.rs index cae9cf44..63d0315c 100644 --- a/cpclib-bndbuild/src/builder.rs +++ b/cpclib-bndbuild/src/builder.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::io::{BufReader, Read}; use std::ops::Deref; -use camino::Utf8Path; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; use minijinja::{context, Environment, Error, ErrorKind}; diff --git a/cpclib-bndbuild/src/lib.rs b/cpclib-bndbuild/src/lib.rs index 45e57f0f..c54bf82f 100644 --- a/cpclib-bndbuild/src/lib.rs +++ b/cpclib-bndbuild/src/lib.rs @@ -1,6 +1,6 @@ use std::env::current_dir; -use camino::{Utf8Path, Utf8PathBuf}; +use cpclib_common::camino::{Utf8Path, Utf8PathBuf}; use cpclib_common::clap; use cpclib_common::clap::*; use cpclib_common::itertools::Itertools; @@ -116,7 +116,7 @@ pub fn process_matches(cmd: Command, matches: &ArgMatches) -> Result<(), BndBuil let add = matches.get_one::("add"); // Read it - if !std::path::Path::new(fname).exists() { + if !Utf8Path::new(fname).exists() { if add.is_some() { std::fs::File::create(fname).expect("create empty {fname}"); } diff --git a/cpclib-bndbuild/src/rules/graph.rs b/cpclib-bndbuild/src/rules/graph.rs index 89367cea..fd90662e 100644 --- a/cpclib-bndbuild/src/rules/graph.rs +++ b/cpclib-bndbuild/src/rules/graph.rs @@ -1,6 +1,6 @@ use std::collections::{BTreeMap, HashSet}; -use camino::Utf8Path; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; use topologic::AcyclicDependencyGraph; diff --git a/cpclib-bndbuild/src/rules/rule.rs b/cpclib-bndbuild/src/rules/rule.rs index be077b8c..a2e8b0da 100644 --- a/cpclib-bndbuild/src/rules/rule.rs +++ b/cpclib-bndbuild/src/rules/rule.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use camino::{Utf8Path, Utf8PathBuf}; +use cpclib_common::camino::{Utf8Path, Utf8PathBuf}; use cpclib_common::itertools::Itertools; use serde::de::Visitor; use serde::{self, Deserialize, Deserializer}; diff --git a/cpclib-bndbuild/src/rules/rules.rs b/cpclib-bndbuild/src/rules/rules.rs index 0f2119a3..2794024a 100644 --- a/cpclib-bndbuild/src/rules/rules.rs +++ b/cpclib-bndbuild/src/rules/rules.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashSet}; use std::fmt::Display; use std::ops::Sub; -use camino::Utf8Path; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; use dot_writer::{Attributes, DotWriter, Style}; use serde::{self, Deserialize}; diff --git a/cpclib-bndbuild/src/runners/cp.rs b/cpclib-bndbuild/src/runners/cp.rs index 32fce9bf..79603021 100644 --- a/cpclib-bndbuild/src/runners/cp.rs +++ b/cpclib-bndbuild/src/runners/cp.rs @@ -1,5 +1,4 @@ -use std::path::Path; - +use cpclib_common::camino::Utf8Path; use cpclib_common::clap::{self, Arg, ArgAction}; use cpclib_common::itertools::Itertools; @@ -40,15 +39,18 @@ impl Runner for CpRunner { .map(expand_glob) .flatten() .collect_vec(); - let files = fnames.iter().map(|fname| Path::new(fname)).collect_vec(); + let files = fnames + .iter() + .map(|fname| Utf8Path::new(fname)) + .collect_vec(); let dest = files.last(); - let copy = |from: &Path, to: &Path, error: &mut String| { + let copy = |from: &Utf8Path, to: &Utf8Path, error: &mut String| { std::fs::copy(from, to).map_err(|e| { error.push_str(&format!( "Error when copying {} to {}. {}.\n", - from.display(), - to.display(), + from, + to, e.to_string() )) }); @@ -78,7 +80,7 @@ impl Runner for CpRunner { _ => { let dest = dest.unwrap(); if !dest.is_dir() { - errors.push_str(&format!("{} must be a directory.", dest.display())) + errors.push_str(&format!("{} must be a directory.", dest)) } else { let files = &files[..files.len() - 1]; @@ -114,8 +116,8 @@ mod test { fn test_copy_successful() { // prepare the files for the test - let mut src = tempfile::NamedTempFile::new().unwrap(); - let dst = tempfile::NamedTempFile::new().unwrap(); + let mut src = camino_tempfile::NamedUtf8TempFile::new().unwrap(); + let dst = camino_tempfile::NamedUtf8TempFile::new().unwrap(); src.as_file_mut().write("test".as_bytes()).unwrap(); @@ -128,8 +130,7 @@ mod test { // Run the test let cp = CpRunner::default(); - cp.inner_run(&[src.display().to_string(), dst.display().to_string()]) - .unwrap(); + cp.inner_run(&[src.to_string(), dst.to_string()]).unwrap(); assert!(dst.exists()); } } diff --git a/cpclib-common/Cargo.toml b/cpclib-common/Cargo.toml index 8543ef20..4190bf4d 100644 --- a/cpclib-common/Cargo.toml +++ b/cpclib-common/Cargo.toml @@ -19,6 +19,7 @@ bitfield.workspace = true bitflags.workspace = true bitvec.workspace = true +camino.workspace = true itertools.workspace = true winnow = {workspace = true, features=["simd"]} num.workspace = true diff --git a/cpclib-common/src/lib.rs b/cpclib-common/src/lib.rs index f9a8c552..6eede28b 100644 --- a/cpclib-common/src/lib.rs +++ b/cpclib-common/src/lib.rs @@ -2,6 +2,9 @@ pub mod riff; +use std::str::FromStr; + +use camino::Utf8PathBuf; #[cfg(feature = "cmdline")] pub use clap; #[cfg(all(not(target_arch = "wasm32"), feature = "rayon"))] @@ -17,10 +20,26 @@ use winnow::stream::{AsBytes, AsChar, Compare, Stream, StreamIsPartial}; use winnow::token::take_while; use winnow::{PResult, Parser}; pub use { - bitfield, bitflags, bitvec, itertools, num, resolve_path, smallvec, smol_str, strsim, + bitfield, bitflags, bitvec, camino, itertools, num, resolve_path, smallvec, smol_str, strsim, winnow }; +pub fn utf8pathbuf_value_parser(must_exist: bool) -> impl Fn(&str) -> Result { + move |p: &str| { + match Utf8PathBuf::from_str(p) { + Ok(p) => { + if !must_exist || p.exists() { + Ok(p) + } + else { + Err(format!("{} does not exists", p)) + } + }, + Err(_) => Err(format!("{} is not a valid filename.", p)) + } + } +} + #[inline] /// (prefix) space number suffix pub fn parse_value>(input: &mut I) -> PResult diff --git a/cpclib-cpr/src/lib.rs b/cpclib-cpr/src/lib.rs index ef18cf3e..13a0203e 100644 --- a/cpclib-cpr/src/lib.rs +++ b/cpclib-cpr/src/lib.rs @@ -3,8 +3,8 @@ use std::fs::File; use std::hash::{DefaultHasher, Hash, Hasher}; use std::io::{Read, Write}; use std::ops::Deref; -use std::path::Path; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; use cpclib_common::riff::{RiffChunk, RiffCode, RiffLen}; use cpclib_common::winnow::Parser; @@ -154,7 +154,7 @@ impl Cpr { } impl Cpr { - pub fn save>(&self, fname: P) -> Result<(), std::io::Error> { + pub fn save>(&self, fname: P) -> Result<(), std::io::Error> { let mut buffer = File::create(fname.as_ref())?; self.write_all(&mut buffer) } @@ -175,7 +175,7 @@ impl Cpr { Ok(()) } - pub fn load>(filename: P) -> Result { + pub fn load>(filename: P) -> Result { let filename = filename.as_ref(); // Read the full content of the file diff --git a/cpclib-cprcli/src/main.rs b/cpclib-cprcli/src/main.rs index 446cf403..f75948d2 100644 --- a/cpclib-cprcli/src/main.rs +++ b/cpclib-cprcli/src/main.rs @@ -1,10 +1,10 @@ use std::collections::HashSet; use std::ops::Sub; -use std::path::PathBuf; use commands::Command; -use cpclib_common::clap::builder::ValueParser; +use cpclib_common::camino::Utf8PathBuf; use cpclib_common::clap::{self, Arg, ArgAction}; +use cpclib_common::utf8pathbuf_value_parser; use cpclib_cpr::Cpr; mod commands; @@ -38,7 +38,7 @@ fn main() { .long("cpr1") .required(true) .action(ArgAction::Set) - .value_parser(ValueParser::path_buf()) + .value_parser(|p: &str| utf8pathbuf_value_parser(true)(p)) ) .arg( Arg::new("INPUT2") @@ -46,16 +46,16 @@ fn main() { .long("cpr2") .required(false) .action(ArgAction::Set) - .value_parser(ValueParser::path_buf()) + .value_parser(|p: &str| utf8pathbuf_value_parser(true)(p)) ); let args = cmd.get_matches(); let mut cpr = { - let cpr_fname = args.get_one::("INPUT").unwrap(); + let cpr_fname = args.get_one::("INPUT").unwrap(); Cpr::load(cpr_fname).unwrap() }; - let mut cpr2 = if let Some(cpr_fname2) = args.get_one::("INPUT2") { + let mut cpr2 = if let Some(cpr_fname2) = args.get_one::("INPUT2") { Some(Cpr::load(cpr_fname2).unwrap()) } else { diff --git a/cpclib-disc/Cargo.toml b/cpclib-disc/Cargo.toml index b52381f4..1658e684 100644 --- a/cpclib-disc/Cargo.toml +++ b/cpclib-disc/Cargo.toml @@ -19,7 +19,6 @@ cpclib-common.workspace = true arrayref.workspace = true -camino.workspace = true enumn.workspace = true cfg-if.workspace = true custom_error.workspace = true @@ -30,7 +29,7 @@ matches.workspace = true #memchr.workspace = true serde.workspace = true thiserror.workspace = true -tempfile.workspace = true +camino-tempfile.workspace = true log = {workspace = true, optional = true } simple_logger = { workspace = true, optional = true} diff --git a/cpclib-disc/build.rs b/cpclib-disc/build.rs index 39c3a39e..d8f91cb9 100644 --- a/cpclib-disc/build.rs +++ b/cpclib-disc/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cpclib-disc/src/amsdos.rs b/cpclib-disc/src/amsdos.rs index 973bdd67..d1cafb06 100644 --- a/cpclib-disc/src/amsdos.rs +++ b/cpclib-disc/src/amsdos.rs @@ -2,10 +2,10 @@ use std::convert::{TryFrom, TryInto}; use std::fs::File; use std::io::Read; use std::iter::Iterator; -use std::path::Path; use arrayref::array_ref; use cpclib_common::bitfield::Bit; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; use delegate::delegate; use thiserror::Error; @@ -1833,7 +1833,7 @@ impl AmsdosFile { } /// Read a file from disc and success if there is no io error and if the header if correct - pub fn open_valid>(path: P) -> Result { + pub fn open_valid>(path: P) -> Result { let mut f = File::open(path.as_ref())?; let mut content = Vec::new(); f.read_to_end(&mut content)?; @@ -1899,7 +1899,7 @@ impl AmsdosFile { } /// Save the file at the given path (header and data) - pub fn save_in_folder>(&self, folder: P) -> std::io::Result<()> { + pub fn save_in_folder>(&self, folder: P) -> std::io::Result<()> { use std::io::Write; let folder = folder.as_ref(); diff --git a/cpclib-disc/src/cfg.rs b/cpclib-disc/src/cfg.rs index 3caa81ac..d64689b8 100644 --- a/cpclib-disc/src/cfg.rs +++ b/cpclib-disc/src/cfg.rs @@ -2,9 +2,9 @@ use std::fmt; use std::fs::File; use std::io::Read; use std::iter::Iterator; -use std::path::Path; use std::str::FromStr; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools; use cpclib_common::winnow::ascii::{line_ending, space0, Caseless}; use cpclib_common::winnow::combinator::{ @@ -87,7 +87,7 @@ impl DiscConfig { } /// Create a configuration from the provided file - pub fn new>(p: P) -> Result { + pub fn new>(p: P) -> Result { let mut content = String::new(); let mut f = File::open(p.as_ref())?; f.read_to_string(&mut content)?; diff --git a/cpclib-disc/src/disc.rs b/cpclib-disc/src/disc.rs index d59648f2..b1554c09 100644 --- a/cpclib-disc/src/disc.rs +++ b/cpclib-disc/src/disc.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use cpclib_common::camino::Utf8Path; use crate::amsdos::{ AmsdosAddBehavior, AmsdosError, AmsdosFile, AmsdosFileName, AmsdosManagerMut, @@ -10,9 +10,9 @@ pub trait Disc { fn open

(path: P) -> Result where Self: Sized, - P: AsRef; + P: AsRef; fn save

(&self, path: P) -> Result<(), String> - where P: AsRef; + where P: AsRef; fn global_min_sector>(&self, side: S) -> u8; fn track_min_sector>(&self, side: S, track: u8) -> u8; diff --git a/cpclib-disc/src/edsk.rs b/cpclib-disc/src/edsk.rs index 8001ff0f..c83ab039 100644 --- a/cpclib-disc/src/edsk.rs +++ b/cpclib-disc/src/edsk.rs @@ -2,10 +2,10 @@ use std::fs::File; use std::io::prelude::*; -use std::path::Path; use std::string::ToString; use cpclib_common::bitflags::bitflags; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::{zip, Itertools}; use delegate::delegate; use getset::Getters; @@ -1159,7 +1159,7 @@ impl ExtendedDsk { impl Disc for ExtendedDsk { /// open an extended dsk from an existing file fn open

(path: P) -> Result - where P: AsRef { + where P: AsRef { let path = path.as_ref(); // Read the whole file let buffer = { @@ -1174,7 +1174,7 @@ impl Disc for ExtendedDsk { /// Save the dsk in a file one disc fn save

(&self, path: P) -> Result<(), String> - where P: AsRef { + where P: AsRef { let path = path.as_ref(); let mut file_buffer = File::create(path).map_err(|e| e.to_string())?; let mut memory_buffer = Vec::new(); diff --git a/cpclib-disc/src/hfe.rs b/cpclib-disc/src/hfe.rs index 9895ce6f..778114df 100644 --- a/cpclib-disc/src/hfe.rs +++ b/cpclib-disc/src/hfe.rs @@ -21,9 +21,7 @@ // unsigned char track0s1_encoding; // alternate track_encoding for track 0 Side 1 // }picfileformatheader; -use std::path::Path; - -use camino::Utf8Path; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; use enumn::N; use hxcfe::{Hxcfe, Img, TrackEncoding}; diff --git a/cpclib-disc/src/lib.rs b/cpclib-disc/src/lib.rs index b22e92f5..40e9ffd0 100644 --- a/cpclib-disc/src/lib.rs +++ b/cpclib-disc/src/lib.rs @@ -6,11 +6,11 @@ use std::collections::VecDeque; use std::fs::File; #[cfg(feature = "cmdline")] use std::io::{Read, Write}; -use std::path::Path; #[cfg(feature = "cmdline")] use std::str::FromStr; use amsdos::AmsdosError; +use cpclib_common::camino::Utf8Path; #[cfg(feature = "cmdline")] use cpclib_common::clap::*; use disc::Disc; @@ -60,17 +60,17 @@ impl From for DskManagerError { } #[cfg(feature = "hfe")] -pub fn new_disc>(path: Option

) -> Hfe { +pub fn new_disc>(path: Option

) -> Hfe { Hfe::default() } #[cfg(not(feature = "hfe"))] -pub fn new_disc>(path: Option

) -> ExtendedDsk { +pub fn new_disc>(path: Option

) -> ExtendedDsk { ExtendedDsk::default() } #[cfg(feature = "hfe")] -pub fn open_disc>(path: P, fail_if_missing: bool) -> Result { +pub fn open_disc>(path: P, fail_if_missing: bool) -> Result { let path = path.as_ref(); if !path.exists() { if fail_if_missing { @@ -85,14 +85,14 @@ pub fn open_disc>(path: P, fail_if_missing: bool) -> R } #[cfg(not(feature = "hfe"))] -pub fn open_disc>( +pub fn open_disc>( path: P, fail_if_missing: bool ) -> Result { let path = path.as_ref(); if !path.exists() { if fail_if_missing { - return Err(format!("{} does not exists", path.display())); + return Err(format!("{} does not exists", path)); } else { return Ok(new_disc(Some(path))); @@ -106,6 +106,8 @@ pub fn open_disc>( #[cfg(feature = "cmdline")] pub fn dsk_manager_handle(matches: &ArgMatches) -> Result<(), DskManagerError> { + use cpclib_common::camino::Utf8Path; + let dsk_fname = matches.get_one::("DSK_FILE").unwrap(); let behavior = amsdos::AmsdosAddBehavior::ReplaceIfPresent; @@ -205,12 +207,7 @@ pub fn dsk_manager_handle(matches: &ArgMatches) -> Result<(), DskManagerError> { .add_file_sequentially(head, track, sector, &content) .unwrap_or_else(|_| panic!("Unable to add {file}")); - let base_label = Path::new(file) - .file_name() - .unwrap() - .to_str() - .unwrap() - .replace('.', "_"); + let base_label = Utf8Path::new(file).file_name().unwrap().replace('.', "_"); listing.add(builder::equ(format!("{}_head", &base_label), head)); listing.add(builder::equ(format!("{}_track", &base_label), track)); listing.add(builder::equ(format!("{}_sector", &base_label), sector)); @@ -472,8 +469,8 @@ pub fn dsk_manager_build_arg_parser() -> Command { } /// Open the file and remove the header if any -pub fn read>(p: P) -> Result<(VecDeque, Option), AmsdosError> { - let data = std::fs::read(p).map_err(|e| AmsdosError::IO(e.to_string()))?; +pub fn read>(p: P) -> Result<(VecDeque, Option), AmsdosError> { + let data = std::fs::read(p.as_ref()).map_err(|e| AmsdosError::IO(e.to_string()))?; Ok(split_header(data)) } diff --git a/cpclib-image/src/convert.rs b/cpclib-image/src/convert.rs index 0223d65e..33d1240f 100644 --- a/cpclib-image/src/convert.rs +++ b/cpclib-image/src/convert.rs @@ -2,9 +2,9 @@ use std::collections::HashSet; use std::fmt::Debug; -use std::path::Path; use cpclib_common::bitfield::{BitRange, BitRangeMut}; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; use image as im; @@ -1108,13 +1108,13 @@ impl<'a> ImageConverter<'a> { output: &'a OutputFormat ) -> anyhow::Result where - P: AsRef + P: AsRef { Self::convert_impl(input_file.as_ref(), palette, mode, transformations, output) } fn convert_impl( - input_file: &Path, + input_file: &Utf8Path, palette: Option, mode: Mode, transformations: TransformationsList, @@ -1240,7 +1240,7 @@ impl<'a> ImageConverter<'a> { /// Load the initial image /// TODO make compatibility tests are alike /// TODO propagate errors when needed - fn load_sprite(&mut self, input_file: &Path) -> Sprite { + fn load_sprite(&mut self, input_file: &Utf8Path) -> Sprite { let matrix = self.load_color_matrix(input_file); let sprite = matrix.as_sprite(self.mode, self.palette.clone()); self.palette = sprite.palette(); @@ -1248,7 +1248,7 @@ impl<'a> ImageConverter<'a> { sprite } - fn load_color_matrix(&self, input_file: &Path) -> ColorMatrix { + fn load_color_matrix(&self, input_file: &Utf8Path) -> ColorMatrix { let img = im::open(input_file) .unwrap_or_else(|_| panic!("Unable to convert {:?} properly.", input_file)); let mat = ColorMatrix::convert(&img.to_rgb8(), ConversionRule::AnyModeUseAllPixels); diff --git a/cpclib-image/src/image.rs b/cpclib-image/src/image.rs index 1c09e037..ce930e6f 100644 --- a/cpclib-image/src/image.rs +++ b/cpclib-image/src/image.rs @@ -3,6 +3,7 @@ use std::collections::HashSet; use anyhow::Context; +use cpclib_common::camino::Utf8Path; use cpclib_common::itertools::Itertools; #[cfg(all(not(target_arch = "wasm32"), feature = "rayon"))] use cpclib_common::rayon::iter::{IntoParallelRefIterator, ParallelIterator}; @@ -1065,7 +1066,7 @@ impl Sprite { matrix.as_sprite(mode, palette) } - pub fn convert_from_fname>( + pub fn convert_from_fname>( fname: P, mode: Mode, conversion: ConversionRule, diff --git a/cpclib-imgconverter/Cargo.toml b/cpclib-imgconverter/Cargo.toml index 1987a3a0..baafb75d 100644 --- a/cpclib-imgconverter/Cargo.toml +++ b/cpclib-imgconverter/Cargo.toml @@ -21,11 +21,10 @@ cpclib = { workspace=true, features = ["cmdline"] } anyhow.workspace = true crossbeam-channel.workspace = true exitcode.workspace = true -tempfile.workspace = true +camino-tempfile.workspace = true notify = {workspace = true, optional = true} - [build-dependencies] built.workspace = true diff --git a/cpclib-imgconverter/build.rs b/cpclib-imgconverter/build.rs index 39c3a39e..d8f91cb9 100644 --- a/cpclib-imgconverter/build.rs +++ b/cpclib-imgconverter/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cpclib-imgconverter/src/lib.rs b/cpclib-imgconverter/src/lib.rs index ca868773..9d0f72dd 100644 --- a/cpclib-imgconverter/src/lib.rs +++ b/cpclib-imgconverter/src/lib.rs @@ -1,11 +1,12 @@ use std::fs::File; use std::io::Write; -use std::path::{Path, PathBuf}; use anyhow::{self, Error}; +use camino_tempfile as tempfile; use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; use cpclib::asm::preamble::defb_elements; use cpclib::asm::{assemble, assemble_to_amsdos_file}; +use cpclib::common::camino::{Utf8Path, Utf8PathBuf}; use cpclib::common::clap; use cpclib::disc::amsdos::*; use cpclib::disc::disc::Disc; @@ -26,13 +27,14 @@ pub mod built_info { #[macro_export] macro_rules! specify_palette { + ($e:expr) => { $e.arg( Arg::new("OCP_PAL") .long("pal") .required(false) .help("OCP PAL file. The first palette among 12 is used") // TODO specify a way to select any palette - .value_parser(value_parser!(std::path::PathBuf)) + .value_parser(|p: &str| cpclib::common::utf8pathbuf_value_parser(true)(p)) ) .arg( Arg::new("PENS") @@ -198,7 +200,7 @@ pub fn get_requested_palette(matches: &ArgMatches) -> Result, Am .collect::>(); return Ok(Some(numbers.into())); } - else if let Some(fname) = matches.get_one::("OCP_PAL") { + else if let Some(fname) = matches.get_one::("OCP_PAL") { let (mut data, header) = cpclib::disc::read(fname)?; // get the file content but skip the header let data = data.make_contiguous(); let pal = OcpPal::from_buffer(data); @@ -232,7 +234,7 @@ macro_rules! export_palette { .short('p') .required(false) .action(ArgAction::Set) - .value_parser(clap::value_parser!(PathBuf)) + .value_parser(clap::value_parser!(Utf8PathBuf)) .help("Name of the binary file that contains the palette (Gate Array format)"), ) .arg( @@ -241,7 +243,7 @@ macro_rules! export_palette { .short('i') .required(false) .action(ArgAction::Set) - .value_parser(clap::value_parser!(PathBuf)) + .value_parser(clap::value_parser!(Utf8PathBuf)) .help("Name of the binary file that will contain the ink numbers (usefull for system based color change)") ) .arg( @@ -249,7 +251,7 @@ macro_rules! export_palette { .long("palette_fadeout") .required(false) .action(ArgAction::Set) - .value_parser(clap::value_parser!(PathBuf)) + .value_parser(clap::value_parser!(Utf8PathBuf)) .help("Name of the file that will contain all the steps for a fade out transition (Gate Array format)") ) .arg( @@ -257,7 +259,7 @@ macro_rules! export_palette { .long("ink_fadeout") .required(false) .action(ArgAction::Set) - .value_parser(clap::value_parser!(PathBuf)) + .value_parser(clap::value_parser!(Utf8PathBuf)) .help("Name of the file that will contain all the steps for a fade out transition") ) }; @@ -265,13 +267,13 @@ macro_rules! export_palette { macro_rules! do_export_palette { ($arg:expr, $palette:ident) => { - if let Some(palette_fname) = $arg.get_one::("EXPORT_PALETTE") { + if let Some(palette_fname) = $arg.get_one::("EXPORT_PALETTE") { let mut file = File::create(palette_fname).expect("Unable to create the palette file"); let p: Vec = $palette.into(); file.write_all(&p).unwrap(); } - if let Some(fade_fname) = $arg.get_one::("EXPORT_PALETTE_FADEOUT") { + if let Some(fade_fname) = $arg.get_one::("EXPORT_PALETTE_FADEOUT") { let palettes = $palette.rgb_fadout(); let bytes = palettes.iter().fold(Vec::::default(), |mut acc, x| { acc.extend(&x.to_gate_array_with_default(0.into())); @@ -284,7 +286,7 @@ macro_rules! do_export_palette { file.write_all(&bytes).unwrap(); } - if let Some(palette_fname) = $arg.get_one::("EXPORT_INKS") { + if let Some(palette_fname) = $arg.get_one::("EXPORT_INKS") { let mut file = File::create(palette_fname).expect("Unable to create the inks file"); let inks = $palette .inks() @@ -294,7 +296,7 @@ macro_rules! do_export_palette { file.write_all(&inks).unwrap(); } - if let Some(fade_fname) = $arg.get_one::("EXPORT_INK_FADEOUT") { + if let Some(fade_fname) = $arg.get_one::("EXPORT_INK_FADEOUT") { let palettes = $palette.rgb_fadout(); let bytes = palettes .iter() @@ -549,7 +551,7 @@ fn get_output_format(matches: &ArgMatches) -> OutputFormat { #[allow(clippy::cast_possible_wrap)] #[allow(clippy::cast_possible_truncation)] fn convert(matches: &ArgMatches) -> anyhow::Result<()> { - let input_file = matches.get_one::("SOURCE").unwrap(); + let input_file = matches.get_one::("SOURCE").unwrap(); let output_mode = matches .get_one::("MODE") .unwrap() @@ -654,11 +656,9 @@ fn convert(matches: &ArgMatches) -> anyhow::Result<()> { .and_then(|conf_fname: &String| { let mut file = File::create(conf_fname) .expect("Unable to create the configuration file"); - let fname = std::path::Path::new(conf_fname) + let fname = Utf8Path::new(conf_fname) .file_stem() .unwrap() - .to_str() - .unwrap() .replace(".", "_"); writeln!(&mut file, "{}_WIDTH equ {}", fname, bytes_width).unwrap(); writeln!(&mut file, "{}_HEIGHT equ {}", fname, height).unwrap(); @@ -680,21 +680,13 @@ fn convert(matches: &ArgMatches) -> anyhow::Result<()> { do_export_palette!(sub_tile, palette); // Save the binary data of the tiles - let tile_fname = Path::new( + let tile_fname = Utf8Path::new( sub_tile .get_one::("SPRITE_FNAME") .expect("Missing tileset name") ); - let base = tile_fname - .with_extension("") - .as_os_str() - .to_str() - .unwrap() - .to_owned(); - let extension = tile_fname - .extension() - .map(|s| s.to_str().unwrap_or("")) - .unwrap_or(""); + let base = tile_fname.with_extension("").to_string(); + let extension = tile_fname.extension().unwrap_or(""); for (i, data) in tile_set.iter().enumerate() { let current_filename = format!("{}_{:03}.{}", base, i, extension); let mut file = File::create(current_filename.clone()) @@ -767,19 +759,20 @@ fn convert(matches: &ArgMatches) -> anyhow::Result<()> { let file = assemble_to_amsdos_file(&code, filename).unwrap(); if sub_exec.is_some() { - let filename = Path::new(filename); + let filename = Utf8Path::new(filename); let folder = filename.parent().unwrap(); - let folder = if folder == Path::new("") { + let folder = if folder == Utf8Path::new("") { std::env::current_dir().unwrap() } else { folder.canonicalize().unwrap() }; + let folder = Utf8PathBuf::from_path_buf(folder).unwrap(); file.save_in_folder(folder)?; } else { let fname = sub_dsk.unwrap().get_one::("DSK").unwrap(); - let p = std::path::Path::new(fname); + let p = Utf8Path::new(fname); let mut dsk = { if p.exists() { @@ -866,9 +859,9 @@ fn convert(matches: &ArgMatches) -> anyhow::Result<()> { let xfer = CpcXfer::new(sub_m4.get_one::("CPCM4").unwrap()); - let tmp_file_name = f.path().to_str().unwrap(); + let tmp_file_name = f.path(); xfer.upload_and_run(tmp_file_name, None) - .expect("An error occured while transfering the snapshot"); + .expect("An error occurred while transferring the snapshot"); } } } @@ -888,7 +881,7 @@ pub fn build_args_parser() -> clap::Command { // .last(true) .required(true) .value_parser(|source: &str| { - let p = std::path::PathBuf::from(source); + let p = Utf8PathBuf::from(source); if p.exists() { Ok(p) } @@ -960,16 +953,14 @@ pub fn build_args_parser() -> clap::Command { .help("executable to generate") .required(true) .value_parser(|fname: &str|{ - let fname = std::path::PathBuf::from(fname); + let fname = Utf8PathBuf::from(fname); if let Some(ext) = fname.extension() { - let ext = ext.to_os_string().into_string().unwrap(); if ext.len() > 3 { return Err(format!("{} is not a valid amsdos extension.", ext)); } } if let Some(stem) = fname.file_stem() { - let stem = stem.to_os_string().into_string().unwrap(); if stem.len() > 8 { return Err(format!("{} is not a valid amsdos file stem.", stem)) } @@ -1177,7 +1168,10 @@ pub fn process(matches: &ArgMatches, mut args: Command) -> anyhow::Result<()> { notify::Config::default() )?; watcher.watch( - &std::path::Path::new(matches.get_one::("SOURCE").unwrap()), + matches + .get_one::("SOURCE") + .unwrap() + .as_std_path(), RecursiveMode::NonRecursive )?; diff --git a/cpclib-sna/Cargo.toml b/cpclib-sna/Cargo.toml index f72e06ab..a0f3e1db 100644 --- a/cpclib-sna/Cargo.toml +++ b/cpclib-sna/Cargo.toml @@ -29,7 +29,7 @@ rustyline = { workspace = true, optional = true} minus = {workspace=true, optional = true} [dev-dependencies] -tempfile.workspace = true +camino-tempfile.workspace = true similar-asserts.workspace = true [build-dependencies] diff --git a/cpclib-sna/src/bin/snapshot.rs b/cpclib-sna/src/bin/snapshot.rs index 4863c623..176d77d0 100644 --- a/cpclib-sna/src/bin/snapshot.rs +++ b/cpclib-sna/src/bin/snapshot.rs @@ -14,7 +14,6 @@ #![allow(clippy::cast_possible_truncation)] #![allow(clippy::identity_op)] -use std::path::Path; use std::str::FromStr; use comfy_table::{Table, *}; @@ -170,7 +169,7 @@ fn main() { // Load a snapshot or generate an empty one let mut sna = if matches.contains_id("inSnapshot") { let fname = matches.get_one::("inSnapshot").unwrap(); - let path = Path::new(&fname); + let path = Utf8Path::new(&fname); Snapshot::load(path).expect("Error while loading the snapshot") } else { diff --git a/cpclib-sna/src/cli.rs b/cpclib-sna/src/cli.rs index 41fe5037..14b2a883 100644 --- a/cpclib-sna/src/cli.rs +++ b/cpclib-sna/src/cli.rs @@ -333,17 +333,9 @@ pub fn cli(fname: &str, mut sna: Snapshot) { let mut rl = Editor::<(), _>::new().unwrap(); if rl.load_history("snapshot.txt").is_err() {} loop { - let fname1 = std::path::Path::new(fname) - .file_name() - .unwrap() - .to_str() - .unwrap(); + let fname1 = Utf8Path::new(fname).file_name().unwrap(); let prompt = if let Some((fname2, _)) = &sna2 { - let fname2 = std::path::Path::new(fname2) - .file_name() - .unwrap() - .to_str() - .unwrap(); + let fname2 = Utf8Path::new(fname2).file_name().unwrap(); format!("{} vs {} > ", fname1, fname2) } else { diff --git a/cpclib-sna/src/lib.rs b/cpclib-sna/src/lib.rs index e3f3ff49..9428e015 100644 --- a/cpclib-sna/src/lib.rs +++ b/cpclib-sna/src/lib.rs @@ -3,9 +3,9 @@ use std::fs::File; use std::io::prelude::*; use std::ops::Deref; -use std::path::Path; use cpclib_common::bitvec::vec::BitVec; +use cpclib_common::camino::Utf8Path; use cpclib_common::riff::{RiffChunk, RiffCode}; use num_enum::TryFromPrimitive; @@ -405,7 +405,7 @@ impl Snapshot { } } - pub fn load>(filename: P) -> Result { + pub fn load>(filename: P) -> Result { let filename = filename.as_ref(); // Read the full content of the file @@ -531,11 +531,11 @@ impl Snapshot { /// Save the snapshot V2 on disc #[deprecated] - pub fn save_sna>(&self, fname: P) -> Result<(), std::io::Error> { + pub fn save_sna>(&self, fname: P) -> Result<(), std::io::Error> { self.save(fname, SnapshotVersion::V2) } - pub fn save>( + pub fn save>( &self, fname: P, version: SnapshotVersion diff --git a/cpclib-sna/tests/format.rs b/cpclib-sna/tests/format.rs index 3df24ea5..0db85077 100644 --- a/cpclib-sna/tests/format.rs +++ b/cpclib-sna/tests/format.rs @@ -1,7 +1,7 @@ use std::fs::read; +use camino_tempfile::NamedUtf8TempFile; use cpclib_sna::{Snapshot, SnapshotVersion}; -use tempfile::NamedTempFile; #[test] fn sna_loadv3() { @@ -15,7 +15,7 @@ fn sna_loadv2() { let sna = Snapshot::load("tests/loop4000_v2.sna").unwrap(); assert_eq!(sna.version(), SnapshotVersion::V2); - let file = NamedTempFile::new().unwrap(); + let file = NamedUtf8TempFile::new().unwrap(); let fname = file.path(); sna.save(fname, SnapshotVersion::V2).unwrap(); @@ -31,7 +31,7 @@ fn sna_loadv3_savev2() { let sna = Snapshot::new_6128().unwrap(); assert_eq!(sna.version(), SnapshotVersion::V3); - let file = NamedTempFile::new().unwrap(); + let file = NamedUtf8TempFile::new().unwrap(); let fname = file.path(); sna.save(fname, SnapshotVersion::V2).unwrap(); diff --git a/cpclib-visual-basm/build.rs b/cpclib-visual-basm/build.rs index cded79ec..eb0fad0b 100644 --- a/cpclib-visual-basm/build.rs +++ b/cpclib-visual-basm/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { static_vcruntime::metabuild(); diff --git a/cpclib-visual-bndbuild/Cargo.toml b/cpclib-visual-bndbuild/Cargo.toml index f0868ae4..c826804b 100644 --- a/cpclib-visual-bndbuild/Cargo.toml +++ b/cpclib-visual-bndbuild/Cargo.toml @@ -19,6 +19,7 @@ independent = true cpclib-bndbuild.workspace = true cpclib-common = {workspace=true, features=["cmdline"]} +camino = {workspace=true, features=["serde1"]} eframe = {workspace=true, features=["persistence"]} egui_file.workspace = true env_logger.workspace = true diff --git a/cpclib-visual-bndbuild/build.rs b/cpclib-visual-bndbuild/build.rs index cded79ec..eb0fad0b 100644 --- a/cpclib-visual-bndbuild/build.rs +++ b/cpclib-visual-bndbuild/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { static_vcruntime::metabuild(); diff --git a/cpclib-visual-bndbuild/src/lib.rs b/cpclib-visual-bndbuild/src/lib.rs index 1cdf546f..1f1b1a60 100644 --- a/cpclib-visual-bndbuild/src/lib.rs +++ b/cpclib-visual-bndbuild/src/lib.rs @@ -6,11 +6,11 @@ mod syntax; use std::collections::HashSet; use std::io::Read; use std::ops::Deref; -use std::path::{Path, PathBuf}; use std::time::{Duration, SystemTime}; use cpclib_bndbuild::rules::Rule; use cpclib_bndbuild::BndBuilder; +use cpclib_common::camino::{Utf8Path, Utf8PathBuf}; use eframe::egui::{self, RichText}; use eframe::epaint::ahash::HashMap; use eframe::epaint::Color32; @@ -42,14 +42,14 @@ static CTRL_R: KeyboardShortcut = KeyboardShortcut { #[serde(default)] pub struct BndBuildApp { /// The provided filename by the user - filename: Option, + filename: Option, /// Recently opened files - recent_files: Vec, + recent_files: Vec, /// Watched target #[serde(skip)] - watched: Option, + watched: Option, #[serde(skip)] watch_logs: String, @@ -86,9 +86,9 @@ pub struct BndBuildApp { /// Target to build requested by button #[serde(skip)] - requested_target: Option, + requested_target: Option, /// Target hovered to highlight dependencies - hovered_target: Option, + hovered_target: Option, /// stdout redirection #[serde(skip)] @@ -150,14 +150,14 @@ impl Default for BndBuildApp { } /// Store the list of targets level per level -struct Layers<'builder>(Vec>); +struct Layers<'builder>(Vec>); /// Cache up to date information to not recompute it 60 times per seconds struct UpToDate<'builder>(HashMap<&'builder Rule, bool>); /// Store the list of dependecies -struct DependencyOf(HashMap>); +struct DependencyOf(HashMap>); impl Deref for DependencyOf { - type Target = HashMap>; + type Target = HashMap>; fn deref(&self) -> &Self::Target { &self.0 @@ -165,7 +165,7 @@ impl Deref for DependencyOf { } impl<'builder> Deref for Layers<'builder> { - type Target = Vec>; + type Target = Vec>; fn deref(&self) -> &Self::Target { &self.0 @@ -215,8 +215,8 @@ impl<'builder> From<&'builder BndBuilder> for Layers<'builder> { impl<'builder> From<&'builder BndBuilder> for DependencyOf { fn from(builder: &'builder BndBuilder) -> Self { - let mut dep_of: HashMap> = Default::default(); - let targets: Vec<&'builder Path> = builder.targets(); + let mut dep_of: HashMap> = Default::default(); + let targets: Vec<&'builder Utf8Path> = builder.targets(); for task in targets.iter() { let deps = builder.get_layered_dependencies_for(task.into()); let deps = deps.into_iter().flatten(); @@ -269,7 +269,7 @@ impl BuilderAndCache { } impl BndBuildApp { - pub fn new>(cc: &eframe::CreationContext<'_>, path: Option

) -> Self { + pub fn new>(cc: &eframe::CreationContext<'_>, path: Option

) -> Self { let mut app = if let Some(storage) = cc.storage { let mut app: BndBuildApp = eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default(); @@ -293,7 +293,7 @@ impl BndBuildApp { app } - pub fn load>(&mut self, path: P) { + pub fn load>(&mut self, path: P) { let path = path.as_ref(); match cpclib_bndbuild::BndBuilder::from_fname(path) { Ok(builder) => { @@ -342,7 +342,7 @@ impl BndBuildApp { for fname in self.recent_files.clone().iter().rev() { if ui .add( - Button::new(fname.display().to_string()) + Button::new(fname.to_string()) .wrap_mode(egui::TextWrapMode::Extend) ) .clicked() @@ -392,7 +392,7 @@ impl BndBuildApp { fn update_status_and_shortcuts(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::TopBottomPanel::bottom("bottom").show(ctx, |ui| { match &self.filename { - Some(fname) => ui.label(fname.display().to_string()), + Some(fname) => ui.label(fname.to_string()), None => ui.label("No file loaded") }; @@ -484,7 +484,7 @@ impl BndBuildApp { for tgt in layer.iter() { let rule = bnl.borrow_owner().get_rule(tgt); - let txt = tgt.display().to_string(); + let txt = tgt.to_string(); let txt = if let Some(watched) = self.watched.as_ref() && watched == tgt { @@ -558,8 +558,7 @@ impl BndBuildApp { self.hovered_target = Some(tgt.into()); } button.context_menu(|ui| { - if tgt.exists() - && ui.button(&format!("Open \"{}\"", tgt.display())).clicked() + if tgt.exists() && ui.button(&format!("Open \"{}\"", tgt)).clicked() { match open::that(tgt) { Ok(_) => {}, @@ -642,7 +641,9 @@ impl eframe::App for BndBuildApp { // Handle file opening if self.request_open { - let mut dialog = egui_file::FileDialog::open_file(self.filename.clone()); + let mut dialog = egui_file::FileDialog::open_file( + self.filename.clone().map(|p| p.into_std_path_buf()) + ); dialog.open(); self.open_file_dialog = dialog.into(); self.file_error = None; @@ -674,7 +675,7 @@ impl eframe::App for BndBuildApp { None }; if let Some(p) = p { - self.load(p); + self.load(Utf8PathBuf::try_from(p).unwrap()); } // Handle reload @@ -689,7 +690,9 @@ impl eframe::App for BndBuildApp { if self.request_save_as { self.request_save_as = false; - let mut dialog = egui_file::FileDialog::save_file(self.filename.clone()); + let mut dialog = egui_file::FileDialog::save_file( + self.filename.clone().map(|p| p.into_std_path_buf()) + ); dialog.open(); self.save_file_dialog = dialog.into(); self.file_error = None; @@ -699,7 +702,7 @@ impl eframe::App for BndBuildApp { if dialog.show(ctx).selected() { if let Some(path) = dialog.path() { self.request_save = true; - self.filename = Some(path.to_path_buf()); + self.filename = Some(path.to_path_buf().try_into().unwrap()); } } } @@ -784,11 +787,11 @@ impl eframe::App for BndBuildApp { .unwrap_or(false) { self.watch_logs - .push_str(&format!("{} needs to be rebuilt", watched.display())); + .push_str(&format!("{} needs to be rebuilt", watched)); if self.requested_target.is_some() { self.watch_logs.push_str(&format!( "Build delayed in favor of {}", - self.requested_target.as_ref().unwrap().display() + self.requested_target.as_ref().unwrap() )); } else { diff --git a/cpclib-xfer/Cargo.toml b/cpclib-xfer/Cargo.toml index ae6ef056..b97f1836 100644 --- a/cpclib-xfer/Cargo.toml +++ b/cpclib-xfer/Cargo.toml @@ -18,6 +18,7 @@ cpclib-disc.workspace = true cpclib-sna.workspace = true cpclib-common.workspace = true +camino-tempfile.workspace = true arrayref.workspace = true cfg-if.workspace = true custom_error.workspace = true @@ -27,7 +28,6 @@ getset.workspace = true matches.workspace = true #memchr.workspace = true serde.workspace = true -tempfile.workspace = true path-absolutize = { workspace = true, optional = false } curl = { workspace = true, optional = false } diff --git a/cpclib-xfer/build.rs b/cpclib-xfer/build.rs index 39c3a39e..d8f91cb9 100644 --- a/cpclib-xfer/build.rs +++ b/cpclib-xfer/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cpclib-xfer/src/lib.rs b/cpclib-xfer/src/lib.rs index bd83b3bf..40e12fbb 100644 --- a/cpclib-xfer/src/lib.rs +++ b/cpclib-xfer/src/lib.rs @@ -1,6 +1,6 @@ use std::fs; -use std::path::Path; +use cpclib_common::camino::Utf8Path; use curl::easy::{Easy, Form}; use curl::Error; use custom_error::custom_error; @@ -189,7 +189,7 @@ impl CpcXfer { header: Option<(AmsdosFileType, u16, u16)> ) -> Result<(), XferError> where - P: AsRef + P: AsRef { self.upload_impl(path.as_ref(), m4_path, header) } @@ -197,11 +197,11 @@ impl CpcXfer { #[allow(clippy::similar_names)] pub fn upload_impl( &self, - path: &Path, + path: &Utf8Path, m4_path: &str, header: Option<(AmsdosFileType, u16, u16)> ) -> Result<(), XferError> { - let local_fname = path.to_str().unwrap(); + let local_fname = path.as_str(); if m4_path.len() > 255 { panic!( @@ -225,12 +225,12 @@ impl CpcXfer { }; // TODO manage more cases in order to allow to provide a destination folder or a destination filename or a different name - let destination = Path::new(m4_path).join( - Path::new(local_fname) + let destination = Utf8Path::new(m4_path).join( + Utf8Path::new(local_fname) .file_name() .expect("Unable to retreive the filename of the file to upload") ); - let destination = destination.to_str().unwrap().to_owned(); + let destination = destination.to_string(); let mut form = Form::new(); form.part("upfile") @@ -248,7 +248,7 @@ impl CpcXfer { /// Directly sends the SNA to the M4. SNA is first saved as a V2 version as M4 is unable to read other ones pub fn upload_and_run_sna(&self, sna: &Snapshot) -> Result<(), XferError> { - use tempfile::Builder; + use camino_tempfile::Builder; let file = Builder::new() .prefix("xfer") .suffix(".sna") @@ -277,7 +277,7 @@ impl CpcXfer { }) } - pub fn upload_and_run>( + pub fn upload_and_run>( &self, path: P, header: Option<(AmsdosFileType, u16, u16)> @@ -287,15 +287,12 @@ impl CpcXfer { fn upload_and_run_impl( &self, - path: &Path, + path: &Utf8Path, header: Option<(AmsdosFileType, u16, u16)> ) -> Result<(), XferError> { // We are sure it is not a snapshot there self.upload_impl(path, "/tmp", header)?; - self.run(&format!( - "/tmp/{}", - path.file_name().unwrap().to_str().unwrap() - ))?; + self.run(&format!("/tmp/{}", path.file_name().unwrap()))?; Ok(()) } @@ -368,9 +365,9 @@ impl CpcXfer { Some('/') => Ok(relative.to_owned()), _ => { let cwd = self.current_working_directory()?; - let absolute = Path::new(&cwd).join(relative); + let absolute = Utf8Path::new(&cwd).join(relative); - let absolute = absolute.absolutize().unwrap(); + let absolute = absolute.as_std_path().absolutize().unwrap(); let path: String = absolute.to_str().unwrap().into(); if cfg!(target_os = "windows") { return Ok(path.replace("C:\\", "/")); @@ -394,7 +391,7 @@ impl CpcXfer { /// Send and run the file on the CPC. /// Snapshot V3 are downgraded to the V2 version -pub fn send_and_run_file>( +pub fn send_and_run_file>( xfer: &CpcXfer, fname: P, run: bool @@ -403,12 +400,12 @@ pub fn send_and_run_file>( let fname = fname.as_ref(); // Snapshot needs to be converted in V2 format and handled differently if let Some(extension) = fname.extension() { - let extension = extension.to_str().unwrap().to_ascii_lowercase(); + let extension = extension.to_ascii_lowercase(); if extension == "sna" { let sna = sna::Snapshot::load(fname).expect("Error while loading snapshot"); if sna.version_header() == 3 { eprintln!("Need to downgrade SNA version. TODO check if it is sill necessary (I think not)"); - let sna_fname = fname.file_name().unwrap().to_str().unwrap(); + let sna_fname = fname.file_name().unwrap(); sna.save(sna_fname, sna::SnapshotVersion::V2).unwrap(); xfer.upload_and_run(sna_fname, None) .expect("Unable to launch SNA"); diff --git a/cpclib-xfertool/Cargo.toml b/cpclib-xfertool/Cargo.toml index 5cadd629..b212a1e8 100644 --- a/cpclib-xfertool/Cargo.toml +++ b/cpclib-xfertool/Cargo.toml @@ -29,7 +29,7 @@ either.workspace = true getset.workspace = true matches.workspace = true serde = { workspace = true, features = ["derive"] } -tempfile.workspace = true +camino-tempfile.workspace = true path-absolutize = {workspace = true, optional = false } curl = {workspace = true, optional = false } diff --git a/cpclib-xfertool/build.rs b/cpclib-xfertool/build.rs index 39c3a39e..d8f91cb9 100644 --- a/cpclib-xfertool/build.rs +++ b/cpclib-xfertool/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cpclib-xfertool/src/interact.rs b/cpclib-xfertool/src/interact.rs index 495b0b4c..239a9f32 100644 --- a/cpclib-xfertool/src/interact.rs +++ b/cpclib-xfertool/src/interact.rs @@ -1,3 +1,4 @@ +use cpclib_common::camino::Utf8Path; use cpclib_common::winnow::Parser; use cpclib_xfer::CpcXfer; use rustyline::completion::{extract_word, Completer, FilenameCompleter, Pair}; @@ -280,7 +281,7 @@ ls List the files in the current M4 directory. }, XferCommand::Put(arg1) => { - let path = std::path::Path::new(&arg1); + let path = Utf8Path::new(&arg1); if !path.exists() { eprintln!("{arg1} does not exists"); return; diff --git a/cpclib-xfertool/src/lib.rs b/cpclib-xfertool/src/lib.rs index 4dc793e4..46c799d7 100644 --- a/cpclib-xfertool/src/lib.rs +++ b/cpclib-xfertool/src/lib.rs @@ -2,15 +2,12 @@ pub mod interact; pub mod parser; -use std::path::PathBuf; - -use cpclib_common::clap; -use cpclib_common::clap::builder::TypedValueParser; +use cpclib_common::camino::Utf8PathBuf; +use cpclib_common::{clap, utf8pathbuf_value_parser}; use cpclib_xfer::{send_and_run_file, CpcXfer}; #[cfg(feature = "watch")] use notify::{RecommendedWatcher, RecursiveMode, Watcher}; -use crate::clap::builder::PathBufValueParser; use crate::clap::{ArgAction, Command}; pub mod built_info { @@ -38,14 +35,7 @@ pub fn build_args_parser() -> clap::Command { clap::Arg::new("fname") .help("Filename to send and execute. Can be an executable (Amsdos header expected) or a snapshot V2") .value_parser( - PathBufValueParser::new() - .try_map(|p: PathBuf| { - if p.exists() { - Ok(p) - } else { - Err(format!("{} does not exists", p.display().to_string())) - } - }) + |p: &str| {utf8pathbuf_value_parser(true)(p)} ) .required(true) ); @@ -74,14 +64,7 @@ pub fn build_args_parser() -> clap::Command { clap::Arg::new("fname") .help("Filename to send to the CPC") .value_parser( - PathBufValueParser::new() - .try_map(|p: PathBuf| { - if p.exists() { - Ok(p) - } else { - Err(format!("{} does not exists", p.display().to_string())) - } - }) + |p: &str| {utf8pathbuf_value_parser(true)(p)} ) .required(true) )/* To implement when needed @@ -151,11 +134,11 @@ pub fn process(matches: &clap::ArgMatches) -> anyhow::Result<()> { xfer.reset_cpc()?; } else if let Some(p_opt) = matches.subcommand_matches("-p") { - let fname: &PathBuf = p_opt.get_one("fname").unwrap(); + let fname: &Utf8PathBuf = p_opt.get_one("fname").unwrap(); send_and_run_file(&xfer, &fname, false); } else if let Some(y_opt) = matches.subcommand_matches("-y") { - let fname: &PathBuf = y_opt.get_one("fname").unwrap(); + let fname: &Utf8PathBuf = y_opt.get_one("fname").unwrap(); // Simple file sending send_and_run_file(&xfer, &fname, true); @@ -180,7 +163,7 @@ pub fn process(matches: &clap::ArgMatches) -> anyhow::Result<()> { notify::event::EventKind::Modify(_) | notify::event::EventKind::Create(_), .. }) => { - send_and_run_file(&xfer, &fname, true); + send_and_run_file(&xfer, fname, true); }, _ => {} } diff --git a/cpclib/Cargo.toml b/cpclib/Cargo.toml index e55b3a6e..2a3431dd 100644 --- a/cpclib/Cargo.toml +++ b/cpclib/Cargo.toml @@ -42,7 +42,7 @@ matches.workspace = true paste.workspace = true path-absolutize = { workspace = true, optional = true } serde = { workspace = true, features = ["derive"] } -tempfile.workspace = true +camino-tempfile.workspace = true time = { workspace = true, optional = true } diff --git a/cpclib/build.rs b/cpclib/build.rs index 39c3a39e..d8f91cb9 100644 --- a/cpclib/build.rs +++ b/cpclib/build.rs @@ -1,6 +1,3 @@ -use std::env; -use std::path::Path; - fn main() { built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cpclib/tests/disccfgparser.rs b/cpclib/tests/disccfgparser.rs index ebc96277..709d2aad 100644 --- a/cpclib/tests/disccfgparser.rs +++ b/cpclib/tests/disccfgparser.rs @@ -360,8 +360,8 @@ sectorIDHead = 0,0,0,0,0,0,0,0,0,0 #[test] fn test_build() { - use tempfile::NamedTempFile; - let file = NamedTempFile::new().unwrap(); + use camino_tempfile::NamedUtf8TempFile; + let file = NamedUtf8TempFile::new().unwrap(); let path = file.into_temp_path(); let cfg = cpclib::disc::cfg::DiscConfig::from_str(SINGLE_SIDED).unwrap(); diff --git a/cpclib/tests/edsk.rs b/cpclib/tests/edsk.rs index 05c057f1..068d6724 100644 --- a/cpclib/tests/edsk.rs +++ b/cpclib/tests/edsk.rs @@ -76,7 +76,7 @@ mod tests { let dsk = cpclib::disc::edsk::ExtendedDsk::open("./tests/dsk/pirate.dsk").unwrap(); test_single_dsk(&dsk); - let f = tempfile::NamedTempFile::new().unwrap(); + let f = camino_tempfile::NamedUtf8TempFile::new().unwrap(); let tmp_file = f.path(); dsk.save(tmp_file).unwrap(); let dsk = cpclib::disc::edsk::ExtendedDsk::open(tmp_file).unwrap(); @@ -95,7 +95,7 @@ mod tests { let dsk = cpclib::disc::edsk::ExtendedDsk::open("./tests/dsk/bf2sides.dsk").unwrap(); test_double_head_bf_edsk(&dsk); - let f = tempfile::NamedTempFile::new().unwrap(); + let f = camino_tempfile::NamedUtf8TempFile::new().unwrap(); let tmp_file = f.path(); dsk.save(tmp_file).unwrap(); @@ -105,7 +105,7 @@ mod tests { #[test] fn save_edsk() { - let f = tempfile::NamedTempFile::new().unwrap(); + let f = camino_tempfile::NamedUtf8TempFile::new().unwrap(); let tmp_file = f.path(); let dsk1 = cpclib::disc::edsk::ExtendedDsk::open("tests/dsk/pirate.dsk").unwrap(); dsk1.save(tmp_file).unwrap(); diff --git a/cpclib/tests/sna.rs b/cpclib/tests/sna.rs index 726edae4..b91ec9c0 100644 --- a/cpclib/tests/sna.rs +++ b/cpclib/tests/sna.rs @@ -64,7 +64,7 @@ mod tests { ); // Save to reload (directly from V2) - let f = tempfile::NamedTempFile::new().unwrap(); + let f = camino_tempfile::NamedUtf8TempFile::new().unwrap(); let tmp_fname = f.path(); // TODO really use a tmp file v2.save(tmp_fname, SnapshotVersion::V2) .expect("Unable to save"); @@ -85,7 +85,7 @@ mod tests { ); // Should also work from V3 - let f = tempfile::NamedTempFile::new().unwrap(); + let f = camino_tempfile::NamedUtf8TempFile::new().unwrap(); let tmp_fname = f.path(); sna1.save(tmp_fname, SnapshotVersion::V2) .expect("Unable to save");