Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for downloading zip and tar archives of repositories. #967

Merged
merged 10 commits into from
Feb 26, 2021

Conversation

chids
Copy link
Contributor

@chids chids commented Oct 20, 2020

👋, found myself needing to download zip/tar archives of repository content which wasn't supported so mucked about with getting that in place.

Now, there's a few things to note here which I'm not sure if/how to tackle:

  1. The wiremock setup for the unit tests seems to use a HTTP client that doesn't follow redirects whereas the one used by default seems to....bug? 🐛
  2. The archive endpoints return a 302 redirect to the actual archive which is hosted at https://codeload.github.com/<owner>/<repo>/legacy.<tar.gz|zip>/<ref> but the redirect doesn't seem to be captured properly by wiremock and the download itself isn't captured at all even when adding manual logic to follow the redirect
  3. Then, more of an FYI, I decided to "drop down" to Requester.client in order to be able to stream the content directly into a StreamConsumer since Requester.fetchStream() reads everything into memory which didn't seem ideal for dealing with entire repository archives

@bitwiseman
Copy link
Member

bitwiseman commented Nov 3, 2020

@chids

Item 2 will require an update to the test framework to fix, but it should be pretty easy - adding another mock server to the list and then recording. You can do that as part of this PR if you like.

Looks like there is another PR that needs to do something similar.
#789 (comment)

As an alternative, you could record the interaction and then manually create a payload that points to the raw mock server and return the data from there.

}

private void downloadArchive(String type, Optional<String> ref, StreamConsumer sink) throws IOException {
requireNonNull(sink, "Sink must not be null");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use spotbugs annotation for this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the annotation doesn't actually enforce it at run time though as far as I know?
they provide hints for IDE and static analysis tools

* @throws IOException
* The IO exception.
*/
public void zipball(StreamConsumer sink, String ref) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see why you did this. This is the endpoint you're hitting, but maybe we should use a more Java-like name for the methods? I'm interested to know your opinion.

Suggested change
public void zipball(StreamConsumer sink, String ref) throws IOException {
public void downloadZip(StreamConsumer sink, String ref) throws IOException {

Copy link
Member

@bitwiseman bitwiseman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timja @chids

I updated this with new library-wide functional interfaces. Also fixed the codeload and redirect issue.

The main question I have is whether it is better to have the public readZip and readTar methods take a Consumer or a Function. This matters because implementing one now and adding the other later may result in compilation errors - the compiler may not be able to distinguish between the two types for some lambda inputs.

Copy link
Collaborator

@timja timja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure either way on whether consumer of function is better

}

private void downloadArchive(String type, Optional<String> ref, StreamConsumer sink) throws IOException {
requireNonNull(sink, "Sink must not be null");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the annotation doesn't actually enforce it at run time though as far as I know?
they provide hints for IDE and static analysis tools

@bitwiseman
Copy link
Member

@timja Thanks for taking the time to review.

@bitwiseman bitwiseman merged commit d4cc3af into hub4j:master Feb 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants