~/selfhut

00c0a2570c1c7c2fa0fb4818059851cd5d6ecff6 — Arthur Melton 616316d3 2 years ago
format code
M src/clone.rs => src/clone.rs +2 -3
@@ 1,9 1,8 @@

use rocket::fs::NamedFile;
use crate::config::CONFIG;
use crate::PathBufWithDotfiles;
use rocket::fs::NamedFile;


#[get("/<repo>/<path..>", rank=3)]
#[get("/<repo>/<path..>", rank = 3)]
pub async fn clone(repo: String, path: PathBufWithDotfiles) -> Option<NamedFile> {
    let mut repo_path = CONFIG.git_location.clone();
    repo_path.push(format!("{}.git", repo));

M src/git/commits.rs => src/git/commits.rs +34 -19
@@ 1,9 1,13 @@

use crate::config::CONFIG;
use serde_derive::{Serialize};
use chrono::{Utc, Duration};
use chrono::{Duration, Utc};
use chrono_humanize::HumanTime;
use serde_derive::Serialize;

pub fn get_commits(repo_name: String, ammount: usize, after: Option<String>) -> Option<Vec<Commits>> {
pub fn get_commits(
    repo_name: String,
    ammount: usize,
    after: Option<String>,
) -> Option<Vec<Commits>> {
    let mut repo_path = CONFIG.git_location.clone();
    repo_path.push(format!("{}.git", repo_name));
    let repo = git2::Repository::open(repo_path).ok()?;

@@ 12,7 16,7 @@ pub fn get_commits(repo_name: String, ammount: usize, after: Option<String>) -> 

    revwalk.set_sorting(git2::Sort::TIME).ok()?;
    match after {
        Some(id) => revwalk.push(git2::Oid::from_str(id.as_str()).ok()?).ok()?,
        None => revwalk.push_head().ok()?
        None => revwalk.push_head().ok()?,
    }
    let mut commits = Vec::new();
    let mut i = 0;

@@ 22,20 26,31 @@ pub fn get_commits(repo_name: String, ammount: usize, after: Option<String>) -> 

        let repo_commit = repo.find_commit(commit_rev);
        match repo_commit {
            Ok(repo_commit) => {
                    let time = Duration::seconds(repo_commit.time().seconds() - Utc::now().timestamp());
                    commits.push(Commits {
                        commit_hash: commit_rev.to_string(),
                        commit: repo_commit.message().unwrap_or("").to_string(),
                        commitie: repo_commit.committer().name().unwrap_or("Unknown").to_string(),
                        commit_hash_short: commit_rev.to_string()[..8].to_string(),
                        time_utc: {
                            let date = chrono::naive::NaiveDateTime::from_timestamp(Utc::now().timestamp() + time.num_seconds(), 0);
                            format!("{} {} UTC", date.date().format("%Y-%m-%d"), date.time().format("%H:%M:%S"))
                        },
                        time_relitive: HumanTime::from(time).to_string(),
                    });
                    i+=1;
            },
                let time = Duration::seconds(repo_commit.time().seconds() - Utc::now().timestamp());
                commits.push(Commits {
                    commit_hash: commit_rev.to_string(),
                    commit: repo_commit.message().unwrap_or("").to_string(),
                    commitie: repo_commit
                        .committer()
                        .name()
                        .unwrap_or("Unknown")
                        .to_string(),
                    commit_hash_short: commit_rev.to_string()[..8].to_string(),
                    time_utc: {
                        let date = chrono::naive::NaiveDateTime::from_timestamp(
                            Utc::now().timestamp() + time.num_seconds(),
                            0,
                        );
                        format!(
                            "{} {} UTC",
                            date.date().format("%Y-%m-%d"),
                            date.time().format("%H:%M:%S")
                        )
                    },
                    time_relitive: HumanTime::from(time).to_string(),
                });
                i += 1;
            }
            Err(_) => {}
        }
        commit = revwalk.next();

@@ 50,5 65,5 @@ pub struct Commits {

    commit_hash_short: String,
    commitie: String,
    time_utc: String,
    time_relitive: String
    time_relitive: String,
}

M src/git/file.rs => src/git/file.rs +30 -20
@@ 1,8 1,8 @@

use serde_derive::{Serialize};
use crate::config::CONFIG;
use std::path::Component;
use humansize::{format_size, DECIMAL};
use git2::ObjectType;
use humansize::{format_size, DECIMAL};
use serde_derive::Serialize;
use std::path::Component;
use std::path::PathBuf;

pub fn files(repo: String, branch: String, path: String) -> Option<Vec<File>> {

@@ 11,7 11,11 @@ pub fn files(repo: String, branch: String, path: String) -> Option<Vec<File>> {

    }
    let mut location = CONFIG.git_location.clone();
    location.push(path.clone());
    if location.components().into_iter().any(|x| x == Component::ParentDir) {
    if location
        .components()
        .into_iter()
        .any(|x| x == Component::ParentDir)
    {
        return None;
    }
    let mut repo_path = CONFIG.git_location.clone();

@@ 26,20 30,21 @@ pub fn files(repo: String, branch: String, path: String) -> Option<Vec<File>> {

                returns.push(File {
                    name: entry.name()?.to_string(),
                    size: match entry.kind() {
                        Some(ObjectType::Blob) => {
                            Some(format_size(entry.to_object(&repo).ok()?.into_blob().ok()?.size(), DECIMAL))
                        },
                        _ => None
                        Some(ObjectType::Blob) => Some(format_size(
                            entry.to_object(&repo).ok()?.into_blob().ok()?.size(),
                            DECIMAL,
                        )),
                        _ => None,
                    },
                    file_type: match entry.kind() {
                        Some(ObjectType::Blob) => FileType::blob,
                        _ => FileType::tree
                        _ => FileType::tree,
                    },
                    properties: unix_mode::to_string(entry.filemode() as u32),
                    properties_int: entry.filemode()
                })   
                    properties_int: entry.filemode(),
                })
            }
        },
        }
        _ => {
            return None;
        }

