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

Generate metadata explicitly for the contract which is build #174

Merged
merged 10 commits into from
Feb 18, 2021
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ subxt = { version = "0.14.0", package = "substrate-subxt", optional = true }
futures = { version = "0.3.12", optional = true }
hex = { version = "0.4.2", optional = true }

# Should be removed once bitvecto-rs/bitvec#105 is resolved
funty = "=1.1.0"

[build-dependencies]
anyhow = "1.0.38"
zip = { version = "0.5.10", default-features = false }
Expand Down
14 changes: 12 additions & 2 deletions src/cmd/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ use contract_metadata::{
SourceLanguage, SourceWasm, User,
};
use semver::Version;
use std::{fs, path::PathBuf};
use std::{
fs,
path::{Path, PathBuf},
};
use url::Url;

const METADATA_FILE: &str = "metadata.json";
Expand Down Expand Up @@ -120,6 +123,13 @@ impl GenerateMetadataCommand {
if self.unstable_options.original_manifest {
generate_metadata(&self.crate_metadata.manifest_path)?;
} else {
let package_name = self.crate_metadata.package_name.clone();
let manifest_dir = match self.crate_metadata.manifest_path.directory() {
Some(dir) => dir,
None => Path::new("./"),
};
let absolute_package_path = manifest_dir.canonicalize()?;

Workspace::new(
&self.crate_metadata.cargo_meta,
&self.crate_metadata.root_package.id,
Expand All @@ -130,7 +140,7 @@ impl GenerateMetadataCommand {
.with_profile_release_lto(false)?;
Ok(())
})?
.with_metadata_gen_package()?
.with_metadata_gen_package(package_name, absolute_package_path)?
.using_temp(generate_metadata)?;
}

Expand Down
39 changes: 23 additions & 16 deletions src/workspace/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,22 @@ impl From<ManifestPath> for PathBuf {
}
}

/// Pointer to the package of a contract.
pub struct ContractPackage {
/// Name of the contract
pub name: String,
/// Path to the contract directory
pub path: PathBuf,
}

/// Create, amend and save a copy of the specified `Cargo.toml`.
pub struct Manifest {
path: ManifestPath,
toml: value::Table,
/// True if a metadata package should be generated for this manifest
metadata_package: bool,
/// Set to `Some(ContractPackage)` if a metadata package should be
/// generated for this manifest. The `ContractPackage` points to the
/// package for which metadata should be generated.
metadata_package: Option<ContractPackage>,
}

