manifest.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use super::{
  5. app_paths::tauri_dir,
  6. config::{all_allowlist_features, ConfigHandle},
  7. };
  8. use anyhow::Context;
  9. use toml_edit::{Array, Document, InlineTable, Item, Value};
  10. use std::{
  11. collections::HashSet,
  12. fs::File,
  13. io::{Read, Write},
  14. path::Path,
  15. };
  16. pub struct Manifest {
  17. pub features: HashSet<String>,
  18. }
  19. fn read_manifest(manifest_path: &Path) -> crate::Result<Document> {
  20. let mut manifest_str = String::new();
  21. let mut manifest_file = File::open(manifest_path)
  22. .with_context(|| format!("failed to open `{:?}` file", manifest_path))?;
  23. manifest_file.read_to_string(&mut manifest_str)?;
  24. let manifest: Document = manifest_str
  25. .parse::<Document>()
  26. .with_context(|| "failed to parse Cargo.toml")?;
  27. Ok(manifest)
  28. }
  29. fn toml_array(features: &HashSet<String>) -> Array {
  30. let mut f = Array::default();
  31. let mut features: Vec<String> = features.iter().map(|f| f.to_string()).collect();
  32. features.sort();
  33. for feature in features {
  34. f.push(feature.as_str()).unwrap();
  35. }
  36. f
  37. }
  38. pub fn rewrite_manifest(config: ConfigHandle) -> crate::Result<Manifest> {
  39. let manifest_path = tauri_dir().join("Cargo.toml");
  40. let mut manifest = read_manifest(&manifest_path)?;
  41. let dependencies = manifest
  42. .as_table_mut()
  43. .entry("dependencies")
  44. .as_table_mut()
  45. .expect("manifest dependencies isn't a table");
  46. let tauri_entry = dependencies.entry("tauri");
  47. let config_guard = config.lock().unwrap();
  48. let config = config_guard.as_ref().unwrap();
  49. let allowlist_features = config.tauri.features();
  50. let mut features = HashSet::new();
  51. for feature in allowlist_features {
  52. features.insert(feature.to_string());
  53. }
  54. if config.tauri.cli.is_some() {
  55. features.insert("cli".to_string());
  56. }
  57. if config.tauri.updater.active {
  58. features.insert("updater".to_string());
  59. }
  60. if config.tauri.system_tray.is_some() {
  61. features.insert("system-tray".to_string());
  62. }
  63. let mut cli_managed_features = all_allowlist_features();
  64. cli_managed_features.extend(vec!["cli", "updater", "system-tray"]);
  65. if let Some(tauri) = tauri_entry.as_table_mut() {
  66. let manifest_features = tauri.entry("features");
  67. if let Item::Value(Value::Array(f)) = &manifest_features {
  68. for feat in f.iter() {
  69. if let Value::String(feature) = feat {
  70. if !cli_managed_features.contains(&feature.value().as_str()) {
  71. features.insert(feature.value().to_string());
  72. }
  73. }
  74. }
  75. }
  76. *manifest_features = Item::Value(Value::Array(toml_array(&features)));
  77. } else if let Some(tauri) = tauri_entry.as_value_mut() {
  78. match tauri {
  79. Value::InlineTable(table) => {
  80. let manifest_features = table.get_or_insert("features", Value::Array(Default::default()));
  81. if let Value::Array(f) = &manifest_features {
  82. for feat in f.iter() {
  83. if let Value::String(feature) = feat {
  84. if !cli_managed_features.contains(&feature.value().as_str()) {
  85. features.insert(feature.value().to_string());
  86. }
  87. }
  88. }
  89. }
  90. *manifest_features = Value::Array(toml_array(&features));
  91. }
  92. Value::String(version) => {
  93. let mut def = InlineTable::default();
  94. def.get_or_insert(
  95. "version",
  96. version.to_string().replace("\"", "").replace(" ", ""),
  97. );
  98. def.get_or_insert("features", Value::Array(toml_array(&features)));
  99. *tauri = Value::InlineTable(def);
  100. }
  101. _ => {
  102. return Err(anyhow::anyhow!(
  103. "Unsupported tauri dependency format on Cargo.toml"
  104. ))
  105. }
  106. }
  107. } else {
  108. return Ok(Manifest { features });
  109. }
  110. let mut manifest_file =
  111. File::create(&manifest_path).with_context(|| "failed to open Cargo.toml for rewrite")?;
  112. manifest_file.write_all(
  113. manifest
  114. .to_string_in_original_order()
  115. // apply some formatting fixes
  116. .replace(r#"" ,features =["#, r#"", features = ["#)
  117. .replace("]}", "] }")
  118. .replace("={", "= {")
  119. .replace("=[", "= [")
  120. .as_bytes(),
  121. )?;
  122. manifest_file.flush()?;
  123. Ok(Manifest { features })
  124. }
  125. pub fn get_workspace_members() -> crate::Result<Vec<String>> {
  126. let mut manifest = read_manifest(&tauri_dir().join("Cargo.toml"))?;
  127. let workspace = manifest.as_table_mut().entry("workspace").as_table_mut();
  128. match workspace {
  129. Some(workspace) => {
  130. let members = workspace
  131. .entry("members")
  132. .as_array()
  133. .expect("workspace members aren't an array");
  134. Ok(
  135. members
  136. .iter()
  137. .map(|v| v.as_str().unwrap().to_string())
  138. .collect(),
  139. )
  140. }
  141. None => Ok(vec![]),
  142. }
  143. }