feat(server): add tracing spans and caching to archive and blame services
- Add tracing spans with repo labels for archive and blame operations - Implement caching for archive list entries when using OID selectors - Implement caching for blame operations when using OID selectors - Add detailed
This commit is contained in:
@@ -3,14 +3,24 @@ use std::path::{Path, PathBuf};
|
||||
use crate::error::{GitError, GitResult};
|
||||
use crate::pb::RepositoryHeader;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GitBare {
|
||||
pub bare_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl GitBare {
|
||||
pub fn new(bare_dir: PathBuf) -> Self {
|
||||
Self { bare_dir }
|
||||
}
|
||||
|
||||
/// Open the gix repository. Callers should open once per logical operation
|
||||
/// and reuse the handle for all gix lookups within that operation.
|
||||
pub fn gix_repo(&self) -> GitResult<gix::Repository> {
|
||||
gix::open(&self.bare_dir)
|
||||
.map_err(|e| GitError::Internal(format!("failed to open gix repository: {e}")))
|
||||
tracing::debug!(repo = %self.bare_dir.display(), "opening gix repository");
|
||||
gix::open(&self.bare_dir).map_err(|e| {
|
||||
tracing::error!(repo = %self.bare_dir.display(), error = %e, "failed to open gix repository");
|
||||
GitError::Internal(format!("failed to open gix repository: {e}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_repository_header(header: &RepositoryHeader) -> GitResult<Self> {
|
||||
@@ -47,6 +57,11 @@ impl GitBare {
|
||||
// Path traversal check: canonical resolved dir must start with base
|
||||
let base_canon = base.canonicalize().unwrap_or_else(|_| base.clone());
|
||||
if !canonical.starts_with(&base_canon) {
|
||||
tracing::warn!(
|
||||
relative_path = %relative_path,
|
||||
base = %base_canon.display(),
|
||||
"path traversal attempt detected"
|
||||
);
|
||||
return Err(GitError::InvalidArgument(format!(
|
||||
"path traversal detected: {relative_path} escapes storage root"
|
||||
)));
|
||||
@@ -60,6 +75,7 @@ impl GitBare {
|
||||
|
||||
// Validate bare_dir exists, is a directory, and is readable
|
||||
if !bare_dir.exists() {
|
||||
tracing::warn!(path = %bare_dir.display(), "repository not found");
|
||||
return Err(GitError::RepoNotFound);
|
||||
}
|
||||
if !bare_dir.is_dir() {
|
||||
@@ -75,6 +91,7 @@ impl GitBare {
|
||||
// Maybe it's a non-bare repo
|
||||
let git_dir = bare_dir.join(".git");
|
||||
if git_dir.is_dir() && git_dir.join("HEAD").exists() {
|
||||
tracing::debug!(path = %git_dir.display(), "resolved non-bare repo via .git subdir");
|
||||
return Ok(Self { bare_dir: git_dir });
|
||||
}
|
||||
return Err(GitError::NotBareRepository);
|
||||
@@ -87,6 +104,7 @@ impl GitBare {
|
||||
pub fn object_format(&self) -> crate::pb::ObjectFormat {
|
||||
let repo = self.gix_repo().ok();
|
||||
let kind = repo
|
||||
.as_ref()
|
||||
.map(|r| r.object_hash())
|
||||
.unwrap_or(gix::hash::Kind::Sha1);
|
||||
match kind {
|
||||
|
||||
Reference in New Issue
Block a user