159 lines
4.9 KiB
Rust
159 lines
4.9 KiB
Rust
//! Copyright (c) 2022-2026 GitDataAi All rights reserved.
|
|
|
|
//! Tests for snapshot operations.
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use gitks::snapshot::ops::{create_snapshot, restore_snapshot};
|
|
use gitks::snapshot::storage::{LocalSnapshotStorage, SnapshotStorageBackend};
|
|
|
|
fn temp_bare_repo() -> PathBuf {
|
|
let dir = tempfile::tempdir().unwrap().path().to_path_buf();
|
|
let result = std::process::Command::new("git")
|
|
.args(["init", "--bare"])
|
|
.arg(&dir)
|
|
.output()
|
|
.expect("git init --bare should work");
|
|
assert!(result.status.success());
|
|
|
|
// Create an initial commit so HEAD exists
|
|
// We need a working tree to create a commit, so we create one temporarily
|
|
let work_dir = tempfile::tempdir().unwrap().path().to_path_buf();
|
|
let result2 = std::process::Command::new("git")
|
|
.args(["init"])
|
|
.arg(&work_dir)
|
|
.output()
|
|
.expect("git init should work");
|
|
assert!(result2.status.success());
|
|
|
|
// Create a file and commit
|
|
std::fs::write(work_dir.join("test.txt"), "hello world").unwrap();
|
|
let result3 = std::process::Command::new("git")
|
|
.args(["add", "test.txt"])
|
|
.current_dir(&work_dir)
|
|
.output();
|
|
let _ = result3;
|
|
|
|
let result4 = std::process::Command::new("git")
|
|
.args(["commit", "-m", "initial commit"])
|
|
.env("GIT_AUTHOR_NAME", "test")
|
|
.env("GIT_AUTHOR_EMAIL", "test@test.com")
|
|
.env("GIT_COMMITTER_NAME", "test")
|
|
.env("GIT_COMMITTER_EMAIL", "test@test.com")
|
|
.current_dir(&work_dir)
|
|
.output();
|
|
let _ = result4;
|
|
|
|
// Push to bare repo
|
|
let result5 = std::process::Command::new("git")
|
|
.args(["push", &dir.to_string_lossy(), "master:refs/heads/master"])
|
|
.current_dir(&work_dir)
|
|
.output();
|
|
let _ = result5;
|
|
|
|
dir
|
|
}
|
|
|
|
#[test]
|
|
fn test_snapshot_create_and_restore() {
|
|
let repo = temp_bare_repo();
|
|
let gb = gitks::bare::GitBare::new(repo.clone());
|
|
|
|
// Create snapshot
|
|
let result = create_snapshot(&gb);
|
|
if let Ok(data) = result {
|
|
assert!(!data.is_empty());
|
|
|
|
// Restore to a different location
|
|
let target = tempfile::tempdir().unwrap().path().to_path_buf();
|
|
// Initialize target as bare repo first
|
|
let init_result = std::process::Command::new("git")
|
|
.args(["init", "--bare"])
|
|
.arg(&target)
|
|
.output();
|
|
if let Ok(init_output) = init_result
|
|
&& init_output.status.success()
|
|
{
|
|
let restore_result = restore_snapshot(&target, &data);
|
|
// May succeed or fail depending on git bundle compatibility
|
|
let _ = restore_result;
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_local_snapshot_storage_write_and_read() {
|
|
let dir = tempfile::tempdir().unwrap().path().to_path_buf();
|
|
let storage = LocalSnapshotStorage::new(dir);
|
|
|
|
// Write snapshot
|
|
let result = storage.write_snapshot("snap001", "test.git", "abc123", b"bundle_data");
|
|
assert!(result.is_ok());
|
|
|
|
// Read snapshot
|
|
let result = storage.read_snapshot("snap001");
|
|
assert!(result.is_ok());
|
|
assert_eq!(result.unwrap(), b"bundle_data".to_vec());
|
|
|
|
// Read non-existent
|
|
let result = storage.read_snapshot("nonexistent");
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_local_snapshot_storage_list() {
|
|
let dir = tempfile::tempdir().unwrap().path().to_path_buf();
|
|
let storage = LocalSnapshotStorage::new(dir);
|
|
|
|
// Write two snapshots
|
|
storage
|
|
.write_snapshot("snap001", "repo1.git", "abc123", b"data1")
|
|
.unwrap();
|
|
storage
|
|
.write_snapshot("snap002", "repo2.git", "def456", b"data2")
|
|
.unwrap();
|
|
|
|
// List all
|
|
let result = storage.list_snapshots("");
|
|
assert!(result.is_ok());
|
|
assert_eq!(result.unwrap().len(), 2);
|
|
|
|
// List filtered
|
|
let result = storage.list_snapshots("repo1.git");
|
|
assert!(result.is_ok());
|
|
let snapshots = result.unwrap();
|
|
assert_eq!(snapshots.len(), 1);
|
|
assert_eq!(snapshots[0].relative_path, "repo1.git");
|
|
}
|
|
|
|
#[test]
|
|
fn test_local_snapshot_storage_delete() {
|
|
let dir = tempfile::tempdir().unwrap().path().to_path_buf();
|
|
let storage = LocalSnapshotStorage::new(dir);
|
|
|
|
storage
|
|
.write_snapshot("snap001", "test.git", "abc123", b"data")
|
|
.unwrap();
|
|
assert!(storage.read_snapshot("snap001").is_ok());
|
|
|
|
storage.delete_snapshot("snap001").unwrap();
|
|
assert!(storage.read_snapshot("snap001").is_err());
|
|
|
|
// Delete non-existent
|
|
assert!(storage.delete_snapshot("nonexistent").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_local_snapshot_storage_rejects_traversal_id() {
|
|
let dir = tempfile::tempdir().unwrap().path().to_path_buf();
|
|
let storage = LocalSnapshotStorage::new(dir);
|
|
|
|
assert!(storage.read_snapshot("../escape").is_err());
|
|
assert!(storage.delete_snapshot("../escape").is_err());
|
|
assert!(
|
|
storage
|
|
.write_snapshot("../escape", "repo.git", "abc123", b"data")
|
|
.is_err()
|
|
);
|
|
}
|