summaryrefslogtreecommitdiff
path: root/subplotlib
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2022-10-22 10:50:41 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2022-10-22 10:50:41 +0100
commit7f52ffc37e1a366f78ba3709f15b09ca22ca98c9 (patch)
treebd5320a7d5493a294fea27972111d54a3a024de8 /subplotlib
parent5ce95579e42171913b0fabbb51b2beca66854ae4 (diff)
downloadsubplot-7f52ffc37e1a366f78ba3709f15b09ca22ca98c9.tar.gz
(steplibrary): Update files and runcmd to use new path type
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
Diffstat (limited to 'subplotlib')
-rw-r--r--subplotlib/src/steplibrary/files.rs83
-rw-r--r--subplotlib/src/steplibrary/runcmd.rs12
2 files changed, 53 insertions, 42 deletions
diff --git a/subplotlib/src/steplibrary/files.rs b/subplotlib/src/steplibrary/files.rs
index 09cde56..8abe546 100644
--- a/subplotlib/src/steplibrary/files.rs
+++ b/subplotlib/src/steplibrary/files.rs
@@ -7,7 +7,7 @@ use std::collections::{HashMap, HashSet};
use std::ffi::OsString;
use std::fs::{self, Metadata, OpenOptions};
use std::io::{self, Write};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime};
use filetime::FileTime;
@@ -31,7 +31,7 @@ pub use super::datadir::Datadir;
/// Because files can typically only be named in Subplot documents, we assume they
/// all have names which can be rendered as utf-8 strings.
pub struct Files {
- metadata: HashMap<String, Metadata>,
+ metadata: HashMap<PathBuf, Metadata>,
}
impl ContextElement for Files {
@@ -50,7 +50,7 @@ impl ContextElement for Files {
#[step]
#[context(Datadir)]
pub fn create_from_embedded(context: &ScenarioContext, embedded_file: SubplotDataFile) {
- let filename_on_disk = format!("{}", embedded_file.name().display());
+ let filename_on_disk = PathBuf::from(format!("{}", embedded_file.name().display()));
create_from_embedded_with_other_name::call(context, &filename_on_disk, embedded_file)?;
}
@@ -63,7 +63,7 @@ pub fn create_from_embedded(context: &ScenarioContext, embedded_file: SubplotDat
#[step]
pub fn create_from_embedded_with_other_name(
context: &Datadir,
- filename_on_disk: &str,
+ filename_on_disk: &Path,
embedded_file: SubplotDataFile,
) {
let filename_on_disk = PathBuf::from(filename_on_disk);
@@ -86,7 +86,7 @@ pub fn create_from_embedded_with_other_name(
/// Sets the modification time for the given filename to the provided mtime.
/// If the file does not exist, it will be created.
#[step]
-pub fn touch_with_timestamp(context: &Datadir, filename: &str, mtime: &str) {
+pub fn touch_with_timestamp(context: &Datadir, filename: &Path, mtime: &str) {
let fd = format_description!(
"[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour]:[offset_minute]"
);
@@ -112,7 +112,7 @@ pub fn touch_with_timestamp(context: &Datadir, filename: &str, mtime: &str) {
///
/// Create/replace the given file with the given content.
#[step]
-pub fn create_from_text(context: &Datadir, text: &str, filename: &str) {
+pub fn create_from_text(context: &Datadir, text: &str, filename: &Path) {
context.open_write(filename)?.write_all(text.as_bytes())?;
}
@@ -125,7 +125,7 @@ pub fn create_from_text(context: &Datadir, text: &str, filename: &str) {
#[step]
#[context(Datadir)]
#[context(Files)]
-pub fn remember_metadata(context: &ScenarioContext, filename: &str) {
+pub fn remember_metadata(context: &ScenarioContext, filename: &Path) {
let full_path = context.with(
|context: &Datadir| context.canonicalise_filename(filename),
false,
@@ -147,7 +147,7 @@ pub fn remember_metadata(context: &ScenarioContext, filename: &str) {
/// This will create the named file if it does not exist, and then it will ensure that the
/// file's modification time is set to the current time.
#[step]
-pub fn touch(context: &Datadir, filename: &str) {
+pub fn touch(context: &Datadir, filename: &Path) {
let full_path = context.canonicalise_filename(filename)?;
let now = FileTime::now();
// If the file doesn't exist, create it
@@ -167,13 +167,13 @@ pub fn touch(context: &Datadir, filename: &str) {
///
/// This simple step will succeed if the given filename exists in some sense.
#[step]
-pub fn file_exists(context: &Datadir, filename: &str) {
+pub fn file_exists(context: &Datadir, filename: &Path) {
let full_path = context.canonicalise_filename(filename)?;
match fs::metadata(full_path) {
Ok(_) => (),
Err(e) => {
if matches!(e.kind(), io::ErrorKind::NotFound) {
- throw!(format!("file '{}' was not found", filename))
+ throw!(format!("file '{}' was not found", filename.display()))
} else {
throw!(e);
}
@@ -187,11 +187,14 @@ pub fn file_exists(context: &Datadir, filename: &str) {
///
/// This simple step will succeed if the given filename does not exist in any sense.
#[step]
-pub fn file_does_not_exist(context: &Datadir, filename: &str) {
+pub fn file_does_not_exist(context: &Datadir, filename: &Path) {
let full_path = context.canonicalise_filename(filename)?;
match fs::metadata(full_path) {
Ok(_) => {
- throw!(format!("file '{}' was unexpectedly found", filename))
+ throw!(format!(
+ "file '{}' was unexpectedly found",
+ filename.display()
+ ))
}
Err(e) => {
if !matches!(e.kind(), io::ErrorKind::NotFound) {
@@ -229,11 +232,11 @@ pub fn only_these_exist(context: &Datadir, filenames: &str) {
/// This will load the content of the named file and ensure it contains the given string.
/// Note: this assumes everything is utf-8 encoded. If not, things will fail.
#[step]
-pub fn file_contains(context: &Datadir, filename: &str, data: &str) {
+pub fn file_contains(context: &Datadir, filename: &Path, data: &str) {
let full_path = context.canonicalise_filename(filename)?;
let body = fs::read_to_string(full_path)?;
if !body.contains(data) {
- println!("file {} contains:\n{}", filename, body);
+ println!("file {} contains:\n{}", filename.display(), body);
throw!("expected file content not found");
}
}
@@ -245,11 +248,11 @@ pub fn file_contains(context: &Datadir, filename: &str, data: &str) {
/// This will load the content of the named file and ensure it lacks the given string.
/// Note: this assumes everything is utf-8 encoded. If not, things will fail.
#[step]
-pub fn file_doesnt_contain(context: &Datadir, filename: &str, data: &str) {
+pub fn file_doesnt_contain(context: &Datadir, filename: &Path, data: &str) {
let full_path = context.canonicalise_filename(filename)?;
let body = fs::read_to_string(full_path)?;
if body.contains(data) {
- println!("file {} contains:\n{}", filename, body);
+ println!("file {} contains:\n{}", filename.display(), body);
throw!("unexpected file content found");
}
}
@@ -262,12 +265,12 @@ pub fn file_doesnt_contain(context: &Datadir, filename: &str, data: &str) {
/// matches the given regular expression. This step will fail if the file is not utf-8
/// encoded, or if the regex fails to compile
#[step]
-pub fn file_matches_regex(context: &Datadir, filename: &str, regex: &str) {
+pub fn file_matches_regex(context: &Datadir, filename: &Path, regex: &str) {
let full_path = context.canonicalise_filename(filename)?;
let regex = Regex::new(regex)?;
let body = fs::read_to_string(full_path)?;
if !regex.is_match(&body) {
- println!("file {} contains:\n{}", filename, body);
+ println!("file {} contains:\n{}", filename.display(), body);
throw!("file content does not match given regex");
}
}
@@ -278,7 +281,7 @@ pub fn file_matches_regex(context: &Datadir, filename: &str, regex: &str) {
///
/// This loads the content of the given two files as **bytes** and checks they mach.
#[step]
-pub fn file_match(context: &Datadir, filename1: &str, filename2: &str) {
+pub fn file_match(context: &Datadir, filename1: &Path, filename2: &Path) {
let full_path1 = context.canonicalise_filename(filename1)?;
let full_path2 = context.canonicalise_filename(filename2)?;
let body1 = fs::read(full_path1)?;
@@ -286,12 +289,12 @@ pub fn file_match(context: &Datadir, filename1: &str, filename2: &str) {
if body1 != body2 {
println!(
"file {} contains:\n{}",
- filename1,
+ filename1.display(),
String::from_utf8_lossy(&body1)
);
println!(
"file {} contains:\n{}",
- filename2,
+ filename2.display(),
String::from_utf8_lossy(&body2)
);
throw!("file contents do not match each other");
@@ -312,7 +315,7 @@ pub fn file_match(context: &Datadir, filename1: &str, filename2: &str) {
#[step]
#[context(Datadir)]
#[context(Files)]
-pub fn has_remembered_metadata(context: &ScenarioContext, filename: &str) {
+pub fn has_remembered_metadata(context: &ScenarioContext, filename: &Path) {
let full_path = context.with(
|context: &Datadir| context.canonicalise_filename(filename),
false,
@@ -327,10 +330,13 @@ pub fn has_remembered_metadata(context: &ScenarioContext, filename: &str) {
|| metadata.len() != remembered.len()
|| metadata.is_file() != remembered.is_file()
{
- throw!(format!("metadata change detected for {}", filename));
+ throw!(format!(
+ "metadata change detected for {}",
+ filename.display()
+ ));
}
} else {
- throw!(format!("no remembered metadata for {}", filename));
+ throw!(format!("no remembered metadata for {}", filename.display()));
}
}
@@ -348,7 +354,7 @@ pub fn has_remembered_metadata(context: &ScenarioContext, filename: &str) {
#[step]
#[context(Datadir)]
#[context(Files)]
-pub fn has_different_metadata(context: &ScenarioContext, filename: &str) {
+pub fn has_different_metadata(context: &ScenarioContext, filename: &Path) {
let full_path = context.with(
|context: &Datadir| context.canonicalise_filename(filename),
false,
@@ -363,10 +369,13 @@ pub fn has_different_metadata(context: &ScenarioContext, filename: &str) {
&& metadata.len() == remembered.len()
&& metadata.is_file() == remembered.is_file()
{
- throw!(format!("metadata change not detected for {}", filename));
+ throw!(format!(
+ "metadata change not detected for {}",
+ filename.display()
+ ));
}
} else {
- throw!(format!("no remembered metadata for {}", filename));
+ throw!(format!("no remembered metadata for {}", filename.display()));
}
}
@@ -376,13 +385,13 @@ pub fn has_different_metadata(context: &ScenarioContext, filename: &str) {
///
/// Specifically this checks that the given file has been modified in the past 5 seconds.
#[step]
-pub fn mtime_is_recent(context: &Datadir, filename: &str) {
+pub fn mtime_is_recent(context: &Datadir, filename: &Path) {
let full_path = context.canonicalise_filename(filename)?;
let metadata = fs::metadata(full_path)?;
let mtime = metadata.modified()?;
let diff = SystemTime::now().duration_since(mtime)?;
if diff > (Duration::from_secs(5)) {
- throw!(format!("{} is older than 5 seconds", filename));
+ throw!(format!("{} is older than 5 seconds", filename.display()));
}
}
@@ -392,13 +401,13 @@ pub fn mtime_is_recent(context: &Datadir, filename: &str) {
///
/// Specifically this checks that the file was modified at least 39 years ago.
#[step]
-pub fn mtime_is_ancient(context: &Datadir, filename: &str) {
+pub fn mtime_is_ancient(context: &Datadir, filename: &Path) {
let full_path = context.canonicalise_filename(filename)?;
let metadata = fs::metadata(full_path)?;
let mtime = metadata.modified()?;
let diff = SystemTime::now().duration_since(mtime)?;
if diff < (Duration::from_secs(39 * 365 * 24 * 3600)) {
- throw!(format!("{} is younger than 39 years", filename));
+ throw!(format!("{} is younger than 39 years", filename.display()));
}
}
@@ -408,7 +417,7 @@ pub fn mtime_is_ancient(context: &Datadir, filename: &str) {
///
/// This is the equivalent of `mkdir -p` within the data directory for the scenario.
#[step]
-pub fn make_directory(context: &Datadir, path: &str) {
+pub fn make_directory(context: &Datadir, path: &Path) {
context.create_dir_all(path)?;
}
@@ -418,7 +427,7 @@ pub fn make_directory(context: &Datadir, path: &str) {
///
/// This is the equivalent of `rm -rf` within the data directory for the scenario.
#[step]
-pub fn remove_directory(context: &Datadir, path: &str) {
+pub fn remove_directory(context: &Datadir, path: &Path) {
let full_path = context.canonicalise_filename(path)?;
remove_dir_all::remove_dir_all(full_path)?;
}
@@ -430,7 +439,7 @@ pub fn remove_directory(context: &Datadir, path: &str) {
/// This ensures that the given path exists in the data directory for the scenario and
/// that it is a directory itself.
#[step]
-pub fn path_exists(context: &Datadir, path: &str) {
+pub fn path_exists(context: &Datadir, path: &Path) {
let full_path = context.canonicalise_filename(path)?;
if !fs::metadata(&full_path)?.is_dir() {
throw!(format!(
@@ -447,7 +456,7 @@ pub fn path_exists(context: &Datadir, path: &str) {
/// This ensures that the given path does not exist in the data directory. If it exists
/// and is not a directory, then this will also fail.
#[step]
-pub fn path_does_not_exist(context: &Datadir, path: &str) {
+pub fn path_does_not_exist(context: &Datadir, path: &Path) {
let full_path = context.canonicalise_filename(path)?;
match fs::metadata(&full_path) {
Ok(_) => throw!(format!("{} exists", full_path.display())),
@@ -466,7 +475,7 @@ pub fn path_does_not_exist(context: &Datadir, path: &str) {
/// This checks that the given path inside the data directory exists and is an
/// empty directory itself.
#[step]
-pub fn path_is_empty(context: &Datadir, path: &str) {
+pub fn path_is_empty(context: &Datadir, path: &Path) {
let full_path = context.canonicalise_filename(path)?;
let mut iter = fs::read_dir(&full_path)?;
match iter.next() {
@@ -484,7 +493,7 @@ pub fn path_is_empty(context: &Datadir, path: &str) {
/// directory itself. The step also asserts that the given directory contains at least
/// one entry.
#[step]
-pub fn path_is_not_empty(context: &Datadir, path: &str) {
+pub fn path_is_not_empty(context: &Datadir, path: &Path) {
let full_path = context.canonicalise_filename(path)?;
let mut iter = fs::read_dir(&full_path)?;
match iter.next() {
diff --git a/subplotlib/src/steplibrary/runcmd.rs b/subplotlib/src/steplibrary/runcmd.rs
index b90f8b7..6692441 100644
--- a/subplotlib/src/steplibrary/runcmd.rs
+++ b/subplotlib/src/steplibrary/runcmd.rs
@@ -56,7 +56,9 @@ static DEFAULT_PATHS: &[&str] = &[
];
// This us used internally to force CWD for running commands
-const USE_CWD: &str = "\0USE_CWD";
+lazy_static! {
+ static ref USE_CWD: PathBuf = PathBuf::from("\0USE_CWD");
+}
impl ContextElement for Runcmd {
fn scenario_starts(&mut self) -> StepResult {
@@ -229,7 +231,7 @@ pub fn run(context: &ScenarioContext, argv0: &str, args: &str) {
#[step]
#[context(Datadir)]
#[context(Runcmd)]
-pub fn run_in(context: &ScenarioContext, dirname: &str, argv0: &str, args: &str) {
+pub fn run_in(context: &ScenarioContext, dirname: &Path, argv0: &str, args: &str) {
try_to_run_in::call(context, dirname, argv0, args)?;
exit_code_is::call(context, 0)?;
}
@@ -244,7 +246,7 @@ pub fn run_in(context: &ScenarioContext, dirname: &str, argv0: &str, args: &str)
#[context(Datadir)]
#[context(Runcmd)]
pub fn try_to_run(context: &ScenarioContext, argv0: &str, args: &str) {
- try_to_run_in::call(context, USE_CWD, argv0, args)?;
+ try_to_run_in::call(context, &USE_CWD, argv0, args)?;
}
/// Run the given command in the given subpath of the data directory
@@ -256,7 +258,7 @@ pub fn try_to_run(context: &ScenarioContext, argv0: &str, args: &str) {
#[step]
#[context(Datadir)]
#[context(Runcmd)]
-pub fn try_to_run_in(context: &ScenarioContext, dirname: &str, argv0: &str, args: &str) {
+pub fn try_to_run_in(context: &ScenarioContext, dirname: &Path, argv0: &str, args: &str) {
// This is the core of runcmd and is how we handle things
let argv0: PathBuf = if argv0.starts_with('.') {
context.with(
@@ -270,7 +272,7 @@ pub fn try_to_run_in(context: &ScenarioContext, dirname: &str, argv0: &str, args
|datadir: &Datadir| Ok(datadir.base_path().to_path_buf()),
false,
)?;
- if dirname != USE_CWD {
+ if dirname != USE_CWD.as_path() {
datadir = datadir.join(dirname);
}
let mut proc = Command::new(&argv0);