Skip to content

Commit 3cef0fa

Browse files
author
fossdd
committed
Update pijul
1 parent aa90f02 commit 3cef0fa

File tree

13 files changed

+323
-203
lines changed

13 files changed

+323
-203
lines changed

Cargo.lock

Lines changed: 108 additions & 83 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libpijul/Cargo.toml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "libpijul"
33
description = "Core library of Pijul, a distributed version control system based on a sound theory of collaborative work."
4-
version = "1.0.0-alpha.52"
4+
version = "1.0.0-beta"
55

66
repository = "https://nest.pijul.com/pijul/libpijul"
77
documentation = "https://docs.rs/libpijul"
@@ -99,14 +99,14 @@ default = [ "ondisk-repos", "text-changes", "dump" ]
9999
tarball = [ "tar", "flate2" ]
100100

101101
[dependencies]
102-
sanakirja = { version = "1.2.13", features = [ "crc32" ] }
103-
byteorder = "1.3"
102+
sanakirja = { version = "1.2.16", features = [ "crc32" ] }
103+
byteorder = "1.4"
104104
log = "0.4"
105105
serde = "1.0"
106106
serde_derive = "1.0"
107-
bitflags = "1.2"
107+
bitflags = "1.3"
108108
thiserror = "1.0"
109-
blake3 = "1.0"
109+
blake3 = "1.3"
110110
chrono = { version = "0.4", features = ["serde"] }
111111
pijul-macros = { path = "../pijul-macros", version = "0.5.0" }
112112
bincode = "1.3"
@@ -120,13 +120,13 @@ crossbeam-deque = "0.8"
120120
crossbeam-utils = "0.8"
121121
nom = "7"
122122

123-
zstd-seekable = { version = "0.1.0", optional = true }
123+
zstd-seekable = { version = "0.1.7", optional = true }
124124
cfg-if = "1.0"
125125
memchr = "2.4"
126126

127-
encoding_rs = "0.8.26"
128-
regex = { version = "1.4", optional = true }
129-
tokio = { version = "1.0", optional = true, features = ["io-util"] }
127+
encoding_rs = "0.8.30"
128+
regex = { version = "1.5", optional = true }
129+
tokio = { version = "1.15", optional = true, features = ["io-util"] }
130130
curve25519-dalek = { version = "3", features = [ "serde" ] }
131131
ed25519-dalek = { version = "1.0", features = [ "serde" ] }
132132
ignore = { version = "0.4", optional = true }

