Files
rgit/src/git_fs/mod.rs
T
2026-03-11 17:49:08 +01:00

92 lines
2.0 KiB
Rust

use anyhow::{Result, bail};
use std::{
fs::File,
io::{self, BufRead, prelude::*},
path::{Path, PathBuf},
};
use crate::GIT_DIR;
pub mod gitignore;
pub mod head;
pub mod index;
pub mod object;
fn read_lines<P>(filename: P) -> Result<io::Lines<io::BufReader<File>>>
where
P: AsRef<Path>,
{
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
pub fn normalize_path_in_worktree(path: &Path) -> Result<PathBuf> {
let wt_root = get_worktree_root()?;
let canon = path.canonicalize()?;
let mut canon_it = canon.components();
for wt_c in wt_root.components() {
if let Some(c) = canon_it.next()
&& wt_c == c
{
continue;
} else {
bail!(
"'{}' is outside repository at '{}'",
path.display(),
wt_root.display()
);
}
}
Ok(canon_it.as_path().to_path_buf())
}
pub fn get_worktree_root() -> Result<PathBuf> {
let canon = Path::new(".").canonicalize()?;
for ancestor in canon.ancestors() {
let potential = ancestor.join(GIT_DIR);
if potential.is_dir() {
return Ok(ancestor.to_path_buf());
}
}
bail!("not a git repository (or any parent up to mount point)")
}
pub fn get_git_root() -> Result<PathBuf> {
Ok(get_worktree_root()?.join(GIT_DIR))
}
pub struct Ref {
ref_name: String,
commit_hash: String,
}
impl Ref {
pub fn load(name: String) -> Result<Self> {
let path = get_git_root()?.join(&name);
let mut lines = read_lines(path)?;
let content = match lines.next() {
Some(line) => line?,
_ => bail!(""),
};
Ok(Ref {
ref_name: name,
commit_hash: content,
})
}
pub fn save(&self) -> Result<()> {
let path = get_git_root()?.join("refs").join(&self.ref_name);
let mut file = File::create(&path)?;
file.write_all(self.commit_hash.as_bytes())?;
Ok(())
}
}