Skip to content

Commit

Permalink
repos/releases improvements (#666)
Browse files Browse the repository at this point in the history
  • Loading branch information
loispostula authored Jul 26, 2024
1 parent 4162be4 commit 66b90cb
Show file tree
Hide file tree
Showing 14 changed files with 1,007 additions and 34 deletions.
7 changes: 7 additions & 0 deletions src/api/repos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod forks;
mod generate;
mod merges;
mod pulls;
pub mod release_assets;
pub mod releases;
mod secrets;
mod stargazers;
Expand All @@ -37,6 +38,7 @@ pub use file::{DeleteFileBuilder, GetContentBuilder, UpdateFileBuilder};
pub use generate::GenerateRepositoryBuilder;
pub use merges::MergeBranchBuilder;
pub use pulls::ListPullsBuilder;
pub use release_assets::ReleaseAssetsHandler;
pub use releases::ReleasesHandler;
pub use secrets::RepoSecretsHandler;
pub use stargazers::ListStarGazersBuilder;
Expand Down Expand Up @@ -520,6 +522,11 @@ impl<'octo> RepoHandler<'octo> {
self.crab.get(route, None::<&()>).await
}

/// Creates a `ReleaseAssetsHandler` for the specified repository.
pub fn release_assets(&self) -> release_assets::ReleaseAssetsHandler<'_, '_> {
release_assets::ReleaseAssetsHandler::new(self)
}

/// Creates a `ReleasesHandler` for the specified repository.
pub fn releases(&self) -> releases::ReleasesHandler<'_, '_> {
releases::ReleasesHandler::new(self)
Expand Down
192 changes: 192 additions & 0 deletions src/api/repos/release_assets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
use super::*;

/// Handler for GitHub's releases API.
///
/// Created with [`RepoHandler::release_assets`].
pub struct ReleaseAssetsHandler<'octo, 'r> {
parent: &'r RepoHandler<'octo>,
}

impl<'octo, 'r> ReleaseAssetsHandler<'octo, 'r> {
pub(crate) fn new(parent: &'r RepoHandler<'octo>) -> Self {
Self { parent }
}
/// Gets the release asset using its id.
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// let release = octocrab::instance()
/// .repos("owner", "repo")
/// .release_assets()
/// .get(3)
/// .await?;
/// # Ok(())
/// # }
/// ```
pub async fn get(&self, id: u64) -> Result<models::repos::Asset> {
let route = format!(
"/repos/{owner}/{repo}/releases/assets/{id}",
owner = self.parent.owner,
repo = self.parent.repo,
id = id,
);

self.parent.crab.get(route, None::<&()>).await
}
/// Creates a new [`UpdateReleaseAssetBuilder`] with `asset_id`.
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// # let octocrab = octocrab::Octocrab::default();
/// let release = octocrab.repos("owner", "repo")
/// .release_assets()
/// .update(1)
/// // Optional Parameters
/// .name("asset_1.tar.gz")
/// .label("Asset 1")
/// .state(octocrab::params::repos::release_assets::State::Uploaded)
/// // Send the request
/// .send()
/// .await?;
/// # Ok(())
/// # }
/// ```
pub fn update(&self, asset_id: u64) -> UpdateReleaseAssetBuilder<'_, '_, '_, '_, '_> {
UpdateReleaseAssetBuilder::new(self, asset_id)
}

/// Delete a release asset using its id.
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// let release = octocrab::instance()
/// .repos("owner", "repo")
/// .release_assets()
/// .delete(3)
/// .await?;
/// # Ok(())
/// # }
/// ```
pub async fn delete(&self, id: u64) -> Result<()> {
let route = format!(
"/repos/{owner}/{repo}/releases/assets/{id}",
owner = self.parent.owner,
repo = self.parent.repo,
id = id,
);

self.parent.crab._delete(route, None::<&()>).await?;
Ok(())
}

/// Streams the binary contents of an asset.
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// use futures_util::StreamExt;
///
/// let mut stream = octocrab::instance()
/// .repos("owner", "repo")
/// .release_assets()
/// .stream_asset(AssetId(42u64))
/// .await?;
///
/// while let Some(chunk) = stream.next().await {
/// println!("{:?}", chunk);
/// }
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "stream")]
#[cfg_attr(docsrs, doc(cfg(feature = "stream")))]
pub async fn stream(
&self,
id: u64,
) -> crate::Result<impl futures_core::Stream<Item = crate::Result<bytes::Bytes>>> {
use futures_util::TryStreamExt;
//use snafu::GenerateImplicitData;

let route = format!(
"/repos/{owner}/{repo}/releases/assets/{id}",
owner = self.parent.owner,
repo = self.parent.repo,
id = id,
);

let uri = Uri::builder()
.path_and_query(route)
.build()
.context(HttpSnafu)?;
let builder = Builder::new()
.method(http::Method::GET)
.uri(uri)
.header(http::header::ACCEPT, "application/octet-stream");
let request = self.parent.crab.build_request(builder, None::<&()>)?;
let response = self.parent.crab.execute(request).await?;
let response = self.parent.crab.follow_location_to_data(response).await?;
Ok(http_body_util::BodyStream::new(response.into_body())
.try_filter_map(|frame| futures_util::future::ok(frame.into_data().ok())))
}
}

/// A builder pattern struct for updating release assets.
///
/// created by [`ReleaseAssetsHandler::update`].
#[derive(serde::Serialize)]
pub struct UpdateReleaseAssetBuilder<'octo, 'repos, 'handler, 'name, 'label> {
#[serde(skip)]
handler: &'handler ReleaseAssetsHandler<'octo, 'repos>,
#[serde(skip)]
asset_id: u64,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<&'name str>,
#[serde(skip_serializing_if = "Option::is_none")]
label: Option<&'label str>,
#[serde(skip_serializing_if = "Option::is_none")]
state: Option<crate::params::repos::release_assets::State>,
}

impl<'octo, 'repos, 'handler, 'name, 'label, 'state>
UpdateReleaseAssetBuilder<'octo, 'repos, 'handler, 'name, 'label>
{
pub(crate) fn new(
handler: &'handler ReleaseAssetsHandler<'octo, 'repos>,
asset_id: u64,
) -> Self {
Self {
handler,
asset_id,
name: None,
label: None,
state: None,
}
}

/// The name of the release asset.
pub fn name(mut self, name: &'name (impl AsRef<str> + ?Sized)) -> Self {
self.name = Some(name.as_ref());
self
}

/// The label of the release asset.
pub fn label(mut self, label: &'label (impl AsRef<str> + ?Sized)) -> Self {
self.label = Some(label.as_ref());
self
}

/// The state of the release asset.
pub fn state<A: Into<crate::params::repos::release_assets::State>>(
mut self,
state: impl Into<Option<A>>,
) -> Self {
self.state = state.into().map(A::into);
self
}

/// Sends the actual request.
pub async fn send(self) -> crate::Result<crate::models::repos::Asset> {
let route = format!(
"/repos/{owner}/{repo}/releases/assets/{asset_id}",
owner = self.handler.parent.owner,
repo = self.handler.parent.repo,
asset_id = self.asset_id,
);
self.handler.parent.crab.patch(route, Some(&self)).await
}
}
Loading

0 comments on commit 66b90cb

Please sign in to comment.