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

Add workspace initial support #1358

Merged
merged 14 commits into from
Nov 6, 2023
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `--all` flag for `info` command - [#1319](https://github.com/paritytech/cargo-contract/pull/1319)
- 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)
- Add `workspace-mode` unstable flag -[#1358](https://github.com/paritytech/cargo-contract/pull/1358)

## [4.0.0-alpha]

Expand Down
4 changes: 3 additions & 1 deletion crates/build/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,14 @@ pub struct UnstableOptions {
#[derive(Clone, Default)]
pub struct UnstableFlags {
pub original_manifest: bool,
pub workspace_mode: bool,
}

impl TryFrom<&UnstableOptions> for UnstableFlags {
type Error = anyhow::Error;

fn try_from(value: &UnstableOptions) -> Result<Self, Self::Error> {
let valid_flags = ["original-manifest"];
let valid_flags = ["original-manifest", "workspace-mode"];
let invalid_flags = value
.options
.iter()
Expand All @@ -245,6 +246,7 @@ impl TryFrom<&UnstableOptions> for UnstableFlags {
}
Ok(UnstableFlags {
original_manifest: value.options.contains(&"original-manifest".to_owned()),
workspace_mode: value.options.contains(&"workspace-mode".to_owned()),
})
}
}
Expand Down
11 changes: 11 additions & 0 deletions crates/build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,17 @@ fn exec_cargo_for_onchain_target(
.bold()
);
cargo_build(&crate_metadata.manifest_path)?;
} else if unstable_flags.workspace_mode {
Workspace::new(&crate_metadata.cargo_meta, &crate_metadata.root_package.id)?
.with_root_package_manifest(|manifest| {
manifest
.with_replaced_lib_to_bin()?
.with_profile_release_defaults(Profile::default_contract_release())?
.with_fixed_workspace_dependencies(crate_metadata)?
.with_empty_workspace();
Ok(())
})?
.using_temp(cargo_build)?;
} else {
Workspace::new(&crate_metadata.cargo_meta, &crate_metadata.root_package.id)?
.with_root_package_manifest(|manifest| {
Expand Down
15 changes: 15 additions & 0 deletions crates/build/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,21 @@ pub fn execute(

if unstable_options.original_manifest {
generate_metadata(&crate_metadata.manifest_path)?;
} else if unstable_options.workspace_mode {
Workspace::new(&crate_metadata.cargo_meta, &crate_metadata.root_package.id)?
.with_root_package_manifest(|manifest| {
manifest
.with_added_crate_type("rlib")?
.with_profile_release_defaults(Profile {
lto: Some(Lto::Thin),
..Profile::default()
})?
.with_fixed_workspace_dependencies(crate_metadata)?
.with_empty_workspace();
Ok(())
})?
.with_metadata_gen_package()?
.using_temp(generate_metadata)?;
} else {
Workspace::new(&crate_metadata.cargo_meta, &crate_metadata.root_package.id)?
.with_root_package_manifest(|manifest| {
Expand Down
111 changes: 110 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_fixed_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)
ascjones marked this conversation as resolved.
Show resolved Hide 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,61 @@ 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()
.as_table()
.unwrap();
dependency.remove("workspace");
for (key, value) in workspace_dependency {
if let Some(config) = dependency.get_mut(key) {
match value {
// If it's an array, we append the values
toml::Value::Array(value) => {
if let toml::Value::Array(config) = config {
config.extend(value.clone());
}
}
// Anything else, we keep the crate value
_ => {}
}

continue
}
dependency.insert(key.clone(), value.clone());
ascjones marked this conversation as resolved.
Show resolved Hide resolved
}
}

Ok(())
}

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