changepacks_core/
workspace.rs1use std::{collections::HashSet, path::Path};
2
3use crate::{Config, Language, Package, update_type::UpdateType};
4use anyhow::{Context, Result};
5use async_trait::async_trait;
6
7#[async_trait]
8pub trait Workspace: std::fmt::Debug + Send + Sync {
9 fn name(&self) -> Option<&str>;
10 fn path(&self) -> &Path;
11 fn relative_path(&self) -> &Path;
12 fn version(&self) -> Option<&str>;
13 async fn update_version(&mut self, update_type: UpdateType) -> Result<()>;
14 fn language(&self) -> Language;
15
16 fn dependencies(&self) -> &HashSet<String>;
17 fn add_dependency(&mut self, dependency: &str);
18
19 fn check_changed(&mut self, path: &Path) -> Result<()> {
21 if self.is_changed() {
22 return Ok(());
23 }
24 if !path.to_string_lossy().contains(".changepacks")
25 && path.starts_with(self.path().parent().context("Parent not found")?)
26 {
27 self.set_changed(true);
28 }
29 Ok(())
30 }
31
32 fn is_changed(&self) -> bool;
33 fn set_changed(&mut self, changed: bool);
34
35 fn default_publish_command(&self) -> &'static str;
37
38 async fn publish(&self, config: &Config) -> Result<()> {
40 let command = self.get_publish_command(config);
41 let workspace_dir = self
43 .path()
44 .parent()
45 .context("Workspace directory not found")?;
46
47 let mut cmd = if cfg!(target_os = "windows") {
48 let mut c = tokio::process::Command::new("cmd");
49 c.arg("/C");
50 c.arg(command);
51 c
52 } else {
53 let mut c = tokio::process::Command::new("sh");
54 c.arg("-c");
55 c.arg(command);
56 c
57 };
58
59 cmd.current_dir(workspace_dir);
60 let output = cmd.output().await?;
61
62 if !output.status.success() {
63 anyhow::bail!(
64 "Publish command failed: {}",
65 String::from_utf8_lossy(&output.stderr)
66 );
67 } else {
68 Ok(())
69 }
70 }
71
72 fn get_publish_command(&self, config: &Config) -> String {
74 if let Some(cmd) = config
76 .publish
77 .get(self.relative_path().to_string_lossy().as_ref())
78 {
79 return cmd.clone();
80 }
81
82 let lang_key = match self.language() {
84 crate::Language::Node => "node",
85 crate::Language::Python => "python",
86 crate::Language::Rust => "rust",
87 crate::Language::Dart => "dart",
88 };
89 if let Some(cmd) = config.publish.get(lang_key) {
90 return cmd.clone();
91 }
92
93 self.default_publish_command().to_string()
95 }
96
97 async fn update_workspace_dependencies(&self, _packages: &[&dyn Package]) -> Result<()> {
98 Ok(())
99 }
100}