1pub mod cache;
2pub mod errors;
3
4use crate::errors::Error;
5use codecov::{
6 author::Author, branch_detail::BranchDetailAPIResponse, branches::BranchesAPIResponse,
7 commits::CommitsAPIResponse, owner::Owner, repos::Repo, Client as CodecovClient,
8};
9
10pub struct Client {
14 codecov_client: CodecovClient,
15 cache_client: cache::Client,
16}
17
18impl Client {
24 pub fn new_from_env() -> Result<Client, Error> {
25 let cache_dir = Client::resolve_cache_dir_root();
26 Ok(Client {
27 codecov_client: CodecovClient::new_from_env()?,
28 cache_client: cache::Client::new(cache_dir, "data.json".to_string()),
29 })
30 }
31
32 fn resolve_cache_dir_root() -> std::path::PathBuf {
33 match std::env::var("CODECOV_CACHE_DIR") {
34 Ok(path) => std::path::PathBuf::from(path),
35 Err(_) => Client::default_cache_dir_root(),
36 }
37 }
38
39 fn default_cache_dir_root() -> std::path::PathBuf {
40 let Some(mut path) = dirs::cache_dir() else {
41 panic!("Unsupported platform");
42 };
43 path.push("rust-codecov-cache");
44 path
45 }
46
47 pub fn new(token: String, cache_dir: std::path::PathBuf) -> Client {
48 Client {
49 codecov_client: CodecovClient::new(token),
50 cache_client: cache::Client::new(cache_dir, "data.json".to_string()),
51 }
52 }
53
54 pub fn get_all_repos(&self, owner: &Owner) -> Result<Vec<Repo>, Error> {
60 Ok(self.codecov_client.get_all_repos(owner)?)
61 }
62
63 pub fn get_commits(&self, author: &Author) -> Result<CommitsAPIResponse, Error> {
68 Ok(self.codecov_client.get_commits(author)?)
69 }
70
71 pub fn get_branches(&self, author: &Author) -> Result<BranchesAPIResponse, Error> {
76 Ok(self.codecov_client.get_branches(author)?)
77 }
78
79 pub fn get_branch_detail(
84 &self,
85 author: &Author,
86 branch_name: &str,
87 ) -> Result<BranchDetailAPIResponse, Error> {
88 Ok(self.codecov_client.get_branch_detail(author, branch_name)?)
89 }
90
91 pub fn get_branch_detail_with_commit_id(
96 &self,
97 author: &Author,
98 branch_name: &str,
99 commit_id: &str,
100 ) -> Result<BranchDetailAPIResponse, Error> {
101 let cache_key = &[
102 &author.service,
103 &author.username,
104 &author.name,
105 branch_name,
106 commit_id,
107 ];
108 if let Ok(data) = self.cache_client.load(cache_key) {
110 if let Ok(value) = serde_json::from_slice(&data) {
111 if let Ok(branch_detail) = serde_json::from_value(value) {
112 return Ok(branch_detail);
113 }
114 }
115 }
116 let retrieved = self.codecov_client.get_branch_detail(author, branch_name)?;
118 if let BranchDetailAPIResponse::Success(detail) = &retrieved {
120 if let Ok(data) = serde_json::to_vec(&detail) {
121 let cache_key = &[
122 &author.service,
123 &author.username,
124 &author.name,
125 branch_name,
126 &detail.head_commit.commitid,
127 ];
128 if let Err(err) = self.cache_client.save(cache_key, &data) {
129 println!("Failed to save cache: {:?}", err);
130 }
131 }
132 return Ok(retrieved);
133 }
134 Ok(retrieved)
135 }
136}
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn test_fetch_and_cache() {
143 let client = Client::new_from_env().unwrap(); let owner = Owner::new("github", "kitsuyui");
145 let author = owner.new_author("rust-codecov");
146
147 let detail = client.get_branch_detail(&author, "main").unwrap();
148
149 let BranchDetailAPIResponse::Success(detail) = detail else {
150 panic!("Unexpected response");
151 };
152 let commit_id = detail.head_commit.commitid.to_string();
153
154 client
155 .get_branch_detail_with_commit_id(&author, "main", &commit_id)
156 .unwrap();
157 assert!(client.cache_client.has(&[
158 "github",
159 "kitsuyui",
160 "rust-codecov",
161 "main",
162 &commit_id
163 ]));
164
165 let mut cache_dir = dirs::cache_dir().unwrap();
167 cache_dir.extend(&[
168 "rust-codecov-cache",
169 "github",
170 "kitsuyui",
171 "rust-codecov",
172 "main",
173 &commit_id,
174 ]);
175 assert!(cache_dir.exists());
176 }
177}