gitea-release/gitea/src/lib.rs

242 lines
6.0 KiB
Rust

use reqwest::header;
use serde::{Deserialize, Serialize};
use std::result::Result as StdResult;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("error from reqwest: {0:#?}")]
Reqwest(#[from] reqwest::Error),
#[error("bad API token: {0:#?}")]
BadAPIToken(#[from] reqwest::header::InvalidHeaderValue),
#[error("error parsing/serializing json: {0:#?}")]
Json(#[from] serde_json::Error),
#[error("tag not found: {0}")]
TagNotFound(String),
}
pub type Result<T> = StdResult<T, Error>;
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Author {
pub id: i64,
pub login: String,
pub full_name: String,
pub email: String,
pub avatar_url: String,
pub language: String,
pub is_admin: bool,
pub last_login: String,
pub created: String,
pub username: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Release {
pub id: i64,
pub tag_name: String,
pub target_commitish: String,
pub name: String,
pub body: String,
pub url: String,
pub tarball_url: String,
pub zipball_url: String,
pub draft: bool,
pub prerelease: bool,
pub created_at: String,
pub published_at: String,
pub author: Author,
pub assets: Vec<Attachment>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CreateRelease {
pub body: String,
pub draft: bool,
pub name: String,
pub prerelease: bool,
pub tag_name: String,
pub target_commitish: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Attachment {
pub id: i64,
pub name: String,
pub size: i64,
pub download_count: i64,
pub created_at: String,
pub uuid: String,
pub browser_download_url: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Repo {
pub allow_merge_commits: bool,
pub allow_rebase: bool,
pub allow_rebase_explicit: bool,
pub allow_squash_merge: bool,
pub archived: bool,
pub avatar_url: String,
pub clone_url: String,
pub created_at: String,
pub default_branch: String,
pub description: String,
pub empty: bool,
pub fork: bool,
pub forks_count: i64,
pub full_name: String,
pub has_issues: bool,
pub has_pull_requests: bool,
pub has_wiki: bool,
pub html_url: String,
pub id: i64,
pub ignore_whitespace_conflicts: bool,
pub mirror: bool,
pub name: String,
pub open_issues_count: i64,
pub open_pr_counter: i64,
pub original_url: String,
pub owner: User,
pub permissions: Permissions,
pub private: bool,
pub release_counter: i64,
pub size: i64,
pub ssh_url: String,
pub stars_count: i64,
pub template: bool,
pub updated_at: String,
pub watchers_count: i64,
pub website: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct User {
pub avatar_url: String,
pub created: String,
pub email: String,
pub full_name: String,
pub id: i64,
pub is_admin: bool,
pub language: String,
pub last_login: String,
pub login: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Permissions {
pub admin: bool,
pub pull: bool,
pub push: bool,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Version {
pub version: String,
}
pub struct Client {
cli: reqwest::Client,
base_url: String,
}
impl Client {
pub fn new(base_url: String, token: String, user_agent: String) -> Result<Self> {
let mut headers = header::HeaderMap::new();
let auth = format!("token {}", token);
let auth = auth.as_str();
headers.insert(header::AUTHORIZATION, header::HeaderValue::from_str(auth)?);
let cli = reqwest::Client::builder()
.user_agent(user_agent)
.default_headers(headers)
.build()?;
Ok(Self {
cli: cli,
base_url: base_url,
})
}
pub async fn version(&self) -> Result<Version> {
Ok(self
.cli
.get(&format!("{}/api/v1/version", self.base_url))
.send()
.await?
.error_for_status()?
.json()
.await?)
}
pub async fn get_release_by_tag(
&self,
owner: String,
repo: String,
tag: String,
) -> Result<Release> {
let releases: Vec<Release> = self.get_releases(owner, repo).await?;
let mut release: Option<Release> = None;
for rls in releases {
if *tag == rls.tag_name {
release = Some(rls);
}
}
match release {
None => Err(Error::TagNotFound(tag)),
Some(release) => Ok(release),
}
}
pub async fn get_repo(&self, owner: String, repo: String) -> Result<Repo> {
Ok(self
.cli
.get(&format!(
"{}/api/v1/repos/{}/{}",
self.base_url, owner, repo
))
.send()
.await?
.error_for_status()?
.json()
.await?)
}
pub async fn get_releases(&self, owner: String, repo: String) -> Result<Vec<Release>> {
Ok(self
.cli
.get(&format!(
"{}/api/v1/repos/{}/{}/releases",
self.base_url, owner, repo
))
.send()
.await?
.error_for_status()?
.json()
.await?)
}
pub async fn create_release(
&self,
owner: String,
repo: String,
cr: CreateRelease,
) -> Result<Release> {
Ok(self
.cli
.post(&format!(
"{}/api/v1/repos/{}/{}/releases",
self.base_url, owner, repo
))
.json(&cr)
.send()
.await?
.error_for_status()?
.json()
.await?)
}
}