A3RM526Y7LUXNYW4TL56YKQ5GVOK2R5D7JJVTSQ6TT5MEXIR6YAAC R245EVN36J34PTG3I2RMX5LIOT76LCPL5RZ2H22BCIXFBGJYJ25QC G6YXRFH24OGXYVO4535WCNQMMWOLDH6JYXFDBCL2HQZSOFD25Z5AC TFK7CYFQSI6KLVA2XZG6JR7ZF5QSUODJBDYM3PTDPBUHVSDQLAIQC 5OGOE4VWS5AIG4U2UYLLIGA3HY6UB7SNQOSESHNXBLET3VQXFBZAC SMMBFECLGSUKRZW5YPOQPOQCOY2CH2OTZXBSZ3KG2N3J3HQZ5PSAC SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC JL4WKA5PBKXRNAMETYO4I52QKASQ3COYHH2JKGA7W5YLIRZZH53AC YN63NUZO4LVJ7XPMURDULTXBVJKW5MVCTZ24R7Z52QMHO3HPDUVQC KLBWKCUZF3ATGINZCGJL5U7MGD7EBJYDORLWDUDMNWMSN2COJ2ZQC WKX5S4Z4DOB5S6A6X5V6ECZFCHQUMWRGX5XT4FBOG57P6HPWK7CAC WZVCLZKY34KQBQU6YBGJLQCDADBQ67LQVDNRVCMQVY3O3C3EIWSQC RRCSHAYZ6RLWVPNYHF2F5FSRL2KKJNPQUQRIJYLJGB23BZQQ7JLQC UDHP4ZVBQZT2VBURB2MDCU2IZDNMCAFSIUKWRBDQ5BWMFKSN2LYQC 76PCXGML77EZWTRI5E6KHLVRAFTJ2AB5YRN5EKOYNAPKTWY2KCGAC GYXIF25T2BCTCWCQI5DQOF3F4HBWDJUDJUMZ2WLHVBIOYATJTFAQC SZWBLWZ4LUJZHTSYOIGJMXM7KPCGWJFPKLHYA5MHY7UTPNLZV5KQC CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC Q45QHPO4HDTEZF2W4UDZSYYQ46BPEIWSW4GJILZR5HTJNLKXJABQC BNPSVXIC72C3WT33YKCH766OBLLNCS7POX6U6JXZSQQPJF2M22MQC HXEIH4UQ6EX3MAY33JK4WQUE5GUSZ673OX57JKNFXC2N2QLTXKXAC 2D7P2VKJASU7QDQZHGCLBIT6G2V5WUFYLWTCEVVEI2EZHGM6XYRAC MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC I24UEJQLCH2SOXA4UHIYWTRDCHSOPU7AFTRUOTX7HZIAV4AZKYEQC KI2AFWOSN3PTGBGYQ7UKHFOZERZWEUWQ4AQNADG5S4QDJ53ESXFAC FBXYP7QM7SG6P2JDJVQPPCRKJE3GVYXNQ5GVV4GRDUNG6Q4ZRDJQC SNZ3OAMCPUGFYON5SZHQQQK46ZZMVMJECJYEUCMG657UVLY2PNBQC EEBKW7VTILH6AGGV57ZIJ3DJGYHDSYBWGU3C7Q4WWAKSVNUGIYMQC IUGP6ZGBFLDRAKJOHFQNG67LZBDXUJ4QM25GOY3QT6GER3NVTHXQC SLJ3OHD4F6GJGZ3SV2D7DMR3PXYHPSI64X77KZ3RJ24EGEX6ZNQAC QL6K2ZM35B3NIXEMMCJWUSFXOBQHAGXRDMO7ID5DCKTJH4QJVY7QC F6V27C3M7GZHBHXMGAZMYO5XGWDYYNNIF2HLDE2VPNHTEVDSYGVQC TFPETWTVADLG2DL7WERHJPGMJVOY4WOKCRWB3NZ3YOOQ4CVAUHBAC ZBNKSYA6PW4DSPC3NCRUZLVHW2GNXMCSDSAGEIKHGHDGGZRBH7ZQC 367UBQ6KNAKUEWG32R4QRJ6H7IE7NAZFOPTC3ZOE4Z6E44RV3ISQC 5BB266P6HPUGYEVR7QNNOA62EFPYPUYJ3UMLE5J3LLYMSUWXANIQC TPEH2XNBS5RO4IEVKENVF6P65AH7IX64KK2JAYMSJT3J5GXO67EAC JRENVH5DF2F4SOV7UNJENFA7VDI3H63XK76R3LFZK6QCW7JIBLSQC IIV3EL2XYI2X7HZWKXEXQFAE3R3KC2Q7SGOT3Q332HSENMYVF32QC GHO6DWPILBBTL6CVZKERJBTFL3EY6ZT4YM4E5R4S6YPGVFKFHCVAC 7ZFRYVVQQGJYG3POPWJWL3CDW37YDXZYZQC3OSWFHWEUSEMYQ4EQC TZ42DX3BML5C3O5Z6OBVNBCHSIIHT6AOJPD6ICOLOP4LPYFXQN2QC VO5OQW4W2656DIYYRNZ3PO7TQ4JOKQ3GVWE5ALUTYVMX3WMXJOYQC 3AMEP2Y5J6GA4AWQONF4JVA3XSR3ASLHHKMYG44R72SOUY3UQCDAC I52XSRUH5RVHQBFWVMAQPTUSPAJ4KNVID2RMI3UGCVKFLYUO6WZAC 3S6LU2U5TIU43WRE5RQS3IOLVJLVNCDL4W44FVK2HR3NAXZ7IDUAC TVVW53HZGYPODAXEQ4BFZNSPBOFG6JEDVOKIYIDZMWFAMOBKOR2QC T3S4P4ETZABWNK6UET3IDKAWRUOUKQNGCSDMTBJZC7U5R47LQ5DQC 6HNRL5RT76NH5YNSUN7B4FHNRZXKNLX4DROFGMO4R5P2U7JWOL2QC 6DOXSHWGKJIMIPFCNLASGKBAJCJMJULW5HFRZAZ67EYSMXXGJ3KAC 3WIQYEISUMGOL5FY4LCWOJS55CTTQA7WMJZXAE3Q4GQUTBFLAE7QC OUWD436ATBTZJR53B6XDSI5SXRRNZV7YGRUEA5ACHZC2RUDP7G5QC XSEODPNEN2Y2THBRO7L5QFPAEQVSQTLAFZFWCRMBGZ3YSRZB2UJAC IXC43DSHDSXCE2X6H6N47GGVKTYM2D2BUUWF34CFWMFT6Z45NOOAC 23LVKATNTT74YKHG7KJM6SBO2IVZEV24TQ46ZJIHQ2IXONWNVXJAC 33SQMZYXPV2A3F7P6WBFKFO2BTQV6THSQXOLV3PCZASC6OTKVHTQC XWETQ4DE4KL2GQWSEBE5NENLTSLIDF7RIWOCCVWJFQOVQJE5P33AC WEHUTJUKHOJIBMEK2M7ILPK532FMO7YGWTEAHOIXZP5WOOOSF3ZAC ENKQ3QZGH2QW246C7GSZRKYLODJOQHKZZSYV7QHB7VPOFP5PASVQC UFCZKKLXVYQYQBYENCAFHY3ZPPSDAJJAIREZSYNQM4QNXV6G6RXAC pub async fn find_root(cur: Option<PathBuf>) -> Result<Self, anyhow::Error> {Self::find_root_with_dot_dir(cur, DOT_DIR).await
pub fn find_root(cur: Option<PathBuf>) -> Result<Self, anyhow::Error> {Self::find_root_with_dot_dir(cur, DOT_DIR)
pub fn ssh_remote(addr: &str) -> Option<Remote> {let cap = ADDRESS.captures(addr)?;
pub fn ssh_remote(addr: &str, with_path: bool) -> Option<Remote> {let cap = if with_path {ADDRESS.captures(addr)?} else {ADDRESS_NOPATH.captures(addr)?};
} else {sender.send(None).unwrap_or(());}}}State::Id { ref mut sender } => {debug!("state: State {:?}", data);if let Some(sender) = sender.take() {let line = if data.last() == Some(&10) {libpijul::pristine::RemoteId::from_base32(&data[..data.len() - 1])} else {None};if let Some(b) = line {sender.send(Some(b)).unwrap_or(());
State::Prove {ref mut key,ref mut sender,ref mut signed,} => {if let Ok(data) = std::str::from_utf8(&data) {if *signed && !data.trim().is_empty() {std::io::stderr().write_all(data.as_bytes())?;} else {let data = data.trim();debug!("signing {:?}", data);let s = key.sign_raw(data.as_bytes())?;session.data(channel,thrussh::CryptoVec::from_slice(format!("prove {}\n", s).as_bytes()),);if let Some(sender) = sender.take() {sender.send(()).unwrap_or(());}*signed = true;}}}State::Identities {ref mut sender,ref mut buf,} => {debug!("data = {:?}", data);if data.ends_with(&[10]) {let buf = if buf.is_empty() {&data} else {buf.extend(&data);&buf};for data in data.split(|c| *c == 10) {if let Ok(p) = serde_json::from_slice(&buf) {debug!("p = {:?}", p);if let Some(ref mut sender) = sender {sender.send(p).await?;}} else {debug!("could not parse {:?}", std::str::from_utf8(&data));*sender = None;break;}}} else {buf.extend(&data);}}
pub async fn get_id(&mut self) -> Result<Option<libpijul::pristine::RemoteId>, anyhow::Error> {let (sender, receiver) = tokio::sync::oneshot::channel();*self.state.lock().await = State::Id {sender: Some(sender),};self.run_protocol().await?;self.c.data(format!("id {}\n", self.channel).as_bytes()).await?;Ok(receiver.await?)}pub async fn prove(&mut self, key: libpijul::key::SKey) -> Result<(), anyhow::Error> {debug!("get_state");let (sender, receiver) = tokio::sync::oneshot::channel();let k = serde_json::to_string(&key.public_key())?;*self.state.lock().await = State::Prove {key,sender: Some(sender),signed: false,};self.run_protocol().await?;self.c.data(format!("challenge {}\n", k).as_bytes()).await?;Ok(receiver.await?)}
}pub async fn update_identities(&mut self,rev: Option<u64>,mut path: PathBuf,) -> Result<u64, anyhow::Error> {let (sender_, mut recv) = tokio::sync::mpsc::channel(100);*self.state.lock().await = State::Identities {sender: Some(sender_),buf: Vec::new(),};self.run_protocol().await?;if let Some(rev) = rev {self.c.data(format!("identities {}\n", rev).as_bytes()).await?;} else {self.c.data("identities\n".as_bytes()).await?;}let mut revision = 0;std::fs::create_dir_all(&path)?;while let Some(id) = recv.recv().await {path.push(&id.public_key.key);debug!("recv identity: {:?} {:?}", id, path);let mut id_file = std::fs::File::create(&path)?;serde_json::to_writer_pretty(&mut id_file, &id)?;path.pop();revision = revision.max(id.last_modified);}debug!("done receiving");Ok(revision)
} else {Ok(None)}}RemoteRepo::None => unreachable!(),}}async fn get_id<T: libpijul::TxnTExt>(&mut self,txn: &T,) -> Result<Option<libpijul::pristine::RemoteId>, anyhow::Error> {match *self {RemoteRepo::Local(ref l) => l.get_id(),RemoteRepo::Ssh(ref mut s) => s.get_id().await,RemoteRepo::Http(ref h) => h.get_id().await,RemoteRepo::LocalChannel(ref channel) => {if let Some(channel) = txn.load_channel(&channel)? {Ok(Some(*txn.id(&*channel.read().unwrap())))
}async fn update_identities(&mut self,rev: Option<u64>,path: PathBuf,) -> Result<u64, anyhow::Error> {let r = match *self {RemoteRepo::Local(ref mut l) => l.update_identities(rev, path).await?,RemoteRepo::Ssh(ref mut s) => s.update_identities(rev, path).await?,RemoteRepo::Http(ref mut h) => h.update_identities(rev, path).await?,RemoteRepo::LocalChannel(_) => 0,RemoteRepo::None => unreachable!(),};Ok(r)
for x in txn.iter_remote(&remote_changes.lock()?.remote, 0)? {let (_, p) = x?;pullable.push(p.a.into())
{let rem = remote_changes.lock()?;for x in txn.iter_remote(&rem.remote, 0)? {let (_, p) = x?;pullable.push(p.a.into())}
if n >= from {let h_int = remote_txn.get_internal(h)?.unwrap();if paths_.is_empty()|| paths_.iter().any(|x| {remote_txn.get_touched_files(x, Some(h_int)).unwrap().is_some()}){txn.put_remote(remote, n, (h.into(), m.into()))?;}
assert!(n >= from);let h_int = remote_txn.get_internal(h)?.unwrap();if paths_.is_empty()|| paths_.iter().any(|x| {remote_txn.get_touched_files(x, Some(h_int)).unwrap().is_some()}){debug!("put_remote {:?} {:?} {:?}", n, h, m);txn.put_remote(remote, n, (h.into(), m.into()))?;
pub async fn update_identities(&mut self,_rev: Option<u64>,mut path: PathBuf,) -> Result<u64, anyhow::Error> {let mut other_path = self.root.join(DOT_DIR);other_path.push("identities");let r = if let Ok(r) = std::fs::read_dir(&other_path) {r} else {return Ok(0);};std::fs::create_dir_all(&path)?;for id in r {let id = id?;let m = id.metadata()?;let p = id.path();path.push(p.file_name().unwrap());if let Ok(ml) = std::fs::metadata(&path) {if ml.modified()? < m.modified()? {std::fs::remove_file(&path)?;} else {continue;}}if std::fs::hard_link(&p, &path).is_err() {std::fs::copy(&p, &path)?;}path.pop();}Ok(0)}
pub async fn get_id(&self) -> Result<Option<libpijul::pristine::RemoteId>, anyhow::Error> {debug!("get_state {:?}", self.url);let url = format!("{}/{}", self.url, super::DOT_DIR);let q = [("channel", self.channel.clone()), ("id", String::new())];let res = self.client.get(&url).query(&q).header(reqwest::header::USER_AGENT, USER_AGENT).send().await?;if !res.status().is_success() {bail!("HTTP error {:?}", res.status())}let resp = res.bytes().await?;debug!("resp = {:?}", resp);Ok(libpijul::pristine::RemoteId::from_bytes(&resp))}
}pub async fn update_identities(&mut self,rev: Option<u64>,mut path: PathBuf,) -> Result<u64, anyhow::Error> {let url = {let mut p = self.url.path().to_string();if !p.ends_with("/") {p.push('/')}p.push_str(super::DOT_DIR);let mut u = self.url.clone();u.set_path(&p);u};let res = self.client.get(url).query(&[("identities",if let Some(rev) = rev {format!("{}", rev)} else {String::new()},)]).header(reqwest::header::USER_AGENT, USER_AGENT).send().await?;if !res.status().is_success() {bail!("HTTP error {:?}", res.status())}use serde_derive::*;#[derive(Debug, Deserialize)]struct Identities {id: Vec<crate::Identity>,rev: u64,}let resp: Identities = res.json().await?;std::fs::create_dir_all(&path)?;for id in resp.id.iter() {path.push(&id.public_key.key);debug!("recv identity: {:?} {:?}", id, path);let mut id_file = std::fs::File::create(&path)?;serde_json::to_writer_pretty(&mut id_file, &id)?;path.pop();}Ok(resp.rev)
let key = if let Some(mut dir) = crate::config::global_config_dir() {dir.push("secretkey.json");if let Ok(key) = std::fs::File::open(&dir) {let k: libpijul::key::SecretKey = serde_json::from_reader(key)?;let pass = if k.encryption.is_some() {Some(rpassword::read_password_from_tty(Some(&format!("Password for {:?}: ",dir)))?)} else {None};k.load(pass.as_deref())?} else {bail!("Secret key not found, please use `pijul key generate` and try again")}} else {bail!("Secret key not found, please use `pijul key generate` and try again")};
let key = super::load_key()?;
} else if let Some(cap) = IDENTITIES.captures(&buf) {let last_touched: u64 = if let Some(last) = cap.get(2) {last.as_str().parse().unwrap()} else {0};let mut id_dir = repo.path.clone();id_dir.push(DOT_DIR);id_dir.push("identities");let r = if let Ok(r) = std::fs::read_dir(&id_dir) {r} else {continue;};for id in r {let id = id?;let m = id.metadata()?;let p = id.path();debug!("{:?}", p);let mod_ts = m.modified()?.duration_since(std::time::SystemTime::UNIX_EPOCH).unwrap().as_secs();if mod_ts >= last_touched {let mut done = HashSet::new();if p.file_name() == Some("publickey.json".as_ref()) {let public_key: libpijul::key::PublicKey =if let Some(mut dir) = crate::config::global_config_dir() {dir.push("publickey.json");let mut pkf = std::fs::File::open(&dir)?;serde_json::from_reader(&mut pkf)?} else {continue;};if !done.insert(public_key.key.clone()) {continue;}if let Ok((config, last_modified)) = crate::config::Global::load() {serde_json::to_writer(&mut o,&crate::Identity {public_key,email: config.author.email,name: config.author.full_name,login: config.author.name,origin: String::new(),last_modified,},).unwrap();writeln!(o)?;o.flush()?;} else {debug!("no global config");}} else {let mut idf = if let Ok(f) = std::fs::File::open(&p) {f} else {continue;};let id: Result<crate::Identity, _> = serde_json::from_reader(&mut idf);if let Ok(id) = id {if !done.insert(id.public_key.key.clone()) {continue;}serde_json::to_writer(&mut o, &id).unwrap();writeln!(o)?;o.flush()?;}}}}writeln!(o)?;o.flush()?;
email: Option<String>,
pub email: Option<String>,pub last_modified: u64,}fn load_key() -> Result<libpijul::key::SKey, anyhow::Error> {if let Some(mut dir) = crate::config::global_config_dir() {dir.push("secretkey.json");if let Ok(key) = std::fs::File::open(&dir) {let k: libpijul::key::SecretKey = serde_json::from_reader(key)?;let pass = if k.encryption.is_some() {Some(rpassword::read_password_from_tty(Some(&format!("Password for {:?}: ",dir)))?)} else {None};Ok(k.load(pass.as_deref())?)} else {bail!("Secret key not found, please use `pijul key generate` and try again")}} else {bail!("Secret key not found, please use `pijul key generate` and try again")}
for auth in header.authors.into_iter() {let auth = match authors.entry(auth.name) {Entry::Occupied(e) => e.into_mut(),Entry::Vacant(e) => {let mut id = None;if let Some(ref mut p) = id_path {p.push(e.key());if let Ok(f) = std::fs::File::open(&p) {
for mut auth in header.authors.into_iter() {let auth = if let Some(k) = auth.0.remove("key") {match authors.entry(k) {Entry::Occupied(e) => e.into_mut(),Entry::Vacant(e) => {let mut id = None;id_path.push(e.key());if let Ok(f) = std::fs::File::open(&id_path) {
Some(SubCommand::Prove {remote,no_cert_check,}) => {let mut remote = if let Ok(repo) = Repository::find_root(None) {use crate::remote::*;if let RemoteRepo::Ssh(ssh) = repo.remote(None, &remote, crate::DEFAULT_CHANNEL, no_cert_check, false).await?{ssh} else {bail!("No such remote: {}", remote)}} else if let Some(mut ssh) = crate::remote::ssh::ssh_remote(&remote, false) {ssh.connect(&remote, crate::DEFAULT_CHANNEL).await?} else {bail!("No such remote: {}", remote)};let key = super::load_key()?;remote.prove(key).await?;}
let mut remote =crate::remote::unknown_remote(None, &self.remote, &self.channel, self.no_cert_check).await?;
let mut remote = crate::remote::unknown_remote(None,&self.remote,&self.channel,self.no_cert_check,true,).await?;
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 graph: Db<Vertex<ChangeId>, SerializedEdge> = Db::from_page(tup.graph.into());let changes: Db<ChangeId, L64> = Db::from_page(tup.changes.into());
UDb::from_page(tup.0[2].into());let states: UDb<SerializedMerkle, L64> = UDb::from_page(tup.0[3].into());let tags: UDb<L64, SerializedHash> = UDb::from_page(tup.0[4].into());
UDb::from_page(tup.revchanges.into());let states: UDb<SerializedMerkle, L64> = UDb::from_page(tup.states.into());let tags: UDb<L64, SerializedHash> = UDb::from_page(tup.tags.into());
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 name: {:?}", name);let remote: UDb<RemoteId, SerializedRemote> = UDb::from_page(tup.remote.into());let rev: UDb<SerializedHash, L64> = UDb::from_page(tup.rev.into());let states: UDb<SerializedMerkle, L64> = UDb::from_page(tup.states.into());
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()),tags: UDb::from_page(tup.0[4].into()),apply_counter: tup.0[5].into(),last_modified: tup.0[6].into(),
graph: Db::from_page(tup.graph.into()),changes: Db::from_page(tup.changes.into()),revchanges: UDb::from_page(tup.revchanges.into()),states: UDb::from_page(tup.states.into()),tags: UDb::from_page(tup.tags.into()),apply_counter: tup.apply_counter.into(),last_modified: tup.last_modified.into(),id: tup.id,
fn load_remote(&self, name: &str) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>> {let name = SmallString::from_str(name);
fn load_remote(&self,name: &RemoteId,) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>> {let name = name.to_owned();
remote: UDb::from_page(remote.0[0].into()),rev: UDb::from_page(remote.0[1].into()),states: UDb::from_page(remote.0[2].into()),
remote: UDb::from_page(remote.remote.into()),rev: UDb::from_page(remote.rev.into()),states: UDb::from_page(remote.states.into()),id_rev: remote.id_rev.into(),path: remote.path.to_owned(),
type Channels = UDb<SmallStr, T8>;type ChannelsCursor = ::sanakirja::btree::cursor::Cursor<SmallStr, T8, UP<SmallStr, T8>>;sanakirja_cursor!(channels, SmallStr, T8,);
type Channels = UDb<SmallStr, SerializedChannel>;type ChannelsCursor = ::sanakirja::btree::cursor::Cursor<SmallStr,SerializedChannel,UP<SmallStr, SerializedChannel>,>;sanakirja_cursor!(channels, SmallStr, SerializedChannel);
type Remotes = UDb<SmallStr, T3>;type RemotesCursor = ::sanakirja::btree::cursor::Cursor<SmallStr, T3, UP<SmallStr, T3>>;sanakirja_cursor!(remotes, SmallStr, T3);
type Remotes = UDb<RemoteId, SerializedRemote>;type RemotesCursor = ::sanakirja::btree::cursor::Cursor<RemoteId,SerializedRemote,UP<RemoteId, SerializedRemote>,>;sanakirja_cursor!(remotes, RemoteId, SerializedRemote);
remote: UDb::from_page(remote.0[0].into()),rev: UDb::from_page(remote.0[1].into()),states: UDb::from_page(remote.0[2].into()),
remote: UDb::from_page(remote.remote.into()),rev: UDb::from_page(remote.rev.into()),states: UDb::from_page(remote.states.into()),id_rev: remote.id_rev.into(),path: remote.path.to_owned(),
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()),tags: UDb::from_page(b.0[4].into()),apply_counter: b.0[5].into(),last_modified: b.0[6].into(),
graph: Db::from_page(b.graph.into()),changes: Db::from_page(b.changes.into()),revchanges: UDb::from_page(b.revchanges.into()),states: UDb::from_page(b.states.into()),tags: UDb::from_page(b.tags.into()),apply_counter: b.apply_counter.into(),last_modified: b.last_modified.into(),id: b.id,
Db::from_page(chan.0[0].into()),Db::from_page(chan.0[1].into()),UDb::from_page(chan.0[2].into()),UDb::from_page(chan.0[3].into()),UDb::from_page(chan.0[4].into()),
Db::from_page(chan.graph.into()),Db::from_page(chan.changes.into()),UDb::from_page(chan.revchanges.into()),UDb::from_page(chan.states.into()),UDb::from_page(chan.tags.into()),
fn open_or_create_remote(&mut self, name: &str) -> Result<RemoteRef<Self>, Self::GraphError> {let name = crate::small_string::SmallString::from_str(name);
fn open_or_create_remote(&mut self,id: RemoteId,path: &str,) -> Result<RemoteRef<Self>, Self::GraphError> {
let r = match btree::get(&self.txn, &self.remotes, &name, None)? {Some((name_, remote)) if name_ == name.as_ref() => RemoteRef {
let r = match btree::get(&self.txn, &self.remotes, &id, None)? {Some((name_, remote)) if *name_ == id => RemoteRef {
remote: UDb::from_page(remote.0[0].into()),rev: UDb::from_page(remote.0[1].into()),states: UDb::from_page(remote.0[2].into()),
remote: UDb::from_page(remote.remote.into()),rev: UDb::from_page(remote.rev.into()),states: UDb::from_page(remote.states.into()),id_rev: remote.id_rev.into(),path: SmallString::from_str(path),
.get(&name).unwrap().clone())}fn drop_remote(&mut self, remote: RemoteRef<Self>) -> Result<bool, Self::GraphError> {let name = remote.name.clone();let r = self.open_remotes.lock().unwrap().remove(&name).unwrap();
.remove(&remote.id).unwrap();
fn drop_named_remote(&mut self, name: &str) -> Result<bool, Self::GraphError> {let name = SmallString::from_str(name);if let Some(r) = self.open_remotes.lock().unwrap().remove(&name) {
fn drop_named_remote(&mut self, id: RemoteId) -> Result<bool, Self::GraphError> {if let Some(r) = self.open_remotes.lock().unwrap().remove(&id) {
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()),tags: UDb::from_page(c.0[4].into()),apply_counter: c.0[5].into(),last_modified: c.0[6].into(),
graph: Db::from_page(c.graph.into()),changes: Db::from_page(c.changes.into()),revchanges: UDb::from_page(c.revchanges.into()),states: UDb::from_page(c.states.into()),tags: UDb::from_page(c.tags.into()),apply_counter: c.apply_counter.into(),last_modified: c.last_modified.into(),id: c.id,
let t8 = T8([channel.graph.db.into(),channel.changes.db.into(),channel.revchanges.db.into(),channel.states.db.into(),channel.tags.db.into(),channel.apply_counter.into(),channel.last_modified.into(),0u64.into(),]);btree::put(&mut self.txn, &mut self.channels, &channel.name, &t8)?;
let sc = SerializedChannel {graph: channel.graph.db.into(),changes: channel.changes.db.into(),revchanges: channel.revchanges.db.into(),states: channel.states.db.into(),tags: channel.tags.db.into(),apply_counter: channel.apply_counter.into(),last_modified: channel.last_modified.into(),id: channel.id,};btree::put(&mut self.txn, &mut self.channels, &channel.name, &sc)?;
btree::put(&mut self.txn,&mut self.remotes,&remote.name,&T3([r.remote.db.into(), r.rev.db.into(), r.states.db.into()]),)?;
let rr = OwnedSerializedRemote {_remote: r.remote.db.into(),_rev: r.rev.db.into(),_states: r.states.db.into(),_id_rev: r.id_rev.into(),_path: r.path.clone(),};debug!("put {:?}", rr);btree::put(&mut self.txn, &mut self.remotes, &remote.id, &rr)?;
direct_repr!(T3);direct_repr!(T8);
impl Storable for SerializedRemote {type PageReferences = std::iter::Empty<u64>;fn page_references(&self) -> Self::PageReferences {std::iter::empty()}fn compare<T: LoadPage>(&self, _t: &T, b: &Self) -> core::cmp::Ordering {self.cmp(b)}}impl UnsizedStorable for SerializedRemote {const ALIGN: usize = 8;fn size(&self) -> usize {33 + self.path.len()}unsafe fn onpage_size(p: *const u8) -> usize {33 + (*p.add(32)) as usize}unsafe fn from_raw_ptr<'a, T>(_: &T, p: *const u8) -> &'a Self {let len = *p.add(32) as usize;let m: &SerializedRemote =std::mem::transmute(std::slice::from_raw_parts(p, 1 + len as usize));m}unsafe fn write_to_page(&self, p: *mut u8) {std::ptr::copy(&self.remote as *const L64 as *const u8,p,33 + self.path.len(),);debug!("write_to_page: {:?}",std::slice::from_raw_parts(p, 33 + self.path.len()));}}#[derive(Debug)]struct OwnedSerializedRemote {_remote: L64,_rev: L64,_states: L64,_id_rev: L64,_path: SmallString,}impl std::ops::Deref for OwnedSerializedRemote {type Target = SerializedRemote;fn deref(&self) -> &Self::Target {let len = 33 + self._path.len() as usize;unsafe {std::mem::transmute(std::slice::from_raw_parts(self as *const Self as *const u8,len,))}}}direct_repr!(SerializedChannel);direct_repr!(RemoteId);
name: self.name.clone(),
id: self.id.clone(),}}}#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]pub struct RemoteId(pub(crate) [u8; 16]);impl RemoteId {pub fn nil() -> Self {RemoteId([0; 16])}pub fn from_bytes(b: &[u8]) -> Option<Self> {if b.len() < 16 {return None;}let mut x = RemoteId([0; 16]);unsafe {std::ptr::copy_nonoverlapping(b.as_ptr(), x.0.as_mut_ptr(), 16);}Some(x)}pub fn as_bytes(&self) -> &[u8; 16] {&self.0}pub fn from_base32(b: &[u8]) -> Option<Self> {let mut bb = RemoteId([0; 16]);if data_encoding::BASE32_NOPAD.decode_mut(b, &mut bb.0).is_ok() {Some(bb)} else {None
let mut prehashed = ed25519_dalek::Sha512::new();prehashed.update(h);let sig = key.sign_prehashed(prehashed, Some(CONTEXT)).unwrap();Ok(data_encoding::BASE32_NOPAD.encode(&sig.to_bytes()))
let sig = key.sign(&h);Ok(bs58::encode(&sig.to_bytes()).into_string())
key: data_encoding::BASE32_NOPAD.encode(&key.public.clone().to_bytes()),signature: data_encoding::BASE32_NOPAD.encode(&sig.to_bytes()),
key: bs58::encode(&key.public.clone().to_bytes()).into_string(),signature: bs58::encode(&sig.to_bytes()).into_string(),
let mut prehashed = ed25519_dalek::Sha512::new();prehashed.update(&signed);data_encoding::BASE32_NOPAD.encode(&prehashed.finalize())
let mut hash = ed25519_dalek::Sha512::new();hash.update(&signed);bs58::encode(&hash.finalize()).into_string()
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]pub struct Author {pub name: String,#[serde(default)]pub full_name: Option<String>,#[serde(default)]pub email: Option<String>,}impl From<String> for Author {fn from(name: String) -> Author {Author {name,..Author::default()}}}
/// The header of a change contains all the metadata about a change/// (but not the actual contents of a change).pub type ChangeHeader = ChangeHeader_<Author>;
let hashed: Hashed<Hunk<Option<Hash>, Local>> = bincode::deserialize(&buf_)?;
let hashed: Hashed<Hunk<Option<Hash>, Local>, Author> = if offsets.version == VERSION {bincode::deserialize(&buf_)?} else {let h: Hashed<noenc::Hunk<Option<Hash>, Local>, noenc::Author> =bincode::deserialize(&buf_)?;h.into()};
impl From<Hashed<Hunk<Option<Hash>, Local>>> for Hashed<super::Hunk<Option<Hash>, Local>> {fn from(hashed: Hashed<Hunk<Option<Hash>, Local>>) -> Self {
impl From<Hashed<Hunk<Option<Hash>, Local>, Author>>for Hashed<super::Hunk<Option<Hash>, Local>, super::Author>{fn from(hashed: Hashed<Hunk<Option<Hash>, Local>, Author>) -> Self {
use super::ChangeHeader_;impl From<ChangeHeader_<Author>> for ChangeHeader_<super::Author> {fn from(c: ChangeHeader_<Author>) -> Self {ChangeHeader_ {message: c.message,description: c.description,timestamp: c.timestamp,authors: c.authors.into_iter().map(|x| x.into()).collect(),}}}#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]pub struct Author {pub name: String,#[serde(default)]pub full_name: Option<String>,#[serde(default)]pub email: Option<String>,}impl From<String> for Author {fn from(name: String) -> Author {Author {name,..Author::default()}}}impl From<Author> for super::Author {fn from(c: Author) -> Self {let mut b = std::collections::BTreeMap::new();b.insert("name".to_string(), c.name);if let Some(n) = c.full_name {b.insert("full_name".to_string(), n);}if let Some(n) = c.email {b.insert("email".to_string(), n);}super::Author(b)}}
debug!("deserialize noenc {:?}", buf2.len());let h: Hashed<noenc::Hunk<Option<Hash>, Local>> = bincode::deserialize(&buf2)?;
trace!("deserialize noenc {:?}", buf2.len());let h: Hashed<noenc::Hunk<Option<Hash>, Local>, noenc::Author> =bincode::deserialize(&buf2)?;
name = "pin-project"version = "1.0.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4"dependencies = ["pin-project-internal",][[package]]name = "pin-project-internal"version = "1.0.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"dependencies = ["proc-macro2","quote","syn",][[package]]