repo: turn off view_dirty flag by enforce_view_invariants()

Otherwise enforce_view_invariants() could mutate view while its reference
is alive.
This commit is contained in:
Yuya Nishihara 2022-11-04 20:10:19 +09:00
parent 2b8dabaae4
commit f26c5c1a05

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::cell::RefCell; use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::io::ErrorKind; use std::io::ErrorKind;
@ -462,7 +462,7 @@ pub struct MutableRepo {
base_repo: Arc<ReadonlyRepo>, base_repo: Arc<ReadonlyRepo>,
index: MutableIndex, index: MutableIndex,
view: RefCell<View>, view: RefCell<View>,
view_dirty: bool, view_dirty: Cell<bool>,
rewritten_commits: HashMap<CommitId, HashSet<CommitId>>, rewritten_commits: HashMap<CommitId, HashSet<CommitId>>,
abandoned_commits: HashSet<CommitId>, abandoned_commits: HashSet<CommitId>,
} }
@ -479,7 +479,7 @@ impl MutableRepo {
base_repo, base_repo,
index: mut_index, index: mut_index,
view: RefCell::new(mut_view), view: RefCell::new(mut_view),
view_dirty: false, view_dirty: Cell::new(false),
rewritten_commits: Default::default(), rewritten_commits: Default::default(),
abandoned_commits: Default::default(), abandoned_commits: Default::default(),
} }
@ -648,7 +648,7 @@ impl MutableRepo {
} }
fn enforce_view_invariants(&self) { fn enforce_view_invariants(&self) {
if !self.view_dirty { if !self.view_dirty.get() {
return; return;
} }
let mut view_borrow_mut = self.view.borrow_mut(); let mut view_borrow_mut = self.view.borrow_mut();
@ -666,6 +666,7 @@ impl MutableRepo {
.iter() .iter()
.cloned() .cloned()
.collect(); .collect();
self.view_dirty.set(false);
} }
pub fn add_head(&mut self, head: &Commit) { pub fn add_head(&mut self, head: &Commit) {
@ -699,23 +700,23 @@ impl MutableRepo {
self.index.add_commit(missing_commit); self.index.add_commit(missing_commit);
} }
self.view.get_mut().add_head(head.id()); self.view.get_mut().add_head(head.id());
self.view_dirty = true; *self.view_dirty.get_mut() = true;
} }
} }
pub fn remove_head(&mut self, head: &CommitId) { pub fn remove_head(&mut self, head: &CommitId) {
self.view_mut().remove_head(head); self.view_mut().remove_head(head);
self.view_dirty = true; *self.view_dirty.get_mut() = true;
} }
pub fn add_public_head(&mut self, head: &Commit) { pub fn add_public_head(&mut self, head: &Commit) {
self.view_mut().add_public_head(head.id()); self.view_mut().add_public_head(head.id());
self.view_dirty = true; *self.view_dirty.get_mut() = true;
} }
pub fn remove_public_head(&mut self, head: &CommitId) { pub fn remove_public_head(&mut self, head: &CommitId) {
self.view_mut().remove_public_head(head); self.view_mut().remove_public_head(head);
self.view_dirty = true; *self.view_dirty.get_mut() = true;
} }
pub fn get_branch(&self, name: &str) -> Option<BranchTarget> { pub fn get_branch(&self, name: &str) -> Option<BranchTarget> {
@ -788,7 +789,7 @@ impl MutableRepo {
pub fn set_view(&mut self, data: op_store::View) { pub fn set_view(&mut self, data: op_store::View) {
self.view_mut().set_view(data); self.view_mut().set_view(data);
self.view_dirty = true; *self.view_dirty.get_mut() = true;
} }
pub fn merge(&mut self, base_repo: &ReadonlyRepo, other_repo: &ReadonlyRepo) { pub fn merge(&mut self, base_repo: &ReadonlyRepo, other_repo: &ReadonlyRepo) {
@ -801,7 +802,7 @@ impl MutableRepo {
self.enforce_view_invariants(); self.enforce_view_invariants();
self.merge_view(&base_repo.view, &other_repo.view); self.merge_view(&base_repo.view, &other_repo.view);
self.view_dirty = true; *self.view_dirty.get_mut() = true;
} }
fn merge_view(&mut self, base: &View, other: &View) { fn merge_view(&mut self, base: &View, other: &View) {