@@ 53,7 58,11 @@ pub fn file(repo: String, branch: String, path: String) -> Option<(File, Option<

    }
    let mut location = CONFIG.git_location.clone();
    location.push(path.clone());
    if location.components().into_iter().any(|x| x == Component::ParentDir) {
    if location
        .components()
        .into_iter()
        .any(|x| x == Component::ParentDir)
    {
        return None;
    }
    let mut repo_path = CONFIG.git_location.clone();

@@ 66,7 75,9 @@ pub fn file(repo: String, branch: String, path: String) -> Option<(File, Option<

            let mut path_to_folder = PathBuf::from(path);
            path_to_folder.pop();
            let path_to_folder = path_to_folder.into_os_string().to_str()?.to_string();
            let tree = repo.revparse_single(&format!("{}:{}", branch, path_to_folder)).ok()?;
            let tree = repo
                .revparse_single(&format!("{}:{}", branch, path_to_folder))
                .ok()?;
            let tree = tree.as_tree()?;
            let tree_item = tree.get_id(blob.id())?;
            let file = File {

@@ 74,32 85,31 @@ pub fn file(repo: String, branch: String, path: String) -> Option<(File, Option<

                size: Some(format_size(blob.size(), DECIMAL)),
                file_type: FileType::blob,
                properties: unix_mode::to_string(tree_item.filemode() as u32),
                properties_int: tree_item.filemode()
                properties_int: tree_item.filemode(),
            };
            let content = match blob.is_binary() {
                false => Some(String::from_utf8_lossy(blob.content()).into_owned()),
                true => None
                true => None,
            };
            return Some((file, content, blob.content().iter().map(|x| *x).collect()));
        },
        }
        _ => {
            return None;
        }
    }
}


#[derive(Serialize)]
pub struct File {
    pub name: String,
    pub size: Option<String>,
    pub file_type: FileType,
    pub properties: String,
    pub properties_int: i32
    pub properties_int: i32,
}

#[derive(Serialize)]
pub enum FileType {
    blob,
    tree
    tree,
}

M src/git/main_branch.rs => src/git/main_branch.rs +11 -1
@@ 4,6 4,16 @@ pub fn main_branch(repo_name: String) -> Option<String> {

    let mut repo_path = CONFIG.git_location.clone();
    repo_path.push(format!("{}.git", repo_name));
    let repo = git2::Repository::open(repo_path).ok()?;
    let x = Some(repo.branches(Some(git2::BranchType::Local)).ok()?.filter(|branch| branch.is_ok() && branch.as_ref().unwrap().0.is_head()).map(|branch| branch.unwrap().0).collect::<Vec<git2::Branch>>().get(0)?.name().ok()??.to_string());
    let x = Some(
        repo.branches(Some(git2::BranchType::Local))
            .ok()?
            .filter(|branch| branch.is_ok() && branch.as_ref().unwrap().0.is_head())
            .map(|branch| branch.unwrap().0)
            .collect::<Vec<git2::Branch>>()
            .get(0)?
            .name()
            .ok()??
            .to_string(),
    );
    x
}

