diff --git a/lib/src/evolution.rs b/lib/src/evolution.rs index 990328cab..f285acee0 100644 --- a/lib/src/evolution.rs +++ b/lib/src/evolution.rs @@ -316,14 +316,39 @@ impl State { } } -pub trait Evolution { - fn successors(&self, commit_id: &CommitId) -> HashSet; +pub enum EvolutionRef<'a, 'm: 'a, 'r: 'm> { + Readonly(&'a ReadonlyEvolution<'r>), + Mutable(&'a MutableEvolution<'m, 'r>), +} - fn is_obsolete(&self, commit_id: &CommitId) -> bool; +impl EvolutionRef<'_, '_, '_> { + pub fn successors(&self, commit_id: &CommitId) -> HashSet { + match self { + EvolutionRef::Readonly(evolution) => evolution.successors(commit_id), + EvolutionRef::Mutable(evolution) => evolution.successors(commit_id), + } + } - fn is_orphan(&self, commit_id: &CommitId) -> bool; + pub fn is_obsolete(&self, commit_id: &CommitId) -> bool { + match self { + EvolutionRef::Readonly(evolution) => evolution.is_obsolete(commit_id), + EvolutionRef::Mutable(evolution) => evolution.is_obsolete(commit_id), + } + } - fn is_divergent(&self, change_id: &ChangeId) -> bool; + pub fn is_orphan(&self, commit_id: &CommitId) -> bool { + match self { + EvolutionRef::Readonly(evolution) => evolution.is_orphan(commit_id), + EvolutionRef::Mutable(evolution) => evolution.is_orphan(commit_id), + } + } + + pub fn is_divergent(&self, change_id: &ChangeId) -> bool { + match self { + EvolutionRef::Readonly(evolution) => evolution.is_divergent(change_id), + EvolutionRef::Mutable(evolution) => evolution.is_divergent(change_id), + } + } /// Given a current parent, finds the new parent candidates. If the current /// parent is not obsolete, then a singleton set of that commit will be @@ -340,7 +365,12 @@ pub trait Evolution { /// change id as A). Then C is rebased to somewhere else and becomes C'. /// We will choose that C' as effective successor even though it has a /// different change id and is not a descendant of one that does. - fn new_parent(&self, old_parent_id: &CommitId) -> HashSet; + pub fn new_parent(&self, old_parent_id: &CommitId) -> HashSet { + match self { + EvolutionRef::Readonly(evolution) => evolution.new_parent(old_parent_id), + EvolutionRef::Mutable(evolution) => evolution.new_parent(old_parent_id), + } + } } pub struct ReadonlyEvolution<'r> { @@ -355,29 +385,6 @@ pub trait EvolveListener { fn divergent_no_common_predecessor(&mut self, commit1: &Commit, commit2: &Commit); } -impl Evolution for ReadonlyEvolution<'_> { - fn successors(&self, commit_id: &CommitId) -> HashSet { - self.get_state().successors(commit_id) - } - - fn is_obsolete(&self, commit_id: &CommitId) -> bool { - self.get_state().is_obsolete(commit_id) - } - - fn is_orphan(&self, commit_id: &CommitId) -> bool { - self.get_state().is_orphan(commit_id) - } - - fn is_divergent(&self, change_id: &ChangeId) -> bool { - self.get_state().is_divergent(change_id) - } - - fn new_parent(&self, old_parent_id: &CommitId) -> HashSet { - self.get_state() - .new_parent(self.repo.store(), old_parent_id) - } -} - impl<'r> ReadonlyEvolution<'r> { pub fn new(repo: &'r ReadonlyRepo) -> Self { ReadonlyEvolution { @@ -403,6 +410,27 @@ impl<'r> ReadonlyEvolution<'r> { state: self.get_state().as_ref().clone(), } } + + pub fn successors(&self, commit_id: &CommitId) -> HashSet { + self.get_state().successors(commit_id) + } + + pub fn is_obsolete(&self, commit_id: &CommitId) -> bool { + self.get_state().is_obsolete(commit_id) + } + + pub fn is_orphan(&self, commit_id: &CommitId) -> bool { + self.get_state().is_orphan(commit_id) + } + + pub fn is_divergent(&self, change_id: &ChangeId) -> bool { + self.get_state().is_divergent(change_id) + } + + pub fn new_parent(&self, old_parent_id: &CommitId) -> HashSet { + self.get_state() + .new_parent(self.repo.store(), old_parent_id) + } } pub struct MutableEvolution<'r: 'm, 'm> { @@ -410,29 +438,27 @@ pub struct MutableEvolution<'r: 'm, 'm> { state: State, } -impl Evolution for MutableEvolution<'_, '_> { - fn successors(&self, commit_id: &CommitId) -> HashSet { +impl MutableEvolution<'_, '_> { + pub fn successors(&self, commit_id: &CommitId) -> HashSet { self.state.successors(commit_id) } - fn is_obsolete(&self, commit_id: &CommitId) -> bool { + pub fn is_obsolete(&self, commit_id: &CommitId) -> bool { self.state.is_obsolete(commit_id) } - fn is_orphan(&self, commit_id: &CommitId) -> bool { + pub fn is_orphan(&self, commit_id: &CommitId) -> bool { self.state.is_orphan(commit_id) } - fn is_divergent(&self, change_id: &ChangeId) -> bool { + pub fn is_divergent(&self, change_id: &ChangeId) -> bool { self.state.is_divergent(change_id) } - fn new_parent(&self, old_parent_id: &CommitId) -> HashSet { + pub fn new_parent(&self, old_parent_id: &CommitId) -> HashSet { self.state.new_parent(self.repo.store(), old_parent_id) } -} -impl MutableEvolution<'_, '_> { pub fn add_commit(&mut self, commit: &Commit) { self.state.add_commit(commit); } diff --git a/lib/src/repo.rs b/lib/src/repo.rs index d2fc23208..5e36ec56c 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -22,7 +22,7 @@ use std::sync::{Arc, Mutex, MutexGuard}; use thiserror::Error; use crate::commit_builder::{new_change_id, signature}; -use crate::evolution::{Evolution, MutableEvolution, ReadonlyEvolution}; +use crate::evolution::{EvolutionRef, MutableEvolution, ReadonlyEvolution}; use crate::git_store::GitStore; use crate::index::ReadonlyIndex; use crate::local_store::LocalStore; @@ -77,10 +77,10 @@ impl<'a, 'r> RepoRef<'a, 'r> { } } - pub fn evolution(&self) -> &'a dyn Evolution { + pub fn evolution(&self) -> EvolutionRef { match self { - RepoRef::Readonly(repo) => repo.evolution(), - RepoRef::Mutable(repo) => repo.evolution(), + RepoRef::Readonly(repo) => EvolutionRef::Readonly(repo.evolution()), + RepoRef::Mutable(repo) => EvolutionRef::Mutable(repo.evolution()), } } } @@ -406,8 +406,10 @@ impl<'r> MutableRepo<'r> { self.view.take().unwrap() } - pub fn evolution(&self) -> &dyn Evolution { - self.evolution.as_ref().unwrap() + pub fn evolution<'m>(&'m self) -> &MutableEvolution<'r, 'm> { + let evolution: &MutableEvolution<'static, 'static> = self.evolution.as_ref().unwrap(); + let evolution: &MutableEvolution<'r, 'm> = unsafe { std::mem::transmute(evolution) }; + evolution } pub fn evolution_mut<'m>(&'m mut self) -> &'m mut MutableEvolution<'r, 'm> { diff --git a/lib/tests/test_operations.rs b/lib/tests/test_operations.rs index 22169f991..a66da40a3 100644 --- a/lib/tests/test_operations.rs +++ b/lib/tests/test_operations.rs @@ -13,7 +13,6 @@ // limitations under the License. use jujube_lib::commit_builder::CommitBuilder; -use jujube_lib::evolution::Evolution; use jujube_lib::repo::RepoRef; use jujube_lib::store::CommitId; use jujube_lib::testutils; diff --git a/src/commands.rs b/src/commands.rs index 9840af8f0..a601b3b90 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -36,7 +36,7 @@ use jujube_lib::commit_builder::CommitBuilder; use jujube_lib::conflicts; use jujube_lib::dag_walk::{common_ancestor, topo_order_reverse, walk_ancestors}; use jujube_lib::evolution::evolve; -use jujube_lib::evolution::{Evolution, EvolveListener}; +use jujube_lib::evolution::EvolveListener; use jujube_lib::files; use jujube_lib::files::DiffLine; use jujube_lib::git;