cargo_wizard/workspace/
mod.rs1use std::path::Path;
2
3use anyhow::Context;
4
5use crate::Template;
6use manifest::CargoManifest;
7
8use crate::workspace::config::{config_path_from_manifest_path, CargoConfig};
9use crate::workspace::manifest::Profile;
10
11pub mod config;
12pub mod manifest;
13
14#[derive(Clone)]
16pub struct CargoWorkspace {
17 manifest: CargoManifest,
18 config: CargoConfig,
19}
20
21impl CargoWorkspace {
22 pub fn apply_template(
23 self,
24 profile: &Profile,
25 template: &Template,
26 ) -> anyhow::Result<ModifiedWorkspace> {
27 let old_manifest = self.manifest.clone();
28 let new_manifest = self.manifest.apply_template(profile, template)?;
29 let manifest = if old_manifest.get_text() == new_manifest.get_text() {
30 ModificationResult::NoChange
31 } else {
32 ModificationResult::Modified {
33 old: old_manifest,
34 new: new_manifest,
35 }
36 };
37
38 let old_config = self.config.clone();
39 let new_config = self.config.apply_template(template)?;
40 let config = if old_config.get_text() == new_config.get_text() {
41 ModificationResult::NoChange
42 } else {
43 ModificationResult::Modified {
44 old: old_config,
45 new: new_config,
46 }
47 };
48 Ok(ModifiedWorkspace { manifest, config })
49 }
50
51 pub fn existing_profiles(&self) -> Vec<String> {
52 self.manifest.get_profiles()
53 }
54}
55
56pub struct ModifiedWorkspace {
58 manifest: ModificationResult<CargoManifest>,
59 config: ModificationResult<CargoConfig>,
60}
61
62impl ModifiedWorkspace {
63 pub fn manifest(&self) -> &ModificationResult<CargoManifest> {
64 &self.manifest
65 }
66
67 pub fn config(&self) -> &ModificationResult<CargoConfig> {
68 &self.config
69 }
70
71 pub fn write(self) -> anyhow::Result<()> {
72 match self.manifest {
73 ModificationResult::NoChange => {}
74 ModificationResult::Modified { new, .. } => {
75 new.write()?;
76 }
77 }
78 match self.config {
79 ModificationResult::NoChange => {}
80 ModificationResult::Modified { new, .. } => {
81 new.write()?;
82 }
83 }
84 Ok(())
85 }
86}
87
88pub enum ModificationResult<T> {
90 NoChange,
91 Modified { old: T, new: T },
92}
93
94pub fn parse_workspace(manifest_path: &Path) -> anyhow::Result<CargoWorkspace> {
96 let manifest = CargoManifest::from_path(manifest_path)?;
97 let config = Some(config_path_from_manifest_path(manifest_path))
98 .filter(|p| p.exists())
99 .map(|path| CargoConfig::from_path(&path))
100 .transpose()
101 .with_context(|| "Cannot load config.toml")?
102 .unwrap_or_else(|| CargoConfig::empty_from_manifest(manifest_path));
103
104 Ok(CargoWorkspace { manifest, config })
105}