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;