Skip to content

Commit

Permalink
Add safe wrappers around fs in run_make_support
Browse files Browse the repository at this point in the history
  • Loading branch information
Oneirical committed May 31, 2024
1 parent 20ad958 commit 1094107
Show file tree
Hide file tree
Showing 30 changed files with 160 additions and 65 deletions.
98 changes: 98 additions & 0 deletions src/tools/run-make-support/src/fs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use std::fs;
use std::path::Path;

/// A safe wrapper around `std::fs::remove_file` that prints the file path if an operation fails.
pub fn remove_file<P: AsRef<Path>>(path: P) {
fs::remove_file(path.as_ref()).expect(&format!(
"the file in path \"{:?}\" could not be removed.",
path.as_ref().display()
));
}

/// A safe wrapper around `std::fs::copy` that prints the file paths if an operation fails.
pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) {
fs::copy(from.as_ref(), to.as_ref()).expect(&format!(
"the file \"{:?}\" could not be copied over to \"{:?}\".",
from.as_ref().display(),
to.as_ref().display(),
));
}

/// A safe wrapper around `std::fs::File::create` that prints the file path if an operation fails.
pub fn create_file<P: AsRef<Path>>(path: P) {
fs::File::create(path.as_ref()).expect(&format!(
"the file in path \"{:?}\" could not be created.",
path.as_ref().display()
));
}

/// A safe wrapper around `std::fs::read` that prints the file path if an operation fails.
pub fn read<P: AsRef<Path>>(path: P) -> Vec<u8> {
fs::read(path.as_ref())
.expect(&format!("the file in path \"{:?}\" could not be read.", path.as_ref().display()))
}

/// A safe wrapper around `std::fs::read_to_string` that prints the file path if an operation fails.
pub fn read_to_string<P: AsRef<Path>>(path: P) -> String {
fs::read_to_string(path.as_ref()).expect(&format!(
"the file in path \"{:?}\" could not be read into a String.",
path.as_ref().display()
))
}

/// A safe wrapper around `std::fs::read_dir` that prints the file path if an operation fails.
pub fn read_dir<P: AsRef<Path>>(path: P) -> fs::ReadDir {
fs::read_dir(path.as_ref()).expect(&format!(
"the directory in path \"{:?}\" could not be read.",
path.as_ref().display()
))
}

/// A safe wrapper around `std::fs::write` that prints the file path if an operation fails.
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) {
fs::write(path.as_ref(), contents.as_ref()).expect(&format!(
"the file in path \"{:?}\" could not be written to.",
path.as_ref().display()
));
}

/// A safe wrapper around `std::fs::remove_dir_all` that prints the file path if an operation fails.
pub fn remove_dir_all<P: AsRef<Path>>(path: P) {
fs::remove_dir_all(path.as_ref()).expect(&format!(
"the directory in path \"{:?}\" could not be removed alongside all its contents.",
path.as_ref().display(),
));
}

/// A safe wrapper around `std::fs::create_dir` that prints the file path if an operation fails.
pub fn create_dir<P: AsRef<Path>>(path: P) {
fs::create_dir(path.as_ref()).expect(&format!(
"the directory in path \"{:?}\" could not be created.",
path.as_ref().display()
));
}

/// A safe wrapper around `std::fs::create_dir_all` that prints the file path if an operation fails.
pub fn create_dir_all<P: AsRef<Path>>(path: P) {
fs::create_dir_all(path.as_ref()).expect(&format!(
"the directory (and all its parents) in path \"{:?}\" could not be created.",
path.as_ref().display()
));
}

/// A safe wrapper around `std::fs::metadata` that prints the file path if an operation fails.
pub fn metadata<P: AsRef<Path>>(path: P) -> fs::Metadata {
fs::metadata(path.as_ref()).expect(&format!(
"the file's metadata in path \"{:?}\" could not be read.",
path.as_ref().display()
))
}

