consolidate git operations into a Repo type

This commit is contained in:
2026-10-03 12:46:44 +07:00
parent 4656f1340b
commit 49d351fe06
21 changed files with 2243 additions and 2203 deletions
+34 -40
View File
@@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use signed_core::{Announcement, RepoAddr};
use crate::remote::{clone_repo, fetch_all};
use crate::repo::Repo;
/// On-disk cache of cloned repositories, keyed by owner pubkey / repo id.
#[derive(Debug, Clone)]
@@ -23,13 +23,13 @@ impl GitCache {
pub fn repo_path(&self, addr: &RepoAddr) -> PathBuf {
self.root
.join(addr.public_key().to_hex())
.join(sanitize_path_component(addr.identifier()))
.join(Self::sanitize_path_component(addr.identifier()))
}
pub fn open(&self, addr: &RepoAddr) -> Result<Option<gix::Repository>> {
pub fn open(&self, addr: &RepoAddr) -> Result<Option<Repo>> {
let path = self.repo_path(addr);
match gix::open(&path) {
Ok(repo) => Ok(Some(repo)),
Ok(repo) => Ok(Some(Repo { inner: repo })),
Err(gix::open::Error::NotARepository { .. }) => Ok(None),
Err(gix::open::Error::Io(e)) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(e) => Err(e.into()),
@@ -37,15 +37,11 @@ impl GitCache {
}
/// Open the existing clone, fetching it first.
pub fn ensure_clone<U: AsRef<str>>(
&self,
addr: &RepoAddr,
clone_urls: &[U],
) -> Result<gix::Repository> {
pub fn ensure_clone<U: AsRef<str>>(&self, addr: &RepoAddr, clone_urls: &[U]) -> Result<Repo> {
let path = self.repo_path(addr);
if let Some(repo) = self.open(addr)? {
fetch_all(&repo).ok();
repo.fetch().ok();
return Ok(repo);
}
@@ -54,37 +50,35 @@ impl GitCache {
.with_context(|| format!("failed to create {}", parent.display()))?;
}
clone_repo(clone_urls, &path)?;
self.open(addr)?
.ok_or_else(|| anyhow::anyhow!("clone finished but the repository cannot be opened"))
}
}
/// Map an untrusted repository id or display name to a safe single path component.
pub fn sanitize_path_component(id: &str) -> String {
let sanitized: String = id
.chars()
.map(|c| {
if c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '.') {
c
} else {
'_'
}
})
.collect();
if sanitized == "." || sanitized == ".." {
return "_".to_owned();
Repo::clone(clone_urls, &path)
}
sanitized
}
/// Map an untrusted repository id or display name to a safe single path component.
pub fn sanitize_path_component(id: &str) -> String {
let sanitized: String = id
.chars()
.map(|c| {
if c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '.') {
c
} else {
'_'
}
})
.collect();
/// The refs namespace of a fork's import in the target mirror.
pub fn fork_namespace(announcement: &Announcement) -> String {
format!(
"{}/{}",
announcement.owner.to_hex(),
sanitize_path_component(&announcement.id)
)
if sanitized == "." || sanitized == ".." {
return "_".to_owned();
}
sanitized
}
/// The refs namespace of a fork's import in the target mirror.
pub fn fork_namespace(announcement: &Announcement) -> String {
format!(
"{}/{}",
announcement.owner.to_hex(),
Self::sanitize_path_component(&announcement.id)
)
}
}