async_git/plumbing/
object.rs1use std::path::PathBuf;
2
3use std::str::FromStr;
4
5use futures::io::BufReader as FBufReader;
6use tokio::{
7 fs::File,
8 io::{AsyncBufReadExt, BufReader as TBufReader},
9};
10
11use crate::errors::{Error, Result};
12use crate::plumbing::Commit;
13use crate::util::{self, FuckYouTokio, ZlibDecoder};
14
15#[derive(Debug)]
16pub struct Object {
17 pub(crate) repo_path: PathBuf,
18 pub(crate) id: Oid,
19}
20
21impl Object {
22 pub fn get_path_on_disk(&self) -> PathBuf {
23 let first_byte = format!("{:02x}", self.id.0[0]);
24 let rest = util::hexlify(&self.id.0[1..]);
25 self.repo_path.join("objects").join(first_byte).join(rest)
26 }
27
28 pub async fn peel(&self) -> Result<ParsedObject> {
29 let file = File::open(self.get_path_on_disk()).await?;
30 let fuck_you_tokio = FuckYouTokio(file);
31 let reader = FBufReader::new(fuck_you_tokio);
32 let mut r = TBufReader::new(FuckYouTokio(ZlibDecoder::new(reader)));
33
34 let mut first_word = vec![];
36 r.read_until(b' ', &mut first_word).await?;
37 let first_word = String::from_utf8(first_word)?;
38
39 Ok(match first_word.as_ref() {
40 "commit " => ParsedObject::Commit(Commit::parse(r).await?),
41 _ => return Err(Error::BadGitObjectType(first_word)),
42 })
43 }
44}
45
46#[derive(Clone, Debug)]
47pub struct Oid([u8; 20]);
48
49impl FromStr for Oid {
50 type Err = Error;
51
52 fn from_str(string: &str) -> Result<Self, Self::Err> {
53 let mut buffer = [0; 20];
54 let bytes = string.as_bytes();
55
56 let len = bytes.len();
57 if len != 40 {
58 return Err(Error::ObjectIdWrongLength(len));
59 }
60
61 let byte_conv = |byte: u8| -> Result<u8, Self::Err> {
62 Ok(match byte {
63 b'0' => 0,
64 b'1' => 1,
65 b'2' => 2,
66 b'3' => 3,
67 b'4' => 4,
68 b'5' => 5,
69 b'6' => 6,
70 b'7' => 7,
71 b'8' => 8,
72 b'9' => 9,
73 b'a' => 10,
74 b'b' => 11,
75 b'c' => 12,
76 b'd' => 13,
77 b'e' => 14,
78 b'f' => 15,
79 _ => return Err(Error::InvalidHexByte(byte)),
80 })
81 };
82
83 let mut ctr = 0;
84 for window in string.as_bytes().chunks(2) {
85 if let &[first, second] = window {
86 let first_byte = byte_conv(first)?;
87 let second_byte = byte_conv(second)?;
88 buffer[ctr] = first_byte << 4 | second_byte;
89 ctr += 1;
90 }
91 }
92
93 Ok(Oid(buffer))
94 }
95}
96
97#[derive(Debug)]
98pub enum ParsedObject {
99 Blob,
100 Commit(Commit),
101 Tag,
102 Tree,
103}