pub fn apply_root_change<R: rand::Rng, T: MutTxnT, P: ChangeStore>(
txn: &mut T,
channel: &ChannelRef<T>,
store: &P,
rng: R,
) -> Result<Option<(Hash, u64, Merkle)>, ApplyError<P::Error, T::GraphError>> {
let mut change = {
// If the graph already has a root.
{
let channel = channel.read();
let gr = txn.graph(&*channel);
for v in iter_adjacent(&*txn, gr, Vertex::ROOT, EdgeFlags::FOLDER, EdgeFlags::FOLDER|EdgeFlags::BLOCK)? {
let v = txn.find_block(gr, v?.dest()).map_err(LocalApplyError::from)?;
if v.start == v.end {
// Already has a root
return Ok(None)
} else {
// Non-empty channel without a root
break
}
}
// If we are here, either the channel is empty, or it
// isn't and doesn't have a root.
}
let root = Position {
change: Some(Hash::None),
pos: ChangePosition(0u64.into()),
};
let contents = rng.sample_iter(rand::distributions::Standard).take(32).collect();
crate::change::LocalChange::make_change(
txn,
channel,
vec![crate::change::Hunk::AddRoot {
name: Atom::NewVertex(NewVertex {
up_context: vec![root],
down_context: Vec::new(),
start: ChangePosition(0u64.into()),
end: ChangePosition(0u64.into()),
flag: EdgeFlags::FOLDER|EdgeFlags::BLOCK,
inode: root,
}),
inode: Atom::NewVertex(NewVertex {
up_context: vec![Position {
change: None,
pos: ChangePosition(0u64.into()),
}],
down_context: Vec::new(),
start: ChangePosition(1u64.into()),
end: ChangePosition(1u64.into()),
flag: EdgeFlags::FOLDER|EdgeFlags::BLOCK,
inode: root,
}),
}],
contents,
crate::change::ChangeHeader::default(),
Vec::new(),
)?
};
let h = store.save_change(&mut change, |_, _| Ok(())).map_err(ApplyError::Changestore)?;
let (n, merkle) = apply_change(store, txn, &mut channel.write(), &h)?;
Ok(Some((h, n, merkle)))
}