~/selfhut

selfhut/src/git/file.rs -rw-r--r-- 3.33 kB
0016c2cc — arthurmelton clippy 2 years ago
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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<File>> {
    if branch.contains(':') {
        return None;
    }
    let mut repo_path = CONFIG.git_location.clone();
    repo_path.push(format!("{}.git", repo));
    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() {
                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,
                    },
                    file_type: match entry.kind() {
                        Some(ObjectType::Blob) => FileType::blob,
                        _ => FileType::tree,
                    },
                    properties: unix_mode::to_string(entry.filemode() as u32),
                    properties_int: entry.filemode(),
                })
            }
        }
        _ => {
            return None;
        }
    }
    Some(returns)
}

pub fn file(repo: String, branch: String, path: String) -> Option<(File, Option<String>, Vec<u8>)> {
    if branch.contains(':') {
        return None;
    }
    let mut repo_path = CONFIG.git_location.clone();
    repo_path.push(format!("{}.git", repo));
    let repo = git2::Repository::open(repo_path).ok()?;
    let obj = repo.revparse_single(&format!("{}:{}", branch, path)).ok()?;
    match obj.kind() {
        Some(ObjectType::Blob) => {
            let blob = obj.as_blob()?;
            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 = tree.as_tree()?;
            let tree_item = tree.get_id(blob.id())?;
            let file = File {
                name: tree_item.name()?.to_string(),
                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(),
            };
            let content = match blob.is_binary() {
                false => Some(String::from_utf8_lossy(blob.content()).into_owned()),
                true => None,
            };
            return Some((file, content, blob.content().iter().map(|x| *x).collect()));
        }
        _ => None
    }
}

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

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