gled-core 2.31.1

The engine of gled without a user interface: inputs, timing, rendering, Art-Net/DMX output and storage
Documentation
//! Bringing the asset files to the current format before they are loaded:
//! old lamp drawings and projects are converted, every file gets its version.

use super::{Loading, STORAGE_DIR, action::StorageAction, git::Git};
use crate::action::UiAction;
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};

static DONE: AtomicUsize = AtomicUsize::new(0);
static TOTAL: AtomicUsize = AtomicUsize::new(0);

/// How many of how many files the running migration has done.
pub(crate) fn progress() -> Option<(usize, usize)> {
    let total = TOTAL.load(Relaxed);
    (super::loading() == Loading::Migrating && total > 0).then(|| (DONE.load(Relaxed), total))
}

/// Migrates what is pending and writes it through git: staged, never
/// committed, so the user sees the change before it is kept. What fails is
/// reported and stays as it was.
///
/// Runs on every asset load, on start and after a branch switch: files of the
/// old format cannot be loaded at all, so whatever a branch brings along is
/// converted (and staged on that branch) before its collections load. With
/// nothing pending this is only a directory scan.
pub(super) fn run(git: &mut Git) {
    let pending = gled_migrate::pending(&STORAGE_DIR);
    if pending.is_empty() {
        return;
    }
    tracing::info!("Migrating {} asset files", pending.len());
    DONE.store(0, Relaxed);
    TOTAL.store(pending.len(), Relaxed);
    Loading::Migrating.set();
    let migration = gled_migrate::migrate(&STORAGE_DIR, &pending, |progress| {
        tracing::debug!("{} ({}/{})", progress.task, progress.done, progress.total);
        DONE.store(progress.done, Relaxed);
    });
    for error in migration.errors {
        tracing::error!("Could not migrate {error}");
        UiAction::Error(format!("Could not migrate {error}")).enqueue();
    }
    let wrote_any = !migration.written.is_empty();
    for file in migration.written {
        if let Err(err) = git.write_asset(&file.path, file.contents) {
            UiAction::Error(format!("Could not write migrated asset: {err}")).enqueue();
        }
    }
    if wrote_any {
        // Staged with the converted files, so an older gled refuses the
        // repository instead of loading files it cannot read and saving over
        // them.
        super::files::write_storage_version_file(git);
    }
    StorageAction::CountStagedFiles.enqueue();
    TOTAL.store(0, Relaxed);
}