Assemble, save, and apply a freshly imported Git commit without going through the normal `insert_change()` load/check path. This preserves the normal graph writer and CRDT table application, but avoids reloading the just-saved change and avoids the `has_change_in_graph` probe. The write transaction is opened before assembly, so globalization and application share one consistent transaction view.
(
&self,
header: ChangeHeader,
recorded_files: &[atomic_core::record::workflow::RecordedFile],
unhashed: serde_json::Value,
deleted_paths: &[String],
op
| 720 | /// probe. The write transaction is opened before assembly, so globalization |
| 721 | /// and application share one consistent transaction view. |
| 722 | pub fn write_import_recorded( |
| 723 | &self, |
| 724 | header: ChangeHeader, |
| 725 | recorded_files: &[atomic_core::record::workflow::RecordedFile], |
| 726 | unhashed: serde_json::Value, |
| 727 | deleted_paths: &[String], |
| 728 | options: InsertOptions, |
| 729 | ) -> Result<ImportWriteOutcome, RepositoryError> { |
| 730 | use atomic_core::record::workflow::assemble_change; |
| 731 | use atomic_core::record::workflow::assembly::AssemblyOptions; |
| 732 | |
| 733 | let mut timings = ImportWriteTimings::default(); |
| 734 | let view_name = options.view.as_deref().unwrap_or(&self.current_view); |
| 735 | |
| 736 | let mut txn = self |
| 737 | .pristine |
| 738 | .write_txn() |
| 739 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 740 | |
| 741 | let assemble_start = std::time::Instant::now(); |
| 742 | let mut change = if recorded_files.is_empty() { |
| 743 | Change::empty(header) |
| 744 | } else { |
| 745 | match assemble_change( |
| 746 | &txn, |
| 747 | recorded_files, |
| 748 | header.clone(), |
| 749 | &AssemblyOptions::default(), |
| 750 | ) { |
| 751 | Ok(result) => result.into_change(), |
| 752 | Err(e) => { |
| 753 | let err_msg = e.to_string(); |
| 754 | if err_msg.contains("empty") || err_msg.contains("AllEmpty") { |
| 755 | Change::empty(header) |
| 756 | } else { |
| 757 | return Err(RepositoryError::Apply(e.to_string())); |
| 758 | } |
| 759 | } |
| 760 | } |
| 761 | }; |
| 762 | timings.assemble_ms = assemble_start.elapsed().as_millis(); |
| 763 | |
| 764 | change.unhashed = Some(unhashed); |
| 765 | |
| 766 | let mut v3_bytes = Vec::new(); |
| 767 | let hash = change |
| 768 | .serialize(&mut v3_bytes) |
| 769 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 770 | let (final_change, verified_hash) = Change::deserialize(&mut v3_bytes.as_slice()) |
| 771 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 772 | debug_assert_eq!(hash, verified_hash); |
| 773 | |
| 774 | let save_start = std::time::Instant::now(); |
| 775 | self.save_change_bytes(&hash, &v3_bytes, &final_change)?; |
| 776 | timings.save_ms = save_start.elapsed().as_millis(); |
| 777 | |
| 778 | let change_id = txn |
| 779 | .register_change(&hash) |
no test coverage detected