git-gemini-forge 0.4.0

A simple Gemini server that serves a read-only view of public repositories from a Git forge.
use crate::config::*;
use crate::network;
use url::Url;
use windmark::response::Response;

/// Answers with Gemtext that consists of an overview of a repository.
pub fn handler(cfg: &Config, username: &str, repo_name: &str) -> Result<Response, network::error::Error> {
	let repo = &cfg.forge_api().get_repo(username, repo_name)?;
	// TODO: This should probs go in a custom deserializer:
	let repo_http: String = match Url::parse(&repo.html_url) {
		Err(parse_error) => (|| {
			println!("Failed to parse repo URL due to error: {parse_error}");
			return String::from("");
		})(),
		Ok(repo_http_url) => format!("\n\n=> {repo_http_url} View on {}", cfg.forge_kind.to_string()),
	};

	// List branches
	let branches = &cfg.forge_api().get_branches(username, repo_name)?;

	// Transform repos into Gemtext internal page links
	let branches_list: Vec<String> = branches.iter()
		.map(|b| super::templates::branch_link(&repo, &b))
		.collect();

	// Format repos into a Gemtext list
	let gemtext_branches_list: String = branches_list.iter()
		.map(|b: &String| format!("{b}\n"))
		.collect::<Vec<String>>()
		.concat();

	// List file tree
	let contents = &cfg.forge_api().get_file_tree(username, repo_name)?;

	// Transform contents into Gemtext internal page links
	let contents_list: Vec<String> = contents.iter()
		.map(|f| super::templates::file_link(&repo, None, &f))
		.collect();

	// Format contents into a Gemtext list
	let gemtext_tree_list: String = contents_list.iter()
		.map(|f| format!("{f}\n"))
		.collect::<Vec<String>>()
		.concat();

	// TODO: Render README.gem if exists

	let gemtext: String = format!("## {username}/{repo_name}\n=> /{username} {username}\n### Branches\n{gemtext_branches_list}\n### Tree\n{gemtext_tree_list}{repo_http}");

	return Ok(Response::success(gemtext));
}