1use serde::Deserialize;
5
6use crate::{Future, Github};
8
9pub struct Git {
11 github: Github,
12 owner: String,
13 repo: String,
14}
15
16impl Git {
17 #[doc(hidden)]
18 pub fn new<O, R>(github: Github, owner: O, repo: R) -> Self
19 where
20 O: Into<String>,
21 R: Into<String>,
22 {
23 Git {
24 github,
25 owner: owner.into(),
26 repo: repo.into(),
27 }
28 }
29
30 fn path(&self, more: &str) -> String {
31 format!("/repos/{}/{}/git{}", self.owner, self.repo, more)
32 }
33
34 pub fn tree<S>(&self, sha: S, recursive: bool) -> Future<TreeData>
38 where
39 S: Into<String>,
40 {
41 self.github.get(&self.path(&format!(
42 "/trees/{}?recursive={}",
43 sha.into(),
44 if recursive { "1" } else { "0" }
45 )))
46 }
47
48 pub fn blob<S>(&self, sha: S) -> Future<Blob>
51 where
52 S: Into<String>,
53 {
54 self.github
55 .get(&self.path(&format!("/blobs/{}", sha.into())))
56 }
57
58 pub fn reference<S>(&self, reference: S) -> Future<GetReferenceResponse>
62 where
63 S: Into<String>,
64 {
65 self.github
66 .get(&self.path(&format!("/refs/{}", reference.into())))
67 }
68
69 pub fn delete_reference<S>(&self, reference: S) -> Future<()>
74 where
75 S: Into<String>,
76 {
77 self.github
78 .delete(&self.path(&format!("/refs/{}", reference.into())))
79 }
80}
81
82#[derive(Debug, Deserialize)]
85pub struct TreeData {
86 pub sha: String,
87 pub url: String,
88 pub tree: Vec<GitFile>,
89 pub truncated: bool,
90}
91
92#[derive(Debug, Deserialize)]
93pub struct GitFile {
94 pub path: String,
95 pub mode: String,
96 #[serde(rename = "type")]
98 pub content_type: String,
99 pub size: Option<usize>,
101 pub sha: String,
102 pub url: Option<String>,
104}
105
106#[derive(Debug, Deserialize)]
107pub struct Blob {
108 pub content: String,
109 pub encoding: String,
110 pub url: String,
111 pub sha: String,
112 pub size: Option<usize>,
114}
115
116#[derive(Debug, Deserialize, PartialEq)]
117#[serde(untagged)]
118pub enum GetReferenceResponse {
120 Exact(Reference),
122 StartWith(Vec<Reference>),
127}
128
129#[derive(Debug, Deserialize, PartialEq)]
130pub struct Reference {
131 #[serde(rename = "ref")]
132 pub reference: String,
133 pub url: String,
134 pub object: Object,
135}
136
137#[derive(Debug, Deserialize, PartialEq)]
138pub struct Object {
139 #[serde(rename = "type")]
140 pub object_type: String,
141 pub sha: String,
142 pub url: String,
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use serde::Deserialize;
149 use std::fmt::Debug;
150
151 fn test_deserializing<'de, T>(payload: &'static str, expected: T)
152 where
153 T: Debug + PartialEq + Deserialize<'de>,
154 {
155 let incoming: T = serde_json::from_str(payload).unwrap();
156 assert_eq!(incoming, expected)
157 }
158
159 #[test]
160 fn deserialize_get_ref_exact() {
161 let payload = r#"{
162 "ref": "refs/heads/featureA",
163 "url": "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/featureA",
164 "object": {
165 "type": "commit",
166 "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
167 "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
168 }
169}"#;
170 let expected = GetReferenceResponse::Exact(Reference {
171 reference: "refs/heads/featureA".to_string(),
172 url: "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/featureA".to_string(),
173 object: Object {
174 object_type: "commit".to_string(),
175 sha: "aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
176 url: "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
177 },
178 });
179 test_deserializing(payload, expected)
180 }
181
182 #[test]
183 fn deserialize_get_ref_starts_with() {
184 let payload = r#"[
185 {
186 "ref": "refs/heads/feature-a",
187 "url": "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-a",
188 "object": {
189 "type": "commit",
190 "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
191 "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
192 }
193 },
194 {
195 "ref": "refs/heads/feature-b",
196 "url": "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-b",
197 "object": {
198 "type": "commit",
199 "sha": "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac",
200 "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac"
201 }
202 }
203]"#;
204 let expected = GetReferenceResponse::StartWith(vec![
205 Reference {
206 reference: "refs/heads/feature-a".to_string(),
207 url: "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-a".to_string(),
208 object: Object {
209 object_type: "commit".to_string(),
210 sha: "aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
211 url: "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
212 },
213 },
214 Reference {
215 reference: "refs/heads/feature-b".to_string(),
216 url: "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-b".to_string(),
217 object: Object {
218 object_type: "commit".to_string(),
219 sha: "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac".to_string(),
220 url: "https://api.github.com/repos/octocat/Hello-World/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac".to_string(),
221 },
222 },
223 ]);
224 test_deserializing(payload, expected)
225 }
226}