feat(solc): relative remappings (#786)
This commit is contained in:
parent
d2b59d7097
commit
b619a5522f
|
@ -190,6 +190,124 @@ impl Remapping {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A relative [`Remapping`] that's aware of the current location
|
||||||
|
///
|
||||||
|
/// See [`RelativeRemappingPathBuf`]
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct RelativeRemapping {
|
||||||
|
pub name: String,
|
||||||
|
pub path: RelativeRemappingPathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelativeRemapping {
|
||||||
|
/// Creates a new `RelativeRemapping` starting prefixed with `root`
|
||||||
|
pub fn new(remapping: Remapping, root: impl AsRef<Path>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: remapping.name,
|
||||||
|
path: RelativeRemappingPathBuf::with_root(root, remapping.path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts this relative remapping into an absolute remapping
|
||||||
|
///
|
||||||
|
/// This sets to root of the remapping to the given `root` path
|
||||||
|
pub fn to_remapping(mut self, root: PathBuf) -> Remapping {
|
||||||
|
self.path.parent = Some(root);
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remappings are printed as `prefix=target`
|
||||||
|
impl fmt::Display for RelativeRemapping {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}={}", self.name, self.path.original().display())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RelativeRemapping> for Remapping {
|
||||||
|
fn from(r: RelativeRemapping) -> Self {
|
||||||
|
Remapping { name: r.name, path: r.path.relative().to_string_lossy().to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Remapping> for RelativeRemapping {
|
||||||
|
fn from(r: Remapping) -> Self {
|
||||||
|
Self { name: r.name, path: r.path.into() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The path part of the [`Remapping`] that knows the path of the file it was configured in, if any.
|
||||||
|
///
|
||||||
|
/// A [`Remapping`] is intended to be absolute, but paths in configuration files are often desired
|
||||||
|
/// to be relative to the configuration file itself. For example, a path of
|
||||||
|
/// `weird-erc20/=lib/weird-erc20/src/` configured in a file `/var/foundry.toml` might be desired to
|
||||||
|
/// resolve as a `weird-erc20/=/var/lib/weird-erc20/src/` remapping.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct RelativeRemappingPathBuf {
|
||||||
|
parent: Option<PathBuf>,
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelativeRemappingPathBuf {
|
||||||
|
/// Creates a new `RelativeRemappingPathBuf` that checks if the `path` is a child path of
|
||||||
|
/// `parent`.
|
||||||
|
pub fn with_root(parent: impl AsRef<Path>, path: impl AsRef<Path>) -> Self {
|
||||||
|
let parent = parent.as_ref();
|
||||||
|
let path = path.as_ref();
|
||||||
|
if let Ok(path) = path.strip_prefix(parent) {
|
||||||
|
Self { parent: Some(parent.to_path_buf()), path: path.to_path_buf() }
|
||||||
|
} else if path.has_root() {
|
||||||
|
Self { parent: None, path: path.to_path_buf() }
|
||||||
|
} else {
|
||||||
|
Self { parent: Some(parent.to_path_buf()), path: path.to_path_buf() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path as it was declared, without modification.
|
||||||
|
pub fn original(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns this path relative to the file it was delcared in, if any.
|
||||||
|
/// Returns the original if this path was not declared in a file or if the
|
||||||
|
/// path has a root.
|
||||||
|
pub fn relative(&self) -> PathBuf {
|
||||||
|
if self.original().has_root() {
|
||||||
|
return self.original().into()
|
||||||
|
}
|
||||||
|
self.parent
|
||||||
|
.as_ref()
|
||||||
|
.map(|p| p.join(self.original()))
|
||||||
|
.unwrap_or_else(|| self.original().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: AsRef<Path>> From<P> for RelativeRemappingPathBuf {
|
||||||
|
fn from(path: P) -> RelativeRemappingPathBuf {
|
||||||
|
Self { parent: None, path: path.as_ref().to_path_buf() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for RelativeRemapping {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::ser::Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for RelativeRemapping {
|
||||||
|
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::de::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let remapping = String::deserialize(deserializer)?;
|
||||||
|
let remapping = Remapping::from_str(&remapping).map_err(serde::de::Error::custom)?;
|
||||||
|
Ok(RelativeRemapping { name: remapping.name, path: remapping.path.into() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Candidate {
|
struct Candidate {
|
||||||
/// dir that opened the window
|
/// dir that opened the window
|
||||||
|
@ -358,6 +476,27 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::utils::tempdir;
|
use crate::utils::tempdir;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn relative_remapping() {
|
||||||
|
let remapping = "oz=a/b/c/d";
|
||||||
|
let remapping = Remapping::from_str(remapping).unwrap();
|
||||||
|
|
||||||
|
let relative = RelativeRemapping::new(remapping.clone(), "a/b/c");
|
||||||
|
assert_eq!(relative.path.relative(), Path::new(&remapping.path));
|
||||||
|
assert_eq!(relative.path.original(), Path::new("d"));
|
||||||
|
|
||||||
|
let relative = RelativeRemapping::new(remapping.clone(), "x/y");
|
||||||
|
assert_eq!(relative.path.relative(), Path::new("x/y/a/b/c/d"));
|
||||||
|
assert_eq!(relative.path.original(), Path::new(&remapping.path));
|
||||||
|
|
||||||
|
let remapping = "oz=/a/b/c/d";
|
||||||
|
let remapping = Remapping::from_str(remapping).unwrap();
|
||||||
|
let relative = RelativeRemapping::new(remapping.clone(), "a/b");
|
||||||
|
assert_eq!(relative.path.relative(), Path::new(&remapping.path));
|
||||||
|
assert_eq!(relative.path.original(), Path::new(&remapping.path));
|
||||||
|
assert!(relative.path.parent.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serde() {
|
fn serde() {
|
||||||
let remapping = "oz=../b/c/d";
|
let remapping = "oz=../b/c/d";
|
||||||
|
|
Loading…
Reference in New Issue