mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-29 20:43:37 +03:00
fix: auto snapshotting on changed lines of code
Compare against the last snapshot
This commit is contained in:
parent
66a21e8ec5
commit
c59767651d
@ -29,7 +29,6 @@ pub mod path;
|
||||
pub mod project_repository;
|
||||
pub mod projects;
|
||||
pub mod reader;
|
||||
pub mod repo;
|
||||
pub mod sessions;
|
||||
pub mod snapshots;
|
||||
pub mod ssh;
|
||||
|
@ -1,18 +0,0 @@
|
||||
use anyhow::Result;
|
||||
|
||||
/// The GbRepository trait provides methods which are building blocks for Gitbutler functionality.
|
||||
pub trait GbRepository {
|
||||
/// Returns the number of uncommitted lines of code (added plus removed) in the repository. Included untracked files.
|
||||
fn changed_lines_count(&self) -> Result<usize>;
|
||||
}
|
||||
|
||||
impl GbRepository for git2::Repository {
|
||||
fn changed_lines_count(&self) -> Result<usize> {
|
||||
let head_tree = self.head()?.peel_to_commit()?.tree()?;
|
||||
let mut opts = git2::DiffOptions::new();
|
||||
opts.include_untracked(true);
|
||||
let diff = self.diff_tree_to_workdir_with_index(Some(&head_tree), Some(&mut opts));
|
||||
let stats = diff?.stats()?;
|
||||
Ok(stats.deletions() + stats.insertions())
|
||||
}
|
||||
}
|
@ -237,6 +237,38 @@ pub fn restore(project: &Project, sha: String) -> Result<Option<String>> {
|
||||
create(project, details)
|
||||
}
|
||||
|
||||
/// Returns the number of uncommitted lines of code (added plus removed) since the last snapshot. Included untracked files.
|
||||
pub fn changed_lines_count(project: &Project) -> Result<usize> {
|
||||
let repo_path = project.path.as_path();
|
||||
let repo = git2::Repository::init(repo_path)?;
|
||||
|
||||
// Exclude files that are larger than the limit (eg. database.sql which may never be intended to be committed)
|
||||
let files_to_exclude = get_exclude_list(&repo)?;
|
||||
// In-memory, libgit2 internal ignore rule
|
||||
repo.add_ignore_rule(&files_to_exclude)?;
|
||||
|
||||
let oplog_state = OplogHandle::new(&project.gb_dir());
|
||||
let head_sha = oplog_state.get_oplog_head()?;
|
||||
if head_sha.is_none() {
|
||||
return Ok(0);
|
||||
}
|
||||
let head_sha = head_sha.unwrap();
|
||||
|
||||
let commit = repo.find_commit(git2::Oid::from_str(&head_sha)?)?;
|
||||
let head_tree = commit.tree()?;
|
||||
|
||||
let wd_tree_entry = head_tree
|
||||
.get_name("workdir")
|
||||
.ok_or(anyhow!("failed to get workdir tree entry"))?;
|
||||
let wd_tree = repo.find_tree(wd_tree_entry.id())?;
|
||||
|
||||
let mut opts = git2::DiffOptions::new();
|
||||
opts.include_untracked(true);
|
||||
let diff = repo.diff_tree_to_workdir_with_index(Some(&wd_tree), Some(&mut opts));
|
||||
let stats = diff?.stats()?;
|
||||
Ok(stats.deletions() + stats.insertions())
|
||||
}
|
||||
|
||||
fn restore_conflicts_tree(
|
||||
snapshot_tree: &git2::Tree,
|
||||
repo: &git2::Repository,
|
||||
|
@ -8,7 +8,6 @@ use std::{path, time};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use gitbutler_core::projects::ProjectId;
|
||||
use gitbutler_core::repo::GbRepository;
|
||||
use gitbutler_core::sessions::SessionId;
|
||||
use gitbutler_core::snapshots::entry::{OperationType, SnapshotDetails, Trailer};
|
||||
use gitbutler_core::snapshots::snapshot;
|
||||
@ -17,7 +16,6 @@ use gitbutler_core::{
|
||||
assets, deltas, gb_repository, git, project_repository, projects, reader, sessions, users,
|
||||
virtual_branches,
|
||||
};
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::instrument;
|
||||
|
||||
use super::{events, Change};
|
||||
@ -43,9 +41,6 @@ pub struct Handler {
|
||||
/// A function to send events - decoupled from app-handle for testing purposes.
|
||||
#[allow(clippy::type_complexity)]
|
||||
send_event: Arc<dyn Fn(Change) -> Result<()> + Send + Sync + 'static>,
|
||||
|
||||
// The number of changed lines since the value was last reset
|
||||
changed_lines_count: Arc<Mutex<usize>>,
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
@ -70,7 +65,6 @@ impl Handler {
|
||||
sessions_db,
|
||||
deltas_db,
|
||||
send_event: Arc::new(send_event),
|
||||
changed_lines_count: Arc::new(Mutex::new(0)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,32 +289,23 @@ impl Handler {
|
||||
let this = self.clone();
|
||||
move || this.calculate_deltas(paths, project_id)
|
||||
});
|
||||
let changed_lines_before = *self.changed_lines_count.lock().await;
|
||||
// Create a snapshot every time there are more than 20 new lines of code
|
||||
// Create a snapshot every time there are more than a configurable number of new lines of code (default 20)
|
||||
let handle_snapshots = tokio::task::spawn_blocking({
|
||||
let this = self.clone();
|
||||
move || this.maybe_create_snapshot(project_id, changed_lines_before, paths_string)
|
||||
move || this.maybe_create_snapshot(project_id, paths_string)
|
||||
});
|
||||
// Set changed lines count to the newly observed value
|
||||
*self.changed_lines_count.lock().await = handle_snapshots.await??;
|
||||
self.calculate_virtual_branches(project_id).await?;
|
||||
let _ = handle_snapshots.await;
|
||||
calc_deltas.await??;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn maybe_create_snapshot(
|
||||
&self,
|
||||
project_id: ProjectId,
|
||||
changed_lines_before: usize,
|
||||
paths: String,
|
||||
) -> anyhow::Result<usize> {
|
||||
fn maybe_create_snapshot(&self, project_id: ProjectId, paths: String) -> anyhow::Result<()> {
|
||||
let project = self
|
||||
.projects
|
||||
.get(&project_id)
|
||||
.context("failed to get project")?;
|
||||
let repo_path = project.path.as_path();
|
||||
let repo = git2::Repository::init(repo_path)?;
|
||||
let changed_lines = repo.changed_lines_count()? - changed_lines_before;
|
||||
let changed_lines = snapshot::changed_lines_count(&project)?;
|
||||
if changed_lines > project.snapshot_lines_threshold {
|
||||
let details = SnapshotDetails {
|
||||
version: Default::default(),
|
||||
@ -334,7 +319,7 @@ impl Handler {
|
||||
};
|
||||
snapshot::create(&project, details)?;
|
||||
}
|
||||
Ok(changed_lines)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn git_file_change(
|
||||
|
Loading…
Reference in New Issue
Block a user