Skip to content

Commit

Permalink
feat: Further improve workspace inheritance, closes #6122, #5070 (#6144)
Browse files Browse the repository at this point in the history
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
  • Loading branch information
FabianLars and lucasfernog authored Jan 26, 2023
1 parent 9da9960 commit d20a728
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 91 deletions.
3 changes: 2 additions & 1 deletion .changes/version-inheritance.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
'cli.rs': 'minor'
'tauri-build': 'minor'
---

Add support for Cargo's workspace inheritance for the package version.
Added support for Cargo's workspace inheritance for package information. The cli now also detects inherited `tauri` and `tauri-build` dependencies and disables manifest rewrites accordingly.
1 change: 1 addition & 0 deletions core/tauri-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ quote = { version = "1", optional = true }
tauri-codegen = { version = "1.2.1", path = "../tauri-codegen", optional = true }
tauri-utils = { version = "1.2.1", path = "../tauri-utils", features = [ "build", "resources" ] }
cargo_toml = "0.14"
serde = "1"
serde_json = "1"
heck = "0.4"
json-patch = "0.3"
Expand Down
160 changes: 114 additions & 46 deletions core/tauri-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
#![cfg_attr(doc_cfg, feature(doc_cfg))]

pub use anyhow::Result;
use cargo_toml::{Dependency, Manifest};
use heck::AsShoutySnakeCase;

use tauri_utils::resources::{external_binaries, resource_relpath, ResourcePaths};
use tauri_utils::{
config::Config,
resources::{external_binaries, resource_relpath, ResourcePaths},
};

use std::path::{Path, PathBuf};

