opensession_local_db/
git.rs1use std::process::Command;
2
3#[derive(Debug, Clone, Default)]
5pub struct GitContext {
6 pub remote: Option<String>,
7 pub branch: Option<String>,
8 pub commit: Option<String>,
9 pub repo_name: Option<String>,
10}
11
12pub fn extract_git_context(cwd: &str) -> GitContext {
15 let toplevel = git_cmd(cwd, &["rev-parse", "--show-toplevel"]);
17 if toplevel.is_none() {
18 return GitContext::default();
19 }
20
21 let remote = git_cmd(cwd, &["remote", "get-url", "origin"]);
22 let branch = git_cmd(cwd, &["rev-parse", "--abbrev-ref", "HEAD"]);
23 let commit = git_cmd(cwd, &["rev-parse", "HEAD"]);
24 let repo_name = remote
25 .as_deref()
26 .and_then(normalize_repo_name)
27 .map(String::from);
28
29 GitContext {
30 remote,
31 branch,
32 commit,
33 repo_name,
34 }
35}
36
37pub fn normalize_repo_name(remote_url: &str) -> Option<&str> {
44 let s = remote_url.trim();
45
46 if let Some(rest) = s.strip_prefix("git@") {
48 let path = rest.split_once(':')?.1;
49 let path = path.strip_suffix(".git").unwrap_or(path);
50 return if path.contains('/') { Some(path) } else { None };
51 }
52
53 if s.starts_with("https://") || s.starts_with("http://") || s.starts_with("ssh://") {
55 let without_scheme = s.split("://").nth(1)?;
57 let path_start = without_scheme.find('/')? + 1;
59 let path = &without_scheme[path_start..];
60 let path = path.strip_suffix(".git").unwrap_or(path);
61 return if path.contains('/') { Some(path) } else { None };
62 }
63
64 None
65}
66
67fn git_cmd(cwd: &str, args: &[&str]) -> Option<String> {
68 let output = Command::new("git")
69 .arg("-C")
70 .arg(cwd)
71 .args(args)
72 .output()
73 .ok()?;
74
75 if !output.status.success() {
76 return None;
77 }
78 let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
79 if stdout.is_empty() {
80 None
81 } else {
82 Some(stdout)
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_normalize_https() {
92 assert_eq!(
93 normalize_repo_name("https://github.com/hwisu/opensession.git"),
94 Some("hwisu/opensession")
95 );
96 }
97
98 #[test]
99 fn test_normalize_ssh() {
100 assert_eq!(
101 normalize_repo_name("git@github.com:hwisu/opensession.git"),
102 Some("hwisu/opensession")
103 );
104 }
105
106 #[test]
107 fn test_normalize_no_suffix() {
108 assert_eq!(
109 normalize_repo_name("https://github.com/foo/bar"),
110 Some("foo/bar")
111 );
112 }
113
114 #[test]
115 fn test_normalize_invalid() {
116 assert_eq!(normalize_repo_name("not-a-url"), None);
117 }
118}