use serde::Deserialize;
use crate::{Future, Github};
pub struct Git {
github: Github,
owner: String,
repo: String,
}
impl Git {
#[doc(hidden)]
pub fn new<O, R>(github: Github, owner: O, repo: R) -> Self
where
O: Into<String>,
R: Into<String>,
{
Git {
github,
owner: owner.into(),
repo: repo.into(),
}
}
fn path(&self, more: &str) -> String {
format!("/repos/{}/{}/git{}", self.owner, self.repo, more)
}
pub fn tree<S>(&self, sha: S, recursive: bool) -> Future<TreeData>
where
S: Into<String>,
{
self.github.get(&self.path(&format!(
"/trees/{}?recursive={}",
sha.into(),
if recursive { "1" } else { "0" }
)))
}
pub fn blob<S>(&self, sha: S) -> Future<Blob>
where
S: Into<String>,
{
self.github
.get(&self.path(&format!("/blobs/{}", sha.into())))
}
pub fn reference<S>(&self, reference: S) -> Future<GetReferenceResponse>
where
S: Into<String>,
{
self.github
.get(&self.path(&format!("/refs/{}", reference.into())))
}
pub fn delete_reference<S>(&self, reference: S) -> Future<()>
where
S: Into<String>,
{
self.github
.delete(&self.path(&format!("/refs/{}", reference.into())))
}
}
#[derive(Debug, Deserialize)]
pub struct TreeData {
pub sha: String,
pub url: String,
pub tree: Vec<GitFile>,
pub truncated: bool,
}
#[derive(Debug, Deserialize)]
pub struct GitFile {
pub path: String,
pub mode: String,
#[serde(rename = "type")]
pub content_type: String,
pub size: Option<usize>,
pub sha: String,
pub url: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct Blob {
pub content: String,
pub encoding: String,
pub url: String,
pub sha: String,
pub size: Option<usize>,
}
#[derive(Debug, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum GetReferenceResponse {
Exact(Reference),
StartWith(Vec<Reference>),
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Reference {
#[serde(rename = "ref")]
pub reference: String,
pub url: String,
pub object: Object,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Object {
#[serde(rename = "type")]
pub object_type: String,
pub sha: String,
pub url: String,
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
use std::fmt::Debug;
fn test_deserializing<'de, T>(payload: &'static str, expected: T)
where
T: Debug + PartialEq + Deserialize<'de>,
{
let incoming: T = serde_json::from_str(payload).unwrap();
assert_eq!(incoming, expected)
}
#[test]
fn deserialize_get_ref_exact() {
let payload = r#"{
"ref": "refs/heads/featureA",
"url": "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/featureA",
"object": {
"type": "commit",
"sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
"url": "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
}
}"#;
let expected = GetReferenceResponse::Exact(Reference {
reference: "refs/heads/featureA".to_string(),
url: "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/featureA".to_string(),
object: Object {
object_type: "commit".to_string(),
sha: "aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
url: "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
},
});
test_deserializing(payload, expected)
}
#[test]
fn deserialize_get_ref_starts_with() {
let payload = r#"[
{
"ref": "refs/heads/feature-a",
"url": "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-a",
"object": {
"type": "commit",
"sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
"url": "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
}
},
{
"ref": "refs/heads/feature-b",
"url": "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-b",
"object": {
"type": "commit",
"sha": "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac",
"url": "https://api.github.com/repos/octocat/Hello-World/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac"
}
}
]"#;
let expected = GetReferenceResponse::StartWith(vec![
Reference {
reference: "refs/heads/feature-a".to_string(),
url: "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-a".to_string(),
object: Object {
object_type: "commit".to_string(),
sha: "aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
url: "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd".to_string(),
},
},
Reference {
reference: "refs/heads/feature-b".to_string(),
url: "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/feature-b".to_string(),
object: Object {
object_type: "commit".to_string(),
sha: "612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac".to_string(),
url: "https://api.github.com/repos/octocat/Hello-World/git/commits/612077ae6dffb4d2fbd8ce0cccaa58893b07b5ac".to_string(),
},
},
]);
test_deserializing(payload, expected)
}
}