Skip to content

Commit

Permalink
Use cargo to get the package associated with a directory
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael-F-Bryan authored and hannobraun committed Jul 18, 2022
1 parent 2df4c33 commit 9baa869
Showing 1 changed file with 40 additions and 29 deletions.
69 changes: 40 additions & 29 deletions crates/fj-host/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use std::{
thread,
};

use cargo_metadata::Metadata;
use notify::Watcher as _;
use thiserror::Error;

Expand All @@ -41,7 +40,8 @@ pub struct Model {
}

impl Model {
/// Initialize the model from a path
/// Initialize the model using the path to its crate (i.e. the folder
/// containing `Cargo.toml`).
///
/// Optionally, the target directory where plugin files are compiled to can
/// be provided. If it is not provided, the target directory is assumed to
Expand All @@ -50,33 +50,28 @@ impl Model {
path: PathBuf,
target_dir: Option<PathBuf>,
) -> io::Result<Self> {
let name = {
// Can't panic. It only would, if the path ends with "..", and we
// are canonicalizing it here to prevent that.
let canonical = path.canonicalize()?;
let file_name = canonical
.file_name()
.expect("Expected path to be canonical");

file_name.to_string_lossy().replace('-', "_")
};
let crate_dir = path.canonicalize()?;

let metadata = cargo_metadata::MetadataCommand::new()
.current_dir(&crate_dir)
.exec()
.map_err(metadata_error_to_io)?;

let src_path = path.join("src");
let pkg = package_associated_with_directory(&metadata, &crate_dir)?;
let src_path = crate_dir.join("src");

let lib_path = {
let name = pkg.name.replace('-', "_");
let file = HostPlatform::lib_file_name(&name);
let target_dir = target_dir
.or_else(|| cargo_metadata_target_dir(&path))
.unwrap_or_else(|| path.join("target"));
.unwrap_or_else(|| metadata.target_directory.clone().into());
target_dir.join("debug").join(file)
};

let manifest_path = path.join("Cargo.toml");

Ok(Self {
src_path,
lib_path,
manifest_path,
manifest_path: pkg.manifest_path.as_std_path().to_path_buf(),
})
}

Expand Down Expand Up @@ -211,6 +206,33 @@ impl Model {
}
}

fn metadata_error_to_io(e: cargo_metadata::Error) -> std::io::Error {
match e {
cargo_metadata::Error::Io(io) => io,
_ => std::io::Error::new(io::ErrorKind::Other, e),
}
}

fn package_associated_with_directory<'m>(
metadata: &'m cargo_metadata::Metadata,
dir: &Path,
) -> Result<&'m cargo_metadata::Package, io::Error> {
for pkg in metadata.workspace_packages() {
let crate_dir = pkg
.manifest_path
.parent()
.and_then(|p| p.canonicalize().ok());

if crate_dir.as_deref() == Some(dir) {
return Ok(pkg);
}
}

let msg = format!("\"{}\" doesn't point to a crate", dir.display());

Err(io::Error::new(io::ErrorKind::Other, msg))
}

/// Watches a model for changes, reloading it continually
pub struct Watcher {
_watcher: Box<dyn notify::Watcher>,
Expand Down Expand Up @@ -288,14 +310,3 @@ pub enum Error {
}

type ModelFn = unsafe extern "C" fn(args: &Parameters) -> fj::Shape;

fn cargo_metadata_target_dir(model: &Path) -> Option<PathBuf> {
let Metadata {
target_directory, ..
} = cargo_metadata::MetadataCommand::new()
.current_dir(model)
.exec()
.ok()?;

Some(target_directory.into())
}

0 comments on commit 9baa869

Please sign in to comment.