1use eyre::Result;
2use std::path::PathBuf;
3
4#[derive(Debug, Clone)]
5pub struct Repository {
6 pub owner: String,
7 pub name: String,
8 pub hostname: String,
9}
10
11impl std::fmt::Display for Repository {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 write!(f, "{}/{}/{}", self.hostname, self.owner, self.name)
14 }
15}
16
17pub struct Git {
18 pub directory: PathBuf,
19}
20
21const GITHUB_HOSTNAME: &str = "github.com";
22
23fn parse_repository(url: &str) -> Result<Repository> {
25 let mut parts = url.trim().split(':');
26 let host = parts.next();
27 let mut parts = parts.next().unwrap().split('/');
28 let owner = parts.next().unwrap().to_string();
29 let name = parts
30 .next()
31 .unwrap()
32 .strip_suffix(".git")
33 .unwrap()
34 .to_string();
35 let hostname = host.unwrap().split('@').nth(1).unwrap().to_string();
36 Ok(Repository {
37 owner,
38 name,
39 hostname,
40 })
41}
42
43pub fn parse_repository_from_github(s: &str) -> Result<Repository> {
45 let mut parts = s.trim().split('/');
46 let owner = parts.next().unwrap().to_string();
47 let name = parts.next().unwrap().to_string();
48 let hostname = GITHUB_HOSTNAME.to_string();
49
50 Ok(Repository {
51 owner,
52 name,
53 hostname,
54 })
55}
56
57impl Git {
58 pub fn new(directory: PathBuf) -> Self {
59 Self { directory }
60 }
61
62 pub fn get_branch(&self) -> Result<String> {
63 let output = std::process::Command::new("git")
64 .arg("rev-parse")
65 .arg("--abbrev-ref")
66 .arg("HEAD")
67 .current_dir(&self.directory)
68 .output()?;
69 let branch = String::from_utf8(output.stdout)?;
70 Ok(branch.trim().to_string())
71 }
72
73 pub fn get_remote(&self) -> Result<Repository> {
74 let output = std::process::Command::new("git")
75 .arg("remote")
76 .arg("get-url")
77 .arg("origin")
78 .current_dir(&self.directory)
79 .output()?;
80 let url = String::from_utf8(output.stdout)?;
81 let repository = parse_repository(&url)?;
82 Ok(repository)
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use pretty_assertions::assert_eq;
90
91 #[test]
92 fn test_parse_repository() {
93 let url = "git@github.com:raine/tgreddit.git";
94 let repository = parse_repository(url).unwrap();
95 assert_eq!(repository.owner, "raine");
96 assert_eq!(repository.name, "tgreddit");
97 assert_eq!(repository.hostname, "github.com");
98 }
99}