mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-29 20:43:37 +03:00
add an enpoint for getting the snapshot diff
This commit is contained in:
parent
2006511a80
commit
58c124627a
@ -218,7 +218,7 @@ pub fn without_large_files(
|
||||
/// `repository` should be `None` if there is no reason to access the workdir, which it will do to
|
||||
/// keep the binary data in the object database, which otherwise would be lost to the system
|
||||
/// (it's not reconstructable from the delta, or it's not attempted).
|
||||
fn hunks_by_filepath(repo: Option<&Repository>, diff: &git2::Diff) -> Result<DiffByPathMap> {
|
||||
pub fn hunks_by_filepath(repo: Option<&Repository>, diff: &git2::Diff) -> Result<DiffByPathMap> {
|
||||
enum LineOrHexHash<'a> {
|
||||
Line(Cow<'a, BStr>),
|
||||
HexHashOfBinaryBlob(String),
|
||||
|
@ -1,12 +1,14 @@
|
||||
use anyhow::anyhow;
|
||||
use git2::FileMode;
|
||||
use itertools::Itertools;
|
||||
use std::fs;
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::projects::Project;
|
||||
use crate::git::diff::FileDiff;
|
||||
use crate::{git::diff::hunks_by_filepath, projects::Project};
|
||||
|
||||
use super::{
|
||||
entry::{OperationType, Snapshot, SnapshotDetails, Trailer},
|
||||
@ -54,6 +56,10 @@ pub trait Oplog {
|
||||
///
|
||||
/// If there are no snapshots, 0 is returned.
|
||||
fn lines_since_snapshot(&self) -> Result<usize>;
|
||||
/// 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>>;
|
||||
}
|
||||
|
||||
impl Oplog for Project {
|
||||
@ -324,6 +330,46 @@ impl Oplog for Project {
|
||||
let stats = diff?.stats()?;
|
||||
Ok(stats.deletions() + stats.insertions())
|
||||
}
|
||||
|
||||
fn snapshot_diff(&self, sha: String) -> Result<HashMap<PathBuf, FileDiff>> {
|
||||
let repo_path = self.path.as_path();
|
||||
let repo = git2::Repository::init(repo_path)?;
|
||||
|
||||
let commit = repo.find_commit(git2::Oid::from_str(&sha)?)?;
|
||||
// Top tree
|
||||
let tree = commit.tree()?;
|
||||
let old_tree = commit.parent(0)?.tree()?;
|
||||
|
||||
let wd_tree_entry = tree
|
||||
.get_name("workdir")
|
||||
.ok_or(anyhow!("failed to get workdir tree entry"))?;
|
||||
let old_wd_tree_entry = old_tree
|
||||
.get_name("workdir")
|
||||
.ok_or(anyhow!("failed to get old workdir tree entry"))?;
|
||||
|
||||
// workdir tree
|
||||
let wd_tree = repo.find_tree(wd_tree_entry.id())?;
|
||||
let old_wd_tree = repo.find_tree(old_wd_tree_entry.id())?;
|
||||
|
||||
// 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 mut diff_opts = git2::DiffOptions::new();
|
||||
diff_opts
|
||||
.recurse_untracked_dirs(true)
|
||||
.include_untracked(true)
|
||||
.show_binary(true)
|
||||
.ignore_submodules(true)
|
||||
.show_untracked_content(true);
|
||||
|
||||
let diff =
|
||||
repo.diff_tree_to_tree(Some(&old_wd_tree), Some(&wd_tree), Some(&mut diff_opts))?;
|
||||
|
||||
let hunks = hunks_by_filepath(None, &diff)?;
|
||||
Ok(hunks)
|
||||
}
|
||||
}
|
||||
|
||||
fn restore_conflicts_tree(
|
||||
|
@ -234,6 +234,7 @@ fn main() {
|
||||
virtual_branches::commands::move_commit,
|
||||
undo::list_snapshots,
|
||||
undo::restore_snapshot,
|
||||
undo::snapshot_diff,
|
||||
menu::menu_item_set_enabled,
|
||||
keys::commands::get_public_key,
|
||||
github::commands::init_device_oauth,
|
||||
|
@ -1,9 +1,12 @@
|
||||
use crate::error::Error;
|
||||
use anyhow::Context;
|
||||
use gitbutler_core::git::diff::FileDiff;
|
||||
use gitbutler_core::{
|
||||
ops::{entry::Snapshot, oplog::Oplog},
|
||||
projects::{self, ProjectId},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use tauri::Manager;
|
||||
use tracing::instrument;
|
||||
|
||||
@ -37,3 +40,18 @@ pub async fn restore_snapshot(
|
||||
project.restore_snapshot(sha)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command(async)]
|
||||
#[instrument(skip(handle), err(Debug))]
|
||||
pub async fn snapshot_diff(
|
||||
handle: tauri::AppHandle,
|
||||
project_id: ProjectId,
|
||||
sha: String,
|
||||
) -> Result<HashMap<PathBuf, FileDiff>, Error> {
|
||||
let project = handle
|
||||
.state::<projects::Controller>()
|
||||
.get(&project_id)
|
||||
.context("failed to get project")?;
|
||||
let diff = project.snapshot_diff(sha)?;
|
||||
Ok(diff)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user