diff --git a/examples/orgs.rs b/examples/orgs.rs new file mode 100644 index 00000000..d298a7dd --- /dev/null +++ b/examples/orgs.rs @@ -0,0 +1,29 @@ +extern crate env_logger; +extern crate hyper; +extern crate hubcaps; + +use hyper::Client; +use hubcaps::{Credentials, Github, OrganizationRepoListOptions}; +use hubcaps::repositories::OrgRepoType; +use std::env; + +fn main() { + env_logger::init().unwrap(); + match env::var("GITHUB_TOKEN").ok() { + Some(token) => { + let client = Client::new(); + let github = Github::new(format!("hubcaps/{}", env!("CARGO_PKG_VERSION")), + &client, + Credentials::Token(token)); + + let options = OrganizationRepoListOptions::builder().repo_type(OrgRepoType::Forks).build(); + + println!("Forks in the rust-lang organization:"); + + for repo in github.org_repos("rust-lang").list(&options).unwrap() { + println!("{}", repo.name) + } + } + _ => println!("example missing GITHUB_TOKEN"), + } +} diff --git a/src/lib.rs b/src/lib.rs index 06f58d19..fcd83c25 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ use hyper::client::RequestBuilder; use hyper::method::Method; use hyper::header::{Authorization, ContentLength, UserAgent}; use hyper::status::StatusCode; -use repositories::{Repository, Repositories, UserRepositories}; +use repositories::{Repository, Repositories, UserRepositories, OrganizationRepositories}; use std::fmt; use std::io::Read; use url::Url; @@ -179,6 +179,13 @@ impl<'a> Github<'a> { Gists::new(self) } + /// Return a reference to a Github Organization + pub fn org_repos(&self, org: O) -> OrganizationRepositories + where O: Into + { + OrganizationRepositories::new(self, org) + } + fn authenticate(&self, method: Method, uri: &str) -> RequestBuilder { let url = format!("{}{}", self.host, uri); match self.credentials { diff --git a/src/rep.rs b/src/rep.rs index c6053f92..4cb3bba1 100644 --- a/src/rep.rs +++ b/src/rep.rs @@ -3,7 +3,7 @@ use super::{SortDirection, Error, State as StdState}; use super::issues::Sort as IssueSort; use super::repositories::{Sort as RepoSort, Affiliation, Type as RepoType, - Visibility as RepoVisibility}; + Visibility as RepoVisibility, OrgRepoType}; use std::collections::HashMap; use std::hash::Hash; use std::option::Option; diff --git a/src/rep.rs.in b/src/rep.rs.in index d3a42947..0e3457d1 100644 --- a/src/rep.rs.in +++ b/src/rep.rs.in @@ -677,6 +677,46 @@ impl UserRepoListOptionsBuilder { } } +#[derive(Default)] +pub struct OrganizationRepoListOptions { + params: HashMap<&'static str, String> +} + +impl OrganizationRepoListOptions { + pub fn builder() -> OrganizationRepoListOptionsBuilder { + OrganizationRepoListOptionsBuilder::new() + } + + /// serialize options as a string. returns None if no options are defined + pub fn serialize(&self) -> Option { + if self.params.is_empty() { + None + } else { + Some(form_urlencoded::serialize(&self.params)) + } + } +} + +#[derive(Default)] +pub struct OrganizationRepoListOptionsBuilder { + params: HashMap<&'static str, String> +} + +impl OrganizationRepoListOptionsBuilder { + pub fn new() -> OrganizationRepoListOptionsBuilder { + OrganizationRepoListOptionsBuilder { ..Default::default() } + } + + pub fn repo_type(&mut self, tpe: OrgRepoType) -> &mut OrganizationRepoListOptionsBuilder { + self.params.insert("type", tpe.to_string()); + self + } + + pub fn build(&self) -> OrganizationRepoListOptions { + OrganizationRepoListOptions { params: self.params.clone() } + } +} + #[derive(Default)] pub struct RepoListOptions { params: HashMap<&'static str, String> diff --git a/src/repositories.rs b/src/repositories.rs index f755a22e..85a56e13 100644 --- a/src/repositories.rs +++ b/src/repositories.rs @@ -7,7 +7,7 @@ use issues::{IssueRef, Issues}; use labels::Labels; use pulls::PullRequests; use releases::Releases; -use rep::{Repo, RepoListOptions, UserRepoListOptions}; +use rep::{Repo, RepoListOptions, UserRepoListOptions, OrganizationRepoListOptions}; use statuses::Statuses; use std::fmt; @@ -97,6 +97,32 @@ impl fmt::Display for Type { } } +/// Describes types of organization repositories +#[derive(Clone, Debug, PartialEq)] +pub enum OrgRepoType { + All, + Public, + Private, + Forks, + Sources, + Member, +} + +impl fmt::Display for OrgRepoType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, + "{}", + match *self { + OrgRepoType::All => "all", + OrgRepoType::Public => "public", + OrgRepoType::Private => "private", + OrgRepoType::Forks => "forks", + OrgRepoType::Sources => "sources", + OrgRepoType::Member => "member", + }) + } +} + pub struct Repositories<'a> { github: &'a Github<'a>, } @@ -151,6 +177,36 @@ impl<'a> UserRepositories<'a> { } } +/// Provides access to an organization's repositories +pub struct OrganizationRepositories<'a> { + github: &'a Github<'a>, + org: String, +} + +impl<'a> OrganizationRepositories<'a> { + pub fn new(github: &'a Github<'a>, org: O) -> OrganizationRepositories<'a> + where O: Into + { + OrganizationRepositories { + github: github, + org: org.into(), + } + } + + fn path(&self, more: &str) -> String { + format!("/orgs/{}/repos{}", self.org, more) + } + + /// https://developer.github.com/v3/repos/#list-organization-repositories + pub fn list(&self, options: &OrganizationRepoListOptions) -> Result> { + let mut uri = vec![self.path("")]; + if let Some(query) = options.serialize() { + uri.push(query); + } + self.github.get::>(&uri.join("?")) + } +} + pub struct Repository<'a> { github: &'a Github<'a>, owner: String,