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>>whereT: 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" ];