git_bug/replica/entity/snapshot/
mod.rs

1// git-bug-rs - A rust library for interfacing with git-bug repositories
2//
3// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
4// SPDX-License-Identifier: GPL-3.0-or-later
5//
6// This file is part of git-bug-rs/git-gub.
7//
8// You should have received a copy of the License along with this program.
9// If not, see <https://www.gnu.org/licenses/agpl.txt>.
10
11//! Snapshots are complied versions of [`Entities`][`super::Entity`], that are
12//! easier to consume (i.e., their attributes are fixed.).
13//! However, changing or re-committing them to disk is impossible, as they drop
14//! all of the information needed to re-construct the correct DAG.
15//!
16//! They are effectively a collapsed version of an [`Entity`][`super::Entity`]
17//! at a point in time.
18
19use timeline::history_step::HistoryStep;
20
21use self::timeline::Timeline;
22use super::{Entity, id::entity_id::EntityId, identity::IdentityStub, operation::Operation};
23
24pub mod timeline;
25
26/// A compiled version of a [`Entity`][`super::Entity`].
27///
28/// If you want to read/display this [`Entity`][`super::Entity`], than this is
29/// the type you want. If you need to change or create an
30/// [`Entity`][`super::Entity`], than use the functions on it directly.
31///
32/// An [`Snapshot<E>`] is, as the name implies, just a snapshot of the current
33/// state of an [`Entity`]. As such, it is not intended to keep these snapshots
34/// around for longer periods of time. Simply call
35/// [`snapshot()`][`Entity::snapshot()`], use the snapshot, and drop it again.
36#[derive(Debug)]
37pub struct Snapshot<E: Entity> {
38    id: EntityId<E>,
39
40    timeline: E::Timeline,
41}
42
43impl<E: Entity> Clone for Snapshot<E>
44where
45    E::Timeline: Clone,
46{
47    fn clone(&self) -> Self {
48        Self {
49            id: self.id,
50            timeline: self.timeline.clone(),
51        }
52    }
53}
54
55impl<E: Entity> Snapshot<E> {
56    /// Return the [`Timeline`] that contains all the changes to the [`Entity`]
57    /// at the time of this snapshot.
58    #[must_use]
59    pub fn timeline(&self) -> &E::Timeline {
60        &self.timeline
61    }
62
63    /// Get the [`EntityId`] of this [`Snapshot`].
64    ///
65    /// This is the same as the [`EntityId`] of the [`Entity`], which was used to
66    /// create this snapshot.
67    #[must_use]
68    pub fn id(&self) -> EntityId<E> {
69        self.id
70    }
71
72    /// Apply another operation to this [`Snapshot`].
73    pub fn apply(&mut self, op: &Operation<E>) {
74        self.timeline.add(op);
75    }
76
77    /// Get an iterator over all the people that acted in this [`Entity`].
78    ///
79    /// This means, that they are an author of one of the
80    /// [`HistorySteps`][`Entity::HistoryStep`] that compose this timeline.
81    pub fn actors<'a>(&'a self) -> impl Iterator<Item = IdentityStub> + use<'a, E>
82    where
83        <E as Entity>::HistoryStep: 'a,
84    {
85        // TODO(@bpeetz): This should de-duplicate. <2025-04-20>
86        self.timeline.history().iter().map(HistoryStep::author)
87    }
88
89    /// Construct this [`Snapshot`] from an [`Entity's`][`Entity`] root
90    /// operation.
91    ///
92    /// This is probably not what you want, you should use [`Entity::snapshot`]
93    /// to get the snapshot of an [`Entity`].
94    pub fn from_root_operation(op: &Operation<E>) -> Self {
95        let timeline = E::Timeline::from_root_operation(op);
96
97        Self {
98            id: op.id(),
99            timeline,
100        }
101    }
102}