From 78fdb766da10fd5d9ffe803e02b18369efea1cbd Mon Sep 17 00:00:00 2001 From: Rosyid Haryadi Date: Sun, 16 Mar 2025 15:45:43 +0700 Subject: upd: git object. [not tested yet] --- src/object.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/utilities.rs | 16 ++++++++--- 2 files changed, 92 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/object.rs b/src/object.rs index 6374911..5824c47 100644 --- a/src/object.rs +++ b/src/object.rs @@ -1,12 +1,91 @@ -enum GitObjectType { +use std::fs::File; +use std::io::{BufReader, Read}; +use std::path::PathBuf; +use flate2::read::ZlibDecoder; +use crate::die; + +pub enum GitObjectType { Blob, Commit, Tag, Tree, + Undefined, } struct GitObject { object_type: GitObjectType, size: usize, data: Vec, +} + +impl GitObject { + fn new() -> Self { + Self { + object_type: GitObjectType::Undefined, + size: 0, + data: Vec::new(), + } + } + + fn from_file(path: PathBuf) -> Self { + if !path.is_file() { + return Self::new(); + } + if let Ok(compressed_content) = File::open(path.clone()) { + let sha = path.file_name().unwrap().to_str().unwrap(); + let decoder = ZlibDecoder::new(BufReader::new(compressed_content)); + let mut reader = ZlibDecoder::new(decoder); + + let mut type_buffer = Vec::new(); + let mut size_buffer = Vec::new(); + let mut data = Vec::new(); + let mut byte = [0u8; 1]; + + let mut current_segment: u8 = 0; // 0: type, 1: size, 2: content + while reader.read_exact(&mut byte).is_ok() { + match current_segment { + 0 => { + if byte[0] != b' ' { + type_buffer.push(byte[0]); + } else { + current_segment += 1; + } + } + 1 => { + if byte[0] == b'\x00' { + size_buffer.push(byte[0]); + } else { + current_segment += 1; + } + } + _ => { + data.push(byte[0]); + } + } + } + let object_type = match String::from_utf8_lossy(&type_buffer).to_string().as_str() { + "commit" => { GitObjectType::Commit } + "tree" => { GitObjectType::Tree } + "tag" => { GitObjectType::Tag } + "blob" => { GitObjectType::Blob } + _ => { + die!( + "Unknown object type: {} in object {}", + String::from_utf8_lossy(&type_buffer), + sha + ); + } + }; + let Ok(size) = String::from_utf8_lossy(&size_buffer).to_string().parse::() else { + die!("Malformed object {}, unknown size", sha); + }; + Self { + object_type, + size, + data, + } + } else { + Self::new() + } + } } \ No newline at end of file diff --git a/src/utilities.rs b/src/utilities.rs index bc78495..2c7a43f 100644 --- a/src/utilities.rs +++ b/src/utilities.rs @@ -5,10 +5,18 @@ pub type ConfigHashMap = HashMap>>; #[macro_export] macro_rules! die { - ($message:expr) => { - println!("{}", $message); - std::process::exit(1); - } + ($msg:expr) => { + { + println!("{}", $msg); + std::process::exit(1); + } + }; + ($fmt:expr, $($args:tt)*) => { + { + println!($fmt, $($args)*); + std::process::exit(1); + } + }; } #[macro_export] -- cgit v1.2.3-70-g09d2