Skip to content
This repository has been archived by the owner on Dec 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #8 from golemcloud/update-cargo-deps
Browse files Browse the repository at this point in the history
GOL-225 Update cargo component deps automatically
  • Loading branch information
vigoo authored Feb 28, 2024
2 parents bd199be + c7f926c commit 51c0b80
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 16 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Options:
-s, --stub-wit-root <STUB_WIT_ROOT>
-d, --dest-wit-root <DEST_WIT_ROOT>
-o, --overwrite
-u, --update-cargo-toml
-h, --help Print help
-V, --version Print version
```
Expand All @@ -117,4 +118,5 @@ The command merges a generated RPC stub as a WIT dependency into an other compon
- `stub-wit-root`: The WIT root generated by either `generate` or `build` command
- `dest-wit-root`: The WIT root of the component where the stub should be added as a dependency
- `overwrite`: This command would not do anything if it detects that it would change an existing WIT file's contents at
the destination. With this flag, it can be forced to overwrite those files.
the destination. With this flag, it can be forced to overwrite those files.
- `update-cargo-toml`: Enables updating the Cargo.toml file in the parent directory of `dest-wit-root` with the copied dependencies.ation. With this flag, it can be forced to overwrite those files.
4 changes: 3 additions & 1 deletion wasm-rpc-stubgen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Options:
-s, --stub-wit-root <STUB_WIT_ROOT>
-d, --dest-wit-root <DEST_WIT_ROOT>
-o, --overwrite
-u, --update-cargo-toml
-h, --help Print help
-V, --version Print version
```
Expand All @@ -79,4 +80,5 @@ The command merges a generated RPC stub as a WIT dependency into an other compon
- `stub-wit-root`: The WIT root generated by either `generate` or `build` command
- `dest-wit-root`: The WIT root of the component where the stub should be added as a dependency
- `overwrite`: This command would not do anything if it detects that it would change an existing WIT file's contents at
the destination. With this flag, it can be forced to overwrite those files.
the destination. With this flag, it can be forced to overwrite those files.
- `update-cargo-toml`: Enables updating the Cargo.toml file in the parent directory of `dest-wit-root` with the copied dependencies.
73 changes: 62 additions & 11 deletions wasm-rpc-stubgen/src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,38 @@
// limitations under the License.

use crate::stub::StubDefinition;
use anyhow::{anyhow, bail};
use crate::wit;
use anyhow::{anyhow, bail, Context};
use cargo_toml::{
Dependency, DependencyDetail, DepsSet, Edition, Inheritable, LtoSetting, Manifest, Profile,
Profiles, StripSetting,
};
use golem_wasm_rpc::WASM_RPC_VERSION;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fs;
use std::path::Path;
use toml::Value;

#[derive(Serialize, Default)]
#[derive(Serialize, Deserialize, Default)]
struct MetadataRoot {
component: Option<ComponentMetadata>,
}

#[derive(Serialize)]
#[derive(Serialize, Deserialize)]
struct ComponentMetadata {
package: String,
package: Option<String>,
target: ComponentTarget,
}

#[derive(Serialize)]
#[derive(Serialize, Deserialize)]
struct ComponentTarget {
world: String,
world: Option<String>,
path: String,
dependencies: HashMap<String, WitDependency>,
}

