remove wasm support and drop unused code paths
This commit is contained in:
+22
-511
@@ -1,4 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
@@ -13,50 +12,6 @@ fn blocks_parent_components() {
|
||||
assert_eq!(sanitize_path_component("a/../b"), "a_.._b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_git_repos_discovers_repositories_recursively() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let root = temp.path();
|
||||
|
||||
// Repositories are found at any depth.
|
||||
// A linked worktree, with a `.git` file instead of a directory, counts too.
|
||||
let nested = root.join("a/b/project");
|
||||
std::fs::create_dir_all(nested.join(".git")).unwrap();
|
||||
let worktree = root.join("wt");
|
||||
std::fs::create_dir_all(&worktree).unwrap();
|
||||
std::fs::write(
|
||||
worktree.join(".git"),
|
||||
"gitdir: ../a/b/project/.git/worktrees/wt",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
std::fs::create_dir_all(root.join("plain")).unwrap();
|
||||
|
||||
std::fs::write(root.join(".gitignore"), "node_modules/\n").unwrap();
|
||||
std::fs::create_dir_all(root.join("node_modules/pkg/.git")).unwrap();
|
||||
|
||||
std::fs::create_dir_all(root.join(".hidden/repo/.git")).unwrap();
|
||||
|
||||
// A repository inside another, like a submodule worktree, is not reported.
|
||||
let outer = root.join("outer");
|
||||
std::fs::create_dir_all(outer.join(".git")).unwrap();
|
||||
std::fs::create_dir_all(outer.join("sub/other/.git")).unwrap();
|
||||
|
||||
let mut found: Vec<PathBuf> = find_git_repos(root)
|
||||
.into_iter()
|
||||
.map(|repo| repo.path)
|
||||
.collect();
|
||||
found.sort();
|
||||
|
||||
let mut expected = vec![
|
||||
nested.canonicalize().unwrap(),
|
||||
worktree.canonicalize().unwrap(),
|
||||
outer.canonicalize().unwrap(),
|
||||
];
|
||||
expected.sort();
|
||||
assert_eq!(found, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn root_commit_reports_the_first_ancestor() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
@@ -80,14 +35,7 @@ fn push_all_mirrors_branches_and_tags() {
|
||||
// A bare server repository reachable via a `file://` URL.
|
||||
// Mirrors a grasp server's `{base}/{owner}/{repo-id}.git` layout.
|
||||
let server = tempfile::tempdir().unwrap();
|
||||
let server_repo = server.path().join("npub1test").join("my-repo.git");
|
||||
std::fs::create_dir_all(server_repo.parent().unwrap()).unwrap();
|
||||
let init_status = Command::new("git")
|
||||
.args(["init", "--bare", "-q"])
|
||||
.arg(&server_repo)
|
||||
.status()
|
||||
.expect("spawn git init --bare");
|
||||
assert!(init_status.success());
|
||||
let server_repo = bare_server(server.path(), "npub1test", "my-repo");
|
||||
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
@@ -111,15 +59,7 @@ fn push_all_mirrors_branches_and_tags() {
|
||||
#[test]
|
||||
fn remote_has_refs_reports_whether_pushed_refs_landed() {
|
||||
let server = tempfile::tempdir().unwrap();
|
||||
let server_repo = server.path().join("npub1test").join("my-repo.git");
|
||||
std::fs::create_dir_all(server_repo.parent().unwrap()).unwrap();
|
||||
let init_status = Command::new("git")
|
||||
.args(["init", "--bare", "-q"])
|
||||
.arg(&server_repo)
|
||||
.status()
|
||||
.expect("spawn git init --bare");
|
||||
assert!(init_status.success());
|
||||
|
||||
bare_server(server.path(), "npub1test", "my-repo");
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
let dir = dir.path();
|
||||
@@ -308,60 +248,6 @@ fn head_commit_and_commits_since_track_applied_commits() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn init_repository_creates_main_branch_and_readme() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let path = dir.path().join("my-repo");
|
||||
|
||||
let commit = init_repository(&path, "My Repo", "Does things.\n\nCool.").expect("init");
|
||||
assert_eq!(commit.len(), 40);
|
||||
|
||||
let repo = gix::open(&path).expect("open");
|
||||
let workdir = repo.workdir().expect("workdir");
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(workdir.join("README.md")).expect("read"),
|
||||
"# My Repo\n\nDoes things.\n\nCool.\n"
|
||||
);
|
||||
|
||||
let branch = current_branch(&repo).expect("branch").expect("on a branch");
|
||||
assert_eq!(branch, "main");
|
||||
// [`FileCommit`] carries the short id, the full id is 40 chars.
|
||||
assert_eq!(
|
||||
head_commit(&repo).expect("head").expect("commit").id,
|
||||
&commit[..7]
|
||||
);
|
||||
|
||||
let state = repo_ref_state(&repo).expect("refs");
|
||||
assert_eq!(state.head.as_deref(), Some("main"));
|
||||
assert_eq!(state.refs, vec![("refs/heads/main".to_owned(), commit)]);
|
||||
|
||||
// The index matches the committed tree, so the fresh repo is clean.
|
||||
assert!(!worktree_dirty(workdir));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_origin_creates_or_replaces_the_remote() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let path = dir.path().join("my-repo");
|
||||
init_repository(&path, "My Repo", "").expect("init");
|
||||
|
||||
set_origin(&path, "https://gitnostr.com/npub1test/repo.git").expect("add");
|
||||
assert_eq!(
|
||||
origin_url(&path).expect("url").as_deref(),
|
||||
Some("https://gitnostr.com/npub1test/repo.git")
|
||||
);
|
||||
|
||||
// An existing origin is replaced, not duplicated.
|
||||
// A clone's origin points at the cloned-from path.
|
||||
// It is re-targeted at the grasp server.
|
||||
set_origin(&path, "https://grasp.example/npub1test/repo.git").expect("replace");
|
||||
assert_eq!(
|
||||
origin_url(&path).expect("url").as_deref(),
|
||||
Some("https://grasp.example/npub1test/repo.git")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn working_copy_cloned_from_the_mirror_matches_head_and_origin() {
|
||||
// The mirror is a freshly initialized repository, standing in for
|
||||
@@ -396,14 +282,7 @@ fn working_copy_cloned_from_the_mirror_matches_head_and_origin() {
|
||||
fn fast_forward_branches_moves_the_mirror_and_keeps_local_work() {
|
||||
// A bare server, like a grasp server's `{base}/{owner}/{repo}.git` layout.
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let base_server = dir.path().join("npub1test").join("repo.git");
|
||||
std::fs::create_dir_all(base_server.parent().unwrap()).unwrap();
|
||||
let init_status = Command::new("git")
|
||||
.args(["init", "--bare", "-q"])
|
||||
.arg(&base_server)
|
||||
.status()
|
||||
.expect("spawn git init --bare");
|
||||
assert!(init_status.success());
|
||||
bare_server(dir.path(), "npub1test", "repo");
|
||||
|
||||
let (work_dir, work_repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&work_repo, "initial");
|
||||
@@ -465,14 +344,7 @@ fn fetch_repo_refs_imports_heads_under_a_prefix() {
|
||||
|
||||
// A bare base server holding the initial commit.
|
||||
// Like a grasp server's `{base}/{owner}/{repo-id}.git` layout.
|
||||
let base_server = dir.path().join("npub1base").join("base.git");
|
||||
std::fs::create_dir_all(base_server.parent().unwrap()).unwrap();
|
||||
let init_status = Command::new("git")
|
||||
.args(["init", "--bare", "-q"])
|
||||
.arg(&base_server)
|
||||
.status()
|
||||
.expect("spawn git init --bare");
|
||||
assert!(init_status.success());
|
||||
let base_server = bare_server(dir.path(), "npub1base", "base");
|
||||
|
||||
let (upstream_dir, upstream_repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&upstream_repo, "initial");
|
||||
@@ -505,14 +377,7 @@ fn fetch_repo_refs_imports_heads_under_a_prefix() {
|
||||
commit_all(&gix::open(&fork_work).expect("open"), "feature commit");
|
||||
let tip = git_in(&fork_work, &["rev-parse", "HEAD"]).expect("tip");
|
||||
|
||||
let fork_server = dir.path().join("npub1fork").join("fork.git");
|
||||
std::fs::create_dir_all(fork_server.parent().unwrap()).unwrap();
|
||||
let init_status = Command::new("git")
|
||||
.args(["init", "--bare", "-q"])
|
||||
.arg(&fork_server)
|
||||
.status()
|
||||
.expect("spawn git init --bare");
|
||||
assert!(init_status.success());
|
||||
let fork_server = bare_server(dir.path(), "npub1fork", "fork");
|
||||
push_commit_ref(
|
||||
&fork_work,
|
||||
&format!("file://{}", fork_server.display()),
|
||||
@@ -565,9 +430,9 @@ fn fetch_repo_refs_imports_heads_under_a_prefix() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Run a git command in `dir`, asserting success.
|
||||
fn git_run(dir: &Path, args: &[&str]) {
|
||||
let status = Command::new("git")
|
||||
/// Run a git command in `dir` with a fixed test identity, asserting success.
|
||||
fn git_run(dir: &Path, args: &[&str]) -> std::process::Output {
|
||||
let output = Command::new("git")
|
||||
.current_dir(dir)
|
||||
.env("GIT_AUTHOR_NAME", "Test Author")
|
||||
.env("GIT_AUTHOR_EMAIL", "test@example.com")
|
||||
@@ -575,324 +440,21 @@ fn git_run(dir: &Path, args: &[&str]) {
|
||||
.env("GIT_COMMITTER_EMAIL", "test@example.com")
|
||||
.env("GIT_EDITOR", "true")
|
||||
.args(args)
|
||||
.status()
|
||||
.output()
|
||||
.expect("spawn git");
|
||||
assert!(status.success(), "git {args:?} failed");
|
||||
assert!(output.status.success(), "git {args:?} failed");
|
||||
output
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn worktree_last_commits_returns_most_recent_change() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
|
||||
std::fs::write(dir.path().join("a.txt"), b"two").expect("write");
|
||||
commit_all(&repo, "change a");
|
||||
|
||||
// A commit touching another file must not be reported for a.txt.
|
||||
std::fs::write(dir.path().join("b.txt"), b"other").expect("write");
|
||||
commit_all(&repo, "add b");
|
||||
|
||||
let commit = worktree_last_commits(dir.path(), &[PathBuf::from("a.txt")])
|
||||
.expect("lookup")
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("found")
|
||||
.1;
|
||||
assert_eq!(commit.summary, "change a");
|
||||
assert_eq!(commit.author, "Test Author");
|
||||
assert!(!commit.id.is_empty());
|
||||
assert!(commit.time > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_commits_lists_every_commit() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
|
||||
std::fs::write(dir.path().join("a.txt"), b"two").expect("write");
|
||||
commit_all(&repo, "second");
|
||||
std::fs::write(dir.path().join("b.txt"), b"b").expect("write");
|
||||
commit_all(&repo, "third");
|
||||
|
||||
let list = all_commits(&repo).expect("commits");
|
||||
assert_eq!(list.total, 3);
|
||||
let mut summaries: Vec<&str> = list.commits.iter().map(|c| c.summary.as_str()).collect();
|
||||
summaries.sort();
|
||||
assert_eq!(summaries, vec!["initial", "second", "third"]);
|
||||
assert!(
|
||||
list.commits
|
||||
.iter()
|
||||
.all(|c| c.author == "Test Author" && !c.id.is_empty() && c.time > 0)
|
||||
/// Create a bare `{base}/{owner}/{name}.git` repository, like a grasp server.
|
||||
fn bare_server(base: &Path, owner: &str, name: &str) -> PathBuf {
|
||||
let repo = base.join(owner).join(format!("{name}.git"));
|
||||
std::fs::create_dir_all(repo.parent().expect("parent")).expect("mkdir");
|
||||
git_run(
|
||||
base,
|
||||
&["init", "--bare", "-q", repo.to_str().expect("utf8 path")],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn worktree_last_commits_reports_merge_commits() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"base")]);
|
||||
commit_all(&repo, "initial");
|
||||
|
||||
let run = |args: &[&str]| {
|
||||
let status = Command::new("git")
|
||||
.current_dir(dir.path())
|
||||
.env("GIT_AUTHOR_NAME", "Test Author")
|
||||
.env("GIT_AUTHOR_EMAIL", "test@example.com")
|
||||
.env("GIT_COMMITTER_NAME", "Test Author")
|
||||
.env("GIT_COMMITTER_EMAIL", "test@example.com")
|
||||
.env("GIT_EDITOR", "true")
|
||||
.args(args)
|
||||
.status()
|
||||
.expect("spawn git");
|
||||
assert!(status.success(), "git {args:?} failed");
|
||||
};
|
||||
run(&["checkout", "-b", "feature"]);
|
||||
std::fs::write(dir.path().join("a.txt"), b"feature").expect("write");
|
||||
commit_all(&repo, "feature change");
|
||||
run(&["checkout", "-"]);
|
||||
// `--no-ff` forces a merge commit, it is the latest commit changing a.txt.
|
||||
run(&["merge", "--no-ff", "--no-edit", "feature"]);
|
||||
|
||||
let commit = worktree_last_commits(dir.path(), &[PathBuf::from("a.txt")])
|
||||
.expect("lookup")
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("found")
|
||||
.1;
|
||||
assert_eq!(
|
||||
commit.id,
|
||||
repo.head_id().expect("head").shorten_or_id().to_string()
|
||||
);
|
||||
assert!(commit.summary.starts_with("Merge branch"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_readme_prefers_markdown() {
|
||||
let (_dir, repo) = fixture(&[("readme.txt", b"txt"), ("README.md", b"md")]);
|
||||
|
||||
let readme = find_readme(&repo).expect("find");
|
||||
assert_eq!(
|
||||
readme.map(|p| p.to_string_lossy().into_owned()),
|
||||
Some("README.md".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn current_branch_tracks_checkout() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
let dir = dir.path();
|
||||
|
||||
let default = worktree_branches(dir)
|
||||
.expect("branches")
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("default branch");
|
||||
assert_eq!(
|
||||
current_branch(&repo).expect("branch").as_deref(),
|
||||
Some(default.as_str())
|
||||
);
|
||||
|
||||
git_run(dir, &["checkout", "-b", "feature"]);
|
||||
assert_eq!(
|
||||
current_branch(&repo).expect("branch").as_deref(),
|
||||
Some("feature")
|
||||
);
|
||||
|
||||
git_run(dir, &["tag", "v1.0"]);
|
||||
worktree_checkout_tag(dir, "v1.0").expect("checkout tag");
|
||||
assert_eq!(current_branch(&repo).expect("branch"), None);
|
||||
|
||||
worktree_checkout_branch(dir, &default).expect("checkout branch");
|
||||
assert_eq!(
|
||||
current_branch(&repo).expect("branch").as_deref(),
|
||||
Some(default.as_str())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn worktree_snapshot_reflects_checked_out_ref() {
|
||||
let (dir, repo) = fixture(&[("README.md", b"# main"), ("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
let dir = dir.path();
|
||||
|
||||
git_run(dir, &["checkout", "-b", "feature"]);
|
||||
std::fs::write(dir.join("README.md"), b"# feature").expect("write");
|
||||
std::fs::write(dir.join("b.txt"), b"b").expect("write");
|
||||
commit_all(&repo, "feature work");
|
||||
|
||||
let snapshot = worktree_snapshot(dir).expect("snapshot");
|
||||
assert_eq!(snapshot.current_branch.as_deref(), Some("feature"));
|
||||
assert_eq!(
|
||||
snapshot.head_commit.as_ref().expect("head commit").summary,
|
||||
"feature work"
|
||||
);
|
||||
assert_eq!(
|
||||
String::from_utf8(snapshot.readme.expect("readme")).expect("utf8"),
|
||||
"# feature"
|
||||
);
|
||||
let entries: Vec<String> = snapshot
|
||||
.entries
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().into_owned())
|
||||
.collect();
|
||||
assert!(entries.contains(&"b.txt".to_string()));
|
||||
|
||||
let default = worktree_branches(dir)
|
||||
.expect("branches")
|
||||
.into_iter()
|
||||
.find(|name| name != "feature")
|
||||
.expect("default branch");
|
||||
worktree_checkout_branch(dir, &default).expect("checkout");
|
||||
|
||||
let snapshot = worktree_snapshot(dir).expect("snapshot");
|
||||
assert_eq!(snapshot.current_branch.as_deref(), Some(default.as_str()));
|
||||
assert_eq!(
|
||||
snapshot.head_commit.as_ref().expect("head commit").summary,
|
||||
"initial"
|
||||
);
|
||||
assert_eq!(
|
||||
String::from_utf8(snapshot.readme.expect("readme")).expect("utf8"),
|
||||
"# main"
|
||||
);
|
||||
assert!(
|
||||
!snapshot
|
||||
.entries
|
||||
.iter()
|
||||
.any(|p| p.to_string_lossy() == "b.txt")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commit_diff_lists_added_modified_and_deleted_files() {
|
||||
let (dir, repo) = fixture(&[("keep.txt", b"keep"), ("mod.txt", b"one\ntwo\nthree\n")]);
|
||||
commit_all(&repo, "initial");
|
||||
|
||||
std::fs::write(dir.path().join("mod.txt"), b"one\ntwo!\nthree\n").expect("write");
|
||||
std::fs::write(dir.path().join("new.txt"), b"hello\n").expect("write");
|
||||
std::fs::remove_file(dir.path().join("keep.txt")).expect("remove");
|
||||
commit_all(&repo, "changes");
|
||||
|
||||
let head = repo.head_id().expect("head").shorten_or_id().to_string();
|
||||
let diff = worktree_commit_diff(dir.path(), &head).expect("diff");
|
||||
|
||||
let by_path: HashMap<&str, &FileDiff> = diff
|
||||
.files
|
||||
.iter()
|
||||
.map(|file| (file.path.as_str(), file))
|
||||
.collect();
|
||||
assert_eq!(by_path.len(), 3);
|
||||
|
||||
let added = by_path["new.txt"];
|
||||
assert_eq!(added.status, DiffStatus::Added);
|
||||
assert_eq!(added.insertions, 1);
|
||||
assert_eq!(added.deletions, 0);
|
||||
assert_eq!(added.hunks.len(), 1);
|
||||
assert_eq!(added.hunks[0].lines.len(), 1);
|
||||
assert_eq!(added.hunks[0].lines[0].kind, DiffLineKind::Addition);
|
||||
assert_eq!(added.hunks[0].lines[0].old, None);
|
||||
assert_eq!(added.hunks[0].lines[0].new, Some(1));
|
||||
assert_eq!(added.hunks[0].lines[0].text, "hello");
|
||||
|
||||
let modified = by_path["mod.txt"];
|
||||
assert_eq!(modified.status, DiffStatus::Modified);
|
||||
assert_eq!(modified.insertions, 1);
|
||||
assert_eq!(modified.deletions, 1);
|
||||
assert!(!modified.binary);
|
||||
let lines = &modified.hunks[0].lines;
|
||||
// One hunk with context around the single-line change.
|
||||
// The removed line is old 2, the added line is new 2.
|
||||
assert!(lines.iter().any(|line| {
|
||||
line.kind == DiffLineKind::Deletion
|
||||
&& line.old == Some(2)
|
||||
&& line.new.is_none()
|
||||
&& line.text == "two"
|
||||
}));
|
||||
assert!(lines.iter().any(|line| {
|
||||
line.kind == DiffLineKind::Addition
|
||||
&& line.old.is_none()
|
||||
&& line.new == Some(2)
|
||||
&& line.text == "two!"
|
||||
}));
|
||||
assert!(lines.iter().any(|line| {
|
||||
line.kind == DiffLineKind::Context && line.old == Some(1) && line.new == Some(1)
|
||||
}));
|
||||
|
||||
let deleted = by_path["keep.txt"];
|
||||
assert_eq!(deleted.status, DiffStatus::Deleted);
|
||||
assert_eq!(deleted.deletions, 1);
|
||||
assert_eq!(deleted.hunks[0].lines[0].kind, DiffLineKind::Deletion);
|
||||
assert_eq!(deleted.hunks[0].lines[0].old, Some(1));
|
||||
assert_eq!(deleted.hunks[0].lines[0].new, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commit_range_diff_lists_changes_between_two_commits() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"a\n"), ("b.txt", b"b\n")]);
|
||||
commit_all(&repo, "first");
|
||||
let base = repo.head_id().expect("head").to_string();
|
||||
|
||||
std::fs::write(dir.path().join("a.txt"), b"changed\n").expect("write");
|
||||
std::fs::write(dir.path().join("c.txt"), b"new\n").expect("write");
|
||||
commit_all(&repo, "second");
|
||||
let tip = repo.head_id().expect("head").to_string();
|
||||
|
||||
let diff = worktree_commit_range_diff(dir.path(), &base, &tip).expect("diff");
|
||||
|
||||
let by_path: HashMap<&str, &FileDiff> = diff
|
||||
.files
|
||||
.iter()
|
||||
.map(|file| (file.path.as_str(), file))
|
||||
.collect();
|
||||
assert_eq!(by_path.len(), 2);
|
||||
assert_eq!(by_path["a.txt"].status, DiffStatus::Modified);
|
||||
assert_eq!(by_path["a.txt"].insertions, 1);
|
||||
assert_eq!(by_path["a.txt"].deletions, 1);
|
||||
assert_eq!(by_path["c.txt"].status, DiffStatus::Added);
|
||||
// b.txt is unchanged between the two commits.
|
||||
assert!(diff.files.iter().all(|file| file.path != "b.txt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commit_diff_reports_binary_files_without_hunks() {
|
||||
let (_dir, repo) = fixture(&[("blob.bin", b"\x00\x01\x02")]);
|
||||
commit_all(&repo, "initial");
|
||||
|
||||
std::fs::write(_dir.path().join("blob.bin"), b"\x00\x03").expect("write");
|
||||
commit_all(&repo, "binary change");
|
||||
|
||||
let head = repo.head_id().expect("head").shorten_or_id().to_string();
|
||||
let diff = worktree_commit_diff(_dir.path(), &head).expect("diff");
|
||||
let file = diff
|
||||
.files
|
||||
.iter()
|
||||
.find(|f| f.path == "blob.bin")
|
||||
.expect("file");
|
||||
assert!(file.binary);
|
||||
assert!(file.hunks.is_empty());
|
||||
assert_eq!(file.insertions, 0);
|
||||
assert_eq!(file.deletions, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commit_diff_reports_renames() {
|
||||
let (_dir, repo) = fixture(&[("old.txt", b"same content\n")]);
|
||||
commit_all(&repo, "initial");
|
||||
|
||||
std::fs::rename(_dir.path().join("old.txt"), _dir.path().join("new.txt")).expect("rename");
|
||||
commit_all(&repo, "rename");
|
||||
|
||||
let head = repo.head_id().expect("head").shorten_or_id().to_string();
|
||||
let diff = worktree_commit_diff(_dir.path(), &head).expect("diff");
|
||||
let file = diff
|
||||
.files
|
||||
.iter()
|
||||
.find(|f| f.path == "new.txt")
|
||||
.expect("file");
|
||||
assert_eq!(file.status, DiffStatus::Renamed);
|
||||
assert_eq!(file.old_path.as_deref(), Some("old.txt"));
|
||||
// A pure rename has no content change, the file is still listed.
|
||||
assert!(file.hunks.is_empty());
|
||||
assert_eq!(file.insertions, 0);
|
||||
assert_eq!(file.deletions, 0);
|
||||
repo
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -971,16 +533,7 @@ fn parses_real_format_patch_output() {
|
||||
std::fs::write(dir.path().join("new file.md"), b"# new\n").expect("write");
|
||||
commit_all(&repo, "changes");
|
||||
|
||||
let output = Command::new("git")
|
||||
.current_dir(dir.path())
|
||||
.env("GIT_AUTHOR_NAME", "Test Author")
|
||||
.env("GIT_AUTHOR_EMAIL", "test@example.com")
|
||||
.env("GIT_COMMITTER_NAME", "Test Author")
|
||||
.env("GIT_COMMITTER_EMAIL", "test@example.com")
|
||||
.args(["format-patch", "-1", "--stdout"])
|
||||
.output()
|
||||
.expect("spawn git format-patch");
|
||||
assert!(output.status.success(), "git format-patch failed");
|
||||
let output = git_run(dir.path(), &["format-patch", "-1", "--stdout"]);
|
||||
let patch = String::from_utf8(output.stdout).expect("patch is utf-8");
|
||||
|
||||
let diff = patch_diffs(&patch).expect("parse real format-patch output");
|
||||
@@ -1018,48 +571,6 @@ fn parses_real_format_patch_output() {
|
||||
assert_eq!(file.status, DiffStatus::Deleted);
|
||||
assert!(file.binary);
|
||||
assert!(file.hunks.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn worktree_dirty_tracks_changes_and_untracked_files() {
|
||||
let (dir, repo) = fixture(&[("tracked.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
let workdir = dir.path();
|
||||
|
||||
assert!(!worktree_dirty(workdir));
|
||||
|
||||
std::fs::write(workdir.join("tracked.txt"), b"two").expect("write");
|
||||
assert!(worktree_dirty(workdir));
|
||||
|
||||
// After restoring, an untracked file alone is dirty as well.
|
||||
git_run(workdir, &["checkout", "--", "tracked.txt"]);
|
||||
assert!(!worktree_dirty(workdir));
|
||||
std::fs::write(workdir.join("untracked.txt"), b"new").expect("write");
|
||||
assert!(worktree_dirty(workdir));
|
||||
|
||||
git_run(workdir, &["rm", "--cached", "tracked.txt"]);
|
||||
assert!(worktree_dirty(workdir));
|
||||
|
||||
// A missing directory is clean, not an error.
|
||||
assert!(!worktree_dirty(&dir.path().join("missing")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn worktree_commits_ahead_counts_branch_only_commits() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
let path = dir.path();
|
||||
|
||||
git_run(path, &["checkout", "-q", "-b", "feature"]);
|
||||
std::fs::write(path.join("f.txt"), b"f\n").expect("write");
|
||||
commit_all(&gix::open(path).expect("open"), "feature work");
|
||||
|
||||
assert_eq!(worktree_commits_ahead(path, "main", "feature"), 1);
|
||||
assert_eq!(worktree_commits_ahead(path, "feature", "main"), 0);
|
||||
|
||||
git_run(path, &["checkout", "-q", "main"]);
|
||||
assert_eq!(worktree_current_branch(path).as_deref(), Some("main"));
|
||||
assert!(worktree_ref_exists(path, "refs/heads/feature"));
|
||||
assert!(!worktree_ref_exists(path, "refs/heads/nope"));
|
||||
assert_eq!(worktree_commits_ahead(path, "main", "feature"), 1);
|
||||
assert_eq!(file.insertions, 0);
|
||||
assert_eq!(file.deletions, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user