| 530 | /// omitted. Read-only. |
| 531 | #[allow(clippy::type_complexity)] |
| 532 | pub fn list_conflicts( |
| 533 | &self, |
| 534 | ) -> Result<Vec<(String, Vec<atomic_core::pristine::StoredConflict>)>, RepositoryError> { |
| 535 | let txn = self |
| 536 | .pristine |
| 537 | .read_txn() |
| 538 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 539 | let view = match txn |
| 540 | .get_view(&self.current_view) |
| 541 | .map_err(|e| RepositoryError::Database(e.to_string()))? |
| 542 | { |
| 543 | Some(v) => v, |
| 544 | None => return Ok(Vec::new()), |
| 545 | }; |
| 546 | let mut out = Vec::new(); |
| 547 | for (_inode, records) in txn |
| 548 | .iter_conflicts(view.id) |
| 549 | .map_err(|e| RepositoryError::Database(e.to_string()))? |
| 550 | { |
| 551 | let Some(first) = records.first() else { |
| 552 | continue; |
| 553 | }; |
| 554 | let abs_path = self.root.join(&first.path); |
| 555 | let still_conflicted = std::fs::read(&abs_path) |
| 556 | .ok() |
| 557 | .and_then(|c| super::materialize::first_conflict_marker_line(&c)) |
| 558 | .is_some(); |
| 559 | if !still_conflicted { |
| 560 | continue; |
| 561 | } |
| 562 | out.push((first.path.clone(), records)); |
| 563 | } |
| 564 | out.sort_by(|a, b| a.0.cmp(&b.0)); |
| 565 | Ok(out) |
| 566 | } |
| 567 | |
| 568 | /// Quick status check — uses default options. |
| 569 | /// |