use super::TargetTripleSource;
use crate::errors::TargetTripleError;
use camino::{Utf8Path, Utf8PathBuf};
use camino_tempfile::Utf8TempDir;
#[derive(Debug)]
pub struct ExtractedCustomPlatform {
source: TargetTripleSource,
dir: Utf8TempDir,
path: Utf8PathBuf,
}
impl ExtractedCustomPlatform {
pub fn new(
triple_str: &str,
json: &str,
source: TargetTripleSource,
) -> Result<Self, TargetTripleError> {
let temp_dir = camino_tempfile::Builder::new()
.prefix("nextest-custom-target-")
.rand_bytes(5)
.tempdir()
.map_err(|error| TargetTripleError::CustomPlatformTempDirError {
source: source.clone(),
error,
})?;
let path = temp_dir.path().join(format!("{triple_str}.json"));
std::fs::write(&path, json).map_err(|error| {
TargetTripleError::CustomPlatformWriteError {
source: source.clone(),
path: path.clone(),
error,
}
})?;
Ok(Self {
source,
dir: temp_dir,
path,
})
}
pub fn source(&self) -> &TargetTripleSource {
&self.source
}
pub fn dir(&self) -> &Utf8TempDir {
&self.dir
}
pub fn path(&self) -> &Utf8Path {
&self.path
}
pub fn close(self) -> Result<(), TargetTripleError> {
let dir_path = self.dir.path().to_owned();
self.dir
.close()
.map_err(|error| TargetTripleError::CustomPlatformCloseError {
source: self.source,
dir_path,
error,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cargo_config::{
CargoTargetArg, TargetDefinitionLocation, TargetTriple, test_helpers::setup_temp_dir,
};
use color_eyre::eyre::{Context, Result, bail, eyre};
#[test]
fn test_extracted_custom_platform() -> Result<()> {
let target = {
let temp_dir = setup_temp_dir()?;
let platform_path = temp_dir.path().join("custom-target/my-target.json");
TargetTriple::custom_from_path(
&platform_path,
TargetTripleSource::CliOption,
temp_dir.path(),
)?
};
let summary = target.platform.to_summary();
let target2 = TargetTriple::deserialize(Some(summary))
.wrap_err("deserializing target triple")?
.ok_or_else(|| eyre!("deserializing target triple resulted in None"))?;
assert_eq!(target2.source, TargetTripleSource::Metadata);
assert!(
matches!(
target2.location,
TargetDefinitionLocation::MetadataCustom(_)
),
"triple2.location should be MetadataCustom: {:?}",
target2.location
);
let arg = target2
.to_cargo_target_arg()
.wrap_err("converting to cargo target arg")?;
let extracted = match &arg {
CargoTargetArg::Extracted(extracted) => extracted,
_ => bail!("expected CargoTargetArg::Extracted, found {:?}", arg),
};
assert!(extracted.path().is_absolute(), "path should be absolute");
assert!(
extracted.path().ends_with("my-target.json"),
"extracted path should end with 'my-target.json'"
);
assert_eq!(
arg.to_string(),
extracted.path(),
"arg matches extracted path"
);
let target3 = TargetTriple::custom_from_path(
extracted.path(),
TargetTripleSource::CliOption,
extracted.dir().path(),
)?;
assert_eq!(target3.platform, target.platform, "platform roundtrips");
Ok(())
}
}