Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix for a Url to String conversion in `info` command - [#1330](https://github.com/paritytech/cargo-contract/pull/1330)
- Add warning message when using incompatible contract's ink! version [#1334](https://github.com/paritytech/cargo-contract/pull/1334)
- Bump `subxt` to `0.32.0` - [#1352](https://github.com/paritytech/cargo-contract/pull/1352)
- Add workspace support -[#1358](https://github.com/paritytech/cargo-contract/pull/1358)

## [4.0.0-alpha]

Expand Down
1 change: 1 addition & 0 deletions crates/build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ fn exec_cargo_for_onchain_target(
manifest
.with_replaced_lib_to_bin()?
.with_profile_release_defaults(Profile::default_contract_release())?
.with_merged_workspace_dependencies(crate_metadata)?
.with_empty_workspace();
Ok(())
})?
Expand Down
1 change: 1 addition & 0 deletions crates/build/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub fn execute(
lto: Some(Lto::Thin),
..Profile::default()
})?
.with_merged_workspace_dependencies(crate_metadata)?
.with_empty_workspace();
Ok(())
})?
Expand Down
117 changes: 116 additions & 1 deletion crates/build/src/workspace/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use super::{
metadata,
Profile,
};
use crate::OptimizationPasses;
use crate::{
CrateMetadata,
OptimizationPasses,
};

use std::{
convert::TryFrom,
Expand Down Expand Up @@ -341,6 +344,57 @@ impl Manifest {
Ok(self)
}

/// Merge the workspace dependencies with the crate dependencies.
pub fn with_merged_workspace_dependencies(
&mut self,
crate_metadata: &CrateMetadata,
) -> Result<&mut Self> {
let workspace_manifest_path =
crate_metadata.cargo_meta.workspace_root.join("Cargo.toml");

// If the workspace manifest is the same as the crate manifest, there's not
// workspace to fix
if workspace_manifest_path == self.path.path {
return Ok(self)
Comment thread
ascjones marked this conversation as resolved.
}

let workspace_toml =
fs::read_to_string(&workspace_manifest_path).context("Loading Cargo.toml")?;
let workspace_toml: value::Table = toml::from_str(&workspace_toml)?;

let workspace_dependencies = workspace_toml
.get("workspace")
.ok_or_else(|| {
anyhow::anyhow!("[workspace] should exist in workspace manifest")
})?
.as_table()
.ok_or_else(|| anyhow::anyhow!("[workspace] should be a table"))?
.get("dependencies");

// If no workspace dependencies are defined, return
let Some(workspace_dependencies) = workspace_dependencies else {
return Ok(self)
};

let workspace_dependencies =
workspace_dependencies.as_table().ok_or_else(|| {
anyhow::anyhow!("[workspace.dependencies] should be a table")
})?;

merge_workspace_with_crate_dependencies(
"dependencies",
&mut self.toml,
workspace_dependencies,
)?;
merge_workspace_with_crate_dependencies(
"dev-dependencies",
&mut self.toml,
workspace_dependencies,
)?;

Ok(self)
}

/// Replace relative paths with absolute paths with the working directory.
///
/// Enables the use of a temporary amended copy of the manifest.
Expand Down Expand Up @@ -548,6 +602,67 @@ fn crate_type_exists(crate_type: &str, crate_types: &[value::Value]) -> bool {
.any(|v| v.as_str().map_or(false, |s| s == crate_type))
}

fn merge_workspace_with_crate_dependencies(
section_name: &str,
crate_toml: &mut value::Table,
workspace_dependencies: &value::Table,
) -> Result<()> {
let Some(dependencies) = crate_toml.get_mut(section_name) else {
return Ok(())
};

let table = dependencies
.as_table_mut()
.ok_or_else(|| anyhow::anyhow!("dependencies should be a table"))?;

for (name, value) in table {
let Some(dependency) = value.as_table_mut() else {
continue
};

let is_workspace_dependency = dependency
.get_mut("workspace")
.unwrap_or(&mut toml::Value::Boolean(false))
.as_bool()
.unwrap_or(false);
if !is_workspace_dependency {
continue
}

let workspace_dependency = workspace_dependencies.get(name).unwrap();
Comment thread
ascjones marked this conversation as resolved.
Outdated
let workspace_dependency = match workspace_dependency {
toml::Value::Table(table) => table.to_owned(),
// If the workspace dependency is just a version string, we create a table
toml::Value::String(version) => {
let mut table = toml::value::Table::new();
table.insert("version".to_string(), toml::Value::String(version.clone()));
table
}
// If the workspace dependency is invalid, we throw an error
_ => {
anyhow::bail!("Invalid workspace dependency for {}", name);
}
};

dependency.remove("workspace");
for (key, value) in workspace_dependency {
if let Some(config) = dependency.get_mut(&key) {
// If it's an array we merge the values,
// otherwise we keep the crate value.
if let toml::Value::Array(value) = value {
if let toml::Value::Array(config) = config {
config.extend(value.clone());
Comment thread
ascjones marked this conversation as resolved.
}
}
continue
}
dependency.insert(key.clone(), value.clone());
Comment thread
ascjones marked this conversation as resolved.
Outdated
}
}

Ok(())
}

#[cfg(test)]
mod test {
use super::ManifestPath;
Expand Down