use std::convert::TryFrom;
use nonempty::NonEmpty;
use serde::{Deserialize, Serialize};
use radicle_surf::vcs::git::{self, Browser, RefScope, Rev};
use crate::{
branch::{branches, Branch},
error::Error,
oid::Oid,
tag::{tags, Tag},
};
pub enum Category<P, U> {
Local { peer_id: P, user: U },
Remote { peer_id: P, user: U },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", tag = "type")]
pub enum Revision<P> {
#[serde(rename_all = "camelCase")]
Tag {
name: String,
},
#[serde(rename_all = "camelCase")]
Branch {
name: String,
peer_id: Option<P>,
},
#[serde(rename_all = "camelCase")]
Sha {
sha: Oid,
},
}
impl<P> TryFrom<Revision<P>> for Rev
where
P: ToString,
{
type Error = Error;
fn try_from(other: Revision<P>) -> Result<Self, Self::Error> {
match other {
Revision::Tag { name } => Ok(git::TagName::new(&name).into()),
Revision::Branch { name, peer_id } => Ok(match peer_id {
Some(peer) => {
git::Branch::remote(&format!("heads/{}", name), &peer.to_string()).into()
},
None => git::Branch::local(&name).into(),
}),
Revision::Sha { sha } => {
let oid: git2::Oid = sha.into();
Ok(oid.into())
},
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Revisions<P, U> {
pub peer_id: P,
pub user: U,
pub branches: NonEmpty<Branch>,
pub tags: Vec<Tag>,
}
pub fn remote<P, U>(
browser: &Browser,
peer_id: P,
user: U,
) -> Result<Option<Revisions<P, U>>, Error>
where
P: Clone + ToString,
{
let remote_branches = branches(browser, Some(peer_id.clone()).into())?;
Ok(
NonEmpty::from_vec(remote_branches).map(|branches| Revisions {
peer_id,
user,
branches,
tags: vec![],
}),
)
}
pub fn local<P, U>(browser: &Browser, peer_id: P, user: U) -> Result<Option<Revisions<P, U>>, Error>
where
P: Clone + ToString,
{
let local_branches = branches(browser, RefScope::Local)?;
let tags = tags(browser)?;
Ok(
NonEmpty::from_vec(local_branches).map(|branches| Revisions {
peer_id,
user,
branches,
tags,
}),
)
}
pub fn revisions<P, U>(
browser: &Browser,
peer: Category<P, U>,
) -> Result<Option<Revisions<P, U>>, Error>
where
P: Clone + ToString,
{
match peer {
Category::Local { peer_id, user } => local(browser, peer_id, user),
Category::Remote { peer_id, user } => remote(browser, peer_id, user),
}
}