use super::*;
use crate::working_copy::{WorkingCopy, WorkingCopyRead};
use std::io::Write;
#[test]
fn missing_context_newnodes_lines() -> Result<(), anyhow::Error> {
missing_context_newnodes(Some("a\nf\n"))
}
#[test]
fn missing_context_newnodes_file() -> Result<(), anyhow::Error> {
missing_context_newnodes(None)
}
fn missing_context_newnodes(alice: Option<&str>) -> Result<(), anyhow::Error> {
env_logger::try_init().unwrap_or(());
let contents = b"a\nb\nc\nd\ne\nf\n";
let bob = b"a\nb\nc\nx\nz\nd\ne\nf\n";
let bob2 = b"a\nb\nc\nx\ny\nz\nd\ne\nf\n";
let repo_alice = working_copy::memory::Memory::new();
let changes = changestore::memory::Memory::new();
repo_alice.add_file("file", contents.to_vec());
let env_alice = pristine::sanakirja::Pristine::new_anon()?;
let txn_alice = env_alice.arc_txn_begin().unwrap();
let channel_alice = txn_alice.write().open_or_create_channel("main").unwrap();
txn_alice.write().add_file("file", 0).unwrap();
let init_h = record_all(&repo_alice, &changes, &txn_alice, &channel_alice, "").unwrap();
let repo_bob = working_copy::memory::Memory::new();
let env_bob = pristine::sanakirja::Pristine::new_anon()?;
let txn_bob = env_bob.arc_txn_begin().unwrap();
let mut channel_bob = txn_bob.write().open_or_create_channel("main").unwrap();
apply::apply_change_arc(&changes, &txn_bob, &channel_bob, &init_h).unwrap();
output::output_repository_no_pending(
&repo_bob,
&changes,
&txn_bob,
&channel_bob,
"",
true,
None,
1,
0,
)
.unwrap();
repo_bob
.write_file("file", Inode::ROOT)
.unwrap()
.write_all(bob)
.unwrap();
let bob_h = record_all(&repo_bob, &changes, &txn_bob, &channel_bob, "").unwrap();
repo_bob
.write_file("file", Inode::ROOT)
.unwrap()
.write_all(bob2)
.unwrap();
let bob_h2 = record_all(&repo_bob, &changes, &txn_bob, &channel_bob, "").unwrap();
if let Some(alice) = alice {
repo_alice
.write_file("file", Inode::ROOT)
.unwrap()
.write_all(alice.as_bytes())
.unwrap();
} else {
repo_alice.remove_path("file", false)?;
}
let alice_h = record_all(&repo_alice, &changes, &txn_alice, &channel_alice, "")?;
debug!("applying Bob's change");
apply::apply_change_arc(&changes, &txn_alice, &channel_alice, &bob_h)?;
apply::apply_change_arc(&changes, &txn_alice, &channel_alice, &bob_h2)?;
debug!("done applying Bob's change");
output::output_repository_no_pending(
&repo_alice,
&changes,
&txn_alice,
&channel_alice,
"",
true,
None,
1,
0,
)?;
crate::unrecord::unrecord(
&mut *txn_alice.write(),
&channel_alice,
&changes,
&bob_h2,
0,
)?;
crate::unrecord::unrecord(&mut *txn_alice.write(), &channel_alice, &changes, &bob_h, 0)?;
apply::apply_change_arc(&changes, &txn_alice, &channel_alice, &bob_h)?;
apply::apply_change_arc(&changes, &txn_alice, &channel_alice, &bob_h2)?;
let mut buf = Vec::new();
repo_alice.read_file("file", &mut buf)?;
let re = regex::bytes::Regex::new(r#" \[[^\]]*\]"#).unwrap();
let buf_ = re.replace_all(&buf, &[][..]);
if alice.is_some() {
assert_eq!(
std::str::from_utf8(&buf_),
Ok(&"a\n>>>>>>> 0\nx\ny\nz\n<<<<<<< 0\nf\n"[..])
);
} else {
assert_eq!(
std::str::from_utf8(&buf_),
Ok(&">>>>>>> 0\nx\ny\nz\n<<<<<<< 0\n"[..])
);
}
let conflict: Vec<_> = std::str::from_utf8(&buf)?.lines().collect();
{
let mut w = repo_alice.write_file("file", Inode::ROOT).unwrap();
for l in conflict.iter().filter(|l| l.len() <= 3) {
writeln!(w, "{}", l)?
}
}
info!("starting fix_deletion");
let _fix_deletion = record_all(&repo_alice, &changes, &txn_alice, &channel_alice, "")?;
info!("fix_deletion over");
info!("Bob applies Alice's change");
apply::apply_change_arc(&changes, &txn_bob, &channel_bob, &alice_h).unwrap();
info!("Outputting Bob's working_copy");
crate::unrecord::unrecord(
&mut *txn_bob.write(),
&mut channel_bob,
&changes,
&alice_h,
0,
)?;
apply::apply_change_arc(&changes, &txn_bob, &channel_bob, &alice_h)?;
let mut buf = Vec::new();
output::output_repository_no_pending(
&repo_bob,
&changes,
&txn_bob,
&channel_bob,
"",
true,
None,
1,
0,
)?;
repo_bob.read_file("file", &mut buf)?;
if alice.is_some() {
let buf_ = re.replace_all(&buf, &[][..]);
assert_eq!(
std::str::from_utf8(&buf_),
Ok(&"a\n>>>>>>> 0\nx\n<<<<<<< 0\ny\n>>>>>>> 1\nz\n<<<<<<< 1\nf\n"[..])
);
} else {
assert_eq!(
std::str::from_utf8(&buf_),
Ok(&">>>>>>> 0\nx\ny\nz\n<<<<<<< 0\n"[..])
);
}
{
let mut w = repo_bob.write_file("file", Inode::ROOT).unwrap();
for l in conflict.iter().filter(|&&l| l != "xyz") {
writeln!(w, "{}", l)?
}
}
info!("starting fix_insertion");
let _fix_insertion = record_all(&repo_bob, &changes, &txn_bob, &channel_bob, "")?;
info!("fix_insertion over");
Ok(())
}
#[test]
fn missing_context_newedges() -> Result<(), anyhow::Error> {
env_logger::try_init().unwrap_or(());
let contents = b"a\nb\nc\nd\ne\nf\n";
let alice = b"d\nf\n";
let bob = b"a\nb\nc\ne\nf\n";
let repo_alice = working_copy::memory::Memory::new();
let changes = changestore::memory::Memory::new();
repo_alice.add_file("file", contents.to_vec());
let env_alice = pristine::sanakirja::Pristine::new_anon()?;
let txn_alice = env_alice.arc_txn_begin().unwrap();
let channel_alice = txn_alice.write().open_or_create_channel("main")?;
txn_alice.write().add_file("file", 0)?;
let init_h = record_all(&repo_alice, &changes, &txn_alice, &channel_alice, "")?;
let repo_bob = working_copy::memory::Memory::new();
let env_bob = pristine::sanakirja::Pristine::new_anon()?;
let txn_bob = env_bob.arc_txn_begin().unwrap();
let channel_bob = txn_bob.write().open_or_create_channel("main")?;
apply::apply_change_arc(&changes, &txn_bob, &channel_bob, &init_h)?;
output::output_repository_no_pending(
&repo_bob,
&changes,
&txn_bob,
&channel_bob,
"",
true,
None,
1,
0,
)?;
info!("Done outputting Bob's working_copy");
{
let mut buf = Vec::new();
repo_bob.read_file("file", &mut buf).unwrap();
info!("Bob = {:?}", std::str::from_utf8(&buf));
}
debug!("Bob edits and records");
repo_bob
.write_file("file", Inode::ROOT)
.unwrap()
.write_all(bob)
.unwrap();
let bob_h = record_all(&repo_bob, &changes, &txn_bob, &channel_bob, "")?;
debug!("Alice edits and records");
repo_alice
.write_file("file", Inode::ROOT)
.unwrap()
.write_all(alice)
.unwrap();
let _alice_h = record_all(&repo_alice, &changes, &txn_alice, &channel_alice, "")?;
debug!("Alice applies Bob's change");
apply::apply_change_arc(&changes, &txn_alice, &channel_alice, &bob_h)?;
output::output_repository_no_pending(
&repo_alice,
&changes,
&txn_alice,
&channel_alice,
"",
true,
None,
1,
0,
)?;
debug!("Bob reverts");
let bob_change = changes.get_change(&bob_h)?;
let mut inv = bob_change.inverse(
&bob_h,
crate::change::ChangeHeader {
authors: vec![],
message: "rollback".to_string(),
description: None,
timestamp: chrono::Utc::now(),
},
Vec::new(),
);
let inv_h = changes.save_change(&mut inv, |_, _| Ok::<_, anyhow::Error>(()))?;
info!("Applying inverse change");
apply::apply_change_arc(&changes, &txn_alice, &channel_alice, &inv_h)?;
output::output_repository_no_pending(
&repo_alice,
&changes,
&txn_alice,
&channel_alice,
"",
true,
None,
1,
0,
)?;
Ok(())
}