(
txn: &atomic_core::pristine::ReadTxn,
store: &C,
inode_graph_table: &redb::ReadOnlyMultimapTable<&'static [u8; 32], &'static [u8; 24]>,
change_filter_arc: &Arc<std::collections::Hash
| 32 | /// deterministic order so the rendering is stable across runs. |
| 33 | #[allow(clippy::too_many_arguments)] |
| 34 | fn render_name_conflict<C: atomic_core::change::ChangeStore>( |
| 35 | txn: &atomic_core::pristine::ReadTxn, |
| 36 | store: &C, |
| 37 | inode_graph_table: &redb::ReadOnlyMultimapTable<&'static [u8; 32], &'static [u8; 24]>, |
| 38 | change_filter_arc: &Arc<std::collections::HashSet<NodeId>>, |
| 39 | path: &str, |
| 40 | sides: &[(Inode, Position<NodeId>)], |
| 41 | ) -> Result<Vec<u8>, String> { |
| 42 | use atomic_core::output::repo::{ |
| 43 | output_graph_content_resolved, resolve_conflicts_semantically, |
| 44 | }; |
| 45 | use atomic_core::output::{compute_order, retrieve_graph, RetrieveOptions, Writer}; |
| 46 | use atomic_core::pristine::InodePreloadTxn; |
| 47 | |
| 48 | let mut out: Vec<u8> = Vec::new(); |
| 49 | for (i, (inode, position)) in sides.iter().enumerate() { |
| 50 | if i == 0 { |
| 51 | out.extend_from_slice(format!(">>>>>>> {} (name conflict)\n", path).as_bytes()); |
| 52 | } else { |
| 53 | out.extend_from_slice(b"=======\n"); |
| 54 | } |
| 55 | |
| 56 | let preloaded = InodePreloadTxn::from_table(txn, *inode, inode_graph_table) |
| 57 | .map_err(|e| format!("{}: name-conflict preload: {:?}", path, e))?; |
| 58 | let retrieve_opts = |
| 59 | RetrieveOptions::default().with_change_filter_arc(change_filter_arc.clone()); |
| 60 | let retrieve_result = retrieve_graph(&preloaded, *position, retrieve_opts) |
| 61 | .map_err(|e| format!("{}: name-conflict retrieve: {:?}", path, e))?; |
| 62 | let mut graph = retrieve_result.graph; |
| 63 | let order = compute_order(&mut graph); |
| 64 | let resolved = resolve_conflicts_semantically(&preloaded, store, &graph, &order); |
| 65 | let buffer = Vec::with_capacity(graph.total_bytes()); |
| 66 | let mut writer = Writer::new(buffer); |
| 67 | let hash_fn = |node_id: NodeId| -> Option<Hash> { |
| 68 | if node_id.is_root() { |
| 69 | return None; |
| 70 | } |
| 71 | preloaded.get_external(node_id).ok().flatten() |
| 72 | }; |
| 73 | output_graph_content_resolved(store, hash_fn, &graph, &order, &mut writer, &resolved) |
| 74 | .map_err(|e| format!("{}: name-conflict content: {:?}", path, e))?; |
| 75 | let side = writer.into_inner(); |
| 76 | out.extend_from_slice(&side); |
| 77 | if !side.ends_with(b"\n") { |
| 78 | out.push(b'\n'); |
| 79 | } |
| 80 | } |
| 81 | out.extend_from_slice(format!("<<<<<<< {} (name conflict)\n", path).as_bytes()); |
| 82 | Ok(out) |
| 83 | } |
| 84 | |
| 85 | impl Repository { |
| 86 | /// Persist the conflict state discovered by a materialize into the |
no test coverage detected