Expand Down Expand Up @@ -242,8 +246,6 @@ pub fn build() {
#[allow(unused_variables)]
pub fn try_build(attributes: Attributes) -> Result<()> {
use anyhow::anyhow;
use cargo_toml::{Dependency, Manifest};
use tauri_utils::config::{Config, TauriConfig};

println!("cargo:rerun-if-env-changed=TAURI_CONFIG");
println!("cargo:rerun-if-changed=tauri.conf.json");
Expand All @@ -268,50 +270,33 @@ pub fn try_build(attributes: Attributes) -> Result<()> {

cfg_alias("dev", !has_feature("custom-protocol"));

let mut manifest = Manifest::from_path("Cargo.toml")?;
if let Some(tauri) = manifest.dependencies.remove("tauri") {
let features = match tauri {
Dependency::Simple(_) => Vec::new(),
Dependency::Detailed(dep) => dep.features,
Dependency::Inherited(dep) => dep.features,
};

let all_cli_managed_features = TauriConfig::all_features();
let diff = features_diff(
&features
.into_iter()
.filter(|f| all_cli_managed_features.contains(&f.as_str()))
.collect::<Vec<String>>(),
&config
.tauri
.features()
.into_iter()
.map(|f| f.to_string())
.collect::<Vec<String>>(),
);

let mut error_message = String::new();
if !diff.remove.is_empty() {
error_message.push_str("remove the `");
error_message.push_str(&diff.remove.join(", "));
error_message.push_str(if diff.remove.len() == 1 {
"` feature"
} else {
"` features"
});
if !diff.add.is_empty() {
error_message.push_str(" and ");
}
}
if !diff.add.is_empty() {
error_message.push_str("add the `");
error_message.push_str(&diff.add.join(", "));
error_message.push_str(if diff.add.len() == 1 {
"` feature"
} else {
"` features"
});
let ws_path = get_workspace_dir()?;
let mut manifest =
Manifest::<cargo_toml::Value>::from_slice_with_metadata(&std::fs::read("Cargo.toml")?)?;

if let Ok(ws_manifest) = Manifest::from_path(ws_path.join("Cargo.toml")) {
Manifest::complete_from_path_and_workspace(
&mut manifest,
Path::new("Cargo.toml"),
Some((&ws_manifest, ws_path.as_path())),
)?;
} else {
Manifest::complete_from_path(&mut manifest, Path::new("Cargo.toml"))?;
}

if let Some(tauri_build) = manifest.build_dependencies.remove("tauri-build") {
let error_message = check_features(&config, tauri_build, true);

if !error_message.is_empty() {
return Err(anyhow!("
The `tauri-build` dependency features on the `Cargo.toml` file does not match the allowlist defined under `tauri.conf.json`.
Please run `tauri dev` or `tauri build` or {}.
", error_message));
}
}

if let Some(tauri) = manifest.dependencies.remove("tauri") {
let error_message = check_features(&config, tauri, false);

if !error_message.is_empty() {
return Err(anyhow!("
Expand Down Expand Up @@ -485,6 +470,89 @@ fn features_diff(current: &[String], expected: &[String]) -> Diff {
Diff { remove, add }
}

fn check_features(config: &Config, dependency: Dependency, is_tauri_build: bool) -> String {
use tauri_utils::config::{PatternKind, TauriConfig};

let features = match dependency {
Dependency::Simple(_) => Vec::new(),
Dependency::Detailed(dep) => dep.features,
Dependency::Inherited(dep) => dep.features,
};

let all_cli_managed_features = if is_tauri_build {
vec!["isolation"]
} else {
TauriConfig::all_features()
};

let expected = if is_tauri_build {
match config.tauri.pattern {
PatternKind::Isolation { .. } => vec!["isolation".to_string()],
_ => vec![],
}
} else {
config
.tauri
.features()
.into_iter()
.map(|f| f.to_string())
.collect::<Vec<String>>()
};

let diff = features_diff(
&features
.into_iter()
.filter(|f| all_cli_managed_features.contains(&f.as_str()))
.collect::<Vec<String>>(),
&expected,
);

let mut error_message = String::new();
if !diff.remove.is_empty() {
error_message.push_str("remove the `");
error_message.push_str(&diff.remove.join(", "));
error_message.push_str(if diff.remove.len() == 1 {
"` feature"
} else {
"` features"
});
if !diff.add.is_empty() {
error_message.push_str(" and ");
}
}
if !diff.add.is_empty() {
error_message.push_str("add the `");
error_message.push_str(&diff.add.join(", "));
error_message.push_str(if diff.add.len() == 1 {
"` feature"
} else {
"` features"
});
}

error_message
}

#[derive(serde::Deserialize)]
struct CargoMetadata {
workspace_root: PathBuf,
}

fn get_workspace_dir() -> Result<PathBuf> {
let output = std::process::Command::new("cargo")
.args(["metadata", "--no-deps", "--format-version", "1"])
.output()?;

if !output.status.success() {
return Err(anyhow::anyhow!(
"cargo metadata command exited with a non zero exit code: {}",
String::from_utf8(output.stderr)?
));
}

Ok(serde_json::from_slice::<CargoMetadata>(&output.stdout)?.workspace_root)
}

#[cfg(test)]
mod tests {
use super::Diff;
Expand Down
24 changes: 13 additions & 11 deletions examples/workspace/Cargo.lock

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

4 changes: 4 additions & 0 deletions examples/workspace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ members = [

[workspace.package]
version = "1.0.0"

[workspace.dependencies]
tauri-build = { path = "../../core/tauri-build", features = [] }
tauri = { path = "../../core/tauri", features = [] }
4 changes: 2 additions & 2 deletions examples/workspace/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ edition = "2021"
rust-version = "1.59"

[build-dependencies]
tauri-build = { path = "../../../core/tauri-build", features = [] }
tauri-build = { workspace = true }

[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { path = "../../../core/tauri", features = [] }
tauri = { workspace = true }
core-api = { path = "../core" }

[features]
Expand Down
2 changes: 1 addition & 1 deletion tooling/cli/Cargo.lock

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

1 change: 1 addition & 0 deletions tooling/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ kuchiki = "0.8"
tokio = { version = "1", features = [ "macros", "sync" ] }
common-path = "1"
serde-value = "0.7.0"
itertools = "0.10"

[target."cfg(windows)".dependencies]
winapi = { version = "0.3", features = [ "handleapi", "processenv", "winbase", "wincon", "winnt" ] }
Expand Down
Loading

0 comments on commit d20a728

Please sign in to comment.