mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-08-16 15:50:37 +03:00
move oplog to its own crate
This protects us from cyclic dependencies. Unfortunatelly as part of this, i had to introduce the imp Project as trait implementations since now Project is foreign
This commit is contained in:
parent
b286a6e2d3
commit
c36f67f148
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -2114,6 +2114,7 @@ dependencies = [
|
||||
"git2-hooks",
|
||||
"gitbutler-core",
|
||||
"gitbutler-git",
|
||||
"gitbutler-oplog",
|
||||
"gitbutler-testsupport",
|
||||
"glob",
|
||||
"hex",
|
||||
@ -2138,6 +2139,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"gitbutler-core",
|
||||
"gitbutler-oplog",
|
||||
"pager",
|
||||
]
|
||||
|
||||
@ -2226,6 +2228,23 @@ dependencies = [
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gitbutler-oplog"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"git2",
|
||||
"gitbutler-core",
|
||||
"gix",
|
||||
"itertools 0.13.0",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"strum",
|
||||
"tempfile",
|
||||
"toml 0.8.14",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gitbutler-sync"
|
||||
version = "0.0.0"
|
||||
@ -2233,6 +2252,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"git2",
|
||||
"gitbutler-core",
|
||||
"gitbutler-oplog",
|
||||
"itertools 0.13.0",
|
||||
"tracing",
|
||||
]
|
||||
@ -2250,6 +2270,7 @@ dependencies = [
|
||||
"git2",
|
||||
"gitbutler-branch",
|
||||
"gitbutler-core",
|
||||
"gitbutler-oplog",
|
||||
"gitbutler-testsupport",
|
||||
"gitbutler-watcher",
|
||||
"log",
|
||||
@ -2300,6 +2321,7 @@ dependencies = [
|
||||
"gitbutler-branch",
|
||||
"gitbutler-core",
|
||||
"gitbutler-notify-debouncer",
|
||||
"gitbutler-oplog",
|
||||
"gitbutler-sync",
|
||||
"gix",
|
||||
"notify",
|
||||
|
@ -9,6 +9,7 @@ members = [
|
||||
"crates/gitbutler-cli",
|
||||
"crates/gitbutler-branch",
|
||||
"crates/gitbutler-sync",
|
||||
"crates/gitbutler-oplog",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
@ -29,6 +30,7 @@ gitbutler-testsupport = { path = "crates/gitbutler-testsupport" }
|
||||
gitbutler-cli ={ path = "crates/gitbutler-cli" }
|
||||
gitbutler-branch = { path = "crates/gitbutler-branch" }
|
||||
gitbutler-sync = { path = "crates/gitbutler-sync" }
|
||||
gitbutler-oplog = { path = "crates/gitbutler-oplog" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
|
||||
|
@ -11,6 +11,7 @@ anyhow = "1.0.86"
|
||||
git2.workspace = true
|
||||
tokio.workspace = true
|
||||
gitbutler-core.workspace = true
|
||||
gitbutler-oplog.workspace = true
|
||||
serde = { workspace = true, features = ["std"]}
|
||||
bstr = "1.9.1"
|
||||
diffy = "0.3.0"
|
||||
|
@ -1,11 +1,15 @@
|
||||
use anyhow::Result;
|
||||
use gitbutler_core::{
|
||||
git::{credentials::Helper, BranchExt},
|
||||
ops::entry::{OperationKind, SnapshotDetails},
|
||||
project_repository::Repository,
|
||||
projects::FetchResult,
|
||||
types::ReferenceName,
|
||||
};
|
||||
use gitbutler_oplog::{
|
||||
entry::{OperationKind, SnapshotDetails},
|
||||
oplog::Oplog,
|
||||
snapshot::Snapshot,
|
||||
};
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
use tokio::sync::Semaphore;
|
||||
|
@ -1,3 +1,4 @@
|
||||
use gitbutler_oplog::snapshot::Snapshot;
|
||||
use std::borrow::Borrow;
|
||||
#[cfg(target_family = "unix")]
|
||||
use std::os::unix::prelude::PermissionsExt;
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use gitbutler_oplog::oplog::Oplog;
|
||||
use itertools::Itertools;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
@ -11,6 +11,7 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
gitbutler-core.workspace = true
|
||||
gitbutler-oplog.workspace = true
|
||||
clap = "4.5.4"
|
||||
anyhow = "1.0.86"
|
||||
chrono = "0.4.10"
|
||||
|
@ -1,5 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use gitbutler_core::projects::Project;
|
||||
use gitbutler_oplog::oplog::Oplog;
|
||||
|
||||
use clap::{arg, Command};
|
||||
#[cfg(not(windows))]
|
||||
|
@ -60,10 +60,7 @@ pub fn iter_worktree_files(
|
||||
|
||||
/// Write a single file so that the write either fully succeeds, or fully fails,
|
||||
/// assuming the containing directory already exists.
|
||||
pub(crate) fn write<P: AsRef<Path>>(
|
||||
file_path: P,
|
||||
contents: impl AsRef<[u8]>,
|
||||
) -> anyhow::Result<()> {
|
||||
pub fn write<P: AsRef<Path>>(file_path: P, contents: impl AsRef<[u8]>) -> anyhow::Result<()> {
|
||||
let mut temp_file = gix::tempfile::new(
|
||||
file_path.as_ref().parent().unwrap(),
|
||||
ContainingDirectory::Exists,
|
||||
@ -104,7 +101,7 @@ fn persist_tempfile(
|
||||
/// Reads and parses the state file.
|
||||
///
|
||||
/// If the file does not exist, it will be created.
|
||||
pub(crate) fn read_toml_file_or_default<T: DeserializeOwned + Default>(path: &Path) -> Result<T> {
|
||||
pub fn read_toml_file_or_default<T: DeserializeOwned + Default>(path: &Path) -> Result<T> {
|
||||
let mut file = match File::open(path) {
|
||||
Ok(f) => f,
|
||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(T::default()),
|
||||
|
@ -23,7 +23,6 @@ pub mod git;
|
||||
pub mod id;
|
||||
pub mod keys;
|
||||
pub mod lock;
|
||||
pub mod ops;
|
||||
pub mod path;
|
||||
pub mod project_repository;
|
||||
pub mod projects;
|
||||
|
@ -5,7 +5,6 @@ mod suite {
|
||||
mod git;
|
||||
mod keys;
|
||||
mod lock;
|
||||
mod ops;
|
||||
mod types;
|
||||
pub mod virtual_branches;
|
||||
mod zip;
|
||||
|
@ -1 +0,0 @@
|
||||
mod entry;
|
25
crates/gitbutler-oplog/Cargo.toml
Normal file
25
crates/gitbutler-oplog/Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "gitbutler-oplog"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
authors = ["GitButler <gitbutler@gitbutler.com>"]
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
git2.workspace = true
|
||||
gitbutler-core.workspace = true
|
||||
serde = { workspace = true, features = ["std"]}
|
||||
itertools = "0.13"
|
||||
strum = { version = "0.26", features = ["derive"] }
|
||||
tracing = "0.1.40"
|
||||
gix = { workspace = true, features = ["dirwalk", "credentials", "parallel"] }
|
||||
toml = "0.8.13"
|
||||
|
||||
[[test]]
|
||||
name="oplog"
|
||||
path = "tests/mod.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1.4"
|
||||
tempfile = "3.10"
|
@ -17,10 +17,10 @@ use serde::Serialize;
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Snapshot {
|
||||
/// The id of the commit that represents the snapshot
|
||||
#[serde(rename = "id", with = "crate::serde::oid")]
|
||||
#[serde(rename = "id", with = "gitbutler_core::serde::oid")]
|
||||
pub commit_id: git2::Oid,
|
||||
/// Snapshot creation time in seconds from Unix epoch seconds, based on a commit as `commit_id`.
|
||||
#[serde(serialize_with = "crate::serde::as_time_seconds_from_unix_epoch")]
|
||||
#[serde(serialize_with = "gitbutler_core::serde::as_time_seconds_from_unix_epoch")]
|
||||
pub created_at: git2::Time,
|
||||
/// The number of working directory lines added in the snapshot
|
||||
pub lines_added: usize,
|
@ -1,7 +1,7 @@
|
||||
pub mod entry;
|
||||
mod oplog;
|
||||
pub mod oplog;
|
||||
mod reflog;
|
||||
mod snapshot;
|
||||
pub mod snapshot;
|
||||
mod state;
|
||||
|
||||
/// The name of the file holding our state, useful for watching for changes.
|
@ -9,11 +9,11 @@ use std::{fs, path::PathBuf};
|
||||
use anyhow::Result;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::git::diff::FileDiff;
|
||||
use crate::virtual_branches::{
|
||||
use gitbutler_core::git::diff::FileDiff;
|
||||
use gitbutler_core::virtual_branches::{
|
||||
Branch, GITBUTLER_INTEGRATION_COMMIT_AUTHOR_EMAIL, GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME,
|
||||
};
|
||||
use crate::{git::diff::hunks_by_filepath, git::RepositoryExt, projects::Project};
|
||||
use gitbutler_core::{git::diff::hunks_by_filepath, git::RepositoryExt, projects::Project};
|
||||
|
||||
use super::{
|
||||
entry::{OperationKind, Snapshot, SnapshotDetails, Trailer},
|
||||
@ -41,11 +41,93 @@ const SNAPSHOT_FILE_LIMIT_BYTES: u64 = 32 * 1024 * 1024;
|
||||
/// │ └── tree (subtree)
|
||||
/// └── virtual_branches.toml
|
||||
/// ```
|
||||
impl Project {
|
||||
pub trait Oplog {
|
||||
/// Prepares a snapshot of the current state of the working directory as well as GitButler data.
|
||||
/// Returns a tree hash of the snapshot. The snapshot is not discoverable until it is committed with [`commit_snapshot`](Self::commit_snapshot())
|
||||
/// If there are files that are untracked and larger than `SNAPSHOT_FILE_LIMIT_BYTES`, they are excluded from snapshot creation and restoring.
|
||||
pub fn prepare_snapshot(&self) -> Result<git2::Oid> {
|
||||
fn prepare_snapshot(&self) -> Result<git2::Oid>;
|
||||
|
||||
/// Commits the snapshot tree that is created with the [`prepare_snapshot`](Self::prepare_snapshot) method,
|
||||
/// which yielded the `snapshot_tree_id` for the entire snapshot state.
|
||||
/// Use `details` to provide metadata about the snapshot.
|
||||
///
|
||||
/// Committing it makes the snapshot discoverable in [`list_snapshots`](Self::list_snapshots) as well as
|
||||
/// restorable with [`restore_snapshot`](Self::restore_snapshot).
|
||||
///
|
||||
/// Returns `Some(snapshot_commit_id)` if it was created or `None` if nothing changed between the previous oplog
|
||||
/// commit and the current one (after comparing trees).
|
||||
fn commit_snapshot(
|
||||
&self,
|
||||
snapshot_tree_id: git2::Oid,
|
||||
details: SnapshotDetails,
|
||||
) -> Result<Option<git2::Oid>>;
|
||||
|
||||
/// Creates a snapshot of the current state of the working directory as well as GitButler data.
|
||||
/// This is a convenience method that combines [`prepare_snapshot`](Self::prepare_snapshot) and
|
||||
/// [`commit_snapshot`](Self::commit_snapshot).
|
||||
///
|
||||
/// Returns `Some(snapshot_commit_id)` if it was created or `None` if nothing changed between the previous oplog
|
||||
/// commit and the current one (after comparing trees).
|
||||
///
|
||||
/// Note that errors in snapshot creation is typically ignored, so we want to learn about them.
|
||||
fn create_snapshot(&self, details: SnapshotDetails) -> Result<Option<git2::Oid>>;
|
||||
|
||||
/// Lists the snapshots that have been created for the given repository, up to the given limit,
|
||||
/// and with the most recent snapshot first, and at the end of the vec.
|
||||
///
|
||||
/// Use `oplog_commit_id` if the traversal root for snapshot discovery should be the specified commit, which
|
||||
/// is usually obtained from a previous iteration. Useful along with `limit` to allow starting where the iteration
|
||||
/// left off. Note that the `oplog_commit_id` is always returned as first item in the result vec.
|
||||
///
|
||||
/// 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,
|
||||
oplog_commit_id: Option<git2::Oid>,
|
||||
) -> Result<Vec<Snapshot>>;
|
||||
|
||||
/// Reverts to a previous state of the working directory, virtual branches and commits.
|
||||
/// The provided `snapshot_commit_id` must refer to a valid snapshot commit, as returned by [`create_snapshot`](Self::create_snapshot).
|
||||
/// Upon success, a new snapshot is created representing the state right before this call.
|
||||
///
|
||||
/// 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, snapshot_commit_id: git2::Oid) -> Result<Option<git2::Oid>>;
|
||||
|
||||
/// 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
|
||||
///
|
||||
/// Use `check_if_last_snapshot_older_than` as a way to control if the check should be performed at all, i.e.
|
||||
/// if this is 10s but the last snapshot was done 9s ago, no check if performed and the return value is `false`.
|
||||
///
|
||||
/// This implementation returns `true` on the following conditions:
|
||||
/// - Head is pointing to the integration branch.
|
||||
/// - 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, check_if_last_snapshot_older_than: Duration) -> 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: git2::Oid) -> Result<HashMap<PathBuf, FileDiff>>;
|
||||
|
||||
/// Gets the sha of the last snapshot commit if present.
|
||||
fn oplog_head(&self) -> Result<Option<git2::Oid>>;
|
||||
}
|
||||
|
||||
impl Oplog for Project {
|
||||
fn prepare_snapshot(&self) -> Result<git2::Oid> {
|
||||
let worktree_dir = self.path.as_path();
|
||||
let repo = git2::Repository::open(worktree_dir)?;
|
||||
|
||||
@ -162,16 +244,7 @@ impl Project {
|
||||
Ok(tree_id)
|
||||
}
|
||||
|
||||
/// Commits the snapshot tree that is created with the [`prepare_snapshot`](Self::prepare_snapshot) method,
|
||||
/// which yielded the `snapshot_tree_id` for the entire snapshot state.
|
||||
/// Use `details` to provide metadata about the snapshot.
|
||||
///
|
||||
/// Committing it makes the snapshot discoverable in [`list_snapshots`](Self::list_snapshots) as well as
|
||||
/// restorable with [`restore_snapshot`](Self::restore_snapshot).
|
||||
///
|
||||
/// Returns `Some(snapshot_commit_id)` if it was created or `None` if nothing changed between the previous oplog
|
||||
/// commit and the current one (after comparing trees).
|
||||
pub fn commit_snapshot(
|
||||
fn commit_snapshot(
|
||||
&self,
|
||||
snapshot_tree_id: git2::Oid,
|
||||
details: SnapshotDetails,
|
||||
@ -212,31 +285,13 @@ impl Project {
|
||||
Ok(Some(snapshot_commit_id))
|
||||
}
|
||||
|
||||
/// Creates a snapshot of the current state of the working directory as well as GitButler data.
|
||||
/// This is a convenience method that combines [`prepare_snapshot`](Self::prepare_snapshot) and
|
||||
/// [`commit_snapshot`](Self::commit_snapshot).
|
||||
///
|
||||
/// Returns `Some(snapshot_commit_id)` if it was created or `None` if nothing changed between the previous oplog
|
||||
/// commit and the current one (after comparing trees).
|
||||
///
|
||||
/// Note that errors in snapshot creation is typically ignored, so we want to learn about them.
|
||||
#[instrument(skip(details), err(Debug))]
|
||||
pub fn create_snapshot(&self, details: SnapshotDetails) -> Result<Option<git2::Oid>> {
|
||||
fn create_snapshot(&self, details: SnapshotDetails) -> Result<Option<git2::Oid>> {
|
||||
let tree_id = self.prepare_snapshot()?;
|
||||
self.commit_snapshot(tree_id, details)
|
||||
}
|
||||
|
||||
/// Lists the snapshots that have been created for the given repository, up to the given limit,
|
||||
/// and with the most recent snapshot first, and at the end of the vec.
|
||||
///
|
||||
/// Use `oplog_commit_id` if the traversal root for snapshot discovery should be the specified commit, which
|
||||
/// is usually obtained from a previous iteration. Useful along with `limit` to allow starting where the iteration
|
||||
/// left off. Note that the `oplog_commit_id` is always returned as first item in the result vec.
|
||||
///
|
||||
/// 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(
|
||||
fn list_snapshots(
|
||||
&self,
|
||||
limit: usize,
|
||||
oplog_commit_id: Option<git2::Oid>,
|
||||
@ -340,18 +395,7 @@ impl Project {
|
||||
Ok(snapshots)
|
||||
}
|
||||
|
||||
/// Reverts to a previous state of the working directory, virtual branches and commits.
|
||||
/// The provided `snapshot_commit_id` must refer to a valid snapshot commit, as returned by [`create_snapshot`](Self::create_snapshot).
|
||||
/// Upon success, a new snapshot is created representing the state right before this call.
|
||||
///
|
||||
/// 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, snapshot_commit_id: git2::Oid) -> Result<Option<git2::Oid>> {
|
||||
fn restore_snapshot(&self, snapshot_commit_id: git2::Oid) -> Result<Option<git2::Oid>> {
|
||||
let worktree_dir = self.path.as_path();
|
||||
let repo = git2::Repository::open(worktree_dir)?;
|
||||
|
||||
@ -501,24 +545,7 @@ impl Project {
|
||||
self.commit_snapshot(before_restore_snapshot_tree_id, details)
|
||||
}
|
||||
|
||||
/// 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
|
||||
///
|
||||
/// Use `check_if_last_snapshot_older_than` as a way to control if the check should be performed at all, i.e.
|
||||
/// if this is 10s but the last snapshot was done 9s ago, no check if performed and the return value is `false`.
|
||||
///
|
||||
/// This implementation returns `true` on the following conditions:
|
||||
/// - Head is pointing to the integration branch.
|
||||
/// - 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,
|
||||
check_if_last_snapshot_older_than: Duration,
|
||||
) -> Result<bool> {
|
||||
fn should_auto_snapshot(&self, check_if_last_snapshot_older_than: Duration) -> Result<bool> {
|
||||
let last_snapshot_time = OplogHandle::new(&self.gb_dir()).modified_at()?;
|
||||
if last_snapshot_time.elapsed()? <= check_if_last_snapshot_older_than {
|
||||
return Ok(false);
|
||||
@ -531,10 +558,7 @@ impl Project {
|
||||
Ok(lines_since_snapshot(self, &repo)? > self.snapshot_lines_threshold())
|
||||
}
|
||||
|
||||
/// 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: git2::Oid) -> Result<HashMap<PathBuf, FileDiff>> {
|
||||
fn snapshot_diff(&self, sha: git2::Oid) -> Result<HashMap<PathBuf, FileDiff>> {
|
||||
let worktree_dir = self.path.as_path();
|
||||
let repo = git2::Repository::init(worktree_dir)?;
|
||||
|
||||
@ -567,7 +591,7 @@ impl Project {
|
||||
}
|
||||
|
||||
/// Gets the sha of the last snapshot commit if present.
|
||||
pub fn oplog_head(&self) -> Result<Option<git2::Oid>> {
|
||||
fn oplog_head(&self) -> Result<Option<git2::Oid>> {
|
||||
let oplog_state = OplogHandle::new(&self.gb_dir());
|
||||
oplog_state.oplog_head()
|
||||
}
|
||||
@ -783,7 +807,7 @@ fn tree_from_applied_vbranches(
|
||||
.find_blob(vb_toml_entry.id())
|
||||
.context("failed to convert virtual_branches tree entry to blob")?;
|
||||
|
||||
let vbs_from_toml: crate::virtual_branches::VirtualBranchesState =
|
||||
let vbs_from_toml: gitbutler_core::virtual_branches::VirtualBranchesState =
|
||||
toml::from_str(from_utf8(vb_toml_blob.content())?)?;
|
||||
let applied_branch_trees: Vec<git2::Oid> = vbs_from_toml
|
||||
.branches
|
@ -1,10 +1,10 @@
|
||||
use crate::{
|
||||
use anyhow::{Context, Result};
|
||||
use gitbutler_core::{
|
||||
fs::write,
|
||||
virtual_branches::{
|
||||
GITBUTLER_INTEGRATION_COMMIT_AUTHOR_EMAIL, GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME,
|
||||
},
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use gix::config::tree::Key;
|
||||
use std::path::Path;
|
||||
|
@ -1,17 +1,51 @@
|
||||
use anyhow::Result;
|
||||
use std::vec;
|
||||
|
||||
use crate::projects::Project;
|
||||
use crate::{
|
||||
ops::entry::{OperationKind, SnapshotDetails},
|
||||
virtual_branches::{branch::BranchUpdateRequest, Branch},
|
||||
entry::{OperationKind, SnapshotDetails},
|
||||
oplog::Oplog,
|
||||
};
|
||||
use gitbutler_core::projects::Project;
|
||||
use gitbutler_core::virtual_branches::{branch::BranchUpdateRequest, Branch};
|
||||
|
||||
use super::entry::Trailer;
|
||||
|
||||
pub trait Snapshot {
|
||||
fn snapshot_branch_unapplied(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
result: Result<&git2::Branch, &anyhow::Error>,
|
||||
) -> anyhow::Result<()>;
|
||||
|
||||
fn snapshot_commit_undo(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
result: Result<&(), &anyhow::Error>,
|
||||
commit_sha: git2::Oid,
|
||||
) -> anyhow::Result<()>;
|
||||
|
||||
fn snapshot_commit_creation(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
error: Option<&anyhow::Error>,
|
||||
commit_message: String,
|
||||
sha: Option<git2::Oid>,
|
||||
) -> anyhow::Result<()>;
|
||||
|
||||
fn snapshot_branch_creation(&self, branch_name: String) -> anyhow::Result<()>;
|
||||
fn snapshot_branch_deletion(&self, branch_name: String) -> anyhow::Result<()>;
|
||||
fn snapshot_branch_update(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
old_branch: &Branch,
|
||||
update: &BranchUpdateRequest,
|
||||
error: Option<&anyhow::Error>,
|
||||
) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
/// Snapshot functionality
|
||||
impl Project {
|
||||
pub fn snapshot_branch_unapplied(
|
||||
impl Snapshot for Project {
|
||||
fn snapshot_branch_unapplied(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
result: Result<&git2::Branch, &anyhow::Error>,
|
||||
@ -22,7 +56,7 @@ impl Project {
|
||||
self.commit_snapshot(snapshot_tree, details)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn snapshot_commit_undo(
|
||||
fn snapshot_commit_undo(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
result: Result<&(), &anyhow::Error>,
|
||||
@ -34,7 +68,7 @@ impl Project {
|
||||
self.commit_snapshot(snapshot_tree, details)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn snapshot_commit_creation(
|
||||
fn snapshot_commit_creation(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
error: Option<&anyhow::Error>,
|
||||
@ -60,7 +94,7 @@ impl Project {
|
||||
self.commit_snapshot(snapshot_tree, details)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn snapshot_branch_creation(&self, branch_name: String) -> anyhow::Result<()> {
|
||||
fn snapshot_branch_creation(&self, branch_name: String) -> anyhow::Result<()> {
|
||||
let details =
|
||||
SnapshotDetails::new(OperationKind::CreateBranch).with_trailers(vec![Trailer {
|
||||
key: "name".to_string(),
|
||||
@ -69,7 +103,7 @@ impl Project {
|
||||
self.create_snapshot(details)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn snapshot_branch_deletion(&self, branch_name: String) -> anyhow::Result<()> {
|
||||
fn snapshot_branch_deletion(&self, branch_name: String) -> anyhow::Result<()> {
|
||||
let details =
|
||||
SnapshotDetails::new(OperationKind::DeleteBranch).with_trailers(vec![Trailer {
|
||||
key: "name".to_string(),
|
||||
@ -79,7 +113,7 @@ impl Project {
|
||||
self.create_snapshot(details)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn snapshot_branch_update(
|
||||
fn snapshot_branch_update(
|
||||
&self,
|
||||
snapshot_tree: git2::Oid,
|
||||
old_branch: &Branch,
|
@ -4,7 +4,7 @@ use std::{
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
use crate::fs::read_toml_file_or_default;
|
||||
use gitbutler_core::fs::read_toml_file_or_default;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use super::OPLOG_FILE_NAME;
|
||||
@ -26,7 +26,7 @@ fn unix_epoch() -> SystemTime {
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Oplog {
|
||||
/// This is the sha of the last oplog commit
|
||||
#[serde(with = "crate::serde::oid_opt", default)]
|
||||
#[serde(with = "gitbutler_core::serde::oid_opt", default)]
|
||||
pub head_sha: Option<git2::Oid>,
|
||||
/// The time when the last snapshot was created. Seconds since Epoch
|
||||
#[serde(
|
||||
@ -92,6 +92,6 @@ impl OplogHandle {
|
||||
|
||||
fn write_file(&self, mut oplog: Oplog) -> Result<()> {
|
||||
oplog.modified_at = SystemTime::now();
|
||||
crate::fs::write(&self.file_path, toml::to_string(&oplog)?)
|
||||
gitbutler_core::fs::write(&self.file_path, toml::to_string(&oplog)?)
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
mod trailer {
|
||||
use gitbutler_core::ops::entry::Trailer;
|
||||
use gitbutler_oplog::entry::Trailer;
|
||||
// use gitbutler_core::ops::entry::Trailer;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
@ -28,7 +29,7 @@ mod trailer {
|
||||
}
|
||||
|
||||
mod version {
|
||||
use gitbutler_core::ops::entry::{Trailer, Version};
|
||||
use gitbutler_oplog::entry::{Trailer, Version};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
@ -57,7 +58,7 @@ mod version {
|
||||
}
|
||||
|
||||
mod operation_kind {
|
||||
use gitbutler_core::ops::entry::{OperationKind, SnapshotDetails, Trailer, Version};
|
||||
use gitbutler_oplog::entry::{OperationKind, SnapshotDetails, Trailer, Version};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
@ -90,7 +91,7 @@ mod operation_kind {
|
||||
}
|
||||
|
||||
mod snapshot_details {
|
||||
use gitbutler_core::ops::entry::{OperationKind, Snapshot, SnapshotDetails, Trailer, Version};
|
||||
use gitbutler_oplog::entry::{OperationKind, Snapshot, SnapshotDetails, Trailer, Version};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
@ -11,3 +11,4 @@ tracing = "0.1.40"
|
||||
itertools = "0.13"
|
||||
git2.workspace = true
|
||||
gitbutler-core.workspace = true
|
||||
gitbutler-oplog.workspace = true
|
||||
|
@ -8,6 +8,7 @@ use gitbutler_core::{
|
||||
projects::{self, CodePushState},
|
||||
users,
|
||||
};
|
||||
use gitbutler_oplog::oplog::Oplog;
|
||||
use itertools::Itertools;
|
||||
|
||||
pub async fn sync_with_gitbutler(
|
||||
|
@ -49,6 +49,7 @@ tracing-subscriber = "0.3.17"
|
||||
gitbutler-core.workspace = true
|
||||
gitbutler-watcher.workspace = true
|
||||
gitbutler-branch.workspace = true
|
||||
gitbutler-oplog.workspace = true
|
||||
open = "5"
|
||||
|
||||
[dependencies.tauri]
|
||||
|
@ -1,10 +1,9 @@
|
||||
use crate::error::Error;
|
||||
use anyhow::Context;
|
||||
use gitbutler_core::git::diff::FileDiff;
|
||||
use gitbutler_core::{
|
||||
ops::entry::Snapshot,
|
||||
projects::{self, ProjectId},
|
||||
};
|
||||
use gitbutler_core::projects::{self, ProjectId};
|
||||
use gitbutler_oplog::entry::Snapshot;
|
||||
use gitbutler_oplog::oplog::Oplog;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use tauri::Manager;
|
||||
|
@ -12,6 +12,7 @@ doctest = false
|
||||
gitbutler-core.workspace = true
|
||||
gitbutler-branch.workspace = true
|
||||
gitbutler-sync.workspace = true
|
||||
gitbutler-oplog.workspace = true
|
||||
thiserror.workspace = true
|
||||
anyhow = "1.0.86"
|
||||
futures = "0.3.30"
|
||||
|
@ -4,9 +4,9 @@ use std::time::Duration;
|
||||
|
||||
use crate::events::InternalEvent;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use gitbutler_core::ops::OPLOG_FILE_NAME;
|
||||
use gitbutler_core::projects::ProjectId;
|
||||
use gitbutler_notify_debouncer::{new_debouncer, Debouncer, NoCache};
|
||||
use gitbutler_oplog::OPLOG_FILE_NAME;
|
||||
use notify::RecommendedWatcher;
|
||||
use notify::Watcher;
|
||||
use tokio::task;
|
||||
|
@ -4,9 +4,12 @@ use std::sync::Arc;
|
||||
use anyhow::{Context, Result};
|
||||
use gitbutler_branch::VirtualBranches;
|
||||
use gitbutler_core::error::Marker;
|
||||
use gitbutler_core::ops::entry::{OperationKind, SnapshotDetails};
|
||||
use gitbutler_core::projects::ProjectId;
|
||||
use gitbutler_core::{assets, git, project_repository, projects, users};
|
||||
use gitbutler_oplog::{
|
||||
entry::{OperationKind, SnapshotDetails},
|
||||
oplog::Oplog,
|
||||
};
|
||||
use gitbutler_sync::cloud::sync_with_gitbutler;
|
||||
use tracing::instrument;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user