git-gemini-forge 0.5.2

A simple Gemini server that serves a read-only view of public repositories from a Git forge.
use crate::network::responses::{ContentsType, JsonUrl, Repo, RepoContents, ServerVersion, User};
use serde::Deserialize;

pub fn gitlab_project_id(username: &str, project_pathname: &str) -> String {
	return format!("{username}%2F{project_pathname}");
}

#[derive(Deserialize, Debug)]
pub struct GitLabMetadata {
	pub version: String,
	pub revision: String,
}

pub fn gitlab_metadata_to_server_version(metadata: &GitLabMetadata) -> ServerVersion {
	let version = &metadata.version;
	let revision = &metadata.revision;
	return ServerVersion {
		version: format!("{version} ({revision})"),
	};
}

#[derive(Deserialize, Debug)]
pub struct GitLabProjectNamespace {
	pub path: String,
}

#[derive(Deserialize, Debug)]
pub struct GitLabProject {
	/// An empty project has no default branch. See https://stackoverflow.com/a/73479901
	pub default_branch: Option<String>,
	pub web_url: JsonUrl,
	pub name: String,
	pub namespace: GitLabProjectNamespace,
	pub updated_at: Option<String>,
	pub created_at: String,
}

pub fn gitlab_project_to_repo(project: &GitLabProject) -> Repo {
	let owner = User {
		login: project.namespace.path.clone(),
	};
	let default_branch = project
		.default_branch
		.clone()
		.or(Some(String::from("main")))
		.expect("");
	let updated_at = project
		.updated_at
		.clone()
		.or(Some(project.created_at.clone()))
		.expect("");
	return Repo {
		default_branch,
		html_url: project.web_url.clone(),
		name: project.name.clone(),
		owner,
		updated_at,
	};
}

#[derive(Deserialize, Debug)]
pub struct GitLabUser {
	pub username: String,
}

pub fn gitlab_user_to_user(user: &GitLabUser) -> User {
	let login = user.username.clone();
	return User { login };
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "lowercase")]
pub enum GitLabProjectContentsType {
	Blob,
	Tree,
}

#[derive(Deserialize, Debug)]
pub struct GitLabProjectContents {
	#[serde(rename = "type")]
	pub kind: GitLabProjectContentsType,
	pub id: String,
	pub name: String,
	pub path: String,
}

pub fn gitlab_contents_to_contents(contents: &GitLabProjectContents) -> RepoContents {
	let kind = match contents.kind {
		GitLabProjectContentsType::Blob => ContentsType::File,
		GitLabProjectContentsType::Tree => ContentsType::Dir,
	};
	return RepoContents {
		kind,
		content: None,
		name: contents.name.clone(),
		path: contents.path.clone(),
	};
}