M src/git/mod.rs => src/git/mod.rs +2 -2
@@ 1,5 1,5 @@

pub mod repos;
pub mod commits;
pub mod file;
pub mod main_branch;
pub mod repos;
pub mod tag;
pub mod file;

M src/git/repos.rs => src/git/repos.rs +1 -1
@@ 1,7 1,7 @@

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

pub fn get_repos() -> Option<Vec<Repo>> {
    let home = CONFIG.git_location.clone();

M src/git/tag.rs => src/git/tag.rs +1 -1
@@ 12,7 12,7 @@ pub fn get_tag(repo_name: String, amount: usize) -> Option<Vec<String>> {

    while i < amount && tag.is_some() && tag.unwrap().is_some() {
        tags.push(tag.unwrap().unwrap().to_string());
        tag = tags_stringarray.next();
        i+=1;
        i += 1;
    }
    Some(tags)
}

M src/main.rs => src/main.rs +15 -4
@@ 1,25 1,36 @@

#[macro_use]
extern crate rocket;
mod clone;
mod git;
mod index;
mod repository;
mod utils;
mod clone;

use utils::config;

use rocket::fs::relative;

use rocket_dyn_templates::Template;
use crate::repository::raw;
use crate::repository::summary;
use crate::repository::tree;
use crate::repository::raw;
use crate::utils::own_pathbuf::PathBufWithDotfiles;
use rocket_dyn_templates::Template;

#[launch]
fn rocket() -> _ {
    rocket::build()
        .mount("/", routes![file_server, index::index, summary::repository, tree::tree_main, tree::tree, clone::clone, raw::raw])
        .mount(
            "/",
            routes![
                file_server,
                index::index,
                summary::repository,
                tree::tree_main,
                tree::tree,
                clone::clone,
                raw::raw
            ],
        )
        .attach(Template::fairing())
}


M src/repository/mod.rs => src/repository/mod.rs +1 -1
@@ 1,3 1,3 @@

pub mod raw;
pub mod summary;
pub mod tree;
pub mod raw;

M src/repository/raw.rs => src/repository/raw.rs +9 -21
@@ 1,26 1,14 @@






use crate::git::file::{file};
use crate::git::file::file;
use crate::PathBufWithDotfiles;








#[get("/<repo>/blob/<branch>/<location..>", rank=2)]
#[get("/<repo>/blob/<branch>/<location..>", rank = 2)]
pub fn raw(repo: String, branch: String, location: PathBufWithDotfiles) -> Option<Vec<u8>> {
    match file(repo.clone(), branch.clone(), location.get().display().to_string()) {
        Some(file) => {
            Some(file.2) 
        },
        None => { 
            None
        }
    match file(
        repo.clone(),
        branch.clone(),
        location.get().display().to_string(),
    ) {
        Some(file) => Some(file.2),
        None => None,
    }
}

M src/repository/summary.rs => src/repository/summary.rs +22 -22
@@ 1,36 1,36 @@

use rocket_dyn_templates::{context, Template};
use crate::config::CONFIG;
use rocket_dyn_templates::{context, Template};

use crate::utils::markdown::md_to_html;
use crate::utils::repo_config::repo_config;
use crate::git::commits::get_commits;
use crate::git::file::file;
use crate::git::main_branch::main_branch;
use crate::git::tag::get_tag;
use crate::git::file::file;
use crate::utils::markdown::md_to_html;
use crate::utils::repo_config::repo_config;

#[get("/<repo>")]
pub fn repository(repo: String) -> Option<Template> {
    let main_branch = main_branch(repo.clone())?;
    let file = file(repo.clone(), main_branch.clone(), "README.md".to_string())?;
    Some(Template::render(
            "repository/summary",
            context! {
                title: repo.clone(),
                repo: repo.clone(),
                config: repo_config(repo.clone()),
                domain: CONFIG.domain.to_string(),
                readme: md_to_html(&file.1?),
                active: "summary",
                preview: get_commits(repo.clone(), 3, None),
                main_branch,
                tag: match get_tag(repo.clone(), 1) {
                    Some(x) => match x.get(0) {
                        Some(x) => Some(x.clone()),
                        None => None
                    },
        "repository/summary",
        context! {
            title: repo.clone(),
            repo: repo.clone(),
            config: repo_config(repo.clone()),
            domain: CONFIG.domain.to_string(),
            readme: md_to_html(&file.1?),
            active: "summary",
            preview: get_commits(repo.clone(), 3, None),
            main_branch,
            tag: match get_tag(repo.clone(), 1) {
                Some(x) => match x.get(0) {
                    Some(x) => Some(x.clone()),
                    None => None
                },
                payment: CONFIG.payment_link.clone()
            }
        ))
                None => None
            },
            payment: CONFIG.payment_link.clone()
        },
    ))
}

M src/repository/tree.rs => src/repository/tree.rs +66 -57
@@ 1,61 1,72 @@

use rocket_dyn_templates::{context, Template};
use crate::config::CONFIG;
use crate::utils::repo_config::repo_config;
use crate::git::commits::get_commits;
use crate::git::file::{file, files};
use crate::git::main_branch::main_branch;
use crate::git::file::{files, file};
use crate::utils::repo_config::repo_config;
use crate::PathBufWithDotfiles;
use rocket_dyn_templates::{context, Template};
use std::ffi::OsStr;

use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;
use syntect::highlighting::{ThemeSet};

use syntect::html::highlighted_html_for_string;
use std::path::Path;
use syntect::html::highlighted_html_for_string;

#[get("/<repo>/tree", rank=2)]
#[get("/<repo>/tree", rank = 2)]
pub fn tree_main(repo: String) -> Option<Template> {
    let main_branch = main_branch(repo.clone())?;
    Some(Template::render(
            "repository/tree",
            context! {
                title: format!("/ :: {}", repo.clone()),
                repo: repo.clone(),
                config: repo_config(repo.clone()),
                domain: CONFIG.domain.to_string(),
                active: "tree",
                commit: match get_commits(repo.clone(), 1, None) {
                    Some(x) => match x.get(0) {
                        Some(x) => Some(x.clone()),
                        None => None
                    }
        "repository/tree",
        context! {
            title: format!("/ :: {}", repo.clone()),
            repo: repo.clone(),
            config: repo_config(repo.clone()),
            domain: CONFIG.domain.to_string(),
            active: "tree",
            commit: match get_commits(repo.clone(), 1, None) {
                Some(x) => match x.get(0) {
                    Some(x) => Some(x.clone()),
                    None => None
                },
                branch: main_branch.clone(),
                files: files(repo, main_branch, "".to_string()),
                current_dir_file: "/",
                current_dir: "/",
                payment: CONFIG.payment_link.clone()
            }
        ))
                }
                None => None
            },
            branch: main_branch.clone(),
            files: files(repo, main_branch, "".to_string()),
            current_dir_file: "/",
            current_dir: "/",
            payment: CONFIG.payment_link.clone()
        },
    ))
}

