YN63NUZO4LVJ7XPMURDULTXBVJKW5MVCTZ24R7Z52QMHO3HPDUVQC
GMGTWOWOPYCGOD3QEQAF5PSQVZWURAIVU6S6URXNHDAGQSC4P3EAC
SPA2OL5ITFMLB5P2WL342QAU2FXPKSFS4XHAMW6HYWOGSGLO2MJAC
ZXCRG5RPZU7DKPFI24IRLHV4DZSB6NJKA73J6FC7ARXT2KGOIV7QC
ZAEUSICJC3YOWGF6NZEQCQ34PHPRSBCJEP7FIWE6VIWJGVU734HQC
NO2QPRFLGCYUDXYJTOY3S3NZJCCLAFOQUHITKDZ7LSZLRLOV5W3QC
CZX6TRWR53F2BRLKSUTBPEONKS65IYNBO2FYB4HSWF6OK7DOEJGAC
2BKYJ2JM5PTXWO6HTVBKFQANWWSCJ4UHJYKAXWGTVZB35AZJ76CQC
JACZYXK43IU5HWLHQBY3BOAE7CUO6NGEXQ3HSZL3CQP3SLGKMBOAC
U4F5G3AU7NBRVVLBLLWU774XAFNB6M5KHK4ENNDQN4FR6HUUNOQQC
EGSVRZJVIBSPYAI65A25CH5RYAGL4PUP3B24VSRUS3M4WIUCZWHAC
ZZXBHCN3WGJG26SBKZP3ZG4FYUKY7WK2EDSDXLDMQLK7PDKXISPQC
KWAGWB73AMLJFK2Z7SBKHHKKHFRX7AQKXCWDN2MBX72RYCNMB36QC
44BN7FWSIXKG75IJUTCXLJE7VANNQFPRHQXTPLQHFU7AKGLSPQRAC
LGEJSLTYI7Y2CYC3AN6ECMT3D3MTWCAKZPVQEG5MPM2OBW5FQ46AC
JGJOYE3JQD7RJVM2RLMFX4QWOZ62V6RZ4RARBW6JUIJTEQG4ORJQC
EQLDTLXVCARE36EJE3S6SNEVTW2JJY4EYD36EX7WSIFLG2XMKKQAC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
G734WNM64AR5BLAZMN5MDPKSFTYXTUQR6MAGB32NRBC5FXFRWSJAC
UZZQ3VIA4YVL7C6P22LBPWWPB4BKH6VQLYKVHGQ3XRFISKM52TRQC
CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC
GHO6DWPILBBTL6CVZKERJBTFL3EY6ZT4YM4E5R4S6YPGVFKFHCVAC
VO5OQW4W2656DIYYRNZ3PO7TQ4JOKQ3GVWE5ALUTYVMX3WMXJOYQC
L4JXJHWXYNCL4QGJXNKKTOKKTAXKKXBJUUY7HFZGEUZ5A2V5H34QC
JL4WKA5PBKXRNAMETYO4I52QKASQ3COYHH2JKGA7W5YLIRZZH53AC
MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC
I52XSRUH5RVHQBFWVMAQPTUSPAJ4KNVID2RMI3UGCVKFLYUO6WZAC
UDHP4ZVBQZT2VBURB2MDCU2IZDNMCAFSIUKWRBDQ5BWMFKSN2LYQC
QE64ATLZWMKHYABCD3VA547PYXCK6YN3K7RE2TX3SCQNKG7XLVAQC
Q45QHPO4HDTEZF2W4UDZSYYQ46BPEIWSW4GJILZR5HTJNLKXJABQC
KTTKF3RWYAK2YSH2DYYW5QVG4KSNGWUBJBFHKE24OJ7LFCBF5FEAC
WLUID7NANDWTN5GOECNEKFTLZF3MUVS7K26YWLYLSGJ56G63NV4QC
3KRGVQFUWFHPOGZOXVTJYNCM4XBRVYITAEOVPKBSAZ5GZIUO5KVQC
XA23FMQM2AI7RMR36AYN7UNP2D5JWVJMJPHURWZO7URM7H46PU6AC
76PCXGML77EZWTRI5E6KHLVRAFTJ2AB5YRN5EKOYNAPKTWY2KCGAC
X6YFD4WVMUYJCR5IYPJH6UKYVWSA7DKBRVJ6XQFXHOE2TRYUTAHAC
WZVCLZKY34KQBQU6YBGJLQCDADBQ67LQVDNRVCMQVY3O3C3EIWSQC
TZVUNELWO5SIK7FKUTAR3ORAV2YYDFJ3EO7CTUOBDX4TXZOL5L3AC
64M73LNCB2V57AWAAKHK2NNERXANMV5V3XI3TFC4XR7FLJNCDCRQC
SNZ3OAMCPUGFYON5SZHQQQK46ZZMVMJECJYEUCMG657UVLY2PNBQC
SLJ3OHD4F6GJGZ3SV2D7DMR3PXYHPSI64X77KZ3RJ24EGEX6ZNQAC
YAJAXIV5VL263Z6FYLKFPROB3MQPRPH22P44GRGRVGEP56HOMBOAC
3AMEP2Y5J6GA4AWQONF4JVA3XSR3ASLHHKMYG44R72SOUY3UQCDAC
5DVRL6MFXQOCPOZMYSKBERMRRVUTYRL2SRGRTU2MH4IEOFCDKM3QC
VNBLGT6GAN2AHKRFKTKED7WNDDRGNULY5H343ZYV3ETSDZZKGBTAC
QMTANHVNRPQ5IX66FYQBFRBDCTN6YKMNCO6OHTQ6QCUASPWWXJKAC
MF3WAHBIH6Q2F7ZOKWPEJF6VGSKJITWLR3Z64GTD6YQZNA5EATWQC
G6S6PWZEFJK7ARWBIFKDU6VYC5DCJ2YFJMWZOLLWWKU52R2QPXZAC
367UBQ6KNAKUEWG32R4QRJ6H7IE7NAZFOPTC3ZOE4Z6E44RV3ISQC
5HF7C67M4DZMYTCIG32XEQQ662AHQMIHTHUK7TAVSO52XLMFBZPAC
HSVGP2G4D2F56DS3YKZLSYPS4A5BNGH4NTAXAOZ57OCXFM3E5AYAC
PCEJFKFXAFGYGHMM4BOBGFV3WRFXEBF2UQYQHLJ7MURRYBKRM3EAC
BE7GUCI2N6TX3P2HRMFSH7XLJKILDPOKOXKA7HWOABBFNKCKMZLAC
PSKXR4QEPPVJZR777HW67IEHUPGZB44MFCNQ2KUS422Q3W22IQWAC
AEPEFS7O3YT7CRRFYQVJWUXUUSRGJ6K6XZQVK62B6N74UXOIFWYAC
VQPAUKBQ2POZKL7CZFAZK5ZQKEBYL27XZYZWYUSH5AH25KK6DWKAC
A6R6SGCPLFM45QNWJLISFBR3EEXVITYHCWEUOPNH4UIGIWJRTZAQC
R3H7D42UZ446V5TO2574BMAQQAYYJPEIMSZVDPAGVIYU2COJSWBAC
33SQMZYXPV2A3F7P6WBFKFO2BTQV6THSQXOLV3PCZASC6OTKVHTQC
5BRU2RRWOQBMS2V3RQM7PRFR5UILYZ73GISHAKJA6KIZGC5M2MFAC
7UPL3Y2A5QOBU6VIUHNWEFGSGQ5CMWGDGOVLRZ53UARXG3TDGLMAC
KQTD46KVVWMJ3W6O55BEJLCVTNTDLUH6QT46AEFT7OU2SELXG4IAC
6YMDOZIB5LVYLFIDGN2WNT5JTHEAMS4TFPVDEZ3OWXWOKJOC5QDAC
NMX52UOGRCY2O7HT7Q45KWISOHNV4PEEMLDYDBJ4QPDIMTVKKJ6AC
3M7WBE24JTPTHWQOU5PO2ZJYKPKEH2F6R4M6RWIRFG334PQEA55QC
CXM5CBS27BL35Z6TRCI7OS4AHWVJ4VFND7HECGAUC74ZQ5KFZXLAC
LLT3GY6ULCVHMO3VUSVI5H4O244Z3ULOWLTW2IGJXIA2TWIHJDSQC
VYHHOEYHO67JNJEODX5L3CQFIV3DAXZBBIQUOMCWJDYF3VWICDNQC
ZXTHL45OYLOICXTXXEQ6AMNSLMQFZ6BFUJWMO6LZOSDK7ERROC5AC
KDF6FJRVF72L274BEUJCTUKRFMNL6BDZMTVKDPEYGFX4TC3YOVSQC
PJ7T2VFLV5PYG3CV23GC2GIQETXKGC6CO74JBGREV3JC3LG5OXUAC
BZCGXVS77ZS3N4QPLIHNWZ3YFVV7H4PXQD3U6RN5ZFVOC7QL7MBQC
V2MDXX622MAXHXGLX7ERVKGYZVZDCYJIFET3TGGIK455XIADYJUAC
3YDPHBANMNSK7Z5SCG745VLTP4BBQWIXCJTQOSDI6UJGYR6S45EQC
QNJBR73KCSCCF6FTHGZDF2K7PZQL3EFKZFOBT77KYZBMALTTW6OQC
6RVT5X4LTRP5XHVDESXMIC2DHMT5MUQ24ZDWEBJ4XYTF6LJXK7CAC
HMMMKONLCRAXVT7SO2ITTFDOJIQKKVSRIZPXYVPDC34RCBHWMHVAC
BD5PC25AB5MKVIYDFSDGRZ4YGX4PKW4SMZ3YAYAPNA5HLDVJUR3QC
BXD3IQYNMKMI5BTANCF6NZHZP4CKPWADGJMBT2R3WTMKVKONT5QAC
IM6UFPOZHZTBMESRXGBALOAWJWUUDGLP2TVLSZ3RZPSJITKB3R7QC
27PYHR6LO4M4RMSMLVMUKSYNQ72V6RRMRXLYQI3JA3LBHJO747YAC
ATZ3BWSEFJBLVGDUZFESRNHVCIO6ZRZ3ALPANZSVGVO7A5BUAFQQC
BZSC7VMYSFRXDHDDAMCDR6X67FN5VWIBOSE76BQLX7OCVOJFUA3AC
OJZWJUF2TCGZ7RFVY6FPKBS5P3C4BGHZDPVH775OHVNVFMJICKNQC
LCERQSWMA2YKOPAPNZUSOQ7FLBGDHBZR33OHLYX7T4KTKULRMJDQC
6T5ULULMRGU5GJ3JQTEH2QFQN5IMP53TYFFXUT5UE6FA6WWFFMFAC
7T5STZYBIUN5AQPFKASNYO24QFLNBX3YCE4YIIXEQNJYR5LSZ6EQC
KD4JIMAE6M2LFWEHFPEL4RTRV7UWYWNGGS52N2TKQ42ZNFSNLCEQC
7A2TSC4PAKK3WOH3DMAJASCEC6D5JLJWNFWJTEEBE4CVS4K76PPQC
L5PHFTIERPDAFIOSHZSMAN2CUSFM626ISMGTDYRN5KWPLXCOVPXAC
UNZXTNSJI4YRY3EQ3M4HMBKQDNYDTY6B7IZRBNYGDJXTA2UKYWRAC
ZRUPLBBTT4S6S7A3LOAHG4ONYEGPA5CFO4L2XBCNFKK45MWX3BDAC
65S67T3EKKLFRBCU73Z542V7A4JSMGP37OJINON6N563UIBQAITAC
73NW2X2MI767RYNTKS67ZB5QUWYEAA4SCORLD52K36ZU3JAK67AQC
7PM25EXLNQ6JUUIZNTAOQYNNIZNG6TJREEBUSAIC3FIOE7FHETSAC
GVQ7YSEDDCYYYWDJ5JUVFSBWA5EZVOZJI63KK6E46N6Y2B6LP72AC
43AJ37IXON6PMMYRZM6OB2MJXPYCNIWW2XBDVNBXIRH5DD7JDTVQC
NA5I4WYNE2O3LPSHXGWXW7XL4YNYFDREEGDOP6LJ5HJXTQDXM7BAC
3WIQYEISUMGOL5FY4LCWOJS55CTTQA7WMJZXAE3Q4GQUTBFLAE7QC
WEHUTJUKHOJIBMEK2M7ILPK532FMO7YGWTEAHOIXZP5WOOOSF3ZAC
6DOXSHWGKJIMIPFCNLASGKBAJCJMJULW5HFRZAZ67EYSMXXGJ3KAC
H62VFFJEBL2I3O4D3BAJZ57ROPWUISC7JCDIWFBC5DAYJRHMMDXAC
LYTVEPH3W5UHF7MAYFWBT6NVNC42HEVKJGGMFDKUDZDNDOI33YJQC
XWETQ4DE4KL2GQWSEBE5NENLTSLIDF7RIWOCCVWJFQOVQJE5P33AC
JRENVH5DF2F4SOV7UNJENFA7VDI3H63XK76R3LFZK6QCW7JIBLSQC
UFCZKKLXVYQYQBYENCAFHY3ZPPSDAJJAIREZSYNQM4QNXV6G6RXAC
TPEH2XNBS5RO4IEVKENVF6P65AH7IX64KK2JAYMSJT3J5GXO67EAC
ENKQ3QZGH2QW246C7GSZRKYLODJOQHKZZSYV7QHB7VPOFP5PASVQC
B3QWIGDERNMB3M6P5WTWP5CN2DB3KCS7MVTEPC2XVJ237ZXVQGMAC
A3DMBJJAPLS6ASSZ7JVVVULRQNZCF2WKYTRUD7EY7PKVYABSATFAC
B5Z4IMEUYAEJPOU5EIAXI7VYZVUM6CWKV7CTSOXK3F4GXTNNMMAAC
JMBGCWM5FYXPAMTU5R7UCMBIHJMUVCT44B6KGQ7P7XZRX662TC4QC
BT2ZHPY4LTECZDNPNLX5IUAEA6CYB4RRBGVBXUNK3ARHMWQK7KHAC
(import
(fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/c71d063a2fce96001c7ef99b301dfbd0c29ebde1.tar.gz";
sha256 = "0vnbhqf0lc4mf2zmzqbfv6kqj9raijxz8xfaimxihz3c6s5gma2x";
})
{ src = ./.; }).shellNix.default
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "Pijul";
buildInputs = with pkgs; [
xxHash
zstd
libsodium
openssl
pkgconfig
] ++ lib.optionals stdenv.isDarwin
(with darwin.apple_sdk.frameworks; [
CoreServices
Security
SystemConfiguration
]);
}
# (import
# (fetchTarball {
# url = "https://github.com/edolstra/flake-compat/archive/c71d063a2fce96001c7ef99b301dfbd0c29ebde1.tar.gz";
# sha256 = "0vnbhqf0lc4mf2zmzqbfv6kqj9raijxz8xfaimxihz3c6s5gma2x";
# })
# { src = ./.; }).shellNix.default
};
let pre_ = proc_macro2::TokenStream::from_iter(next(&mut input_iter).into_iter());
let pre = if !pre_.is_empty() {
quote! {
let (key, value) = #pre_;
}
} else {
quote! {}
};
let post_ = proc_macro2::TokenStream::from_iter(next(&mut input_iter).into_iter());
let post = if post_.is_empty() {
quote! { if let Ok(x) = self.txn.get(&self.#name, key, value) {
Ok(x)
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
}
}
} else {
quote! { if let Ok(x) = self.txn.get(&self.#name, key, value) {
Ok(x . #post_)
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
}}
fn #name_get <'txn> (&'txn self, key: #key, value: Option<#value>) -> Result<Option<#value>, TxnErr<Self::#error>> {
use ::sanakirja::Transaction;
#pre
#post
fn #name_get <'txn> (&'txn self, key: &#key, value: Option<&#value>) -> Result<Option<&'txn #value>, TxnErr<Self::#error>> {
match ::sanakirja::btree::get(&self.txn, &self.#name, key, value) {
Ok(Some((k, v))) if k == key => Ok(Some(v)),
Ok(_) => Ok(None),
Err(e) => {
error!("{:?}", e);
Err(TxnErr(SanakirjaError::PristineCorrupt))
}
}
fn #name_get(&self, db: &Self::#name_capital, key: #key, value: Option<#value>) -> Result<Option<#value>, TxnErr<Self::#error>> {
use ::sanakirja::Transaction;
if let Ok(x) = self.txn.get(db, key, value) {
Ok(x)
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
fn #name_get<'txn>(&'txn self, db: &Self::#name_capital, key: &#key, value: Option<&#value>) -> Result<Option<&'txn #value>, TxnErr<Self::#error>> {
match ::sanakirja::btree::get(&self.txn, db, key, value) {
Ok(Some((k, v))) if k == key => Ok(Some(v)),
Ok(_) => Ok(None),
Err(e) => {
error!("{:?}", e);
Err(TxnErr(SanakirjaError::PristineCorrupt))
}
fn #name_get<'txn>(&'txn self, db: &Self::#name_capital, key: #key, value: Option<#value>) -> Result<Option<#value>, TxnErr<Self::#error>>;
fn #name_get<'txn>(&'txn self, db: &Self::#name_capital, key: &#key, value: Option<&#value>) -> Result<Option<&'txn #value>, TxnErr<Self::#error>>;
let pre = proc_macro2::TokenStream::from_iter(next(&mut input_iter).into_iter());
let post = proc_macro2::TokenStream::from_iter(next(&mut input_iter).into_iter());
let pre_init = if !pre.is_empty() {
quote! { let pos = #pre; }
} else {
quote! {}
};
let post = if !post.is_empty() {
quote! { . #post }
} else {
quote! {}
};
#pre_init
if let Ok((cursor, _)) = txn.txn.set_cursors(&db, pos) {
Ok(Cursor {
cursor,
txn,
marker: std::marker::PhantomData,
})
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
let mut cursor = ::sanakirja::btree::cursor::Cursor::new(&txn.txn, &db)?;
if let Some((k, v)) = pos {
cursor.set(&txn.txn, k, v)?;
#pre_init
let mut cursor = if pos.is_some() {
if let Ok((x, _)) = self.txn.set_cursors(&db, pos) {
x
} else {
return Err(TxnErr(SanakirjaError::PristineCorrupt))
}
} else if let Ok(x) = self.txn.set_cursors_last(&db) {
x
let mut cursor = ::sanakirja::btree::cursor::Cursor::new(&self.txn, &db)?;
if let Some((k, v)) = pos {
cursor.set(&self.txn, k, v)?;
#pre_init
let mut cursor = if let Ok((x, _)) = self.txn.set_cursors(&db, pos) {
x
} else {
return Err(TxnErr(SanakirjaError::PristineCorrupt))
};
let mut cursor = ::sanakirja::btree::cursor::Cursor::new(&self.txn, &db)?;
if let Some((k, v)) = pos {
cursor.set(&self.txn, k, v)?;
}
) -> Result<Option<(#key, #value)>, TxnErr<SanakirjaError>> {
let x = if let Ok(x) = unsafe { ::sanakirja::next(&self.txn, cursor) } {
) -> Result<Option<(&'txn #key, &'txn #value)>, TxnErr<SanakirjaError>> {
let x = if let Ok(x) = cursor.next(&self.txn) {
) -> Result<Option<(#key, #value)>, TxnErr<SanakirjaError>> {
let x = if let Ok(x) = unsafe { ::sanakirja::prev(&self.txn, cursor) } {
) -> Result<Option<(&'txn #key, &'txn #value)>, TxnErr<SanakirjaError>> {
let x = if let Ok(x) = cursor.next(&self.txn) {
impl<T: #txnt, RT: std::ops::Deref<Target = T>>
crate::pristine::Cursor<T, RT, T::#cursor_name, #key, #value>
impl<'a, T: #txnt>
crate::pristine::Cursor<T, &'a T, T::#cursor_name, #key, #value>
if pre_key.is_empty() {
proc_macro::TokenStream::from(quote! {
fn #put(
&mut self,
k: #key,
v: #value,
) -> Result<bool, TxnErr<Self::#error>> {
Ok(self.txn.put(&mut self.rng, &mut self.#name, k, v).map_err(TxnErr)?)
}
fn #del(
&mut self,
k: #key,
v: Option<#value>,
) -> Result<bool, TxnErr<Self::#error>> {
Ok(self.txn.del(&mut self.rng, &mut self.#name, k, v).map_err(TxnErr)?)
}
})
} else {
proc_macro::TokenStream::from(quote! {
fn #put(
&mut self,
k: #key,
v: #value,
) -> Result<bool, TxnErr<Self::#error>> {
let k = #pre_key;
let v = #pre_value;
Ok(self.txn.put(&mut self.rng, &mut self.#name, k, v).map_err(TxnErr)?)
}
fn #del(
&mut self,
k: #key,
v: Option<#value>,
) -> Result<bool, TxnErr<Self::#error>> {
let k = #pre_key;
let v = v.map(|v| #pre_value);
Ok(self.txn.del(&mut self.rng, &mut self.#name, k, v).map_err(TxnErr)?)
}
})
}
proc_macro::TokenStream::from(quote! {
fn #put(
&mut self,
k: &#key,
v: &#value,
) -> Result<bool, TxnErr<Self::#error>> {
Ok(::sanakirja::btree::put(&mut self.txn, &mut self.#name, k, v).map_err(TxnErr)?)
}
fn #del(
&mut self,
k: &#key,
v: Option<&#value>,
) -> Result<bool, TxnErr<Self::#error>> {
Ok(::sanakirja::btree::del(&mut self.txn, &mut self.#name, k, v).map_err(TxnErr)?)
}
})
impl Lock {
pub async fn mut_txn_lock<P: AsRef<Path>>(p: P) -> Result<Self, anyhow::Error> {
let pp = p.as_ref().join("db_lock");
Ok(Lock::MutTxn(mut_txn(&pp).await?))
}
pub async fn txn_lock<P: AsRef<Path>>(p: P) -> Result<Self, anyhow::Error> {
let pp = p.as_ref().join("db_lock");
Ok(Lock::Txn(txn(&pp).await?))
}
pub async fn commit(&mut self) -> Result<(), anyhow::Error> {
match self {
Lock::MutTxn(m) => m.commit().await,
_ => Ok(()),
}
}
}
}
use crate::{config, current_dir};
lock: if mutable {
lock::Lock::mut_txn_lock(&pristine_dir).await?
} else {
lock::Lock::txn_lock(&pristine_dir).await?
},
pristine: unsafe {
libpijul::pristine::sanakirja::Pristine::new_nolock(&pristine_dir)?
},
pristine: libpijul::pristine::sanakirja::Pristine::new(&pristine_dir.join("db"))?,
} else if let Ok(data) = std::str::from_utf8(&data) {
for l in data.lines() {
} else {
debug!("{:?}", data);
let mut p = 0;
while let Some(i) = (&data[p..]).iter().position(|i| *i == b'\n') {
let line = if !pending.is_empty() {
pending.extend(&data[p..p + i]);
&pending
} else {
&data[p..p + i]
};
let l = std::str::from_utf8(line)?;
Ok(())
}
pub async fn clone_channel<T: TxnTExt + MutTxnTExt>(
&mut self,
repo: &mut Repository,
txn: &mut T,
channel: &mut ChannelRef<T>,
lazy: bool,
) -> Result<(), anyhow::Error> {
let (sender, mut recv) = tokio::sync::mpsc::channel(10);
*self.state.lock().await = State::Channel { sender };
self.run_protocol().await?;
debug!("clone channel");
self.c
.data(format!("channel {}\n", self.channel).as_bytes())
.await?;
let progress = indicatif::ProgressBar::new_spinner();
progress.set_style(
indicatif::ProgressStyle::default_spinner().template("{spinner} Cloning channel"),
);
progress.enable_steady_tick(100);
*PROGRESS.lock().await = Some(progress);
let from_dump_alive = {
let mut from_dump =
libpijul::pristine::channel_dump::ChannelFromDump::new(txn, channel.clone());
debug!("receiving channel");
while let Some(msg) = recv.recv().await {
debug!("msg = {:?}", msg.len());
if from_dump.read(&msg)? {
debug!("break");
break;
}
}
debug!("from dump done");
from_dump.alive
};
if let Some(ref mut progress) = *PROGRESS.lock().await {
progress.set_style(
indicatif::ProgressStyle::default_spinner().template("✓ Cloning channel"),
);
progress.finish();
}
let channel_ = channel.borrow();
debug!("cloned, now downloading changes");
let mut hashes = Vec::new();
if lazy {
for &ch in from_dump_alive.iter() {
let h = txn.get_external(ch)?.unwrap();
hashes.push(h);
}
} else {
for h in txn.log(&channel_, 0)? {
hashes.push((h?.1).0);
}
}
std::mem::drop(channel_);
debug!("hashes = {:#?}", hashes);
self.download_changes_(&hashes, None, &mut repo.changes_dir, true)
.await?;
txn.output_repository_no_pending(
&mut repo.working_copy,
&repo.changes,
channel,
"",
true,
None,
)?;
let (mut b, (_, state)) = if let Some(last) = txn.last_remote(remote)? {
last
let (mut b, state): (_, Merkle) = if let Some((u, v)) = txn.last_remote(remote)? {
debug!("dichotomy_changelist: {:?} {:?}", u, v);
(u, (&v.b).into())
if let RemoteRepo::Ssh(ref mut s) = self {
s.clone_channel(repo, txn, channel, lazy).await?;
let mut to_unrecord = Vec::new();
let mut found = false;
for x in txn.iter_rev_remote(&remote.borrow().remote, None)? {
let (n, (h, s)) = x?;
debug!("{:?} {:?} {:?}", n, h, s);
if s == state {
found = true;
break;
}
to_unrecord.push(h);
}
if !found {
bail!("State not found: {:?}", state)
}
self.pull(repo, txn, channel, &to_unrecord, &HashSet::new(), false)
.await?;
for unrec in to_unrecord.iter() {
txn.unrecord(&repo.changes, channel, unrec)?;
}
return Ok(());
}
for x in libpijul::pristine::changeid_log(txn, chan, from)? {
let (n, (u, _)) = x?;
debug!("{:?} {:?} {:?}", n, u, from);
for x in libpijul::pristine::changeid_log(txn, chan, from.into())? {
let (n, p) = x?;
let n: u64 = (*n).into();
debug!("{:?} {:?} {:?}", n, p, from);
} else if let Some(cap) = CHANNEL.captures(&buf) {
let channel = load_channel(&txn, &cap[1])?;
let channel = channel.borrow();
for d in libpijul::pristine::channel_dump::dump_channel(&txn, channel)? {
o.write_all(&d?)?;
}
o.flush()?;
if let Some(inode) = txn.get_revinodes(pos, None)? {
del_inodes_with_rev(txn, inode, pos)?;
if let Some(&inode) = txn.get_revinodes(&pos, None)? {
del_inodes_with_rev(txn, &inode, &pos)?;
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)?;
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.into(), None)?;
if !e.flag.is_deleted() {
if e.flag.is_parent() {
if !e.flag.is_folder() {
let up_v = txn.find_block_end(channel, e.dest)?;
ws.up.insert(up_v, new_vertex.inode);
if !e.flag().is_deleted() {
if e.flag().is_parent() {
if !e.flag().is_folder() {
let up_v = txn.find_block_end(channel, e.dest())?;
ws.up.insert(*up_v, new_vertex.inode);
let down_v = txn.find_block(channel, e.dest)?;
ws.down.insert(down_v, new_vertex.inode);
if e.flag.is_folder() {
ws.apply.missing_context.files.insert(down_v);
let down_v = txn.find_block(channel, e.dest())?;
ws.down.insert(*down_v, new_vertex.inode);
if e.flag().is_folder() {
ws.apply.missing_context.files.insert(*down_v);
if e.flag.contains(EdgeFlags::PARENT)
|| e.dest != b.start_pos()
|| e.introduced_by.is_root()
|| e.introduced_by == current_id
if e.flag().contains(EdgeFlags::PARENT)
|| e.dest() != b.start_pos()
|| e.introduced_by().is_root()
|| e.introduced_by() == current_id
if e.flag.contains(EdgeFlags::PARENT) {
let u = txn.find_block_end(channel, e.dest)?;
e.flag -= EdgeFlags::PARENT;
del_graph_with_rev(txn, channel, e.flag, u, v, e.introduced_by)?;
if e.flag().contains(EdgeFlags::PARENT) {
let u = *txn.find_block_end(channel, e.dest())?;
e -= EdgeFlags::PARENT;
del_graph_with_rev(txn, channel, e.flag(), u, v, e.introduced_by())?;
let w = txn.find_block(channel, e.dest)?;
del_graph_with_rev(txn, channel, e.flag, v, w, e.introduced_by)?;
let w = *txn.find_block(channel, e.dest())?;
del_graph_with_rev(txn, channel, e.flag(), v, w, e.introduced_by())?;
assert_eq!(repo.list_files(), vec!["file"]);
// Checking that unrecord doesn't delete `dir`, and moves `file`
// back to the root.
let mut files = repo.list_files();
files.sort();
assert_eq!(files, vec!["dir", "file"]);
apply::apply_change(&changes, &mut txn2, &mut channel2, h0)?;
output::output_repository_no_pending(&mut repo2, &changes, &mut txn2, &mut channel2, "", true)?;
apply::apply_change(&changes, &mut txn3, &mut channel3, h0)?;
output::output_repository_no_pending(&mut repo3, &changes, &mut txn3, &mut channel3, "", true)?;
apply::apply_change(&changes, &mut txn2, &mut channel2, &h0)?;
output::output_repository_no_pending(&mut repo2, &changes, &mut txn2, &mut channel2, "", true, None)?;
apply::apply_change(&changes, &mut txn3, &mut channel3, &h0)?;
output::output_repository_no_pending(&mut repo3, &changes, &mut txn3, &mut channel3, "", true, None)?;
apply::apply_change(&changes, &mut txn, &mut channel, h2)?;
apply::apply_change(&changes, &mut txn, &mut channel, h3)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true)?;
apply::apply_change(&changes, &mut txn, &mut channel, &h2)?;
apply::apply_change(&changes, &mut txn, &mut channel, &h3)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true, None)?;
apply::apply_change(&changes, &mut txn2, &mut channel2, h0)?;
output::output_repository_no_pending(&mut repo2, &changes, &mut txn2, &mut channel2, "", true)?;
apply::apply_change(&changes, &mut txn2, &mut channel2, &h0)?;
output::output_repository_no_pending(&mut repo2, &changes, &mut txn2, &mut channel2, "", true, None)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true)?;
let files = repo.list_files();
if !files.is_empty() {
panic!("Files should be empty {:?}", files);
}
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true, None)?;
// Checking that unrecord doesn't delete files on the filesystem,
// but updates the tree/revtree tables.
let mut files = repo.list_files();
files.sort();
assert_eq!(files, &["dir", "dir/file"]);
apply::apply_change(&changes, &mut txn, &mut channelb, ha)?;
apply::apply_change(&changes, &mut txn, &mut channela, hb)?;
apply::apply_change(&changes, &mut txn, &mut channelb, &ha).unwrap();
apply::apply_change(&changes, &mut txn, &mut channela, &hb).unwrap();
let resb = record_all(&mut repo, &changes, &mut txn, &mut channela, "")?;
debug_to_file(&txn, &channela.borrow(), "debugres")?;
let resb = record_all(&mut repo, &changes, &mut txn, &mut channela, "").unwrap();
debug_to_file(&txn, &channela.borrow(), "debugres").unwrap();
let h_inv = changes.save_change(&p_inv)?;
apply::apply_change(&changes, &mut txn, &mut channela, h_inv)?;
debug_to_file(&txn, &channela.borrow(), "debug")?;
Ok(())
let h_inv = changes.save_change(&p_inv).unwrap();
apply::apply_change(&changes, &mut txn, &mut channela, &h_inv).unwrap();
debug_to_file(&txn, &channela.borrow(), "debug").unwrap();
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_h2)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_h2)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_h2)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_h2)?;
apply::apply_change(&changes, &mut txn, &mut channel, p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true)
apply::apply_change(&changes, &mut txn, &mut channel, &p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true, None)
apply::apply_change(&changes, &mut txn, &mut channel, p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true)
apply::apply_change(&changes, &mut txn, &mut channel, &p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true, None)
apply::apply_change(&changes, &mut txn, &mut channel, p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true)
apply::apply_change(&changes, &mut txn, &mut channel, &p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true, None)
apply::apply_change(&changes, &mut txn, &mut channel, p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true)
apply::apply_change(&changes, &mut txn, &mut channel, &p)?;
output::output_repository_no_pending(&mut repo, &changes, &mut txn, &mut channel, "", true, None)
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, bob_h)?;
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, alice_h)?;
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, &bob_h)?;
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, &alice_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, charlie_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &charlie_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, alice_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, charlie_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, &alice_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, &charlie_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, charlie_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &charlie_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, alice_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, charlie_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, &alice_h)?;
apply::apply_change(&changes, &mut txn_bob, &mut channel_bob, &charlie_h)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_h).unwrap();
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, bob_resolution).unwrap();
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_h).unwrap();
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &bob_resolution).unwrap();
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, init_h).unwrap();
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, alice_h).unwrap();
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, &init_h).unwrap();
apply::apply_change(&changes, &mut txn_charlie, &mut channel_charlie, &alice_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, alice_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, charlie_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, &alice_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, &charlie_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, alice_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, bob_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &alice_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &bob_h).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, resolution).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, resolution2).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &resolution).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &resolution2).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, alice_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, resolution)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, &alice_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, &resolution)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, alice_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, resolution)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, &alice_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, &resolution)?;
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, p_bob).unwrap();
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, resolution).unwrap();
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &p_bob).unwrap();
apply::apply_change(&changes, &mut txn_alice, &mut channel_alice, &resolution).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, alice_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, resolution)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, &alice_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, &resolution)?;
apply::apply_change(&changes, &mut txn, &mut channel_alice, bob_h1)?;
apply::apply_change(&changes, &mut txn, &mut channel_alice, bob_h2)?;
apply::apply_change(&changes, &mut txn, &mut channel_alice, bob_h3)?;
apply::apply_change(&changes, &mut txn, &mut channel_alice, &bob_h1)?;
apply::apply_change(&changes, &mut txn, &mut channel_alice, &bob_h2)?;
apply::apply_change(&changes, &mut txn, &mut channel_alice, &bob_h3)?;
apply::apply_change(&changes, &mut txn, &mut channel_bob, alice_h1).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, alice_h2).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, alice_h3).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, &alice_h1).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, &alice_h2).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_bob, &alice_h3).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, init_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, alice_h1)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, alice_h2)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, alice_h3)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, bob_h1)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, bob_h2)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, bob_h3)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &init_h)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &alice_h1)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &alice_h2)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &alice_h3)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &bob_h1)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &bob_h2)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &bob_h3)?;
apply::apply_change(&changes, &mut txn, &mut channel_charlie, alices_resolution).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, bobs_resolution).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &alices_resolution).unwrap();
apply::apply_change(&changes, &mut txn, &mut channel_charlie, &bobs_resolution).unwrap();
apply::apply_change(&store, &mut txn2, &mut channel2, h0)?;
apply::apply_change(&store, &mut txn2, &mut channel2, h1)?;
apply::apply_change(&store, &mut txn2, &mut channel2, h2)?;
output::output_repository_no_pending(&mut repo2, &store, &mut txn2, &mut channel2, "", true)?;
apply::apply_change(&store, &mut txn2, &mut channel2, &h0)?;
apply::apply_change(&store, &mut txn2, &mut channel2, &h1)?;
apply::apply_change(&store, &mut txn2, &mut channel2, &h2)?;
output::output_repository_no_pending(&mut repo2, &store, &mut txn2, &mut channel2, "", true, None)?;
apply::apply_change(&store, &mut txn2, &mut channel2, h3)?;
output::output_repository_no_pending(&mut repo2, &store, &mut txn2, &mut channel2, "", true)?;
apply::apply_change(&store, &mut txn2, &mut channel2, &h3)?;
output::output_repository_no_pending(&mut repo2, &store, &mut txn2, &mut channel2, "", true, None)?;
impl std::ops::Deref for SmallString {
type Target = SmallStr;
fn deref(&self) -> &Self::Target {
let len = self.len as usize;
unsafe {
std::mem::transmute(std::slice::from_raw_parts(self as *const Self as *const u8, 1 + len))
}
}
}
impl AsRef<SmallStr> for SmallString {
fn as_ref(&self) -> &SmallStr {
let len = self.len as usize;
unsafe {
std::mem::transmute(std::slice::from_raw_parts(self as *const Self as *const u8, 1 + len))
}
}
}
impl AsMut<SmallStr> for SmallString {
fn as_mut(&mut self) -> &mut SmallStr {
let len = self.len as usize;
unsafe {
std::mem::transmute(std::slice::from_raw_parts_mut(self as *mut Self as *mut u8, 1 + len))
}
}
}
impl std::ops::DerefMut for SmallString {
fn deref_mut(&mut self) -> &mut Self::Target {
let len = self.len as usize;
unsafe {
std::mem::transmute(std::slice::from_raw_parts_mut(self as *mut Self as *mut u8, 1 + len))
}
}
}
}
/// ```ignore
/// use libpijul::small_string::*;
/// let mut s = SmallString::from_str("blah");
/// let s_ = s.as_small_str();
/// let s2_ = s_;
/// let s3_ = s_.clone();
/// assert_eq!(s_, s2_);
/// assert_eq!(s_, s3_);
/// ```
pub fn as_small_str(&self) -> SmallStr {
SmallStr {
p: self as *const SmallString as *const u8,
marker: std::marker::PhantomData,
}
/// An internal "unsafe" version of a [`small_string::SmallStr`], used
/// to circumvent the absence of associated type constructors in Rust
/// (else this would be borrow on a table).
#[derive(Clone, Copy)]
#[doc(hidden)]
pub struct UnsafeSmallStr(*const u8);
impl sanakirja::UnsizedStorable for SmallStr {
const ALIGN: usize = 1;
unsafe fn write_to_page(&self, p: *mut u8) {
std::ptr::copy(&self.len, p, 1 + self.len as usize);
debug!("writing {:?}", std::slice::from_raw_parts(p, 1+self.len as usize));
}
unsafe fn from_raw_ptr<'a, T>(_: &T, p: *const u8) -> &'a Self {
smallstr_from_raw_ptr(p)
}
unsafe fn onpage_size(p: *const u8) -> usize {
let len = *p as usize;
debug!("onpage_size {:?}", std::slice::from_raw_parts(p, 1+len as usize));
1 + len
}
impl sanakirja::Representable for UnsafeSmallStr {
fn alignment() -> sanakirja::Alignment {
sanakirja::Alignment::B1
}
fn onpage_size(&self) -> u16 {
unsafe {
let len = (*self.0) as u16;
1 + len
}
}
unsafe fn write_value(&self, p: *mut u8) {
std::ptr::copy(self.0, p, self.onpage_size() as usize)
}
unsafe fn read_value(p: *const u8) -> Self {
UnsafeSmallStr(p)
}
unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
let a = UnsafeSmallStr(self.0).to_small_str();
let b = x.to_small_str();
a.as_str().cmp(b.as_str())
}
type PageOffsets = std::iter::Empty<u64>;
fn page_offsets(&self) -> Self::PageOffsets {
std::iter::empty()
unsafe fn smallstr_from_raw_ptr<'a>(p: *const u8) -> &'a SmallStr {
let len = *p as usize;
std::mem::transmute(std::slice::from_raw_parts(p, 1 + len as usize))
}
#[test]
fn smallstr_repr() {
use sanakirja::UnsizedStorable;
let o = SmallString::from_str("blablabla");
let mut x = vec![0u8; 200];
unsafe {
o.write_to_page(x.as_mut_ptr());
let p = smallstr_from_raw_ptr(x.as_ptr());
assert_eq!(p.as_str(), "blablabla")
let end = ChangePosition(self.rec.contents.len() as u64);
self.rec.largest_file = self.rec.largest_file.max(end.0 - start.0);
let end = ChangePosition(self.rec.contents.len().into());
self.rec.largest_file = self.rec.largest_file.max(end.0.as_u64() - start.0.as_u64());
let child = txn.find_block(channel, child.dest).unwrap();
for grandchild in iter_adjacent(txn, channel, child, f0, f1)? {
let child = txn.find_block(channel, child.dest()).unwrap();
for grandchild in iter_adjacent(txn, channel, *child, f0, f1)? {
assert!(parent.flag.contains(EdgeFlags::FOLDER));
let parent_dest = txn.find_block_end(channel, parent.dest).unwrap();
assert!(parent.flag().contains(EdgeFlags::FOLDER));
let parent_dest = txn.find_block_end(channel, parent.dest()).unwrap();
assert!(grandparent.flag.contains(EdgeFlags::PARENT));
assert!(grandparent.flag.contains(EdgeFlags::FOLDER));
assert!(grandparent.flag().contains(EdgeFlags::PARENT));
assert!(grandparent.flag().contains(EdgeFlags::FOLDER));
previous: parent.flag - EdgeFlags::PARENT,
flag: (parent.flag - EdgeFlags::PARENT) | EdgeFlags::DELETED,
from: parent.dest.to_option(),
previous: parent.flag() - EdgeFlags::PARENT,
flag: (parent.flag() - EdgeFlags::PARENT) | EdgeFlags::DELETED,
from: parent.dest().to_option(),
pub(crate) const ROOT: ChangePosition = ChangePosition(0);
pub(crate) const BOTTOM: ChangePosition = ChangePosition(1);
pub(crate) const ROOT: ChangePosition = ChangePosition(L64(0u64));
pub(crate) const BOTTOM: ChangePosition = ChangePosition(L64(1u64.to_le()));
(self.0 - x.0) as usize
let a: u64 = self.0.into();
let b: u64 = x.0.into();
(a - b) as usize
}
}
impl ChangePosition {
pub(crate) fn us(&self) -> usize {
u64::from_le((self.0).0) as usize
}
}
impl From<ChangePosition> for u64 {
fn from(f: ChangePosition) -> u64 {
u64::from_le((f.0).0)
use crate::small_string;
use ::sanakirja::{Alignment, Commit, Db, Representable, Transaction, UnsafeDb};
use byteorder::{ByteOrder, LittleEndian};
use rand::rngs::ThreadRng;
use rand::thread_rng;
use ::sanakirja::*;
channels: txn.root(Root::Channels as usize)?,
external: txn.root(Root::External as usize)?,
internal: txn.root(Root::Internal as usize)?,
inodes: txn.root(Root::Inodes as usize)?,
revinodes: txn.root(Root::RevInodes as usize)?,
tree: txn.root(Root::Tree as usize)?,
revtree: txn.root(Root::RevTree as usize)?,
revdep: txn.root(Root::RevDep as usize)?,
touched_files: txn.root(Root::TouchedFiles as usize)?,
rev_touched_files: txn.root(Root::RevTouchedFiles as usize)?,
partials: txn.root(Root::Partials as usize)?,
dep: txn.root(Root::Dep as usize)?,
remotes: txn.root(Root::Remotes as usize)?,
rng: thread_rng(),
channels: txn.root_db(Root::Channels as usize)?,
external: txn.root_db(Root::External as usize)?,
internal: txn.root_db(Root::Internal as usize)?,
inodes: txn.root_db(Root::Inodes as usize)?,
revinodes: txn.root_db(Root::RevInodes as usize)?,
tree: txn.root_db(Root::Tree as usize)?,
revtree: txn.root_db(Root::RevTree as usize)?,
revdep: txn.root_db(Root::RevDep as usize)?,
touched_files: txn.root_db(Root::TouchedFiles as usize)?,
rev_touched_files: txn.root_db(Root::RevTouchedFiles as usize)?,
partials: txn.root_db(Root::Partials as usize)?,
dep: txn.root_db(Root::Dep as usize)?,
remotes: txn.root_db(Root::Remotes as usize)?,
pub type Txn = GenericTxn<
::sanakirja::Txn<::sanakirja::Exclusive, Arc<::sanakirja::Env<::sanakirja::Exclusive>>>,
>;
pub type MutTxn<T> =
GenericTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env<::sanakirja::Exclusive>>, T>>;
pub type Txn = GenericTxn<::sanakirja::Txn<Arc<::sanakirja::Env>>>;
pub type MutTxn<T> = GenericTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>, T>>;
partials: Db<UnsafeSmallStr, Position<ChangeId>>,
channels: Db<UnsafeSmallStr, (Graph, ChangeSet, RevChangeSet, ChannelStates, u64, u64)>,
remotes: Db<UnsafeSmallStr, (Db<u64, (Hash, Merkle)>, Db<Hash, u64>, Db<Merkle, u64>)>,
rng: ThreadRng,
open_channels: RefCell<HashMap<SmallString, ChannelRef<Self>>>,
partials: UDb<SmallStr, Position<ChangeId>>,
channels: UDb<SmallStr, T6>,
remotes: UDb<SmallStr, T3>,
pub(crate) open_channels: RefCell<HashMap<SmallString, ChannelRef<Self>>>,
pub fn check_database(&self) -> DatabaseReport {
let mut refs = HashMap::new();
self.txn.references(&mut refs, self.internal);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.external);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.inodes);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.revinodes);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.tree);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.revtree);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.revdep);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.dep);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.touched_files);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.rev_touched_files);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.partials);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, self.channels);
info!("refs = {:?}", refs);
for x in self.txn.iter(&self.channels, None).unwrap() {
let (a, (g, c, r, s, _, _)) = x.unwrap();
info!("channel = {:?}", a);
self.txn.references(&mut refs, g);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, c);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, r);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, s);
info!("refs = {:?}", refs);
pub fn check_database(&self) {
let mut refs = std::collections::BTreeMap::new();
debug!("check: internal 0x{:x}", self.internal.db);
::sanakirja::debug::add_refs(&self.txn, &self.internal, &mut refs).unwrap();
debug!("check: external 0x{:x}", self.external.db);
::sanakirja::debug::add_refs(&self.txn, &self.external, &mut refs).unwrap();
debug!("check: inodes 0x{:x}", self.inodes.db);
::sanakirja::debug::add_refs(&self.txn, &self.inodes, &mut refs).unwrap();
debug!("check: revinodes 0x{:x}", self.revinodes.db);
::sanakirja::debug::add_refs(&self.txn, &self.revinodes, &mut refs).unwrap();
debug!("check: tree 0x{:x}", self.tree.db);
::sanakirja::debug::add_refs(&self.txn, &self.tree, &mut refs).unwrap();
debug!("check: revtree 0x{:x}", self.revtree.db);
::sanakirja::debug::add_refs(&self.txn, &self.revtree, &mut refs).unwrap();
debug!("check: revdep 0x{:x}", self.revdep.db);
::sanakirja::debug::add_refs(&self.txn, &self.revdep, &mut refs).unwrap();
debug!("check: dep 0x{:x}", self.dep.db);
::sanakirja::debug::add_refs(&self.txn, &self.dep, &mut refs).unwrap();
debug!("check: touched_files 0x{:x}", self.touched_files.db);
::sanakirja::debug::add_refs(&self.txn, &self.touched_files, &mut refs).unwrap();
debug!("check: rev_touched_files 0x{:x}", self.rev_touched_files.db);
::sanakirja::debug::add_refs(&self.txn, &self.rev_touched_files, &mut refs).unwrap();
debug!("check: partials 0x{:x}", self.partials.db);
::sanakirja::debug::add_refs(&self.txn, &self.partials, &mut refs).unwrap();
debug!("check: channels 0x{:x}", self.channels.db);
::sanakirja::debug::add_refs(&self.txn, &self.channels, &mut refs).unwrap();
for x in btree::iter(&self.txn, &self.channels, None).unwrap() {
let (name, tup) = x.unwrap();
debug!("check: channel name: {:?}", name.as_str());
let graph: Db<Vertex<ChangeId>, SerializedEdge> = Db::from_page(tup.0[0].into());
let changes: Db<ChangeId, L64> = Db::from_page(tup.0[1].into());
let revchanges: UDb<L64, Pair<ChangeId, SerializedMerkle>> = UDb::from_page(tup.0[2].into());
let states: UDb<SerializedMerkle, L64> = UDb::from_page(tup.0[3].into());
debug!("check: graph 0x{:x}", graph.db);
::sanakirja::debug::add_refs(&self.txn, &graph, &mut refs).unwrap();
debug!("check: changes 0x{:x}", changes.db);
::sanakirja::debug::add_refs(&self.txn, &changes, &mut refs).unwrap();
debug!("check: revchanges 0x{:x}", revchanges.db);
::sanakirja::debug::add_refs(&self.txn, &revchanges, &mut refs).unwrap();
debug!("check: states 0x{:x}", states.db);
::sanakirja::debug::add_refs(&self.txn, &states, &mut refs).unwrap();
self.txn.references(&mut refs, self.remotes);
info!("refs = {:?}", refs);
for x in self.txn.iter(&self.remotes, None).unwrap() {
let (a, (u, v, w)) = x.unwrap();
info!("remote = {:?}", a);
self.txn.references(&mut refs, u);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, v);
info!("refs = {:?}", refs);
self.txn.references(&mut refs, w);
info!("refs = {:?}", refs);
}
let stats = self.txn.statistics();
let report = DatabaseReport {
refs: refs.len(),
stats: stats.clone(),
};
let mut channel_roots: Vec<UnsafeDb> = Vec::new();
for x in self.txn.iter(&self.channels, None).unwrap() {
let (a, (g, c, r, s, _, _)) = x.unwrap();
info!("channel: {:?}", a);
unsafe {
channel_roots.push(std::mem::transmute(g));
channel_roots.push(std::mem::transmute(c));
channel_roots.push(std::mem::transmute(r));
channel_roots.push(std::mem::transmute(s));
}
}
::sanakirja::debug_(&self.txn, &channel_roots[..], "debug_sanakirja", true);
self.txn.check_references(&mut refs);
info!("stats = {:?}", stats);
let occupied_pages =
stats.total_pages - stats.free_pages.len() - stats.bookkeeping_pages.len();
for i in 1..(stats.total_pages as u64) {
let p = i * 4096;
if !refs.contains_key(&p)
&& !stats.free_pages.contains(&p)
&& !stats.bookkeeping_pages.contains(&p)
{
panic!("does not contain {:?} ({:?})", i, p);
}
}
// check that there is no intersection.
for (r, _) in refs.iter() {
if stats.free_pages.contains(r) {
panic!("referenced page is free: {:?}", r);
}
if stats.bookkeeping_pages.contains(r) {
panic!("referenced page is a bookkeeping page: {:?}", r);
}
debug!("check: remotes 0x{:x}", self.remotes.db);
::sanakirja::debug::add_refs(&self.txn, &self.remotes, &mut refs).unwrap();
for x in btree::iter(&self.txn, &self.remotes, None).unwrap() {
let (name, tup) = x.unwrap();
debug!("check: remote name: {:?}", name.as_str());
let remote: UDb<SmallStr, T3> = UDb::from_page(tup.0[0].into());
let rev: UDb<SerializedHash, L64> = UDb::from_page(tup.0[1].into());
let states: UDb<SerializedMerkle, L64> = UDb::from_page(tup.0[2].into());
debug!("check: remote 0x{:x}", remote.db);
::sanakirja::debug::add_refs(&self.txn, &remote, &mut refs).unwrap();
debug!("check: rev 0x{:x}", rev.db);
::sanakirja::debug::add_refs(&self.txn, &rev, &mut refs).unwrap();
debug!("check: states 0x{:x}", states.db);
::sanakirja::debug::add_refs(&self.txn, &states, &mut refs).unwrap();
for p in stats.free_pages.iter() {
if stats.bookkeeping_pages.contains(p) {
panic!("bookkeeping inter free: {:?}", p);
}
}
assert_eq!(1 + refs.len(), occupied_pages);
report
::sanakirja::debug::add_free_refs(&self.txn, &mut refs).unwrap();
::sanakirja::debug::check_free(&self.txn, &refs);
impl<T: ::sanakirja::Transaction> GraphTxnT for GenericTxn<T> {
type Graph = Db<Vertex<ChangeId>, Edge>;
impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error>> GraphTxnT for GenericTxn<T> {
type Graph = Db<Vertex<ChangeId>, SerializedEdge>;
sanakirja_get!(graph, Vertex<ChangeId>, Edge, GraphError);
fn get_external(&self, p: ChangeId) -> Result<Option<Hash>, TxnErr<Self::GraphError>> {
sanakirja_get!(graph, Vertex<ChangeId>, SerializedEdge, GraphError);
fn get_external(
&self,
p: &ChangeId,
) -> Result<Option<&SerializedHash>, TxnErr<Self::GraphError>> {
debug!("get_external {:?}", p);
fn get_internal(&self, p: Hash) -> Result<Option<ChangeId>, TxnErr<Self::GraphError>> {
if let Hash::None = p {
Ok(Some(ChangeId::ROOT))
} else if let Ok(x) = self.txn.get(&self.internal, p, None) {
Ok(x)
fn get_internal(&self, p: &SerializedHash) -> Result<Option<&ChangeId>, TxnErr<Self::GraphError>> {
if p.t == HashAlgorithm::None as u8 {
Ok(Some(&ChangeId::ROOT))
let edge = Edge {
flag: min_flag,
dest,
introduced_by: ChangeId::ROOT,
};
if let Ok((cursor, _)) = self.txn.set_cursors(g, Some((key, Some(edge)))) {
Ok(Adj {
cursor,
key,
min_flag,
max_flag,
})
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
}
let edge = SerializedEdge::new(min_flag, dest.change, dest.pos, ChangeId::ROOT);
let mut cursor = btree::cursor::Cursor::new(&self.txn, g).map_err(TxnErr)?;
cursor.set(&self.txn, &key, Some(&edge))?;
Ok(Adj {
cursor,
key,
min_flag,
max_flag,
})
unsafe fn next_graph<T: ::sanakirja::Transaction>(
txn: &T,
cursor: &mut ::sanakirja::Cursor,
) -> Result<Option<(Vertex<ChangeId>, Edge)>, BlockError<SanakirjaError>> {
match ::sanakirja::next::<_, Vertex<ChangeId>, Edge>(txn, cursor) {
Ok(x) => Ok(x),
Err(::sanakirja::CRCError {}) => Err(BlockError::Txn(SanakirjaError::PristineCorrupt)),
}
}
unsafe fn prev_graph<T: ::sanakirja::Transaction>(
txn: &T,
cursor: &mut ::sanakirja::Cursor,
) -> Result<Option<(Vertex<ChangeId>, Edge)>, BlockError<SanakirjaError>> {
match ::sanakirja::prev::<_, Vertex<ChangeId>, Edge>(txn, cursor) {
Ok(x) => Ok(x),
Err(::sanakirja::CRCError {}) => Err(BlockError::Txn(SanakirjaError::PristineCorrupt)),
}
}
pub fn find_block<T: ::sanakirja::Transaction>(
txn: &T,
graph: &::sanakirja::Db<Vertex<ChangeId>, Edge>,
pub fn find_block<'a, T: ::sanakirja::LoadPage<Error = ::sanakirja::Error>>(
txn: &'a T,
graph: &::sanakirja::btree::Db<Vertex<ChangeId>, SerializedEdge>,
let mut k = if let Some((k, _)) = unsafe { next_graph(txn, &mut cursor)? } {
let mut cursor =
btree::cursor::Cursor::new(txn, &graph).map_err(|x| BlockError::Txn(x.into()))?;
let mut k = if let Some((k, _)) = cursor.set(txn, &key, None).map_err(|x| BlockError::Txn(x.into()))? {
k
} else if let Some((k, _)) = cursor.prev(txn).map_err(|x| BlockError::Txn(x.into()))? {
debug!("k = {:?}", k);
// The only guarantee here is that k is either the first key
// >= `key`, or the key just before that. We might need to
// rewind by one step if key is strictly larger than the
// result (i.e. if `p` is in the middle of the key).
// The only guarantee here is that k is either the first key >=
// `key`. We might need to rewind by one step if key is strictly
// larger than the result (i.e. if `p` is in the middle of the
// key).
pub fn find_block_end<T: ::sanakirja::Transaction>(
txn: &T,
graph: &::sanakirja::Db<Vertex<ChangeId>, Edge>,
pub fn find_block_end<'a, T: ::sanakirja::LoadPage<Error = ::sanakirja::Error>>(
txn: &'a T,
graph: &::sanakirja::btree::Db<Vertex<ChangeId>, SerializedEdge>,
debug!(target: "libpijul::find_block_end", "find_block_end {:?}, p.change.0 = {:?}", key, p.change.0);
let mut cursor = if let Ok((cursor, _)) = txn.set_cursors(&graph, Some((key, None))) {
cursor
} else {
return Err(BlockError::Txn(SanakirjaError::PristineCorrupt));
};
let mut k = if let Some((k, _)) = unsafe { next_graph(txn, &mut cursor)? } {
let mut cursor = ::sanakirja::btree::cursor::Cursor::new(txn, graph)
.map_err(|x| BlockError::Txn(x.into()))?;
let mut k = if let Some((k, _)) = cursor
.set(txn, &key, None)
.map_err(|x| BlockError::Txn(x.into()))?
{
k
} else if let Some((k, _)) = cursor.prev(txn).map_err(|x| BlockError::Txn(x.into()))? {
impl<T: ::sanakirja::Transaction> GraphIter for GenericTxn<T> {
type GraphCursor = ::sanakirja::Cursor;
impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error>> GraphIter for GenericTxn<T> {
type GraphCursor = ::sanakirja::btree::cursor::Cursor<
Vertex<ChangeId>,
SerializedEdge,
P<Vertex<ChangeId>, SerializedEdge>,
>;
if let Ok((cursor, _)) = self.txn.set_cursors(&g, None) {
Ok(cursor)
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
}
Ok(::sanakirja::btree::cursor::Cursor::new(&self.txn, &g)?)
) -> Option<Result<(Vertex<ChangeId>, Edge), TxnErr<Self::GraphError>>> {
match unsafe { ::sanakirja::next(&self.txn, a) } {
) -> Option<Result<(&'txn Vertex<ChangeId>, &'txn SerializedEdge), TxnErr<Self::GraphError>>>
{
match a.next(&self.txn) {
// There is a choice here: the datastructure for `revchanges` is
// intuitively a list. Moreover, when removing a change, we must
// recompute the entire merkle tree after the removed change.
//
// This seems to indicate that a linked list could be an appropriate
// structure (a growable array is excluded because amortised
// complexity is not really acceptable here).
//
// However, we want to be able to answers queries such as "when was
// change X introduced?" without having to read the entire database.
//
// Additionally, even though `SerializedMerkle` has only one
// implementation, and is therefore sized in the current
// implementation, we can't exclude that other algorithms may be
// added, which means that the pages inside linked lists won't even be
// randomly-accessible arrays.
pub graph: Db<Vertex<ChangeId>, Edge>,
pub changes: Db<ChangeId, u64>,
pub revchanges: Db<u64, (ChangeId, Merkle)>,
pub states: Db<Merkle, u64>,
pub graph: Db<Vertex<ChangeId>, SerializedEdge>,
pub changes: Db<ChangeId, L64>,
pub revchanges: UDb<L64, Pair<ChangeId, SerializedMerkle>>,
pub states: UDb<SerializedMerkle, L64>,
c: ChangeId,
) -> Result<Option<u64>, TxnErr<Self::GraphError>> {
if let Ok(x) = self.txn.get(channel, c, None) {
Ok(x)
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
c: &ChangeId,
) -> Result<Option<&L64>, TxnErr<Self::GraphError>> {
match btree::get(&self.txn, channel, c, None) {
Ok(Some((k, x))) if k == c => Ok(Some(x)),
Ok(x) => {
debug!("get_changeset = {:?}", x);
Ok(None)
},
Err(e) => {
error!("{:?}", e);
Err(TxnErr(SanakirjaError::PristineCorrupt))
}
c: u64,
) -> Result<Option<(ChangeId, Merkle)>, TxnErr<Self::GraphError>> {
if let Ok(x) = self.txn.get(revchanges, c, None) {
Ok(x)
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
c: &L64,
) -> Result<Option<&Pair<ChangeId, SerializedMerkle>>, TxnErr<Self::GraphError>> {
match btree::get(&self.txn, revchanges, c, None) {
Ok(Some((k, x))) if k == c => Ok(Some(x)),
Ok(_) => Ok(None),
Err(e) => {
error!("{:?}", e);
Err(TxnErr(SanakirjaError::PristineCorrupt))
}
if let Ok((cursor, _)) = self.txn.set_cursors(&channel, pos.map(|x| (x, None))) {
Ok(Cursor {
cursor,
txn: self,
marker: std::marker::PhantomData,
})
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
let mut cursor = btree::cursor::Cursor::new(&self.txn, &channel)?;
if let Some(k) = pos {
cursor.set(&self.txn, &k, None)?;
if let Ok((cursor, _)) = txn.txn.set_cursors(channel, pos.map(|x| (x, None))) {
Ok(Cursor {
cursor,
txn,
marker: std::marker::PhantomData,
})
} else {
Err(TxnErr(SanakirjaError::PristineCorrupt))
let mut cursor = btree::cursor::Cursor::new(&txn.txn, channel)?;
if let Some(k) = pos {
cursor.set(&txn.txn, &k, None)?;
let cursor = if let Some(pos) = pos {
if let Ok((x, _)) = self.txn.set_cursors(channel, Some((pos, None))) {
x
} else {
return Err(TxnErr(SanakirjaError::PristineCorrupt));
}
} else if let Ok(x) = self.txn.set_cursors_last(channel) {
x
let mut cursor = btree::cursor::Cursor::new(&self.txn, channel)?;
if let Some(ref pos) = pos {
cursor.set(&self.txn, pos, None)?;
) -> Result<Option<(u64, (ChangeId, Merkle))>, TxnErr<SanakirjaError>> {
if let Ok(x) = unsafe { ::sanakirja::next(&self.txn, cursor) } {
) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<SanakirjaError>> {
if let Ok(x) = cursor.next(&self.txn) {
) -> Result<Option<(u64, (ChangeId, Merkle))>, TxnErr<SanakirjaError>> {
if let Ok(x) = unsafe { ::sanakirja::prev(&self.txn, cursor) } {
) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<SanakirjaError>> {
if let Ok(x) = cursor.prev(&self.txn) {
m: Merkle,
) -> Result<Option<u64>, TxnErr<Self::GraphError>> {
Ok(self.txn.get(channel, m, None)?)
m: &SerializedMerkle,
) -> Result<Option<L64>, TxnErr<Self::GraphError>> {
match btree::get(&self.txn, channel, m, None)? {
Some((k, v)) if k == m => Ok(Some(*v)),
_ => Ok(None)
}
type Tree = Db<UnsafePathId, Inode>;
sanakirja_table_get!(
tree,
PathId,
Inode,
TreeError,
(UnsafePathId::from_fileid(key), value),
);
sanakirja_iter!(
tree,
OwnedPathId,
Inode,
if let Some((ref k, ref v)) = pos {
info!("tree iter {:?} {:?}", k, v);
Some((UnsafePathId::from_fileid(k.as_file_id()), *v))
} else {
None
},
map(|(k, v): (UnsafePathId, Inode)| (unsafe { k.to_fileid().to_owned() }, v))
);
sanakirja_iter!(
revtree,
Inode,
OwnedPathId,
if let Some((ref k, ref v)) = pos {
let v = if let Some(ref v) = *v {
Some(UnsafePathId::from_fileid(v.as_file_id()))
} else {
None
};
Some((*k, v))
} else {
None
},
map(|(k, v): (Inode, UnsafePathId)| (k, unsafe { v.to_fileid().to_owned() }))
);
type Tree = UDb<PathId, Inode>;
sanakirja_table_get!(tree, PathId, Inode, TreeError,);
type TreeCursor =
::sanakirja::btree::cursor::Cursor<PathId, Inode, UP<PathId, Inode>>;
sanakirja_iter!(tree, PathId, Inode,);
type RevtreeCursor =
::sanakirja::btree::cursor::Cursor<Inode, PathId, UP<Inode, PathId>>;
sanakirja_iter!(revtree, Inode, PathId);
type Revtree = Db<Inode, UnsafePathId>;
sanakirja_table_get!(
revtree,
Inode,
PathId,
TreeError,
(
key,
if let Some(value) = value {
Some(UnsafePathId::from_fileid(value))
} else {
None
}
),
map(|value| unsafe { value.to_fileid() })
);
type Revtree = UDb<Inode, PathId>;
sanakirja_table_get!(revtree, Inode, PathId, TreeError,);
if let Some((ref k, ref v)) = pos {
Some((UnsafeSmallStr::from_small_str(k.as_small_str()), *v))
} else {
None
},
map(|(k, v): (UnsafeSmallStr, Position<ChangeId>)| (
unsafe { k.to_small_str().to_owned() },
v
))
);
UP<SmallStr, Position<ChangeId>>,
>;
sanakirja_cursor!(partials, SmallStr, Position<ChangeId>,);
type InodesCursor =
::sanakirja::btree::cursor::Cursor<Inode, Position<ChangeId>, P<Inode, Position<ChangeId>>>;
if let Some((channel, changes, revchanges, states, counter, last_modified)) = self.txn.get(
&self.channels,
UnsafeSmallStr::from_small_str(name.as_small_str()),
None,
)? {
debug!("unsafe_load_channel: found {:?} {:?}", changes, revchanges);
Ok(Some(Channel {
graph: channel,
changes,
revchanges,
apply_counter: counter,
states,
name: name.clone(),
last_modified,
}))
} else {
debug!("unsafe_load_channel: not found");
Ok(None)
match btree::get(&self.txn, &self.channels, &name, None)? {
Some((name_, tup)) => {
assert_eq!(name_, name.as_ref());
debug!("load_channel: {:?} {:?}", name, tup);
Ok(Some(Channel {
graph: Db::from_page(tup.0[0].into()),
changes: Db::from_page(tup.0[1].into()),
revchanges: UDb::from_page(tup.0[2].into()),
states: UDb::from_page(tup.0[3].into()),
apply_counter: tup.0[4].into(),
last_modified: tup.0[5].into(),
name,
}))
}
_ => {
debug!("unsafe_load_channel: not found");
Ok(None)
}
if let Some(remote) = self.txn.get(
&self.remotes,
UnsafeSmallStr::from_small_str(name.as_small_str()),
None,
)? {
let r = RemoteRef {
db: Rc::new(RefCell::new(Remote {
remote: remote.0,
rev: remote.1,
states: remote.2,
})),
name: name.clone(),
};
Ok(Some(v.insert(r).clone()))
} else {
return Ok(None);
match btree::get(&self.txn, &self.remotes, &name, None)? {
Some((name_, remote)) if name.as_ref() == name_ => {
debug!("load_remote: {:?} {:?}", name_, remote);
let r = Remote {
remote: UDb::from_page(remote.0[0].into()),
rev: UDb::from_page(remote.0[1].into()),
states: UDb::from_page(remote.0[2].into()),
};
for x in btree::iter(&self.txn, &r.remote, None).unwrap() {
debug!("remote -> {:?}", x);
}
for x in btree::iter(&self.txn, &r.rev, None).unwrap() {
debug!("rev -> {:?}", x);
}
for x in btree::iter(&self.txn, &r.states, None).unwrap() {
debug!("states -> {:?}", x);
}
for x in self.iter_remote(&r.remote, 0).unwrap() {
debug!("ITER {:?}", x);
}
let r = RemoteRef {
db: Rc::new(RefCell::new(r)),
name: name.clone(),
};
Ok(Some(v.insert(r).clone()))
}
_ => return Ok(None)
type Channels = Db<UnsafeSmallStr, (u64, u64, u64, u64, u64, u64)>;
sanakirja_cursor!(
channels,
SmallString,
(u64, u64, u64, u64, u64, u64),
if let Some((ref k, ref v)) = pos {
Some((UnsafeSmallStr::from_small_str(k.as_small_str()), *v))
} else {
None
},
map(|(k, v): (UnsafeSmallStr, (u64, u64, u64, u64, u64, u64))| (
unsafe { k.to_small_str().to_owned() },
v
))
);
type Channels = UDb<SmallStr, T6>;
type ChannelsCursor = ::sanakirja::btree::cursor::Cursor<SmallStr, T6, UP<SmallStr, T6>>;
sanakirja_cursor!(channels, SmallStr, T6,);
let name = UnsafeSmallStr::from_small_str(name.as_small_str());
Ok(ChannelIterator {
cursor: self.txn.set_cursors(&self.channels, Some((name, None)))?.0,
txn: self,
})
let mut cursor = btree::cursor::Cursor::new(&self.txn, &self.channels)?;
cursor.set(&self.txn, &name, None)?;
Ok(ChannelIterator { cursor, txn: self })
type Remotes = Db<UnsafeSmallStr, (u64, u64, u64)>;
sanakirja_cursor!(
remotes,
SmallString,
(u64, u64, u64),
if let Some((ref k, ref v)) = pos {
Some((UnsafeSmallStr::from_small_str(k.as_small_str()), *v))
} else {
None
},
map(|(k, v): (UnsafeSmallStr, (u64, u64, u64))| (
unsafe { k.to_small_str().to_owned() },
v
))
);
type Remotes = UDb<SmallStr, T3>;
type RemotesCursor = ::sanakirja::btree::cursor::Cursor<SmallStr, T3, UP<SmallStr, T3>>;
sanakirja_cursor!(remotes, SmallStr, T3);
let name = UnsafeSmallStr::from_small_str(name.as_small_str());
Ok(RemotesIterator {
cursor: self.txn.set_cursors(&self.remotes, Some((name, None)))?.0,
txn: self,
})
let mut cursor = btree::cursor::Cursor::new(&self.txn, &self.remotes)?;
cursor.set(&self.txn, &name, None)?;
Ok(RemotesIterator { cursor, txn: self })
type Remote = Db<u64, (Hash, Merkle)>;
type Revremote = Db<Hash, u64>;
type Remotestates = Db<Merkle, u64>;
sanakirja_cursor!(remote, u64, (Hash, Merkle));
sanakirja_rev_cursor!(remote, u64, (Hash, Merkle));
type Remote = UDb<L64, Pair<SerializedHash, SerializedMerkle>>;
type Revremote = UDb<SerializedHash, L64>;
type Remotestates = UDb<SerializedMerkle, L64>;
type RemoteCursor = ::sanakirja::btree::cursor::Cursor<
L64,
Pair<SerializedHash, SerializedMerkle>,
UP<L64, Pair<SerializedHash, SerializedMerkle>>,
>;
sanakirja_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
sanakirja_rev_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
if let Some(remote) = self.txn.get(
&self.remotes,
UnsafeSmallStr::from_small_str(name.as_small_str()),
None,
)? {
let r = RemoteRef {
db: Rc::new(RefCell::new(Remote {
remote: remote.0,
rev: remote.1,
states: remote.2,
})),
name: name.clone(),
};
v.insert(r);
} else {
return Ok(None);
match btree::get(&self.txn, &self.remotes, &name, None)? {
Some((name_, remote)) if name_ == name.as_ref() => {
let r = RemoteRef {
db: Rc::new(RefCell::new(Remote {
remote: UDb::from_page(remote.0[0].into()),
rev: UDb::from_page(remote.0[1].into()),
states: UDb::from_page(remote.0[2].into()),
})),
name: name.clone(),
};
v.insert(r);
}
_ => return Ok(None),
) -> Result<Option<(u64, (Hash, Merkle))>, TxnErr<Self::GraphError>> {
Ok(self.txn.rev_iter(remote, None)?.next().transpose()?)
) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>
{
if let Some(x) = btree::rev_iter(&self.txn, remote, None)?.next() {
let (&k, v) = x?;
Ok(Some((k.into(), v)))
} else {
Ok(None)
}
) -> Result<Option<(u64, (Hash, Merkle))>, TxnErr<Self::GraphError>> {
for x in self.txn.iter(remote, Some((n, None)))? {
let (k, m) = x?;
) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>
{
let n = n.into();
for x in btree::iter(&self.txn, remote, Some((&n, None)))? {
let (&k, m) = x?;
sanakirja_put_del!(internal, Hash, ChangeId, GraphError);
sanakirja_put_del!(external, ChangeId, Hash, GraphError);
sanakirja_put_del!(internal, SerializedHash, ChangeId, GraphError);
sanakirja_put_del!(external, ChangeId, SerializedHash, GraphError);
assert!(chi.introduced_by != ChangeId::ROOT || chi.flag.contains(EdgeFlags::PSEUDO));
if chi.flag.contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {
assert!(
chi.introduced_by() != ChangeId::ROOT || chi.flag().contains(EdgeFlags::PSEUDO)
);
if chi.flag().contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {
for i in self.txn.iter(&channel.changes, None).unwrap() {
debug!("changes {:?}", i);
}
let m = if let Some(x) = self.txn.rev_iter(&channel.revchanges, None)?.next() {
(x?.1).1
let m = if let Some(x) = btree::rev_iter(&self.txn, &channel.revchanges, None)?.next() {
(&(x?.1).b).into()
.txn
.put(&mut self.rng, &mut channel.revchanges, t, (p, m))?);
Ok(Some(m))
} else {
Ok(None)
.get_revchangeset(&channel.revchanges, &t.into())?
.is_none());
assert!(btree::put(
&mut self.txn,
&mut channel.changes,
&p,
&t.into()
)?);
assert!(btree::put(
&mut self.txn,
&mut channel.revchanges,
&t.into(),
&Pair { a: p, b: m.into() }
)?);
Ok(Some(m.into()))
for x in self.txn.iter(&channel.revchanges, Some((t, None)))? {
let (t_, (p, _)) = x?;
if t_ >= t {
repl.push((t_, p))
let tl = t.into();
for x in btree::iter(&self.txn, &channel.revchanges, Some((&tl, None)))? {
let (t_, p) = x?;
if *t_ >= tl {
repl.push((*t_, p.a))
for x in self.txn.rev_iter(&channel.revchanges, Some((t, None)))? {
let (t_, (_, m_)) = x?;
if t_ < t {
m = m_;
for x in btree::rev_iter(&self.txn, &channel.revchanges, Some((&tl, None)))? {
let (t_, mm) = x?;
if t_ < &tl {
m = (&mm.b).into();
self.txn
.del(&mut self.rng, &mut channel.revchanges, *t_, None)?;
if *t_ > t {
m = m.next(&self.get_external(*p)?.unwrap());
self.txn
.put(&mut self.rng, &mut channel.revchanges, *t_, (*p, m))?;
btree::del(&mut self.txn, &mut channel.revchanges, t_, None)?;
if *t_ > tl {
m = m.next(&self.get_external(p)?.unwrap().into());
btree::put(
&mut self.txn,
&mut channel.revchanges,
t_,
&Pair { a: *p, b: m.into() },
)?;
sanakirja_put_del!(
tree,
PathId,
Inode,
TreeError,
UnsafePathId::from_fileid(k),
v
);
sanakirja_put_del!(
revtree,
Inode,
PathId,
TreeError,
k,
UnsafePathId::from_fileid(v)
);
sanakirja_put_del!(tree, PathId, Inode, TreeError,);
sanakirja_put_del!(revtree, Inode, PathId, TreeError,);
self.txn.put(&mut self.rng, &mut remote.remote, k, v)?;
self.txn.put(&mut self.rng, &mut remote.states, v.1, k)?;
Ok(self.txn.put(&mut self.rng, &mut remote.rev, v.0, k)?)
let h = (&v.0).into();
let m: SerializedMerkle = (&v.1).into();
btree::put(
&mut self.txn,
&mut remote.remote,
&k.into(),
&Pair { a: h, b: m.clone() },
)?;
btree::put(&mut self.txn, &mut remote.states, &m, &k.into())?;
Ok(btree::put(&mut self.txn, &mut remote.rev, &h, &k.into())?)
if let Some((h, m)) = self.txn.get(&remote.remote, k, None)? {
self.txn.del(&mut self.rng, &mut remote.rev, h, None)?;
self.txn.del(&mut self.rng, &mut remote.states, m, None)?;
Ok(self.txn.del(&mut self.rng, &mut remote.remote, k, None)?)
} else {
Ok(false)
let k = k.into();
match btree::get(&self.txn, &remote.remote, &k, None)? {
Some((k0, p)) if k0 == &k => {
debug!("del_remote {:?} {:?}", k0, p);
let p = p.clone();
btree::del(&mut self.txn, &mut remote.rev, &p.a, None)?;
btree::del(&mut self.txn, &mut remote.states, &p.b, None)?;
Ok(btree::del(
&mut self.txn,
&mut remote.remote,
&k.into(),
None,
)?)
}
x => {
debug!("not found, {:?}", x);
Ok(false)
}
let r = if let Some((
graph,
changes,
revchanges,
states,
apply_counter,
last_modified,
)) = self.txn.get(
&self.channels,
UnsafeSmallStr::from_small_str(name.as_small_str()),
None,
)? {
ChannelRef {
r: Rc::new(RefCell::new(Channel {
graph,
changes,
revchanges,
states,
apply_counter,
name: name.clone(),
last_modified,
})),
}
} else {
let br = ChannelRef {
r: Rc::new(RefCell::new(Channel {
graph: self.txn.create_db()?,
changes: self.txn.create_db()?,
revchanges: self.txn.create_db()?,
states: self.txn.create_db()?,
apply_counter: 0,
name: name.clone(),
last_modified: 0,
})),
let r =
match btree::get(&self.txn, &self.channels, &name, None)? {
Some((name_, b)) => {
assert_eq!(name_, name.as_ref());
ChannelRef {
r: Rc::new(RefCell::new(Channel {
graph: Db::from_page(b.0[0].into()),
changes: Db::from_page(b.0[1].into()),
revchanges: UDb::from_page(b.0[2].into()),
states: UDb::from_page(b.0[3].into()),
apply_counter: b.0[4].into(),
name: name.clone(),
last_modified: b.0[5].into(),
})),
}
}
_ => {
let br = ChannelRef {
r: Rc::new(RefCell::new(Channel {
graph: btree::create_db_(&mut self.txn)?,
changes: btree::create_db_(&mut self.txn)?,
revchanges: btree::create_db_(&mut self.txn)?,
states: btree::create_db_(&mut self.txn)?,
apply_counter: 0,
name: name.clone(),
last_modified: 0,
})),
};
commit = Some(br.clone());
br
}
let br = ChannelRef {
r: Rc::new(RefCell::new(Channel {
graph: self
.txn
.fork(&mut self.rng, &channel.graph)
.map_err(|e| ForkError::Txn(e.into()))?,
changes: self
.txn
.fork(&mut self.rng, &channel.changes)
.map_err(|e| ForkError::Txn(e.into()))?,
revchanges: self
.txn
.fork(&mut self.rng, &channel.revchanges)
.map_err(|e| ForkError::Txn(e.into()))?,
states: self
.txn
.fork(&mut self.rng, &channel.states)
.map_err(|e| ForkError::Txn(e.into()))?,
name: name.clone(),
apply_counter: channel.apply_counter,
last_modified: channel.last_modified,
})),
};
self.open_channels.borrow_mut().insert(name, br.clone());
Ok(br)
} else {
Err(super::ForkError::ChannelNameExists(new_name.to_string()))
Some((name_, _)) if name_ == name.as_ref() =>
Err(super::ForkError::ChannelNameExists(new_name.to_string())),
_ => {
let br = ChannelRef {
r: Rc::new(RefCell::new(Channel {
graph: btree::fork_db(&mut self.txn, &channel.graph)
.map_err(|e| ForkError::Txn(e.into()))?,
changes: btree::fork_db(&mut self.txn, &channel.changes)
.map_err(|e| ForkError::Txn(e.into()))?,
revchanges: btree::fork_db(&mut self.txn, &channel.revchanges)
.map_err(|e| ForkError::Txn(e.into()))?,
states: btree::fork_db(&mut self.txn, &channel.states)
.map_err(|e| ForkError::Txn(e.into()))?,
name: name.clone(),
apply_counter: channel.apply_counter,
last_modified: channel.last_modified,
})),
};
self.open_channels.borrow_mut().insert(name, br.clone());
Ok(br)
}
let mut dbs_channels: ::sanakirja::Db<UnsafeSmallStr, (u64, u64, u64, u64, u64, u64)> =
unsafe { std::mem::transmute(self.channels) };
self.txn
.del(
&mut self.rng,
&mut dbs_channels,
UnsafeSmallStr::from_small_str(channel.borrow().name.as_small_str()),
Some((name_, _)) if name_ == name.as_ref() =>
Err(super::ForkError::ChannelNameExists(new_name.to_string())),
_ => {
btree::del(
&mut self.txn,
&mut self.channels,
&channel.borrow().name,
.map_err(|e| ForkError::Txn(e.into()))?;
self.channels = unsafe { std::mem::transmute(dbs_channels) };
std::mem::drop(
.map_err(|e| ForkError::Txn(e.into()))?;
std::mem::drop(
self.open_channels
.borrow_mut()
.remove(&channel.borrow().name)
.unwrap(),
);
std::cell::RefCell::borrow_mut(&std::rc::Rc::get_mut(&mut channel.r).unwrap()).name =
name.clone();
.remove(&channel.borrow().name)
.unwrap(),
);
std::cell::RefCell::borrow_mut(&std::rc::Rc::get_mut(&mut channel.r).unwrap()).name =
name.clone();
self.open_channels
.borrow_mut()
.insert(name, channel.clone());
Ok(())
} else {
Err(ForkError::ChannelNameExists(new_name.to_string()))
.insert(name, channel.clone());
Ok(())
}
let r = if let Some(remote) = self.txn.get(
&self.remotes,
UnsafeSmallStr::from_small_str(name.as_small_str()),
None,
)? {
RemoteRef {
db: Rc::new(RefCell::new(Remote {
remote: remote.0,
rev: remote.1,
states: remote.2,
})),
name: name.clone(),
}
} else {
let br = RemoteRef {
db: Rc::new(RefCell::new(Remote {
remote: self.txn.create_db()?,
rev: self.txn.create_db()?,
states: self.txn.create_db()?,
})),
name: name.clone(),
let r =
match btree::get(&self.txn, &self.remotes, &name, None)? {
Some((name_, remote)) if name_ == name.as_ref() => {
RemoteRef {
db: Rc::new(RefCell::new(Remote {
remote: UDb::from_page(remote.0[0].into()),
rev: UDb::from_page(remote.0[1].into()),
states: UDb::from_page(remote.0[2].into()),
})),
name: name.clone(),
}
}
_ => {
let br = RemoteRef {
db: Rc::new(RefCell::new(Remote {
remote: btree::create_db_(&mut self.txn)?,
rev: btree::create_db_(&mut self.txn)?,
states: btree::create_db_(&mut self.txn)?,
})),
name: name.clone(),
};
commit = Some(br.clone());
br
}
self.txn.set_root(Root::Tree as usize, self.tree);
self.txn.set_root(Root::RevTree as usize, self.revtree);
self.txn.set_root(Root::Inodes as usize, self.inodes);
self.txn.set_root(Root::RevInodes as usize, self.revinodes);
self.txn.set_root(Root::Internal as usize, self.internal);
self.txn.set_root(Root::External as usize, self.external);
self.txn.set_root(Root::RevDep as usize, self.revdep);
self.txn.set_root(Root::Channels as usize, self.channels);
self.txn.set_root(Root::Remotes as usize, self.remotes);
self.txn.set_root(Root::Tree as usize, self.tree.db);
self.txn.set_root(Root::RevTree as usize, self.revtree.db);
self.txn.set_root(Root::Inodes as usize, self.inodes.db);
self.txn.set_root(Root::RevInodes as usize, self.revinodes.db);
self.txn.set_root(Root::Internal as usize, self.internal.db);
self.txn.set_root(Root::External as usize, self.external.db);
self.txn.set_root(Root::RevDep as usize, self.revdep.db);
self.txn.set_root(Root::Channels as usize, self.channels.db);
self.txn.set_root(Root::Remotes as usize, self.remotes.db);
.set_root(Root::RevTouchedFiles as usize, self.rev_touched_files);
self.txn.set_root(Root::Partials as usize, self.partials);
.set_root(Root::RevTouchedFiles as usize, self.rev_touched_files.db);
self.txn.set_root(Root::Partials as usize, self.partials.db);
if let Some((channel, changes, revchanges, states, counter, last_modified)) = self.txn.get(
&self.channels,
UnsafeSmallStr::from_small_str(name.as_small_str()),
None,
)? {
Ok(Some(Channel {
graph: channel,
changes,
revchanges,
states,
apply_counter: counter,
name,
last_modified,
}))
} else {
Ok(None)
match btree::get(&self.txn, &self.channels, &name, None)? {
Some((name_, c)) => {
assert_eq!(name.as_ref(), name_);
debug!("load_const_channel = {:?} {:?}", name_ ,c);
Ok(Some(Channel {
graph: Db::from_page(c.0[0].into()),
changes: Db::from_page(c.0[1].into()),
revchanges: UDb::from_page(c.0[2].into()),
states: UDb::from_page(c.0[3].into()),
apply_counter: c.0[4].into(),
last_modified: c.0[5].into(),
name,
}))
}
_ => Ok(None)
let mut dbs_channels: ::sanakirja::Db<UnsafeSmallStr, (u64, u64, u64, u64, u64, u64)> =
unsafe { std::mem::transmute(self.channels) };
debug!("Commit_channel, dbs_channels = {:?}", dbs_channels);
self.txn.del(
&mut self.rng,
&mut dbs_channels,
UnsafeSmallStr::from_small_str(channel.name.as_small_str()),
debug!("Commit_channel, dbs_channels = {:?}", self.channels);
btree::del(
&mut self.txn,
&mut self.channels,
&channel.name,
debug!("Commit_channel, dbs_channels = {:?}", dbs_channels);
self.channels = unsafe { std::mem::transmute(dbs_channels) };
self.txn.put(
&mut self.rng,
let t6 = T6([
channel.graph.db.into(),
channel.changes.db.into(),
channel.revchanges.db.into(),
channel.states.db.into(),
channel.apply_counter.into(),
channel.last_modified.into(),
]);
debug!("t6 = {:?}", t6);
btree::put(
&mut self.txn,
let mut dbs_remotes: ::sanakirja::Db<UnsafeSmallStr, (u64, u64, u64)> =
unsafe { std::mem::transmute(self.remotes) };
debug!("Commit_remote, dbs_remotes = {:?}", dbs_remotes);
self.txn.del(
&mut self.rng,
&mut dbs_remotes,
UnsafeSmallStr::from_small_str(remote.name.as_small_str()),
btree::del(
&mut self.txn,
&mut self.remotes,
&remote.name,
const CHANGE_ID_SIZE: usize = 8;
impl Representable for ChangeId {
fn alignment() -> Alignment {
Alignment::B8
}
fn onpage_size(&self) -> u16 {
CHANGE_ID_SIZE as u16
}
unsafe fn write_value(&self, p: *mut u8) {
LittleEndian::write_u64(std::slice::from_raw_parts_mut(p, 8), self.0)
}
unsafe fn read_value(p: *const u8) -> Self {
ChangeId(LittleEndian::read_u64(std::slice::from_raw_parts(p, 8)))
}
unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
self.0.cmp(&x.0)
}
type PageOffsets = std::iter::Empty<u64>;
fn page_offsets(&self) -> Self::PageOffsets {
std::iter::empty()
}
}
direct_repr!(L64);
impl Representable for Vertex<ChangeId> {
fn alignment() -> Alignment {
Alignment::B1
}
fn onpage_size(&self) -> u16 {
VERTEX_SIZE as u16
}
unsafe fn write_value(&self, p: *mut u8) {
let p = std::slice::from_raw_parts_mut(p, VERTEX_SIZE);
LittleEndian::write_u64(p, self.change.0);
LittleEndian::write_u64(&mut p[CHANGE_ID_SIZE..], self.start.0);
LittleEndian::write_u64(&mut p[CHANGE_ID_SIZE + 8..], self.end.0);
}
unsafe fn read_value(p: *const u8) -> Self {
let p = std::slice::from_raw_parts(p, VERTEX_SIZE);
let change = LittleEndian::read_u64(p);
let start = LittleEndian::read_u64(&p[CHANGE_ID_SIZE..]);
let end = LittleEndian::read_u64(&p[CHANGE_ID_SIZE + 8..]);
Vertex {
change: ChangeId(change),
start: ChangePosition(start),
end: ChangePosition(end),
}
}
unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
self.cmp(&x)
}
type PageOffsets = std::iter::Empty<u64>;
fn page_offsets(&self) -> Self::PageOffsets {
std::iter::empty()
}
}
direct_repr!(Vertex<ChangeId>);
direct_repr!(Position<ChangeId>);
impl Representable for Position<ChangeId> {
fn alignment() -> Alignment {
Alignment::B1
}
fn onpage_size(&self) -> u16 {
(CHANGE_ID_SIZE + 8) as u16
}
unsafe fn write_value(&self, p: *mut u8) {
let p = std::slice::from_raw_parts_mut(p, CHANGE_ID_SIZE + 8);
LittleEndian::write_u64(p, self.change.0);
LittleEndian::write_u64(&mut p[CHANGE_ID_SIZE..], self.pos.0);
}
unsafe fn read_value(p: *const u8) -> Self {
let p = std::slice::from_raw_parts(p, CHANGE_ID_SIZE + 8);
let change = LittleEndian::read_u64(p);
let pos = LittleEndian::read_u64(&p[CHANGE_ID_SIZE..]);
Position {
change: ChangeId(change),
pos: ChangePosition(pos),
}
}
unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
self.cmp(&x)
direct_repr!(SerializedEdge);
impl Storable for PathId {
fn compare<T>(&self, _: &T, x: &Self) -> std::cmp::Ordering {
self.cmp(x)
unsafe fn write_value(&self, p: *mut u8) {
let s = std::slice::from_raw_parts_mut(p, 25);
s[0] = (*self).flag.bits();
LittleEndian::write_u64(&mut s[1..], (*self).dest.change.0);
LittleEndian::write_u64(&mut s[9..], (*self).dest.pos.0);
LittleEndian::write_u64(&mut s[17..], (*self).introduced_by.0);
unsafe fn onpage_size(p: *const u8) -> usize {
let len = *(p.add(8)) as usize;
9 + len
unsafe fn read_value(p: *const u8) -> Self {
let s = std::slice::from_raw_parts(p, 25);
Edge {
flag: if let Some(b) = EdgeFlags::from_bits(s[0]) {
b
} else {
panic!("read_value, edge = {:?}", s);
},
dest: Position {
change: ChangeId(LittleEndian::read_u64(&s[1..])),
pos: ChangePosition(LittleEndian::read_u64(&s[9..])),
},
introduced_by: ChangeId(LittleEndian::read_u64(&s[17..])),
}
unsafe fn from_raw_ptr<'a, T>(_: &T, p: *const u8) -> &'a Self {
path_id_from_raw_ptr(p)
unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
let a: &Edge = self;
let b: &Edge = &x;
a.cmp(b)
unsafe fn write_to_page(&self, p: *mut u8) {
*(p as *mut u64) = (self.parent_inode.0).0;
self.basename.write_to_page(p.add(8))
/// An internal "unsafe" version of a [`pristine::PathId`], used to
/// circumvent the absence of associated type constructors in Rust
/// (else this would be borrow on a table).
#[derive(Clone, Copy, Debug)]
pub struct UnsafePathId {
parent_inode: Inode,
basename: UnsafeSmallStr,
unsafe fn path_id_from_raw_ptr<'a>(p: *const u8) -> &'a PathId {
let len = *(p.add(8)) as usize;
std::mem::transmute(std::slice::from_raw_parts(p, 1 + len as usize))
impl UnsafePathId {
pub fn from_fileid(f: PathId) -> UnsafePathId {
UnsafePathId {
parent_inode: f.parent_inode,
basename: UnsafeSmallStr::from_small_str(f.basename),
}
}
pub unsafe fn to_fileid<'a>(&self) -> PathId<'a> {
PathId {
parent_inode: self.parent_inode,
basename: self.basename.to_small_str(),
}
#[test]
fn pathid_repr() {
let o = OwnedPathId {
parent_inode: Inode::ROOT,
basename: SmallString::from_str("blablabla")
};
let mut x = vec![0u8; 200];
unsafe {
o.write_to_page(x.as_mut_ptr());
let p = path_id_from_raw_ptr(x.as_ptr());
assert_eq!(p.basename.as_str(), "blablabla");
assert_eq!(p.parent_inode, Inode::ROOT);
impl Representable for UnsafePathId {
fn alignment() -> Alignment {
Alignment::B1
}
fn onpage_size(&self) -> u16 {
INODE_SIZE + self.basename.onpage_size()
}
unsafe fn write_value(&self, p: *mut u8) {
self.parent_inode.write_value(p);
self.basename.write_value(p.offset(INODE_SIZE as isize));
}
unsafe fn read_value(p: *const u8) -> Self {
UnsafePathId {
parent_inode: Inode::read_value(p),
basename: UnsafeSmallStr::read_value(p.offset(INODE_SIZE as isize)),
}
}
unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
let a: PathId = self.to_fileid();
let b: PathId = x.to_fileid();
a.cmp(&b)
}
type PageOffsets = std::iter::Empty<u64>;
fn page_offsets(&self) -> Self::PageOffsets {
std::iter::empty()
}
}
const INODE_SIZE: u16 = 8;
impl Representable for Inode {
fn alignment() -> Alignment {
Alignment::B8
}
fn onpage_size(&self) -> u16 {
INODE_SIZE
}
unsafe fn write_value(&self, p: *mut u8) {
LittleEndian::write_u64(std::slice::from_raw_parts_mut(p, 8), self.0)
}
unsafe fn read_value(p: *const u8) -> Self {
Inode(LittleEndian::read_u64(std::slice::from_raw_parts(p, 8)))
}
unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
self.0.cmp(&x.0)
}
type PageOffsets = std::iter::Empty<u64>;
fn page_offsets(&self) -> Self::PageOffsets {
std::iter::empty()
}
}
fn onpage_size(&self) -> u16 {
1 + (match *self {
Hash::Blake3(_) => 32,
Hash::None => 0,
})
}
unsafe fn write_value(&self, p: *mut u8) {
match *self {
Hash::Blake3(q) => {
*p = HashAlgorithm::Blake3 as u8;
std::ptr::copy(q.as_ptr(), p.offset(1), 32)
}
Hash::None => *p = HashAlgorithm::None as u8,
}
impl<A: Storable, B: Storable> Storable for Pair<A, B> {
type PageReferences = core::iter::Chain<A::PageReferences, B::PageReferences>;
fn page_references(&self) -> Self::PageReferences {
self.a.page_references().chain(self.b.page_references())
unsafe fn read_value(p: *const u8) -> Self {
assert!(*p <= HashAlgorithm::Blake3 as u8);
match std::mem::transmute(*p) {
HashAlgorithm::Blake3 => {
let mut h = [0; BLAKE3_BYTES];
std::ptr::copy(p.offset(1), h.as_mut_ptr(), BLAKE3_BYTES);
Hash::Blake3(h)
}
HashAlgorithm::None => Hash::None,
fn compare<T: LoadPage>(&self, t: &T, b: &Self) -> core::cmp::Ordering {
match self.a.compare(t, &b.a) {
core::cmp::Ordering::Equal => self.b.compare(t, &b.b),
ord => ord
unsafe fn write_value(&self, p: *mut u8) {
match *self {
Merkle::Ed25519(q) => {
*p = MerkleAlgorithm::Ed25519 as u8;
assert_eq!(*p, 1);
let q = q.compress();
let q = q.as_bytes();
std::ptr::copy(q.as_ptr(), p.offset(1), 32);
}
}
}
unsafe fn read_value(p: *const u8) -> Self {
assert_eq!(*p, MerkleAlgorithm::Ed25519 as u8);
let slice = std::slice::from_raw_parts(p.offset(1), 32);
Merkle::Ed25519(
curve25519_dalek::edwards::CompressedEdwardsY::from_slice(slice)
.decompress()
.unwrap(),
)
unsafe fn onpage_size(p: *const u8) -> usize {
let a = A::onpage_size(p);
let b_off = (a + (B::ALIGN - 1)) & !(B::ALIGN - 1);
let b_size = B::onpage_size(p.add(b_off));
(b_off + b_size + (Self::ALIGN - 1)) & !(Self::ALIGN - 1)
type PageOffsets = std::iter::Empty<u64>;
fn page_offsets(&self) -> Self::PageOffsets {
std::iter::empty()
unsafe fn write_to_page(&self, p: *mut u8) {
self.a.write_to_page(p);
let off = (self.a.size() + (B::ALIGN - 1)) & !(B::ALIGN - 1);
self.b.write_to_page(p.add(off));
direct_repr!(T3);
direct_repr!(T6);
#[cfg(feature = "dump")]
pub mod channel_dump;
// #[cfg(feature = "dump")]
// pub mod channel_dump;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct L64(pub u64);
impl From<usize> for L64 {
fn from(u: usize) -> Self {
L64((u as u64).to_le())
}
}
impl From<u64> for L64 {
fn from(u: u64) -> Self {
L64(u.to_le())
}
}
impl From<L64> for u64 {
fn from(u: L64) -> Self {
u64::from_le(u.0)
}
}
impl From<L64> for usize {
fn from(u: L64) -> Self {
u64::from_le(u.0) as usize
}
}
impl L64 {
pub fn as_u64(&self) -> u64 {
u64::from_le(self.0)
}
pub fn as_usize(&self) -> usize {
u64::from_le(self.0) as usize
}
}
impl std::fmt::Display for L64 {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
self.0.fmt(fmt)
}
}
impl Ord for L64 {
fn cmp(&self, x: &Self) -> std::cmp::Ordering {
u64::from_le(self.0).cmp(&u64::from_le(x.0))
}
}
impl PartialOrd for L64 {
fn partial_cmp(&self, x: &Self) -> Option<std::cmp::Ordering> {
Some(u64::from_le(self.0).cmp(&u64::from_le(x.0)))
}
}
impl std::ops::Add<L64> for L64 {
type Output = Self;
fn add(self, x: L64) -> L64 {
L64((u64::from_le(self.0) + u64::from_le(x.0)).to_le())
}
}
impl std::ops::Add<usize> for L64 {
type Output = Self;
fn add(self, x: usize) -> L64 {
L64((u64::from_le(self.0) + x as u64).to_le())
}
}
impl std::ops::SubAssign<usize> for L64 {
fn sub_assign(&mut self, x: usize) {
self.0 = ((u64::from_le(self.0)) - x as u64).to_le()
}
}
impl L64 {
pub fn from_slice_le(s: &[u8]) -> Self {
let mut u = 0u64;
assert!(s.len() >= 8);
unsafe {
std::ptr::copy_nonoverlapping(s.as_ptr(), &mut u as *mut u64 as *mut u8, 8)
}
L64(u)
}
pub fn to_slice_le(&self, s: &mut [u8]) {
assert!(s.len() >= 8);
unsafe {
std::ptr::copy_nonoverlapping(&self.0 as *const u64 as *const u8, s.as_mut_ptr(), 8)
}
}
}
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
#[repr(C)]
pub struct T3([L64; 3]);
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
#[repr(C)]
pub struct T6([L64; 6]);
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
#[repr(C)]
pub struct Pair<A, B> {
pub a: A,
pub b: B,
}
from: u64,
) -> Result<Cursor<T, &'txn T, T::RevchangesetCursor, u64, (ChangeId, Merkle)>, TxnErr<T::GraphError>>
from: L64,
) -> Result<Cursor<T, &'txn T, T::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>, TxnErr<T::GraphError>>
}
pub(crate) fn changeid_log_ref<T: ChannelTxnT, RT: std::ops::Deref<Target = T>>(
txn: RT,
channel: &T::Channel,
from: u64,
) -> Result<Cursor<T, RT, T::RevchangesetCursor, u64, (ChangeId, Merkle)>, TxnErr<T::GraphError>> {
let c = txn.rev_changes(&channel);
Ok(T::cursor_revchangeset_ref(txn, c, Some(from))?)
while txn.get_external(p)?.is_some() {
p = ChangeId(rand::thread_rng().gen());
while let Some(ext) = txn.get_external(&p)? {
debug!("ext = {:?}", ext);
p = ChangeId(L64(rand::thread_rng().gen()));
if v.flag.contains(EdgeFlags::PARENT)
&& (v.flag.contains(EdgeFlags::BLOCK) || k.is_empty())
&& !v.flag.contains(EdgeFlags::DELETED)
if v.flag().contains(EdgeFlags::PARENT)
&& (v.flag().contains(EdgeFlags::BLOCK) || k.is_empty())
&& !v.flag().contains(EdgeFlags::DELETED)
if e.flag.contains(EdgeFlags::PARENT) ^ down {
debug_edge(txn, &channel, &mut f, v, e)?;
let v = if e.flag.contains(EdgeFlags::PARENT) {
txn.find_block_end(&channel, e.dest).unwrap()
if e.flag().contains(EdgeFlags::PARENT) ^ down {
debug_edge(txn, &channel, &mut f, v, *e)?;
let v = if e.flag().contains(EdgeFlags::PARENT) {
txn.find_block_end(&channel, e.dest()).unwrap()
initialized_cursor!(tree, OwnedPathId, Inode, TreeTxnT, TreeError);
initialized_cursor!(revtree, Inode, OwnedPathId, TreeTxnT, TreeError);
initialized_cursor!(tree, PathId, Inode, TreeTxnT, TreeError);
initialized_cursor!(revtree, Inode, PathId, TreeTxnT, TreeError);
initialized_cursor!(remote, u64, (Hash, Merkle));
initialized_rev_cursor!(remote, u64, (Hash, Merkle));
initialized_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
initialized_rev_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
match is_ancestor_of(self.txn, self.txn.graph(&self.channel), self.key, touched) {
Ok(true) => return self.txn.get_external(changeid).transpose(),
match is_ancestor_of(self.txn, self.txn.graph(&self.channel), self.key, *touched) {
Ok(true) => return self.txn.get_external(&changeid).transpose().map(|x| x.map(|x| x.into())),
match is_ancestor_of(self.txn, self.txn.graph(&self.channel), self.key, touched) {
Ok(true) => return self.txn.get_external(changeid).transpose(),
match is_ancestor_of(self.txn, self.txn.graph(&self.channel), self.key, *touched) {
Ok(true) => return self.txn.get_external(&changeid).transpose().map(|x| x.map(From::from)),
k0,
Some(Edge {
flag,
dest: Position {
change: k1.change,
pos: k1.start,
},
introduced_by,
}),
&k0,
Some(&SerializedEdge::new(flag, k1.change, k1.start, introduced_by)),
k0,
Edge {
flag,
dest: Position {
change: k1.change,
pos: k1.start,
},
introduced_by,
},
&k0,
&SerializedEdge::new(flag, k1.change, k1.start, introduced_by)
) -> Result<Option<(u64, Merkle)>, TxnErr<T::GraphError>> {
for x in T::cursor_revchangeset_ref(txn, txn.rev_changes(&c), Some(pos))? {
let (n, (_, m)) = x?;
) -> Result<Option<(u64, SerializedMerkle)>, TxnErr<T::GraphError>> {
for x in T::cursor_revchangeset_ref(txn, txn.rev_changes(&c), Some(pos.into()))? {
let (&n, m) = x?;
let n: u64 = n.into();
if let Some(aa) = txn.channel_has_state(txn.states(c0), state)? {
return Ok((aa, b, state));
if let Some(aa) = txn.channel_has_state(txn.states(c0), &state)? {
return Ok((aa.into(), b, state));
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SerializedMerkle(pub [u8; 33]);
impl PartialEq<Merkle> for SerializedMerkle {
fn eq(&self, m: &Merkle) -> bool {
match m {
Merkle::Ed25519(q) => {
(self.0)[0] == MerkleAlgorithm::Ed25519 as u8
&& {
let q = q.compress();
q.as_bytes() == &(self.0)[1..]
}
}
}
}
}
impl PartialEq<SerializedMerkle> for Merkle {
fn eq(&self, m: &SerializedMerkle) -> bool {
m.eq(self)
}
}
impl<'a> From<&'a Merkle> for SerializedMerkle {
fn from(m: &'a Merkle) -> Self {
let mut mm = [0; 33];
match m {
Merkle::Ed25519(q) => {
mm[0] = MerkleAlgorithm::Ed25519 as u8;
let q = q.compress();
let q = q.as_bytes();
(&mut mm[1..]).copy_from_slice(q);
SerializedMerkle(mm)
}
}
}
}
impl From<Merkle> for SerializedMerkle {
fn from(m: Merkle) -> Self {
let mut mm = [0; 33];
match m {
Merkle::Ed25519(q) => {
mm[0] = MerkleAlgorithm::Ed25519 as u8;
let q = q.compress();
let q = q.as_bytes();
(&mut mm[1..]).copy_from_slice(q);
SerializedMerkle(mm)
}
}
}
}
impl<'a> From<&'a SerializedMerkle> for Merkle {
fn from(m: &'a SerializedMerkle) -> Self {
assert_eq!((m.0)[0], MerkleAlgorithm::Ed25519 as u8);
Merkle::Ed25519(
curve25519_dalek::edwards::CompressedEdwardsY::from_slice(&(m.0)[1..])
.decompress()
.unwrap(),
)
}
}
impl From<SerializedMerkle> for Merkle {
fn from(m: SerializedMerkle) -> Self {
assert_eq!((m.0)[0], MerkleAlgorithm::Ed25519 as u8);
Merkle::Ed25519(
curve25519_dalek::edwards::CompressedEdwardsY::from_slice(&(m.0)[1..])
.decompress()
.unwrap(),
)
}
}
}
#[derive(Clone, Copy)]
pub struct SerializedHash {
pub(crate) t: u8,
h: H
}
#[derive(Clone, Copy)]
pub(crate) union H {
none: (),
blake3: [u8; 32],
}
pub(crate) const HASH_NONE: SerializedHash = SerializedHash {
t: HashAlgorithm::None as u8,
h: H { none: () },
};
use std::cmp::Ordering;
impl PartialOrd for SerializedHash {
fn partial_cmp(&self, b: &Self) -> Option<Ordering> {
Some(self.t.cmp(&b.t))
}
}
impl Ord for SerializedHash {
fn cmp(&self, b: &Self) -> Ordering {
match self.t.cmp(&b.t) {
Ordering::Equal => {
if self.t == HashAlgorithm::Blake3 as u8 {
unsafe { self.h.blake3.cmp(&b.h.blake3) }
} else {
Ordering::Equal
}
}
o => o
}
}
}
impl PartialEq for SerializedHash {
fn eq(&self, b: &Self) -> bool {
if self.t == HashAlgorithm::Blake3 as u8 && self.t == b.t {
unsafe { self.h.blake3 == b.h.blake3 }
} else if self.t == b.t {
true
} else {
false
}
}
}
impl Eq for SerializedHash {}
impl std::fmt::Debug for SerializedHash {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
Hash::from(self).fmt(fmt)
}
}
impl<'a> From<&'a SerializedHash> for Hash {
fn from(s: &'a SerializedHash) -> Hash {
if s.t == HashAlgorithm::Blake3 as u8 {
Hash::Blake3(unsafe { s.h.blake3.clone() })
} else if s.t == HashAlgorithm::None as u8 {
Hash::None
} else {
panic!("Unknown hash algorithm {:?}", s.t)
}
}
}
impl From<SerializedHash> for Hash {
fn from(s: SerializedHash) -> Hash {
(&s).into()
}
impl From<Hash> for SerializedHash {
fn from(s: Hash) -> SerializedHash {
(&s).into()
}
}
impl<'a> From<&'a Hash> for SerializedHash {
fn from(s: &'a Hash) -> Self {
match s {
Hash::Blake3(s) => SerializedHash {
t: HashAlgorithm::Blake3 as u8,
h: H { blake3: s.clone() },
},
Hash::None => SerializedHash {
t: 0,
h: H { none: () },
}
}
}
}
}
/// The target half of an edge in the repository graph.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct SerializedEdge([super::L64; 3]);
impl std::fmt::Debug for SerializedEdge {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
let pos = self.dest();
use super::Base32;
write!(fmt, "E({:?}, {}[{}], {})", self.flag(), pos.change.to_base32(), (pos.pos.0).0, self.introduced_by().to_base32())
}
}
impl std::ops::SubAssign<EdgeFlags> for SerializedEdge {
fn sub_assign(&mut self, e: EdgeFlags) {
let ref mut f = (self.0)[0];
f.0 = ((u64::from_le(f.0)) & !((e.bits() as u64) << 56)).to_le()
}
}
impl SerializedEdge {
pub fn flag(&self) -> EdgeFlags {
let f = u64::from_le((self.0)[0].0);
EdgeFlags::from_bits((f >> 56) as u8).unwrap()
}
pub fn dest(&self) -> Position<ChangeId> {
let pos = u64::from_le((self.0[0]).0);
Position {
change: ChangeId((self.0)[1]),
pos: ChangePosition(L64((pos & 0xffffffffffffff).to_le()))
}
}
pub fn introduced_by(&self) -> ChangeId {
ChangeId((self.0)[2])
}
}
impl From<SerializedEdge> for Edge {
fn from(s: SerializedEdge) -> Edge {
Edge {
flag: s.flag(),
dest: s.dest(),
introduced_by: s.introduced_by(),
}
}
}
impl From<Edge> for SerializedEdge {
fn from(s: Edge) -> SerializedEdge {
let pos = u64::from_le((s.dest.pos.0).0);
assert!(pos < 1 << 56);
SerializedEdge([
(((s.flag.bits() as u64) << 56) | pos).into(),
s.dest.change.0,
s.introduced_by.0
])
}
}
impl<'a> From<&'a SerializedEdge> for Edge {
fn from(s: &'a SerializedEdge) -> Edge {
Edge {
flag: s.flag(),
dest: s.dest(),
introduced_by: s.introduced_by(),
}
}
}
impl SerializedEdge {
pub fn empty(dest: Position<ChangeId>, intro: ChangeId) -> Self {
SerializedEdge([dest.pos.0, dest.change.0, intro.0])
}
pub fn new(flag: EdgeFlags, change: ChangeId, pos: ChangePosition, intro: ChangeId) -> Self {
let pos = u64::from_le((pos.0).0);
assert!(pos < 1 <<56);
SerializedEdge([(pos | ((flag.bits() as u64) << 56)).into(), change.0, intro.0])
}
debug!("no current name, inserting {:?} {:?}", file_id_, inode);
if let Some(inode) = txn.get_tree(file_id_, None)? {
crate::fs::rec_delete(txn, file_id.clone(), inode, true)
debug!("no current name, inserting {:?} {:?}", file_id, inode);
if let Some(&inode) = txn.get_tree(&file_id, None)? {
crate::fs::rec_delete(txn, &file_id, inode, true)
del_tree_with_rev(txn, fileid.as_file_id(), *inode)?;
if let Some(vertex) = txn.get_inodes(*inode, None)? {
del_tree_with_rev(txn, &fileid, inode)?;
for i in txn.iter_inodes().unwrap() {
debug!("inodes = {:?}", i);
}
if let Some(&vertex) = txn.get_inodes(inode, None)? {
let source = txn.find_block_end(&channel, internal_pos(txn, &e.from, change_id)?)?;
let target = txn.find_block(&channel, internal_pos(txn, &e.to.start_pos(), change_id)?)?;
let source = *txn.find_block_end(&channel, internal_pos(txn, &e.from, change_id)?)?;
let target = *txn.find_block(&channel, internal_pos(txn, &e.to.start_pos(), change_id)?)?;
let p = txn.find_block(channel, edge.dest)?;
assert!(!edge.flag.contains(EdgeFlags::FOLDER));
let p = *txn.find_block(channel, edge.dest())?;
assert!(!edge.flag().contains(EdgeFlags::FOLDER));
if !is_alive(txn, channel, dest_vertex)? && !ws.repaired.contains(&dest_vertex) {
if e.flag.contains(EdgeFlags::PARENT) {
let p = txn.find_block_end(channel, e.dest)?;
if !is_alive(txn, channel, p)? {
if !is_alive(txn, channel, &dest_vertex)? && !ws.repaired.contains(&dest_vertex) {
if e.flag().contains(EdgeFlags::PARENT) {
let p = *txn.find_block_end(channel, e.dest())?;
if !is_alive(txn, channel, &p)? {
let p = txn.find_block_end(channel, edge.dest)?;
ws.unknown_parents.push((dest_vertex, p, inode, edge.flag));
let p = *txn.find_block_end(channel, edge.dest())?;
ws.unknown_parents.push((dest_vertex, p, inode, edge.flag()));
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)? {
fn touched_files(&self, h: &pristine::Hash) -> Result<Option<Touched<Self>>, Self::DepsError> {
if let Some(id) = pristine::GraphTxnT::get_internal(self, &h.into()).map_err(|e| e.0)? {
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)?;
del_tree_with_rev(txn, &parent_id, &inode)?;
if let Some(&vertex) = txn.get_inodes(&inode, None)? {
del_inodes_with_rev(txn, &inode, &vertex)?;
let mut stack = vec![Edge {
dest: vertex0.start_pos(),
introduced_by: ChangeId::ROOT,
flag: EdgeFlags::empty(),
}];
let mut stack = vec![SerializedEdge::empty(vertex0.start_pos(), ChangeId::ROOT)];
if v.flag.contains(EdgeFlags::PARENT) {
if v.flag.contains(EdgeFlags::BLOCK)
&& !v.flag.contains(EdgeFlags::DELETED)
&& vertex != vertex0
&& !v.flag.contains(EdgeFlags::PSEUDO)
if v.flag().contains(EdgeFlags::PARENT) {
if v.flag().contains(EdgeFlags::BLOCK)
&& !v.flag().contains(EdgeFlags::DELETED)
&& *vertex != vertex0
&& !v.flag().contains(EdgeFlags::PSEUDO)
for x in changeid_log(txn, &channel, 0)? {
let (_, (ch, _)) = x?;
let h = txn.get_external(ch)?.unwrap();
deps.insert(h);
for x in changeid_log(txn, &channel, L64(0))? {
let (_, p) = x?;
let h = txn.get_external(&p.a)?.unwrap();
deps.insert(h.into());
if let Some(parent) = txn.get_revtree(inode, None)?.map(|x| x.to_owned()) {
del_tree_with_rev(txn, parent.as_file_id(), inode)?;
if let Some(parent) = txn.get_revtree(&inode, None)?.map(|x| x.to_owned()) {
del_tree_with_rev(txn, &parent, &inode)?;
is_folder |= parent.flag.contains(EdgeFlags::PARENT | EdgeFlags::FOLDER);
if parent.flag.contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {
if parent.flag.contains(EdgeFlags::DELETED) {
let introduced_by = txn.get_external(parent.introduced_by)?.unwrap();
is_folder |= parent.flag().contains(EdgeFlags::PARENT | EdgeFlags::FOLDER);
if parent.flag().contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {
if parent.flag().contains(EdgeFlags::DELETED) {
let introduced_by = txn.get_external(&parent.introduced_by())?.unwrap().into();
if !e.flag.contains(EdgeFlags::FOLDER) {
if e.flag.contains(EdgeFlags::PARENT) {
let p = txn.find_block_end(channel, e.dest)?;
if !e.flag().contains(EdgeFlags::FOLDER) {
if e.flag().contains(EdgeFlags::PARENT) {
let p = txn.find_block_end(channel, e.dest())?;
let up = txn.find_block_end(channel, internal_pos(txn, &up, change_id)?)?;
if !is_alive(txn, channel, up)? {
let up = *txn.find_block_end(channel, internal_pos(txn, &up, change_id)?)?;
if !is_alive(txn, channel, &up)? {
debug!("al = {:?}, flag = {:?}", al, parent.flag);
stack.push((anc, false, parent.flag.is_deleted(), al));
debug!("al = {:?}, flag = {:?}", al, parent.flag());
stack.push((*anc, false, parent.flag().is_deleted(), al));
if e.flag.contains(EdgeFlags::PARENT) {
if e.flag & (EdgeFlags::FOLDER | EdgeFlags::DELETED) == EdgeFlags::FOLDER {
if e.flag().contains(EdgeFlags::PARENT) {
if e.flag() & (EdgeFlags::FOLDER | EdgeFlags::DELETED) == EdgeFlags::FOLDER {
checksum = "08944cea9021170d383287169859c0ca8147d9ec285978393109954448f33cc7"
dependencies = [
"once_cell",
]
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
version = "0.4.13"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "loom"
version = "0.4.0"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15"
dependencies = [
"pin-project-internal 0.4.27",
]
[[package]]
name = "pin-project"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95b70b68509f17aa2857863b6fa00bf21fc93674c7a8893de2f469f6aa7ca2f2"
dependencies = [
"pin-project-internal 1.0.4",
]
[[package]]
name = "pin-project-internal"
version = "0.4.27"
version = "1.0.5"
name = "tokio-stream"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76066865172052eb8796c686f0b441a93df8b08d40a950b062ffb9a426f00edd"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]