Skip to content

Commit

Permalink
Merge pull request #431 from fitzgen/stop-reading-cargo-toml-many-times
Browse files Browse the repository at this point in the history
Stop reading cargo toml many times
  • Loading branch information
fitzgen authored Nov 5, 2018
2 parents 91e3de3 + 098eb33 commit 400cfba
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 129 deletions.
12 changes: 7 additions & 5 deletions src/command/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use PBAR;
#[allow(missing_docs)]
pub struct Build {
pub crate_path: PathBuf,
pub crate_data: manifest::CargoManifest,
pub scope: Option<String>,
pub disable_dts: bool,
pub target: String,
Expand Down Expand Up @@ -104,11 +105,13 @@ impl Build {
/// Construct a build command from the given options.
pub fn try_from_opts(build_opts: BuildOptions) -> Result<Self, failure::Error> {
let crate_path = set_crate_path(build_opts.path)?;
let crate_name = manifest::get_crate_name(&crate_path)?;
let crate_data = manifest::CargoManifest::read(&crate_path)?;
let crate_name = crate_data.get_crate_name().to_string();
let out_dir = crate_path.join(PathBuf::from(build_opts.out_dir));
// let build_config = manifest::xxx(&crate_path).xxx();
Ok(Build {
crate_path,
crate_data,
scope: build_opts.scope,
disable_dts: build_opts.disable_dts,
target: build_opts.target,
Expand Down Expand Up @@ -213,7 +216,7 @@ impl Build {

fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> {
info!(&log, "Checking crate configuration...");
manifest::check_crate_config(&self.crate_path, step)?;
self.crate_data.check_crate_config(step)?;
info!(&log, "Crate is correctly configured.");
Ok(())
}
Expand Down Expand Up @@ -250,8 +253,7 @@ impl Build {

fn step_create_json(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> {
info!(&log, "Writing a package.json...");
manifest::write_package_json(
&self.crate_path,
self.crate_data.write_package_json(
&self.out_dir,
&self.scope,
self.disable_dts,
Expand Down Expand Up @@ -298,7 +300,7 @@ impl Build {
info!(&log, "Installing wasm-bindgen-cli was successful.");

info!(&log, "Getting the crate name from the manifest...");
self.crate_name = manifest::get_crate_name(&self.crate_path)?;
self.crate_name = self.crate_data.get_crate_name().to_string();
info!(
&log,
"Got crate name {:#?} from the manifest at {:#?}.",
Expand Down
12 changes: 4 additions & 8 deletions src/command/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub struct TestOptions {
/// A configured `wasm-pack test` command.
pub struct Test {
crate_path: PathBuf,
crate_data: manifest::CargoManifest,
cache: Cache,
node: bool,
mode: BuildMode,
Expand Down Expand Up @@ -116,13 +117,7 @@ impl Test {
} = test_opts;

let crate_path = set_crate_path(path)?;

// let geckodriver = get_web_driver("geckodriver", test_opts.geckodriver, test_opts.firefox)?;
// let chromedriver =
// get_web_driver("chromedriver", test_opts.chromedriver, test_opts.chrome)?;
// let safaridriver =
// get_web_driver("safaridriver", test_opts.safaridriver, test_opts.safari)?;

let crate_data = manifest::CargoManifest::read(&crate_path)?;
let any_browser = chrome || firefox || safari;

if !node && !any_browser {
Expand All @@ -143,6 +138,7 @@ impl Test {
Ok(Test {
cache: Cache::new()?,
crate_path,
crate_data,
node,
mode,
chrome,
Expand Down Expand Up @@ -248,7 +244,7 @@ impl Test {

fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> {
info!(log, "Checking crate configuration...");
manifest::check_crate_config(&self.crate_path, step)?;
self.crate_data.check_crate_config(step)?;
info!(log, "Crate is correctly configured.");
Ok(())
}
Expand Down
156 changes: 79 additions & 77 deletions src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ use serde_json;
use toml;
use PBAR;

#[derive(Debug, Deserialize)]
struct CargoManifest {
/// A parsed `Cargo.toml` manifest.
#[derive(Clone, Debug, Deserialize)]
pub struct CargoManifest {
package: CargoPackage,
dependencies: Option<HashMap<String, CargoDependency>>,
#[serde(rename = "dev-dependencies")]
dev_dependencies: Option<HashMap<String, CargoDependency>>,
lib: Option<CargoLib>,
}

#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize)]
struct CargoPackage {
name: String,
authors: Vec<String>,
Expand Down Expand Up @@ -59,42 +60,99 @@ impl CargoPackage {
}
}

#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
enum CargoDependency {
Simple(String),
Detailed(DetailedCargoDependency),
}

#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize)]
struct DetailedCargoDependency {
version: Option<String>,
}

#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize)]
struct CargoLib {
#[serde(rename = "crate-type")]
crate_type: Option<Vec<String>>,
}

fn read_cargo_toml(path: &Path) -> Result<CargoManifest, failure::Error> {
let manifest_path = path.join("Cargo.toml");
if !manifest_path.is_file() {
return Err(Error::crate_config(&format!(
"Crate directory is missing a `Cargo.toml` file; is `{}` the wrong directory?",
path.display()
))
.into());
impl CargoManifest {
/// Read the `Cargo.toml` inside the crate at the given `crate_path`.
pub fn read(crate_path: &Path) -> Result<CargoManifest, failure::Error> {
let manifest_path = crate_path.join("Cargo.toml");
if !manifest_path.is_file() {
return Err(Error::crate_config(&format!(
"Crate directory is missing a `Cargo.toml` file; is `{}` the wrong directory?",
crate_path.display()
))
.into());
}
let mut cargo_file = File::open(manifest_path)?;
let mut cargo_contents = String::new();
cargo_file.read_to_string(&mut cargo_contents)?;

let manifest: CargoManifest = toml::from_str(&cargo_contents)?;
Ok(manifest)
}
let mut cargo_file = File::open(manifest_path)?;
let mut cargo_contents = String::new();
cargo_file.read_to_string(&mut cargo_contents)?;

let manifest: CargoManifest = toml::from_str(&cargo_contents)?;
Ok(manifest)
}
/// Generate a package.json file inside in `./pkg`.
pub fn write_package_json(
&self,
out_dir: &Path,
scope: &Option<String>,
disable_dts: bool,
target: &str,
step: &Step,
) -> Result<(), failure::Error> {
let msg = format!("{}Writing a package.json...", emoji::MEMO);

PBAR.step(step, &msg);
let pkg_file_path = out_dir.join("package.json");
let mut pkg_file = File::create(pkg_file_path)?;
let npm_data = if target == "nodejs" {
self.clone().into_commonjs(scope, disable_dts)
} else if target == "no-modules" {
self.clone().into_nomodules(scope, disable_dts)
} else {
self.clone().into_esmodules(scope, disable_dts)
};

let npm_json = serde_json::to_string_pretty(&npm_data)?;
pkg_file.write_all(npm_json.as_bytes())?;
Ok(())
}

/// Get the crate name for the crate at the given path.
pub fn get_crate_name(&self) -> &str {
&self.package.name
}

/// Check that the crate the given path is properly configured.
pub fn check_crate_config(&self, step: &Step) -> Result<(), failure::Error> {
let msg = format!("{}Checking crate configuration...", emoji::WRENCH);
PBAR.step(&step, &msg);
self.check_crate_type()?;
Ok(())
}

fn check_crate_type(&self) -> Result<(), failure::Error> {
if self.lib.as_ref().map_or(false, |lib| {
lib.crate_type
.as_ref()
.map_or(false, |types| types.iter().any(|s| s == "cdylib"))
}) {
return Ok(());
}
Err(Error::crate_config(
"crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your \
Cargo.toml file:\n\n\
[lib]\n\
crate-type = [\"cdylib\", \"rlib\"]"
).into())
}

impl CargoManifest {
fn into_commonjs(mut self, scope: &Option<String>, disable_dts: bool) -> NpmPackage {
let filename = self.package.name.replace("-", "_");
let wasm_file = format!("{}_bg.wasm", filename);
Expand Down Expand Up @@ -207,59 +265,3 @@ impl CargoManifest {
})
}
}

/// Generate a package.json file inside in `./pkg`.
pub fn write_package_json(
path: &Path,
out_dir: &Path,
scope: &Option<String>,
disable_dts: bool,
target: &str,
step: &Step,
) -> Result<(), failure::Error> {
let msg = format!("{}Writing a package.json...", emoji::MEMO);

PBAR.step(step, &msg);
let pkg_file_path = out_dir.join("package.json");
let mut pkg_file = File::create(pkg_file_path)?;
let crate_data = read_cargo_toml(path)?;
let npm_data = if target == "nodejs" {
crate_data.into_commonjs(scope, disable_dts)
} else if target == "no-modules" {
crate_data.into_nomodules(scope, disable_dts)
} else {
crate_data.into_esmodules(scope, disable_dts)
};

let npm_json = serde_json::to_string_pretty(&npm_data)?;
pkg_file.write_all(npm_json.as_bytes())?;
Ok(())
}

/// Get the crate name for the crate at the given path.
pub fn get_crate_name(path: &Path) -> Result<String, failure::Error> {
Ok(read_cargo_toml(path)?.package.name)
}

/// Check that the crate the given path is properly configured.
pub fn check_crate_config(path: &Path, step: &Step) -> Result<(), failure::Error> {
let msg = format!("{}Checking crate configuration...", emoji::WRENCH);
PBAR.step(&step, &msg);
check_crate_type(path)?;
Ok(())
}

fn check_crate_type(path: &Path) -> Result<(), failure::Error> {
if read_cargo_toml(path)?.lib.map_or(false, |lib| {
lib.crate_type
.map_or(false, |types| types.iter().any(|s| s == "cdylib"))
}) {
return Ok(());
}
Err(Error::crate_config(
"crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your \
Cargo.toml file:\n\n\
[lib]\n\
crate-type = [\"cdylib\", \"rlib\"]"
).into())
}
Loading

0 comments on commit 400cfba

Please sign in to comment.