d243dce027
- Replaced manual remote client functions with remote_client! macro for archive, blame, branch, commit, and diff services - Simplified remote client creation logic using declarative macro approach - Maintained same functionality while reducing code duplication across services security(bare): enhance path traversal protection with comprehensive validation - Added early relative_path validation to prevent path traversal attacks - Implemented unified path validation to avoid TOCTOU race conditions - Enhanced canonicalization checks for both existing and non-existent paths - Added detailed logging for path traversal detection attempts feat(cache): migrate from CLruCache to Moka with TTL and invalidation support - Replaced clru dependency with moka for improved caching capabilities - Added 300-second time-to-live for cache entries - Implemented repository-specific cache invalidation mechanism - Enhanced cache operations with thread-safe async support refactor(commit): improve security validation for commit operations - Added ref name validation to prevent command injection in cherry_pick_commit - Implemented revision validation for commit selectors - Added comprehensive input validation for create_commit parameters - Enhanced file path validation to prevent traversal
175 lines
4.7 KiB
Rust
175 lines
4.7 KiB
Rust
use gitks::bare::GitBare;
|
|
use gitks::server::GitksService;
|
|
|
|
#[allow(dead_code)]
|
|
pub fn setup_service(dir: &std::path::Path) -> GitksService {
|
|
GitksService::new(dir.to_path_buf())
|
|
}
|
|
|
|
pub fn run_git(work_dir: &std::path::Path, args: &[&str]) -> duct::Expression {
|
|
duct::cmd("git", {
|
|
let work_str = work_dir.to_string_lossy().into_owned();
|
|
let mut v: Vec<String> = vec!["-C".into(), work_str];
|
|
v.extend(args.iter().map(|s| s.to_string()));
|
|
v
|
|
})
|
|
.env("GIT_AUTHOR_NAME", "Test")
|
|
.env("GIT_AUTHOR_EMAIL", "test@example.com")
|
|
.env("GIT_COMMITTER_NAME", "Test")
|
|
.env("GIT_COMMITTER_EMAIL", "test@example.com")
|
|
}
|
|
|
|
pub fn run(work_dir: &std::path::Path, args: &[&str]) {
|
|
let result = run_git(work_dir, args)
|
|
.stdout_capture()
|
|
.stderr_capture()
|
|
.unchecked()
|
|
.run()
|
|
.unwrap();
|
|
assert!(
|
|
result.status.success(),
|
|
"git {} failed: {}",
|
|
args.join(" "),
|
|
String::from_utf8_lossy(&result.stderr)
|
|
);
|
|
}
|
|
|
|
pub fn setup_bare_repo() -> (tempfile::TempDir, GitBare) {
|
|
let dir = tempfile::tempdir().expect("create temp dir");
|
|
let bare_dir = dir.path().join("test-repo");
|
|
|
|
duct::cmd(
|
|
"git",
|
|
["init", "--bare", bare_dir.to_string_lossy().as_ref()],
|
|
)
|
|
.run()
|
|
.expect("git init --bare");
|
|
|
|
let work_dir = dir.path().join("work");
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"clone",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
work_dir.to_string_lossy().as_ref(),
|
|
],
|
|
)
|
|
.run()
|
|
.expect("clone");
|
|
|
|
run(&work_dir, &["checkout", "-b", "main"]);
|
|
|
|
std::fs::write(work_dir.join("README.md"), "# Test\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "initial commit"]);
|
|
|
|
run(&work_dir, &["branch", "feature"]);
|
|
|
|
std::fs::write(work_dir.join("src.txt"), "source\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "second commit"]);
|
|
|
|
std::fs::write(work_dir.join("README.md"), "# Test\n\nUpdated.\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "third commit"]);
|
|
|
|
std::fs::create_dir_all(work_dir.join("src/lib")).unwrap();
|
|
std::fs::write(work_dir.join("src/lib/mod.rs"), "pub fn hello() {}\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "add nested file"]);
|
|
|
|
run(&work_dir, &["tag", "v0.1.0"]);
|
|
|
|
run(
|
|
&work_dir,
|
|
&["push", "-f", "origin", "main:main", "feature:feature"],
|
|
);
|
|
run(
|
|
&work_dir,
|
|
&["push", "-f", "origin", "refs/tags/v0.1.0:refs/tags/v0.1.0"],
|
|
);
|
|
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"--git-dir",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
"symbolic-ref",
|
|
"HEAD",
|
|
"refs/heads/main",
|
|
],
|
|
)
|
|
.run()
|
|
.expect("set HEAD to main");
|
|
|
|
(dir, GitBare::new(bare_dir))
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn setup_bare_repo_with_conflict() -> (tempfile::TempDir, GitBare) {
|
|
let dir = tempfile::tempdir().expect("create temp dir");
|
|
let bare_dir = dir.path().join("test-repo");
|
|
|
|
duct::cmd(
|
|
"git",
|
|
["init", "--bare", bare_dir.to_string_lossy().as_ref()],
|
|
)
|
|
.run()
|
|
.expect("git init --bare");
|
|
|
|
let work_dir = dir.path().join("work");
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"clone",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
work_dir.to_string_lossy().as_ref(),
|
|
],
|
|
)
|
|
.run()
|
|
.expect("clone");
|
|
|
|
run(&work_dir, &["checkout", "-b", "main"]);
|
|
std::fs::write(work_dir.join("file.txt"), "base content\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "base commit"]);
|
|
|
|
run(&work_dir, &["checkout", "-b", "branch-a"]);
|
|
std::fs::write(work_dir.join("file.txt"), "branch A content\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "branch A change"]);
|
|
|
|
run(&work_dir, &["checkout", "main"]);
|
|
run(&work_dir, &["checkout", "-b", "branch-b"]);
|
|
std::fs::write(work_dir.join("file.txt"), "branch B content\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "branch B change"]);
|
|
|
|
run(
|
|
&work_dir,
|
|
&[
|
|
"push",
|
|
"-f",
|
|
"origin",
|
|
"main:main",
|
|
"branch-a:branch-a",
|
|
"branch-b:branch-b",
|
|
],
|
|
);
|
|
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"--git-dir",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
"symbolic-ref",
|
|
"HEAD",
|
|
"refs/heads/main",
|
|
],
|
|
)
|
|
.run()
|
|
.expect("set HEAD to main");
|
|
|
|
(dir, GitBare::new(bare_dir))
|
|
}
|