Add a centralized ui module with Arc's visual identity: colored commit IDs (magenta), bookmarks (cyan), tags (yellow), status symbols, and diff highlighting. Update all command output and tests accordingly.
215 lines
5.8 KiB
Rust
215 lines
5.8 KiB
Rust
use std::process::Command;
|
|
use tempfile::TempDir;
|
|
|
|
fn arc_cmd() -> Command {
|
|
let mut cmd = Command::new(env!("CARGO_BIN_EXE_arc"));
|
|
cmd.env("NO_COLOR", "1");
|
|
cmd
|
|
}
|
|
|
|
fn init_repo() -> TempDir {
|
|
let dir = TempDir::new().unwrap();
|
|
arc_cmd()
|
|
.arg("init")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to init");
|
|
dir
|
|
}
|
|
|
|
#[test]
|
|
fn ignore_matches_arc_directory() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("real.txt"), "data\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.arg("status")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(!stdout.contains(".arc"));
|
|
assert!(stdout.contains("real.txt"));
|
|
}
|
|
|
|
#[test]
|
|
fn ignore_directory_pattern() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join(".arcignore"), "build/\n").unwrap();
|
|
std::fs::create_dir_all(dir.path().join("build")).unwrap();
|
|
std::fs::write(dir.path().join("build/output.bin"), "binary\n").unwrap();
|
|
std::fs::write(dir.path().join("src.txt"), "source\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.arg("status")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(!stdout.contains("output.bin"));
|
|
assert!(stdout.contains("src.txt"));
|
|
}
|
|
|
|
#[test]
|
|
fn ignore_wildcard_pattern() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join(".arcignore"), "*.o\n").unwrap();
|
|
std::fs::write(dir.path().join("main.o"), "object\n").unwrap();
|
|
std::fs::write(dir.path().join("main.c"), "source\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.arg("status")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(!stdout.contains("main.o"));
|
|
assert!(stdout.contains("main.c"));
|
|
}
|
|
|
|
#[test]
|
|
fn negation_pattern_overrides_ignore() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join(".arcignore"), "*.log\n!important.log\n").unwrap();
|
|
std::fs::write(dir.path().join("debug.log"), "debug\n").unwrap();
|
|
std::fs::write(dir.path().join("important.log"), "keep\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.arg("status")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(!stdout.contains("debug.log"));
|
|
assert!(stdout.contains("important.log"));
|
|
}
|
|
|
|
#[test]
|
|
fn state_reconstruction_multi_commit() {
|
|
let dir = init_repo();
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "v1\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "c1"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(dir.path().join("b.txt"), "b\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "c2"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "v2\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "c3"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
let output = arc_cmd()
|
|
.arg("status")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stdout.contains("working tree clean"));
|
|
}
|
|
|
|
#[test]
|
|
fn state_reconstruction_with_delete() {
|
|
let dir = init_repo();
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "a\n").unwrap();
|
|
std::fs::write(dir.path().join("b.txt"), "b\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "c1"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::remove_file(dir.path().join("b.txt")).unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "c2"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
let output = arc_cmd()
|
|
.arg("status")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stdout.contains("working tree clean"));
|
|
}
|
|
|
|
#[test]
|
|
fn binary_file_commit_and_status() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("binary.bin"), [0u8, 1, 2, 255, 254, 253]).unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "add binary"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
assert!(output.status.success());
|
|
|
|
let status = arc_cmd()
|
|
.arg("status")
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
assert!(status.status.success());
|
|
let stdout = String::from_utf8_lossy(&status.stdout);
|
|
assert!(stdout.contains("working tree clean"));
|
|
}
|
|
|
|
#[test]
|
|
fn zstd_compressed_storage() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("file.txt"), "content\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "test zstd"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
assert!(output.status.success());
|
|
|
|
let commits_dir = dir.path().join(".arc").join("commits");
|
|
let entries: Vec<_> = std::fs::read_dir(&commits_dir)
|
|
.unwrap()
|
|
.filter_map(|e| e.ok())
|
|
.collect();
|
|
assert_eq!(entries.len(), 1);
|
|
|
|
let entry = &entries[0];
|
|
let name = entry.file_name().to_string_lossy().to_string();
|
|
assert!(
|
|
name.ends_with(".zst"),
|
|
"commit file should have .zst extension"
|
|
);
|
|
|
|
let bytes = std::fs::read(entry.path()).unwrap();
|
|
assert_eq!(
|
|
&bytes[0..4],
|
|
&[0x28, 0xB5, 0x2F, 0xFD],
|
|
"should have zstd magic bytes"
|
|
);
|
|
}
|