From 34d12fb1e6c9c6f9dfa4ab4145ee329f3d8d0104 Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Sun, 28 Apr 2024 20:05:46 +0200 Subject: [PATCH 1/4] add snapshotting tests --- .../gitbutler-core/src/snapshots/snapshot.rs | 87 ++++++++++++++++++- crates/gitbutler-tauri/src/snapshots.rs | 2 +- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/crates/gitbutler-core/src/snapshots/snapshot.rs b/crates/gitbutler-core/src/snapshots/snapshot.rs index 5978d7a03..189a21409 100644 --- a/crates/gitbutler-core/src/snapshots/snapshot.rs +++ b/crates/gitbutler-core/src/snapshots/snapshot.rs @@ -94,7 +94,7 @@ pub fn create(project: &Project, details: SnapshotDetails) -> Result<()> { /// An alternative way of retrieving the snapshots would be to manually the oplog head `git log ` available in `.git/gitbutler/oplog.toml`. /// /// If there are no snapshots, an empty list is returned. -pub fn list(project: Project, limit: usize) -> Result> { +pub fn list(project: &Project, limit: usize) -> Result> { let repo_path = project.path.as_path(); let repo = git2::Repository::init(repo_path)?; @@ -178,3 +178,88 @@ pub fn restore(project: &Project, sha: String) -> Result<()> { Ok(()) } + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use super::*; + use tempfile::tempdir; + + #[test] + fn test_create_and_restore() { + let dir = tempdir().unwrap(); + let repo = git2::Repository::init(dir.path()).unwrap(); + let file_path = dir.path().join("1.txt"); + std::fs::write(file_path, "test").unwrap(); + let file_path = dir.path().join("2.txt"); + std::fs::write(file_path, "test").unwrap(); + let mut index = repo.index().unwrap(); + index.add_path(&PathBuf::from("1.txt")).unwrap(); + index.add_path(&PathBuf::from("2.txt")).unwrap(); + let oid = index.write_tree().unwrap(); + let name = "Your Name"; + let email = "your.email@example.com"; + let signature = git2::Signature::now(name, email).unwrap(); + let initial_commit = repo + .commit( + Some("HEAD"), + &signature, + &signature, + "initial commit", + &repo.find_tree(oid).unwrap(), + &[], + ) + .unwrap(); + + // create a new branch called "gitbutler/integraion" from initial commit + repo.branch( + "gitbutler/integration", + &repo.find_commit(initial_commit).unwrap(), + false, + ) + .unwrap(); + + let project = Project { + path: dir.path().to_path_buf(), + enable_snapshots: Some(true), + ..Default::default() + }; + // create gb_dir folder + std::fs::create_dir_all(project.gb_dir()).unwrap(); + + let vb_state = VirtualBranchesHandle::new(&project.gb_dir()); + + let target_sha = initial_commit.to_string(); + let default_target = crate::virtual_branches::target::Target { + branch: crate::git::RemoteRefname::new("origin", "main"), + remote_url: Default::default(), + sha: crate::git::Oid::from_str(&target_sha).unwrap(), + }; + vb_state.set_default_target(default_target).unwrap(); + + // create a snapshot + create(&project, SnapshotDetails::new(OperationType::CreateCommit)).unwrap(); + let snapshots = list(&project, 100).unwrap(); + + let file_path = dir.path().join("1.txt"); + std::fs::write(file_path, "TEST").unwrap(); + let file_path = dir.path().join("2.txt"); + std::fs::remove_file(file_path).unwrap(); + let file_path = dir.path().join("3.txt"); + std::fs::write(file_path, "something_new").unwrap(); + // File 1 was modified, file 2 was deleted, file 3 was added + + restore(&project, snapshots.first().unwrap().id.clone()).unwrap(); + + let file_path = dir.path().join("1.txt"); + let file_lines = std::fs::read_to_string(file_path).unwrap(); + assert_eq!(file_lines, "test"); + let file_path = dir.path().join("2.txt"); + assert!(file_path.exists()); + let file_lines = std::fs::read_to_string(file_path).unwrap(); + assert_eq!(file_lines, "test"); + // let file_path = dir.path().join("3.txt"); + // assert!(!file_path.exists()); + } +} diff --git a/crates/gitbutler-tauri/src/snapshots.rs b/crates/gitbutler-tauri/src/snapshots.rs index 35f8a7760..0f0ee43ad 100644 --- a/crates/gitbutler-tauri/src/snapshots.rs +++ b/crates/gitbutler-tauri/src/snapshots.rs @@ -17,7 +17,7 @@ pub async fn list_snapshots( .state::() .get(&project_id) .context("failed to get project")?; - let snapshots = snapshot::list(project, limit)?; + let snapshots = snapshot::list(&project, limit)?; Ok(snapshots) } From 3be8dd444b65f9637d1fb29804b196843d435e9c Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Sun, 28 Apr 2024 20:08:47 +0200 Subject: [PATCH 2/4] fixes a snapshot restor bug where untracked files arent removed --- crates/gitbutler-core/src/snapshots/snapshot.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/gitbutler-core/src/snapshots/snapshot.rs b/crates/gitbutler-core/src/snapshots/snapshot.rs index 189a21409..1474edc64 100644 --- a/crates/gitbutler-core/src/snapshots/snapshot.rs +++ b/crates/gitbutler-core/src/snapshots/snapshot.rs @@ -153,6 +153,7 @@ pub fn restore(project: &Project, sha: String) -> Result<()> { // Define the checkout builder let mut checkout_builder = git2::build::CheckoutBuilder::new(); + checkout_builder.remove_untracked(true); checkout_builder.force(); // Checkout the tree repo.checkout_tree(tree.as_object(), Some(&mut checkout_builder))?; @@ -259,7 +260,7 @@ mod tests { assert!(file_path.exists()); let file_lines = std::fs::read_to_string(file_path).unwrap(); assert_eq!(file_lines, "test"); - // let file_path = dir.path().join("3.txt"); - // assert!(!file_path.exists()); + let file_path = dir.path().join("3.txt"); + assert!(!file_path.exists()); } } From 27ce10cdcf2dececd591b023426d5f9e89e4acea Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Sun, 28 Apr 2024 20:23:02 +0200 Subject: [PATCH 3/4] add test asserions for restoring virtual_branches.toml --- .../gitbutler-core/src/snapshots/snapshot.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/gitbutler-core/src/snapshots/snapshot.rs b/crates/gitbutler-core/src/snapshots/snapshot.rs index 1474edc64..1fccdc4fe 100644 --- a/crates/gitbutler-core/src/snapshots/snapshot.rs +++ b/crates/gitbutler-core/src/snapshots/snapshot.rs @@ -184,6 +184,8 @@ pub fn restore(project: &Project, sha: String) -> Result<()> { mod tests { use std::path::PathBuf; + use crate::virtual_branches::Branch; + use super::*; use tempfile::tempdir; @@ -237,20 +239,31 @@ mod tests { remote_url: Default::default(), sha: crate::git::Oid::from_str(&target_sha).unwrap(), }; - vb_state.set_default_target(default_target).unwrap(); + vb_state.set_default_target(default_target.clone()).unwrap(); // create a snapshot create(&project, SnapshotDetails::new(OperationType::CreateCommit)).unwrap(); let snapshots = list(&project, 100).unwrap(); + // Modify file 1, remove file 2, create file 3 let file_path = dir.path().join("1.txt"); std::fs::write(file_path, "TEST").unwrap(); let file_path = dir.path().join("2.txt"); std::fs::remove_file(file_path).unwrap(); let file_path = dir.path().join("3.txt"); std::fs::write(file_path, "something_new").unwrap(); - // File 1 was modified, file 2 was deleted, file 3 was added + // Create a fake branch in virtual_branches.toml + let id = crate::id::Id::from_str("9acb2a3b-cddf-47d7-b531-a7798978c237").unwrap(); + vb_state + .set_branch(Branch { + id, + ..Default::default() + }) + .unwrap(); + assert!(vb_state.get_branch(&id).is_ok()); + + // restore from the snapshot restore(&project, snapshots.first().unwrap().id.clone()).unwrap(); let file_path = dir.path().join("1.txt"); @@ -262,5 +275,7 @@ mod tests { assert_eq!(file_lines, "test"); let file_path = dir.path().join("3.txt"); assert!(!file_path.exists()); + // The fake branch is gone + assert!(vb_state.get_branch(&id).is_err()); } } From 7e11171211bfa06c9e15d7cc00b04e68b631e6ac Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Sun, 28 Apr 2024 20:38:34 +0200 Subject: [PATCH 4/4] fix: snapshot uses uses gitbutler as comitter --- crates/gitbutler-core/src/snapshots/snapshot.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/gitbutler-core/src/snapshots/snapshot.rs b/crates/gitbutler-core/src/snapshots/snapshot.rs index 1fccdc4fe..e32bc41f1 100644 --- a/crates/gitbutler-core/src/snapshots/snapshot.rs +++ b/crates/gitbutler-core/src/snapshots/snapshot.rs @@ -54,7 +54,9 @@ pub fn create(project: &Project, details: SnapshotDetails) -> Result<()> { let tree = repo.find_tree(tree_id)?; // Construct a new commit - let signature = repo.signature()?; + let name = "GitButler"; + let email = "gitbutler@gitbutler.com"; + let signature = git2::Signature::now(name, email).unwrap(); let new_commit_oid = repo.commit( None, &signature,