use super::*;
use crate::private_storage::write_private_file;
use crate::test_support::{fixture, remove};
fn created(relative_path: &str, device: u64, inode: u64) -> InstalledPath {
return InstalledPath {
device,
inode,
relative_path: String::from(relative_path),
selected: true,
};
}
#[test]
fn appended_records_are_read_back_on_reopen() {
let root: PathBuf = fixture("install-log-round-trip");
let stage: PathBuf = root.join(".cli-git-worktree-copy-x");
std::fs::create_dir(stage.as_path()).expect("stage");
{
let mut opened: OpenedLog = open_install_log(stage.as_path()).expect("open");
assert!(opened.recorded.intended.is_empty());
assert!(opened.recorded.created.is_empty());
opened
.log
.append_intents(&[String::from("a"), String::from("b")])
.expect("intents");
opened
.log
.append_creations(&[created("a", 1, 2)])
.expect("creations");
opened
.log
.append_intents(&[])
.expect("empty intents write nothing");
}
let text: String = std::fs::read_to_string(stage.join(INSTALL_LOG_NAME)).expect("log");
assert_eq!(
text,
"{\"intended\":[\"a\",\"b\"]}\n{\"created\":[{\"device\":\"1\",\"inode\":\"2\",\"relativePath\":\"a\",\"selected\":true}]}\n"
);
let reopened: OpenedLog = open_install_log(stage.as_path()).expect("reopen");
assert_eq!(
reopened.recorded.intended,
vec![String::from("a"), String::from("b")]
);
assert_eq!(reopened.recorded.created, vec![created("a", 1, 2)]);
remove(root.as_path());
}
#[cfg(unix)]
#[test]
fn log_is_private() {
use std::os::unix::fs::PermissionsExt;
let root: PathBuf = fixture("install-log-private");
let stage: PathBuf = root.join("stage");
std::fs::create_dir(stage.as_path()).expect("stage");
let _opened: OpenedLog = open_install_log(stage.as_path()).expect("open");
assert_eq!(
std::fs::metadata(stage.join(INSTALL_LOG_NAME))
.expect("log")
.permissions()
.mode()
& 0o777,
0o600
);
remove(root.as_path());
}
#[test]
fn unfinished_trailing_append_is_truncated() {
let root: PathBuf = fixture("install-log-trailing");
let stage: PathBuf = root.join("stage");
std::fs::create_dir(stage.as_path()).expect("stage");
let complete: &str = "{\"intended\":[\"kept\"]}\n";
write_private_file(
stage.join(INSTALL_LOG_NAME).as_path(),
format!("{complete}{{\"intended\":[\"half").as_bytes(),
)
.expect("log");
let mut opened: OpenedLog = open_install_log(stage.as_path()).expect("reopen");
assert_eq!(opened.recorded.intended, vec![String::from("kept")]);
opened
.log
.append_intents(&[String::from("next")])
.expect("append");
drop(opened);
assert_eq!(
std::fs::read_to_string(stage.join(INSTALL_LOG_NAME)).expect("log"),
format!("{complete}{{\"intended\":[\"next\"]}}\n")
);
remove(root.as_path());
}
#[test]
fn corrupt_line_fails_closed() {
let root: PathBuf = fixture("install-log-corrupt");
let stage: PathBuf = root.join("stage");
std::fs::create_dir(stage.as_path()).expect("stage");
let path: PathBuf = stage.join(INSTALL_LOG_NAME);
write_private_file(path.as_path(), b"{\"other\":1}\n").expect("log");
let failure: WorktreeCopyError = open_install_log(stage.as_path()).expect_err("corrupt");
assert_eq!(
failure.0,
format!(
"cli-git: worktree-copy install log is corrupt: {}.",
quote(path.to_string_lossy().as_ref())
)
);
assert!(path.exists());
remove(root.as_path());
}
#[test]
fn unsafe_intent_is_refused() {
let root: PathBuf = fixture("install-log-unsafe");
let stage: PathBuf = root.join("stage");
std::fs::create_dir(stage.as_path()).expect("stage");
write_private_file(
stage.join(INSTALL_LOG_NAME).as_path(),
b"{\"intended\":[\"../up\"]}
",
)
.expect("log");
let failure: WorktreeCopyError = open_install_log(stage.as_path()).expect_err("unsafe");
assert_eq!(
failure.0,
"cli-git: Git returned unsafe ignored path \"../up\"."
);
remove(root.as_path());
}