1use crate::{GitError, GitRepo, GitTree};
6use rhai::{Array, Dynamic, Engine, EvalAltResult};
7
8pub fn register_git_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
18 engine.register_type::<GitTree>();
20 engine.register_fn("git_tree_new", git_tree_new);
21
22 engine.register_fn("list", git_tree_list);
24 engine.register_fn("find", git_tree_find);
25 engine.register_fn("get", git_tree_get);
26
27 engine.register_type::<GitRepo>();
29 engine.register_fn("path", git_repo_path);
30 engine.register_fn("has_changes", git_repo_has_changes);
31 engine.register_fn("pull", git_repo_pull);
32 engine.register_fn("reset", git_repo_reset);
33 engine.register_fn("commit", git_repo_commit);
34 engine.register_fn("push", git_repo_push);
35
36 engine.register_fn("git_clone", git_clone);
38
39 Ok(())
40}
41
42fn git_error_to_rhai_error<T>(result: Result<T, GitError>) -> Result<T, Box<EvalAltResult>> {
44 result.map_err(|e| {
45 Box::new(EvalAltResult::ErrorRuntime(
46 format!("Git error: {}", e).into(),
47 rhai::Position::NONE,
48 ))
49 })
50}
51
52pub fn git_tree_new(base_path: &str) -> Result<GitTree, Box<EvalAltResult>> {
60 git_error_to_rhai_error(GitTree::new(base_path))
61}
62
63pub fn git_tree_list(git_tree: &mut GitTree) -> Result<Array, Box<EvalAltResult>> {
67 let repos = git_error_to_rhai_error(git_tree.list())?;
68
69 let mut array = Array::new();
71 for repo in repos {
72 array.push(Dynamic::from(repo));
73 }
74
75 Ok(array)
76}
77
78pub fn git_tree_find(git_tree: &mut GitTree, pattern: &str) -> Result<Array, Box<EvalAltResult>> {
83 let repos: Vec<GitRepo> = git_error_to_rhai_error(git_tree.find(pattern))?;
84
85 let mut array = Array::new();
87 for repo in repos {
88 array.push(Dynamic::from(repo));
89 }
90
91 Ok(array)
92}
93
94pub fn git_tree_get(
102 git_tree: &mut GitTree,
103 name_or_url: &str,
104) -> Result<GitRepo, Box<EvalAltResult>> {
105 let mut repos_vec: Vec<GitRepo> = git_error_to_rhai_error(git_tree.get(name_or_url))?;
106
107 match repos_vec.len() {
108 1 => Ok(repos_vec.remove(0)), 0 => Err(Box::new(EvalAltResult::ErrorRuntime(
110 format!("Git error: Repository '{}' not found.", name_or_url).into(),
111 rhai::Position::NONE,
112 ))),
113 _ => Err(Box::new(EvalAltResult::ErrorRuntime(
114 format!(
115 "Git error: Multiple repositories ({}) found matching '{}'. Use find() for patterns or provide a more specific name for get().",
116 repos_vec.len(),
117 name_or_url
118 )
119 .into(),
120 rhai::Position::NONE,
121 ))),
122 }
123}
124
125pub fn git_repo_path(git_repo: &mut GitRepo) -> String {
133 git_repo.path().to_string()
134}
135
136pub fn git_repo_has_changes(git_repo: &mut GitRepo) -> Result<bool, Box<EvalAltResult>> {
140 git_error_to_rhai_error(git_repo.has_changes())
141}
142
143pub fn git_repo_pull(git_repo: &mut GitRepo) -> Result<GitRepo, Box<EvalAltResult>> {
147 git_error_to_rhai_error(git_repo.pull())
148}
149
150pub fn git_repo_reset(git_repo: &mut GitRepo) -> Result<GitRepo, Box<EvalAltResult>> {
154 git_error_to_rhai_error(git_repo.reset())
155}
156
157pub fn git_repo_commit(
161 git_repo: &mut GitRepo,
162 message: &str,
163) -> Result<GitRepo, Box<EvalAltResult>> {
164 git_error_to_rhai_error(git_repo.commit(message))
165}
166
167pub fn git_repo_push(git_repo: &mut GitRepo) -> Result<GitRepo, Box<EvalAltResult>> {
171 git_error_to_rhai_error(git_repo.push())
172}
173
174pub fn git_clone(url: &str) -> Result<GitRepo, Box<EvalAltResult>> {
188 let base_path = std::env::var("GIT_DEFAULT_BASE_PATH").unwrap_or_else(|_| {
190 std::env::temp_dir()
191 .join("sal_git_clones")
192 .to_string_lossy()
193 .to_string()
194 });
195
196 let git_tree = git_error_to_rhai_error(GitTree::new(&base_path))?;
198 let repos = git_error_to_rhai_error(git_tree.get(url))?;
199
200 repos.into_iter().next().ok_or_else(|| {
202 Box::new(EvalAltResult::ErrorRuntime(
203 "Git error: No repository was cloned".into(),
204 rhai::Position::NONE,
205 ))
206 })
207}