#[derive(Serialize)]
#[derive(Serialize, Deserialize)]
struct WitDependency {
path: String,
}
Expand Down Expand Up @@ -91,12 +93,12 @@ pub fn generate_cargo_toml(def: &StubDefinition) -> anyhow::Result<()> {

let metadata = MetadataRoot {
component: Some(ComponentMetadata {
package: format!(
package: Some(format!(
"{}:{}",
def.root_package_name.namespace, def.root_package_name.name
),
)),
target: ComponentTarget {
world: def.target_world_name()?,
world: Some(def.target_world_name()?),
path: "wit".to_string(),
dependencies: wit_dependencies,
},
Expand Down Expand Up @@ -168,3 +170,52 @@ pub fn generate_cargo_toml(def: &StubDefinition) -> anyhow::Result<()> {
fs::write(def.target_cargo_path(), cargo_toml)?;
Ok(())
}

pub fn is_cargo_component_toml(path: &Path) -> anyhow::Result<bool> {
let manifest: Manifest<MetadataRoot> = Manifest::from_path_with_metadata(path)?;

if let Some(package) = manifest.package {
if let Some(metadata) = package.metadata {
if metadata.component.is_some() {
return Ok(true);
}
}
}

Ok(false)
}

pub fn add_dependencies_to_cargo_toml(cargo_path: &Path, names: &[String]) -> anyhow::Result<()> {
let mut manifest: Manifest<MetadataRoot> = Manifest::from_path_with_metadata(cargo_path)?;
if let Some(ref mut package) = manifest.package {
if let Some(ref mut metadata) = package.metadata {
if let Some(ref mut component) = metadata.component {
let existing: HashSet<_> = component.target.dependencies.keys().cloned().collect();
for name in names {
if !existing.contains(name) {
let relative_path = format!("wit/deps/{}", name);
let path = cargo_path
.parent()
.context("Parent directory of Cargo.toml")?
.join(&relative_path);
let package_name = wit::get_package_name(&path)?;

component.target.dependencies.insert(
format!("{}:{}", package_name.namespace, package_name.name),
WitDependency {
path: relative_path,
},
);
}
}

let cargo_toml = toml::to_string(&manifest)?;

println!("Writing updated Cargo.toml to {:?}", cargo_path);
fs::write(cargo_path, cargo_toml)?;
}
}
}

Ok(())
}
14 changes: 14 additions & 0 deletions wasm-rpc-stubgen/src/compilation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright 2024 Golem Cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use cargo_component::config::{CargoArguments, Config};
use cargo_component::{load_component_metadata, load_metadata, run_cargo_command};
use cargo_component_core::terminal::{Color, Terminal, Verbosity};
Expand Down
31 changes: 29 additions & 2 deletions wasm-rpc-stubgen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::compilation::compile;
use crate::rust::generate_stub_source;
use crate::stub::StubDefinition;
use crate::wit::{copy_wit_files, generate_stub_wit, verify_action, WitAction};
use anyhow::Context;
use anyhow::{anyhow, Context};
use clap::Parser;
use fs_extra::dir::CopyOptions;
use heck::ToSnakeCase;
Expand Down Expand Up @@ -81,6 +81,8 @@ struct AddStubDependencyArgs {
dest_wit_root: PathBuf,
#[clap(short, long)]
overwrite: bool,
#[clap(short, long)]
update_cargo_toml: bool,
}

#[tokio::main]
Expand Down Expand Up @@ -208,10 +210,35 @@ fn add_stub_dependency(args: AddStubDependencyArgs) -> anyhow::Result<()> {
}

if proceed {
for action in actions {
for action in &actions {
action.perform(&args.dest_wit_root)?;
}
}

if let Some(target_parent) = args.dest_wit_root.parent() {
let target_cargo_toml = target_parent.join("Cargo.toml");
if target_cargo_toml.exists()
&& target_cargo_toml.is_file()
&& cargo::is_cargo_component_toml(&target_cargo_toml).is_ok()
{
if !args.update_cargo_toml {
eprintln!("Warning: the newly copied dependencies have to be added to {}. Use the --update-cargo-toml flag to update it automatically.", target_cargo_toml.to_string_lossy());
} else {
let mut names = Vec::new();
for action in actions {
names.push(action.get_dep_dir_name()?);
}
cargo::add_dependencies_to_cargo_toml(&target_cargo_toml, &names)?;
}
} else if args.update_cargo_toml {
return Err(anyhow!(
"Cannot update {:?} file because it does not exist or is not a file",
target_cargo_toml
));
}
} else if args.update_cargo_toml {
return Err(anyhow!("Cannot update the Cargo.toml file because parent directory of the destination WIT root does not exist."));
}

Ok(())
}
13 changes: 12 additions & 1 deletion wasm-rpc-stubgen/src/wit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ pub fn get_dep_dirs(wit_root: &Path) -> anyhow::Result<Vec<PathBuf>> {
}

pub fn get_package_name(wit: &Path) -> anyhow::Result<PackageName> {
let pkg = UnresolvedPackage::parse_file(wit)?;
let pkg = UnresolvedPackage::parse_path(wit)?;
Ok(pkg.name)
}

Expand Down Expand Up @@ -369,6 +369,17 @@ impl WitAction {

Ok(())
}

pub fn get_dep_dir_name(&self) -> anyhow::Result<String> {
match self {
WitAction::CopyDepDir { source_dir } => Ok(source_dir
.file_name()
.context("Get wit dependency directory name")?
.to_string_lossy()
.to_string()),
WitAction::CopyDepWit { dir_name, .. } => Ok(dir_name.clone()),
}
}
}

pub fn verify_action(
Expand Down

0 comments on commit 51c0b80

Please sign in to comment.