Skip to main content

dk_engine/git/
objects.rs

1use std::path::Path;
2
3use dk_core::{Error, Result};
4
5/// Provides read/write access to Git objects (blobs) and working tree files
6/// through a borrowed reference to a [`super::GitRepository`].
7pub struct GitObjects<'a> {
8    repo: &'a super::GitRepository,
9}
10
11impl<'a> GitObjects<'a> {
12    /// Create a new `GitObjects` handle tied to the given repository.
13    pub fn new(repo: &'a super::GitRepository) -> Self {
14        Self { repo }
15    }
16
17    /// Write a blob to the Git object store and return its OID as a hex string.
18    pub fn write_blob(&self, data: &[u8]) -> Result<String> {
19        let id = self.repo.inner().write_blob(data).map_err(|e| {
20            Error::Git(format!("failed to write blob: {}", e))
21        })?;
22        Ok(id.to_hex().to_string())
23    }
24
25    /// Read a blob from the Git object store by its OID hex string.
26    ///
27    /// Returns an error if the OID is invalid, the object is not found,
28    /// or the object is not a blob.
29    pub fn read_blob(&self, oid_hex: &str) -> Result<Vec<u8>> {
30        let oid = gix::ObjectId::from_hex(oid_hex.as_bytes()).map_err(|e| {
31            Error::Git(format!("invalid OID '{}': {}", oid_hex, e))
32        })?;
33
34        let object = self.repo.inner().find_object(oid).map_err(|e| {
35            Error::Git(format!("object not found '{}': {}", oid_hex, e))
36        })?;
37
38        if object.kind != gix::object::Kind::Blob {
39            return Err(Error::Git(format!(
40                "object '{}' is not a blob (found {:?})",
41                oid_hex, object.kind
42            )));
43        }
44
45        Ok(object.data.to_vec())
46    }
47
48    /// Read a file from the working tree, relative to the repository root.
49    pub fn read_file(&self, file_path: &Path) -> Result<Vec<u8>> {
50        let full_path = self.repo.path().join(file_path);
51        std::fs::read(&full_path).map_err(|e| {
52            Error::Git(format!("failed to read file {}: {}", full_path.display(), e))
53        })
54    }
55
56    /// Write a file to the working tree, relative to the repository root.
57    ///
58    /// Creates parent directories as needed.
59    pub fn write_file(&self, file_path: &Path, content: &[u8]) -> Result<()> {
60        let full_path = self.repo.path().join(file_path);
61
62        if let Some(parent) = full_path.parent() {
63            std::fs::create_dir_all(parent).map_err(|e| {
64                Error::Git(format!(
65                    "failed to create parent dirs for {}: {}",
66                    full_path.display(),
67                    e
68                ))
69            })?;
70        }
71
72        std::fs::write(&full_path, content).map_err(|e| {
73            Error::Git(format!("failed to write file {}: {}", full_path.display(), e))
74        })
75    }
76}