Refactoring apply
[?]
Dec 25, 2020, 12:14 PM
6YMDOZIB5LVYLFIDGN2WNT5JTHEAMS4TFPVDEZ3OWXWOKJOC5QDACDependencies
- [2]
BD5PC25ADeleting conflict resolution vertices when the sides are deleted - [3]
ATZ3BWSEFixing the double-deletion of repairs for folder edges - [4]
CFNFIUJVParsing the correct flags for new vertices - [5]
I52XSRUHMassive cleanup, and simplification - [6]
7FFFKQZUadd 'Default' implementations - [7]
L5PHFTIEMinor simplification - [8]
43AJ37IXGetting rid of edge validation, which does not work for zombie conflicts - [9]
SXEYMYF7Fixing the bad changes in history (unfortunately, by rebooting). - [10]
7A2TSC4PConflict solving code (FOLDER edges) - [11]
BAUL3WR2Format, versions, README - [12]
KQTD46KVUnrecord: restore files *after* having unapplied the *entire* change - [13]
HMMMKONLFixing alive vertices - [14]
BXD3IQYNFixing --features git - [15]
WZVCLZKYaddress clippy lints - [16]
KDF6FJRVbigger clippy refactors - [17]
ZXTHL45Oaddress clippy lints - [18]
VO5OQW4WRemoving anyhow in libpijul
Change contents
- replacement in libpijul/src/unrecord/mod.rs at line 124
let mut ws = Workspace::new();let mut ws = Workspace::default(); - replacement in libpijul/src/unrecord/mod.rs at line 143
repair_newvertex_contexts::<T, C>(txn, channel, &mut ws)?;repair_newvertex_contexts::<T, C>(txn, channel, &mut ws, change_id)?; - replacement in libpijul/src/unrecord/mod.rs at line 146
remove_zombies::<T, C>(txn, channel, change_id, n)?;remove_zombies::<_, C>(txn, channel, &mut ws, change_id, n)?; - replacement in libpijul/src/unrecord/mod.rs at line 178
crate::apply::clean_obsolete_pseudo_edges(txn, channel, &mut ws.apply)?;crate::apply::clean_obsolete_pseudo_edges(txn, channel, &mut ws.apply, change_id)?;crate::apply::repair_cyclic_paths(txn, channel, &mut ws.apply)?; - edit in libpijul/src/unrecord/mod.rs at line 184
#[derive(Default)] - replacement in libpijul/src/unrecord/mod.rs at line 187
down: HashMap<Vertex<ChangeId>, (Position<Option<Hash>>, bool)>,down: HashMap<Vertex<ChangeId>, Position<Option<Hash>>>,parents: HashSet<Vertex<ChangeId>>, - edit in libpijul/src/unrecord/mod.rs at line 191
stack: Vec<Vertex<ChangeId>>,del_edges: Vec<(Vertex<ChangeId>, Edge)>, - edit in libpijul/src/unrecord/mod.rs at line 195
impl Workspace {fn new() -> Self {Workspace {up: HashMap::new(),down: HashMap::new(),del: Vec::new(),apply: crate::apply::Workspace::new(),}}} - replacement in libpijul/src/unrecord/mod.rs at line 207[5.236556]→[5.236556:236629](∅→∅),[5.236629]→[5.7507:7575](∅→∅),[5.7575]→[5.236696:237011](∅→∅),[5.236696]→[5.236696:237011](∅→∅),[5.237011]→[5.7576:7645](∅→∅),[5.7645]→[5.237079:237184](∅→∅),[5.237079]→[5.237079:237184](∅→∅)
while pos.pos <= new_vertex.end {debug!("pos = {:?}", pos);let vertex = if let Ok(v) = find_block(txn, channel, pos) {v} else {// This means that the only edges to this block were// removed from the graph, which can only happen if this// block is the bottommost vertex in the graph.if cfg!(debug_assertions) {while pos.pos <= new_vertex.end {assert!(find_block(txn, channel, pos).is_err());pos.pos = pos.pos + 1;}}break;};while let Ok(vertex) = find_block(txn, channel, pos) { - replacement in libpijul/src/unrecord/mod.rs at line 209
for e in iter_adjacent(txn, channel, vertex, EdgeFlags::empty(), EdgeFlags::all()) {for e in iter_adj_all(txn, channel, vertex) { - replacement in libpijul/src/unrecord/mod.rs at line 211
if !e.flag.contains(EdgeFlags::DELETED) {if e.flag.contains(EdgeFlags::PARENT) {if !e.flag.contains(EdgeFlags::FOLDER) {if !e.flag.is_deleted() {if e.flag.is_parent() {if !e.flag.is_folder() { - replacement in libpijul/src/unrecord/mod.rs at line 219
ws.down.insert(down_v,(new_vertex.inode, e.flag.contains(EdgeFlags::FOLDER)),);ws.down.insert(down_v, new_vertex.inode);if e.flag.is_folder() {ws.apply.missing_context.files.insert(down_v);} - edit in libpijul/src/unrecord/mod.rs at line 230
ws.perform_del::<C, T>(txn, channel, vertex)?;if vertex.end < new_vertex.end {pos.pos = vertex.end}}Ok(())} - replacement in libpijul/src/unrecord/mod.rs at line 238
// Delete all in `del`.for e in ws.del.drain(..) {let (a, b) = if e.flag.contains(EdgeFlags::PARENT) {impl Workspace {fn perform_del<C: ChangeStore, T: MutTxnT>(&mut self,txn: &mut T,channel: &mut Channel<T>,vertex: Vertex<ChangeId>,) -> Result<(), UnrecordError<C::Error, T::Error>> {for e in self.del.drain(..) {let (a, b) = if e.flag.is_parent() { - replacement in libpijul/src/unrecord/mod.rs at line 261
// Move on to the next split of ~new_vertex~.pos.pos = vertex.endOk(()) - edit in libpijul/src/unrecord/mod.rs at line 263
Ok(()) - edit in libpijul/src/unrecord/mod.rs at line 269
change_id: ChangeId, - replacement in libpijul/src/unrecord/mod.rs at line 286
let mut parents = HashSet::new();for (down, (inode, is_folder)) in ws.down.drain() {for (down, inode) in ws.down.drain() { - replacement in libpijul/src/unrecord/mod.rs at line 296
parents.insert(parent);ws.parents.insert(parent); - replacement in libpijul/src/unrecord/mod.rs at line 299
debug!("parents {:#?}", parents);for up in parents.drain() {debug!("parents {:#?}", ws.parents);for up in ws.parents.drain() { - edit in libpijul/src/unrecord/mod.rs at line 305
change_id, - edit in libpijul/src/unrecord/mod.rs at line 309
is_folder, - replacement in libpijul/src/unrecord/mod.rs at line 326
// This is ok: since this change is applied, this can't fail.let int = internal(txn, &edge.introduced_by, change_id).unwrap();let intro = internal(txn, &edge.introduced_by, change_id).unwrap(); - replacement in libpijul/src/unrecord/mod.rs at line 331
int,intro, - replacement in libpijul/src/unrecord/mod.rs at line 333
&NewEdge {previous: edge.flag,flag: edge.previous,from: edge.from,to: edge.to,introduced_by: Some(ext),},&edge.reverse(Some(ext)), - replacement in libpijul/src/unrecord/mod.rs at line 335
must_reintroduce(txn,channel,changes,a,b,edge.introduced_by.unwrap(),int,)must_reintroduce(txn, channel, changes, a, b, ext, intro, change_id) - edit in libpijul/src/unrecord/mod.rs at line 350
current_id: ChangeId, - replacement in libpijul/src/unrecord/mod.rs at line 360
for e in iter_adjacent(txn, channel, a, EdgeFlags::empty(), EdgeFlags::all()).filter(|e| {!e.flag.contains(EdgeFlags::PARENT) && e.dest == b.start_pos() && !e.introduced_by.is_root()for e in iter_adj_all(txn, channel, a).filter(|e| {!e.flag.contains(EdgeFlags::PARENT)&& e.dest == b.start_pos()&& !e.introduced_by.is_root()&& e.introduced_by != current_id - replacement in libpijul/src/unrecord/mod.rs at line 366
// Optimisation to avoid opening change files// in the vast majority of cases: if there is// an edge `e` parallel to a -> b introduced// by the change that introduced a or b, don't// reinsert a -> b: that edge was removed by// `e`.if !cfg!(debug_assertions) && (a.change == intro_id || b.change == intro_id) {// Optimisation to avoid opening change files in the vast// majority of cases: if there is an edge `e` parallel to a ->// b introduced by the change that introduced a or b, don't// reinsert a -> b: that edge was removed by `e`.if a.change == intro_id || b.change == intro_id { - edit in libpijul/src/unrecord/mod.rs at line 406
ws: &mut Workspace, - edit in libpijul/src/unrecord/mod.rs at line 410
let mut del = Vec::new();let mut stack = vec![];let mut visited = HashSet::new(); - edit in libpijul/src/unrecord/mod.rs at line 412
// Remove zombies caused by this EdgeMap. - replacement in libpijul/src/unrecord/mod.rs at line 413[5.8786]→[5.8786:8837](∅→∅),[5.8837]→[5.244476:244670](∅→∅),[5.244476]→[5.244476:244670](∅→∅),[5.244670]→[5.8838:8930](∅→∅),[5.8930]→[5.244761:244800](∅→∅),[5.244761]→[5.244761:244800](∅→∅),[5.244800]→[5.244800:244866](∅→∅),[5.244866]→[5.244866:245084](∅→∅),[5.245084]→[5.245084:245085](∅→∅),[5.245085]→[5.2568:2629](∅→∅),[5.2629]→[5.2629:2659](∅→∅),[5.2659]→[5.245224:245298](∅→∅),[5.245224]→[5.245224:245298](∅→∅),[5.245298]→[5.8931:9001](∅→∅),[5.9001]→[5.245367:245392](∅→∅),[5.245367]→[5.245367:245392](∅→∅),[5.245392]→[5.9002:9068](∅→∅),[5.9068]→[5.245457:245604](∅→∅),[5.245457]→[5.245457:245604](∅→∅),[5.245604]→[5.245604:245689](∅→∅)
stack.push(find_block(txn, channel, to)?);visited.clear();while let Some(v) = stack.pop() {debug!("remove_zombies, v = {:?}", v);if !visited.insert(v) {continue;}for e in iter_adjacent(txn, channel, v, EdgeFlags::empty(), EdgeFlags::all()) {debug!("e = {:?}", e);// If the edge is a parent-non-block edge, go up.let mut follow =e.flag.contains(EdgeFlags::DELETED) && e.introduced_by != change_id;follow |= e.flag & (EdgeFlags::BLOCK | EdgeFlags::PARENT) == EdgeFlags::PARENT;if !follow && e.introduced_by != change_id {continue;}if e.flag.contains(EdgeFlags::PARENT) {stack.push(find_block_end(txn, channel, e.dest)?)} else {stack.push(find_block(txn, channel, e.dest)?)}if e.introduced_by == change_id {del.push((v, e))}}}debug!("remove_zombies = {:#?}", del);for (v, e) in del.drain(..) {collect_zombies(txn, channel, change_id, to, ws)?;debug!("remove_zombies = {:#?}", ws.del_edges);for (v, mut e) in ws.del_edges.drain(..) { - replacement in libpijul/src/unrecord/mod.rs at line 418[5.9132]→[5.9132:9353](∅→∅),[5.9353]→[5.10635:10700](∅→∅),[5.10700]→[5.9373:9621](∅→∅),[5.9373]→[5.9373:9621](∅→∅),[5.9621]→[5.2660:2711](∅→∅),[5.2711]→[5.9698:9725](∅→∅),[5.9698]→[5.9698:9725](∅→∅),[5.9725]→[5.246288:246511](∅→∅),[5.246288]→[5.246288:246511](∅→∅),[5.246511]→[5.10701:10828](∅→∅),[5.9800]→[5.246584:246602](∅→∅),[5.10828]→[5.246584:246602](∅→∅),[5.246584]→[5.246584:246602](∅→∅)
del_graph_with_rev(txn,channel,e.flag - EdgeFlags::PARENT,u,v,e.introduced_by,).map_err(UnrecordError::Txn)?;if iter_adjacent(txn,channel,u,EdgeFlags::empty(),EdgeFlags::all() - EdgeFlags::DELETED - EdgeFlags::PARENT,).find(|e| e.dest == v.start_pos()).is_none(){let f = if e.flag.contains(EdgeFlags::FOLDER) {EdgeFlags::FOLDER} else {EdgeFlags::empty()};put_graph_with_rev(txn, channel, f, u, v, u.change).map_err(UnrecordError::Txn)?;}e.flag -= EdgeFlags::PARENT;del_graph_with_rev(txn, channel, e.flag, u, v, e.introduced_by).map_err(UnrecordError::Txn)?; - edit in libpijul/src/unrecord/mod.rs at line 431
fn collect_zombies<T: TxnT>(txn: &mut T,channel: &mut Channel<T>,change_id: ChangeId,to: Position<ChangeId>,ws: &mut Workspace,) -> Result<(), BlockError> {ws.stack.push(find_block(txn, channel, to)?);while let Some(v) = ws.stack.pop() {debug!("remove_zombies, v = {:?}", v);if !ws.parents.insert(v) {continue;}for e in iter_adj_all(txn, channel, v) {debug!("e = {:?}", e);if !(e.introduced_by == change_id || e.flag & EdgeFlags::bp() == EdgeFlags::PARENT) {continue;}if e.flag.contains(EdgeFlags::PARENT) {ws.stack.push(find_block_end(txn, channel, e.dest)?)} else {ws.stack.push(find_block(txn, channel, e.dest)?)}if e.introduced_by == change_id {ws.del_edges.push((v, e))}}}ws.stack.clear();ws.parents.clear();Ok(())} - edit in libpijul/src/unrecord/mod.rs at line 475
let intro = internal(txn, &e.introduced_by, change_id).unwrap();let intro_ext = e.introduced_by.unwrap_or(change_hash); - edit in libpijul/src/unrecord/mod.rs at line 478[5.247312]→[5.247312:247531](∅→∅),[5.247531]→[5.9943:10020](∅→∅),[5.10020]→[5.247607:247675](∅→∅),[5.247607]→[5.247607:247675](∅→∅)
let e = NewEdge {previous: e.flag,flag: e.previous,from: e.from,to: e.to,introduced_by: Some(change_hash),};let intro = internal(txn, &e.introduced_by, change_id).unwrap();let intro_ext = e.introduced_by.unwrap_or(change_hash); - replacement in libpijul/src/unrecord/mod.rs at line 485
&e,&e.reverse(Some(change_hash)), - edit in libpijul/src/unrecord/mod.rs at line 488
let intro = internal(txn, &e.introduced_by, change_id).unwrap();let intro_ext = e.introduced_by.unwrap_or(change_hash); - replacement in libpijul/src/unrecord/mod.rs at line 500
&NewEdge {previous: e.flag,flag: e.previous,from: e.from,to: e.to,introduced_by: Some(change_hash),},&e.reverse(Some(change_hash)), - replacement in libpijul/src/tests/missing_context.rs at line 120
&"a\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nx\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\ny\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nz\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\nf\n"&"a\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nx\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\ny\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nz\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\nf\n" - replacement in libpijul/src/tests/missing_context.rs at line 127
Ok(&">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nx\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\ny\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nz\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"[..])Ok(&">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nx\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\ny\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nz\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"[..]) - replacement in libpijul/src/tests/file_conflicts.rs at line 414
let files_charlie = repo_charlie.list_files();let mut files_charlie = repo_charlie.list_files();files_charlie.sort();// Two files with the same name (file), one of which also has another name (file3). This means that we don't know which one of the two names crate::output will pick, between "file3" and the conflicting name.// This depends on which file gets output first.assert_eq!(files_charlie[0], "file");assert!(files_charlie[1] == "file3" || files_charlie[1].starts_with("file.")); - edit in libpijul/src/tests/file_conflicts.rs at line 422
repo_charlie.rename(&files_charlie[1], "file3")?;txn_charlie.move_file(&files_charlie[1], "file3")?;let _charlie_solution = record_all(&mut repo_charlie,&changes,&mut txn_charlie,&mut channel_charlie,"",).unwrap();debug_to_file(&txn_charlie, &channel_charlie, "debug_charlie3")?;output::output_repository_no_pending(&mut repo_charlie,&changes,&mut txn_charlie,&mut channel_charlie,"",true,)?;let mut files_charlie = repo_charlie.list_files();files_charlie.sort();assert_eq!(files_charlie, &["file", "file3"]); - replacement in libpijul/src/tests/file_conflicts.rs at line 457
let files_alice = repo_alice.list_files();let mut files_alice = repo_alice.list_files();files_alice.sort(); - replacement in libpijul/src/tests/file_conflicts.rs at line 471
// Bob applies Alice's change// Bob applies Alice's change and Charlie's change - replacement in libpijul/src/tests/file_conflicts.rs at line 1195
// Charlie applies Alice's move and deletes.// Charlie applies Alice's move and deletes (i.e. does the same as Bob). - edit in libpijul/src/tests/file_conflicts.rs at line 1225
debug!("Charlie applies Bob's deletion"); - edit in libpijul/src/tests/file_conflicts.rs at line 1228
debug!("Charlie applies Bob's resolution"); - replacement in libpijul/src/tests/file_conflicts.rs at line 1245
assert_eq!(conflicts.len(), 2);match (&conflicts[0], &conflicts[1]) {(Conflict::ZombieFile { ref path }, Conflict::MultipleNames { .. })| (Conflict::MultipleNames { .. }, Conflict::ZombieFile { ref path }) => {assert!(path == "a/b/c/alice" || path == "a/b/c/file")}assert_eq!(conflicts.len(), 1);match conflicts[0] {Conflict::ZombieFile { ref path } => assert_eq!(path, "a/b/c/alice"), - edit in libpijul/src/tests/file_conflicts.rs at line 1252
debug!("Alice applies Charlie's deletion"); - replacement in libpijul/src/record.rs at line 262
flag: EdgeFlags::empty(),flag: EdgeFlags::BLOCK, - edit in libpijul/src/record.rs at line 572
if !moved.need_new_name {moved.resurrect.extend(moved.edges.drain(..));} - edit in libpijul/src/record.rs at line 584
- replacement in libpijul/src/record.rs at line 784
if intro.len() > 1 {if intro.len() > 1 || !moved.resurrect.is_empty() { - edit in libpijul/src/pristine/vertex.rs at line 34
}/// Is this vertex of zero length?pub fn is_empty(&self) -> bool {self.end == self.start - edit in libpijul/src/pristine/vertex.rs at line 66
/// Is this vertex of zero length?pub fn is_empty(&self) -> bool {self.end == self.start} - edit in libpijul/src/pristine/mod.rs at line 63
}}impl<T: MutTxnT> Channel<T> {pub(crate) fn touch(&mut self) {use std::time::SystemTime;if let Ok(duration) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {self.last_modified = duration.as_secs();} - edit in libpijul/src/pristine/mod.rs at line 307
}pub(crate) fn iter_alive_children<'db, 'txn: 'db, T: TxnT>(txn: &'txn T,channel: &'db Channel<T>,key: Vertex<ChangeId>,) -> AdjacentIterator<'txn, T> {iter_adjacent(txn,channel,key,EdgeFlags::empty(),EdgeFlags::alive_children(),) - edit in libpijul/src/pristine/mod.rs at line 323
pub(crate) fn iter_deleted_parents<'db, 'txn: 'db, T: TxnT>(txn: &'txn T,channel: &'db Channel<T>,key: Vertex<ChangeId>,) -> AdjacentIterator<'txn, T> {iter_adjacent(txn,channel,key,EdgeFlags::DELETED | EdgeFlags::PARENT,EdgeFlags::all(),)}pub(crate) fn iter_adj_all<'db, 'txn: 'db, T: TxnT>(txn: &'txn T,channel: &'db Channel<T>,key: Vertex<ChangeId>,) -> AdjacentIterator<'txn, T> {iter_adjacent(txn, channel, key, EdgeFlags::empty(), EdgeFlags::all())} - replacement in libpijul/src/pristine/mod.rs at line 766
for e in iter_adjacent(txn, &channel, v, EdgeFlags::empty(), EdgeFlags::all()) {for e in iter_adj_all(txn, &channel, v) { - replacement in libpijul/src/pristine/mod.rs at line 1457
for e in iter_adjacent(txn,&channel,vertex.inode_vertex(),EdgeFlags::empty(),EdgeFlags::all(),) {for e in iter_adj_all(txn, &channel, vertex.inode_vertex()) { - replacement in libpijul/src/pristine/edge.rs at line 5
/// Possible flags of edges.#[derive(Serialize, Deserialize)]pub struct EdgeFlags: u8 {const BLOCK = 1;/// A pseudo-edge, computed when applying the change to/// restore connectivity, and/or mark conflicts.const PSEUDO = 4;/// An edge encoding file system hierarchy.const FOLDER = 16;/// A "reverse" edge (all edges in the graph have a reverse edge).const PARENT = 32;/// An edge whose target (if not also `PARENT`) or/// source (if also `PARENT`) is marked as deleted.const DELETED = 128;/// Possible flags of edges.#[derive(Serialize, Deserialize)]pub struct EdgeFlags: u8 {const BLOCK = 1;/// A pseudo-edge, computed when applying the change to/// restore connectivity, and/or mark conflicts.const PSEUDO = 4;/// An edge encoding file system hierarchy.const FOLDER = 16;/// A "reverse" edge (all edges in the graph have a reverse edge).const PARENT = 32;/// An edge whose target (if not also `PARENT`) or/// source (if also `PARENT`) is marked as deleted.const DELETED = 128;} - edit in libpijul/src/pristine/edge.rs at line 21
impl EdgeFlags {#[inline]pub(crate) fn db() -> Self {Self::DELETED | Self::BLOCK}#[inline]pub(crate) fn bp() -> Self {Self::BLOCK | Self::PARENT}#[inline]pub(crate) fn pseudof() -> Self {Self::PSEUDO | Self::FOLDER}#[inline]pub(crate) fn alive_children() -> Self {Self::BLOCK | Self::PSEUDO | Self::FOLDER}#[inline]pub(crate) fn parent_folder() -> Self {Self::PARENT | Self::FOLDER}#[inline]pub(crate) fn is_deleted(&self) -> bool {self.contains(EdgeFlags::DELETED)}#[inline]pub(crate) fn is_parent(&self) -> bool {self.contains(EdgeFlags::PARENT)}#[inline]pub(crate) fn is_folder(&self) -> bool {self.contains(EdgeFlags::FOLDER)}#[inline]pub(crate) fn is_block(&self) -> bool {self.contains(EdgeFlags::BLOCK)} - replacement in libpijul/src/output/output.rs at line 98
b.sort_by(|u, v| {b.sort_unstable_by(|u, v| { - replacement in libpijul/src/missing_context.rs at line 26
match self.graphs.entry(inode) {match self.graphs.0.entry(inode) { - edit in libpijul/src/missing_context.rs at line 60
change_id: ChangeId, - edit in libpijul/src/missing_context.rs at line 64
d_is_folder: bool, - replacement in libpijul/src/missing_context.rs at line 66
let (mut alive, files) = find_alive_up(txn, channel, c)?;let mut alive = find_alive_up(txn, channel, &mut ws.files, c, change_id)?; - edit in libpijul/src/missing_context.rs at line 71
debug!("repair_missing_up_context, files = {:?}", files); - replacement in libpijul/src/missing_context.rs at line 72
if let Some((graph, vids)) = ws.graphs.get(&inode) {if let Some((graph, vids)) = ws.graphs.0.get(&inode) { - replacement in libpijul/src/missing_context.rs at line 81[5.698941]→[5.698941:699328](∅→∅),[5.699328]→[5.56974:57027](∅→∅),[5.57027]→[5.699364:699639](∅→∅),[5.699364]→[5.699364:699639](∅→∅),[5.699639]→[5.26489:26545](∅→∅),[5.26545]→[5.699655:699665](∅→∅),[5.699655]→[5.699655:699665](∅→∅),[5.699665]→[5.699665:699700](∅→∅),[5.699700]→[5.57028:57081](∅→∅),[5.57081]→[5.699736:699886](∅→∅),[5.699736]→[5.699736:699886](∅→∅),[5.699886]→[5.26546:26602](∅→∅),[5.26602]→[5.699902:699912](∅→∅),[5.699902]→[5.699902:699912](∅→∅)
for &ancestor in alive.iter() {debug!("put_graph_with_rev {:?} -> {:?}", ancestor, d);if ancestor == d {info!("repair_missing_up_context, alive: {:?} == {:?}",ancestor, d);continue;}debug!("repair_missing_up {:?} {:?}", ancestor, d);put_graph_with_rev(txn,channel,if d_is_folder {EdgeFlags::PSEUDO | EdgeFlags::FOLDER} else {EdgeFlags::PSEUDO},ancestor,d,ChangeId::ROOT,).map_err(MissingError::Txn)?;}if d_is_folder && c != d {put_graph_with_rev(txn,channel,EdgeFlags::PSEUDO | EdgeFlags::FOLDER,c,d,ChangeId::ROOT,).map_err(MissingError::Txn)?;}repair_regular_up(txn, channel, &alive, d, EdgeFlags::PSEUDO).map_err(MissingError::Txn)?; - edit in libpijul/src/missing_context.rs at line 83
repair_files_up(txn, channel, &files, ws)?; - replacement in libpijul/src/missing_context.rs at line 86
fn repair_files_up<T: MutTxnT>(fn repair_regular_up<T: MutTxnT>( - replacement in libpijul/src/missing_context.rs at line 89[5.700055]→[5.700055:700095](∅→∅),[5.700095]→[3.49:73](∅→∅),[3.73]→[5.26603:26645](∅→∅),[5.700095]→[5.26603:26645](∅→∅),[5.26645]→[5.700128:700155](∅→∅),[5.700128]→[5.700128:700155](∅→∅),[5.700155]→[5.700155:700193](∅→∅),[5.700193]→[5.57082:57132](∅→∅),[5.57132]→[5.700242:700395](∅→∅),[5.700242]→[5.700242:700395](∅→∅),[5.700395]→[5.57133:57178](∅→∅),[5.57178]→[5.700427:700557](∅→∅),[5.700427]→[5.700427:700557](∅→∅),[5.700557]→[5.26646:26694](∅→∅),[5.26694]→[3.74:105](∅→∅)
files: &[(Vertex<ChangeId>, Edge)],ws: &mut Workspace,) -> Result<(), MissingError<T::Error>> {for &(a, b) in files {let b = if a.start == a.end {find_block_end(txn, channel, b.dest)?} else {b.dest.inode_vertex()};debug!("put_graph_with_rev (files) {:?} -> {:?}", b, a);assert_ne!(a, b);put_graph_with_rev(txn,channel,EdgeFlags::FOLDER | EdgeFlags::PSEUDO,b,a,ChangeId::ROOT,).map_err(MissingError::Txn)?;ws.repaired.insert(a);alive: &HashSet<Vertex<ChangeId>>,d: Vertex<ChangeId>,flag: EdgeFlags,) -> Result<(), T::Error> {for &ancestor in alive.iter() {debug!("put_graph_with_rev {:?} -> {:?}", ancestor, d);if ancestor == d {info!("repair_missing_up_context, alive: {:?} == {:?}",ancestor, d);continue;}debug!("repair_missing_up {:?} {:?}", ancestor, d);put_graph_with_rev(txn, channel, flag, ancestor, d, ChangeId::ROOT)?; - replacement in libpijul/src/missing_context.rs at line 124
if let Some((graph, vids)) = ws.graphs.get(&inode) {if let Some((graph, vids)) = ws.graphs.0.get(&inode) { - replacement in libpijul/src/missing_context.rs at line 133
for &descendant in alive.iter() {if d == descendant {info!("repair_missing_down_context, alive: {:?} == {:?}",d, descendant);for &desc in alive.iter() {if d == desc {info!("repair_missing_down_context, alive: {:?} == {:?}", d, desc); - replacement in libpijul/src/missing_context.rs at line 138
debug!("repair_missing_down {:?} {:?}", d, descendant);put_graph_with_rev(txn,channel,EdgeFlags::PSEUDO,d,descendant,ChangeId::ROOT,).map_err(MissingError::Txn)?;debug!("repair_missing_down {:?} {:?}", d, desc);put_graph_with_rev(txn, channel, EdgeFlags::PSEUDO, d, desc, ChangeId::ROOT).map_err(MissingError::Txn)?; - replacement in libpijul/src/missing_context.rs at line 158[5.702212]→[5.57388:57622](∅→∅),[5.57622]→[5.702442:702686](∅→∅),[5.702442]→[5.702442:702686](∅→∅),[5.702686]→[5.702686:702821](∅→∅),[5.702821]→[5.702821:702861](∅→∅),[5.702861]→[5.702861:702899](∅→∅),[5.702899]→[5.57623:57712](∅→∅),[5.57712]→[5.702987:703036](∅→∅),[5.702987]→[5.702987:703036](∅→∅),[5.703036]→[5.703036:703103](∅→∅),[5.703103]→[5.703103:703217](∅→∅),[5.703217]→[5.703217:703315](∅→∅),[5.703315]→[5.703315:703347](∅→∅),[5.703347]→[5.703347:703470](∅→∅),[5.703470]→[5.703470:703471](∅→∅),[5.703471]→[5.703471:703497](∅→∅),[5.703497]→[5.703497:703811](∅→∅)
let source = internal_pos(txn, &e.from, change_id)?;let source = find_block_end(txn, &channel, source)?;let target = internal_pos(txn, &e.to.start_pos(), change_id)?;let target = find_block(txn, &channel, target)?;debug!("repair_context_nondeleted: source = {:?}, target: {:?}",source, target);// Fixing the connection from root to the source: if the source is// deleted by an unknown patch, or if the target is deleted// (necessarily by unknown patch), then `target` might be// disconnected from the alive graph, so we need to fix the context.let mut deleted_by_unknown = false;let mut target_is_folder = false;for v in iter_adjacent(txn, channel, source, EdgeFlags::empty(), EdgeFlags::all()) {if !v.flag.contains(EdgeFlags::PARENT) {target_is_folder = v.flag.contains(EdgeFlags::FOLDER);continue;}if !v.flag.contains(EdgeFlags::DELETED) {continue;}if v.introduced_by == change_id || v.dest.change.is_root() || v.introduced_by.is_root() {continue;}// This unwrap is ok, since `v` is in the channel.let intro = txn.get_external(v.introduced_by).unwrap();if known(intro) {// If a known change also delete the context, we're good.deleted_by_unknown = false;break;} else {// If an unknown change deletes the context, wait: maybe a// known change will delete it too.deleted_by_unknown = true;}if e.flag.contains(EdgeFlags::FOLDER) {return Ok(()); - replacement in libpijul/src/missing_context.rs at line 161
debug!("deleted_by_unknown {:?}", deleted_by_unknown);if deleted_by_unknown {repair_missing_up_context(txn, channel, ws, inode, source, &[target], target_is_folder)?;let source = find_block_end(txn, &channel, internal_pos(txn, &e.from, change_id)?)?;let target = find_block(txn,&channel,internal_pos(txn, &e.to.start_pos(), change_id)?,)?;if deleted_by_unknown(txn, channel, source, change_id, &mut known) {repair_missing_up_context(txn, channel, ws, change_id, inode, source, &[target])?; - edit in libpijul/src/missing_context.rs at line 170
reconnect_target_up(txn, channel, ws, inode, target, change_id)?;reconnect_target_down(txn, channel, ws, inode, target, change_id, &mut known)} - replacement in libpijul/src/missing_context.rs at line 175
// Now, maybe ~source~ was deleted by known changes, but// accessibility to ~target~ was provided by other edges that got// deleted by unknown changes.fn reconnect_target_up<T: MutTxnT>(txn: &mut T,channel: &mut Channel<T>,ws: &mut Workspace,inode: Position<Option<Hash>>,target: Vertex<ChangeId>,change_id: ChangeId,) -> Result<(), MissingError<T::Error>> { - replacement in libpijul/src/missing_context.rs at line 184
for v in iter_adjacent(txn, channel, target, EdgeFlags::empty(), EdgeFlags::all()) {if !v.flag.contains(EdgeFlags::PARENT) || !v.flag.contains(EdgeFlags::DELETED) {for v in iter_deleted_parents(txn, channel, target) {if v.dest.change.is_root() || v.introduced_by.is_root() { - replacement in libpijul/src/missing_context.rs at line 188
if v.introduced_by == change_id || v.dest.change.is_root() || v.introduced_by.is_root() {continue;if v.introduced_by == change_id {unknown.clear();break; - replacement in libpijul/src/missing_context.rs at line 193
// since no change can create a conflict.// since no change can create a conflict with itself. - replacement in libpijul/src/missing_context.rs at line 197
repair_missing_up_context(txn, channel, ws, inode, up, &[target], target_is_folder)?;repair_missing_up_context(txn, channel, ws, change_id, inode, up, &[target])?; - edit in libpijul/src/missing_context.rs at line 199
Ok(())} - edit in libpijul/src/missing_context.rs at line 202
fn reconnect_target_down<T: MutTxnT, K>(txn: &mut T,channel: &mut Channel<T>,ws: &mut Workspace,inode: Position<Option<Hash>>,target: Vertex<ChangeId>,change_id: ChangeId,known: &mut K,) -> Result<(), MissingError<T::Error>>whereK: FnMut(Hash) -> bool,{ - replacement in libpijul/src/missing_context.rs at line 216
for v in iter_adjacent(txn, channel, target, EdgeFlags::empty(), EdgeFlags::all()) {for v in iter_adj_all(txn, channel, target) { - edit in libpijul/src/missing_context.rs at line 237
}fn deleted_by_unknown<T: TxnT, K>(txn: &T,channel: &Channel<T>,source: Vertex<ChangeId>,change_id: ChangeId,known: &mut K,) -> boolwhereK: FnMut(Hash) -> bool,{let mut deleted_by_unknown = false;for v in iter_deleted_parents(txn, channel, source) {if v.dest.change.is_root() || v.introduced_by.is_root() {continue;}if v.introduced_by == change_id || known(txn.get_external(v.introduced_by).unwrap()) {// If a known change also delete the context, we're good.return false;} else {// If an unknown change deletes the context, wait: maybe a// known change will delete it too.deleted_by_unknown = true;}}deleted_by_unknown - edit in libpijul/src/missing_context.rs at line 278
if e.flag.contains(EdgeFlags::FOLDER) {return Ok(());} - edit in libpijul/src/missing_context.rs at line 283
let end_pos = internal_pos(txn, &e.to.end_pos(), change_id)?; - replacement in libpijul/src/missing_context.rs at line 286
if dest_vertex.end < end_pos.pos {if dest_vertex.end < e.to.end { - replacement in libpijul/src/missing_context.rs at line 307
pub(crate) graphs:HashMap<Position<Option<Hash>>, (Graph, HashMap<Vertex<ChangeId>, crate::alive::VertexId>)>,pub(crate) graphs: Graphs, - edit in libpijul/src/missing_context.rs at line 309
pub(crate) files: HashSet<Vertex<ChangeId>>, - edit in libpijul/src/missing_context.rs at line 312
#[derive(Debug, Default)]pub(crate) struct Graphs(pub HashMap<Position<Option<Hash>>, (Graph, HashMap<Vertex<ChangeId>, crate::alive::VertexId>)>,);impl Graphs {pub(crate) fn get(&self,inode: Position<Option<Hash>>,) -> Result<&(Graph, HashMap<Vertex<ChangeId>, VertexId>), InconsistentChange> {if let Some(n) = self.0.get(&inode) {Ok(n)} else {Err(InconsistentChange {})}}pub fn split(&mut self,inode: Position<Option<Hash>>,vertex: Vertex<ChangeId>,mid: ChangePosition,) {if let Some((_, vids)) = self.0.get_mut(&inode) {if let Some(vid) = vids.remove(&vertex) {vids.insert(Vertex { end: mid, ..vertex }, vid);vids.insert(Vertex {start: mid,..vertex},vid,);}}}} - replacement in libpijul/src/missing_context.rs at line 356
self.graphs.clear();self.graphs.0.clear(); - replacement in libpijul/src/missing_context.rs at line 365
assert!(self.graphs.is_empty());assert!(self.graphs.0.is_empty()); - replacement in libpijul/src/missing_context.rs at line 381
for v in iter_adjacent(txn,channel,dest_vertex,EdgeFlags::empty(),EdgeFlags::all() - EdgeFlags::DELETED - EdgeFlags::PARENT,) {for v in iter_alive_children(txn, channel, dest_vertex) { - edit in libpijul/src/missing_context.rs at line 393
// If `dest_vertex` is not also deleted by the same change// that introduced unknown edge `v`, then `v` is really// a missing context. - edit in libpijul/src/missing_context.rs at line 402
// This unwrap is ok, since `v` is in the channel. - replacement in libpijul/src/missing_context.rs at line 425
if unknown.is_empty() {trace!("unknown = []")} else {debug!("dest_vertex = {:?}, unknown = {:?}", dest_vertex, unknown)}debug!("dest_vertex = {:?}, unknown = {:?}", dest_vertex, unknown); - replacement in libpijul/src/missing_context.rs at line 428[5.58613]→[5.710141:710193](∅→∅),[5.710141]→[5.710141:710193](∅→∅),[5.710260]→[5.710260:710324](∅→∅),[5.710324]→[5.58614:58667](∅→∅),[5.58667]→[5.710360:710515](∅→∅),[5.710360]→[5.710360:710515](∅→∅),[5.710515]→[5.26924:26938](∅→∅)
if !edge.flag.contains(EdgeFlags::FOLDER) {debug!("dest_vertex {:?}, p {:?}", dest_vertex, p);put_graph_with_rev(txn,channel,EdgeFlags::DELETED | EdgeFlags::BLOCK,dest_vertex,p,change_id,)assert!(!edge.flag.contains(EdgeFlags::FOLDER));debug!("dest_vertex {:?}, p {:?}", dest_vertex, p);put_graph_with_rev(txn, channel, EdgeFlags::db(), dest_vertex, p, change_id) - replacement in libpijul/src/missing_context.rs at line 432[5.26980]→[5.710531:710558](∅→∅),[5.710531]→[5.710531:710558](∅→∅),[5.710558]→[5.58668:58738](∅→∅),[5.58738]→[5.710627:710733](∅→∅),[5.710627]→[5.710627:710733](∅→∅),[5.710733]→[5.58739:58808](∅→∅),[5.58808]→[5.710777:710962](∅→∅),[5.710777]→[5.710777:710962](∅→∅),[5.710962]→[5.26981:27003](∅→∅)
let mut u = p;while let Ok(v) = find_block(txn, channel, u.end_pos()) {if u != v {debug!("repair_children_of_deleted: {:?} -> {:?}", u, v);put_graph_with_rev(txn,channel,EdgeFlags::DELETED | EdgeFlags::BLOCK,u,v,change_id,)let mut u = p;while let Ok(v) = find_block(txn, channel, u.end_pos()) {if u != v {debug!("repair_children_of_deleted: {:?} -> {:?}", u, v);put_graph_with_rev(txn, channel, EdgeFlags::db(), u, v, change_id) - replacement in libpijul/src/missing_context.rs at line 438
u = v} else {break;}u = v} else {break; - replacement in libpijul/src/missing_context.rs at line 443[5.711169]→[5.58809:58889](∅→∅),[5.58889]→[5.711248:711317](∅→∅),[5.711248]→[5.711248:711317](∅→∅),[5.711317]→[5.711317:711414](∅→∅)
if is_alive(txn, channel, p) || edge.flag.contains(EdgeFlags::FOLDER) {let p_is_folder = edge.flag.contains(EdgeFlags::FOLDER);repair_missing_up_context(txn, channel, ws, inode, dest_vertex, &[p], p_is_folder)?;if is_alive(txn, channel, p) {repair_missing_up_context(txn, channel, ws, change_id, inode, dest_vertex, &[p])?; - replacement in libpijul/src/missing_context.rs at line 447
repair_missing_up_context(txn, channel, ws, inode, dest_vertex, &alive, false)?;repair_missing_up_context(txn, channel, ws, change_id, inode, dest_vertex, &alive)?; - replacement in libpijul/src/missing_context.rs at line 462
for (dest_vertex, e) in ws.pseudo.drain(..) {for (dest_vertex, mut e) in ws.pseudo.drain(..) { - replacement in libpijul/src/missing_context.rs at line 469[5.59118]→[5.59118:59187](∅→∅),[5.59187]→[5.712296:712486](∅→∅),[5.712296]→[5.712296:712486](∅→∅),[5.712486]→[5.27097:27169](∅→∅)
del_graph_with_rev(txn,channel,e.flag - EdgeFlags::PARENT,p,dest_vertex,e.introduced_by,).map_err(MissingError::Txn)?;e.flag -= EdgeFlags::PARENT;del_graph_with_rev(txn, channel, e.flag, p, dest_vertex, e.introduced_by).map_err(MissingError::Txn)?; - replacement in libpijul/src/find_alive.rs at line 23
for v in iter_adjacent(txn, &channel, vertex, EdgeFlags::empty(), EdgeFlags::all()) {for v in iter_adj_all(txn, &channel, vertex) { - edit in libpijul/src/find_alive.rs at line 50
files: &mut HashSet<Vertex<ChangeId>>, - replacement in libpijul/src/find_alive.rs at line 52
) -> Result<(HashSet<Vertex<ChangeId>>, Vec<(Vertex<ChangeId>, Edge)>), BlockError> {change: ChangeId,) -> Result<HashSet<Vertex<ChangeId>>, BlockError> { - edit in libpijul/src/find_alive.rs at line 55
let mut files = Vec::new(); - replacement in libpijul/src/find_alive.rs at line 71
let mut next_file = None;for v in iter_adjacent(txn, &channel, vertex, EdgeFlags::PARENT, EdgeFlags::all()) {let mut is_file = false;let mut it = iter_adj_all(txn, &channel, vertex);while let Some(v) = it.next() { - replacement in libpijul/src/find_alive.rs at line 75
if !v.flag.contains(EdgeFlags::PARENT) || v.flag.contains(EdgeFlags::PSEUDO) {if !v.flag.is_parent() {is_file |= !v.flag.is_folder(); - replacement in libpijul/src/find_alive.rs at line 79[5.766481]→[5.766481:766828](∅→∅),[5.766828]→[5.5337:5422](∅→∅),[5.5422]→[5.64922:65388](∅→∅),[5.64922]→[5.64922:65388](∅→∅),[5.65388]→[5.5423:5472](∅→∅)
if !v.flag.contains(EdgeFlags::DELETED) {if v.flag.contains(EdgeFlags::FOLDER) {// check whether `vertex` is a "file" inode,// i.e. if it has non-folder children. We're never// in the case of an empty file if we call this// function.if next_file.is_none()&& iter_adjacent(txn,&channel,vertex,EdgeFlags::empty(),EdgeFlags::all(),).any(|e| {e.flag.contains(EdgeFlags::BLOCK)&& !e.flag.contains(EdgeFlags::PARENT)&& !e.flag.contains(EdgeFlags::FOLDER)}){if v.flag & EdgeFlags::pseudof() == EdgeFlags::PSEUDO {continue;}if !v.flag.is_deleted() {if v.flag.is_folder() {is_file |= it.any(|e| !e.flag.intersects(EdgeFlags::parent_folder()));if is_file { - edit in libpijul/src/find_alive.rs at line 87
files.insert(vertex); - replacement in libpijul/src/find_alive.rs at line 89
next_file = None;break; - edit in libpijul/src/find_alive.rs at line 92
if v.introduced_by != change {stack.truncate(elt_index);break;} - edit in libpijul/src/find_alive.rs at line 97
stack.truncate(elt_index);break; - replacement in libpijul/src/find_alive.rs at line 98[5.767610]→[5.767610:767662](∅→∅),[5.767662]→[5.767662:768099](∅→∅),[5.768099]→[5.768099:768226](∅→∅),[5.768226]→[5.65418:65516](∅→∅),[5.65516]→[5.768348:768567](∅→∅),[5.768348]→[5.768348:768567](∅→∅),[5.768567]→[5.768567:768635](∅→∅)
if v.flag.contains(EdgeFlags::FOLDER) {let v_age = txn.get_changeset(&channel.changes, v.introduced_by, None).unwrap();if let Some((ref mut file, ref mut age)) = next_file {if v_age > *age {*age = v_age;*file = (vertex, v)}} else {next_file = Some(((vertex, v), v_age));// If `vertex` is a "file" inode (as opposed to a// "folder" inode), mark it "alive".if iter_adjacent(txn, &channel, vertex, EdgeFlags::empty(), EdgeFlags::all()).any(|e| {!e.flag.contains(EdgeFlags::PARENT)&& !e.flag.contains(EdgeFlags::FOLDER)}){alive.insert(vertex);}if v.flag.is_folder() {if is_file {alive.insert(vertex);files.insert(vertex); - edit in libpijul/src/find_alive.rs at line 103
break; - edit in libpijul/src/find_alive.rs at line 107
}if let Some((file, _)) = next_file {files.push(file);stack.push(file.1) - edit in libpijul/src/find_alive.rs at line 108
debug!("is_file = {:?}", is_file); - replacement in libpijul/src/find_alive.rs at line 110
Ok((alive, files))Ok(alive) - replacement in libpijul/src/diff/delete.rs at line 176
flag: previous | EdgeFlags::BLOCK | EdgeFlags::DELETED,flag: previous | EdgeFlags::DELETED, - edit in libpijul/src/change.rs at line 84
}impl<T: Clone> NewEdge<T> {pub(crate) fn reverse(&self, introduced_by: T) -> Self {NewEdge {previous: self.flag,flag: self.previous,from: self.from.clone(),to: self.to.clone(),introduced_by,}} - replacement in libpijul/src/change.rs at line 285
for edge in iter_adjacent(txn, channel, from, EdgeFlags::empty(), EdgeFlags::all()) {for edge in iter_adj_all(txn, channel, from) { - replacement in libpijul/src/change.rs at line 317
for edge in iter_adjacent(txn, channel, to, EdgeFlags::empty(), EdgeFlags::all()) {for edge in iter_adj_all(txn, channel, to) { - edit in libpijul/src/change/text_changes.rs at line 783
v.flag = EdgeFlags::BLOCK; - replacement in libpijul/src/apply.rs at line 2
use crate::change::{Atom, Change, NewEdge, NewVertex};use crate::change::{Atom, Change, EdgeMap, NewEdge, NewVertex}; - edit in libpijul/src/apply.rs at line 35
impl<E: std::error::Error> LocalApplyError<E> {const INCONSISTENT: Self =LocalApplyError::InconsistentChange(crate::pristine::InconsistentChange {});} - replacement in libpijul/src/apply.rs at line 219
)?)?; - replacement in libpijul/src/apply.rs at line 252
clean_obsolete_pseudo_edges(txn, channel, ws)?;clean_obsolete_pseudo_edges(txn, channel, ws, change_id)?; - replacement in libpijul/src/apply.rs at line 256
repair_cyclic_paths(txn, channel, ws, change_id, change)?;repair_cyclic_paths(txn, channel, ws)?; - replacement in libpijul/src/apply.rs at line 258
if let Ok(duration) =std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH){channel.last_modified = duration.as_secs();}channel.touch(); - replacement in libpijul/src/apply.rs at line 382
put_up_context(txn, channel, ch, n.inode, ws, up)?;if put_up_context(txn, channel, ch, ws, up)? && n.flag.contains(EdgeFlags::FOLDER) {return Err(LocalApplyError::INCONSISTENT);} - replacement in libpijul/src/apply.rs at line 388
put_down_context(txn, channel, ch, n.inode, ws, down)?;if down.change == change {return Err((InconsistentChange {}).into());}if put_down_context(txn, channel, ch, ws, down)? && !n.flag.contains(EdgeFlags::FOLDER) {return Err(LocalApplyError::INCONSISTENT);} - edit in libpijul/src/apply.rs at line 397
let up_flag = n.flag | EdgeFlags::BLOCK | EdgeFlags::DELETED; - replacement in libpijul/src/apply.rs at line 401
for (change, _) in ws.deleted_by.iter() {let flag = n.flag | EdgeFlags::BLOCK | EdgeFlags::DELETED;put_graph_with_rev(txn, channel, flag, up, vertex, *change)for change in ws.deleted_by.iter() {put_graph_with_rev(txn, channel, up_flag, up, vertex, *change) - replacement in libpijul/src/apply.rs at line 406[5.956727]→[5.67624:67684](∅→∅),[5.67684]→[5.965:1046](∅→∅),[5.1046]→[5.250:354](∅→∅),[5.250]→[5.250:354](∅→∅),[5.354]→[5.97017:97116](∅→∅)
debug!("put_graph_with_rev {:?} {:?}", up, vertex);let flag = if n.flag.contains(EdgeFlags::FOLDER) || !vertex.is_empty() {n.flag | EdgeFlags::BLOCK} else {n.flag - EdgeFlags::BLOCK};put_graph_with_rev(txn, channel, flag, up, vertex, change).map_err(LocalApplyError::Txn)?;put_graph_with_rev(txn, channel, n.flag | EdgeFlags::BLOCK, up, vertex, change).map_err(LocalApplyError::Txn)?; - edit in libpijul/src/apply.rs at line 410
let mut down_flag = n.flag;if !n.flag.is_folder() {down_flag -= EdgeFlags::BLOCK} - replacement in libpijul/src/apply.rs at line 416
if n.flag.contains(EdgeFlags::FOLDER) {put_graph_with_rev(txn,channel,n.flag | EdgeFlags::BLOCK,vertex,down,change,)put_graph_with_rev(txn, channel, down_flag, vertex, down, change) - replacement in libpijul/src/apply.rs at line 418[5.68075]→[5.957404:957421](∅→∅),[5.97176]→[5.957404:957421](∅→∅),[5.957404]→[5.957404:957421](∅→∅),[5.957421]→[5.68076:68267](∅→∅),[5.68267]→[5.97177:97191](∅→∅),[5.97191]→[5.97191:97236](∅→∅)
} else {put_graph_with_rev(txn,channel,n.flag - EdgeFlags::BLOCK,vertex,down,change,).map_err(LocalApplyError::Txn)?;if n.flag.is_folder() {ws.missing_context.files.insert(down); - edit in libpijul/src/apply.rs at line 430
inode: Position<Option<Hash>>, - replacement in libpijul/src/apply.rs at line 432
) -> Result<(), LocalApplyError<T::Error>> {) -> Result<bool, LocalApplyError<T::Error>> { - replacement in libpijul/src/apply.rs at line 442
if let Some((_, vids)) = ws.missing_context.graphs.get_mut(&inode) {if let Some(vid) = vids.remove(&k) {vids.insert(Vertex { end: up.pos, ..k }, vid);vids.insert(Vertex { start: up.pos, ..k }, vid);}}// The missing context "graphs" are only used at the// DELETION stage, check that:assert!(ws.missing_context.graphs.0.is_empty()); - edit in libpijul/src/apply.rs at line 456
let mut is_non_folder = false; - edit in libpijul/src/apply.rs at line 458
is_non_folder |= parent.flag & (EdgeFlags::PARENT | EdgeFlags::FOLDER) == EdgeFlags::PARENT; - edit in libpijul/src/apply.rs at line 463
// This unwrap is ok: `parent` is in the channel. - replacement in libpijul/src/apply.rs at line 465
ws.deleted_by.insert((parent.introduced_by, parent.flag - EdgeFlags::PARENT));ws.deleted_by.insert(parent.introduced_by); - edit in libpijul/src/apply.rs at line 467
} else if parent.flag.contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {// This vertex is alive, even if its parent is in conflict.debug!("up_context: alive {:?} {:?}", up_vertex, parent);break; - replacement in libpijul/src/apply.rs at line 470
Ok(())Ok(is_non_folder) - edit in libpijul/src/apply.rs at line 477
inode: Position<Option<Hash>>, - replacement in libpijul/src/apply.rs at line 479
) -> Result<Vertex<ChangeId>, LocalApplyError<T::Error>> {) -> Result<bool, LocalApplyError<T::Error>> { - replacement in libpijul/src/apply.rs at line 484
if let Some((_, vids)) = ws.missing_context.graphs.get_mut(&inode) {if let Some(vid) = vids.remove(&k) {vids.insert(Vertex { end: down.pos, ..k }, vid);vids.insert(Vertex {start: down.pos,..k},vid,);}}// The missing context "graphs" are only used at the// DELETION stage, check that:assert!(ws.missing_context.graphs.0.is_empty()); - edit in libpijul/src/apply.rs at line 498
let mut is_folder = false; - edit in libpijul/src/apply.rs at line 500
is_folder |= parent.flag.contains(EdgeFlags::PARENT | EdgeFlags::FOLDER); - edit in libpijul/src/apply.rs at line 503
// This unwrap is ok: `parent` is in the channel. - replacement in libpijul/src/apply.rs at line 505
ws.deleted_by.insert((parent.introduced_by, parent.flag - EdgeFlags::PARENT));ws.deleted_by.insert(parent.introduced_by); - edit in libpijul/src/apply.rs at line 507
} else {// This parent is alivebreak; - replacement in libpijul/src/apply.rs at line 511
Ok(down_vertex)Ok(is_folder) - replacement in libpijul/src/apply.rs at line 519
deleted_by: HashSet<(ChangeId, EdgeFlags)>,deleted_by: HashSet<ChangeId>, - edit in libpijul/src/apply.rs at line 566
debug!("put_newedge {:?} {:?}", n, change); - edit in libpijul/src/apply.rs at line 572
if (n.previous.is_block() != n.flag.is_block())|| (n.previous.is_folder() != n.flag.is_folder()){return Err(LocalApplyError::INCONSISTENT.into());} - replacement in libpijul/src/apply.rs at line 578
assert!(ws.children.is_empty());assert!(ws.parents.is_empty());debug!("put_newedge {:?} {:?}", n, change);debug_assert!(ws.children.is_empty());debug_assert!(ws.parents.is_empty()); - replacement in libpijul/src/apply.rs at line 583
return Err(LocalApplyError::InconsistentChange(crate::pristine::InconsistentChange {}).into(),);return Err(LocalApplyError::INCONSISTENT.into()); - edit in libpijul/src/apply.rs at line 589
if n.flag.contains(EdgeFlags::FOLDER) {ws.missing_context.files.insert(target);} - replacement in libpijul/src/apply.rs at line 596
if let Some((_, vids)) = ws.missing_context.graphs.get_mut(&inode) {if let Some(vid) = vids.remove(&target) {vids.insert(Vertex {end: n.to.end,..target},vid,);vids.insert(Vertex {start: n.to.end,..target},vid,);}}ws.missing_context.graphs.split(inode, target, n.to.end); - edit in libpijul/src/apply.rs at line 607
ws.parents.clear(); - replacement in libpijul/src/apply.rs at line 610
debug!("deleting {:?} {:?}", n.previous, n.flag);let del = del_graph_with_rev(txn, channel, n.previous, source, target, n_introduced_by)del_graph_with_rev(txn, channel, n.previous, source, target, n_introduced_by) - edit in libpijul/src/apply.rs at line 612[5.69899]→[5.965198:965236](∅→∅),[5.98184]→[5.965198:965236](∅→∅),[5.965198]→[5.965198:965236](∅→∅),[5.965631]→[5.965631:965742](∅→∅)
debug!("deleted: {:?}", del);debug!("put_graph {:?} {:?}, intro {:?}", source, target, change);assert_ne!(source, target); - replacement in libpijul/src/apply.rs at line 618
assert_eq!(target.end, n.to.end);debug!("{:?} {:?}", target, n.to);debug_assert_eq!(target.end, n.to.end); - replacement in libpijul/src/apply.rs at line 644
if let Some((_, vids)) = ws.missing_context.graphs.get_mut(&inode) {if let Some(vid) = vids.remove(&source) {vids.insert(Vertex {end: from.pos,..source},vid,);vids.insert(Vertex {start: from.pos,..source},vid,);}}ws.missing_context.graphs.split(inode, source, from.pos); - replacement in libpijul/src/apply.rs at line 661
debug!("find_target_vertex");debug!("find_target_vertex, to = {:?}", to); - replacement in libpijul/src/apply.rs at line 666
if let Some((_, vids)) = ws.missing_context.graphs.get_mut(&inode) {if let Some(vid) = vids.remove(&target) {vids.insert(Vertex {end: to.start,..target},vid,);vids.insert(Vertex {start: to.start,..target},vid,);}}ws.missing_context.graphs.split(inode, target, to.start); - replacement in libpijul/src/apply.rs at line 713
debug!("reconnect: parents.len() = {:?} to children.len() = {:?}",ws.parents.len(),ws.children.len());debug!("reconnect: parents = {:#?} to children = {:#?}",ws.parents, ws.children);if ws.parents.is_empty() {ws.children.clear();if ws.parents.is_empty() || ws.children.is_empty() { - replacement in libpijul/src/apply.rs at line 716
if ws.children.is_empty() {ws.parents.clear();return Ok(());}let (graph, vids) = ws.missing_context.graphs.get(inode)?; - edit in libpijul/src/apply.rs at line 719[5.970271]→[5.970271:970375](∅→∅),[5.970375]→[5.98789:98841](∅→∅),[5.98841]→[5.970436:970443](∅→∅),[5.970436]→[5.970436:970443](∅→∅)
let (graph, vids) = if let Some(n) = ws.missing_context.graphs.get(&inode) {n} else {return Err((InconsistentChange {}).into());}; - edit in libpijul/src/apply.rs at line 731
debug!("reconnect (nonredundant) {:?} to {:?}",ws.parents, ws.children); - replacement in libpijul/src/apply.rs at line 732
for p in ws.parents.drain() {for c in ws.children.iter() {if p != *c && is_alive(txn, channel, p) && is_alive(txn, channel, *c) {put_graph_with_rev(txn, channel, EdgeFlags::PSEUDO, p, *c, ChangeId::ROOT)for &p in ws.parents.iter() {debug_assert!(is_alive(txn, channel, p));for &c in ws.children.iter() {if p != c {debug_assert!(is_alive(txn, channel, c));put_graph_with_rev(txn, channel, EdgeFlags::PSEUDO, p, c, ChangeId::ROOT) - edit in libpijul/src/apply.rs at line 749
change_id: ChangeId, - edit in libpijul/src/apply.rs at line 751
debug!("pseudo = {:#?}", ws.pseudo); - replacement in libpijul/src/apply.rs at line 752
// Reorder next_vertex and p.dest to reformulate this as an "a -> b" edge.debug!("{:?} {:?}", next_vertex, p);let (a, b) = if p.flag.contains(EdgeFlags::PARENT) {let (a, b) = if p.flag.is_parent() { - edit in libpijul/src/apply.rs at line 763
- replacement in libpijul/src/apply.rs at line 765
debug!("{:?} {:?}", a_is_alive, b_is_alive);if a_is_alive && b_is_alive {continue;}del_graph_with_rev(txn,channel,p.flag - EdgeFlags::PARENT,a,b,p.introduced_by,).map_err(LocalApplyError::Txn)?; - replacement in libpijul/src/apply.rs at line 778[5.972877]→[5.972877:972961](∅→∅),[5.972961]→[5.70994:71058](∅→∅),[5.71058]→[5.973004:973164](∅→∅),[5.973004]→[5.973004:973164](∅→∅),[5.973164]→[5.99033:99117](∅→∅),[5.99117]→[5.973185:973501](∅→∅),[5.973185]→[5.973185:973501](∅→∅),[5.973501]→[5.99118:99201](∅→∅),[5.99201]→[5.973524:973638](∅→∅),[5.973524]→[5.973524:973638](∅→∅),[5.973638]→[5.71059:71094](∅→∅)
if !b_is_alive {debug!("deleting {:?} -> {:?}", a, b);if del_graph_with_rev(txn,channel,p.flag - EdgeFlags::PARENT,a,b,p.introduced_by,).map_err(LocalApplyError::Txn)?{// repair down context.crate::missing_context::repair_missing_down_context(txn,channel,&mut ws.missing_context,inode,b,&[a],).map_err(LocalApplyError::from_missing)?}}} else if b_is_alive {debug!("deleting {:?} -> {:?}", a, b);if del_graph_with_rev(debug_assert!(!b_is_alive);crate::missing_context::repair_missing_down_context( - replacement in libpijul/src/apply.rs at line 782
p.flag - EdgeFlags::PARENT,a,&mut ws.missing_context,inode, - replacement in libpijul/src/apply.rs at line 785
p.introduced_by,&[a], - replacement in libpijul/src/apply.rs at line 787[5.99216]→[5.99216:99260](∅→∅),[5.99260]→[5.99260:99274](∅→∅),[5.71272]→[5.973739:973844](∅→∅),[5.99274]→[5.973739:973844](∅→∅),[5.973739]→[5.973739:973844](∅→∅),[5.973844]→[5.973844:973970](∅→∅),[5.973970]→[5.973970:974075](∅→∅),[5.974075]→[5.99275:99350](∅→∅),[5.99350]→[5.974094:974108](∅→∅),[5.974094]→[5.974094:974108](∅→∅),[5.974108]→[5.974108:974125](∅→∅),[5.974125]→[5.71273:71305](∅→∅)
.map_err(LocalApplyError::Txn)?{// repair up context.crate::missing_context::repair_missing_up_context(txn,channel,&mut ws.missing_context,inode,a,&[b],p.flag.contains(EdgeFlags::FOLDER),).map_err(LocalApplyError::from_missing)?}} else {del_graph_with_rev(.map_err(LocalApplyError::from_missing)?} else if !p.flag.is_folder() {crate::missing_context::repair_missing_up_context( - replacement in libpijul/src/apply.rs at line 792
p.flag - EdgeFlags::PARENT,&mut ws.missing_context,change_id,inode, - replacement in libpijul/src/apply.rs at line 796
b,p.introduced_by,&[b], - replacement in libpijul/src/apply.rs at line 798
.map_err(LocalApplyError::Txn)?;.map_err(LocalApplyError::from_missing)? - replacement in libpijul/src/apply.rs at line 816
Atom::NewVertex(ref n) => {Atom::NewVertex(ref n) if !n.flag.is_folder() => { - replacement in libpijul/src/apply.rs at line 822[5.974920]→[5.974920:975038](∅→∅),[5.975038]→[5.71483:71579](∅→∅),[5.71579]→[5.975132:975133](∅→∅),[5.975132]→[5.975132:975133](∅→∅),[5.975133]→[5.71580:71633](∅→∅),[5.71633]→[5.975185:975617](∅→∅),[5.975185]→[5.975185:975617](∅→∅),[5.975617]→[5.99601:99692](∅→∅),[5.99692]→[5.975644:975797](∅→∅),[5.975644]→[5.975644:975797](∅→∅),[5.975797]→[5.71634:72020](∅→∅),[5.72020]→[5.1712:1776](∅→∅),[5.1776]→[5.72118:72153](∅→∅),[5.72118]→[5.72118:72153](∅→∅),[5.72153]→[5.976346:976780](∅→∅),[5.976346]→[5.976346:976780](∅→∅),[5.976780]→[5.99693:99792](∅→∅),[5.99792]→[5.976811:976945](∅→∅),[5.976811]→[5.976811:976945](∅→∅)
debug!("repairing missing context for {:?}", vertex);for up in n.up_context.iter() {let up = find_block_end(txn, channel, internal_pos(txn, &up, change_id)?)?;if !is_alive(txn, channel, up) {debug!("repairing missing up context {:?} {:?}", up, vertex);repair_missing_up_context(txn,channel,&mut ws.missing_context,n.inode,up,&[vertex],n.flag.contains(EdgeFlags::FOLDER),).map_err(LocalApplyError::from_missing)?}}if !n.flag.contains(EdgeFlags::FOLDER) {for down in n.down_context.iter() {let down = find_block(txn, channel, internal_pos(txn, &down, change_id)?)?;if iter_adjacent(txn,channel,down,EdgeFlags::PARENT,EdgeFlags::all() - EdgeFlags::DELETED,).find(|e| e.introduced_by != change_id).is_none(){debug!("repairing missing down context {:?} {:?}", down, vertex);repair_missing_down_context(txn,channel,&mut ws.missing_context,n.inode,down,&[vertex],).map_err(LocalApplyError::from_missing)?}}}debug!("done repairing contexts for {:?}", vertex);repair_new_vertex_context_up(txn, channel, ws, change_id, n, vertex)?;repair_new_vertex_context_down(txn, channel, ws, change_id, n, vertex)?; - edit in libpijul/src/apply.rs at line 825
Atom::NewVertex(_) => {} - replacement in libpijul/src/apply.rs at line 827[5.976997]→[5.976997:977570](∅→∅),[5.977570]→[5.99793:99884](∅→∅),[5.99884]→[5.977597:977637](∅→∅),[5.977597]→[5.977597:977637](∅→∅)
for e in n.edges.iter() {assert!(!e.flag.contains(EdgeFlags::PARENT));if !e.flag.contains(EdgeFlags::DELETED) {trace!("repairing context nondeleted {:?}", e);repair_context_nondeleted(txn,channel,&mut ws.missing_context,n.inode,change_id,|h| change.knows(&h),e,).map_err(LocalApplyError::from_missing)?}}repair_edge_context(txn, channel, ws, change_id, change, n)?; - edit in libpijul/src/apply.rs at line 831[5.977667]→[5.977667:977730](∅→∅),[5.977730]→[5.7144:7639](∅→∅),[5.7639]→[5.99885:99968](∅→∅),[5.7662]→[5.978338:978356](∅→∅),[5.99968]→[5.978338:978356](∅→∅),[5.978338]→[5.978338:978356](∅→∅),[5.978356]→[5.978356:978370](∅→∅),[5.978390]→[5.978390:978406](∅→∅)
for atom in change.changes.iter().flat_map(|r| r.iter()) {if let Atom::EdgeMap(ref n) = atom {for e in &n.edges {if e.flag.contains(EdgeFlags::DELETED) {trace!("repairing context deleted {:?}", e);repair_context_deleted(txn,channel,&mut ws.missing_context,n.inode,change_id,|h| change.knows(&h),e,).map_err(LocalApplyError::from_missing)?}}}} - replacement in libpijul/src/apply.rs at line 837
fn repair_cyclic_paths<T: MutTxnT>(fn repair_new_vertex_context_up<T: MutTxnT>(txn: &mut T,channel: &mut Channel<T>,ws: &mut Workspace,change_id: ChangeId,n: &NewVertex<Option<Hash>>,vertex: Vertex<ChangeId>,) -> Result<(), LocalApplyError<T::Error>> {for up in n.up_context.iter() {let up = find_block_end(txn, channel, internal_pos(txn, &up, change_id)?)?;if !is_alive(txn, channel, up) {debug!("repairing missing up context {:?} {:?}", up, vertex);repair_missing_up_context(txn,channel,&mut ws.missing_context,change_id,n.inode,up,&[vertex],).map_err(LocalApplyError::from_missing)?}}Ok(())}fn repair_new_vertex_context_down<T: MutTxnT>(txn: &mut T,channel: &mut Channel<T>,ws: &mut Workspace,change_id: ChangeId,n: &NewVertex<Option<Hash>>,vertex: Vertex<ChangeId>,) -> Result<(), LocalApplyError<T::Error>> {debug!("repairing missing context for {:?}", vertex);if n.flag.contains(EdgeFlags::FOLDER) {return Ok(());}for down in n.down_context.iter() {let down = find_block(txn, channel, internal_pos(txn, &down, change_id)?)?;if iter_adjacent(txn,channel,down,EdgeFlags::PARENT,EdgeFlags::all() - EdgeFlags::DELETED,).any(|e| e.introduced_by != change_id){continue;}debug!("repairing missing down context {:?} {:?}", down, vertex);repair_missing_down_context(txn,channel,&mut ws.missing_context,n.inode,down,&[vertex],).map_err(LocalApplyError::from_missing)?}Ok(())}fn repair_edge_context<T: MutTxnT>( - edit in libpijul/src/apply.rs at line 909
n: &EdgeMap<Option<Hash>>,) -> Result<(), LocalApplyError<T::Error>> {for e in n.edges.iter() {assert!(!e.flag.contains(EdgeFlags::PARENT));if e.flag.contains(EdgeFlags::DELETED) {trace!("repairing context deleted {:?}", e);repair_context_deleted(txn,channel,&mut ws.missing_context,n.inode,change_id,|h| change.knows(&h),e,).map_err(LocalApplyError::from_missing)?} else {trace!("repairing context nondeleted {:?}", e);repair_context_nondeleted(txn,channel,&mut ws.missing_context,n.inode,change_id,|h| change.knows(&h),e,).map_err(LocalApplyError::from_missing)?}}Ok(())}pub(crate) fn repair_cyclic_paths<T: MutTxnT>(txn: &mut T,channel: &mut Channel<T>,ws: &mut Workspace, - replacement in libpijul/src/apply.rs at line 948
for atom in change.changes.iter().flat_map(|r| r.iter()) {if let Atom::EdgeMap(ref n) = atom {for e in n.edges.iter() {assert!(!e.flag.contains(EdgeFlags::PARENT));if e.flag.contains(EdgeFlags::FOLDER | EdgeFlags::DELETED) && e.to.len() > 0 {repair_edge(txn, channel, e, change_id, ws)?;let mut files = std::mem::replace(&mut ws.missing_context.files, HashSet::new());for file in files.drain() {if file.is_empty() {if !is_rooted(txn, channel, file, ws)? {repair_edge(txn, channel, file, ws)?}} else {let f0 = EdgeFlags::FOLDER;let f1 = EdgeFlags::FOLDER | EdgeFlags::BLOCK | EdgeFlags::PSEUDO;if let Some(ee) = iter_adjacent(txn, channel, file, f0, f1).next() {let dest = ee.dest.inode_vertex();if !is_rooted(txn, channel, dest, ws)? {repair_edge(txn, channel, dest, ws)? - edit in libpijul/src/apply.rs at line 965
ws.missing_context.files = files; - replacement in libpijul/src/apply.rs at line 973
e: &NewEdge<Option<Hash>>,change_id: ChangeId,to0: Vertex<ChangeId>, - replacement in libpijul/src/apply.rs at line 976
// If we're deleting a name and not a whole file.let h = if let Some(h) = e.to.change {h} else {return Ok(());};let to = Vertex {change: if let Some(h) = txn.get_internal(h) {hdebug!("repair_edge {:?}", to0);let mut stack = vec![(to0, true, true, true)];ws.parents.clear();while let Some((current, _, al, anc_al)) = stack.pop() {if !ws.parents.insert(current) {continue;}debug!("repair_cyclic {:?}", current);if current != to0 {stack.push((current, true, al, anc_al));}if current.is_root() {debug!("root");break;}if let Some(&true) = ws.rooted.get(¤t) {debug!("rooted");break;}let f = EdgeFlags::PARENT | EdgeFlags::FOLDER;let len = stack.len();for parent in iter_adjacent(txn, channel, current, f, EdgeFlags::all()) {if parent.flag.is_parent() {let anc = find_block_end(txn, channel, parent.dest)?;debug!("is_rooted, parent = {:?}", parent);let al = iter_adjacent(txn,channel,anc,f,f | EdgeFlags::BLOCK | EdgeFlags::PSEUDO,).next().is_some();debug!("al = {:?}, flag = {:?}", al, parent.flag);stack.push((anc, false, parent.flag.is_deleted(), al));}}if stack.len() == len {stack.pop(); - replacement in libpijul/src/apply.rs at line 1017[5.979933]→[5.100199:100272](∅→∅),[5.100272]→[5.979998:980262](∅→∅),[5.979998]→[5.979998:980262](∅→∅),[5.980262]→[5.72154:72210](∅→∅),[5.72210]→[5.980317:980413](∅→∅),[5.980317]→[5.980317:980413](∅→∅)
return Err((crate::pristine::InconsistentChange {}).into());},start: e.to.start,end: e.to.end,};// Check that the inode descendant of this name is rooted.let mut unrooted = false;let f0 = EdgeFlags::FOLDER;let f1 = EdgeFlags::FOLDER | EdgeFlags::BLOCK | EdgeFlags::PSEUDO;for ee in iter_adjacent(txn, channel, to, f0, f1) {if !is_rooted(txn, channel, ee.dest.inode_vertex(), ws)? {unrooted = true;(&mut stack[len..]).sort_unstable_by(|a, b| a.3.cmp(&b.3)) - replacement in libpijul/src/apply.rs at line 1020[5.980429]→[5.980429:980470](∅→∅),[5.980470]→[5.72211:72301](∅→∅),[5.72301]→[5.980558:980617](∅→∅),[5.980558]→[5.980558:980617](∅→∅),[5.980617]→[5.72302:72347](∅→∅),[5.72347]→[5.980649:980783](∅→∅),[5.980649]→[5.980649:980783](∅→∅),[5.980783]→[5.100273:100324](∅→∅)
// If not, repair.if unrooted {let from = find_block_end(txn, channel, internal_pos(txn, &e.from, change_id)?)?;debug!("repairing unrooted: {:?} {:?}", from, to);put_graph_with_rev(txn,channel,EdgeFlags::FOLDER | EdgeFlags::PSEUDO,from,to,ChangeId::ROOT,).map_err(LocalApplyError::Txn)?;let mut current = to0;for (next, on_path, del, _) in stack {if on_path {if del {put_graph_with_rev(txn,channel,EdgeFlags::FOLDER | EdgeFlags::PSEUDO,next,current,ChangeId::ROOT,).map_err(LocalApplyError::Txn)?;}current = next} - edit in libpijul/src/apply.rs at line 1046
let mut alive = false;assert!(v.is_empty());for e in iter_adjacent(txn, channel, v, EdgeFlags::empty(), EdgeFlags::all()) {if e.flag.contains(EdgeFlags::PARENT) {if e.flag & (EdgeFlags::FOLDER | EdgeFlags::DELETED) == EdgeFlags::FOLDER {alive = true;break;}} else if !e.flag.is_deleted() {alive = true;break;}}if !alive {debug!("is_rooted, not alive");return Ok(true);} - replacement in libpijul/src/apply.rs at line 1102
let parent = find_block_end(txn, channel, parent.dest)?;stack.push(parent)stack.push(find_block_end(txn, channel, parent.dest)?)