lix 0.17.1

Embeddable version control for apps and AI agents.
Documentation
use super::{MigrationOptions, publish::PublicationPlan};
use crate::LixError;
use crate::storage_adapter::{StorageAdapterRead, StorageWriteSet};

pub(super) async fn stage_repair(
    read: &(impl StorageAdapterRead + ?Sized),
    plan: &mut PublicationPlan,
    options: &MigrationOptions,
    entries: &mut usize,
    bytes: &mut usize,
) -> Result<(), LixError> {
    let collected = crate::sync::collect_certified_snapshot_omitted_owners(
        read,
        options.max_changes.saturating_sub(*entries),
        options.max_preflight_bytes.saturating_sub(*bytes),
    )
    .await?;
    *entries = entries.saturating_add(collected.entries);
    *bytes = bytes.saturating_add(collected.bytes);
    let space = crate::tracked_state::TRACKED_STATE_COMMIT_HISTORY_DEFERRED_SPACE;
    let mut staged = StorageWriteSet::new();
    let mut markers = Vec::with_capacity(collected.owners.len());
    for (id, scope) in collected.owners {
        crate::tracked_state::stage_commit_history_omitted(&mut staged, id, scope);
        let key = id.as_uuid().as_bytes();
        let value = staged.staged_value(space, key).ok_or_else(|| {
            LixError::new(
                "LIX_ERROR_MIGRATION_FAILED",
                "omission marker staging produced no value",
            )
        })?;
        *entries = entries.saturating_add(1);
        *bytes = bytes.saturating_add(key.len() + value.len());
        if *entries > options.max_changes || *bytes > options.max_preflight_bytes {
            return Err(LixError::new(
                "LIX_ERROR_MIGRATION_LIMIT_EXCEEDED",
                "snapshot omission marker publication exceeds preflight limits",
            ));
        }
        markers.push((key.to_vec(), value.to_vec()));
    }
    if !markers.is_empty() {
        plan.put_mutable(space, markers)?;
    }
    Ok(())
}