Skip to content

Commit

Permalink
feat: add support for cargo workspaces
Browse files Browse the repository at this point in the history
  • Loading branch information
Its-Just-Nans committed Feb 17, 2025
1 parent e221ba3 commit f1a4c86
Show file tree
Hide file tree
Showing 12 changed files with 383 additions and 8 deletions.
149 changes: 149 additions & 0 deletions examples/workplace/Cargo.lock

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

10 changes: 10 additions & 0 deletions examples/workplace/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[workspace]
resolver = "2"
members = ["simple-example", "not-default-example"]
default-members = ["simple-example"]

[workspace.package]
edition = "2021"
license = "MIT OR Apache-2.0"
rust-version = "1.76"
version = "0.27.2"
15 changes: 15 additions & 0 deletions examples/workplace/not-default-example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "not-default-example"
version = "0.1.0"
authors = ["Jens Reimann <[email protected]>"]
edition = "2021"

[dependencies]
web-sys = { version = "0.3", features = [
"console",
"Document",
"HtmlElement",
"Node",
"Text",
"Window",
] }
13 changes: 13 additions & 0 deletions examples/workplace/not-default-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Trunk | No-Rust</title>

<base data-trunk-public-url />
</head>
<body>
<h1>Trunk without WASM in workspace (not default target)</h1>
</body>
</html>
15 changes: 15 additions & 0 deletions examples/workplace/not-default-example/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use web_sys::window;

fn start_app() {
let document = window()
.and_then(|win| win.document())
.expect("Could not access document");
let body = document.body().expect("Could not access document.body");
let text_node = document.create_text_node("Hello, world from Vanilla Rust!");
body.append_child(text_node.as_ref())
.expect("Failed to append text");
}

fn main() {
start_app();
}
15 changes: 15 additions & 0 deletions examples/workplace/simple-example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "simple-example"
version = "0.1.0"
authors = ["Jens Reimann <[email protected]>"]
edition = "2021"

[dependencies]
web-sys = { version = "0.3", features = [
"console",
"Document",
"HtmlElement",
"Node",
"Text",
"Window",
] }
13 changes: 13 additions & 0 deletions examples/workplace/simple-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Trunk | No-Rust</title>

<base data-trunk-public-url />
</head>
<body>
<h1>Trunk without WASM in workspace</h1>
</body>
</html>
15 changes: 15 additions & 0 deletions examples/workplace/simple-example/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use web_sys::window;

fn start_app() {
let document = window()
.and_then(|win| win.document())
.expect("Could not access document");
let body = document.body().expect("Could not access document.body");
let text_node = document.create_text_node("Hello, world from Vanilla Rust!");
body.append_child(text_node.as_ref())
.expect("Failed to append text");
}

fn main() {
start_app();
}
57 changes: 55 additions & 2 deletions src/config/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ mod test;
use anyhow::{bail, Context, Result};
use schemars::JsonSchema;
use serde::Deserialize;
use source::Source;
use std::path::PathBuf;
use source::{workspace::WorkspaceConfig, Source};
use std::path::{Path, PathBuf};
use tracing::log;

/// Common configuration model functionality
Expand Down Expand Up @@ -114,6 +114,59 @@ impl ConfigModel for Configuration {
}
}

pub async fn load_workspace_config(
current_path: &Path,
workspace_name: Option<String>,
) -> Result<Option<PathBuf>> {
let cargo_toml = current_path.join("Cargo.toml");
if cargo_toml.exists() {
if let Ok(workspace) = WorkspaceConfig::new(&cargo_toml).await {
match workspace_name {
Some(name) => {
if let Some(workspace) = workspace.get_workspace_by_name(&name) {
// get the parent directory of the workspace
let workspace = match workspace.parent() {
Some(parent) => parent,
None => {
return Err(anyhow::format_err!(
"unable to get parent directory of workspace '{}'",
workspace.display()
));
}
};
return Ok(Some(workspace.to_path_buf()));
}
return Err(anyhow::format_err!(
"workspace '{}' not found in {}",
name,
cargo_toml.display()
));
}
None => {
if let Some(workspace) = workspace.get_default_workspace() {
// get the parent directory of the workspace
let workspace = match workspace.parent() {
Some(parent) => parent,
None => {
return Err(anyhow::format_err!(
"unable to get parent directory of workspace '{}'",
workspace.display()
));
}
};
return Ok(Some(workspace.to_path_buf()));
}
return Err(anyhow::format_err!(
"default workspace not found in {}",
cargo_toml.display()
));
}
}
}
}
Ok(None)
}

/// Locate and load the configuration, given an optional file or directory. Falling back to the
/// current directory.
pub async fn load(path: Option<PathBuf>) -> Result<(Configuration, PathBuf)> {
Expand Down
1 change: 1 addition & 0 deletions src/config/models/source/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod cargo;
pub mod workspace;

use crate::config::{models::ConfigModel, Configuration};
use anyhow::bail;
Expand Down
54 changes: 54 additions & 0 deletions src/config/models/source/workspace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use anyhow::{Context, Result};
use cargo_metadata::{Metadata, MetadataCommand};
use serde::{Deserialize, Serialize};
use std::path::Path;
use std::path::PathBuf;
use tokio::task::spawn_blocking;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkspaceConfig {
pub metadata: Metadata,
}

impl WorkspaceConfig {
pub async fn new(manifest: &Path) -> Result<Self> {
let mut cmd = MetadataCommand::new();
cmd.manifest_path(dunce::simplified(manifest));
let metadata = spawn_blocking(move || cmd.exec())
.await
.context("error awaiting spawned cargo metadata task")?
.context("error getting cargo metadata")?;
Ok(Self { metadata })
}

pub fn get_default_workspace(self) -> Option<PathBuf> {
if let Some(default_member) = self.metadata.workspace_default_members.first() {
if let Some(found) = self
.metadata
.packages
.into_iter()
.find(|p| p.id == *default_member)
{
return Some(found.manifest_path.clone().into());
}
}
None
}

pub fn get_workspace_by_name(self, name: &str) -> Option<PathBuf> {
// we search for the package in the workspace packages list
if let Some(one_package) = self.metadata.packages.iter().find(|m| m.name == name) {
// we check if the package is present in the workspace members list
if self
.metadata
.workspace_members
.into_iter()
.any(|p| p == one_package.id)
{
// we return the manifest path of the package
return Some(one_package.manifest_path.clone().into());
}
}
None
}
}
Loading

0 comments on commit f1a4c86

Please sign in to comment.