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.
266 lines
6.6 KiB
Rust
266 lines
6.6 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
|
|
}
|
|
|
|
fn commit_file(dir: &TempDir, name: &str, content: &str, msg: &str) -> String {
|
|
std::fs::write(dir.path().join(name), content).unwrap();
|
|
let output = arc_cmd()
|
|
.args(["commit", msg])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed to commit");
|
|
assert!(output.status.success());
|
|
String::from_utf8_lossy(&output.stdout)
|
|
.trim()
|
|
.strip_prefix("✓ committed ")
|
|
.unwrap()
|
|
.to_string()
|
|
}
|
|
|
|
#[test]
|
|
fn merge_diverged_branches() {
|
|
let dir = init_repo();
|
|
commit_file(&dir, "base.txt", "base\n", "base commit");
|
|
|
|
arc_cmd()
|
|
.args(["mark", "add", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
commit_file(&dir, "main-file.txt", "main\n", "main change");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
commit_file(&dir, "feature-file.txt", "feature\n", "feature change");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "main"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
let output = arc_cmd()
|
|
.args(["merge", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stdout.contains("merged feature"));
|
|
|
|
assert!(dir.path().join("base.txt").exists());
|
|
assert!(dir.path().join("main-file.txt").exists());
|
|
assert!(dir.path().join("feature-file.txt").exists());
|
|
}
|
|
|
|
#[test]
|
|
fn merge_creates_commit_with_two_parents() {
|
|
let dir = init_repo();
|
|
commit_file(&dir, "base.txt", "base\n", "base");
|
|
|
|
arc_cmd()
|
|
.args(["mark", "add", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
commit_file(&dir, "a.txt", "main\n", "main work");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
commit_file(&dir, "b.txt", "feature\n", "feature work");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "main"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
let output = arc_cmd()
|
|
.args(["merge", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let merged_line = stdout.trim();
|
|
assert!(merged_line.contains("merged"));
|
|
|
|
let show_output = arc_cmd()
|
|
.args(["show", "HEAD"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
let show_stdout = String::from_utf8_lossy(&show_output.stdout);
|
|
assert!(show_stdout.contains("parent"));
|
|
}
|
|
|
|
#[test]
|
|
fn merge_fails_with_dirty_worktree() {
|
|
let dir = init_repo();
|
|
commit_file(&dir, "a.txt", "a\n", "first");
|
|
|
|
arc_cmd()
|
|
.args(["mark", "add", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
commit_file(&dir, "b.txt", "b\n", "main work");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
commit_file(&dir, "c.txt", "c\n", "feature work");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "main"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(dir.path().join("dirty.txt"), "dirty\n").unwrap();
|
|
|
|
let output = arc_cmd()
|
|
.args(["merge", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("uncommitted changes"));
|
|
}
|
|
|
|
#[test]
|
|
fn merge_same_file_no_conflict() {
|
|
let dir = init_repo();
|
|
std::fs::write(dir.path().join("a.txt"), "line1\nline2\nline3\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "base"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
arc_cmd()
|
|
.args(["mark", "add", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "line1\nline2\nline3\nmain-line\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "main edit"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(
|
|
dir.path().join("a.txt"),
|
|
"feature-line\nline1\nline2\nline3\n",
|
|
)
|
|
.unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "feature edit"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "main"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
let output = arc_cmd()
|
|
.args(["merge", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn merge_conflict_reports_error() {
|
|
let dir = init_repo();
|
|
commit_file(&dir, "a.txt", "original\n", "base");
|
|
|
|
arc_cmd()
|
|
.args(["mark", "add", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "main version\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "main change"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
std::fs::write(dir.path().join("a.txt"), "feature version\n").unwrap();
|
|
arc_cmd()
|
|
.args(["commit", "feature change"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
arc_cmd()
|
|
.args(["switch", "main"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
let output = arc_cmd()
|
|
.args(["merge", "feature"])
|
|
.current_dir(dir.path())
|
|
.output()
|
|
.expect("failed");
|
|
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("conflict"));
|
|
}
|