mygit

[UNMAINTAINED] A cgit/webgit alternative, written in Rust
Log | Files | Refs | README | LICENSE

commit ecd95a4f36758786e817592241bf87b7ab52e7da
parent 7973f6e1e3ee1bc688d6c4bb262dff21509969c2
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Sat, 13 Mar 2021 10:59:31 -0800

Start to style homepage

Diffstat:
Amygit.toml | 5+++++
Msrc/main.rs | 65++++++++++++++++++++++++++++++++++++++++-------------------------
Mtemplates/base.html | 9+++++++++
Mtemplates/index.html | 9+++++++--
Atemplates/static/robots.txt | 2++
Atemplates/static/style.css | 37+++++++++++++++++++++++++++++++++++++
6 files changed, 100 insertions(+), 27 deletions(-)

diff --git a/mygit.toml b/mygit.toml @@ -0,0 +1,5 @@ +port = 8081 +# Directory to store git repos +repo_directory = "repos" +emoji_favicon = "💻" +page_title = "My git repositories" diff --git a/src/main.rs b/src/main.rs @@ -1,18 +1,19 @@ -use tide::Request; use askama::Template; -use tide::prelude::*; -use std::path::Path; -use std::time::Instant; +use git2::Repository; use once_cell::sync::OnceCell; -use std::fs; -use serde::{Serialize, Deserialize}; use pico_args; -use git2::Repository; +use serde::{Deserialize, Serialize}; +use std::fs; +use std::path::Path; +use std::time::Instant; +use tide::prelude::*; +use tide::Request; #[derive(Deserialize, Debug)] pub struct Config { port: i32, // should be u8 - repo_directory: String + repo_directory: String, + emoji_favicon: String, } static CONFIG: OnceCell<Config> = OnceCell::new(); @@ -21,42 +22,48 @@ impl Config { pub fn global() -> &'static Config { CONFIG.get().expect("Config is not initialized") } - } -#[derive(Template)] +#[derive(Template)] #[template(path = "index.html")] // using the template in this path, relative -struct IndexTemplate { - repos: Vec<Repository> +struct IndexTemplate<'a> { + repos: Vec<Repository>, + config: &'a Config, } async fn index(req: Request<()>) -> tide::Result { - let repos = &Config::global().repo_directory; + let config = &Config::global(); + let repos = &config.repo_directory; let paths = fs::read_dir(repos)?; - let mut index_template = IndexTemplate{ - repos: vec![] + let mut index_template = IndexTemplate { + repos: vec![], + config: config, }; // TODO replace with map/collect for path in paths { let repo = Repository::open(path?.path())?; index_template.repos.push(repo); } + Ok(index_template.into()) } -#[derive(Template)] +#[derive(Template)] #[template(path = "repo.html")] // using the template in this path, relative -struct RepoHomeTemplate<'a> { +struct RepoHomeTemplate<'a> { repo: Repository, - readme_text: &'a str + readme_text: &'a str, + config: &'a Config, } async fn repo_home(req: Request<()>) -> tide::Result { - let repo_path = Path::new(&Config::global().repo_directory).join(req.param("repo_name")?); + let config = &Config::global(); + let repo_path = Path::new(&config.repo_directory).join(req.param("repo_name")?); // TODO CLEAN PATH! VERY IMPORTANT! DONT FORGET! let repo = Repository::open(repo_path)?; let tmpl = RepoHomeTemplate { - repo: repo, - readme_text: "Hello world" + repo, + readme_text: "Hello world", + config, }; Ok(tmpl.into()) } @@ -70,7 +77,6 @@ OPTIONS: -c Path to config file "; - #[async_std::main] async fn main() -> Result<(), std::io::Error> { let mut pargs = pico_args::Arguments::from_env(); @@ -81,7 +87,7 @@ async fn main() -> Result<(), std::io::Error> { } // TODO cli - + let toml_text = fs::read_to_string("mygit.toml")?; let config: Config = toml::from_str(&toml_text)?; CONFIG.set(config).unwrap(); @@ -89,9 +95,18 @@ async fn main() -> Result<(), std::io::Error> { tide::log::start(); let mut app = tide::new(); app.at("/").get(index); + app.at("/robots.txt") + .serve_file("templates/static/robots.txt")?; // TODO configurable + app.at("/style.css") + .serve_file("templates/static/style.css")?; // TODO configurable app.at("/:repo_name").get(repo_home); - app.at("/:repo_name/log").get(repo_log); - // app.at("/:repo_name/:commit/tree").get(repo_log); + // ALSO do git pull at this url somehow ^ + // app.at("/:repo_name/commit/:hash").get(repo_log); + // app.at("/:repo_name/log/:ref").get(repo_log); ref optional, default master/main + // app.at("/:repo_name/tree/:ref").get(repo_log); ref = master/main when not present + // app.at("/:repo_name/tree/:ref/item/:file").get(repo_log); ref = master/main when not present + // app.at("/:repo_name/refs").get(repo_log); ref = master/main when not present + // Bonus: raw files, patchsets app.listen("127.0.0.1:8081").await?; Ok(()) } diff --git a/templates/base.html b/templates/base.html @@ -1,6 +1,11 @@ <!DOCTYPE html> <html lang="en"> <head> + <meta charset="utf-8"> + <link rel="stylesheet" type="text/css" href="/style.css" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=0" /> + <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>{{config.emoji_favicon}}</text></svg>"> + <meta name="description" content="My self-hosted git repositories"> <title>{% block title %}My Site{% endblock %}</title> {% block head %}{% endblock %} </head> @@ -8,5 +13,9 @@ <div id="content"> {% block content %}{% endblock %} </div> + <hr class = "thin"> + <div class="footer"> + Server running <a href="git.alexwennerberg.com/mygit">mygit</a> + </div> </body> </html> diff --git a/templates/index.html b/templates/index.html @@ -1,9 +1,14 @@ {% extends "base.html" %} {% block content %} - <h1>Repositories</h1> + <div class="page-title"><h1>Repositories</h1></div> + <h2>Subheading</h2> {% for repo in repos %} {% let name = repo.workdir().unwrap().file_name().unwrap().to_str().unwrap() %} - <a href="{{name}}">{{ name }}</a> -- description -- + <div class="repo-listing"> + <div class="repo-link"><a href="{{name}}">{{ name }}</a></div> + <div class="repo-description">a cool repository</div> + <div class="repo-last-updated">updated 2021-02-01</div> + </div> {% endfor %} {% endblock %} diff --git a/templates/static/robots.txt b/templates/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /*?* diff --git a/templates/static/style.css b/templates/static/style.css @@ -0,0 +1,37 @@ +body { + max-width: 90ch; + padding: 2ch; + margin: auto; + font-family: "Roboto", Helvetica, Arial, Sans-serif; + word-wrap: break-word; + background-color: white; + line-height: 1.5; +} + +.repo-last-updated { + font-style: italic; +} + +.repo-link { + font-family: "Roboto Mono", monospace; + font-size: 1.2rem; +} + +.repo-listing { + background-color: #f0f0f0; + padding: .3rem; + margin-bottom: .5rem; +} + +.footer { + text-align: center; + font-style: italic; + font-size: .9rem; +} + +hr.thin { + border: 0; + height: 0; + border-top: 1px solid rgba(0, 0, 0, 0.1); + border-bottom: 1px solid rgba(255, 255, 255, 0.3); +}