evolution: replace Evolution trait by enum with Readonly and Mutable variants

This commit is contained in:
Martin von Zweigbergk 2021-01-31 18:13:37 -08:00
parent f1666375bd
commit d1e5f46969
4 changed files with 72 additions and 45 deletions

View file

@ -316,14 +316,39 @@ impl State {
} }
} }
pub trait Evolution { pub enum EvolutionRef<'a, 'm: 'a, 'r: 'm> {
fn successors(&self, commit_id: &CommitId) -> HashSet<CommitId>; 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<CommitId> {
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 /// 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 /// 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'. /// 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 /// 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. /// different change id and is not a descendant of one that does.
fn new_parent(&self, old_parent_id: &CommitId) -> HashSet<CommitId>; pub fn new_parent(&self, old_parent_id: &CommitId) -> HashSet<CommitId> {
match self {
EvolutionRef::Readonly(evolution) => evolution.new_parent(old_parent_id),
EvolutionRef::Mutable(evolution) => evolution.new_parent(old_parent_id),
}
}
} }
pub struct ReadonlyEvolution<'r> { pub struct ReadonlyEvolution<'r> {
@ -355,29 +385,6 @@ pub trait EvolveListener {
fn divergent_no_common_predecessor(&mut self, commit1: &Commit, commit2: &Commit); fn divergent_no_common_predecessor(&mut self, commit1: &Commit, commit2: &Commit);
} }
impl Evolution for ReadonlyEvolution<'_> {
fn successors(&self, commit_id: &CommitId) -> HashSet<CommitId> {
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<CommitId> {
self.get_state()
.new_parent(self.repo.store(), old_parent_id)
}
}
impl<'r> ReadonlyEvolution<'r> { impl<'r> ReadonlyEvolution<'r> {
pub fn new(repo: &'r ReadonlyRepo) -> Self { pub fn new(repo: &'r ReadonlyRepo) -> Self {
ReadonlyEvolution { ReadonlyEvolution {
@ -403,6 +410,27 @@ impl<'r> ReadonlyEvolution<'r> {
state: self.get_state().as_ref().clone(), state: self.get_state().as_ref().clone(),
} }
} }
pub fn successors(&self, commit_id: &CommitId) -> HashSet<CommitId> {
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<CommitId> {
self.get_state()
.new_parent(self.repo.store(), old_parent_id)
}
} }
pub struct MutableEvolution<'r: 'm, 'm> { pub struct MutableEvolution<'r: 'm, 'm> {
@ -410,29 +438,27 @@ pub struct MutableEvolution<'r: 'm, 'm> {
state: State, state: State,
} }
impl Evolution for MutableEvolution<'_, '_> { impl MutableEvolution<'_, '_> {
fn successors(&self, commit_id: &CommitId) -> HashSet<CommitId> { pub fn successors(&self, commit_id: &CommitId) -> HashSet<CommitId> {
self.state.successors(commit_id) 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) 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) 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) self.state.is_divergent(change_id)
} }
fn new_parent(&self, old_parent_id: &CommitId) -> HashSet<CommitId> { pub fn new_parent(&self, old_parent_id: &CommitId) -> HashSet<CommitId> {
self.state.new_parent(self.repo.store(), old_parent_id) self.state.new_parent(self.repo.store(), old_parent_id)
} }
}
impl MutableEvolution<'_, '_> {
pub fn add_commit(&mut self, commit: &Commit) { pub fn add_commit(&mut self, commit: &Commit) {
self.state.add_commit(commit); self.state.add_commit(commit);
} }

View file

@ -22,7 +22,7 @@ use std::sync::{Arc, Mutex, MutexGuard};
use thiserror::Error; use thiserror::Error;
use crate::commit_builder::{new_change_id, signature}; 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::git_store::GitStore;
use crate::index::ReadonlyIndex; use crate::index::ReadonlyIndex;
use crate::local_store::LocalStore; 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 { match self {
RepoRef::Readonly(repo) => repo.evolution(), RepoRef::Readonly(repo) => EvolutionRef::Readonly(repo.evolution()),
RepoRef::Mutable(repo) => repo.evolution(), RepoRef::Mutable(repo) => EvolutionRef::Mutable(repo.evolution()),
} }
} }
} }
@ -406,8 +406,10 @@ impl<'r> MutableRepo<'r> {
self.view.take().unwrap() self.view.take().unwrap()
} }
pub fn evolution(&self) -> &dyn Evolution { pub fn evolution<'m>(&'m self) -> &MutableEvolution<'r, 'm> {
self.evolution.as_ref().unwrap() 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> { pub fn evolution_mut<'m>(&'m mut self) -> &'m mut MutableEvolution<'r, 'm> {

View file

@ -13,7 +13,6 @@
// limitations under the License. // limitations under the License.
use jujube_lib::commit_builder::CommitBuilder; use jujube_lib::commit_builder::CommitBuilder;
use jujube_lib::evolution::Evolution;
use jujube_lib::repo::RepoRef; use jujube_lib::repo::RepoRef;
use jujube_lib::store::CommitId; use jujube_lib::store::CommitId;
use jujube_lib::testutils; use jujube_lib::testutils;

View file

@ -36,7 +36,7 @@ use jujube_lib::commit_builder::CommitBuilder;
use jujube_lib::conflicts; use jujube_lib::conflicts;
use jujube_lib::dag_walk::{common_ancestor, topo_order_reverse, walk_ancestors}; use jujube_lib::dag_walk::{common_ancestor, topo_order_reverse, walk_ancestors};
use jujube_lib::evolution::evolve; use jujube_lib::evolution::evolve;
use jujube_lib::evolution::{Evolution, EvolveListener}; use jujube_lib::evolution::EvolveListener;
use jujube_lib::files; use jujube_lib::files;
use jujube_lib::files::DiffLine; use jujube_lib::files::DiffLine;
use jujube_lib::git; use jujube_lib::git;