diff --git a/crates/gitbutler-core/src/git/branch.rs b/crates/gitbutler-core/src/git/branch.rs index 701d805be..2bae7ad4c 100644 --- a/crates/gitbutler-core/src/git/branch.rs +++ b/crates/gitbutler-core/src/git/branch.rs @@ -1,4 +1,4 @@ -use super::{Commit, Oid, Result, Tree}; +use super::{Commit, Oid, Result}; pub struct Branch<'repo> { branch: git2::Branch<'repo>, @@ -31,12 +31,8 @@ impl<'repo> Branch<'repo> { self.branch.get().name_bytes() } - pub fn peel_to_tree(&self) -> Result> { - self.branch - .get() - .peel_to_tree() - .map_err(Into::into) - .map(Into::into) + pub fn peel_to_tree(&self) -> Result> { + self.branch.get().peel_to_tree().map_err(Into::into) } pub fn peel_to_commit(&self) -> Result> { diff --git a/crates/gitbutler-core/src/git/commit.rs b/crates/gitbutler-core/src/git/commit.rs index c9fbe473f..34dfb6813 100644 --- a/crates/gitbutler-core/src/git/commit.rs +++ b/crates/gitbutler-core/src/git/commit.rs @@ -1,4 +1,4 @@ -use super::{Oid, Result, Signature, Tree}; +use super::{Oid, Result, Signature}; use bstr::BStr; #[derive(Debug)] @@ -35,8 +35,8 @@ impl<'repo> Commit<'repo> { self.commit.parent_count() } - pub fn tree(&self) -> Result> { - self.commit.tree().map(Into::into).map_err(Into::into) + pub fn tree(&self) -> Result> { + self.commit.tree().map_err(Into::into) } pub fn tree_id(&self) -> Oid { diff --git a/crates/gitbutler-core/src/git/diff.rs b/crates/gitbutler-core/src/git/diff.rs index 788ebdaa5..d99447de9 100644 --- a/crates/gitbutler-core/src/git/diff.rs +++ b/crates/gitbutler-core/src/git/diff.rs @@ -160,8 +160,8 @@ pub fn workdir(repository: &Repository, commit_oid: &git::Oid) -> Result Result { let mut diff_opts = git2::DiffOptions::new(); diff_opts diff --git a/crates/gitbutler-core/src/git/index.rs b/crates/gitbutler-core/src/git/index.rs index 8b0293bef..bfd8933fa 100644 --- a/crates/gitbutler-core/src/git/index.rs +++ b/crates/gitbutler-core/src/git/index.rs @@ -2,30 +2,12 @@ use std::path; use filetime::FileTime; -use super::{Error, Oid, Repository, Result, Tree}; +use super::{Oid, Repository, Result}; pub struct Index { index: git2::Index, } -impl TryFrom> for Index { - type Error = Error; - - fn try_from(value: Tree<'_>) -> std::result::Result { - Self::try_from(&value) - } -} - -impl TryFrom<&Tree<'_>> for Index { - type Error = Error; - - fn try_from(value: &Tree) -> Result { - let mut empty_index = Self::new()?; - empty_index.read_tree(value)?; - Ok(empty_index) - } -} - impl<'a> From<&'a mut Index> for &'a mut git2::Index { fn from(index: &'a mut Index) -> Self { &mut index.index @@ -62,10 +44,6 @@ impl Index { self.index.conflicts().map_err(Into::into) } - pub fn read_tree(&mut self, tree: &Tree) -> Result<()> { - self.index.read_tree(tree.into()).map_err(Into::into) - } - pub fn write_tree_to(&mut self, repo: &Repository) -> Result { self.index .write_tree_to(repo.into()) diff --git a/crates/gitbutler-core/src/git/mod.rs b/crates/gitbutler-core/src/git/mod.rs index fcabed881..88fb04428 100644 --- a/crates/gitbutler-core/src/git/mod.rs +++ b/crates/gitbutler-core/src/git/mod.rs @@ -42,3 +42,6 @@ pub use self::url::*; mod repository_ext; pub use repository_ext::*; + +mod tree_ext; +pub use tree_ext::*; diff --git a/crates/gitbutler-core/src/git/reference/mod.rs b/crates/gitbutler-core/src/git/reference/mod.rs index 27c360014..0ce3cd639 100644 --- a/crates/gitbutler-core/src/git/reference/mod.rs +++ b/crates/gitbutler-core/src/git/reference/mod.rs @@ -1,7 +1,7 @@ mod refname; pub use refname::{LocalRefname, Refname, RemoteRefname, VirtualRefname}; -use super::{Commit, Oid, Result, Tree}; +use super::{Commit, Oid, Result}; pub struct Reference<'repo> { reference: git2::Reference<'repo>, @@ -35,13 +35,6 @@ impl<'repo> Reference<'repo> { .map_err(Into::into) } - pub fn peel_to_tree(&self) -> Result> { - self.reference - .peel_to_tree() - .map(Into::into) - .map_err(Into::into) - } - pub fn rename( &mut self, new_name: &Refname, diff --git a/crates/gitbutler-core/src/git/repository.rs b/crates/gitbutler-core/src/git/repository.rs index 29d7f7f23..8145c7bf7 100644 --- a/crates/gitbutler-core/src/git/repository.rs +++ b/crates/gitbutler-core/src/git/repository.rs @@ -1,5 +1,5 @@ use super::{ - Blob, Branch, Commit, Config, Index, Oid, Reference, Refname, Remote, Result, Signature, Tree, + Blob, Branch, Commit, Config, Index, Oid, Reference, Refname, Remote, Result, Signature, TreeBuilder, Url, }; use git2::{BlameOptions, Submodule}; @@ -98,42 +98,37 @@ impl Repository { pub fn merge_trees( &self, - ancestor_tree: &Tree<'_>, - our_tree: &Tree<'_>, - their_tree: &Tree<'_>, + ancestor_tree: &git2::Tree<'_>, + our_tree: &git2::Tree<'_>, + their_tree: &git2::Tree<'_>, ) -> Result { self.0 - .merge_trees( - ancestor_tree.into(), - our_tree.into(), - their_tree.into(), - None, - ) + .merge_trees(ancestor_tree, our_tree, their_tree, None) .map(Index::from) .map_err(Into::into) } pub fn diff_tree_to_tree( &self, - old_tree: Option<&Tree<'_>>, - new_tree: Option<&Tree<'_>>, + old_tree: Option<&git2::Tree<'_>>, + new_tree: Option<&git2::Tree<'_>>, opts: Option<&mut git2::DiffOptions>, ) -> Result> { self.0 - .diff_tree_to_tree(old_tree.map(Into::into), new_tree.map(Into::into), opts) + .diff_tree_to_tree(old_tree, new_tree, opts) .map_err(Into::into) } pub fn diff_tree_to_workdir( &self, - old_tree: Option<&Tree<'_>>, + old_tree: Option<&git2::Tree<'_>>, opts: Option<&mut git2::DiffOptions>, ) -> Result> { if let Ok(mut index) = self.0.index() { index.update_all(vec!["*"], None)?; } self.0 - .diff_tree_to_workdir_with_index(old_tree.map(Into::into), opts) + .diff_tree_to_workdir_with_index(old_tree, opts) .map_err(Into::into) } @@ -160,11 +155,8 @@ impl Repository { self.0.head().map(Reference::from).map_err(Into::into) } - pub fn find_tree(&self, id: Oid) -> Result { - self.0 - .find_tree(id.into()) - .map(Tree::from) - .map_err(Into::into) + pub fn find_tree(&self, id: Oid) -> Result { + self.0.find_tree(id.into()).map_err(Into::into) } pub fn find_commit(&self, id: Oid) -> Result { @@ -238,7 +230,7 @@ impl Repository { author: &Signature<'_>, committer: &Signature<'_>, message: &str, - tree: &Tree<'_>, + tree: &git2::Tree<'_>, parents: &[&Commit<'_>], change_id: Option<&str>, ) -> Result { @@ -251,7 +243,7 @@ impl Repository { author.into(), committer.into(), message, - tree.into(), + tree, &parents, )?; @@ -431,7 +423,7 @@ impl Repository { self.0.config().map(Into::into).map_err(Into::into) } - pub fn treebuilder<'repo>(&'repo self, tree: Option<&'repo Tree>) -> TreeBuilder<'repo> { + pub fn treebuilder<'repo>(&'repo self, tree: Option<&'repo git2::Tree>) -> TreeBuilder<'repo> { TreeBuilder::new(self, tree) } @@ -528,9 +520,9 @@ impl Repository { Ok(()) } - pub fn checkout_tree<'a>(&'a self, tree: &'a Tree<'a>) -> CheckoutTreeBuidler { + pub fn checkout_tree<'a>(&'a self, tree: &'a git2::Tree<'a>) -> CheckoutTreeBuidler { CheckoutTreeBuidler { - tree: tree.into(), + tree, repo: &self.0, checkout_builder: git2::build::CheckoutBuilder::new(), } diff --git a/crates/gitbutler-core/src/git/tree.rs b/crates/gitbutler-core/src/git/tree.rs index d822c1783..3bb0a4f93 100644 --- a/crates/gitbutler-core/src/git/tree.rs +++ b/crates/gitbutler-core/src/git/tree.rs @@ -1,93 +1,6 @@ use std::path::Path; use super::{Oid, Repository, Result}; -use crate::path::Normalize; - -pub struct Tree<'repo> { - pub tree: git2::Tree<'repo>, -} - -impl<'repo> From> for Tree<'repo> { - fn from(tree: git2::Tree<'repo>) -> Self { - Tree { tree } - } -} - -impl<'repo> From<&'repo Tree<'repo>> for &'repo git2::Tree<'repo> { - fn from(tree: &'repo Tree<'repo>) -> Self { - &tree.tree - } -} - -impl<'repo> Tree<'repo> { - pub fn id(&self) -> Oid { - self.tree.id().into() - } - - pub fn get_path>(&self, path: P) -> Result> { - self.tree - .get_path(path.normalize().as_path()) - .map(Into::into) - .map_err(Into::into) - } - - pub fn walk(&self, mut callback: C) -> Result<()> - where - C: FnMut(&str, &TreeEntry) -> TreeWalkResult, - { - self.tree - .walk(git2::TreeWalkMode::PreOrder, |root, entry| { - match callback(root, &entry.clone().into()) { - TreeWalkResult::Continue => git2::TreeWalkResult::Ok, - TreeWalkResult::Skip => git2::TreeWalkResult::Skip, - TreeWalkResult::Stop => git2::TreeWalkResult::Abort, - } - }) - .map_err(Into::into) - } - - pub fn get_name(&self, filename: &str) -> Option { - self.tree.get_name(filename).map(Into::into) - } -} - -pub enum TreeWalkResult { - Continue, - Skip, - Stop, -} - -pub struct TreeEntry<'repo> { - entry: git2::TreeEntry<'repo>, -} - -impl<'repo> From> for TreeEntry<'repo> { - fn from(entry: git2::TreeEntry<'repo>) -> Self { - TreeEntry { entry } - } -} - -impl<'repo> TreeEntry<'repo> { - pub fn filemode(&self) -> i32 { - self.entry.filemode() - } - - pub fn to_object(&self, repo: &'repo Repository) -> Result { - self.entry.to_object(repo.into()).map_err(Into::into) - } - - pub fn kind(&self) -> Option { - self.entry.kind() - } - - pub fn id(&self) -> Oid { - self.entry.id().into() - } - - pub fn name(&self) -> Option<&str> { - self.entry.name() - } -} #[derive(PartialEq)] pub enum FileMode { @@ -115,11 +28,11 @@ pub struct TreeBuilder<'repo> { } impl<'repo> TreeBuilder<'repo> { - pub fn new(repo: &'repo Repository, base: Option<&'repo Tree>) -> Self { + pub fn new(repo: &'repo Repository, base: Option<&'repo git2::Tree>) -> Self { TreeBuilder { repo: repo.into(), builder: git2::build::TreeUpdateBuilder::new(), - base: base.map(Into::into), + base, } } diff --git a/crates/gitbutler-core/src/git/tree_ext.rs b/crates/gitbutler-core/src/git/tree_ext.rs new file mode 100644 index 000000000..b439c134f --- /dev/null +++ b/crates/gitbutler-core/src/git/tree_ext.rs @@ -0,0 +1,19 @@ +use crate::path::Normalize; +use anyhow::Result; +use git2::TreeEntry; +use std::path::Path; + +/// Extension trait for `git2::Tree`. +/// +/// For now, it collects useful methods from `gitbutler-core::git::Tree` +pub trait TreeExt { + fn get_path>(&self, path: P) -> Result>; +} + +impl<'repo> TreeExt for git2::Tree<'repo> { + fn get_path>(&self, path: P) -> Result> { + self.get_path(path.normalize().as_path()) + .map(Into::into) + .map_err(Into::into) + } +} diff --git a/crates/gitbutler-core/src/project_repository/repository.rs b/crates/gitbutler-core/src/project_repository/repository.rs index 6ee400fc0..87a6edb48 100644 --- a/crates/gitbutler-core/src/project_repository/repository.rs +++ b/crates/gitbutler-core/src/project_repository/repository.rs @@ -340,7 +340,7 @@ impl Repository { &self, user: Option<&users::User>, message: &str, - tree: &git::Tree, + tree: &git2::Tree, parents: &[&git::Commit], change_id: Option<&str>, ) -> Result { diff --git a/crates/gitbutler-core/src/reader.rs b/crates/gitbutler-core/src/reader.rs index e841975fb..11ac48acc 100644 --- a/crates/gitbutler-core/src/reader.rs +++ b/crates/gitbutler-core/src/reader.rs @@ -5,10 +5,10 @@ use std::{ sync::Arc, }; -use anyhow::{Context, Result}; +use anyhow::Result; use serde::{ser::SerializeStruct, Serialize}; -use crate::{git, lock, path::Normalize}; +use crate::git::{self}; #[derive(Debug, Clone, thiserror::Error)] pub enum Error { @@ -37,216 +37,6 @@ impl From for Error { } } -pub enum Reader<'reader> { - Filesystem(FilesystemReader), - Commit(CommitReader<'reader>), - Prefixed(PrefixedReader<'reader>), -} - -impl<'reader> Reader<'reader> { - pub fn open>(root: P) -> Result { - FilesystemReader::open(root).map(Reader::Filesystem) - } - - pub fn sub>(&'reader self, prefix: P) -> Self { - Reader::Prefixed(PrefixedReader::new(self, prefix)) - } - - pub fn commit_id(&self) -> Option { - match self { - Reader::Filesystem(_) => None, - Reader::Commit(reader) => Some(reader.get_commit_oid()), - Reader::Prefixed(reader) => reader.reader.commit_id(), - } - } - - pub fn from_commit( - repository: &'reader git::Repository, - commit: &git::Commit<'reader>, - ) -> Result { - Ok(Reader::Commit(CommitReader::new(repository, commit)?)) - } - - pub fn exists>(&self, file_path: P) -> Result { - match self { - Reader::Filesystem(reader) => reader.exists(file_path), - Reader::Commit(reader) => Ok(reader.exists(file_path)), - Reader::Prefixed(reader) => reader.exists(file_path), - } - } - - pub fn read>(&self, path: P) -> Result { - let mut contents = self.batch(&[path])?; - contents - .pop() - .expect("batch should return at least one result") - } - - pub fn batch>( - &self, - paths: &[P], - ) -> Result>, io::Error> { - match self { - Reader::Filesystem(reader) => reader.batch(|root| { - paths - .iter() - .map(|path| { - let path = root.join(path); - if !path.exists() { - return Err(Error::NotFound); - } - let content = Content::read_from_file(&path)?; - Ok(content) - }) - .collect() - }), - Reader::Commit(reader) => Ok(paths - .iter() - .map(|path| reader.read(path.normalize())) - .collect()), - Reader::Prefixed(reader) => reader.batch(paths), - } - } - - pub fn list_files>(&self, dir_path: P) -> Result> { - match self { - Reader::Filesystem(reader) => reader.list_files(dir_path.as_ref()), - Reader::Commit(reader) => reader.list_files(dir_path.as_ref()), - Reader::Prefixed(reader) => reader.list_files(dir_path.as_ref()), - } - } -} - -pub struct FilesystemReader(lock::Dir); - -impl FilesystemReader { - fn open>(root: P) -> Result { - lock::Dir::new(root).map(Self) - } - - fn exists>(&self, path: P) -> Result { - let exists = self.0.batch(|root| root.join(path.as_ref()).exists())?; - Ok(exists) - } - - fn batch(&self, action: impl FnOnce(&Path) -> R) -> Result { - self.0.batch(action) - } - - fn list_files>(&self, path: P) -> Result> { - let path = path.as_ref(); - self.0 - .batch(|root| crate::fs::list_files(root.join(path).as_path(), &[Path::new(".git")]))? - } -} - -pub struct CommitReader<'reader> { - repository: &'reader git::Repository, - commit_oid: git::Oid, - tree: git::Tree<'reader>, -} - -impl<'reader> CommitReader<'reader> { - pub fn new( - repository: &'reader git::Repository, - commit: &git::Commit<'reader>, - ) -> Result> { - let tree = commit - .tree() - .with_context(|| format!("{}: tree not found", commit.id()))?; - Ok(CommitReader { - repository, - tree, - commit_oid: commit.id(), - }) - } - - pub fn get_commit_oid(&self) -> git::Oid { - self.commit_oid - } - - fn read>(&self, path: P) -> Result { - let path = path.as_ref(); - let entry = match self - .tree - .get_path(Path::new(path)) - .context(format!("{}: tree entry not found", path.display())) - { - Ok(entry) => entry, - Err(_) => return Err(Error::NotFound), - }; - let blob = match self.repository.find_blob(entry.id()) { - Ok(blob) => blob, - Err(_) => return Err(Error::NotFound), - }; - Ok(Content::from(&blob)) - } - - pub fn list_files>(&self, dir_path: P) -> Result> { - let dir_path = dir_path.as_ref(); - let mut files = vec![]; - self.tree - .walk(|root, entry| { - if entry.kind() == Some(git2::ObjectType::Tree) { - return git::TreeWalkResult::Continue; - } - - if entry.name().is_none() { - return git::TreeWalkResult::Continue; - } - let entry_path = Path::new(root).join(entry.name().unwrap()); - - if !entry_path.starts_with(dir_path) { - return git::TreeWalkResult::Continue; - } - - files.push(entry_path.strip_prefix(dir_path).unwrap().to_path_buf()); - - git::TreeWalkResult::Continue - }) - .with_context(|| format!("{}: tree walk failed", dir_path.display()))?; - - Ok(files) - } - - pub fn exists>(&self, file_path: P) -> bool { - self.tree.get_path(file_path.normalize()).is_ok() - } -} - -pub struct PrefixedReader<'r> { - reader: &'r Reader<'r>, - prefix: PathBuf, -} - -impl<'r> PrefixedReader<'r> { - fn new>(reader: &'r Reader, prefix: P) -> Self { - PrefixedReader { - reader, - prefix: prefix.as_ref().to_path_buf(), - } - } - - pub fn batch>( - &self, - paths: &[P], - ) -> Result>, io::Error> { - let paths = paths - .iter() - .map(|path| self.prefix.join(path)) - .collect::>(); - self.reader.batch(paths.as_slice()) - } - - fn list_files>(&self, dir_path: P) -> Result> { - self.reader.list_files(self.prefix.join(dir_path.as_ref())) - } - - fn exists>(&self, file_path: P) -> Result { - self.reader.exists(self.prefix.join(file_path.as_ref())) - } -} - #[derive(Debug, Clone, thiserror::Error)] pub enum FromError { #[error(transparent)] diff --git a/crates/gitbutler-core/src/virtual_branches/base.rs b/crates/gitbutler-core/src/virtual_branches/base.rs index 6efcaaf87..12666620a 100644 --- a/crates/gitbutler-core/src/virtual_branches/base.rs +++ b/crates/gitbutler-core/src/virtual_branches/base.rs @@ -439,7 +439,7 @@ pub fn update_base_branch( let branch_merge_index_tree_oid = branch_tree_merge_index.write_tree_to(repo)?; - if branch_merge_index_tree_oid == new_target_tree.id() { + if branch_merge_index_tree_oid == new_target_tree.id().into() { return result_integrated_detected(branch); } diff --git a/crates/gitbutler-core/src/virtual_branches/virtual.rs b/crates/gitbutler-core/src/virtual_branches/virtual.rs index 0cddcea3e..6133aeec2 100644 --- a/crates/gitbutler-core/src/virtual_branches/virtual.rs +++ b/crates/gitbutler-core/src/virtual_branches/virtual.rs @@ -428,7 +428,7 @@ pub fn apply_branch( } } - branch.tree = repo.find_commit(branch.head)?.tree()?.id(); + branch.tree = repo.find_commit(branch.head)?.tree()?.id().into(); vb_state.set_branch(branch.clone())?; } @@ -440,7 +440,7 @@ pub fn apply_branch( // check index for conflicts let mut merge_index = repo - .merge_trees(&target_tree, &wd_tree.into(), &branch_tree) + .merge_trees(&target_tree, &wd_tree, &branch_tree) .context("failed to merge trees")?; if merge_index.has_conflicts() { @@ -740,7 +740,7 @@ fn find_base_tree<'a>( repo: &'a git::Repository, branch_commit: &'a git::Commit<'a>, target_commit: &'a git::Commit<'a>, -) -> Result> { +) -> Result> { // find merge base between target_commit and branch_commit let merge_base = repo .merge_base(target_commit.id(), branch_commit.id()) @@ -1110,7 +1110,7 @@ pub fn create_virtual_branch( applied: true, upstream: None, upstream_head: None, - tree: tree.id(), + tree: tree.id().into(), head: default_target.sha, created_timestamp_ms: now, updated_timestamp_ms: now, @@ -1269,7 +1269,7 @@ pub fn integrate_upstream_commits( .find_commit(get_workspace_head(&vb_state, project_repository)?)? .tree()?; - let mut merge_index = repo.merge_trees(&integration_tree, &new_head_tree, &wd_tree.into())?; + let mut merge_index = repo.merge_trees(&integration_tree, &new_head_tree, &wd_tree)?; if merge_index.has_conflicts() { repo.checkout_index(&mut merge_index) @@ -1279,7 +1279,7 @@ pub fn integrate_upstream_commits( .checkout()?; } else { branch.head = new_head; - branch.tree = head_commit.tree()?.id(); + branch.tree = head_commit.tree()?.id().into(); vb_state.set_branch(branch.clone())?; repo.checkout_index(&mut merge_index).force().checkout()?; }; @@ -1313,7 +1313,7 @@ pub fn integrate_with_merge( let upstream_branch = branch.upstream.as_ref().context("upstream not found")?; let merge_tree = repo.find_commit(merge_base).and_then(|c| c.tree())?; - let mut merge_index = repo.merge_trees(&merge_tree, &wd_tree.into(), &remote_tree)?; + let mut merge_index = repo.merge_trees(&merge_tree, &wd_tree, &remote_tree)?; if merge_index.has_conflicts() { let conflicts = merge_index.conflicts()?; @@ -2097,7 +2097,7 @@ pub fn write_tree_onto_commit( pub fn write_tree_onto_tree( project_repository: &project_repository::Repository, - base_tree: &git::Tree, + base_tree: &git2::Tree, files: impl IntoIterator, impl Borrow>)>, ) -> Result { let git_repository = &project_repository.git_repository; @@ -2178,7 +2178,7 @@ pub fn write_tree_onto_tree( } else { // blob from tree_entry let blob = tree_entry - .to_object(git_repository) + .to_object(git_repository.into()) .unwrap() .peel_to_blob() .context("failed to get blob")?; @@ -2538,7 +2538,7 @@ fn is_commit_integrated( // if the merge_tree is the same as the new_target_tree and there are no files (uncommitted changes) // then the vbranch is fully merged - Ok(merge_tree_oid == upstream_tree.id()) + Ok(merge_tree_oid == upstream_tree.id().into()) } pub fn is_remote_branch_mergeable( @@ -2580,7 +2580,7 @@ pub fn is_remote_branch_mergeable( let branch_tree = branch_commit.tree().context("failed to find branch tree")?; let mergeable = !project_repository .git_repository - .merge_trees(&base_tree, &branch_tree, &wd_tree.into()) + .merge_trees(&base_tree, &branch_tree, &wd_tree) .context("failed to merge trees")? .has_conflicts(); @@ -2644,7 +2644,7 @@ pub fn is_virtual_branch_mergeable( let is_mergeable = !project_repository .git_repository - .merge_trees(&base_tree, &branch_tree, &wd_tree.into()) + .merge_trees(&base_tree, &branch_tree, &wd_tree) .context("failed to merge trees")? .has_conflicts(); @@ -4133,7 +4133,7 @@ pub fn create_virtual_branch_from_branch( applied: false, upstream_head: upstream_branch.is_some().then_some(head_commit.id()), upstream: upstream_branch, - tree: head_commit_tree.id(), + tree: head_commit_tree.id().into(), head: head_commit.id(), created_timestamp_ms: now, updated_timestamp_ms: now, diff --git a/crates/gitbutler-core/tests/core.rs b/crates/gitbutler-core/tests/core.rs index 99b51d0d2..45353094f 100644 --- a/crates/gitbutler-core/tests/core.rs +++ b/crates/gitbutler-core/tests/core.rs @@ -8,7 +8,6 @@ mod git; mod keys; mod lock; mod ops; -mod reader; mod types; pub mod virtual_branches; mod zip; diff --git a/crates/gitbutler-core/tests/reader/mod.rs b/crates/gitbutler-core/tests/reader/mod.rs deleted file mode 100644 index 67ef76305..000000000 --- a/crates/gitbutler-core/tests/reader/mod.rs +++ /dev/null @@ -1,183 +0,0 @@ -use std::{fs, path::Path}; - -use anyhow::Result; -use gitbutler_core::reader::{CommitReader, Content, Reader}; - -use gitbutler_testsupport::{commit_all, temp_dir, test_repository}; - -#[test] -fn directory_reader_read_file() -> Result<()> { - let dir = temp_dir(); - - let file_path = Path::new("test.txt"); - fs::write(dir.path().join(file_path), "test")?; - - let reader = Reader::open(dir.path())?; - assert_eq!(reader.read(file_path)?, Content::UTF8("test".to_string())); - - Ok(()) -} - -#[test] -fn commit_reader_read_file() -> Result<()> { - let (repository, _tmp) = test_repository(); - - let file_path = Path::new("test.txt"); - fs::write(repository.path().parent().unwrap().join(file_path), "test")?; - - let oid = commit_all(&repository); - - fs::write(repository.path().parent().unwrap().join(file_path), "test2")?; - - let reader = Reader::from_commit(&repository, &repository.find_commit(oid)?)?; - assert_eq!(reader.read(file_path)?, Content::UTF8("test".to_string())); - - Ok(()) -} - -#[test] -fn reader_list_files_should_return_relative() -> Result<()> { - let dir = temp_dir(); - - fs::write(dir.path().join("test1.txt"), "test")?; - fs::create_dir_all(dir.path().join("dir"))?; - fs::write(dir.path().join("dir").join("test.txt"), "test")?; - - let reader = Reader::open(dir.path())?; - let files = reader.list_files(Path::new("dir"))?; - assert_eq!(files.len(), 1); - assert!(files.contains(&Path::new("test.txt").to_path_buf())); - - Ok(()) -} - -#[test] -fn reader_list_files() -> Result<()> { - let dir = temp_dir(); - - fs::write(dir.path().join("test.txt"), "test")?; - fs::create_dir_all(dir.path().join("dir"))?; - fs::write(dir.path().join("dir").join("test.txt"), "test")?; - - let reader = Reader::open(dir.path())?; - let files = reader.list_files(Path::new(""))?; - assert_eq!(files.len(), 2); - assert!(files.contains(&Path::new("test.txt").to_path_buf())); - assert!(files.contains(&Path::new("dir/test.txt").to_path_buf())); - - Ok(()) -} - -#[test] -fn commit_reader_list_files_should_return_relative() -> Result<()> { - let (repository, _tmp) = test_repository(); - - fs::write( - repository.path().parent().unwrap().join("test1.txt"), - "test", - )?; - fs::create_dir_all(repository.path().parent().unwrap().join("dir"))?; - fs::write( - repository - .path() - .parent() - .unwrap() - .join("dir") - .join("test.txt"), - "test", - )?; - - let oid = commit_all(&repository); - - fs::remove_dir_all(repository.path().parent().unwrap().join("dir"))?; - - let reader = CommitReader::new(&repository, &repository.find_commit(oid)?)?; - let files = reader.list_files(Path::new("dir"))?; - assert_eq!(files.len(), 1); - assert!(files.contains(&Path::new("test.txt").to_path_buf())); - - Ok(()) -} - -#[test] -fn commit_reader_list_files() -> Result<()> { - let (repository, _tmp) = test_repository(); - - fs::write(repository.path().parent().unwrap().join("test.txt"), "test")?; - fs::create_dir_all(repository.path().parent().unwrap().join("dir"))?; - fs::write( - repository - .path() - .parent() - .unwrap() - .join("dir") - .join("test.txt"), - "test", - )?; - - let oid = commit_all(&repository); - - fs::remove_dir_all(repository.path().parent().unwrap().join("dir"))?; - - let reader = CommitReader::new(&repository, &repository.find_commit(oid)?)?; - let files = reader.list_files(Path::new(""))?; - assert_eq!(files.len(), 2); - assert!(files.contains(&Path::new("test.txt").to_path_buf())); - assert!(files.contains(&Path::new("dir/test.txt").to_path_buf())); - - Ok(()) -} - -#[test] -fn directory_reader_exists() -> Result<()> { - let dir = temp_dir(); - - fs::write(dir.path().join("test.txt"), "test")?; - - let reader = Reader::open(dir.path())?; - assert!(reader.exists(Path::new("test.txt"))?); - assert!(!reader.exists(Path::new("test2.txt"))?); - - Ok(()) -} - -#[test] -fn commit_reader_exists() -> Result<()> { - let (repository, _tmp) = test_repository(); - - fs::write(repository.path().parent().unwrap().join("test.txt"), "test")?; - - let oid = commit_all(&repository); - - fs::remove_file(repository.path().parent().unwrap().join("test.txt"))?; - - let reader = CommitReader::new(&repository, &repository.find_commit(oid)?)?; - assert!(reader.exists(Path::new("test.txt"))); - assert!(!reader.exists(Path::new("test2.txt"))); - - Ok(()) -} - -#[test] -fn from_bytes() { - for (bytes, expected) in [ - ("test".as_bytes(), Content::UTF8("test".to_string())), - (&[0, 159, 146, 150, 159, 146, 150], Content::Binary), - ] { - assert_eq!(Content::from(bytes), expected); - } -} - -#[test] -fn serialize_content() { - for (content, expected) in [ - ( - Content::UTF8("test".to_string()), - r#"{"type":"utf8","value":"test"}"#, - ), - (Content::Binary, r#"{"type":"binary"}"#), - (Content::Large, r#"{"type":"large"}"#), - ] { - assert_eq!(serde_json::to_string(&content).unwrap(), expected); - } -} diff --git a/crates/gitbutler-core/tests/virtual_branches/mod.rs b/crates/gitbutler-core/tests/virtual_branches/mod.rs index 596b1265b..f640e032c 100644 --- a/crates/gitbutler-core/tests/virtual_branches/mod.rs +++ b/crates/gitbutler-core/tests/virtual_branches/mod.rs @@ -13,8 +13,9 @@ use std::{ }; use anyhow::{Context, Result}; +use git2::TreeEntry; use gitbutler_core::{ - git, + git::{self}, virtual_branches::{ self, apply_branch, branch::{BranchCreateRequest, BranchOwnershipClaims}, @@ -1991,16 +1992,16 @@ fn commit_executable_and_symlinks() -> Result<()> { Ok(()) } -fn tree_to_file_list(repository: &git::Repository, tree: &git::Tree) -> Vec { +fn tree_to_file_list(repository: &git::Repository, tree: &git2::Tree) -> Vec { let mut file_list = Vec::new(); - tree.walk(|_, entry| { + walk(tree, |_, entry| { let path = entry.name().unwrap(); let entry = tree.get_path(Path::new(path)).unwrap(); - let object = entry.to_object(repository).unwrap(); + let object = entry.to_object(repository.into()).unwrap(); if object.kind() == Some(git2::ObjectType::Blob) { file_list.push(path.to_string()); } - git::TreeWalkResult::Continue + TreeWalkResult::Continue }) .expect("failed to walk tree"); file_list @@ -2008,13 +2009,13 @@ fn tree_to_file_list(repository: &git::Repository, tree: &git::Tree) -> Vec Vec<(String, String, String, String)> { let mut file_list = Vec::new(); - tree.walk(|_root, entry| { + walk(tree, |_root, entry| { let path = entry.name().unwrap(); let entry = tree.get_path(Path::new(path)).unwrap(); - let object = entry.to_object(repository).unwrap(); + let object = entry.to_object(repository.into()).unwrap(); let blob = object.as_blob().expect("failed to get blob"); // convert content to string let octal_mode = format!("{:o}", entry.filemode()); @@ -2035,7 +2036,7 @@ fn tree_to_entry_list( blob.id().to_string(), )); } - git::TreeWalkResult::Continue + TreeWalkResult::Continue }) .expect("failed to walk tree"); file_list @@ -2267,3 +2268,23 @@ fn commit_msg_hook_rejection() -> Result<()> { Ok(()) } + +fn walk(tree: &git2::Tree, mut callback: C) -> Result<()> +where + C: FnMut(&str, &TreeEntry) -> TreeWalkResult, +{ + tree.walk(git2::TreeWalkMode::PreOrder, |root, entry| { + match callback(root, &entry.clone()) { + TreeWalkResult::Continue => git2::TreeWalkResult::Ok, + // TreeWalkResult::Skip => git2::TreeWalkResult::Skip, + // TreeWalkResult::Stop => git2::TreeWalkResult::Abort, + } + }) + .map_err(Into::into) +} + +enum TreeWalkResult { + Continue, + // Skip, + // Stop, +}