git-bug 0.2.4

A rust library for interfacing with git-bug repositories
Documentation
// git-bug-rs - A rust library for interfacing with git-bug repositories
//
// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
// SPDX-License-Identifier: GPL-3.0-or-later
//
// This file is part of git-bug-rs/git-gub.
//
// You should have received a copy of the License along with this program.
// If not, see <https://www.gnu.org/licenses/agpl.txt>.

//! Snapshots are complied versions of [`Entities`][`super::Entity`], that are
//! easier to consume (i.e., their attributes are fixed.).
//! However, changing or re-committing them to disk is impossible, as they drop
//! all of the information needed to re-construct the correct DAG.
//!
//! They are effectively a collapsed version of an [`Entity`][`super::Entity`]
//! at a point in time.

use timeline::history_step::HistoryStep;

use self::timeline::Timeline;
use super::{Entity, id::entity_id::EntityId, identity::IdentityStub, operation::Operation};

pub mod timeline;

/// A compiled version of a [`Entity`][`super::Entity`].
///
/// If you want to read/display this [`Entity`][`super::Entity`], than this is
/// the type you want. If you need to change or create an
/// [`Entity`][`super::Entity`], than use the functions on it directly.
///
/// An [`Snapshot<E>`] is, as the name implies, just a snapshot of the current
/// state of an [`Entity`]. As such, it is not intended to keep these snapshots
/// around for longer periods of time. Simply call
/// [`snapshot()`][`Entity::snapshot()`], use the snapshot, and drop it again.
#[derive(Debug)]
pub struct Snapshot<E: Entity> {
    id: EntityId<E>,

    timeline: E::Timeline,
}

impl<E: Entity> Clone for Snapshot<E>
where
    E::Timeline: Clone,
{
    fn clone(&self) -> Self {
        Self {
            id: self.id,
            timeline: self.timeline.clone(),
        }
    }
}

impl<E: Entity> Snapshot<E> {
    /// Return the [`Timeline`] that contains all the changes to the [`Entity`]
    /// at the time of this snapshot.
    #[must_use]
    pub fn timeline(&self) -> &E::Timeline {
        &self.timeline
    }

    /// Get the [`EntityId`] of this [`Snapshot`].
    ///
    /// This is the same as the [`EntityId`] of the [`Entity`], which was used to
    /// create this snapshot.
    #[must_use]
    pub fn id(&self) -> EntityId<E> {
        self.id
    }

    /// Apply another operation to this [`Snapshot`].
    pub fn apply(&mut self, op: &Operation<E>) {
        self.timeline.add(op);
    }

    /// Get an iterator over all the people that acted in this [`Entity`].
    ///
    /// This means, that they are an author of one of the
    /// [`HistorySteps`][`Entity::HistoryStep`] that compose this timeline.
    pub fn actors<'a>(&'a self) -> impl Iterator<Item = IdentityStub> + use<'a, E>
    where
        <E as Entity>::HistoryStep: 'a,
    {
        // TODO(@bpeetz): This should de-duplicate. <2025-04-20>
        self.timeline.history().iter().map(HistoryStep::author)
    }

    /// Construct this [`Snapshot`] from an [`Entity's`][`Entity`] root
    /// operation.
    ///
    /// This is probably not what you want, you should use [`Entity::snapshot`]
    /// to get the snapshot of an [`Entity`].
    pub fn from_root_operation(op: &Operation<E>) -> Self {
        let timeline = E::Timeline::from_root_operation(op);

        Self {
            id: op.id(),
            timeline,
        }
    }
}