CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC
MF3WAHBIH6Q2F7ZOKWPEJF6VGSKJITWLR3Z64GTD6YQZNA5EATWQC
7PM25EXLNQ6JUUIZNTAOQYNNIZNG6TJREEBUSAIC3FIOE7FHETSAC
SNZ3OAMCPUGFYON5SZHQQQK46ZZMVMJECJYEUCMG657UVLY2PNBQC
VXZNQQHCDC6MBLUMNDJVPM4I7XWTDYBPZZNCPZCA6EJ3GS5WAQGQC
KD4JIMAE6M2LFWEHFPEL4RTRV7UWYWNGGS52N2TKQ42ZNFSNLCEQC
IUGP6ZGBFLDRAKJOHFQNG67LZBDXUJ4QM25GOY3QT6GER3NVTHXQC
WKX5S4Z4DOB5S6A6X5V6ECZFCHQUMWRGX5XT4FBOG57P6HPWK7CAC
PH7B6I3U5XCACAX6VX3ZDJD2DQOQS7725R6CTOATNC26NP4VPUFQC
7T5STZYBIUN5AQPFKASNYO24QFLNBX3YCE4YIIXEQNJYR5LSZ6EQC
A7NTQINQCT6GSJZIBPWM6KD2HYGV4XBSV7FWLFYY4YKLSEOW57KQC
A6R6SGCPLFM45QNWJLISFBR3EEXVITYHCWEUOPNH4UIGIWJRTZAQC
IM6UFPOZHZTBMESRXGBALOAWJWUUDGLP2TVLSZ3RZPSJITKB3R7QC
PSKXR4QEPPVJZR777HW67IEHUPGZB44MFCNQ2KUS422Q3W22IQWAC
BE7GUCI2N6TX3P2HRMFSH7XLJKILDPOKOXKA7HWOABBFNKCKMZLAC
6RVT5X4LTRP5XHVDESXMIC2DHMT5MUQ24ZDWEBJ4XYTF6LJXK7CAC
4VWXL6KQGYGDUQRCVJCEVIV6CKJSEIYDX4YF33OX6EDNKJNEGD2AC
Y7YAFMFFJY3SQ3GYN3SS4V3FZWMH3B5L65AXQBXOR5XARSMF5JJQC
6DOXSHWGKJIMIPFCNLASGKBAJCJMJULW5HFRZAZ67EYSMXXGJ3KAC
VBMXB443FGZL6DLT6KAP2ICFCCQNXCUMDEUL67HB4CNKFMBBNSSAC
6YMDOZIB5LVYLFIDGN2WNT5JTHEAMS4TFPVDEZ3OWXWOKJOC5QDAC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
VO5OQW4W2656DIYYRNZ3PO7TQ4JOKQ3GVWE5ALUTYVMX3WMXJOYQC
JACZWIJ6UEL5HWZRNOOXTFXUEG67XJDPC5D72LYUPCVVJ6WB7JQAC
L4JXJHWXYNCL4QGJXNKKTOKKTAXKKXBJUUY7HFZGEUZ5A2V5H34QC
I52XSRUH5RVHQBFWVMAQPTUSPAJ4KNVID2RMI3UGCVKFLYUO6WZAC
76PCXGML77EZWTRI5E6KHLVRAFTJ2AB5YRN5EKOYNAPKTWY2KCGAC
MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC
Q45QHPO4HDTEZF2W4UDZSYYQ46BPEIWSW4GJILZR5HTJNLKXJABQC
FBXYP7QM7SG6P2JDJVQPPCRKJE3GVYXNQ5GVV4GRDUNG6Q4ZRDJQC
IQ4FCHPZYGTZHCQHUIRCMUI5LCHIDSJCM2AZXGRJARWLCPPLXZOQC
FMKKWCFVK5CPPP55T4VMCHSFPZ47EBK6V7D4MJ5BH55TP4UBOZXAC
YAJAXIV5VL263Z6FYLKFPROB3MQPRPH22P44GRGRVGEP56HOMBOAC
VQPAUKBQ2POZKL7CZFAZK5ZQKEBYL27XZYZWYUSH5AH25KK6DWKAC
AN7IDX26RK33ZXASXLJMD4GTFWHCTHMJ6Y5C4ROCPIH33VUT2EYQC
5DVRL6MFXQOCPOZMYSKBERMRRVUTYRL2SRGRTU2MH4IEOFCDKM3QC
SLJ3OHD4F6GJGZ3SV2D7DMR3PXYHPSI64X77KZ3RJ24EGEX6ZNQAC
ZHABNS3S6FSINO74FOI5KHYXYDTBPO4FQTTYTUS7NNKEVVNLYC4AC
WZVCLZKY34KQBQU6YBGJLQCDADBQ67LQVDNRVCMQVY3O3C3EIWSQC
4OCC6D42GZYRDLH3NSKXMJTRKXP7UZ6Z3YNGCNUT7NT6WBDBCBIAC
5BRU2RRWOQBMS2V3RQM7PRFR5UILYZ73GISHAKJA6KIZGC5M2MFAC
BD5PC25AB5MKVIYDFSDGRZ4YGX4PKW4SMZ3YAYAPNA5HLDVJUR3QC
HMMMKONLCRAXVT7SO2ITTFDOJIQKKVSRIZPXYVPDC34RCBHWMHVAC
GLMOA3PFDR7HHJ3QMVZBNNJ3CGZAF72AZ5UBNEQON37K5WFNZP6QC
PJ7T2VFLV5PYG3CV23GC2GIQETXKGC6CO74JBGREV3JC3LG5OXUAC
OJZWJUF2TCGZ7RFVY6FPKBS5P3C4BGHZDPVH775OHVNVFMJICKNQC
7UPL3Y2A5QOBU6VIUHNWEFGSGQ5CMWGDGOVLRZ53UARXG3TDGLMAC
KQTD46KVVWMJ3W6O55BEJLCVTNTDLUH6QT46AEFT7OU2SELXG4IAC
BZSC7VMYSFRXDHDDAMCDR6X67FN5VWIBOSE76BQLX7OCVOJFUA3AC
H23LO7U7MNB5GTLOUIFYAJ6DP57DM3VFBR4IBOAVPMHS356AYFPQC
6T5ULULMRGU5GJ3JQTEH2QFQN5IMP53TYFFXUT5UE6FA6WWFFMFAC
7A2TSC4PAKK3WOH3DMAJASCEC6D5JLJWNFWJTEEBE4CVS4K76PPQC
74HX2XZDHFRE7FIQ6LQZALIIKED2ABSGGBQ34ULYZ5ZBKK7UTHQQC
QNJBR73KCSCCF6FTHGZDF2K7PZQL3EFKZFOBT77KYZBMALTTW6OQC
DNQHXWRZF6EWII3RGQ6HPGFD47BOOFH4FCQHSCACBS3RLQO3DNIQC
3YDPHBANMNSK7Z5SCG745VLTP4BBQWIXCJTQOSDI6UJGYR6S45EQC
BXD3IQYNMKMI5BTANCF6NZHZP4CKPWADGJMBT2R3WTMKVKONT5QAC
ERV3644QELKOHAVNMZGRWYCPPN3XELTAH4PPFR6QKGWW73XBOOKQC
ATZ3BWSEFJBLVGDUZFESRNHVCIO6ZRZ3ALPANZSVGVO7A5BUAFQQC
LCERQSWMA2YKOPAPNZUSOQ7FLBGDHBZR33OHLYX7T4KTKULRMJDQC
XL6Y64UPFLIVRV3YVJMTTMZU7VL6SUXVE6BKL6K7DYRKVJ4X727AC
KDF6FJRVF72L274BEUJCTUKRFMNL6BDZMTVKDPEYGFX4TC3YOVSQC
UBCBQ5FGH2KASHEUPDLIKGLVVX3GSRQ4F4P2JEJZL2NX2DUSYARAC
L5PHFTIERPDAFIOSHZSMAN2CUSFM626ISMGTDYRN5KWPLXCOVPXAC
UNZXTNSJI4YRY3EQ3M4HMBKQDNYDTY6B7IZRBNYGDJXTA2UKYWRAC
43AJ37IXON6PMMYRZM6OB2MJXPYCNIWW2XBDVNBXIRH5DD7JDTVQC
GVQ7YSEDDCYYYWDJ5JUVFSBWA5EZVOZJI63KK6E46N6Y2B6LP72AC
G734WNM64AR5BLAZMN5MDPKSFTYXTUQR6MAGB32NRBC5FXFRWSJAC
SAGSYAPXQ2T6GC3B3TNRPNFTZMS7UMME6YQGSF5MOIM66S5NKB2QC
FXT5FS5WIDBA3HPTJRFGRGULZIGAWAJXT2U6RFYGDLO2PYDG4VEAC
UFCZKKLXVYQYQBYENCAFHY3ZPPSDAJJAIREZSYNQM4QNXV6G6RXAC
OUWD436ATBTZJR53B6XDSI5SXRRNZV7YGRUEA5ACHZC2RUDP7G5QC
BT2ZHPY4LTECZDNPNLX5IUAEA6CYB4RRBGVBXUNK3ARHMWQK7KHAC
#[doc(hidden)]
fn #name_get<'txn>(&'txn self, db: &Self::#name_capital, key: #key, value: Option<#value>) -> Option<#value>;
fn #name_get<'txn>(&'txn self, db: &Self::#name_capital, key: #key, value: Option<#value>) -> Result<Option<#value>, TxnErr<Self::#error>>;
let mut cursor = txn.txn.set_cursors(&db, pos).0;
super::Cursor {
cursor,
txn,
marker: std::marker::PhantomData,
if let Ok((cursor, _)) = txn.txn.set_cursors(&db, pos) {
Ok(super::Cursor {
cursor,
txn,
marker: std::marker::PhantomData,
})
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
) -> Option<(#key, #value)> {
(unsafe { ::sanakirja::next(&self.txn, cursor) })
#post
) -> Result<Option<(#key, #value)>, TxnErr<SanakirjaError>> {
let x = if let Ok(x) = unsafe { ::sanakirja::next(&self.txn, cursor) } {
x
} else {
return Err(TxnErr(SanakirjaError::PristineCorrupt))
};
Ok(x #post)
) -> Option<(#key, #value)> {
(unsafe { ::sanakirja::prev(&self.txn, cursor) })
#post
) -> Result<Option<(#key, #value)>, TxnErr<SanakirjaError>> {
let x = if let Ok(x) = unsafe { ::sanakirja::prev(&self.txn, cursor) } {
x
} else {
return Err(TxnErr(SanakirjaError::PristineCorrupt))
};
Ok(x #post)
let txnt = next(&mut input_iter);
let txnt: proc_macro2::TokenStream = if txnt.is_empty() {
proc_macro2::TokenStream::from(quote! { TxnT })
} else {
proc_macro2::TokenStream::from_iter(txnt.into_iter())
};
let error = next(&mut input_iter);
let error: proc_macro2::TokenStream = if error.is_empty() {
proc_macro2::TokenStream::from(quote! { GraphError })
} else {
proc_macro2::TokenStream::from_iter(error.into_iter())
};
impl<T: TxnT, RT: std::ops::Deref<Target = T>> Iterator for crate::pristine::RevCursor<T, RT, T::#cursor_name, #key, #value>
impl<T: #txnt, RT: std::ops::Deref<Target = T>> Iterator for crate::pristine::RevCursor<T, RT, T::#cursor_name, #key, #value>
type Item = (#key, #value);
fn next(&mut self) -> Option<(#key, #value)> {
self.txn.#name_prev(&mut self.cursor)
type Item = Result<(#key, #value), TxnErr<T::#error>>;
fn next(&mut self) -> Option<Self::Item> {
match self.txn.#name_prev(&mut self.cursor) {
Ok(Some(x)) => Some(Ok(x)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
pub fn prev(&mut self) -> Option<(#key, #value)> {
self.txn.#name_prev(&mut self.cursor)
pub fn prev(&mut self) -> Option<Result<(#key, #value), TxnErr<T::#error>>> {
match self.txn.#name_prev(&mut self.cursor) {
Ok(Some(x)) => Some(Ok(x)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
type Item = (#key, #value);
fn next(&mut self) -> Option<(#key, #value)> {
self.txn.#name_next(&mut self.cursor)
type Item = Result<(#key, #value), TxnErr<T::#error>>;
fn next(&mut self) -> Option<Self::Item> {
match self.txn.#name_next(&mut self.cursor) {
Ok(Some(x)) => Some(Ok(x)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
) -> Result<bool, Self::Error> {
Ok(self.txn.put(&mut self.rng, &mut self.#name, k, v)?)
) -> Result<bool, TxnErr<Self::#error>> {
Ok(self.txn.put(&mut self.rng, &mut self.#name, k, v).map_err(TxnErr)?)
) -> Result<bool, Self::Error> {
Ok(self.txn.del(&mut self.rng, &mut self.#name, k, v)?)
) -> Result<bool, TxnErr<Self::#error>> {
Ok(self.txn.del(&mut self.rng, &mut self.#name, k, v).map_err(TxnErr)?)
}
#[derive(Debug, Error)]
pub enum Error {
#[error("No Pijul repository found")]
NoRepoRoot,
#[error("Cannot access working directory")]
CannotAccessWorkingDirectory,
#[error("Already in a repository")]
AlreadyInARepo,
#[error("No such channel: {}", channel)]
NoSuchChannel { channel: String },
#[error("Protocol error. Is this the correct URL?")]
ProtocolError { line: Vec<u8> },
#[error("Not authenticated")]
NotAuthenticated,
#[error("No change message")]
NoChangeMessage,
#[error("Incorrect remote: {}", name)]
IncorrectRemote { name: String },
#[error("Unknown host key")]
UnknownHostKey,
#[error("Cannot record a binary change interactively. Use -a")]
RecordBinaryChange,
#[error("Remote not found: {:?}", remote)]
RemoteNotFound { remote: String },
#[error("No global config directory")]
NoGlobalConfigDir,
#[error("Could not parse global config")]
CouldNotParseGlobal,
#[error("Remote error: {}", msg)]
Remote { msg: String },
#[error("Remote exited with status {}", status)]
RemoteExit { status: u32 },
#[error("Missing remote")]
MissingRemote,
#[error("State not found in remote: {:?}", state)]
StateNotFound { state: libpijul::pristine::Merkle },
#[error("Missing dependencies for change {:?}", h)]
MissingDep { h: libpijul::pristine::Hash },
#[error("No prefixes given. Use `.` to record the current directory.")]
NoRecordPrefixes,
#[error("HTTP error: {}", status.as_str())]
Http { status: reqwest::StatusCode },
#[error("Could not parse configuration file at {:?}", path)]
CouldNotReadConfig { path: PathBuf },
#[error("No current channel")]
NoCurrentChannel,
#[error("Cannot delete the current channel")]
CannotDeleteCurrentChannel,
#[error("Channel not found: {:?}", channel)]
ChannelNotFound { channel: String },
#[error("Cannot reset, because there are unrecorded changes")]
UnrecordedChanges,
#[error("Could not infer repository name")]
CouldNotInferRepositoryName { repo: String },
#[error("Cannot unrecord change {}, because change {} depends on it", change, dep.to_base32())]
CannotUnrecord {
change: String,
dep: libpijul::pristine::Hash,
},
pub fn current_dir() -> Result<PathBuf, Error> {
std::env::current_dir().map_err(|_| Error::CannotAccessWorkingDirectory)
pub fn current_dir() -> Result<PathBuf, anyhow::Error> {
if let Ok(cur) = std::env::current_dir() {
Ok(cur)
} else {
bail!("Cannot access working directory")
}
for (_, (h, m)) in txn.iter_remote(&remote_changes.borrow().remote, 0) {
if txn.channel_has_state(&channel, m) {
for x in txn.iter_remote(&remote_changes.borrow().remote, 0)? {
let (h, m) = x?.1;
if txn.channel_has_state(&channel, m)? {
fn load_channel<T: MutTxnTExt>(txn: &T, name: &str) -> Result<ChannelRef<T>, Error> {
if let Some(c) = txn.load_channel(name) {
fn load_channel<T: MutTxnTExt>(txn: &T, name: &str) -> Result<ChannelRef<T>, anyhow::Error> {
if let Some(c) = txn.load_channel(name)? {
)
.find(|e| e.flag.contains(EdgeFlags::PARENT | EdgeFlags::FOLDER))
.unwrap()
.dest;
)? {
let e = e?;
if e.flag.contains(EdgeFlags::PARENT | EdgeFlags::FOLDER) {
source_parent = Some(e.dest);
break;
}
}
let source_parent = source_parent.unwrap();
let inode = crate::fs::create_new_inode(txn);
put_tree_with_rev(txn, file_id.as_file_id(), inode).map_err(super::UnrecordError::Txn)?;
put_inodes_with_rev(txn, inode, dest).map_err(super::UnrecordError::Txn)?;
let inode = crate::fs::create_new_inode(txn)?;
put_tree_with_rev(txn, file_id.as_file_id(), inode)?;
put_inodes_with_rev(txn, inode, dest)?;
if let Some(inode) = txn.get_revinodes(position, None) {
del_inodes_with_rev(txn, inode, position).map_err(super::UnrecordError::Txn)?;
if let Some(inode) = txn.get_revinodes(position, None)? {
del_inodes_with_rev(txn, inode, position)?;
assert!(txn.get_revdep(change_id, None).is_none());
while txn.del_dep(change_id, None).map_err(UnrecordError::Txn)? {}
txn.del_external(change_id, None)
.map_err(UnrecordError::Txn)?;
txn.del_internal(*hash, None).map_err(UnrecordError::Txn)?;
assert!(txn.get_revdep(change_id, None)?.is_none());
while txn.del_dep(change_id, None)? {}
txn.del_external(change_id, None)?;
txn.del_internal(*hash, None)?;
) -> Result<(), UnrecordError<P::Error, T::Error>> {
let timestamp = if let Some(ts) = txn.get_changeset(&channel.changes, change_id, None) {
) -> Result<(), UnrecordError<P::Error, T::GraphError>> {
let timestamp = if let Some(ts) = txn.get_changeset(&channel.changes, change_id, None)? {
crate::apply::clean_obsolete_pseudo_edges(txn, channel, &mut ws.apply, change_id)?;
crate::apply::repair_cyclic_paths(txn, channel, &mut ws.apply)?;
crate::apply::clean_obsolete_pseudo_edges(txn, &mut channel.graph, &mut ws.apply, change_id)?;
crate::apply::repair_cyclic_paths(txn, &mut channel.graph, &mut ws.apply)?;
for e in iter_adj_all(txn, channel, a).filter(|e| {
!e.flag.contains(EdgeFlags::PARENT)
&& e.dest == b.start_pos()
&& !e.introduced_by.is_root()
&& e.introduced_by != current_id
}) {
for e in iter_adj_all(txn, channel, a)? {
let e = e?;
if e.flag.contains(EdgeFlags::PARENT)
|| e.dest != b.start_pos()
|| e.introduced_by.is_root()
|| e.introduced_by == current_id
{
continue;
}
) -> Result<(), UnrecordError<P::Error, T::Error>> {
let change_hash = txn.get_external(change_id).unwrap();
) -> Result<(), UnrecordError<P::Error, T::GraphError>> {
let change_hash = txn.get_external(change_id)?.unwrap();
let key = txn.get_inodes(inode, None).unwrap();
let changes: Vec<_> = txn.log_for_path(&channel.borrow(), key, 0).collect();
let key = txn.get_inodes(inode, None).unwrap().unwrap();
let changes: Vec<_> = txn
.log_for_path(&channel.borrow(), key, 0)
.unwrap()
.map(|x| x.unwrap())
.collect();
for x in txn_alice.iter_tree(
OwnedPathId {
parent_inode: Inode::ROOT,
basename: crate::small_string::SmallString::new(),
},
None,
) {
for x in txn_alice
.iter_tree(
OwnedPathId {
parent_inode: Inode::ROOT,
basename: crate::small_string::SmallString::new(),
},
None,
)
.unwrap()
{
for channel in txn.iter_channels("") {
for (_, (i, _)) in txn.log(&channel.borrow(), 0) {
for channel in txn.iter_channels("").unwrap() {
let channel = channel.unwrap();
for x in txn.log(&channel.borrow(), 0).unwrap() {
let (_, (i, _)) = x.unwrap();
let mut it = crate::fs::iter_graph_children(&txn, &changes, &channel, Position::ROOT);
let (key, meta, file) = it.next().unwrap();
let mut it =
crate::fs::iter_graph_children(&txn, &changes, &channel.graph, Position::ROOT).unwrap();
let (key, meta, file) = it.next().unwrap().unwrap();
let mut it = crate::fs::iter_graph_children(&txn, &changes, &channel, key);
let (file_key, _, _) = it.next().unwrap();
crate::fs::iter_paths(&txn, &channel_, file_key, |path| {
let mut it = crate::fs::iter_graph_children(&txn, &changes, &channel.graph, key).unwrap();
let (file_key, _, _) = it.next().unwrap().unwrap();
crate::fs::iter_paths(&txn, &channel_.borrow().graph, file_key, |path| {
let mut it = crate::fs::iter_basenames(&txn, &changes, &channel, key);
let (key, _, name) = it.next().unwrap();
let mut it = crate::fs::iter_basenames(&txn, &changes, &channel.graph, key).unwrap();
let (key, _, name) = it.next().unwrap().unwrap();
let mut it = crate::fs::working_copy_children(&txn, inode);
let (name, _) = it.next().unwrap();
let mut it = crate::fs::working_copy_children(&txn, inode).unwrap();
let (name, _) = it.next().unwrap().unwrap();
fn get_inodes<T: TxnT>(txn: &T, channel: &Channel<T>, inode: Inode) -> Option<Position<ChangeId>> {
if let Some(vertex) = txn.get_inodes(inode, None) {
fn get_inodes<T: ChannelTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>>(
txn: &T,
channel: &Channel<T>,
inode: Inode,
) -> Result<Option<Position<ChangeId>>, TxnErr<T::GraphError>> {
if let Some(vertex) = txn.get_inodes(inode, None)? {
) -> Result<(), RecordError<C::Error, W::Error, T::Error>> {
) -> Result<(), RecordError<C::Error, W::Error, T::GraphError>>
where
T: ChannelTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError> + GraphMutTxnT,
<W as WorkingCopy>::Error: 'static,
{
for name_ in iter_adjacent(txn, &channel, vertex.inode_vertex(), f0, f1)
.filter(|e| e.flag.contains(EdgeFlags::PARENT))
{
for name_ in iter_adjacent(txn, &channel.graph, vertex.inode_vertex(), f0, f1)? {
let name_ = name_?;
if !name_.flag.contains(EdgeFlags::PARENT) {
continue;
}
for child in iter_adjacent(txn, &channel, v.inode_vertex(), f0, f1) {
let child = find_block(txn, &channel, child.dest).unwrap();
for grandchild in iter_adjacent(txn, &channel, child, f0, f1) {
for child in iter_adjacent(txn, channel, v.inode_vertex(), f0, f1)? {
let child = child?;
let child = find_block(txn, channel, child.dest).unwrap();
for grandchild in iter_adjacent(txn, channel, child, f0, f1)? {
let grandchild = grandchild?;
let needs_deletion = if let Some(inode) = txn.get_revinodes(grandchild.dest, None) {
debug!("inode = {:?} {:?}", inode, txn.get_revtree(inode, None));
if let Some(path) = crate::fs::inode_filename(txn, inode) {
working_copy.file_metadata(&path).is_err()
let needs_deletion =
if let Some(inode) = txn.get_revinodes(grandchild.dest, None)? {
debug!("inode = {:?} {:?}", inode, txn.get_revtree(inode, None));
if let Some(path) = crate::fs::inode_filename(txn, inode)? {
working_copy.file_metadata(&path).is_err()
} else {
true
}
} else if let Some(vertex) = get_inodes(txn, &channel, child_inode) {
self.record_deleted_file(txn, &channel, working_copy, &full_path, vertex)
} else if let Some(vertex) = get_inodes(txn, &channel, child_inode)? {
self.record_deleted_file(txn, &channel.graph, working_copy, &full_path, vertex)?
)
.filter(|e| e.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT))
{
)? {
let parent = parent?;
if !parent.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT) {
continue;
}
let parent_dest = find_block_end(txn, &channel, parent.dest).unwrap();
changes.get_contents(|p| txn.get_external(p), parent_dest, &mut previous_name)?;
let parent_dest = find_block_end(txn, channel, parent.dest).unwrap();
changes
.get_contents(
|p| txn.get_external(p).unwrap(),
parent_dest,
&mut previous_name,
)
.map_err(RecordError::Changestore)?;
)
.filter(|e| {
e.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT)
&& !e.flag.contains(EdgeFlags::PSEUDO)
}) {
)? {
let grandparent = grandparent?;
if !grandparent
.flag
.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT)
|| grandparent.flag.contains(EdgeFlags::PSEUDO)
{
continue;
}
)
.filter(|e| e.flag.contains(EdgeFlags::PARENT) && !e.flag.contains(EdgeFlags::PSEUDO))
{
)? {
let grandparent = grandparent?;
if !grandparent.flag.contains(EdgeFlags::PARENT)
|| grandparent.flag.contains(EdgeFlags::PSEUDO)
{
continue;
}
}
impl std::convert::From<::sanakirja::CRCError> for SanakirjaError {
fn from(_: ::sanakirja::CRCError) -> Self {
SanakirjaError::PristineCorrupt
}
}
impl std::convert::From<::sanakirja::CRCError> for TxnErr<SanakirjaError> {
fn from(_: ::sanakirja::CRCError) -> Self {
TxnErr(SanakirjaError::PristineCorrupt)
}
}
impl std::convert::From<::sanakirja::Error> for TxnErr<SanakirjaError> {
fn from(e: ::sanakirja::Error) -> Self {
TxnErr(e.into())
}
}
impl std::convert::From<TxnErr<::sanakirja::Error>> for TxnErr<SanakirjaError> {
fn from(e: TxnErr<::sanakirja::Error>) -> Self {
TxnErr(e.0.into())
}
sanakirja_get!(graph, Vertex<ChangeId>, Edge);
fn get_external(&self, p: ChangeId) -> Option<Hash> {
sanakirja_get!(graph, Vertex<ChangeId>, Edge, GraphError);
fn get_external(&self, p: ChangeId) -> Result<Option<Hash>, TxnErr<Self::GraphError>> {
fn hash_from_prefix(&self, s: &str) -> Result<(Hash, ChangeId), super::HashPrefixError> {
let h = if let Some(h) = Hash::from_prefix(s) {
h
} else {
return Err(super::HashPrefixError::Parse(s.to_string()));
};
let mut result = None;
debug!("h = {:?}", h);
for (e, i) in self.txn.iter(&self.internal, Some((h, None))) {
debug!("{:?} {:?}", e, i);
if e < h {
continue;
} else {
let b32 = e.to_base32();
debug!("{:?}", b32);
let (b32, _) = b32.split_at(s.len().min(b32.len()));
if b32 != s {
break;
} else if result.is_none() {
result = Some((e, i))
} else {
return Err(super::HashPrefixError::Ambiguous(s.to_string()));
}
}
}
if let Some(result) = result {
Ok(result)
} else {
Err(super::HashPrefixError::NotFound(s.to_string()))
}
impl<T: ::sanakirja::Transaction> ChannelTxnT for GenericTxn<T> {
type Changeset = Db<ChangeId, u64>;
type Revchangeset = Db<u64, (ChangeId, Merkle)>;
type Channelstates = Db<Merkle, u64>;
sanakirja_get!(changeset, ChangeId, u64, GraphError);
sanakirja_get!(revchangeset, u64, (ChangeId, Merkle), GraphError);
sanakirja_cursor!(changeset, ChangeId, u64);
sanakirja_cursor_ref!(revchangeset, u64, (ChangeId, Merkle));
sanakirja_rev_cursor!(revchangeset, u64, (ChangeId, Merkle));
}
impl<T: ::sanakirja::Transaction> DepsTxnT for GenericTxn<T> {
type DepsError = SanakirjaError;
type Dep = Db<ChangeId, ChangeId>;
type Revdep = Db<ChangeId, ChangeId>;
sanakirja_table_get!(dep, ChangeId, ChangeId, DepsError);
sanakirja_table_get!(revdep, ChangeId, ChangeId, DepsError);
sanakirja_cursor_ref!(dep, ChangeId, ChangeId);
fn iter_dep_ref<RT: std::ops::Deref<Target = Self> + Clone>(
txn: RT,
p: ChangeId,
) -> Result<super::Cursor<Self, RT, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>
{
Self::cursor_dep_ref(txn.clone(), &txn.dep, Some((p, None)))
fn hash_from_prefix_remote<'txn>(
&'txn self,
remote: &RemoteRef<Self>,
s: &str,
) -> Result<Hash, super::HashPrefixError> {
let remote = remote.borrow();
let h = if let Some(h) = Hash::from_prefix(s) {
h
} else {
return Err(super::HashPrefixError::Parse(s.to_string()));
};
let mut result = None;
debug!("h = {:?}", h);
for (e, _) in self.txn.iter(&remote.rev, Some((h, None))) {
debug!("{:?}", e);
if e < h {
continue;
} else {
let b32 = e.to_base32();
debug!("{:?}", b32);
let (b32, _) = b32.split_at(s.len().min(b32.len()));
if b32 != s {
break;
} else if result.is_none() {
result = Some(e)
} else {
return Err(super::HashPrefixError::Ambiguous(s.to_string()));
}
}
}
if let Some(result) = result {
Ok(result)
} else {
Err(super::HashPrefixError::NotFound(s.to_string()))
}
type Rev_touched_files = Db<ChangeId, Position<ChangeId>>;
sanakirja_iter!(touched_files, Position<ChangeId>, ChangeId);
sanakirja_iter!(rev_touched_files, ChangeId, Position<ChangeId>);
fn iter_revdep(
&self,
k: ChangeId,
) -> Result<
super::Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>,
TxnErr<Self::DepsError>,
> {
self.cursor_dep(&self.revdep, Some((k, None)))
}
fn iter_dep(
&self,
k: ChangeId,
) -> Result<
super::Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>,
TxnErr<Self::DepsError>,
> {
self.cursor_dep(&self.dep, Some((k, None)))
}
fn iter_touched(
&self,
k: Position<ChangeId>,
) -> Result<
super::Cursor<Self, &Self, Self::Touched_filesCursor, Position<ChangeId>, ChangeId>,
TxnErr<Self::DepsError>,
> {
self.cursor_touched_files(&self.touched_files, Some((k, None)))
fn iter_rev_touched(
&self,
k: ChangeId,
) -> Result<
super::Cursor<Self, &Self, Self::Rev_touched_filesCursor, ChangeId, Position<ChangeId>>,
TxnErr<Self::DepsError>,
> {
self.cursor_rev_touched_files(&self.rev_touched_files, Some((k, None)))
}
}
impl<T: ::sanakirja::Transaction> TreeTxnT for GenericTxn<T> {
type TreeError = SanakirjaError;
sanakirja_table_get!(inodes, Inode, Position<ChangeId>);
sanakirja_table_get!(revinodes, Position<ChangeId>, Inode);
sanakirja_table_get!(inodes, Inode, Position<ChangeId>, TreeError);
sanakirja_table_get!(revinodes, Position<ChangeId>, Inode, TreeError);
type Channelstates = Db<Merkle, u64>;
sanakirja_get!(changeset, ChangeId, u64);
sanakirja_get!(revchangeset, u64, (ChangeId, Merkle));
sanakirja_cursor!(changeset, ChangeId, u64);
sanakirja_cursor_ref!(revchangeset, u64, (ChangeId, Merkle));
sanakirja_rev_cursor!(revchangeset, u64, (ChangeId, Merkle));
type Dep = Db<ChangeId, ChangeId>;
type Revdep = Db<ChangeId, ChangeId>;
sanakirja_table_get!(dep, ChangeId, ChangeId);
sanakirja_table_get!(revdep, ChangeId, ChangeId);
sanakirja_cursor_ref!(dep, ChangeId, ChangeId);
sanakirja_table_get!(touched_files, Position<ChangeId>, ChangeId);
sanakirja_table_get!(rev_touched_files, ChangeId, Position<ChangeId>);
fn iter_dep_ref<RT: std::ops::Deref<Target = Self> + Clone>(
txn: RT,
p: ChangeId,
) -> super::Cursor<Self, RT, Self::DepCursor, ChangeId, ChangeId> {
Self::cursor_dep_ref(txn.clone(), &txn.dep, Some((p, None)))
}
type Touched_files = Db<Position<ChangeId>, ChangeId>;
type Rev_touched_files = Db<ChangeId, Position<ChangeId>>;
sanakirja_iter!(touched_files, Position<ChangeId>, ChangeId);
sanakirja_iter!(rev_touched_files, ChangeId, Position<ChangeId>);
fn iter_inodes(
&self,
) -> Result<
super::Cursor<Self, &Self, Self::InodesCursor, Inode, Position<ChangeId>>,
TxnErr<Self::TreeError>,
> {
self.cursor_inodes(&self.inodes, None)
}
#[cfg(debug_assertions)]
fn iter_revinodes(
&self,
) -> Result<
super::Cursor<Self, &Self, Self::RevinodesCursor, Position<ChangeId>, Inode>,
TxnErr<SanakirjaError>,
> {
self.cursor_revinodes(&self.revinodes, None)
}
fn iter_partials<'txn>(
&'txn self,
k: &str,
) -> Result<
super::Cursor<Self, &'txn Self, Self::PartialsCursor, SmallString, Position<ChangeId>>,
TxnErr<SanakirjaError>,
> {
let k0 = SmallString::from_str(k);
self.cursor_partials(&self.partials, Some((k0, None)))
}
}
impl<T: ::sanakirja::Transaction> TxnT for GenericTxn<T> {
fn hash_from_prefix(
&self,
s: &str,
) -> Result<(Hash, ChangeId), super::HashPrefixError<Self::GraphError>> {
let h = if let Some(h) = Hash::from_prefix(s) {
h
} else {
return Err(super::HashPrefixError::Parse(s.to_string()));
};
let mut result = None;
debug!("h = {:?}", h);
for x in self
.txn
.iter(&self.internal, Some((h, None)))
.map_err(|e| super::HashPrefixError::Txn(e.into()))?
{
let (e, i) = x.map_err(|e| super::HashPrefixError::Txn(e.into()))?;
debug!("{:?} {:?}", e, i);
if e < h {
continue;
} else {
let b32 = e.to_base32();
debug!("{:?}", b32);
let (b32, _) = b32.split_at(s.len().min(b32.len()));
if b32 != s {
break;
} else if result.is_none() {
result = Some((e, i))
} else {
return Err(super::HashPrefixError::Ambiguous(s.to_string()));
}
}
}
if let Some(result) = result {
Ok(result)
} else {
Err(super::HashPrefixError::NotFound(s.to_string()))
}
}
fn hash_from_prefix_remote<'txn>(
&'txn self,
remote: &RemoteRef<Self>,
s: &str,
) -> Result<Hash, super::HashPrefixError<Self::GraphError>> {
let remote = remote.borrow();
let h = if let Some(h) = Hash::from_prefix(s) {
h
} else {
return Err(super::HashPrefixError::Parse(s.to_string()));
};
let mut result = None;
debug!("h = {:?}", h);
for x in self
.txn
.iter(&remote.rev, Some((h, None)))
.map_err(|e| super::HashPrefixError::Txn(e.into()))?
{
let (e, _) = x.map_err(|e| super::HashPrefixError::Txn(e.into()))?;
debug!("{:?}", e);
if e < h {
continue;
} else {
let b32 = e.to_base32();
debug!("{:?}", b32);
let (b32, _) = b32.split_at(s.len().min(b32.len()));
if b32 != s {
break;
} else if result.is_none() {
result = Some(e)
} else {
return Err(super::HashPrefixError::Ambiguous(s.to_string()));
}
}
}
if let Some(result) = result {
Ok(result)
} else {
Err(super::HashPrefixError::NotFound(s.to_string()))
}
}
fn iter_inodes(
&self,
) -> super::Cursor<Self, &Self, Self::InodesCursor, Inode, Position<ChangeId>> {
self.cursor_inodes(&self.inodes, None)
}
#[cfg(debug_assertions)]
fn iter_revinodes(
&self,
) -> super::Cursor<Self, &Self, Self::RevinodesCursor, Position<ChangeId>, Inode> {
self.cursor_revinodes(&self.revinodes, None)
}
fn iter_revdep(
&self,
k: ChangeId,
) -> super::Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId> {
self.cursor_dep(&self.revdep, Some((k, None)))
}
fn iter_dep(
&self,
k: ChangeId,
) -> super::Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId> {
self.cursor_dep(&self.dep, Some((k, None)))
}
fn iter_touched(
&self,
k: Position<ChangeId>,
) -> super::Cursor<Self, &Self, Self::Touched_filesCursor, Position<ChangeId>, ChangeId> {
self.cursor_touched_files(&self.touched_files, Some((k, None)))
}
fn iter_rev_touched(
&self,
k: ChangeId,
) -> super::Cursor<Self, &Self, Self::Rev_touched_filesCursor, ChangeId, Position<ChangeId>>
{
self.cursor_rev_touched_files(&self.rev_touched_files, Some((k, None)))
}
fn iter_partials<'txn>(
&'txn self,
k: &str,
) -> super::Cursor<Self, &'txn Self, Self::PartialsCursor, SmallString, Position<ChangeId>>
{
let k0 = SmallString::from_str(k);
self.cursor_partials(&self.partials, Some((k0, None)))
}
fn last_remote(&self, remote: &Self::Remote) -> Option<(u64, (Hash, Merkle))> {
self.txn.rev_iter(remote, None).next()
fn last_remote(
&self,
remote: &Self::Remote,
) -> Result<Option<(u64, (Hash, Merkle))>, TxnErr<Self::GraphError>> {
Ok(self.txn.rev_iter(remote, None)?.next().transpose()?)
fn get_remote_state(&self, remote: &Self::Remote, n: u64) -> Option<(u64, (Hash, Merkle))> {
self.txn
.iter(remote, Some((n, None)))
.find(|(k, _)| *k >= n)
fn get_remote_state(
&self,
remote: &Self::Remote,
n: u64,
) -> Result<Option<(u64, (Hash, Merkle))>, TxnErr<Self::GraphError>> {
for x in self.txn.iter(remote, Some((n, None)))? {
let (k, m) = x?;
if k >= n {
return Ok(Some((k, m)));
}
}
Ok(None)
fn remote_has_change(&self, remote: &RemoteRef<Self>, hash: Hash) -> bool {
self.txn.get(&remote.db.borrow().rev, hash, None).is_some()
fn remote_has_change(
&self,
remote: &RemoteRef<Self>,
hash: Hash,
) -> Result<bool, TxnErr<Self::GraphError>> {
Ok(self.txn.get(&remote.db.borrow().rev, hash, None)?.is_some())
fn remote_has_state(&self, remote: &RemoteRef<Self>, m: Merkle) -> bool {
self.txn.get(&remote.db.borrow().states, m, None).is_some()
fn remote_has_state(
&self,
remote: &RemoteRef<Self>,
m: Merkle,
) -> Result<bool, TxnErr<Self::GraphError>> {
Ok(self.txn.get(&remote.db.borrow().states, m, None)?.is_some())
fn channel_has_state(&self, channel: &ChannelRef<Self>, m: Merkle) -> bool {
self.txn.get(&channel.borrow().states, m, None).is_some()
}
}
/*
impl<T> MutTxn<T> {
pub fn with_remote_mut<F: FnMut(&mut Db<u64, (Hash, Merkle)>)>(
&mut self,
name: &str,
mut f: F,
) -> Result<bool, anyhow::Error> {
let name = SmallString::from_str(name);
let name = UnsafeSmallStr::from_small_str(name.as_small_str());
if let Some((mut db0, db1, db2)) = self.txn.get(&self.remotes, name, None) {
f(&mut db0);
let mut db: ::sanakirja::Db<UnsafeSmallStr, (u64, u64, u64)> =
unsafe { std::mem::transmute(self.remotes) };
self.txn.del(&mut self.rng, &mut db, name, None)?;
self.remotes = unsafe { std::mem::transmute(db) };
self.txn
.put(&mut self.rng, &mut self.remotes, name, (db0, db1, db2))?;
Ok(true)
} else {
Ok(false)
}
}
pub fn del_remote(&mut self, name: &str) -> Result<(), anyhow::Error> {
let name = SmallString::from_str(name);
let name = UnsafeSmallStr::from_small_str(name.as_small_str());
self.txn.del(&mut self.rng, &mut self.remotes, name, None)?;
Ok(())
fn channel_has_state(
&self,
channel: &ChannelRef<Self>,
m: Merkle,
) -> Result<bool, TxnErr<Self::GraphError>> {
Ok(self.txn.get(&channel.borrow().states, m, None)?.is_some())
*/
impl MutTxnT for MutTxn<()> {
sanakirja_put_del!(internal, Hash, ChangeId);
sanakirja_put_del!(external, ChangeId, Hash);
sanakirja_put_del!(inodes, Inode, Position<ChangeId>);
sanakirja_put_del!(revinodes, Position<ChangeId>, Inode);
sanakirja_put_del!(tree, PathId, Inode, UnsafePathId::from_fileid(k), v);
sanakirja_put_del!(revtree, Inode, PathId, k, UnsafePathId::from_fileid(v),);
sanakirja_put_del!(dep, ChangeId, ChangeId);
sanakirja_put_del!(revdep, ChangeId, ChangeId);
sanakirja_put_del!(touched_files, Position<ChangeId>, ChangeId);
sanakirja_put_del!(rev_touched_files, ChangeId, Position<ChangeId>);
fn put_partials(&mut self, k: &str, e: Position<ChangeId>) -> Result<bool, Self::Error> {
let k = SmallString::from_str(k);
Ok(self.txn.put(
&mut self.rng,
&mut self.partials,
UnsafeSmallStr::from_small_str(k.as_small_str()),
e,
)?)
}
fn del_partials(
&mut self,
k: &str,
e: Option<Position<ChangeId>>,
) -> Result<bool, Self::Error> {
let k = SmallString::from_str(k);
Ok(self.txn.del(
&mut self.rng,
&mut self.partials,
UnsafeSmallStr::from_small_str(k.as_small_str()),
e,
)?)
}
impl ChannelMutTxnT for MutTxn<()> {
) -> Result<Option<Merkle>, Self::Error> {
if self.get_changeset(&channel.changes, p, None).is_none() {
) -> Result<Option<Merkle>, TxnErr<Self::GraphError>> {
if self.get_changeset(&channel.changes, p, None)?.is_none() {
}
}
impl DepsMutTxnT for MutTxn<()> {
sanakirja_put_del!(dep, ChangeId, ChangeId, DepsError);
sanakirja_put_del!(revdep, ChangeId, ChangeId, DepsError);
sanakirja_put_del!(touched_files, Position<ChangeId>, ChangeId, DepsError);
sanakirja_put_del!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
}
impl TreeMutTxnT for MutTxn<()> {
sanakirja_put_del!(inodes, Inode, Position<ChangeId>, TreeError);
sanakirja_put_del!(revinodes, Position<ChangeId>, Inode, TreeError);
sanakirja_put_del!(
tree,
PathId,
Inode,
TreeError,
UnsafePathId::from_fileid(k),
v
);
sanakirja_put_del!(
revtree,
Inode,
PathId,
TreeError,
k,
UnsafePathId::from_fileid(v)
);
fn put_partials(
&mut self,
k: &str,
e: Position<ChangeId>,
) -> Result<bool, TxnErr<Self::TreeError>> {
let k = SmallString::from_str(k);
Ok(self.txn.put(
&mut self.rng,
&mut self.partials,
UnsafeSmallStr::from_small_str(k.as_small_str()),
e,
)?)
fn del_partials(
&mut self,
k: &str,
e: Option<Position<ChangeId>>,
) -> Result<bool, TxnErr<Self::TreeError>> {
let k = SmallString::from_str(k);
Ok(self.txn.del(
&mut self.rng,
&mut self.partials,
UnsafeSmallStr::from_small_str(k.as_small_str()),
e,
)?)
}
}
impl MutTxnT for MutTxn<()> {
/// The trait of immutable transactions.
pub trait TxnT: Sized {
type Error: std::error::Error + Send + Sync + 'static;
#[derive(Debug, Error)]
#[error(transparent)]
pub struct TxnErr<E: std::error::Error + 'static>(pub E);
pub trait GraphTxnT: Sized {
type GraphError: std::error::Error + Send + Sync + 'static;
cursor_ref!(graph, Vertex<ChangeId>, Edge);
get!(graph, Vertex<ChangeId>, Edge);
cursor_ref!(graph, Vertex<ChangeId>, Edge, GraphError);
get!(graph, Vertex<ChangeId>, Edge, GraphError);
/// Returns the external hash of an internal change identifier, if
/// the change is known.
fn get_external(&self, p: ChangeId) -> Result<Option<Hash>, TxnErr<Self::GraphError>>;
/// Returns the internal change identifier of change with external
/// hash `hash`, if the change is known.
fn get_internal(&self, p: Hash) -> Result<Option<ChangeId>, TxnErr<Self::GraphError>>;
}
get!(revchangeset, u64, (ChangeId, Merkle));
cursor_ref!(revchangeset, u64, (ChangeId, Merkle));
rev_cursor!(revchangeset, u64, (ChangeId, Merkle));
get!(revchangeset, u64, (ChangeId, Merkle), GraphError);
cursor_ref!(revchangeset, u64, (ChangeId, Merkle), GraphError);
rev_cursor!(revchangeset, u64, (ChangeId, Merkle), GraphError);
}
pub trait DepsTxnT: Sized {
type DepsError: std::error::Error + Send + Sync + 'static;
table!(revdep);
table!(dep);
table_get!(dep, ChangeId, ChangeId, DepsError);
cursor_ref!(dep, ChangeId, ChangeId, DepsError);
table_get!(revdep, ChangeId, ChangeId, DepsError);
fn iter_revdep(
&self,
p: ChangeId,
) -> Result<Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>;
fn iter_dep(
&self,
p: ChangeId,
) -> Result<Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>;
fn iter_dep_ref<RT: std::ops::Deref<Target = Self> + Clone>(
txn: RT,
p: ChangeId,
) -> Result<Cursor<Self, RT, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>;
fn iter_touched(
&self,
p: Position<ChangeId>,
) -> Result<
Cursor<Self, &Self, Self::Touched_filesCursor, Position<ChangeId>, ChangeId>,
TxnErr<Self::DepsError>,
>;
fn iter_rev_touched(
&self,
p: ChangeId,
) -> Result<
Cursor<Self, &Self, Self::Rev_touched_filesCursor, ChangeId, Position<ChangeId>>,
TxnErr<Self::DepsError>,
>;
table!(touched_files);
table!(rev_touched_files);
table_get!(touched_files, Position<ChangeId>, ChangeId, DepsError);
table_get!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
iter!(touched_files, Position<ChangeId>, ChangeId, DepsError);
iter!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
}
table_get!(inodes, Inode, Position<ChangeId>);
table_get!(revinodes, Position<ChangeId>, Inode);
table_get!(inodes, Inode, Position<ChangeId>, TreeError);
table_get!(revinodes, Position<ChangeId>, Inode, TreeError);
cursor!(partials, SmallString, Position<ChangeId>);
cursor!(partials, SmallString, Position<ChangeId>, TreeError);
cursor!(inodes, Inode, Position<ChangeId>, TreeError);
fn iter_inodes(
&self,
) -> Result<
Cursor<Self, &Self, Self::InodesCursor, Inode, Position<ChangeId>>,
TxnErr<Self::TreeError>,
>;
table!(channels);
cursor!(channels, SmallString, (u64, u64, u64, u64, u64, u64));
#[cfg(debug_assertions)]
cursor!(revinodes, Position<ChangeId>, Inode, TreeError);
#[cfg(debug_assertions)]
fn iter_revinodes(
&self,
) -> Result<
Cursor<Self, &Self, Self::RevinodesCursor, Position<ChangeId>, Inode>,
TxnErr<Self::TreeError>,
>;
table!(revdep);
table!(dep);
table_get!(dep, ChangeId, ChangeId);
cursor_ref!(dep, ChangeId, ChangeId);
table_get!(revdep, ChangeId, ChangeId);
table!(touched_files);
table!(rev_touched_files);
table_get!(touched_files, Position<ChangeId>, ChangeId);
table_get!(rev_touched_files, ChangeId, Position<ChangeId>);
iter!(touched_files, Position<ChangeId>, ChangeId);
iter!(rev_touched_files, ChangeId, Position<ChangeId>);
/// Returns the external hash of an internal change identifier, if
/// the change is known.
fn get_external(&self, p: ChangeId) -> Option<Hash>;
/// Returns the internal change identifier of change with external
/// hash `hash`, if the change is known.
fn get_internal(&self, p: Hash) -> Option<ChangeId>;
/// The trait of immutable transactions.
pub trait TxnT:
GraphTxnT
+ ChannelTxnT
+ DepsTxnT<DepsError = <Self as GraphTxnT>::GraphError>
+ TreeTxnT<TreeError = <Self as GraphTxnT>::GraphError>
{
table!(channels);
cursor!(channels, SmallString, (u64, u64, u64, u64, u64, u64));
fn iter_channels<'txn>(&'txn self, start: &str) -> ChannelIterator<'txn, Self>;
fn iter_remotes<'txn>(&'txn self, start: &str) -> RemotesIterator<'txn, Self>;
fn iter_revdep(&self, p: ChangeId) -> Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>;
fn iter_dep(&self, p: ChangeId) -> Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>;
fn iter_dep_ref<RT: std::ops::Deref<Target = Self> + Clone>(
txn: RT,
p: ChangeId,
) -> Cursor<Self, RT, Self::DepCursor, ChangeId, ChangeId>;
fn iter_channels<'txn>(
&'txn self,
start: &str,
) -> Result<ChannelIterator<'txn, Self>, TxnErr<Self::GraphError>>;
fn iter_touched(
&self,
p: Position<ChangeId>,
) -> Cursor<Self, &Self, Self::Touched_filesCursor, Position<ChangeId>, ChangeId>;
fn iter_remotes<'txn>(
&'txn self,
start: &str,
) -> Result<RemotesIterator<'txn, Self>, TxnErr<Self::GraphError>>;
fn iter_rev_touched(
&self,
p: ChangeId,
) -> Cursor<Self, &Self, Self::Rev_touched_filesCursor, ChangeId, Position<ChangeId>>;
) -> RevCursor<Self, &'txn Self, Self::RemoteCursor, u64, (Hash, Merkle)>;
fn get_remote(&mut self, name: &str) -> Option<RemoteRef<Self>>;
fn last_remote(&self, remote: &Self::Remote) -> Option<(u64, (Hash, Merkle))>;
) -> Result<
RevCursor<Self, &'txn Self, Self::RemoteCursor, u64, (Hash, Merkle)>,
TxnErr<Self::GraphError>,
>;
fn remote_has_change(&self, remote: &RemoteRef<Self>, hash: Hash) -> bool;
fn remote_has_state(&self, remote: &RemoteRef<Self>, hash: Merkle) -> bool;
fn channel_has_state(&self, channel: &ChannelRef<Self>, hash: Merkle) -> bool;
fn last_remote(
&self,
remote: &Self::Remote,
) -> Result<Option<(u64, (Hash, Merkle))>, TxnErr<Self::GraphError>>;
cursor!(inodes, Inode, Position<ChangeId>);
fn iter_inodes(&self) -> Cursor<Self, &Self, Self::InodesCursor, Inode, Position<ChangeId>>;
fn get_remote_state(
&self,
remote: &Self::Remote,
n: u64,
) -> Result<Option<(u64, (Hash, Merkle))>, TxnErr<Self::GraphError>>;
#[cfg(debug_assertions)]
cursor!(revinodes, Position<ChangeId>, Inode);
#[cfg(debug_assertions)]
fn iter_revinodes(
fn remote_has_change(
&self,
remote: &RemoteRef<Self>,
hash: Hash,
) -> Result<bool, TxnErr<Self::GraphError>>;
fn remote_has_state(
) -> Cursor<Self, &Self, Self::RevinodesCursor, Position<ChangeId>, Inode>;
remote: &RemoteRef<Self>,
hash: Merkle,
) -> Result<bool, TxnErr<Self::GraphError>>;
fn channel_has_state(
&self,
channel: &ChannelRef<Self>,
hash: Merkle,
) -> Result<bool, TxnErr<Self::GraphError>>;
pub(crate) fn tree_path<T: TxnT>(txn: &T, v: Position<ChangeId>) -> Option<String> {
if let Some(mut inode) = txn.get_revinodes(v, None) {
pub(crate) fn tree_path<T: TreeTxnT>(
txn: &T,
v: Position<ChangeId>,
) -> Result<Option<String>, TxnErr<T::TreeError>> {
if let Some(mut inode) = txn.get_revinodes(v, None)? {
#[error("Inconsistent change")]
pub struct InconsistentChange {}
pub enum InconsistentChange<T: std::error::Error + 'static> {
#[error("Undeclared dependency")]
UndeclaredDep,
#[error(transparent)]
Txn(T),
}
impl<T: std::error::Error + 'static> std::convert::From<TxnErr<T>> for InconsistentChange<T> {
fn from(e: TxnErr<T>) -> Self {
InconsistentChange::Txn(e.0)
}
}
) -> Cursor<T, RT, T::RevchangesetCursor, u64, (ChangeId, Merkle)> {
T::cursor_revchangeset_ref(txn, &channel.revchanges, Some((from, None)))
) -> Result<Cursor<T, RT, T::RevchangesetCursor, u64, (ChangeId, Merkle)>, TxnErr<T::GraphError>> {
Ok(T::cursor_revchangeset_ref(
txn,
&channel.revchanges,
Some((from, None)),
)?)
) -> RevCursor<T, &'txn T, T::RevchangesetCursor, u64, (ChangeId, Merkle)> {
txn.rev_cursor_revchangeset(&channel.revchanges, from.map(|from| (from, None)))
) -> Result<
RevCursor<T, &'txn T, T::RevchangesetCursor, u64, (ChangeId, Merkle)>,
TxnErr<T::GraphError>,
> {
Ok(txn.rev_cursor_revchangeset(&channel.revchanges, from.map(|from| (from, None)))?)
) -> PathChangeset<'channel, 'txn, T> {
PathChangeset {
iter: txn.cursor_revchangeset(&channel.revchanges, Some((from_timestamp, None))),
) -> Result<PathChangeset<'channel, 'txn, T>, TxnErr<T::GraphError>> {
Ok(PathChangeset {
iter: txn.cursor_revchangeset(&channel.revchanges, Some((from_timestamp, None)))?,
) -> RevPathChangeset<'channel, 'txn, T> {
RevPathChangeset {
iter: txn.rev_cursor_revchangeset(&channel.revchanges, Some((from_timestamp, None))),
) -> Result<RevPathChangeset<'channel, 'txn, T>, TxnErr<T::GraphError>> {
Ok(RevPathChangeset {
iter: txn.rev_cursor_revchangeset(&channel.revchanges, Some((from_timestamp, None)))?,
let mut cursor = txn.cursor_graph(&channel.graph, Some((key, Some(edge))));
let (a_, b_) = cursor.next().unwrap();
a_.change == a.change
let mut cursor = txn.cursor_graph(&channel, Some((key, Some(edge))))?;
let (a_, b_) = cursor.next().unwrap()?;
Ok(a_.change == a.change
pub(crate) fn is_alive<T: TxnT>(txn: &T, channel: &Channel<T>, a: Vertex<ChangeId>) -> bool {
a.is_root()
|| iter_adjacent(
txn,
channel,
a,
EdgeFlags::PARENT,
EdgeFlags::all() - EdgeFlags::DELETED,
)
.any(|e| {
!e.flag.contains(EdgeFlags::PSEUDO)
&& (e.flag.contains(EdgeFlags::BLOCK) || a.is_empty())
})
pub(crate) fn is_alive<T: GraphTxnT>(
txn: &T,
channel: &T::Graph,
a: Vertex<ChangeId>,
) -> Result<bool, TxnErr<T::GraphError>> {
if a.is_root() {
return Ok(true);
}
for e in iter_adjacent(
txn,
channel,
a,
EdgeFlags::PARENT,
EdgeFlags::all() - EdgeFlags::DELETED,
)? {
let e = e?;
if !e.flag.contains(EdgeFlags::PSEUDO)
&& (e.flag.contains(EdgeFlags::BLOCK) || a.is_empty())
{
return Ok(true);
}
}
Ok(false)
pub(crate) fn make_changeid<T: TxnT>(txn: &T, h: &Hash) -> ChangeId {
if let Some(h) = txn.get_internal(*h) {
return h;
pub(crate) fn make_changeid<T: GraphTxnT>(
txn: &T,
h: &Hash,
) -> Result<ChangeId, TxnErr<T::GraphError>> {
if let Some(h) = txn.get_internal(*h)? {
return Ok(h);
initialized_cursor!(graph, Vertex<ChangeId>, Edge);
initialized_cursor!(changeset, ChangeId, u64);
initialized_cursor!(revchangeset, u64, (ChangeId, Merkle));
initialized_rev_cursor!(revchangeset, u64, (ChangeId, Merkle));
initialized_cursor!(tree, OwnedPathId, Inode);
initialized_cursor!(revtree, Inode, OwnedPathId);
initialized_cursor!(dep, ChangeId, ChangeId);
initialized_cursor!(partials, SmallString, Position<ChangeId>);
initialized_cursor!(rev_touched_files, ChangeId, Position<ChangeId>);
initialized_cursor!(touched_files, Position<ChangeId>, ChangeId);
initialized_cursor!(graph, Vertex<ChangeId>, Edge, GraphTxnT, GraphError);
initialized_cursor!(changeset, ChangeId, u64, ChannelTxnT, GraphError);
initialized_cursor!(
revchangeset,
u64,
(ChangeId, Merkle),
ChannelTxnT,
GraphError
);
initialized_rev_cursor!(
revchangeset,
u64,
(ChangeId, Merkle),
ChannelTxnT,
GraphError
);
initialized_cursor!(tree, OwnedPathId, Inode, TreeTxnT, TreeError);
initialized_cursor!(revtree, Inode, OwnedPathId, TreeTxnT, TreeError);
initialized_cursor!(dep, ChangeId, ChangeId, DepsTxnT, DepsError);
initialized_cursor!(
partials,
SmallString,
Position<ChangeId>,
TreeTxnT,
TreeError
);
initialized_cursor!(
rev_touched_files,
ChangeId,
Position<ChangeId>,
DepsTxnT,
DepsError
);
initialized_cursor!(
touched_files,
Position<ChangeId>,
ChangeId,
DepsTxnT,
DepsError
);
if let Some((v, e)) = self.it.next() {
debug!("adjacent iterator: {:?} {:?}", v, e);
if v == self.key {
if e.flag >= self.min_flag {
if e.flag <= self.max_flag {
return Some(e);
} else {
return None;
match self.it.next() {
Some(Ok((v, e))) => {
debug!("adjacent iterator: {:?} {:?}", v, e);
if v == self.key {
if e.flag >= self.min_flag {
if e.flag <= self.max_flag {
return Some(Ok(e));
} else {
return None;
}
impl<'channel, 'txn: 'channel, T: TxnT> Iterator for PathChangeset<'channel, 'txn, T> {
type Item = Hash;
impl<
'channel,
'txn: 'channel,
T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>,
> Iterator for PathChangeset<'channel, 'txn, T>
{
type Item = Result<Hash, TxnErr<T::GraphError>>;
while let Some((_, (changeid, _))) = self.iter.next() {
for (p, touched) in self.txn.iter_rev_touched_files(changeid, None) {
while let Some(x) = self.iter.next() {
let (_, (changeid, _)) = match x {
Ok(x) => x,
Err(e) => return Some(Err(e)),
};
let iter = match self.txn.iter_rev_touched_files(changeid, None) {
Ok(iter) => iter,
Err(e) => return Some(Err(e)),
};
for x in iter {
let (p, touched) = match x {
Ok(x) => x,
Err(e) => return Some(Err(e)),
};
if is_ancestor_of(self.txn, self.channel, self.key, touched) {
return self.txn.get_external(changeid);
match is_ancestor_of(self.txn, &self.channel.graph, self.key, touched) {
Ok(true) => return self.txn.get_external(changeid).transpose(),
Err(e) => return Some(Err(e)),
Ok(false) => {}
impl<'channel, 'txn: 'channel, T: TxnT> Iterator for RevPathChangeset<'channel, 'txn, T> {
type Item = Hash;
impl<
'channel,
'txn: 'channel,
T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>,
> Iterator for RevPathChangeset<'channel, 'txn, T>
{
type Item = Result<Hash, TxnErr<T::GraphError>>;
while let Some((_, (changeid, _))) = self.iter.next() {
for (p, touched) in self.txn.iter_rev_touched_files(changeid, None) {
loop {
let changeid = match self.iter.next()? {
Err(e) => return Some(Err(e)),
Ok((_, (changeid, _))) => changeid,
};
let iter = match self.txn.iter_rev_touched_files(changeid, None) {
Ok(iter) => iter,
Err(e) => return Some(Err(e)),
};
for x in iter {
let (p, touched) = match x {
Ok(x) => x,
Err(e) => return Some(Err(e)),
};
if is_ancestor_of(self.txn, self.channel, self.key, touched) {
return self.txn.get_external(changeid);
match is_ancestor_of(self.txn, &self.channel.graph, self.key, touched) {
Ok(true) => return self.txn.get_external(changeid).transpose(),
Err(e) => return Some(Err(e)),
Ok(false) => {}
let next: Option<(SmallString, (u64, u64, u64, u64, u64, u64))> =
self.txn.cursor_channels_next(&mut self.cursor);
if let Some((name, _)) = next {
self.txn.load_channel(name.as_str())
} else {
None
// Option<(SmallString, (u64, u64, u64, u64, u64, u64))>
match self.txn.cursor_channels_next(&mut self.cursor) {
Err(e) => Some(Err(e)),
Ok(Some((name, _))) => self.txn.load_channel(name.as_str()).transpose(),
Ok(None) => None,
let next: Option<(SmallString, (u64, u64, u64))> =
self.txn.cursor_remotes_next(&mut self.cursor);
if let Some((name, _)) = next {
self.txn.load_remote(name.as_str())
} else {
None
match self.txn.cursor_remotes_next(&mut self.cursor) {
Ok(Some((name, _))) => self.txn.load_remote(name.as_str()).transpose(),
Ok(None) => None,
Err(e) => Some(Err(e)),
/// The trait of immutable transactions.
pub trait MutTxnT: TxnT {
put_del!(internal, Hash, ChangeId);
put_del!(external, ChangeId, Hash);
pub trait GraphMutTxnT: GraphTxnT {
put_del!(internal, Hash, ChangeId, GraphError);
put_del!(external, ChangeId, Hash, GraphError);
put_del!(inodes, Inode, Position<ChangeId>);
put_del!(revinodes, Position<ChangeId>, Inode);
put_del!(tree, PathId, Inode);
put_del!(revtree, Inode, PathId);
put_del!(dep, ChangeId, ChangeId);
put_del!(revdep, ChangeId, ChangeId);
put_del!(touched_files, Position<ChangeId>, ChangeId);
put_del!(rev_touched_files, ChangeId, Position<ChangeId>);
) -> Result<bool, Self::Error>;
) -> Result<bool, TxnErr<Self::GraphError>>;
}
pub trait DepsMutTxnT: DepsTxnT {
put_del!(dep, ChangeId, ChangeId, DepsError);
put_del!(revdep, ChangeId, ChangeId, DepsError);
put_del!(touched_files, Position<ChangeId>, ChangeId, DepsError);
put_del!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
}
pub trait TreeMutTxnT: TreeTxnT {
put_del!(inodes, Inode, Position<ChangeId>, TreeError);
put_del!(revinodes, Position<ChangeId>, Inode, TreeError);
put_del!(tree, PathId, Inode, TreeError);
put_del!(revtree, Inode, PathId, TreeError);
fn put_partials(
&mut self,
k: &str,
e: Position<ChangeId>,
) -> Result<bool, TxnErr<Self::TreeError>>;
fn del_partials(
&mut self,
k: &str,
e: Option<Position<ChangeId>>,
) -> Result<bool, TxnErr<Self::TreeError>>;
}
fn commit(self) -> Result<(), Self::Error>;
fn put_partials(&mut self, k: &str, e: Position<ChangeId>) -> Result<bool, Self::Error>;
fn commit(self) -> Result<(), Self::GraphError>;
) -> Result<(), T::Error> {
trace!("key = {:?}, pos = {:?}", key, pos);
let adjacent: Vec<_> = txn
.cursor_graph(&channel.graph, Some((key, None)))
.take_while(|&(k, _)| k <= key)
.filter(|&(k, _)| k == key)
.map(|(_, e)| e)
.collect();
debug!("adjacent {:?}", adjacent);
for chi in adjacent {
buf: &mut Vec<Edge>,
) -> Result<(), TxnErr<T::GraphError>> {
for x in txn.cursor_graph(graph, Some((key, None)))? {
let (k, v) = x?;
if k > key {
break;
} else if k < key {
continue;
}
buf.push(v)
}
for chi in buf.drain(..) {
if !is_alive(txn, &channel, vertex.inode_vertex()) {
for e in iter_adj_all(txn, &channel, vertex.inode_vertex()) {
error!("{:?} {:?} {:?}", inode, vertex, e)
if !is_alive(txn, &channel, vertex.inode_vertex()).unwrap() {
for e in iter_adj_all(txn, channel, vertex.inode_vertex()).unwrap() {
error!("{:?} {:?} {:?}", inode, vertex, e.unwrap())
let graph = crate::alive::retrieve::retrieve(txn, &channel.borrow(), file_);
graph.debug(changes, txn, &channel.borrow(), false, false, &mut f)?;
let graph = crate::alive::retrieve::retrieve(txn, &channel.graph, file_).unwrap();
graph.debug(changes, txn, &channel.graph, false, false, &mut f)?;
if let Some((_, (h, _))) = log.next() {
let deps = Some(T::iter_dep_ref(self.txn.clone(), h));
if let Some(x) = log.next() {
let (_, (h, _)) = match x {
Ok(e) => e,
Err(e) => return Some(Err(e)),
};
let deps = match T::iter_dep_ref(self.txn.clone(), h) {
Ok(e) => Some(e),
Err(e) => return Some(Err(e)),
};
#[error("Block error: {:?}", block)]
pub struct BlockError {
block: Position<ChangeId>,
pub enum BlockError<T: std::error::Error + 'static> {
#[error(transparent)]
Txn(T),
#[error("Block error: {:?}", block)]
Block { block: Position<ChangeId> },
}
impl<T: std::error::Error + 'static> std::convert::From<TxnErr<T>> for BlockError<T> {
fn from(e: TxnErr<T>) -> Self {
BlockError::Txn(e.0)
}
if let Some((inode, _)) = output_item.inode {
let output_item_inode =
if let Some(inode) = txn.get_revinodes(output_item.pos, None)? {
Some((inode, txn.get_inodes(inode, None)?.unwrap()))
} else {
None
};
if let Some((inode, _)) = output_item_inode {
put_inodes_with_rev(txn, inode, output_item.pos)
.map_err(PristineOutputError::Txn)?;
put_tree_with_rev(txn, file_id_, inode).map_err(PristineOutputError::Txn)?;
put_inodes_with_rev(txn, inode, output_item.pos)?;
put_tree_with_rev(txn, file_id_, inode)?;
put_inodes_with_rev(txn, inode, output_item.pos).map_err(PristineOutputError::Txn)?;
put_tree_with_rev(txn, file_id_, inode).map_err(PristineOutputError::Txn)?;
put_inodes_with_rev(txn, inode, output_item.pos)?;
put_tree_with_rev(txn, file_id_, inode)?;
put_inodes_with_rev(txn, inode, output_item.pos).map_err(PristineOutputError::Txn)?;
put_tree_with_rev(txn, file_id_, inode).map_err(PristineOutputError::Txn)?;
put_inodes_with_rev(txn, inode, output_item.pos)?;
put_tree_with_rev(txn, file_id_, inode)?;
) -> Result<(), OutputError<P::Error, T::Error, W::Error>> {
let mut l = retrieve(txn, channel, output_item.pos);
) -> Result<(), OutputError<P::Error, T::GraphError, W::Error>> {
let mut l = retrieve(txn, &channel.graph, output_item.pos)?;
del_tree_with_rev(txn, fileid.as_file_id(), *inode).map_err(PristineOutputError::Txn)?;
if let Some(vertex) = txn.get_inodes(*inode, None) {
del_tree_with_rev(txn, fileid.as_file_id(), *inode)?;
if let Some(vertex) = txn.get_inodes(*inode, None)? {
}
}
impl<C: std::error::Error, T: std::error::Error + 'static> From<TxnErr<T>>
for PristineOutputError<C, T>
{
fn from(e: TxnErr<T>) -> Self {
PristineOutputError::Txn(e.0)
}
}
impl<C: std::error::Error, T: std::error::Error + 'static, W: std::error::Error> From<TxnErr<T>>
for OutputError<C, T, W>
{
fn from(e: TxnErr<T>) -> Self {
OutputError::Pristine(e.into())
) {
// This unwrap is ok since e.dest is in the channel.
let name_vertex = find_block(txn, &channel, e.dest).unwrap();
)? {
let e = e?;
let name_vertex = find_block(txn, channel, e.dest).unwrap();
)
.find(|e| !e.flag.contains(EdgeFlags::PARENT))
.unwrap();
)? {
let e = e?;
if !e.flag.contains(EdgeFlags::PARENT) {
edge = Some(e);
break;
}
}
let e = edge.unwrap();
iter_adjacent(txn, &channel, pos.inode_vertex(), f, f | EdgeFlags::BLOCK)
.next()
.is_some()
if let Some(n) =
iter_adjacent(txn, channel, pos.inode_vertex(), f, f | EdgeFlags::BLOCK)?.next()
{
n?;
Ok(true)
} else {
Ok(false)
}
pub(crate) fn archive<'a, T: TxnT, P: ChangeStore, I: Iterator<Item = &'a str>, A: Archive>(
impl<
P: std::error::Error + 'static,
T: std::error::Error + 'static,
A: std::error::Error + 'static,
> std::convert::From<TxnErr<T>> for ArchiveError<P, T, A>
{
fn from(e: TxnErr<T>) -> Self {
ArchiveError::Txn(e.0)
}
}
pub(crate) fn archive<
'a,
T: ChannelTxnT,
P: ChangeStore,
I: Iterator<Item = &'a str>,
A: Archive,
>(
if let Some((inode, _)) = output_item.inode {
if !done_inodes.insert(inode) {
debug!("inode already visited: {:?} {:?}", a, inode);
continue;
}
if !done_inodes.insert(output_item.pos) {
debug!("inode already visited: {:?} {:?}", a, output_item.pos);
continue;
)
.any(|e| e.introduced_by == v.introduced_by)
{
let intro = txn.get_external(v.introduced_by).unwrap();
)? {
let e = e?;
if e.introduced_by == v.introduced_by {
not_del_by_change = false;
break;
}
}
if not_del_by_change {
let intro = txn.get_external(v.introduced_by)?.unwrap();
put_graph_with_rev(txn, channel, EdgeFlags::db(), dest_vertex, p, change_id)
.map_err(MissingError::Txn)?;
put_graph_with_rev(txn, channel, EdgeFlags::db(), dest_vertex, p, change_id)?;
Base32, ChangeId, Channel, ChannelRef, EdgeFlags, Hash, Inode, Merkle, MutTxnT, OwnedPathId,
RemoteRef, TxnT, Vertex,
Base32, ChangeId, Channel, ChannelRef, ChannelTxnT, DepsTxnT, EdgeFlags, GraphTxnT, Hash,
Inode, Merkle, MutTxnT, OwnedPathId, RemoteRef, TreeTxnT, TxnT, Vertex,
) -> Result<(), crate::record::RecordError<C::Error, W::Error, Self::Error>> {
builder.record(self, diff_algorithm, channel, working_copy, changes, prefix)
) -> Result<(), crate::record::RecordError<C::Error, W::Error, Self::GraphError>>
where
<W as crate::working_copy::WorkingCopy>::Error: 'static,
{
builder.record(
self,
diff_algorithm,
&mut channel.borrow_mut(),
working_copy,
changes,
prefix,
)
) -> Result<record::Recorded, crate::record::RecordError<C::Error, W::Error, Self::Error>> {
) -> Result<record::Recorded, crate::record::RecordError<C::Error, W::Error, Self::GraphError>>
where
<W as crate::working_copy::WorkingCopy>::Error: 'static,
{
) -> Option<u64> {
let cid = pristine::TxnT::get_internal(self, hash)?;
self.get_changeset(&channel.borrow().changes, cid, None)
) -> Result<Option<u64>, Self::GraphError> {
if let Some(cid) = pristine::GraphTxnT::get_internal(self, hash).map_err(|e| e.0)? {
self.get_changeset(&channel.borrow().changes, cid, None)
.map_err(|e| e.0)
} else {
Ok(None)
}
fn current_state(&self, channel: &pristine::Channel<Self>) -> pristine::Merkle {
pristine::current_state(self, channel)
fn current_state(
&self,
channel: &pristine::Channel<Self>,
) -> Result<pristine::Merkle, Self::GraphError> {
pristine::current_state(self, channel).map_err(|e| e.0)
) -> pristine::PathChangeset<'channel, 'txn, Self> {
pristine::log_for_path(self, channel, pos, from)
) -> Result<pristine::PathChangeset<'channel, 'txn, Self>, Self::GraphError> {
pristine::log_for_path(self, channel, pos, from).map_err(|e| e.0)
) -> pristine::RevPathChangeset<'channel, 'txn, Self> {
pristine::rev_log_for_path(self, channel, pos, from)
) -> Result<pristine::RevPathChangeset<'channel, 'txn, Self>, Self::DepsError> {
pristine::rev_log_for_path(self, channel, pos, from).map_err(|e| e.0)
) -> pristine::RevCursor<
Self,
&'txn Self,
Self::RevchangesetCursor,
u64,
(pristine::ChangeId, pristine::Merkle),
) -> Result<
pristine::RevCursor<
Self,
&'txn Self,
Self::RevchangesetCursor,
u64,
(pristine::ChangeId, pristine::Merkle),
>,
Self::GraphError,
) -> Option<(pristine::Hash, pristine::Merkle)> {
self.get_revchangeset(&channel.borrow().revchanges, n, None)
.map(|(h, m)| (self.get_external(h).unwrap(), m))
) -> Result<Option<(pristine::Hash, pristine::Merkle)>, Self::GraphError> {
if let Some((h, m)) = self
.get_revchangeset(&channel.borrow().revchanges, n, None)
.map_err(|e| e.0)?
{
Ok(Some((self.get_external(h).map_err(|e| e.0)?.unwrap(), m)))
} else {
Ok(None)
}
fn touched_files(&self, h: pristine::Hash) -> Option<Touched<Self>> {
if let Some(id) = pristine::TxnT::get_internal(self, h) {
Some(Touched {
fn touched_files(&self, h: pristine::Hash) -> Result<Option<Touched<Self>>, Self::DepsError> {
if let Some(id) = pristine::GraphTxnT::get_internal(self, h).map_err(|e| e.0)? {
Ok(Some(Touched {
) -> Result<(pristine::Position<pristine::ChangeId>, bool), fs::FsError<C::Error>> {
fs::follow_oldest_path(changes, self, channel, path)
) -> Result<
(pristine::Position<pristine::ChangeId>, bool),
fs::FsErrorC<C::Error, Self::GraphError>,
> {
fs::follow_oldest_path(changes, self, &channel.borrow(), path)
) -> pristine::AdjacentIterator<'txn, Self> {
pristine::iter_adjacent(self, channel, key, min_flag, max_flag)
) -> Result<pristine::AdjacentIterator<'txn, Self>, pristine::TxnErr<Self::GraphError>> {
pristine::iter_adjacent(self, &graph.graph, key, min_flag, max_flag)
impl<'txn, T: pristine::TxnT> Iterator for Log<'txn, T> {
type Item = (u64, (pristine::Hash, pristine::Merkle));
impl<'txn, T: pristine::ChannelTxnT> Iterator for Log<'txn, T> {
type Item = Result<(u64, (pristine::Hash, pristine::Merkle)), T::GraphError>;
self.iter
.next()
.map(|(n, (c, m))| (n, (self.txn.get_external(c).unwrap(), m)))
match self.iter.next() {
Some(Ok((n, (c, m)))) => {
let ext = match self.txn.get_external(c) {
Err(pristine::TxnErr(e)) => return Some(Err(e)),
Ok(Some(ext)) => ext,
Ok(None) => panic!("Unknown change {:?}", c),
};
Some(Ok((n, (ext, m))))
}
None => None,
Some(Err(e)) => Some(Err(e.0)),
}
impl<'txn, T: pristine::TxnT> Iterator for RevLog<'txn, T> {
type Item = (u64, (pristine::Hash, pristine::Merkle));
impl<'txn, T: pristine::ChannelTxnT> Iterator for RevLog<'txn, T> {
type Item = Result<(u64, (pristine::Hash, pristine::Merkle)), T::GraphError>;
self.iter
.next()
.map(|(n, (c, m))| (n, (self.txn.get_external(c).unwrap(), m)))
match self.iter.next() {
Some(Ok((n, (c, m)))) => match self.txn.get_external(c) {
Ok(Some(ext)) => Some(Ok((n, (ext, m)))),
Err(e) => Some(Err(e.0)),
Ok(None) => panic!("Unknown change {:?}", c),
},
None => None,
Some(Err(e)) => Some(Err(e.0)),
}
impl<'txn, T: pristine::TxnT> Iterator for Touched<'txn, T> {
type Item = pristine::Position<pristine::Hash>;
impl<
'txn,
T: pristine::DepsTxnT + pristine::GraphTxnT<GraphError = <T as pristine::DepsTxnT>::DepsError>,
> Iterator for Touched<'txn, T>
{
type Item = Result<pristine::Position<pristine::Hash>, T::DepsError>;
let change = self.txn.get_external(file.change).unwrap();
return Some(pristine::Position {
let change = match self.txn.get_external(file.change) {
Ok(ext) => ext.unwrap(),
Err(e) => return Some(Err(e.0)),
};
return Some(Ok(pristine::Position {
#[error(transparent)]
Changestore(C),
#[error(transparent)]
NotFound(#[from] FsNotFound),
}
#[derive(Debug, Error)]
#[error("Path not found: {0}")]
pub struct FsNotFound(String);
impl<T: std::error::Error + 'static> std::convert::From<TxnErr<T>> for FsError<T> {
fn from(e: TxnErr<T>) -> Self {
FsError::Txn(e.0)
}
}
impl<C: std::error::Error + 'static, T: std::error::Error + 'static> std::convert::From<TxnErr<T>>
for FsErrorC<C, T>
{
fn from(e: TxnErr<T>) -> Self {
FsErrorC::Txn(e.0)
}
del_tree_with_rev(txn, parent_id.as_file_id(), inode).map_err(FsError::Txn)?;
if let Some(vertex) = txn.get_inodes(inode, None) {
del_inodes_with_rev(txn, inode, vertex).map_err(FsError::Txn)?;
del_tree_with_rev(txn, parent_id.as_file_id(), inode)?;
if let Some(vertex) = txn.get_inodes(inode, None)? {
del_inodes_with_rev(txn, inode, vertex)?;
) -> Result<(), FsError<T::Error>> {
let fileref = txn.get_revtree(inode, None).unwrap().to_owned();
) -> Result<(), FsError<T::TreeError>> {
let fileref = txn.get_revtree(inode, None)?.unwrap().to_owned();
if !inode.is_root()
&& del_tree_with_rev(txn, parent.as_file_id(), inode).map_err(FsError::Txn)?
{
if let Some(vertex) = txn.get_inodes(inode, None) {
del_inodes_with_rev(txn, inode, vertex).map_err(FsError::Txn)?;
if !inode.is_root() && del_tree_with_rev(txn, parent.as_file_id(), inode)? {
if let Some(vertex) = txn.get_inodes(inode, None)? {
del_inodes_with_rev(txn, inode, vertex)?;
if let Some((k, v)) = self.iter.next() {
if k.parent_inode == self.inode {
if k.basename.len() > 0 {
return Some((k.basename, v));
match self.iter.next() {
Some(Ok((k, v))) => {
if k.parent_inode == self.inode {
if k.basename.len() > 0 {
return Some(Ok((k.basename, v)));
}
} else if k.parent_inode > self.inode {
return None;
pub fn working_copy_children<T: TxnT>(txn: &T, inode: Inode) -> WorkingCopyChildren<T> {
WorkingCopyChildren {
iter: txn.iter_tree(
OwnedPathId {
parent_inode: inode,
basename: SmallString::new(),
},
None,
),
pub fn working_copy_children<T: TreeTxnT>(
txn: &T,
inode: Inode,
) -> Result<WorkingCopyChildren<T>, T::TreeError> {
Ok(WorkingCopyChildren {
iter: txn
.iter_tree(
OwnedPathId {
parent_inode: inode,
basename: SmallString::new(),
},
None,
)
.map_err(|e| e.0)?,
for (k, v) in self.txn.iter_tree(fileid, None) {
let iter = match self.txn.iter_tree(fileid, None) {
Ok(iter) => iter,
Err(e) => return Some(Err(e.0)),
};
for x in iter {
let (k, v) = match x {
Ok(x) => x,
Err(e) => return Some(Err(e.0)),
};
impl<'txn, 'channel, T: TxnT> Iterator for GraphDescendants<'txn, 'channel, T> {
type Item = Position<ChangeId>;
impl<'txn, 'channel, T: GraphTxnT> Iterator for GraphDescendants<'txn, 'channel, T> {
type Item = Result<Position<ChangeId>, T::GraphError>;
if let Some(child) = adj.next() {
self.stack.push(adj);
let dest = find_block(self.txn, &self.channel, child.dest).unwrap();
let grandchild = iter_adjacent(
self.txn,
&self.channel,
dest,
EdgeFlags::FOLDER,
EdgeFlags::FOLDER | EdgeFlags::PSEUDO | EdgeFlags::BLOCK,
)
.next()
.unwrap();
if self.visited.insert(grandchild.dest) {
self.stack.push(iter_adjacent(
match adj.next() {
Some(Ok(child)) => {
self.stack.push(adj);
let dest = match find_block(self.txn, self.channel, child.dest) {
Ok(dest) => dest,
Err(BlockError::Txn(t)) => return Some(Err(t)),
Err(e) => panic!("{}", e),
};
let grandchild = match iter_adjacent(
))
) {
Ok(mut x) => match x.next().unwrap() {
Ok(x) => x,
Err(e) => return Some(Err(e.0)),
},
Err(e) => return Some(Err(e.0)),
};
if self.visited.insert(grandchild.dest) {
match iter_adjacent(
self.txn,
self.channel,
grandchild.dest.inode_vertex(),
EdgeFlags::FOLDER,
EdgeFlags::FOLDER | EdgeFlags::PSEUDO | EdgeFlags::BLOCK,
) {
Ok(adj) => self.stack.push(adj),
Err(e) => return Some(Err(e.0)),
}
}
return Some(Ok(grandchild.dest));
self.adj.next().map(move |child| {
let dest = find_block(self.txn, &self.channel, child.dest).unwrap();
let mut buf = std::mem::replace(&mut self.buf, Vec::new());
self.changes
.get_contents(|p| self.txn.get_external(p), dest, &mut buf)
.unwrap();
self.buf = buf;
let (perms, basename) = self.buf.split_at(2);
let perms = InodeMetadata::from_basename(perms);
let basename = std::str::from_utf8(basename).unwrap();
let child = match self.adj.next()? {
Ok(child) => child,
Err(e) => return Some(Err(e.0)),
};
let dest = find_block(self.txn, self.channel, child.dest).unwrap();
let mut buf = std::mem::replace(&mut self.buf, Vec::new());
self.changes
.get_contents(|p| self.txn.get_external(p).unwrap(), dest, &mut buf)
.unwrap();
self.buf = buf;
let (perms, basename) = self.buf.split_at(2);
let perms = InodeMetadata::from_basename(perms);
let basename = std::str::from_utf8(basename).unwrap();
let grandchild = iter_adjacent(
self.txn,
&self.channel,
dest,
EdgeFlags::FOLDER,
EdgeFlags::FOLDER | EdgeFlags::PSEUDO | EdgeFlags::BLOCK,
)
.next()
.unwrap();
(grandchild.dest, perms, basename.to_string())
})
let grandchild = match iter_adjacent(
self.txn,
self.channel,
dest,
EdgeFlags::FOLDER,
EdgeFlags::FOLDER | EdgeFlags::PSEUDO | EdgeFlags::BLOCK,
) {
Ok(mut adj) => match adj.next() {
Some(Ok(n)) => n,
None => unreachable!(),
Some(Err(e)) => return Some(Err(e.0)),
},
Err(e) => return Some(Err(e.0)),
};
Some(Ok((grandchild.dest, perms, basename.to_string())))
)
.next()
{
return Some((grandparent.dest, perms, basename));
) {
Ok(mut adj) => match adj.next() {
Some(Ok(grandparent)) => return Some(Ok((grandparent.dest, perms, basename))),
Some(Err(e)) => return Some(Err(e.0)),
None => {}
},
Err(e) => return Some(Err(e.0)),
for (_, parent) in iter_graph(txn, &channel.graph, cur_key.inode_vertex(), Some(e))
.take_while(|&(k, _)| k == cur_key.inode_vertex())
.filter(|&(_, ref v)| v.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT))
{
let parent_dest = find_block_end(txn, &channel, parent.dest).unwrap();
for (_, grandparent) in iter_graph(txn, &channel.graph, parent_dest, Some(e))
.take_while(|&(k, _)| k == parent_dest)
.filter(|&(_, ref v)| v.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT))
{
stack.push((grandparent.dest, false))
for x in iter_graph(txn, &graph, cur_key.inode_vertex(), Some(e)).map_err(|e| e.0)? {
let (k, parent) = x.map_err(|e| e.0)?;
if k != cur_key.inode_vertex() {
break;
} else if !parent.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT) {
continue;
}
let parent_dest = find_block_end(txn, &graph, parent.dest).unwrap();
for x in iter_graph(txn, &graph, parent_dest, Some(e)).map_err(|e| e.0)? {
let (k, grandparent) = x.map_err(|e| e.0)?;
if k != parent_dest {
break;
}
if grandparent
.flag
.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT)
{
stack.push((grandparent.dest, false))
}
for name in iter_adjacent(txn, &channel, current.inode_vertex(), flag0, flag1) {
let name_dest = find_block(txn, &channel, name.dest).unwrap();
for name in iter_adjacent(txn, &channel.graph, current.inode_vertex(), flag0, flag1)? {
let name = name?;
let name_dest = find_block(txn, &channel.graph, name.dest).unwrap();
if let Some(next) = iter_adjacent(txn, channel, name_dest, flag0, flag1)
.find(|e| e.flag.contains(EdgeFlags::PARENT | EdgeFlags::FOLDER))
{
let mut next = None;
for e in iter_adjacent(txn, &channel.graph, name_dest, flag0, flag1)? {
let e = e?;
if e.flag.contains(EdgeFlags::PARENT | EdgeFlags::FOLDER) {
next = Some(e);
break;
}
}
if let Some(next) = next {
)
.filter(|e| e.flag.contains(EdgeFlags::PARENT) && !e.flag.contains(EdgeFlags::PSEUDO))
{
let previous = v.flag - EdgeFlags::PARENT;
)? {
let e = e?;
if !e.flag.contains(EdgeFlags::PARENT) || e.flag.contains(EdgeFlags::PSEUDO) {
continue;
}
let previous = e.flag - EdgeFlags::PARENT;
pub fn dependencies<'a, Local: 'a, I: Iterator<Item = &'a Record<Option<Hash>, Local>>, T: TxnT>(
pub fn dependencies<
'a,
Local: 'a,
I: Iterator<Item = &'a Record<Option<Hash>, Local>>,
T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>,
>(
add_zombie_deps_from(txn, &channel, &mut zombie_deps, e.from);
add_zombie_deps_to(txn, &channel, &mut zombie_deps, e.to)
add_zombie_deps_from(txn, &channel.graph, &mut zombie_deps, e.from)?;
add_zombie_deps_to(txn, &channel.graph, &mut zombie_deps, e.to)?
pub fn full_dependencies<T: TxnT>(txn: &T, channel: &ChannelRef<T>) -> (Vec<Hash>, Vec<Hash>) {
pub fn full_dependencies<T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>>(
txn: &T,
channel: &ChannelRef<T>,
) -> Result<(Vec<Hash>, Vec<Hash>), TxnErr<T::DepsError>> {
for (_, (ch, _)) in changeid_log(txn, &channel, 0) {
let h = txn.get_external(ch).unwrap();
for x in changeid_log(txn, &channel, 0)? {
let (_, (ch, _)) = x?;
let h = txn.get_external(ch)?.unwrap();
for edge in iter_adj_all(txn, channel, from) {
if let Some(ext) = txn.get_external(edge.introduced_by) {
for edge in iter_adj_all(txn, channel, from)? {
let edge = edge?;
if let Some(ext) = txn.get_external(edge.introduced_by)? {
for edge in iter_adj_all(txn, channel, to) {
if let Some(ext) = txn.get_external(edge.introduced_by) {
for edge in iter_adj_all(txn, channel, to)? {
let edge = edge?;
if let Some(ext) = txn.get_external(edge.introduced_by)? {
fn minimize_deps<T: TxnT>(txn: &T, channel: &Channel<T>, deps: &BTreeSet<Hash>) -> Vec<Hash> {
fn minimize_deps<T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>>(
txn: &T,
channel: &Channel<T>,
deps: &BTreeSet<Hash>,
) -> Result<Vec<Hash>, TxnErr<T::DepsError>> {
add_name: add_name.globalize(txn),
add_inode: add_inode.globalize(txn),
contents: contents.as_ref().map(|add| add.globalize(txn)),
add_name: add_name.globalize(txn)?,
add_inode: add_inode.globalize(txn)?,
contents: contents.as_ref().map(|add| add.globalize(txn).unwrap()),
#[error(transparent)]
Block(#[from] crate::pristine::BlockError),
#[error(transparent)]
InconsistentChange(#[from] crate::pristine::InconsistentChange),
#[error("Block error: {:?}", block)]
Block { block: Position<ChangeId> },
#[error("Invalid change")]
InvalidChange,
MissingError::Block(e) => LocalApplyError::Block(e),
MissingError::Inconsistent(e) => LocalApplyError::InconsistentChange(e),
MissingError::Block(e) => e.into(),
MissingError::Inconsistent(_) => LocalApplyError::InvalidChange,
}
}
}
impl<T: std::error::Error> From<crate::pristine::InconsistentChange<T>> for LocalApplyError<T> {
fn from(err: crate::pristine::InconsistentChange<T>) -> Self {
match err {
InconsistentChange::Txn(e) => LocalApplyError::Txn(e),
_ => LocalApplyError::InvalidChange,
}
}
}
impl<T: std::error::Error> From<crate::pristine::TxnErr<T>> for LocalApplyError<T> {
fn from(err: crate::pristine::TxnErr<T>) -> Self {
LocalApplyError::Txn(err.0)
}
}
impl<C: std::error::Error, T: std::error::Error> From<crate::pristine::TxnErr<T>>
for ApplyError<C, T>
{
fn from(err: crate::pristine::TxnErr<T>) -> Self {
LocalApplyError::Txn(err.0).into()
}
}
impl<T: std::error::Error> From<crate::pristine::BlockError<T>> for LocalApplyError<T> {
fn from(err: crate::pristine::BlockError<T>) -> Self {
match err {
BlockError::Txn(e) => LocalApplyError::Txn(e),
BlockError::Block { block } => LocalApplyError::Block { block },
let internal: ChangeId = make_changeid(txn, &hash);
register_change(txn, internal, hash, &change).map_err(LocalApplyError::Txn)?;
let internal: ChangeId = make_changeid(txn, &hash)?;
register_change(txn, internal, hash, &change)?;
let internal: ChangeId = make_changeid(txn, &hash);
register_change(txn, internal, hash, &change).map_err(LocalApplyError::Txn)?;
let internal: ChangeId = make_changeid(txn, &hash)?;
register_change(txn, internal, hash, &change)?;
let merkle = if let Some(m) = txn
.put_changes(channel, change_id, channel.apply_counter, hash)
.map_err(LocalApplyError::Txn)?
{
m
} else {
return Err(LocalApplyError::ChangeAlreadyOnChannel { hash: *hash });
};
let merkle =
if let Some(m) = txn.put_changes(channel, change_id, channel.apply_counter, hash)? {
m
} else {
return Err(LocalApplyError::ChangeAlreadyOnChannel { hash: *hash });
};
put_newedge(txn, channel, ws, change_id, n.inode, edge, |_, _, _, _| {
Ok::<bool, LocalApplyError<T::Error>>(true)
})?;
put_newedge(
txn,
&mut channel.graph,
ws,
change_id,
n.inode,
edge,
|_, _, _, _| Ok::<bool, LocalApplyError<T::GraphError>>(true),
)?;
repair_missing_contexts(txn, channel, ws, change_id, change)?;
repair_cyclic_paths(txn, channel, ws)?;
repair_missing_contexts(txn, &mut channel.graph, ws, change_id, change)?;
repair_cyclic_paths(txn, &mut channel.graph, ws)?;
if let Some(parent) = txn.get_revtree(inode, None).map(|x| x.to_owned()) {
del_tree_with_rev(txn, parent.as_file_id(), inode).map_err(LocalApplyError::Txn)?;
if let Some(parent) = txn.get_revtree(inode, None)?.map(|x| x.to_owned()) {
del_tree_with_rev(txn, parent.as_file_id(), inode)?;
)
.map_err(LocalApplyError::Txn)?;
if let Some(vertex) = txn.get_inodes(inode, None) {
del_inodes_with_rev(txn, inode, vertex).map_err(LocalApplyError::Txn)?;
)?;
if let Some(vertex) = txn.get_inodes(inode, None)? {
del_inodes_with_rev(txn, inode, vertex)?;
if put_up_context(txn, channel, ch, ws, up)? && n.flag.contains(EdgeFlags::FOLDER) {
return Err(LocalApplyError::INCONSISTENT);
if put_up_context(txn, graph, ch, ws, up)? && n.flag.contains(EdgeFlags::FOLDER) {
return Err(LocalApplyError::InvalidChange);
if put_down_context(txn, channel, ch, ws, down)? && !n.flag.contains(EdgeFlags::FOLDER) {
return Err(LocalApplyError::INCONSISTENT);
if put_down_context(txn, graph, ch, ws, down)? && !n.flag.contains(EdgeFlags::FOLDER) {
return Err(LocalApplyError::InvalidChange);
) -> Result<bool, LocalApplyError<T::Error>> {
let k = find_block(txn, &channel, down)?;
) -> Result<bool, LocalApplyError<T::GraphError>> {
let k = find_block(txn, &graph, down)?;
T: MutTxnT,
E: From<LocalApplyError<T::Error>>,
F: Fn(&mut T, &mut Channel<T>, Vertex<ChangeId>, Vertex<ChangeId>) -> Result<bool, E>,
T: GraphMutTxnT,
E: From<LocalApplyError<T::GraphError>> + From<TxnErr<T::GraphError>>,
F: Fn(&mut T, &mut T::Graph, Vertex<ChangeId>, Vertex<ChangeId>) -> Result<bool, E>,
let mut source = find_source_vertex(txn, channel, &n.from, change, inode, n.flag, ws)?;
let mut target = find_target_vertex(txn, channel, &n.to, change, inode, n.flag, ws)?;
let mut source = find_source_vertex(txn, graph, &n.from, change, inode, n.flag, ws)?;
let mut target = find_target_vertex(txn, graph, &n.to, change, inode, n.flag, ws)?;
del_graph_with_rev(txn, channel, n.previous, source, target, n_introduced_by)
.map_err(LocalApplyError::Txn)?;
if apply_check(txn, channel, source, target)? {
put_graph_with_rev(txn, channel, n.flag, source, target, change)
.map_err(LocalApplyError::Txn)?;
del_graph_with_rev(txn, graph, n.previous, source, target, n_introduced_by)?;
if apply_check(txn, graph, source, target)? {
put_graph_with_rev(txn, graph, n.flag, source, target, change)?;
debug_assert!(is_alive(txn, channel, c));
put_graph_with_rev(txn, channel, EdgeFlags::PSEUDO, p, c, ChangeId::ROOT)
.map_err(LocalApplyError::Txn)?;
debug_assert!(is_alive(txn, channel, c).unwrap());
put_graph_with_rev(txn, channel, EdgeFlags::PSEUDO, p, c, ChangeId::ROOT)?;
) -> Option<AliveVertex> {
let vertex = crate::pristine::find_block(txn, &channel, pos).unwrap();
if !is_alive(txn, &channel, vertex) {
return None;
) -> Result<Option<AliveVertex>, TxnErr<T::GraphError>> {
let vertex = crate::pristine::find_block(txn, graph, pos).unwrap();
if !is_alive(txn, graph, vertex)? {
return Ok(None);
}
let mut flags = Flags::empty();
for e in crate::pristine::iter_adjacent(
txn,
graph,
vertex,
EdgeFlags::PARENT | EdgeFlags::DELETED | EdgeFlags::BLOCK,
EdgeFlags::all(),
)? {
if e?
.flag
.contains(EdgeFlags::PARENT | EdgeFlags::DELETED | EdgeFlags::BLOCK)
{
flags = Flags::ZOMBIE;
break;
}
flags: if crate::pristine::iter_adjacent(
txn,
&channel,
vertex,
EdgeFlags::PARENT | EdgeFlags::DELETED | EdgeFlags::BLOCK,
EdgeFlags::all(),
)
.any(|e| {
e.flag
.contains(EdgeFlags::PARENT | EdgeFlags::DELETED | EdgeFlags::BLOCK)
}) {
Flags::ZOMBIE
} else {
Flags::empty()
},
flags,
})
.min()
.unwrap(),
PathElement::Conflict { ref sides } => sides
.iter()
.map(|x| {
x.path
.iter()
.map(|x| x.oldest_vertex(changes, txn, channel, graph, sccs))
.min()
.unwrap()
})
.min()
.unwrap(),
}
Ok(min.unwrap())
}
PathElement::Conflict { ref sides } => {
let mut min: Option<u64> = None;
for x in sides.iter() {
for y in x.path.iter() {
let t = y.oldest_vertex(changes, txn, channel, graph, sccs)?;
if let Some(ref mut m) = min {
*m = (*m).min(t)
} else {
min = Some(t)
}
}
}
Ok(min.unwrap())
}
for (_, v) in crate::pristine::iter_graph(txn, &channel.graph, line.vertex, None)
.take_while(|&(k, _)| k == line.vertex)
{
for x in crate::pristine::iter_graph(txn, &channel, line.vertex, None).unwrap() {
let (k, v) = x.unwrap();
if k != line.vertex {
break;
}
resolvedDefaultFeatures = [ "canonical-path" "default" "dump" "flate2" "ignore" "mmap" "ondisk-repos" "regex" "tar" "tarball" "text-changes" "tokio" "zstd" "zstd-seekable" ];
resolvedDefaultFeatures = [ "canonical-path" "default" "dump" "flate2" "ignore" "lru-cache" "mmap" "ondisk-repos" "regex" "tar" "tarball" "tempfile" "text-changes" "tokio" "zstd" "zstd-seekable" ];