Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop reading cargo toml many times #431

Merged
merged 6 commits into from
Nov 5, 2018
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
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