Skip to content
This repository has been archived by the owner on Aug 1, 2022. It is now read-only.

Commit

Permalink
feat(proxy): integrate repository selector (#636)
Browse files Browse the repository at this point in the history
* Use NonEmpty instead of Vec
* Fake a remote peer tracking a project
* Update Cargo.lock
* Remove local_branches and use filter directly
* Add From impl for User to Identity
* Move Revision to peer.rs

Moving Revision to peer.rs and removing the Remote type we can clean up
the handler call to revisions. We also utilise the From<User> impl for
Identity to make the conversion cleaner.

* Improve docs

Co-authored-by: FintanH <fintan.halpenny@gmail.com>
  • Loading branch information
rudolfs and FintanH committed Jul 15, 2020
1 parent 1e8ccc5 commit ea28bb0
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 177 deletions.
8 changes: 4 additions & 4 deletions proxy/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions proxy/Cargo.toml
Expand Up @@ -19,7 +19,7 @@ hex = "0.4"
kv = { version = "0.20", features = [ "bincode-value", "json-value" ] }
lazy_static = "1.4"
log = "0.4"
nonempty = "0.2"
nonempty = "0.5"
percent-encoding = "2.1"
parity-scale-codec = "1.3.1"
pico-args = "0.3"
Expand All @@ -39,7 +39,7 @@ warp = { git = "https://github.com/radicle-dev/warp", branch = "openapi", featur

[dependencies.librad]
git = "https://github.com/radicle-dev/radicle-link.git"
rev = "f97ed83b9d1d4303407de038206c7da852cfe22e"
rev = "269a7ededafd7373ebfb03210770d0b3778002fb"

[dependencies.radicle-keystore]
git = "https://github.com/radicle-dev/radicle-keystore.git"
Expand All @@ -50,7 +50,7 @@ git = "https://github.com/radicle-dev/radicle-registry.git"
rev = "e98f433712646bf29815f287d228154282c7e819"

[dependencies.radicle-surf]
version = "0.4.0"
version = "0.4.1"
features = ["serialize"]

[dev-dependencies]
Expand Down
3 changes: 2 additions & 1 deletion proxy/src/coco.rs
Expand Up @@ -10,7 +10,8 @@ pub use radicle_surf::vcs::git::Stats;
mod peer;
pub use peer::{
create_peer_api, default_owner, get_project, get_user, init_owner, init_project, init_user,
list_projects, list_users, set_default_owner, verify_user, with_browser, PeerApi, User,
list_projects, list_users, revisions, set_default_owner, verify_user, with_browser, PeerApi,
User, UserRevisions,
};

/// Module that captures all types and functions for source code.
Expand Down
79 changes: 78 additions & 1 deletion proxy/src/coco/peer.rs
@@ -1,3 +1,5 @@
use nonempty::NonEmpty;
use serde::Serialize;
use std::convert::TryFrom;
use std::net::SocketAddr;

Expand All @@ -8,14 +10,28 @@ use librad::meta::user;
use librad::net::discovery;
pub use librad::net::peer::{PeerApi, PeerConfig};
use librad::uri::RadUrn;
use radicle_surf::vcs::git::{self, git2};
use radicle_surf::vcs::git::{self, git2, BranchType};

use super::source;
use crate::error;
use crate::identity;
use crate::project::Project;

/// Export a verified [`user::User`] type.
pub type User = user::User<entity::Verified>;

/// Bundled response to retrieve both branches and tags for a user repo.
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UserRevisions {
/// Owner of the repo.
pub(crate) identity: identity::Identity,
/// List of [`source::Branch`].
pub(crate) branches: Vec<source::Branch>,
/// List of [`source::Tag`].
pub(crate) tags: Vec<source::Tag>,
}

/// Create a new `PeerApi` given a `PeerConfig`.
///
/// # Errors
Expand Down Expand Up @@ -107,6 +123,67 @@ pub fn list_projects(peer: &PeerApi) -> Result<Vec<Project>, error::Error> {
.collect()
}

/// Get all [`UserRevisions`] for a given project.
///
/// # Parameters
///
/// * `peer` - the peer API we're interacting through
/// * `owner` - the owner of this peer, i.e. the current user
/// * `project_urn` - the [`RadUrn`] pointing to the project we're interested in
///
/// # Errors
///
/// * [`error::Error::LibradLock`]
/// * [`error::Error::Git`]
pub fn revisions(
peer: &PeerApi,
owner: &User,
project_urn: &RadUrn,
) -> Result<NonEmpty<UserRevisions>, error::Error> {
let project = get_project(peer, project_urn)?;
let storage = peer.storage().reopen()?;
let repo = storage.open_repo(project.urn())?;
let mut user_revisions = vec![];

let (local_branches, local_tags) = with_browser(peer, &project.urn(), |browser| {
Ok((
source::branches(browser, Some(BranchType::Local))?,
source::tags(browser)?,
))
})?;

if !local_branches.is_empty() {
user_revisions.push(UserRevisions {
identity: (peer.peer_id().clone(), owner.clone()).into(),
branches: local_branches,
tags: local_tags,
})
}

for peer_id in repo.tracked()? {
let remote_branches = with_browser(peer, &project.urn(), |browser| {
source::branches(
browser,
Some(BranchType::Remote {
name: Some(format!("{}/heads", peer_id)),
}),
)
})?;

let user = repo.get_rad_self_of(peer_id.clone())?;

user_revisions.push(UserRevisions {
identity: (peer_id, user).into(),
branches: remote_branches,
// TODO(rudolfs): implement remote peer tags once we decide how
// https://radicle.community/t/git-tags/214
tags: vec![],
});
}

NonEmpty::from_vec(user_revisions).ok_or(error::Error::EmptyUserRevisions)
}

/// Returns the list of [`user::User`]s known for your peer.
///
/// # Errors
Expand Down
16 changes: 10 additions & 6 deletions proxy/src/coco/source.rs
Expand Up @@ -6,7 +6,7 @@ use std::str::FromStr;
use librad::peer;
use radicle_surf::{
diff, file_system,
vcs::git::{self, git2, Browser, Rev},
vcs::git::{self, git2, BranchType, Browser, Rev},
};

use syntect::easy::HighlightLines;
Expand All @@ -26,7 +26,7 @@ lazy_static::lazy_static! {

/// Branch name representation.
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
pub struct Branch(pub(super) String);
pub struct Branch(pub(crate) String);

impl fmt::Display for Branch {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -38,7 +38,7 @@ impl fmt::Display for Branch {
///
/// We still need full tag support.
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Tag(pub(super) String);
pub struct Tag(pub(crate) String);

impl fmt::Display for Tag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down Expand Up @@ -322,9 +322,12 @@ fn blob_content(path: &str, content: &[u8], theme: Option<&Theme>) -> BlobConten
/// # Errors
///
/// Will return [`error::Error`] if the project doesn't exist or the surf interaction fails.
pub fn branches<'repo>(browser: &Browser<'repo>) -> Result<Vec<Branch>, error::Error> {
pub fn branches<'repo>(
browser: &Browser<'repo>,
branch_type: Option<BranchType>,
) -> Result<Vec<Branch>, error::Error> {
let mut branches = browser
.list_branches(None)?
.list_branches(branch_type)?
.into_iter()
.map(|b| Branch(b.name.name().to_string()))
.collect::<Vec<Branch>>();
Expand All @@ -350,9 +353,10 @@ pub struct LocalState {
/// Will return [`error::Error`] if the repository doesn't exist.
pub fn local_state(repo_path: &str) -> Result<LocalState, error::Error> {
let repo = git::Repository::new(repo_path)?;
// TODO(finto): This should be the default branch of the project, possibly.
let browser = Browser::new(&repo, git::Branch::local("master"))?;
let mut branches = browser
.list_branches(Some(git::BranchType::Local))?
.list_branches(Some(BranchType::Local))?
.into_iter()
.map(|b| Branch(b.name.name().to_string()))
.collect::<Vec<Branch>>();
Expand Down
7 changes: 7 additions & 0 deletions proxy/src/error.rs
Expand Up @@ -163,6 +163,13 @@ pub enum Error {
/// Overflow while incrementing confirmed transaction.
#[error("while calculating the number of confirmed transactions, we encountered an overflow")]
TransactionConfirmationOverflow,

/// We expect at least one [`coco::UserRevisions`] when looking at a project, however the
/// computation found none.
#[error(
"while trying to get user revisions we could not find any, there should be at least one"
)]
EmptyUserRevisions,
}

impl From<registry::DispatchError> for Error {
Expand Down
2 changes: 1 addition & 1 deletion proxy/src/http/identity.rs
Expand Up @@ -118,7 +118,7 @@ mod handler {

let keystore = keystore.read().await;
let key = keystore.get_librad_key().map_err(error::Error::from)?;
let id = identity::create(&*peer.lock().await, key, input.handle.parse()?)?;
let id = identity::create(&*peer.lock().await, key, &input.handle)?;

session::set_identity(&store, id.clone())?;

Expand Down
2 changes: 1 addition & 1 deletion proxy/src/http/project.rs
Expand Up @@ -432,7 +432,7 @@ mod test {
let path = dir.path().to_str().unwrap();

let handle = "cloudhead";
let id = identity::create(&*peer.lock().await, key, handle.parse().unwrap())?;
let id = identity::create(&*peer.lock().await, key, handle)?;

session::set_identity(&store, id.clone())?;

Expand Down

0 comments on commit ea28bb0

Please sign in to comment.