impl Manifest {
Expand All @@ -128,7 +138,7 @@ impl Manifest {
Ok(Manifest {
path: manifest_path,
toml,
metadata_package: false,
metadata_package: None,
})
}

Expand All @@ -137,6 +147,12 @@ impl Manifest {
&self.path
}

/// If existent the `ContractPackage` points to the package for which
/// metadata should be generated.
pub(super) fn metadata_package_mut(&mut self) -> Option<&mut ContractPackage> {
self.metadata_package.as_mut()
}

/// Get mutable reference to `[lib] crate-types = []` section
fn get_crate_types_mut(&mut self) -> Result<&mut value::Array> {
let lib = self
Expand Down Expand Up @@ -213,7 +229,7 @@ impl Manifest {
}

/// Adds a metadata package to the manifest workspace for generating metadata
pub fn with_metadata_package(&mut self) -> Result<&mut Self> {
pub fn with_metadata_package(&mut self, target_contract: ContractPackage) -> Result<&mut Self> {
let workspace = self
.toml
.entry("workspace")
Expand Down Expand Up @@ -242,7 +258,7 @@ impl Manifest {
members.push(METADATA_PACKAGE_PATH.into());
}

self.metadata_package = true;
self.metadata_package = Some(target_contract);
Ok(self)
}

Expand Down Expand Up @@ -359,7 +375,7 @@ impl Manifest {
fs::create_dir_all(dir).context(format!("Creating directory '{}'", dir.display()))?;
}

if self.metadata_package {
if let Some(metadata_target_package) = &self.metadata_package {
let dir = if let Some(manifest_dir) = manifest_path.directory() {
manifest_dir.join(METADATA_PACKAGE_PATH)
} else {
Expand All @@ -368,15 +384,6 @@ impl Manifest {

fs::create_dir_all(&dir).context(format!("Creating directory '{}'", dir.display()))?;

let contract_package_name = self
.toml
.get("package")
.ok_or_else(|| anyhow::anyhow!("package section not found"))?
.get("name")
.ok_or_else(|| anyhow::anyhow!("[package] name field not found"))?
.as_str()
.ok_or_else(|| anyhow::anyhow!("[package] name should be a string"))?;

let ink_metadata = self
.toml
.get("dependencies")
Expand All @@ -386,7 +393,7 @@ impl Manifest {
.as_table()
.ok_or_else(|| anyhow::anyhow!("ink_metadata dependency should be a table"))?;

metadata::generate_package(dir, contract_package_name, ink_metadata.clone())?;
metadata::generate_package(dir, &metadata_target_package, ink_metadata.clone())?;
}

let updated_toml = toml::to_string(&self.toml)?;
Expand Down
19 changes: 16 additions & 3 deletions src/workspace/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use anyhow::Result;
use std::{fs, path::Path};
use toml::value;

use crate::workspace::manifest::ContractPackage;

/// Generates a cargo workspace package `metadata-gen` which will be invoked via `cargo run` to
/// generate contract metadata.
///
Expand All @@ -27,13 +29,13 @@ use toml::value;
/// versions are utilized.
pub(super) fn generate_package<P: AsRef<Path>>(
target_dir: P,
contract_package_name: &str,
target_package: &ContractPackage,
mut ink_metadata_dependency: value::Table,
) -> Result<()> {
let dir = target_dir.as_ref();
log::debug!(
"Generating metadata package for {} in {}",
contract_package_name,
target_package.name,
dir.display()
);

Expand All @@ -53,7 +55,18 @@ pub(super) fn generate_package<P: AsRef<Path>>(
.expect("contract dependency specified in the template")
.as_table_mut()
.expect("contract dependency is a table specified in the template");
contract.insert("package".into(), contract_package_name.into());

// the metadata data generation package is put under `.ink/metadata_gen` and we need to
// explicitly reference the (possibly sub-)contract which is build.
let path = target_package
.path
.to_str()
.expect("path must be convertible to str");
contract.insert("path".into(), toml::Value::String(path.to_string()));
contract.insert(
"package".into(),
toml::Value::String(target_package.name.clone()),
);

// make ink_metadata dependency use default features
ink_metadata_dependency.remove("default-features");
Expand Down
29 changes: 26 additions & 3 deletions src/workspace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ use std::{
path::{Path, PathBuf},
};

use crate::workspace::manifest::ContractPackage;

/// Make a copy of a cargo workspace, maintaining only the directory structure and manifest
/// files. Relative paths to source files and non-workspace dependencies are rewritten to absolute
/// paths to the original locations.
Expand Down Expand Up @@ -121,10 +123,22 @@ impl Workspace {
Ok(self)
}

/// Generates a package to invoke for generating contract metadata
pub(super) fn with_metadata_gen_package(&mut self) -> Result<&mut Self> {
/// Generates a package to invoke for generating contract metadata.
///
/// The contract metadata will be generated for the supplied `package_name`
/// found at `package_path`.
pub(super) fn with_metadata_gen_package(
&mut self,
package_name: String,
package_path: PathBuf,
) -> Result<&mut Self> {
let target_contract = ContractPackage {
name: package_name,
path: package_path,
};

self.with_workspace_manifest(|manifest| {
manifest.with_metadata_package()?;
manifest.with_metadata_package(target_contract)?;
Ok(())
})
}
Expand All @@ -149,6 +163,15 @@ impl Workspace {
new_path.push(package.manifest_path.strip_prefix(&self.workspace_root)?);
let new_manifest = ManifestPath::new(new_path)?;

// replace the original path to the package for which metadata should be
// generated with the absolute path to the package in the temporary directory.
if let Some(package) = manifest.metadata_package_mut() {
let absolute_package_path = package.path.canonicalize()?;
let mut new_path: PathBuf = target.as_ref().into();
new_path.push(absolute_package_path.strip_prefix(&self.workspace_root)?);
package.path = new_path;
}
cmichi marked this conversation as resolved.
Show resolved Hide resolved

manifest.rewrite_relative_paths(&exclude_member_package_names)?;
manifest.write(&new_manifest)?;

Expand Down