git-gemini-forge 0.6.2

A simple Gemini server that serves a read-only view of public repositories from a Git forge.
use super::ForgejoApi;
use crate::handlers::templates::PercentEncoded;
use crate::network::net::{ApiEndpoint, Net};
use crate::network::responses::{Contents, Item};
use crate::network::{error, ForgeApi};
use url::Url;

struct ContentsEndpoint<'a> {
	api: &'a ForgejoApi,
	base_url: Url,
	username: &'a PercentEncoded,
	repo_name: &'a PercentEncoded,
	branch_name: &'a PercentEncoded,
	path: &'a PercentEncoded,
}

impl ApiEndpoint<ForgejoApi, Contents<Item>> for ContentsEndpoint<'_> {
	fn api(&self) -> &ForgejoApi {
		self.api
	}

	fn url(&self) -> Url {
		let mut url = self
			.base_url
			.join(&format!(
				"repos/{}/{}/contents/{}",
				self.username.uri_component(),
				self.repo_name.uri_component(),
				self.path.uri_component()
			))
			.expect("Valid URL path");
		url.set_query(Some(&format!("ref={}", self.branch_name.uri_component())));
		url
	}
}

/// Retrieves the file or list of files at the given path.
pub fn get_contents(
	api: &ForgejoApi,
	net: &Net,
	username: &PercentEncoded,
	repo_name: &PercentEncoded,
	branch_name: &PercentEncoded,
	path: &PercentEncoded,
) -> Result<Contents<Item>, error::Error> {
	let base_url = api.base_url().clone();
	let endpoint = ContentsEndpoint {
		api,
		base_url,
		username,
		repo_name,
		branch_name,
		path,
	};

	// TODO: What if this is huge?
	match net.call(&endpoint)? {
		Contents::Single(item) => Ok(Contents::Single(item)),
		Contents::Multiple(mut items) => {
			items.sort();
			Ok(Contents::Multiple(items))
		}
	}
}