Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 13 additions & 19 deletions src/docker.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
use crate::{
failure,
failure::Failure,
format::{CodePath, CodeStr},
spinner::spin,
toastfile::MappingPath,
};
use crate::{failure, failure::Failure, format::CodeStr, spinner::spin, toastfile::MappingPath};
use std::{
collections::HashMap,
convert::TryFrom,
Expand Down Expand Up @@ -223,15 +217,15 @@ fn rename_or_copy_file_or_symlink(
#[cfg(unix)]
let target_path = read_link(source_path).map_err(failure::system(format!(
"Unable to read target of symbolic link {}.",
source_path.code_path(),
source_path.code_str(),
)))?;

// Create a copy of the symlink at the destination.
#[cfg(unix)]
std::os::unix::fs::symlink(target_path, destination_path).map_err(failure::system(
format!(
"Unable to create symbolic link at {}.",
destination_path.code_path(),
destination_path.code_str(),
),
))?;

Expand All @@ -240,16 +234,16 @@ fn rename_or_copy_file_or_symlink(
format!(
"Unable to create symbolic link at {}, because symlinks are not currently \
supported on Windows.",
destination_path.code_path(),
destination_path.code_str(),
),
None,
));
} else {
// It's a file. Copy it to the destination.
copy(source_path, destination_path).map_err(failure::system(format!(
"Unable to move or copy file {} to destination {}.",
source_path.code_path(),
destination_path.code_path(),
source_path.code_str(),
destination_path.code_str(),
)))?;
}
}
Expand All @@ -271,7 +265,7 @@ pub fn copy_from_container(
for path in paths {
debug!(
"Copying {} from container {}\u{2026}",
path.code_path(),
path.code_str(),
container.code_str(),
);

Expand All @@ -291,7 +285,7 @@ pub fn copy_from_container(
let intermediate = temp_dir.path().join("data");
let destination = destination_dir.join(
std::path::PathBuf::try_from(path.clone())
.map_err(|_| Failure::User(format!("Invalid path {}", path.code_path()), None))?,
.map_err(|_| Failure::User(format!("Invalid path {}", path.code_str()), None))?,
);

// Docker's composite copy arguments require paths that can be represented as UTF-8.
Expand Down Expand Up @@ -322,7 +316,7 @@ pub fn copy_from_container(
let intermediate_metadata =
symlink_metadata(&intermediate).map_err(failure::system(format!(
"Unable to fetch filesystem metadata for {}.",
intermediate.code_path(),
intermediate.code_str(),
)))?;

// Determine what we got from the container.
Expand All @@ -332,13 +326,13 @@ pub fn copy_from_container(
// If we run into an error traversing the filesystem, report it.
let entry = entry.map_err(failure::system(format!(
"Unable to traverse directory {}.",
intermediate.code_path(),
intermediate.code_str(),
)))?;

// Fetch the metadata for this entry.
let entry_metadata = entry.metadata().map_err(failure::system(format!(
"Unable to fetch filesystem metadata for {}.",
entry.path().code_path(),
entry.path().code_str(),
)))?;

// Figure out what needs to go where. The `unwrap` is safe because `entry` is
Expand All @@ -352,7 +346,7 @@ pub fn copy_from_container(
// It's a directory. Create a directory at the destination.
create_dir_all(&entry_destination_path).map_err(failure::system(format!(
"Unable to create directory {}.",
entry_destination_path.code_path(),
entry_destination_path.code_str(),
)))?;
} else {
// It's a file or symlink. Move or copy it to the destination.
Expand All @@ -371,7 +365,7 @@ pub fn copy_from_container(
// Make sure the destination directory exists.
create_dir_all(&destination_parent).map_err(failure::system(format!(
"Unable to create directory {}.",
destination_parent.code_path(),
destination_parent.code_str(),
)))?;

// Move or copy it to the destination.
Expand Down
29 changes: 12 additions & 17 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,6 @@ use colored::{ColoredString, Colorize, control::SHOULD_COLORIZE};
use std::path::Path;
use typed_path::UnixPath;

// This trait formats a filesystem path for human-facing diagnostic output.
pub trait CodePath {
fn code_path(&self) -> ColoredString;
}

impl CodePath for Path {
fn code_path(&self) -> ColoredString {
self.to_string_lossy().code_str()
}
}

impl CodePath for UnixPath {
fn code_path(&self) -> ColoredString {
self.to_string_lossy().code_str()
}
}

// This trait has a function for formatting "code-like" text, such as a file path. The reason it's
// implemented as a trait and not just a function is so we can use it with method syntax, as in
// `x.code_str()`. Rust does not allow us to implement methods on primitive types such as `str`.
Expand All @@ -38,6 +21,18 @@ impl CodeStr for str {
}
}

impl CodeStr for Path {
fn code_str(&self) -> ColoredString {
self.to_string_lossy().code_str()
}
}

impl CodeStr for UnixPath {
fn code_str(&self) -> ColoredString {
self.to_string_lossy().code_str()
}
}

// This function takes a number and a noun and returns a string representing the noun with the
// given multiplicity (pluralizing if necessary). For example, (3, "cow") becomes "3 cows".
pub fn number(n: usize, noun: &str) -> String {
Expand Down
15 changes: 6 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ mod spinner;
mod tar;
mod toastfile;

use crate::{
failure::Failure,
format::{CodePath, CodeStr},
};
use crate::{failure::Failure, format::CodeStr};
use clap::{ArgAction, Parser};
use env_logger::{Builder, fmt::style::Effects};
use log::{Level, LevelFilter};
Expand Down Expand Up @@ -288,7 +285,7 @@ fn settings() -> Result<Settings, Failure> {
.and_then(|path| {
debug!(
"Attempting to load configuration file {}\u{2026}",
path.code_path(),
path.code_str(),
);
fs::read_to_string(path).ok()
})
Expand All @@ -307,7 +304,7 @@ fn settings() -> Result<Settings, Failure> {
config_file_path
.as_ref()
.unwrap() // Manually verified safe
.code_path(),
.code_str(),
)))?;

// Read the local caching switches.
Expand Down Expand Up @@ -361,13 +358,13 @@ fn parse_toastfile(toastfile_path: &Path) -> Result<toastfile::Toastfile, Failur
// Read the file from disk.
let toastfile_data = fs::read_to_string(toastfile_path).map_err(failure::user(format!(
"Unable to read file {}.",
toastfile_path.code_path(),
toastfile_path.code_str(),
)))?;

// Parse it.
toastfile::parse(&toastfile_data).map_err(failure::user(format!(
"Unable to parse file {}.",
toastfile_path.code_path(),
toastfile_path.code_str(),
)))
}

Expand Down Expand Up @@ -414,7 +411,7 @@ fn get_roots<'a>(
format!(
"No task named {} in {}.",
task.code_str(),
settings.toastfile_path.code_path(),
settings.toastfile_path.code_str(),
),
None,
));
Expand Down
32 changes: 16 additions & 16 deletions src/tar.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{cache, cache::CryptoHash, failure, failure::Failure, format::CodePath, spinner::spin};
use crate::{cache, cache::CryptoHash, failure, failure::Failure, format::CodeStr, spinner::spin};
use sha2::{Digest, Sha256};
use std::{
collections::HashSet,
Expand Down Expand Up @@ -98,7 +98,7 @@ fn add_file<W: Write + Seek>(
.append_writer(
&mut header,
std::path::PathBuf::try_from(path_rcr.to_path_buf()).map_err(|_| {
Failure::User(format!("Invalid path {}", path_rcr.code_path()), None)
Failure::User(format!("Invalid path {}", path_rcr.code_str()), None)
})?,
)
.map_err(failure::system("Error appending data to tar archive."))?;
Expand Down Expand Up @@ -137,7 +137,7 @@ fn add_symlink<W: Write>(
header
.set_link_name(
std::path::PathBuf::try_from(target.to_path_buf())
.map_err(|_| Failure::User(format!("Invalid path {}", target.code_path()), None))?,
.map_err(|_| Failure::User(format!("Invalid path {}", target.code_str()), None))?,
)
.map_err(failure::system(
"Error appending symbolic link to tar archive.",
Expand All @@ -150,7 +150,7 @@ fn add_symlink<W: Write>(
.append_data(
&mut header,
std::path::PathBuf::try_from(path_rcr.to_path_buf()).map_err(|_| {
Failure::User(format!("Invalid path {}", path_rcr.code_path()), None)
Failure::User(format!("Invalid path {}", path_rcr.code_str()), None)
})?,
empty(),
)
Expand Down Expand Up @@ -180,7 +180,7 @@ fn add_directory<W: Write>(builder: &mut Builder<W>, path_rcr: &UnixPath) -> Res
.append_data(
&mut header,
std::path::PathBuf::try_from(path_rcr.to_path_buf()).map_err(|_| {
Failure::User(format!("Invalid path {}", path_rcr.code_path()), None)
Failure::User(format!("Invalid path {}", path_rcr.code_str()), None)
})?,
empty(),
)
Expand Down Expand Up @@ -223,7 +223,7 @@ fn add_path<W: Write + Seek>(
// archive.
let file = File::open(path_cd).map_err(failure::system(format!(
"Unable to open file {}.",
path_cd.code_path(),
path_cd.code_str(),
)))?;

// Add the file to the archive and compute the hash from the exact bytes we archived.
Expand All @@ -240,10 +240,10 @@ fn add_path<W: Write + Seek>(
// It's a symlink. Read the target path.
let target_path_std = read_link(path_cd).map_err(failure::system(format!(
"Unable to read target of symbolic link {}.",
path_cd.code_path(),
path_cd.code_str(),
)))?;
let target_path = UnixPathBuf::try_from(target_path_std)
.map_err(|_| Failure::User(format!("Invalid path {}.", path_cd.code_path()), None))?;
.map_err(|_| Failure::User(format!("Invalid path {}.", path_cd.code_str()), None))?;

// Compute the hash of the symlink path and the target path.
content_hashes.push(cache::combine(
Expand All @@ -263,7 +263,7 @@ fn add_path<W: Write + Seek>(
Err(Failure::User(
format!(
"{} is not a file, directory, or symbolic link.",
path_cd.code_path(),
path_cd.code_str(),
),
None,
))
Expand Down Expand Up @@ -315,15 +315,15 @@ pub fn create<W: Write + Seek>(
// current working directory instead.
let input_path_cd = source_dir_cd.join(
std::path::PathBuf::try_from(input_path_rsd.clone()).map_err(|_| {
Failure::User(format!("Invalid path {}", input_path_rsd.code_path()), None)
Failure::User(format!("Invalid path {}", input_path_rsd.code_str()), None)
})?,
);

// Fetch filesystem metadata for `input_path`.
let input_path_metadata =
symlink_metadata(&input_path_cd).map_err(failure::system(format!(
"Unable to fetch filesystem metadata for {}.",
input_path_cd.code_path(),
input_path_cd.code_str(),
)))?;

// Check what type of filesystem object the path corresponds to.
Expand All @@ -344,7 +344,7 @@ pub fn create<W: Write + Seek>(
}
.map_err(failure::user(format!(
"Unable to traverse directory {}.",
input_path_cd.code_path(),
input_path_cd.code_str(),
)))?;

// Compute the path relative to the container filesystem root.
Expand All @@ -354,20 +354,20 @@ pub fn create<W: Write + Seek>(
.strip_prefix(source_dir_cd)
.map_err(failure::system(format!(
"Unable to relativize path {} with respect to {}.",
entry.path().code_path(),
source_dir_cd.code_path(),
entry.path().code_str(),
source_dir_cd.code_str(),
)))?;
let entry_path_acr = destination_dir_acr.join(
UnixPathBuf::try_from(entry_path_rsd.to_path_buf()).map_err(|_| {
Failure::User(format!("Invalid path {}", entry_path_rsd.code_path()), None)
Failure::User(format!("Invalid path {}", entry_path_rsd.code_str()), None)
})?,
);
let entry_path_rcr = strip_root_rcr(&entry_path_acr);

// Fetch the metadata for this entry.
let entry_metadata = entry.metadata().map_err(failure::system(format!(
"Unable to fetch filesystem metadata for {}.",
entry.path().code_path(),
entry.path().code_str(),
)))?;

// Skip descending into directories which are denied by `excluded_input_paths`.
Expand Down
18 changes: 7 additions & 11 deletions src/toastfile.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use crate::{
failure::Failure,
format,
format::{CodePath, CodeStr},
};
use crate::{failure::Failure, format, format::CodeStr};
use serde::{Deserialize, Deserializer, de::Error};
use std::{
collections::{HashMap, HashSet},
Expand Down Expand Up @@ -253,7 +249,7 @@ pub fn parse(toastfile_data: &str) -> Result<Toastfile, Failure> {
format!(
"Toastfile has a relative {}: {}.",
"location".code_str(),
toastfile.location.code_path(),
toastfile.location.code_str(),
),
None,
));
Expand Down Expand Up @@ -509,7 +505,7 @@ fn check_task(name: &str, task: &Task) -> Result<(), Failure> {
"Task {} has an absolute {}: {}.",
name.code_str(),
"input_path".code_str(),
path.code_path(),
path.code_str(),
),
None,
));
Expand All @@ -524,7 +520,7 @@ fn check_task(name: &str, task: &Task) -> Result<(), Failure> {
"Task {} has an absolute {}: {}.",
name.code_str(),
"excluded_input_path".code_str(),
path.code_path(),
path.code_str(),
),
None,
));
Expand All @@ -539,7 +535,7 @@ fn check_task(name: &str, task: &Task) -> Result<(), Failure> {
"Task {} has an absolute path in {}: {}.",
name.code_str(),
"output_paths".code_str(),
path.code_path(),
path.code_str(),
),
None,
));
Expand All @@ -554,7 +550,7 @@ fn check_task(name: &str, task: &Task) -> Result<(), Failure> {
"Task {} has an absolute path in {}: {}.",
name.code_str(),
"output_paths_on_failure".code_str(),
path.code_path(),
path.code_str(),
),
None,
));
Expand Down Expand Up @@ -600,7 +596,7 @@ fn check_task(name: &str, task: &Task) -> Result<(), Failure> {
"Task {} has a relative {}: {}.",
name.code_str(),
"location".code_str(),
location.code_path(),
location.code_str(),
),
None,
));
Expand Down
Loading