#[get("/<repo>/tree/<branch>/<location..>", rank=2)]
#[get("/<repo>/tree/<branch>/<location..>", rank = 2)]
pub fn tree(repo: String, branch: String, location: PathBufWithDotfiles) -> Option<Template> {
    match file(repo.clone(), branch.clone(), location.get().display().to_string()) {
    match file(
        repo.clone(),
        branch.clone(),
        location.get().display().to_string(),
    ) {
        Some(file) => {
            let mut content = "".to_string();
            let mut lines: Vec<usize> = (1..1).collect();
            if file.1.is_some() {
                let ps = SyntaxSet::load_defaults_newlines();
                let ts = ThemeSet::load_defaults();
                let syntax = match ps.find_syntax_by_extension(Path::new(&file.0.name).extension().and_then(OsStr::to_str).unwrap_or("txt")) {
                let syntax = match ps.find_syntax_by_extension(
                    Path::new(&file.0.name)
                        .extension()
                        .and_then(OsStr::to_str)
                        .unwrap_or("txt"),
                ) {
                    Some(x) => x,
                    None => ps.find_syntax_by_extension("txt").unwrap()
                    None => ps.find_syntax_by_extension("txt").unwrap(),
                };
                let s = file.1.as_ref().unwrap();
                lines = (1..s.lines().count()+1).collect();
                content = highlighted_html_for_string(s, &ps, syntax, &ts.themes["Solarized (light)"]).ok()?
                lines = (1..s.lines().count() + 1).collect();
                content =
                    highlighted_html_for_string(s, &ps, syntax, &ts.themes["Solarized (light)"])
                        .ok()?
            }
            Some(Template::render(
                "repository/file",

@@ 80,32 91,30 @@ pub fn tree(repo: String, branch: String, location: PathBufWithDotfiles) -> Opti

                    content,
                    lines,
                    payment: CONFIG.payment_link.clone()
                }
            ))
        },
        None => { 
            Some(Template::render(
                "repository/tree",
                context! {
                    title: format!("/{} :: {}", location.get().display(), repo.clone()),
                    repo: repo.clone(),
                    config: repo_config(repo.clone()),
                    domain: CONFIG.domain.to_string(),
                    active: "tree",
                    commit: match get_commits(repo.clone(), 1, None) {
                        Some(x) => match x.clone().get(0) {
                            Some(x) => Some(x.clone()),
                            None => None
                        }
                        None => None
                    },
                    branch: branch.clone(),
                    files: files(repo, branch, location.get().display().to_string()),
                    current_dir_file: format!("/{}/", location.get().display()).replace("//", "/"),
                    current_dir: format!("/{}", location.get().display()),
                    payment: CONFIG.payment_link.clone()
                }
                },
            ))
        }
        None => Some(Template::render(
            "repository/tree",
            context! {
                title: format!("/{} :: {}", location.get().display(), repo.clone()),
                repo: repo.clone(),
                config: repo_config(repo.clone()),
                domain: CONFIG.domain.to_string(),
                active: "tree",
                commit: match get_commits(repo.clone(), 1, None) {
                    Some(x) => match x.clone().get(0) {
                        Some(x) => Some(x.clone()),
                        None => None
                    }
                    None => None
                },
                branch: branch.clone(),
                files: files(repo, branch, location.get().display().to_string()),
                current_dir_file: format!("/{}/", location.get().display()).replace("//", "/"),
                current_dir: format!("/{}", location.get().display()),
                payment: CONFIG.payment_link.clone()
            },
        )),
    }
}