libpijul/src/change/text_changes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,7 @@ pub fn get_deleted_names<C: ChangeStore>(
11181118
if !h.insert(d.to) {
11191119
continue;
11201120
}
1121-
tmp.clear();
1121+
tmp.resize(d.to.end - d.to.start, 0);
11221122
changes
11231123
.get_contents_ext(d.to, &mut tmp)
11241124
.map_err(TextSerError::C)?;

libpijul/src/diff/vertex_buffer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ impl Diff {
279279
},
280280
Err(i) => {
281281
assert!(i > 0);
282-
let len = self.pos_a[i-1].vertex.end - self.pos_a[i-1].vertex.start;
283-
if pos < self.pos_a[i-1].pos + len || len == 0 {
282+
let len = self.pos_a[i - 1].vertex.end - self.pos_a[i - 1].vertex.start;
283+
if pos < self.pos_a[i - 1].pos + len || len == 0 {
284284
i - 1
285285
} else {
286286
i

libpijul/src/find_alive.rs

Lines changed: 126 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,49 @@
11
use crate::pristine::*;
22
use crate::{HashMap, HashSet};
3-
use std::cell::RefCell;
4-
use std::rc::Rc;
53

6-
type Alive = Rc<RefCell<HashSet<Vertex<ChangeId>>>>;
7-
8-
pub(crate) fn find_alive_down<T: GraphTxnT>(
4+
/// The following is an unrolled DFS, where each alive vertex is
5+
/// inserted into each "alive set" along the current path (which is
6+
/// recognised by looking at the visited vertices on the stack).
7+
pub(crate) fn find_alive_down<'a, T: GraphTxnT>(
98
txn: &T,
109
channel: &T::Graph,
1110
vertex0: Vertex<ChangeId>,
12-
cache: &mut HashMap<Vertex<ChangeId>, Alive>,
13-
) -> Result<Alive, BlockError<T::GraphError>> {
14-
let mut stack = vec![SerializedEdge::empty(vertex0.start_pos(), ChangeId::ROOT)];
11+
cache: &'a mut HashMap<Vertex<ChangeId>, Option<HashSet<Vertex<ChangeId>>>>,
12+
) -> Result<&'a Option<HashSet<Vertex<ChangeId>>>, BlockError<T::GraphError>> {
13+
let mut stack: Vec<(_, Option<HashSet<Vertex<ChangeId>>>)> = vec![(
14+
SerializedEdge::empty(vertex0.start_pos(), ChangeId::ROOT),
15+
None,
16+
)];
1517
let mut visited = HashSet::default();
16-
let alive = Rc::new(RefCell::new(HashSet::new()));
17-
while let Some(elt) = stack.pop() {
18-
if !visited.insert(elt.dest()) {
18+
while let Some((elt, alive)) = stack.pop() {
19+
if let Some(alive) = alive {
20+
// We've gone through all the descendants, put this in the
21+
// cache.
22+
let vertex = txn.find_block(&channel, elt.dest())?;
23+
cache.insert(*vertex, Some(alive.clone()));
24+
if stack.is_empty() {
25+
// Done!
26+
return Ok(cache.get(&vertex0).unwrap());
27+
}
1928
continue;
29+
} else {
30+
if !visited.insert(elt.dest()) {
31+
continue;
32+
}
33+
stack.push((elt, Some(HashSet::new())));
2034
}
2135
let vertex = txn.find_block(&channel, elt.dest())?;
2236
if let Some(c) = cache.get(vertex) {
23-
alive.borrow_mut().extend(c.borrow().iter().cloned());
37+
for st in stack.iter_mut() {
38+
if let Some(ref mut st) = st.1 {
39+
if let Some(c) = c {
40+
st.extend(c.iter().cloned());
41+
} else {
42+
st.insert(*vertex);
43+
}
44+
}
45+
}
2446
continue;
25-
} else {
26-
cache.insert(*vertex, alive.clone());
2747
}
2848
debug!("elt = {:?}, vertex = {:?}", elt, vertex);
2949
let elt_index = stack.len();
@@ -39,60 +59,94 @@ pub(crate) fn find_alive_down<T: GraphTxnT>(
3959
&& !v.flag().contains(EdgeFlags::PSEUDO)
4060
{
4161
if *vertex == vertex0 {
42-
assert!(alive.borrow().is_empty());
43-
return Ok(alive);
62+
// vertex0 is alive.
63+
stack.truncate(elt_index);
64+
let (_, alive) = stack.pop().unwrap();
65+
let alive = alive.unwrap();
66+
assert!(alive.is_empty());
67+
cache.insert(vertex0, None);
68+
return Ok(cache.get(&vertex0).unwrap());
4469
} else {
45-
alive.borrow_mut().insert(*vertex);
70+
// vertex is alive, insert it into all the
71+
// alive sets on the current DFS path
72+
// (including `vertex`).
73+
for st in stack.iter_mut() {
74+
if let Some(ref mut st) = st.1 {
75+
st.insert(*vertex);
76+
}
77+
}
4678
stack.truncate(elt_index);
4779
break;
4880
}
4981
}
5082
} else {
51-
stack.push(*v)
83+
stack.push((*v, None))
5284
}
5385
}
5486
}
55-
Ok(alive)
87+
unreachable!()
5688
}
5789

58-
pub fn find_alive_up<T: GraphTxnT>(
90+
pub fn find_alive_up<'a, T: GraphTxnT>(
5991
txn: &T,
6092
channel: &T::Graph,
6193
files: &mut HashSet<Vertex<ChangeId>>,
6294
vertex0: Vertex<ChangeId>,
6395
change: ChangeId,
64-
cache: &mut HashMap<Vertex<ChangeId>, (Alive, Alive)>,
65-
) -> Result<Alive, BlockError<T::GraphError>> {
96+
cache: &'a mut HashMap<
97+
Vertex<ChangeId>,
98+
(Option<HashSet<Vertex<ChangeId>>>, HashSet<Vertex<ChangeId>>),
99+
>,
100+
) -> Result<&'a Option<HashSet<Vertex<ChangeId>>>, BlockError<T::GraphError>> {
66101
debug!("find alive up: {:?}", vertex0);
67-
let alive = Rc::new(RefCell::new(HashSet::default()));
68-
let files_ = Rc::new(RefCell::new(HashSet::default()));
69-
let mut stack = vec![SerializedEdge::empty(vertex0.end_pos(), ChangeId::ROOT)];
102+
let mut stack: Vec<(
103+
_,
104+
Option<(HashSet<Vertex<ChangeId>>, HashSet<Vertex<ChangeId>>)>,
105+
)> = vec![(
106+
SerializedEdge::empty(vertex0.end_pos(), ChangeId::ROOT),
107+
None,
108+
)];
70109
let mut visited = HashSet::default();
71110

72-
while let Some(elt) = stack.pop() {
111+
while let Some((elt, alive)) = stack.pop() {
73112
if elt.dest().is_root() {
74113
continue;
75114
}
76-
if !visited.insert(elt.dest()) {
115+
if let Some((alive, files_)) = alive {
116+
let vertex = *txn.find_block_end(&channel, elt.dest())?;
117+
cache.insert(vertex, (Some(alive), files_));
118+
if stack.is_empty() {
119+
// Done!
120+
return Ok(&cache.get(&vertex0).unwrap().0);
121+
}
77122
continue;
78-
}
79-
let vertex = *txn.find_block_end(&channel, elt.dest())?;
80-
debug!("vertex = {:?}", vertex);
81-
let is_cached = if let Some((c, f)) = cache.get(&vertex) {
82-
alive.borrow_mut().extend(c.borrow().iter().cloned());
83-
files_.borrow_mut().extend(f.borrow().iter().cloned());
84-
files.extend(f.borrow().iter().cloned());
85-
// We're not continuing here, since the while loop below
86-
// needs to insert stuff into `files` and `files_`.
87-
true
88123
} else {
89-
cache.insert(vertex, (alive.clone(), files_.clone()));
90-
false
124+
if !visited.insert(elt.dest()) {
125+
continue;
126+
}
127+
stack.push((elt, Some((HashSet::new(), HashSet::new()))));
91128
};
129+
let vertex = *txn.find_block_end(&channel, elt.dest())?;
130+
debug!("vertex = {:?}", vertex);
131+
if let Some((c, d)) = cache.get(&vertex) {
132+
debug!("Cached: {:?} {:?}", c, d);
133+
for st in stack.iter_mut() {
134+
if let Some((ref mut al, ref mut f)) = st.1 {
135+
if let Some(c) = c {
136+
al.extend(c.iter().cloned());
137+
} else {
138+
al.insert(vertex);
139+
}
140+
f.extend(d.iter().cloned());
141+
files.extend(d.iter().cloned());
142+
}
143+
}
144+
continue;
145+
}
92146
debug!("find_alive_up: elt = {:?}, vertex = {:?}", elt, vertex);
93147
debug!("stack = {:?}", stack);
94148
let elt_index = stack.len();
95-
let mut is_file = false;
149+
let mut is_file = false; // Is this the "inode" vertex of a file?
96150
let mut it = iter_adj_all(txn, &channel, vertex)?;
97151
while let Some(v) = it.next() {
98152
let v = v?;
@@ -105,40 +159,59 @@ pub fn find_alive_up<T: GraphTxnT>(
105159
continue;
106160
}
107161
if !v.flag().is_deleted() {
162+
if vertex == vertex0 {
163+
// vertex0 is alive.
164+
stack.truncate(elt_index);
165+
let (_, alive) = stack.pop().unwrap();
166+
let (alive, _) = alive.unwrap();
167+
assert!(alive.is_empty());
168+
cache.insert(vertex0, (None, HashSet::new()));
169+
return Ok(&cache.get(&vertex0).unwrap().0);
170+
}
108171
if v.flag().is_folder() {
109172
for e in it {
110173
let e = e?;
111174
is_file |= !e.flag().intersects(EdgeFlags::parent_folder())
112175
}
113-
if is_file && vertex != vertex0 {
176+
if is_file {
114177
debug!("is alive + is file {:?}", vertex);
115-
alive.borrow_mut().insert(vertex);
116-
files_.borrow_mut().insert(vertex);
178+
for st in stack.iter_mut() {
179+
if let Some((ref mut al, ref mut fi)) = st.1 {
180+
al.insert(vertex);
181+
fi.insert(vertex);
182+
}
183+
}
117184
files.insert(vertex);
118185
}
119186
break;
120187
} else if v.flag().is_block() || vertex.is_empty() {
121-
if vertex != vertex0 {
122-
debug!("is alive {:?}", vertex);
123-
alive.borrow_mut().insert(vertex);
188+
debug!("is alive {:?}", vertex);
189+
for st in stack.iter_mut() {
190+
if let Some((ref mut st, _)) = st.1 {
191+
st.insert(vertex);
192+
}
124193
}
125194
stack.truncate(elt_index);
126195
break;
127196
}
128197
}
129198
if v.flag().is_folder() {
130-
if is_file && vertex != vertex0 {
131-
debug!("is alive {:?}", vertex);
132-
alive.borrow_mut().insert(vertex);
133-
files_.borrow_mut().insert(vertex);
199+
if is_file {
200+
debug!("is pseudo-alive folder {:?}", vertex);
201+
for st in stack.iter_mut() {
202+
if let Some((ref mut al, ref mut fi)) = st.1 {
203+
al.insert(vertex);
204+
fi.insert(vertex);
205+
}
206+
}
134207
files.insert(vertex);
135208
}
136209
break;
137-
} else if !is_cached {
138-
stack.push(*v)
210+
} else {
211+
stack.push((*v, None))
139212
}
140213
}
141214
debug!("is_file = {:?}", is_file);
142215
}
143-
Ok(alive)
216+
unreachable!()
144217
}

libpijul/src/fs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,7 @@ pub(crate) fn follow_oldest_path<T: ChannelTxnT, C: ChangeStore>(
878878
)? {
879879
let name = name?;
880880
let name_dest = txn.find_block(txn.graph(channel), name.dest()).unwrap();
881+
debug!("name_dest = {:?}", name_dest);
881882
if name_dest.start == name_dest.end {
882883
// non-null root, just continue.
883884
current = iter_adjacent(txn, txn.graph(channel), *name_dest, flag0, flag1)?
@@ -956,6 +957,7 @@ pub fn find_path<T: ChannelTxnT, C: ChangeStore>(
956957
}
957958
Err(BlockError::Txn(t)) => return Err(crate::output::FileError::Txn(TxnErr(t))),
958959
};
960+
debug!("inode_vertex = {:?}", inode_vertex);
959961
if *inode_vertex != v.inode_vertex() {
960962
info!(
961963
"find_path: {:?} != {:?}, this may be due to a corrupt change",
@@ -988,6 +990,7 @@ pub fn find_path<T: ChannelTxnT, C: ChangeStore>(
988990
break;
989991
}
990992
}
993+
debug!("next = {:?}", next);
991994
if let Some(next) = next {
992995
debug!("oldest_path, next = {:?}", next);
993996
if !next.flag().contains(EdgeFlags::DELETED) {
@@ -999,6 +1002,7 @@ pub fn find_path<T: ChannelTxnT, C: ChangeStore>(
9991002
}
10001003
if let Some((_, p_age, _)) = next_v {
10011004
if (age > p_age) ^ youngest {
1005+
debug!("youngest");
10021006
continue;
10031007
}
10041008
}

libpijul/src/key.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ impl PublicKey {
209209
let signed =
210210
bincode::serialize(&(Algorithm::Ed25519, self.expires.clone(), &self.key))
211211
.unwrap();
212-
let mut hash = ed25519_dalek::Sha512::new();
212+
let mut hash = ed25519_dalek::Sha512::default();
213213
hash.update(&signed);
214214
bs58::encode(&hash.finalize()).into_string()
215215
}

0 commit comments

Comments
 (0)