use std::fs;
use assert_cmd::prelude::*;
use predicates::prelude::*;
use conserve::test_fixtures::{ScratchArchive, TreeFixture};
use crate::run_conserve;
fn setup() -> (ScratchArchive, TreeFixture) {
let af = ScratchArchive::new();
let tf = TreeFixture::new();
tf.create_file_with_contents("hello.c", b"void main() {}");
tf.create_dir("subdir");
run_conserve()
.arg("backup")
.arg(af.path())
.arg(tf.path())
.assert()
.success();
(af, tf)
}
#[cfg(unix)]
fn setup_symlink() -> (ScratchArchive, TreeFixture) {
let af = ScratchArchive::new();
let tf = TreeFixture::new();
tf.create_dir("subdir");
tf.create_symlink("subdir/link", "target");
run_conserve()
.arg("backup")
.arg(af.path())
.arg(tf.path())
.assert()
.success();
(af, tf)
}
#[test]
fn no_changes() {
let (af, tf) = setup();
run_conserve()
.arg("diff")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout(predicate::str::is_empty())
.stderr(predicate::str::is_empty());
run_conserve()
.arg("diff")
.arg("--include-unchanged")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout(".\t/\n.\t/hello.c\n.\t/subdir\n")
.stderr(predicate::str::is_empty());
}
#[test]
fn add_entries() {
let (af, tf) = setup();
tf.create_dir("src");
tf.create_file_with_contents("src/new.rs", b"pub fn main() {}");
run_conserve()
.arg("diff")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout("+\t/src\n+\t/src/new.rs\n")
.stderr(predicate::str::is_empty());
}
#[test]
fn remove_file() {
let (af, tf) = setup();
std::fs::remove_file(tf.path().join("hello.c")).unwrap();
run_conserve()
.arg("diff")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout("-\t/hello.c\n")
.stderr(predicate::str::is_empty());
run_conserve()
.arg("diff")
.arg("--include-unchanged")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout(".\t/\n-\t/hello.c\n.\t/subdir\n")
.stderr(predicate::str::is_empty());
}
#[test]
fn change_kind() {
let (af, tf) = setup();
std::fs::remove_dir(tf.path().join("subdir")).unwrap();
tf.create_file_with_contents("subdir", b"used to be a directory, no longer");
run_conserve()
.arg("diff")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout("*\t/subdir\n")
.stderr(predicate::str::is_empty());
run_conserve()
.arg("diff")
.arg("--include-unchanged")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout(".\t/\n.\t/hello.c\n*\t/subdir\n")
.stderr(predicate::str::is_empty());
}
#[test]
fn change_file_content() {
let (af, tf) = setup();
tf.create_file_with_contents("hello.c", b"int main() { abort(); }");
run_conserve()
.arg("diff")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout("*\t/hello.c\n")
.stderr(predicate::str::is_empty());
run_conserve()
.arg("diff")
.arg("--include-unchanged")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout(".\t/\n*\t/hello.c\n.\t/subdir\n")
.stderr(predicate::str::is_empty());
}
#[cfg(unix)]
#[test]
pub fn symlink_unchanged() {
let (af, tf) = setup_symlink();
run_conserve()
.arg("diff")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout("")
.stderr(predicate::str::is_empty());
run_conserve()
.arg("diff")
.arg("--include-unchanged")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout(".\t/\n.\t/subdir\n.\t/subdir/link\n")
.stderr(predicate::str::is_empty());
}
#[cfg(unix)]
#[test]
pub fn symlink_changed() {
let (af, tf) = setup_symlink();
fs::remove_file(tf.path().join("subdir/link")).unwrap();
tf.create_symlink("subdir/link", "newtarget");
run_conserve()
.arg("diff")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout("*\t/subdir/link\n")
.stderr(predicate::str::is_empty());
run_conserve()
.arg("diff")
.arg("--include-unchanged")
.arg(af.path())
.arg(tf.path())
.assert()
.success()
.stdout(".\t/\n.\t/subdir\n*\t/subdir/link\n")
.stderr(predicate::str::is_empty());
}