use super::*;
use crate::test_support::{fixture, git, git_context, git_output, git_text, remove, repository};
use std::os::unix::ffi::OsStrExt;
use std::path::PathBuf;
fn index_behind(name: &str, files: &[Vec<u8>]) -> (PathBuf, PathBuf, String, String) {
let root: PathBuf = fixture(name);
let repo: PathBuf = repository(root.as_path(), "repo");
let first: String = git_text(repo.as_path(), &["rev-parse", "HEAD"]);
for file in files {
let path: PathBuf = repo.join(std::ffi::OsStr::from_bytes(file.as_slice()));
std::fs::create_dir_all(path.parent().expect("parent")).expect("directories");
std::fs::write(path, b"x\n").expect("write");
}
git(repo.as_path(), &["add", "--all"]);
git(repo.as_path(), &["commit", "--quiet", "--message=second"]);
let second: String = git_text(repo.as_path(), &["rev-parse", "HEAD"]);
git(repo.as_path(), &["read-tree", first.as_str()]);
return (root, repo, first, second);
}
fn differs(repo: &Path, commit: &str) -> bool {
return !git_output(repo, &["diff", "--cached", "--quiet", commit]).status.success();
}
#[test]
fn derived_paths_cover_names_that_are_not_text_and_lists_past_the_request_limit() {
let mut files: Vec<Vec<u8>> = vec![b"not-utf8-\xff\xfe.txt".to_vec(), b"back\\slash \"quoted\".txt".to_vec(), b"line\nbreak.txt".to_vec()];
files.extend((0..crate::service_protocol::MAX_CHANGES + 50).map(|number| { return format!("many/file-{number}.txt").into_bytes(); }));
let (root, repo, first, second) = index_behind("service-follow-derived", files.as_slice());
assert!(differs(repo.as_path(), second.as_str()), "the index starts behind the commit");
update_index(&git_context(), repo.as_path(), second.as_str(), IndexPaths::Derived { old: first.as_str() }).expect("updated");
assert!(!differs(repo.as_path(), second.as_str()));
remove(root.as_path());
}
#[test]
fn a_root_commit_is_updated_from_the_all_zero_old_value() {
let (root, repo, first, _second) = index_behind("service-follow-root", &[b"new.txt".to_vec()]);
git(repo.as_path(), &["read-tree", "--empty"]);
let zero: String = "0".repeat(first.len());
update_index(&git_context(), repo.as_path(), first.as_str(), IndexPaths::Derived { old: zero.as_str() }).expect("updated");
assert!(!differs(repo.as_path(), first.as_str()));
remove(root.as_path());
}
#[test]
fn an_empty_list_leaves_the_index_alone() {
let (root, repo, first, second) = index_behind("service-follow-empty", &[b"new.txt".to_vec()]);
update_index(&git_context(), repo.as_path(), second.as_str(), IndexPaths::Listed(&[])).expect("nothing to do");
assert!(differs(repo.as_path(), second.as_str()));
update_index(&git_context(), repo.as_path(), second.as_str(), IndexPaths::Derived { old: second.as_str() }).expect("no difference");
assert!(differs(repo.as_path(), second.as_str()), "{first}");
remove(root.as_path());
}
#[test]
fn a_cleanup_without_its_scratch_directory_is_done() {
let root: PathBuf = fixture("service-follow-gone");
let repo: PathBuf = repository(root.as_path(), "repo");
let cleanup: Cleanup = Cleanup { git_dir: repo.join(".git"), scratch: repo.join(".git").join("gone"), reftable: false };
assert!(remove_conclusion_state(&git_context(), repo.as_path(), &cleanup));
remove(root.as_path());
}