Files
gitks/pack/list_packfiles.rs
T
zhenyi 10a4398e81 refactor(bare): enhance security and performance optimizations
- Remove unnecessary sorting in advertise_refs for deterministic output
- Add path traversal detection and validation in bare_dir construction
- Implement symlink resolution checks to prevent security vulnerabilities
- Refactor cache system with CRC validation and improved metrics
- Integrate repo-specific cache invalidation using indexed keys
- Add comprehensive unit tests for commit operations and diff functionality
- Move configuration constants to centralized config module
- Optimize string operations in disk cache random value generation
- Enhance license detection algorithm with cleaner matching logic
- Streamline argument processing in various git operations
- Update dependencies including crc32fast and flate2 for performance
- Add signal handling capability to tokio runtime configuration
2026-06-12 15:04:12 +08:00

92 lines
3.8 KiB
Rust

use crate::bare::GitBare;
use crate::error::GitError;
use crate::paginate;
use crate::pb::{ListPackfilesRequest, ListPackfilesResponse, PackfileInfo};
impl GitBare {
pub fn list_packfiles(
&self,
request: ListPackfilesRequest,
) -> crate::error::GitResult<ListPackfilesResponse> {
let pack_dir = self.bare_dir.join("objects").join("pack");
let mut packfiles = Vec::new();
if pack_dir.exists() {
for entry in std::fs::read_dir(&pack_dir).map_err(GitError::Io)? {
let entry = entry.map_err(GitError::Io)?;
let name = entry.file_name().to_string_lossy().into_owned();
if !name.ends_with(".pack") {
continue;
}
let metadata = entry.metadata().map_err(GitError::Io)?;
let base_name = name.trim_end_matches(".pack");
let idx_name = format!("{base_name}.idx");
let bmp_name = format!("{base_name}.bitmap");
let rev_name = format!("{base_name}.rev");
let keep_name = format!("{base_name}.keep");
let pack_hash = base_name
.strip_prefix("pack-")
.filter(|hex| !hex.is_empty())
.map(|hex| self.oid_to_pb(hex));
let mut object_count = 0u64;
if let Some(hash_str) = base_name.strip_prefix("pack-") {
let idx_path = pack_dir.join(format!("pack-{hash_str}.idx"));
if idx_path.exists() {
let verify = duct::cmd(
"git",
[
"--git-dir",
self.bare_dir.to_string_lossy().as_ref(),
"verify-pack",
"-v",
idx_path.to_string_lossy().as_ref(),
],
)
.stdout_capture()
.stderr_capture()
.unchecked()
.run();
if let Ok(v) = verify {
let out = String::from_utf8_lossy(&v.stdout);
object_count = out
.lines()
.filter(|l| {
let parts: Vec<&str> = l.split_whitespace().collect();
parts.len() >= 3
&& parts
.first()
.map(|s| s.len() == 40 || s.len() == 64)
.unwrap_or(false)
})
.count() as u64;
}
}
}
packfiles.push(PackfileInfo {
name,
pack_hash,
size_bytes: metadata.len(),
index_size_bytes: pack_dir
.join(&idx_name)
.metadata()
.map(|m| m.len())
.unwrap_or(0),
object_count,
has_bitmap: pack_dir.join(&bmp_name).exists(),
has_rev_index: pack_dir.join(&rev_name).exists(),
kept: pack_dir.join(&keep_name).exists(),
});
}
}
packfiles.sort_by(|a, b| a.name.cmp(&b.name));
let (packfiles, page_info) = paginate::paginate(&packfiles, request.pagination.as_ref());
Ok(ListPackfilesResponse {
packfiles,
page_info: Some(page_info),
})
}
}