/// A safe wrapper around `std::fs::rename` that prints the file paths if an operation fails.
pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) {
fs::rename(from.as_ref(), to.as_ref()).expect(&format!(
"the file \"{:?}\" could not be moved over to \"{:?}\".",
from.as_ref().display(),
to.as_ref().display(),
));
}
26 changes: 10 additions & 16 deletions src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
pub mod cc;
pub mod clang;
pub mod diff;
pub mod fs;
pub mod llvm_readobj;
pub mod run;
pub mod rustc;
pub mod rustdoc;

use std::env;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
Expand All @@ -35,8 +35,9 @@ pub fn tmp_dir() -> PathBuf {
env::var_os("TMPDIR").unwrap().into()
}

pub fn tmp_path<P: AsRef<Path>>(path: P) -> PathBuf {
tmp_dir().join(path.as_ref())
/// Returns the directory TMPDIR/name.
pub fn tmp_path<P: AsRef<Path>>(name: P) -> PathBuf {
tmp_dir().join(name.as_ref())
}

/// `TARGET`
Expand Down Expand Up @@ -218,15 +219,15 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
fn copy_dir_all_inner(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
let dst = dst.as_ref();
if !dst.is_dir() {
fs::create_dir_all(&dst)?;
std::fs::create_dir_all(&dst)?;
}
for entry in fs::read_dir(src)? {
for entry in std::fs::read_dir(src)? {
let entry = entry?;
let ty = entry.file_type()?;
if ty.is_dir() {
copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?;
} else {
fs::copy(entry.path(), dst.join(entry.file_name()))?;
std::fs::copy(entry.path(), dst.join(entry.file_name()))?;
}
}
Ok(())
Expand All @@ -245,15 +246,8 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {

/// Check that all files in `dir1` exist and have the same content in `dir2`. Panic otherwise.
pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
fn read_file(path: &Path) -> Vec<u8> {
match fs::read(path) {
Ok(c) => c,
Err(e) => panic!("Failed to read `{}`: {:?}", path.display(), e),
}
}

let dir2 = dir2.as_ref();
for entry in fs::read_dir(dir1).unwrap() {
for entry in fs::read_dir(dir1) {
let entry = entry.unwrap();
let entry_name = entry.file_name();
let path = entry.path();
Expand All @@ -262,8 +256,8 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
recursive_diff(&path, &dir2.join(entry_name));
} else {
let path2 = dir2.join(entry_name);
let file1 = read_file(&path);
let file2 = read_file(&path2);
let file1 = fs::read(&path);
let file2 = fs::read(&path2);

// We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
// Why not using String? Because there might be minified files or even potentially
Expand Down
3 changes: 2 additions & 1 deletion tests/run-make/c-link-to-rust-staticlib/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@

//@ ignore-cross-compile

use run_make_support::fs::remove_file;
use run_make_support::{cc, extra_c_flags, run, rustc, static_lib};
use std::fs;

fn main() {
rustc().input("foo.rs").run();
cc().input("bar.c").input(static_lib("foo")).out_exe("bar").args(&extra_c_flags()).run();
run("bar");
fs::remove_file(static_lib("foo"));
remove_file(static_lib("foo"));
run("bar");
}
10 changes: 5 additions & 5 deletions tests/run-make/compiler-builtins/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#![deny(warnings)]

use run_make_support::fs::{read, read_dir, write};
use run_make_support::object;
use run_make_support::object::read::archive::ArchiveFile;
use run_make_support::object::read::Object;
Expand Down Expand Up @@ -41,8 +42,8 @@ fn main() {

// Set up the tiniest Cargo project: An empty no_std library. Just enough to run -Zbuild-std.
let manifest_path = tmp_path("Cargo.toml");
std::fs::write(&manifest_path, MANIFEST.as_bytes()).unwrap();
std::fs::write(tmp_path("lib.rs"), b"#![no_std]").unwrap();
write(&manifest_path, MANIFEST.as_bytes());
write(tmp_path("lib.rs"), b"#![no_std]");

let path = std::env::var("PATH").unwrap();
let rustc = std::env::var("RUSTC").unwrap();
Expand Down Expand Up @@ -71,8 +72,7 @@ fn main() {
assert!(status.success());

let rlibs_path = target_dir.join(target).join("debug").join("deps");
let compiler_builtins_rlib = std::fs::read_dir(rlibs_path)
.unwrap()
let compiler_builtins_rlib = read_dir(rlibs_path)
.find_map(|e| {
let path = e.unwrap().path();
let file_name = path.file_name().unwrap().to_str().unwrap();
Expand All @@ -86,7 +86,7 @@ fn main() {

// rlib files are archives, where the archive members each a CGU, and we also have one called
// lib.rmeta which is the encoded metadata. Each of the CGUs is an object file.
let data = std::fs::read(compiler_builtins_rlib).unwrap();
let data = read(compiler_builtins_rlib);

let mut defined_symbols = HashSet::new();
let mut undefined_relocations = HashSet::new();
Expand Down
6 changes: 3 additions & 3 deletions tests/run-make/doctests-keep-binaries/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Check that valid binaries are persisted by running them, regardless of whether the
// --run or --no-run option is used.

use run_make_support::fs::{create_dir, remove_dir_all};
use run_make_support::{run, rustc, rustdoc, tmp_dir, tmp_path};
use std::fs::{create_dir, remove_dir_all};
use std::path::Path;

fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) {
let out_dir = tmp_path("doctests");
create_dir(&out_dir).expect("failed to create doctests folder");
create_dir(&out_dir);
rustc().input("t.rs").crate_type("rlib").run();
callback(&out_dir, &tmp_path("libt.rlib"));
remove_dir_all(out_dir);
Expand Down Expand Up @@ -46,7 +46,7 @@ fn main() {
setup_test_env(|_out_dir, extern_path| {
let run_dir = "rundir";
let run_dir_path = tmp_path("rundir");
create_dir(&run_dir_path).expect("failed to create rundir folder");
create_dir(&run_dir_path);

rustdoc()
.current_dir(tmp_dir())
Expand Down
4 changes: 2 additions & 2 deletions tests/run-make/doctests-runtool/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Tests behavior of rustdoc `--runtool`.

use run_make_support::fs::{create_dir, remove_dir_all};
use run_make_support::{rustc, rustdoc, tmp_dir, tmp_path};
use std::env::current_dir;
use std::fs::{create_dir, remove_dir_all};
use std::path::PathBuf;

fn mkdir(name: &str) -> PathBuf {
let dir = tmp_path(name);
create_dir(&dir).expect("failed to create doctests folder");
create_dir(&dir);
dir
}

Expand Down
2 changes: 1 addition & 1 deletion tests/run-make/issue-107495-archive-permissions/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#[cfg(unix)]
extern crate libc;

use run_make_support::fs;
use run_make_support::{aux_build, tmp_path};
use std::fs;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
Expand Down
1 change: 1 addition & 0 deletions tests/run-make/no-intermediate-extras/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::fs;
fn main() {
rustc().crate_type("rlib").arg("--test").input("foo.rs").run();
assert!(
// Do not use run-make-support's fs wrapper here - this needs to return an Error.
fs::remove_file(tmp_path("foo.bc")).is_err(),
"An unwanted .bc file was created by run-make/no-intermediate-extras."
);
Expand Down
3 changes: 2 additions & 1 deletion tests/run-make/non-unicode-env/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use run_make_support::fs;
use run_make_support::rustc;

fn main() {
Expand All @@ -7,6 +8,6 @@ fn main() {
let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]);
let output = rustc().input("non_unicode_env.rs").env("NON_UNICODE_VAR", non_unicode).run_fail();
let actual = std::str::from_utf8(&output.stderr).unwrap();
let expected = std::fs::read_to_string("non_unicode_env.stderr").unwrap();
let expected = fs::read_to_string("non_unicode_env.stderr");
assert_eq!(actual, expected);
}
5 changes: 3 additions & 2 deletions tests/run-make/non-unicode-in-incremental-dir/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ fn main() {
let non_unicode: &std::ffi::OsStr = std::os::unix::ffi::OsStrExt::from_bytes(&[0xFF]);
#[cfg(windows)]
let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]);
// Do not use run-make-support's fs wrapper, this needs special handling.
match std::fs::create_dir(tmp_path(&non_unicode)) {
// If an error occurs, check if creating a directory with a valid Unicode name would
// succeed.
Expand All @@ -17,8 +18,8 @@ fn main() {
}
let incr_dir = tmp_path("incr-dir");
rustc().input("foo.rs").incremental(&incr_dir).run();
for crate_dir in std::fs::read_dir(&incr_dir).unwrap() {
std::fs::create_dir(crate_dir.unwrap().path().join(&non_unicode)).unwrap();
for crate_dir in run_make_support::fs::read_dir(&incr_dir) {
run_make_support::fs::create_dir(crate_dir.unwrap().path().join(&non_unicode));
}
rustc().input("foo.rs").incremental(&incr_dir).run();
}
3 changes: 2 additions & 1 deletion tests/run-make/print-cfg/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::ffi::OsString;
use std::io::BufRead;
use std::iter::FromIterator;

use run_make_support::fs;
use run_make_support::{rustc, tmp_path};

struct PrintCfg {
Expand Down Expand Up @@ -97,7 +98,7 @@ fn check(PrintCfg { target, includes, disallow }: PrintCfg) {

let output = rustc().target(target).arg(print_arg).run();

let output = std::fs::read_to_string(&tmp_path).unwrap();
let output = fs::read_to_string(&tmp_path).unwrap();

check_(&output, includes, disallow);
}
Expand Down
3 changes: 2 additions & 1 deletion tests/run-make/print-to-output/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use std::ffi::OsString;

use run_make_support::fs;
use run_make_support::{rustc, target, tmp_path};

struct Option<'a> {
Expand Down Expand Up @@ -52,7 +53,7 @@ fn check(args: Option) {

let _output = rustc().target(args.target).arg(print_arg).run();

std::fs::read_to_string(&tmp_path).unwrap()
fs::read_to_string(&tmp_path)
};

check_(&stdout, args.includes);
Expand Down
5 changes: 2 additions & 3 deletions tests/run-make/repr128-dwarf/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use gimli::{AttributeValue, Dwarf, EndianRcSlice, Reader, RunTimeEndian};
use object::{Object, ObjectSection};
use run_make_support::fs;
use run_make_support::{gimli, object, rustc, tmp_path};
use std::borrow::Cow;
use std::collections::HashMap;
Expand All @@ -18,9 +19,7 @@ fn main() {
.join("Resources")
.join("DWARF")
.join("repr128");
let output =
std::fs::read(if dsym_location.try_exists().unwrap() { dsym_location } else { output })
.unwrap();
let output = fs::read(if dsym_location.try_exists().unwrap() { dsym_location } else { output });
let obj = object::File::parse(output.as_slice()).unwrap();
let endian = if obj.is_little_endian() { RunTimeEndian::Little } else { RunTimeEndian::Big };
let dwarf = gimli::Dwarf::load(|section| -> Result<_, ()> {
Expand Down
4 changes: 2 additions & 2 deletions tests/run-make/reset-codegen-1/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

//@ ignore-cross-compile

use run_make_support::fs;
use run_make_support::{rustc, tmp_path};
use std::fs;

fn compile(output_file: &str, emit: Option<&str>) {
let mut rustc = rustc();
Expand All @@ -31,7 +31,7 @@ fn main() {
("multi-output", Some("asm,obj")),
];
for (output_file, emit) in flags {
fs::remove_file(output_file).unwrap_or_default();
std::fs::remove_file(output_file).unwrap_or_default();
compile(output_file, emit);
fs::remove_file(output_file);
}
Expand Down
Loading

0 comments on commit 1094107

Please sign in to comment.