remove single-use traits while leaving the structure as is

This commit is contained in:
Sebastian Thiel 2024-05-26 14:34:45 +02:00
parent 346c96869e
commit e3156ba75c
No known key found for this signature in database
GPG Key ID: 9CB5EE7895E8268B
9 changed files with 65 additions and 100 deletions

View File

@ -1,5 +1,5 @@
use anyhow::Result;
use gitbutler_core::{ops::oplog::Oplog, projects::Project};
use gitbutler_core::projects::Project;
use clap::{arg, Command};
#[cfg(not(windows))]

View File

@ -21,7 +21,7 @@ use super::{
const SNAPSHOT_FILE_LIMIT_BYTES: u64 = 32 * 1024 * 1024;
/// The Oplog trait allows for crating snapshots of the current state of the project as well as restoring to a previous snapshot.
/// The Oplog allows for crating snapshots of the current state of the project as well as restoring to a previous snapshot.
/// Snapshots include the state of the working directory as well as all additional GitButler state (e.g virtual branches, conflict state).
/// The data is stored as git trees in the following shape:
/// .
@ -34,60 +34,11 @@ const SNAPSHOT_FILE_LIMIT_BYTES: u64 = 32 * 1024 * 1024;
/// │ ├── commit-message.txt
/// │ └── tree (subtree)
/// └── virtual_branches.toml
pub trait Oplog {
impl Project {
/// Prepares a snapshot of the current state of the working directory as well as GitButler data.
/// Returns a tree sha of the snapshot. The snapshot is not discoverable until it is comitted with `commit_snapshot`
/// If there are files that are untracked and larger than SNAPSHOT_FILE_LIMIT_BYTES, they are excluded from snapshot creation and restoring.
fn prepare_snapshot(&self) -> Result<String>;
/// Commits the snapshot tree that is created with the `prepare_snapshot` method.
/// Committing it makes the snapshot discoverable in `list_snapshots` as well as restorable with `restore_snapshot`.
/// Returns the sha of the created snapshot commit or None if snapshots are disabled.
fn commit_snapshot(
&self,
snapshot_tree_sha: String,
details: SnapshotDetails,
) -> Result<Option<String>>;
/// Creates a snapshot of the current state of the working directory as well as GitButler data.
/// This is a convinience method that combines `prepare_snapshot` and `commit_snapshot`.
fn create_snapshot(&self, details: SnapshotDetails) -> Result<Option<String>>;
/// Lists the snapshots that have been created for the given repository, up to the given limit.
/// An alternative way of retrieving the snapshots would be to manually the oplog head `git log <oplog_head>` available in `.git/gitbutler/operations-log.toml`.
///
/// If there are no snapshots, an empty list is returned.
fn list_snapshots(&self, limit: usize, sha: Option<String>) -> Result<Vec<Snapshot>>;
/// Reverts to a previous state of the working directory, virtual branches and commits.
/// The provided sha must refer to a valid snapshot commit.
/// Upon success, a new snapshot is created.
///
/// This will restore the following:
/// - The state of the working directory is checked out from the subtree `workdir` in the snapshot.
/// - The state of virtual branches is restored from the blob `virtual_branches.toml` in the snapshot.
/// - The state of conflicts (.git/base_merge_parent and .git/conflicts) is restored from the subtree `conflicts` in the snapshot (if not present, existing files are deleted).
///
/// If there are files that are untracked and larger than SNAPSHOT_FILE_LIMIT_BYTES, they are excluded from snapshot creation and restoring.
/// Returns the sha of the created revert snapshot commit or None if snapshots are disabled.
fn restore_snapshot(&self, sha: String) -> Result<Option<String>>;
/// Determines if a new snapshot should be created due to file changes being created since the last snapshot.
/// The needs for the automatic snapshotting are:
/// - It needs to facilitate backup of work in progress code
/// - The snapshots should not be too frequent or small - both for UX and performance reasons
/// - Checking if an automatic snapshot is needed should be fast and efficient since it is called on filesystem events
///
/// This implementation works as follows:
/// - If it's been more than 5 minutes since the last snapshot,
/// check the sum of added and removed lines since the last snapshot, otherwise return false.
/// - If the sum of added and removed lines is greater than a configured threshold, return true, otherwise return false.
fn should_auto_snapshot(&self) -> Result<bool>;
/// Returns the diff of the snapshot and it's parent. It only includes the workdir changes.
///
/// This is useful to show what has changed in this particular snapshot
fn snapshot_diff(&self, sha: String) -> Result<HashMap<PathBuf, FileDiff>>;
/// Gets the sha of the last snapshot commit if present.
fn oplog_head(&self) -> Result<Option<String>>;
}
impl Oplog for Project {
fn prepare_snapshot(&self) -> Result<String> {
/// If there are files that are untracked and larger than `SNAPSHOT_FILE_LIMIT_BYTES`, they are excluded from snapshot creation and restoring.
pub(crate) fn prepare_snapshot(&self) -> Result<String> {
let repo_path = self.path.as_path();
let repo = git2::Repository::init(repo_path)?;
@ -248,7 +199,14 @@ impl Oplog for Project {
Ok(tree_id.to_string())
}
fn commit_snapshot(&self, tree_id: String, details: SnapshotDetails) -> Result<Option<String>> {
/// Commits the snapshot tree that is created with the `prepare_snapshot` method.
/// Committing it makes the snapshot discoverable in `list_snapshots` as well as restorable with `restore_snapshot`.
/// Returns the sha of the created snapshot commit or None if snapshots are disabled.
pub(crate) fn commit_snapshot(
&self,
tree_id: String,
details: SnapshotDetails,
) -> Result<Option<String>> {
let repo_path = self.path.as_path();
let repo = git2::Repository::init(repo_path)?;
@ -306,14 +264,21 @@ impl Oplog for Project {
Ok(Some(new_commit_oid.to_string()))
}
/// Creates a snapshot of the current state of the working directory as well as GitButler data.
/// This is a convinience method that combines `prepare_snapshot` and `commit_snapshot`.
///
/// Note that errors in snapshot creation is typically ignored, so we want to learn about them.
#[instrument(skip(details), err(Debug))]
fn create_snapshot(&self, details: SnapshotDetails) -> Result<Option<String>> {
pub fn create_snapshot(&self, details: SnapshotDetails) -> Result<Option<String>> {
let tree_id = self.prepare_snapshot()?;
self.commit_snapshot(tree_id, details)
}
fn list_snapshots(&self, limit: usize, sha: Option<String>) -> Result<Vec<Snapshot>> {
/// Lists the snapshots that have been created for the given repository, up to the given limit.
/// An alternative way of retrieving the snapshots would be to manually the oplog head `git log <oplog_head>` available in `.git/gitbutler/operations-log.toml`.
///
/// If there are no snapshots, an empty list is returned.
pub fn list_snapshots(&self, limit: usize, sha: Option<String>) -> Result<Vec<Snapshot>> {
let repo_path = self.path.as_path();
let repo = git2::Repository::init(repo_path)?;
@ -408,7 +373,18 @@ impl Oplog for Project {
Ok(snapshots)
}
fn restore_snapshot(&self, sha: String) -> Result<Option<String>> {
/// Reverts to a previous state of the working directory, virtual branches and commits.
/// The provided sha must refer to a valid snapshot commit.
/// Upon success, a new snapshot is created.
///
/// This will restore the following:
/// - The state of the working directory is checked out from the subtree `workdir` in the snapshot.
/// - The state of virtual branches is restored from the blob `virtual_branches.toml` in the snapshot.
/// - The state of conflicts (.git/base_merge_parent and .git/conflicts) is restored from the subtree `conflicts` in the snapshot (if not present, existing files are deleted).
///
/// If there are files that are untracked and larger than `SNAPSHOT_FILE_LIMIT_BYTES`, they are excluded from snapshot creation and restoring.
/// Returns the sha of the created revert snapshot commit or None if snapshots are disabled.
pub fn restore_snapshot(&self, sha: String) -> Result<Option<String>> {
let repo_path = self.path.as_path();
let repo = git2::Repository::init(repo_path)?;
@ -577,7 +553,17 @@ impl Oplog for Project {
snapshot_tree.and_then(|snapshot_tree| self.commit_snapshot(snapshot_tree, details))
}
fn should_auto_snapshot(&self) -> Result<bool> {
/// Determines if a new snapshot should be created due to file changes being created since the last snapshot.
/// The needs for the automatic snapshotting are:
/// - It needs to facilitate backup of work in progress code
/// - The snapshots should not be too frequent or small - both for UX and performance reasons
/// - Checking if an automatic snapshot is needed should be fast and efficient since it is called on filesystem events
///
/// This implementation works as follows:
/// - If it's been more than 5 minutes since the last snapshot,
/// check the sum of added and removed lines since the last snapshot, otherwise return false.
/// - If the sum of added and removed lines is greater than a configured threshold, return true, otherwise return false.
pub fn should_auto_snapshot(&self) -> Result<bool> {
let oplog_state = OplogHandle::new(&self.gb_dir());
let last_snapshot_time = oplog_state.get_modified_at()?;
if last_snapshot_time.elapsed()? > Duration::from_secs(300) {
@ -591,7 +577,10 @@ impl Oplog for Project {
Ok(false)
}
fn snapshot_diff(&self, sha: String) -> Result<HashMap<PathBuf, FileDiff>> {
/// Returns the diff of the snapshot and it's parent. It only includes the workdir changes.
///
/// This is useful to show what has changed in this particular snapshot
pub fn snapshot_diff(&self, sha: String) -> Result<HashMap<PathBuf, FileDiff>> {
let repo_path = self.path.as_path();
let repo = git2::Repository::init(repo_path)?;
@ -630,7 +619,9 @@ impl Oplog for Project {
let hunks = hunks_by_filepath(None, &diff)?;
Ok(hunks)
}
fn oplog_head(&self) -> Result<Option<String>> {
/// Gets the sha of the last snapshot commit if present.
pub fn oplog_head(&self) -> Result<Option<String>> {
let oplog_state = OplogHandle::new(&self.gb_dir());
oplog_state.get_oplog_head()
}

View File

@ -1,33 +1,16 @@
use std::vec;
use crate::projects::Project;
use crate::{
ops::entry::{OperationKind, SnapshotDetails},
virtual_branches::{branch::BranchUpdateRequest, Branch},
};
use super::{entry::Trailer, oplog::Oplog};
use super::entry::Trailer;
pub trait Snapshot {
fn snapshot_branch_creation(&self, branch_name: String) -> anyhow::Result<()>;
fn snapshot_branch_deletion(&self, branch_name: String) -> anyhow::Result<()>;
fn snapshot_branch_applied(&self, branch_name: String) -> anyhow::Result<()>;
fn snapshot_branch_unapplied(&self, branch_name: String) -> anyhow::Result<()>;
fn snapshot_branch_update(
&self,
old_branch: &Branch,
update: &BranchUpdateRequest,
) -> anyhow::Result<()>;
fn snapshot_commit_creation(
&self,
snapshot_tree: String,
commit_message: String,
sha: Option<String>,
) -> anyhow::Result<()>;
fn snapshot_commit_undo(&self, commit_sha: String) -> anyhow::Result<()>;
}
impl<T: Oplog> Snapshot for T {
fn snapshot_branch_applied(&self, branch_name: String) -> anyhow::Result<()> {
/// Snapshot functionality
impl Project {
pub(crate) fn snapshot_branch_applied(&self, branch_name: String) -> anyhow::Result<()> {
let details =
SnapshotDetails::new(OperationKind::ApplyBranch).with_trailers(vec![Trailer {
key: "name".to_string(),
@ -36,7 +19,7 @@ impl<T: Oplog> Snapshot for T {
self.create_snapshot(details)?;
Ok(())
}
fn snapshot_branch_unapplied(&self, branch_name: String) -> anyhow::Result<()> {
pub(crate) fn snapshot_branch_unapplied(&self, branch_name: String) -> anyhow::Result<()> {
let details =
SnapshotDetails::new(OperationKind::UnapplyBranch).with_trailers(vec![Trailer {
key: "name".to_string(),
@ -45,7 +28,7 @@ impl<T: Oplog> Snapshot for T {
self.create_snapshot(details)?;
Ok(())
}
fn snapshot_commit_undo(&self, commit_sha: String) -> anyhow::Result<()> {
pub(crate) fn snapshot_commit_undo(&self, commit_sha: String) -> anyhow::Result<()> {
let details =
SnapshotDetails::new(OperationKind::UndoCommit).with_trailers(vec![Trailer {
key: "sha".to_string(),
@ -54,7 +37,7 @@ impl<T: Oplog> Snapshot for T {
self.create_snapshot(details)?;
Ok(())
}
fn snapshot_commit_creation(
pub(crate) fn snapshot_commit_creation(
&self,
snapshot_tree: String,
commit_message: String,
@ -73,7 +56,7 @@ impl<T: Oplog> Snapshot for T {
self.commit_snapshot(snapshot_tree, details)?;
Ok(())
}
fn snapshot_branch_creation(&self, branch_name: String) -> anyhow::Result<()> {
pub(crate) fn snapshot_branch_creation(&self, branch_name: String) -> anyhow::Result<()> {
let details =
SnapshotDetails::new(OperationKind::CreateBranch).with_trailers(vec![Trailer {
key: "name".to_string(),
@ -82,7 +65,7 @@ impl<T: Oplog> Snapshot for T {
self.create_snapshot(details)?;
Ok(())
}
fn snapshot_branch_deletion(&self, branch_name: String) -> anyhow::Result<()> {
pub(crate) fn snapshot_branch_deletion(&self, branch_name: String) -> anyhow::Result<()> {
let details =
SnapshotDetails::new(OperationKind::DeleteBranch).with_trailers(vec![Trailer {
key: "name".to_string(),
@ -92,7 +75,7 @@ impl<T: Oplog> Snapshot for T {
self.create_snapshot(details)?;
Ok(())
}
fn snapshot_branch_update(
pub(crate) fn snapshot_branch_update(
&self,
old_branch: &Branch,
update: &BranchUpdateRequest,

View File

@ -1,7 +1,6 @@
use std::time;
use crate::id::Id;
use crate::ops::oplog::Oplog;
use crate::{
git::{self, Oid},
project_repository,

View File

@ -1,10 +1,6 @@
use crate::{
error::Error,
ops::{
entry::{OperationKind, SnapshotDetails},
oplog::Oplog,
snapshot::Snapshot,
},
ops::entry::{OperationKind, SnapshotDetails},
};
use std::{collections::HashMap, path::Path, sync::Arc};

View File

@ -26,7 +26,6 @@ use super::{
};
use crate::error::{self, AnyhowContextExt, Code};
use crate::git::diff::{diff_files_into_hunks, trees, FileDiff};
use crate::ops::snapshot::Snapshot;
use crate::time::now_since_unix_epoch_ms;
use crate::virtual_branches::branch::HunkHash;
use crate::{

View File

@ -1,7 +1,5 @@
use std::io::Write;
use gitbutler_core::ops::oplog::Oplog;
use super::*;
#[tokio::test]

View File

@ -2,7 +2,7 @@ use crate::error::Error;
use anyhow::Context;
use gitbutler_core::git::diff::FileDiff;
use gitbutler_core::{
ops::{entry::Snapshot, oplog::Oplog},
ops::entry::Snapshot,
projects::{self, ProjectId},
};
use std::collections::HashMap;

View File

@ -3,7 +3,6 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use gitbutler_core::ops::entry::{OperationKind, SnapshotDetails};
use gitbutler_core::ops::oplog::Oplog;
use gitbutler_core::projects::ProjectId;
use gitbutler_core::synchronize::sync_with_gitbutler;
use gitbutler_core::virtual_branches::VirtualBranches;