~/selfhut

b961c5bf13c1b6610d6f23b10a897451cc9653d9 — Arthur Melton d91f7723 2 years ago
tarballs!
6 files changed, 79 insertions(+), 1 deletions(-)

M Cargo.toml
A src/git/get_all.rs
M src/git/mod.rs
M src/main.rs
A src/repository/archive.rs
M src/repository/mod.rs
M Cargo.toml => Cargo.toml +1 -0
@@ 19,5 19,6 @@ rocket_dyn_templates = {version = "0.1.0-rc.2", features=["handlebars"]}

serde = "1.0.145"
serde_derive = "1.0.145"
syntect = "5.0.0"
tar = "0.4.38"
toml = "0.5.9"
unix_mode = "0.1.3"

A src/git/get_all.rs +37 -0
@@ 0,0 1,37 @@

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

use std::path::PathBuf;

pub fn files(repo: String, branch: String, path: String) -> Option<Vec<String>> {
    if branch.contains(":") {
        return None;
    }
    let mut repo_path = CONFIG.git_location.clone();
    repo_path.push(format!("{}.git", repo));
    let repo_clone = repo.clone();
    let repo = git2::Repository::open(repo_path).ok()?;
    let obj = repo.revparse_single(&format!("{}:{}", branch, path)).ok()?;
    let mut returns = Vec::new();
    match obj.kind() {
        Some(ObjectType::Tree) => {
            let tree = obj.as_tree()?;
            for entry in tree.iter() {
                if entry.kind() == Some(ObjectType::Blob) {
                    returns.push(format!("{}{}", path, entry.name()?));
                }
                else {
                    for i in files(repo_clone.clone(), branch.clone(), format!("{}{}/", path, entry.name()?))? {
                        returns.push(i);
                    }
                }
            }
        }
        _ => {
            return None;
        }
    }
    Some(returns)
}

M src/git/mod.rs => src/git/mod.rs +1 -0
@@ 6,3 6,4 @@ pub mod file;

pub mod main_branch;
pub mod repos;
pub mod tag;
pub mod get_all;

M src/main.rs => src/main.rs +3 -1
@@ 18,6 18,7 @@ use crate::repository::raw;

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


@@ 41,7 42,8 @@ fn rocket() -> _ {

                commit::commit,
                commit::patch,
                refs::refs,
                refs::refs_id
                refs::refs_id,
                archive::archive
            ],
        )
        .attach(Template::fairing())

A src/repository/archive.rs +36 -0
@@ 0,0 1,36 @@

use crate::config::CONFIG;
use crate::git::get_all::files;
use tar::{Builder, Header};
use rocket::response::stream::ByteStream;
use rocket::futures::stream::{repeat, StreamExt};
use rocket::tokio::time::{self, Duration};

#[get("/<repo>/archive/<oid>", rank = 2)]
pub fn archive(repo: String, oid: String) -> ByteStream![Vec<u8>] {
    ByteStream! {
        let oid = oid[..oid.len()-7].to_string();
        let files = files(repo.clone(), oid.clone(), "".to_string()).unwrap();
        for i in files { 
            match get_tar(repo.clone(), oid.clone(), i) {
                Some(x) => yield x[..x.len()-1024].to_vec(),
                None => {},
            }
        }
        yield vec![0;1024]
    }
}

fn get_tar(repo: String, oid: String, path: String) -> Option<Vec<u8>> {
    let mut repo_path = CONFIG.git_location.clone();
    repo_path.push(format!("{}.git", repo));
    let repo_clone = repo.clone();
    let repo = git2::Repository::open(repo_path).unwrap();
    let obj = repo.revparse_single(&format!("{}:{}", oid, path)).ok()?;
    let blob = obj.as_blob()?;
    let mut header = Header::new_gnu();
    header.set_size(blob.size() as u64);
    header.set_cksum();
    let mut ar = Builder::new(Vec::new());
    ar.append_data(&mut header, format!("{}/{}", repo_clone, path), blob.content()).unwrap();
    Some(ar.into_inner().ok()?)
}

M src/repository/mod.rs => src/repository/mod.rs +1 -0
@@ 5,3 5,4 @@ pub mod raw;

pub mod refs;
pub mod summary;
pub mod tree;
pub mod archive;