Fast path for external importers (e.g. git-import) that already have pre-built `RecordedFile`s and just need globalization + assembly + hashing. Returns `(Change, Hash)`.
(
&self,
header: ChangeHeader,
recorded_files: &[atomic_core::record::workflow::RecordedFile],
)
| 1118 | /// |
| 1119 | /// Returns `(Change, Hash)`. |
| 1120 | pub fn assemble_and_hash( |
| 1121 | &self, |
| 1122 | header: ChangeHeader, |
| 1123 | recorded_files: &[atomic_core::record::workflow::RecordedFile], |
| 1124 | ) -> Result<(Change, Hash), RecordError> { |
| 1125 | use atomic_core::record::workflow::assemble_change; |
| 1126 | use atomic_core::record::workflow::assembly::AssemblyOptions; |
| 1127 | |
| 1128 | let overall_start = std::time::Instant::now(); |
| 1129 | |
| 1130 | let txn = self |
| 1131 | .pristine |
| 1132 | .read_txn() |
| 1133 | .map_err(|e| RecordError::Database(e.to_string()))?; |
| 1134 | |
| 1135 | // Use a bare transaction — no ViewGraph filter needed. |
| 1136 | // |
| 1137 | // This method is the fast path for git import, where every change |
| 1138 | // is written to a shared view and all edges land in the global |
| 1139 | // GRAPH table. A bare ReadTxn sees every edge directly. |
| 1140 | // |
| 1141 | // Wrapping in ViewGraph + collect_visible_change_ids would scan |
| 1142 | // the entire view change log on every call (O(N) per commit, |
| 1143 | // O(N²) total for N commits), which makes large imports |
| 1144 | // progressively slower. |
| 1145 | let assembly_options = AssemblyOptions::default(); |
| 1146 | |
| 1147 | let assembly_result = assemble_change(&txn, recorded_files, header, &assembly_options)?; |
| 1148 | |
| 1149 | let change = assembly_result.into_change(); |
| 1150 | log::debug!( |
| 1151 | "assemble_and_hash: assembly complete, content_size={} hunks={}", |
| 1152 | change.contents.len(), |
| 1153 | change.hunks().len(), |
| 1154 | ); |
| 1155 | |
| 1156 | let step = std::time::Instant::now(); |
| 1157 | let mut v3_bytes = Vec::new(); |
| 1158 | let hash = change |
| 1159 | .serialize(&mut v3_bytes) |
| 1160 | .map_err(|e| RecordError::ChangeStore(e.to_string()))?; |
| 1161 | let serialize_ms = step.elapsed().as_millis(); |
| 1162 | |
| 1163 | let step = std::time::Instant::now(); |
| 1164 | let (final_change, _) = Change::deserialize(&mut v3_bytes.as_slice()) |
| 1165 | .map_err(|e| RecordError::ChangeStore(e.to_string()))?; |
| 1166 | let deserialize_ms = step.elapsed().as_millis(); |
| 1167 | |
| 1168 | let total_ms = overall_start.elapsed().as_millis(); |
| 1169 | if serialize_ms + deserialize_ms > 100 { |
| 1170 | log::warn!( |
| 1171 | "assemble_and_hash: serialize={}ms ({} bytes) deserialize={}ms total={}ms", |
| 1172 | serialize_ms, |
| 1173 | v3_bytes.len(), |
| 1174 | deserialize_ms, |
| 1175 | total_ms, |
| 1176 | ); |
| 1177 | } else { |
nothing calls this directly
no test coverage detected