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],
)
| 883 | /// |
| 884 | /// Returns `(Change, Hash)`. |
| 885 | pub fn assemble_and_hash( |
| 886 | &self, |
| 887 | header: ChangeHeader, |
| 888 | recorded_files: &[atomic_core::record::workflow::RecordedFile], |
| 889 | ) -> Result<(Change, Hash), RecordError> { |
| 890 | use atomic_core::record::workflow::assemble_change; |
| 891 | use atomic_core::record::workflow::assembly::AssemblyOptions; |
| 892 | |
| 893 | let overall_start = std::time::Instant::now(); |
| 894 | |
| 895 | let txn = self |
| 896 | .pristine |
| 897 | .read_txn() |
| 898 | .map_err(|e| RecordError::Database(e.to_string()))?; |
| 899 | |
| 900 | // Use a bare transaction — no ViewGraph filter needed. |
| 901 | // |
| 902 | // This method is the fast path for git import, where every change |
| 903 | // is written to a shared view and all edges land in the global |
| 904 | // GRAPH table. A bare ReadTxn sees every edge directly. |
| 905 | // |
| 906 | // Wrapping in ViewGraph + collect_visible_change_ids would scan |
| 907 | // the entire view change log on every call (O(N) per commit, |
| 908 | // O(N²) total for N commits), which makes large imports |
| 909 | // progressively slower. |
| 910 | let assembly_options = AssemblyOptions::default(); |
| 911 | |
| 912 | let assembly_result = assemble_change(&txn, recorded_files, header, &assembly_options)?; |
| 913 | |
| 914 | let change = assembly_result.into_change(); |
| 915 | log::debug!( |
| 916 | "assemble_and_hash: assembly complete, content_size={} hunks={}", |
| 917 | change.contents.len(), |
| 918 | change.hunks().len(), |
| 919 | ); |
| 920 | |
| 921 | let step = std::time::Instant::now(); |
| 922 | let mut v3_bytes = Vec::new(); |
| 923 | let hash = change |
| 924 | .serialize(&mut v3_bytes) |
| 925 | .map_err(|e| RecordError::ChangeStore(e.to_string()))?; |
| 926 | let serialize_ms = step.elapsed().as_millis(); |
| 927 | |
| 928 | let step = std::time::Instant::now(); |
| 929 | let (final_change, _) = Change::deserialize(&mut v3_bytes.as_slice()) |
| 930 | .map_err(|e| RecordError::ChangeStore(e.to_string()))?; |
| 931 | let deserialize_ms = step.elapsed().as_millis(); |
| 932 | |
| 933 | let total_ms = overall_start.elapsed().as_millis(); |
| 934 | if serialize_ms + deserialize_ms > 100 { |
| 935 | log::warn!( |
| 936 | "assemble_and_hash: serialize={}ms ({} bytes) deserialize={}ms total={}ms", |
| 937 | serialize_ms, |
| 938 | v3_bytes.len(), |
| 939 | deserialize_ms, |
| 940 | total_ms, |
| 941 | ); |
| 942 | } else { |
nothing calls this directly
no test coverage detected