vibe_workspace/utils/
git.rs1use anyhow::Result;
2use std::path::Path;
3use std::process::Command;
4
5pub fn is_git_available() -> bool {
7 Command::new("git")
8 .arg("--version")
9 .output()
10 .map(|output| output.status.success())
11 .unwrap_or(false)
12}
13
14pub fn is_github_cli_available() -> bool {
16 Command::new("gh")
17 .arg("--version")
18 .output()
19 .map(|output| output.status.success())
20 .unwrap_or(false)
21}
22
23pub fn get_git_version() -> Result<String> {
25 let output = Command::new("git").arg("--version").output()?;
26
27 if !output.status.success() {
28 anyhow::bail!("Failed to get git version");
29 }
30
31 let version = String::from_utf8_lossy(&output.stdout);
32 Ok(version.trim().to_string())
33}
34
35pub fn validate_git_repository<P: AsRef<Path>>(path: P) -> Result<()> {
37 let path = path.as_ref();
38
39 if !path.exists() {
40 anyhow::bail!("Path does not exist: {}", path.display());
41 }
42
43 if !path.is_dir() {
44 anyhow::bail!("Path is not a directory: {}", path.display());
45 }
46
47 let git_dir = path.join(".git");
48 if !git_dir.exists() {
49 anyhow::bail!("Not a git repository: {}", path.display());
50 }
51
52 Ok(())
53}
54
55pub fn extract_repo_name_from_url(url: &str) -> Option<String> {
57 let url = url.trim_end_matches(".git");
59
60 if let Some(last_part) = url.split('/').next_back() {
61 if !last_part.is_empty() {
62 return Some(last_part.to_string());
63 }
64 }
65
66 None
67}
68
69pub fn normalize_git_url(url: &str) -> String {
71 if url.starts_with("git@github.com:") {
72 let repo_path = url.strip_prefix("git@github.com:").unwrap_or(url);
74 let repo_path = repo_path.strip_suffix(".git").unwrap_or(repo_path);
75 format!("https://github.com/{repo_path}")
76 } else if url.starts_with("https://github.com/") {
77 url.strip_suffix(".git").unwrap_or(url).to_string()
79 } else {
80 url.to_string()
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_extract_repo_name_from_url() {
91 assert_eq!(
92 extract_repo_name_from_url("https://github.com/user/repo.git"),
93 Some("repo".to_string())
94 );
95
96 assert_eq!(
97 extract_repo_name_from_url("git@github.com:user/repo.git"),
98 Some("repo".to_string())
99 );
100
101 assert_eq!(
102 extract_repo_name_from_url("https://github.com/user/repo"),
103 Some("repo".to_string())
104 );
105
106 assert_eq!(
107 extract_repo_name_from_url("invalid-url"),
108 Some("invalid-url".to_string())
109 );
110 }
111
112 #[test]
113 fn test_normalize_git_url() {
114 assert_eq!(
115 normalize_git_url("git@github.com:user/repo.git"),
116 "https://github.com/user/repo"
117 );
118
119 assert_eq!(
120 normalize_git_url("https://github.com/user/repo.git"),
121 "https://github.com/user/repo"
122 );
123
124 assert_eq!(
125 normalize_git_url("https://github.com/user/repo"),
126 "https://github.com/user/repo"
127 );
128
129 assert_eq!(
130 normalize_git_url("https://gitlab.com/user/repo.git"),
131 "https://gitlab.com/user/repo.git"
132 );
133 }
134}