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.
307 lines
8.1 KiB
Rust
307 lines
8.1 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 commit_first_creates_commit() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("hello.txt"), "hello world\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "initial commit"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stdout.contains("committed"));
|
|
}
|
|
|
|
#[test]
|
|
fn commit_creates_zst_file() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("file.txt"), "content\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "add file"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let commit_id = stdout.trim().strip_prefix("✓ committed ").unwrap();
|
|
|
|
let commits_dir = dir.path().join(".arc").join("commits");
|
|
let found = std::fs::read_dir(&commits_dir)
|
|
.unwrap()
|
|
.filter_map(|e| e.ok())
|
|
.any(|e| e.file_name().to_string_lossy().starts_with(commit_id));
|
|
assert!(found, "commit .zst file should exist");
|
|
}
|
|
|
|
#[test]
|
|
fn commit_updates_head_to_attached() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("a.txt"), "a\n").unwrap();
|
|
|
|
arc_cmd()
|
|
.args(["commit", "first"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
let head = std::fs::read_to_string(dir.path().join(".arc").join("HEAD")).unwrap();
|
|
assert!(head.contains("attached"));
|
|
assert!(head.contains("main"));
|
|
}
|
|
|
|
#[test]
|
|
fn commit_updates_bookmark_ref() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("a.txt"), "a\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "first"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let commit_id = stdout.trim().strip_prefix("✓ committed ").unwrap();
|
|
|
|
let bookmark =
|
|
std::fs::read_to_string(dir.path().join(".arc").join("bookmarks").join("main")).unwrap();
|
|
assert!(bookmark.contains(commit_id));
|
|
}
|
|
|
|
#[test]
|
|
fn commit_fails_with_no_changes() {
|
|
let dir = init_repo();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "empty"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("nothing to commit"));
|
|
}
|
|
|
|
#[test]
|
|
fn commit_nothing_after_same_content() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("a.txt"), "hello\n").unwrap();
|
|
|
|
arc_cmd()
|
|
.args(["commit", "first"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "second"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("nothing to commit"));
|
|
}
|
|
|
|
#[test]
|
|
fn second_commit_has_parent() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("a.txt"), "first\n").unwrap();
|
|
|
|
let first = arc_cmd()
|
|
.args(["commit", "first"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
let first_id = String::from_utf8_lossy(&first.stdout)
|
|
.trim()
|
|
.strip_prefix("✓ committed ")
|
|
.unwrap()
|
|
.to_string();
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "second\n").unwrap();
|
|
|
|
let second = arc_cmd()
|
|
.args(["commit", "second"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
assert!(second.status.success());
|
|
|
|
let head = std::fs::read_to_string(dir.path().join(".arc").join("HEAD")).unwrap();
|
|
let second_id = String::from_utf8_lossy(&second.stdout)
|
|
.trim()
|
|
.strip_prefix("✓ committed ")
|
|
.unwrap()
|
|
.to_string();
|
|
assert!(head.contains(&second_id));
|
|
assert_ne!(first_id, second_id);
|
|
}
|
|
|
|
#[test]
|
|
fn commit_ignores_arc_directory() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("file.txt"), "data\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "test"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn commit_ignores_arcignore_patterns() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join(".arcignore"), "*.log\n").unwrap();
|
|
std::fs::write(dir.path().join("data.log"), "log data\n").unwrap();
|
|
std::fs::write(dir.path().join("keep.txt"), "keep\n").unwrap();
|
|
|
|
arc_cmd()
|
|
.args(["commit", "first"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::remove_file(dir.path().join("data.log")).unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "should fail"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(!output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn commit_detects_deletions() {
|
|
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", "add files"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::remove_file(dir.path().join("b.txt")).unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "delete b"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn commit_detects_modifications() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("a.txt"), "original\n").unwrap();
|
|
|
|
arc_cmd()
|
|
.args(["commit", "add file"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "modified\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "modify file"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn commit_outside_repo_fails() {
|
|
let dir = TempDir::new().unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "fail"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to run arc");
|
|
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("not an arc repository"));
|
|
}
|
|
|
|
#[test]
|
|
fn commit_with_subdirectories() {
|
|
let dir = init_repo();
|
|
std::fs::create_dir_all(dir.path().join("src").join("nested")).unwrap();
|
|
std::fs::write(dir.path().join("src/nested/deep.txt"), "deep\n").unwrap();
|
|
std::fs::write(dir.path().join("root.txt"), "root\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["commit", "nested dirs"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn three_sequential_commits_succeed() {
|
|
let dir = init_repo();
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "v1\n").unwrap();
|
|
let c1 = arc_cmd()
|
|
.args(["commit", "c1"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
assert!(c1.status.success());
|
|
|
|
std::fs::write(dir.path().join("b.txt"), "v1\n").unwrap();
|
|
let c2 = arc_cmd()
|
|
.args(["commit", "c2"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
assert!(c2.status.success());
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "v2\n").unwrap();
|
|
let c3 = arc_cmd()
|
|
.args(["commit", "c3"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
assert!(c3.status.success());
|
|
}
|