M src/utils/markdown.rs => src/utils/markdown.rs +1 -1
@@ 1,5 1,5 @@

use pulldown_cmark::{Parser, Options, html};
use emojicons::EmojiFormatter;
use pulldown_cmark::{html, Options, Parser};

pub fn md_to_html(input: &str) -> String {
    let input = EmojiFormatter(input).to_string();

M src/utils/mod.rs => src/utils/mod.rs +2 -2
@@ 1,4 1,4 @@

pub mod markdown;
pub mod repo_config;
pub mod config;
pub mod markdown;
pub mod own_pathbuf;
pub mod repo_config;

M src/utils/own_pathbuf.rs => src/utils/own_pathbuf.rs +2 -2
@@ 1,6 1,6 @@

use std::path::PathBuf;
use rocket::http::uri::{Segments, error::PathError, fmt::Path};
use rocket::http::uri::{error::PathError, fmt::Path, Segments};
use rocket::request::FromSegments;
use std::path::PathBuf;

pub struct PathBufWithDotfiles(PathBuf);


M src/utils/repo_config.rs => src/utils/repo_config.rs +7 -5
@@ 1,5 1,5 @@

use serde_derive::{Deserialize, Serialize};
use crate::config::CONFIG;
use serde_derive::{Deserialize, Serialize};
use std::fs;

pub fn repo_config(repo: String) -> RepoConfig {

@@ 7,15 7,17 @@ pub fn repo_config(repo: String) -> RepoConfig {

    config.push(format!("{}.git", repo));
    config.push("repo.toml");
    let config_string = match fs::read(config) {
        Ok(content) => String::from_utf8_lossy(&content).parse().unwrap_or("".to_string()),
        Err(_) => "".to_string()
        Ok(content) => String::from_utf8_lossy(&content)
            .parse()
            .unwrap_or("".to_string()),
        Err(_) => "".to_string(),
    };
    match toml::from_str(&config_string) {
        Ok(x) => x,
        Err(_) => RepoConfig {
            description: None,
            website: None
        }
            website: None,
        },
    }
}