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]]