octocrab icon indicating copy to clipboard operation
octocrab copied to clipboard

How do you actually download a tarball?

Open winstonpurnomo opened this issue 1 year ago • 4 comments

The download_tarball method returns an object, once awaited and unwrapped, is a Response<Body>. I'm not sure how to turn this into an actual working tar.gz file on my computer, since the hyper::body::to_bytes method has been deprecated recently.

winstonpurnomo avatar Jan 31 '24 02:01 winstonpurnomo

https://hyper.rs/guides/1/client/basic/ has some detail on how to stream payloads. They have an example here: https://github.com/hyperium/hyper/blob/master/examples/client.rs#L64-L76

Streaming like this will be a much better approach than trying to hold the entire payload in memory at once.

@XAMPPRocky, it does mean we'll need to adapt to this breaking change in hyper. We're using ::to_bytes() in a few places:

src/api/actions.rs:        body::to_bytes(body).await.context(HyperSnafu)
src/from_response.rs:        let body = hyper::body::to_bytes(body)
src/lib.rs:            body::to_bytes(response.into_body())
src/lib.rs:        let body_bytes = body::to_bytes(res.into_body()).await.context(HyperSnafu)?;
src/models/repos.rs:            body::to_bytes(response.into_body())
src/page.rs:            body::to_bytes(response.into_body())
tests/follow_redirect.rs:                    format!("/repos/{new_owner}/{repo}/stargazers").into_bytes(),

manchicken avatar Feb 04 '24 04:02 manchicken

(This appears to be a duplicate of #493)

manchicken avatar Feb 04 '24 04:02 manchicken

https://hyper.rs/guides/1/client/basic/ has some detail on how to stream payloads. They have an example here: https://github.com/hyperium/hyper/blob/master/examples/client.rs#L64-L76

Streaming like this will be a much better approach than trying to hold the entire payload in memory at once.

Sorry to ask a follow up, but the example provided:

 let mut res = sender.send_request(req).await?;

res is a Response<Incoming> type, while download_tarball, after awaiting and unwrapping, is a Response<Body>, which doesn't have a frame() method I can call.

winstonpurnomo avatar Feb 04 '24 22:02 winstonpurnomo

I was able to stream a repo into a tarball on disk utilizing the following.

use http_body_util::BodyExt;

let mut resp = octocrab
    .repos(REPO_OWNER, REPO_NAME)
    .download_tarball(Reference::Branch("BRANCH_NAME".to_owned()))
    .await?;

let body = resp.body_mut();

let mut file = File::create("test.tar.gz")?;

while let Some(next) = body.frame().await {
    let frame = next?;
    if let Some(chunk) = frame.data_ref() {
        file.write_all(&chunk)?;
    }
}

In order to get frame in scope requires the BodyExt import.

SSS475 avatar Feb 22 '24 15:02 SSS475