Fixing a bug where zombie files could be deleted by unrecord, but not their contents
Dependencies
- [2]
ZDK3GNDBTag transactions (including a massive refactoring of errors) - [3]
YUJV2OHLchangelog - [4]
2BKYJ2JMFixing a bug introduced by the recent refactoring - [5]
IIV3EL2XCleanup, formatting, and fixing the Git feature - [6]
YN63NUZOSanakirja 1.0 - [7]
6YMDOZIBRefactoring apply - [*]
SXEYMYF7Fixing the bad changes in history (unfortunately, by rebooting). - [*]
CCLLB7OIUpgrading to Sanakirja 0.15 + version bump - [*]
HMMMKONLFixing alive vertices
Change contents
- edit in libpijul/src/unrecord/mod.rs at line 566
// Do not follow edges that are introduced by this patch// and are trivial parents (i.e. non-blocks), since they// aren't part of the zombie conflict. - edit in libpijul/src/unrecord/mod.rs at line 600
debug!("repair_edges_context: {:?}", e); - edit in libpijul/src/apply.rs at line 479
alive_folder: HashMap<Vertex<ChangeId>, bool>,folder_stack: Vec<(Vertex<ChangeId>, bool)>, - edit in libpijul/src/apply.rs at line 497
self.alive_folder.clear();self.folder_stack.clear(); - edit in libpijul/src/apply.rs at line 510
assert!(self.alive_folder.is_empty());assert!(self.folder_stack.is_empty()); - edit in libpijul/src/apply.rs at line 521
let mut alive_folder = std::mem::replace(&mut ws.alive_folder, HashMap::new());let mut folder_stack = std::mem::replace(&mut ws.folder_stack, Vec::new()); - edit in libpijul/src/apply.rs at line 540
// If we're deleting a FOLDER edge, repair_context_deleted// will not repair its potential descendants. Hence, we must// also count as "alive" a FOLDER node with alive descendants.if p.flag().is_folder() {if folder_has_alive_descendants(txn, channel, &mut alive_folder, &mut folder_stack, b)?{continue;}}if a.is_empty() && b_is_alive {// In this case, `a` can be an inode, in which case we// can't simply delete the edge, since b would become// unreachable.//// We test this here:let mut is_inode = false;for e in iter_adjacent(txn,channel,a,EdgeFlags::FOLDER | EdgeFlags::PARENT,EdgeFlags::all(),)? {let e = e?;if e.flag().contains(EdgeFlags::FOLDER | EdgeFlags::PARENT) {is_inode = true;break;}}if is_inode {continue;}} - replacement in libpijul/src/apply.rs at line 577
"Deleting {:?} {:?} {:?} {:?}","Deleting {:?} {:?} {:?} {:?} {:?} {:?}", - replacement in libpijul/src/apply.rs at line 581
p.flag()p.flag(),a_is_alive,b_is_alive, - edit in libpijul/src/apply.rs at line 607
// Note: if this is a folder edge,// repair_missing_up_context will stop immediately, so we// don't even need to call it. - edit in libpijul/src/apply.rs at line 623
ws.alive_folder = alive_folder;ws.folder_stack = folder_stack; - edit in libpijul/src/apply.rs at line 628[11.1060][2.42354]
fn folder_has_alive_descendants<T: GraphMutTxnT + TreeTxnT>(txn: &mut T,channel: &mut T::Graph,alive: &mut HashMap<Vertex<ChangeId>, bool>,stack: &mut Vec<(Vertex<ChangeId>, bool)>,b: Vertex<ChangeId>,) -> Result<bool, LocalApplyError<T>> {if let Some(r) = alive.get(&b) {return Ok(*r);}debug!("alive descendants");stack.clear();stack.push((b, false));while let Some((b, visited)) = stack.pop() {debug!("visiting {:?} {:?}", b, visited);if visited {if !alive.contains_key(&b) {alive.insert(b, false);}continue;}stack.push((b, true));for e in iter_adjacent(txn,channel,b,EdgeFlags::empty(),EdgeFlags::all() - EdgeFlags::DELETED - EdgeFlags::PARENT,)? {let e = e?;if e.flag().contains(EdgeFlags::FOLDER) {let c = txn.find_block(channel, e.dest())?;stack.push((*c, false));} else {// This is a non-deleted non-folder edge.let c = txn.find_block(channel, e.dest())?;if is_alive(txn, channel, &c)? {// The entire path is alive.for (x, on_path) in stack.iter() {if *on_path {alive.insert(*x, true);}}}}}}Ok(*alive.get(&b).unwrap_or(&false))} - edit in CHANGELOG.md at line 2
## Unreleased - edit in CHANGELOG.md at line 5
### Fixed- Fixing a bug with name conflicts, where files could end up with 0 alive name.- Fixing a few panics/unwraps- Fixing a bug where a zombie file could be deleted by `pijul unrecord`, but its contents would stay zombie.