~/selfhut

ad9e51646644e0a95b0eccfe339a38981571af15 — arthurmelton 94e2262d 2 years ago
format
6 files changed, 157 insertions(+), 75 deletions(-)

M src/config.rs
M src/git/repos.rs
M src/index.rs
M src/main.rs
A templates/index.html
M templates/layout.html.hbs
M src/config.rs => src/config.rs +14 -7
@@ 1,5 1,5 @@

use lazy_static::lazy_static;
use serde_derive::{Serialize, Deserialize};
use serde_derive::{Deserialize, Serialize};
use std::{fs, path::PathBuf};

lazy_static! {

@@ 8,19 8,26 @@ lazy_static! {

        config.push("git-server");
        config.push("git-server.toml");
        if config.exists() {
           let config:Config = toml::from_str(&String::from_utf8_lossy(&fs::read(config.as_path()).expect("Failed to read the config file"))).expect("Could not parse the toml in the config file");
           config
        }
        else {
            let config: Config = toml::from_str(&String::from_utf8_lossy(
                &fs::read(config.as_path()).expect("Failed to read the config file"),
            ))
            .expect("Could not parse the toml in the config file");
            config
        } else {
            let config_struct = Config {
                name: "Example User".to_string(),
                description: "This is billy and he loves his [website](https://example.com)!!!".to_string(),
                description: "This is billy and he loves his [website](https://example.com)!!!"
                    .to_string(),
                git_location: dirs::home_dir().unwrap_or(PathBuf::from("/")),
            };
            config.pop();
            let _ = fs::create_dir_all(config.clone());
            config.push("git-server.toml");
            fs::write(config, toml::to_string(&config_struct).expect("Failed to stringify config")).expect("Failed to set the config content");
            fs::write(
                config,
                toml::to_string(&config_struct).expect("Failed to stringify config"),
            )
            .expect("Failed to set the config content");
            config_struct
        }
    };

M src/git/repos.rs => src/git/repos.rs +41 -32
@@ 1,37 1,40 @@

use std::fs;
use serde_derive::Serialize;
use crate::config::CONFIG;
use serde_derive::Serialize;
use std::fs;

pub fn get_repos() -> Option<Vec<Repo>> {
    let home = CONFIG.git_location.clone();
    Some(sort_modified(fs::read_dir(home.clone()).ok()?
        .filter(|path| path.is_ok())
        .map(|path| path.unwrap())
        .filter(|path| path.file_type().is_ok())
        .filter(|path| path.file_type().unwrap().is_dir())
        .filter(|path| path.metadata().is_ok())
        .filter(|path| path.metadata().unwrap().modified().is_ok())
        .map(|path| path.file_name().into_string())
        .filter(|path| path.is_ok())
        .map(|path| path.unwrap())
        .filter(|path| !path.starts_with("."))
        .filter(|path| path.ends_with(".git"))
        .map(|path| {
            let mut description_path = home.clone();
            description_path.push(path.clone());
            description_path.push("DESCRIPTION");
            let description = match fs::read(description_path.clone()) {
                Ok(content) => {
                    String::from_utf8_lossy(&content).parse().unwrap_or("".to_string())
                },
                Err(_) => "".to_string()
            };
            Repo {
                name: path[0..path.len() - 4].to_string(),
                description
            }
        })
        .collect::<Vec<Repo>>()))
    Some(sort_modified(
        fs::read_dir(home.clone())
            .ok()?
            .filter(|path| path.is_ok())
            .map(|path| path.unwrap())
            .filter(|path| path.file_type().is_ok())
            .filter(|path| path.file_type().unwrap().is_dir())
            .filter(|path| path.metadata().is_ok())
            .filter(|path| path.metadata().unwrap().modified().is_ok())
            .map(|path| path.file_name().into_string())
            .filter(|path| path.is_ok())
            .map(|path| path.unwrap())
            .filter(|path| !path.starts_with("."))
            .filter(|path| path.ends_with(".git"))
            .map(|path| {
                let mut description_path = home.clone();
                description_path.push(path.clone());
                description_path.push("DESCRIPTION");
                let description = match fs::read(description_path.clone()) {
                    Ok(content) => String::from_utf8_lossy(&content)
                        .parse()
                        .unwrap_or("".to_string()),
                    Err(_) => "".to_string(),
                };
                Repo {
                    name: path[0..path.len() - 4].to_string(),
                    description,
                }
            })
            .collect::<Vec<Repo>>(),
    ))
}

#[derive(Serialize, Clone)]

@@ 43,12 46,18 @@ pub struct Repo {

fn sort_modified(repos: Vec<Repo>) -> Vec<Repo> {
    let mut repos = repos.clone();
    let home = CONFIG.git_location.clone();
    repos.sort_by(|a,b| {
    repos.sort_by(|a, b| {
        let mut a_loc = home.clone();
        a_loc.push(format!("{}.git", a.name));
        let mut b_loc = home.clone();
        b_loc.push(format!("{}.git", b.name));
        b_loc.metadata().unwrap().modified().unwrap().partial_cmp(&a_loc.metadata().unwrap().modified().unwrap()).unwrap()
        b_loc
            .metadata()
            .unwrap()
            .modified()
            .unwrap()
            .partial_cmp(&a_loc.metadata().unwrap().modified().unwrap())
            .unwrap()
    });
    repos
}

M src/index.rs => src/index.rs +30 -22
@@ 1,39 1,47 @@

use crate::git::repos::get_repos;
use crate::config::CONFIG;
use crate::git::repos::get_repos;
use crate::git::repos::Repo;

use rocket_dyn_templates::{Template, context};
use rocket_dyn_templates::{context, Template};

const PAGE_REPO_COUNT:usize = 10;
const PAGE_REPO_COUNT: usize = 10;

#[get("/?<page>&<search>")]
pub fn index(page: Option<usize>, search: Option<String>) -> Option<Template> {
    let mut repos = get_repos()?;
    let page = page.unwrap_or(1);
    if search.is_some() {
        repos = repos.iter().filter(|repo| repo.name.contains(&*search.as_ref().unwrap()) || repo.description.contains(&*search.as_ref().unwrap())).map(|repo| repo.clone()).collect::<Vec<Repo>>();
        repos = repos
            .iter()
            .filter(|repo| {
                repo.name.contains(&*search.as_ref().unwrap())
                    || repo.description.contains(&*search.as_ref().unwrap())
            })
            .map(|repo| repo.clone())
            .collect::<Vec<Repo>>();
    }
    let total_page = if repos.len() > 0 {
        (repos.len()-1)/PAGE_REPO_COUNT+1
    }
    else {
        (repos.len() - 1) / PAGE_REPO_COUNT + 1
    } else {
        1
    };
    let last_item = if repos.len() > page*PAGE_REPO_COUNT {
        page*PAGE_REPO_COUNT
    }
    else {
    let last_item = if repos.len() > page * PAGE_REPO_COUNT {
        page * PAGE_REPO_COUNT
    } else {
        repos.len()
    };
    Some(Template::render("index", context! {
        title: "Me",
        user: CONFIG.name.clone(),
        description: markdown::to_html(&CONFIG.description.clone()),
        repos: repos[(page-1)*PAGE_REPO_COUNT..last_item].to_vec(),
        search: search.unwrap_or("".to_string()),
        page,
        total_page,
        page_inc: page+1,
        page_dec: if page > 1 {page-1} else {page}
    }))
    Some(Template::render(
        "index",
        context! {
            title: "Me",
            user: CONFIG.name.clone(),
            description: markdown::to_html(&CONFIG.description.clone()),
            repos: repos[(page-1)*PAGE_REPO_COUNT..last_item].to_vec(),
            search: search.unwrap_or("".to_string()),
            page,
            total_page,
            page_inc: page+1,
            page_dec: if page > 1 {page-1} else {page}
        },
    ))
}

M src/main.rs => src/main.rs +5 -4
@@ 1,11 1,12 @@

#[macro_use] extern crate rocket;
#[macro_use]
extern crate rocket;
mod config;
mod git;
mod index;
mod config;

use rocket_dyn_templates::Template;
use rocket::fs::FileServer;
use rocket::fs::relative;
use rocket::fs::FileServer;
use rocket_dyn_templates::Template;

#[launch]
fn rocket() -> _ {

A templates/index.html +57 -0
@@ 0,0 1,57 @@

{{#*inline "page"}}
<div class="container" style="margin-top:56px">
   <div class="row">
      <div class="col-md-4">
         <h2>{{ user }}!</h2>
         {{{ description }}}
      </div>
      <div class="col-md-8">
         <form>
            <input class="form-control" dir="auto" name="search" placeholder="Search" type="text" value="{{ search }}">
         </form>
         <div class="event-list">
            {{#each repos}}
            <div class="event">
               <h4> 
                  <a href="/{{this.name}}">{{ this.name }}</a>
               </h4>
               <p>{{ this.description }}</p>
            </div>
            {{/each}}
         </div>
         {{#if (ne total_page 1)}}
         <div class="row">
            <div class="col-4">
               {{#if (ne page 1)}}
               <a class="btn btn-default" href="?page={{page_dec}}&search={{search}}">
                  <span aria-hidden="true" class="icon icon-caret-left">
                     <svg viewBox="0 0 192 512" xmlns="http://www.w3.org/2000/svg">
                        <path d="M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z"></path>
                     </svg>
                  </span>
                  prev
               </a>
               {{/if}}
            </div>
            <div class="col-4 text-centered">
               {{page}} / {{ total_page }}
            </div>
            {{#if (ne page total_page)}}
            <div class="col-4 text-right">
               <a class="btn btn-default" href="?page={{page_inc}}&search={{search}}">
                  next
                  <span aria-hidden="true" class="icon icon-caret-right">
                     <svg viewBox="0 0 192 512" xmlns="http://www.w3.org/2000/svg">
                        <path d="M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"></path>
                     </svg>
                  </span>
               </a>
            </div>
            {{/if}}
         </div>
         {{/if}}
      </div>
   </div>
</div>
{{/inline}}
{{> layout}}
\ No newline at end of file

M templates/layout.html.hbs => templates/layout.html.hbs +10 -10
@@ 1,12 1,12 @@

<!doctype html>
<html>
  <head>
    <meta charset="utf8">
    <meta content="width=device-width, initial-scale=1" name="viewport">
    <title>{{ title }} :: Arthur Melton Git</title>
    <link rel="stylesheet" href="/style.css">
  </head>
  <body>
    {{~> page}}
  </body>
</html>
   <head>
      <meta charset="utf8">
      <meta content="width=device-width, initial-scale=1" name="viewport">
      <title>{{ title }} :: Arthur Melton Git</title>
      <link rel="stylesheet" href="/style.css">
   </head>
   <body>
      {{~> page}}
   </body>
</html>
\ No newline at end of file