jj: improve initialization process
This commit is contained in:
parent
19764794b7
commit
a83c935d7c
5 changed files with 106 additions and 19 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -8724,7 +8724,9 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"gpui",
|
"gpui",
|
||||||
"jj-lib",
|
"jj-lib",
|
||||||
|
"project",
|
||||||
"workspace-hack",
|
"workspace-hack",
|
||||||
|
"worktree",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -15,4 +15,6 @@ path = "src/jj.rs"
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
jj-lib.workspace = true
|
jj-lib.workspace = true
|
||||||
|
project.workspace = true
|
||||||
workspace-hack.workspace = true
|
workspace-hack.workspace = true
|
||||||
|
worktree.workspace = true
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use std::path::Path;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gpui::{App, Entity, Global, prelude::*};
|
use gpui::{App, Context, Entity, EventEmitter, Global, Subscription, prelude::*};
|
||||||
|
use project::worktree_store::{WorktreeStore, WorktreeStoreEvent};
|
||||||
|
use worktree::{Worktree, WorktreeId};
|
||||||
|
|
||||||
use crate::{JujutsuRepository, RealJujutsuRepository};
|
use crate::{JujutsuRepository, RealJujutsuRepository};
|
||||||
|
|
||||||
|
@ -11,18 +13,22 @@ struct GlobalJujutsuStore(Entity<JujutsuStore>);
|
||||||
impl Global for GlobalJujutsuStore {}
|
impl Global for GlobalJujutsuStore {}
|
||||||
|
|
||||||
pub struct JujutsuStore {
|
pub struct JujutsuStore {
|
||||||
repository: Arc<dyn JujutsuRepository>,
|
active_repository: Option<WorktreeId>,
|
||||||
|
repositories: HashMap<WorktreeId, Arc<dyn JujutsuRepository>>,
|
||||||
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum JujutsuStoreEvent {
|
||||||
|
ActiveRepositoryChanged(Option<WorktreeId>),
|
||||||
|
RepositoryAdded(WorktreeId),
|
||||||
|
RepositoryRemoved(WorktreeId),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<JujutsuStoreEvent> for JujutsuStore {}
|
||||||
|
|
||||||
impl JujutsuStore {
|
impl JujutsuStore {
|
||||||
pub fn init_global(cx: &mut App) {
|
pub fn init_global(cx: &mut App, worktree_store: Entity<WorktreeStore>) {
|
||||||
let Some(repository) = RealJujutsuRepository::new(Path::new(".")).ok() else {
|
let jj_store = cx.new(|cx| JujutsuStore::new(worktree_store, cx));
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let repository = Arc::new(repository);
|
|
||||||
let jj_store = cx.new(|cx| JujutsuStore::new(repository, cx));
|
|
||||||
|
|
||||||
cx.set_global(GlobalJujutsuStore(jj_store));
|
cx.set_global(GlobalJujutsuStore(jj_store));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,11 +37,84 @@ impl JujutsuStore {
|
||||||
.map(|global| global.0.clone())
|
.map(|global| global.0.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(repository: Arc<dyn JujutsuRepository>, _cx: &mut Context<Self>) -> Self {
|
pub fn new(worktree_store: Entity<WorktreeStore>, cx: &mut Context<Self>) -> Self {
|
||||||
Self { repository }
|
let _subscriptions = vec![cx.subscribe(&worktree_store, Self::on_worktree_store_event)];
|
||||||
|
|
||||||
|
let mut store = JujutsuStore {
|
||||||
|
active_repository: None,
|
||||||
|
repositories: HashMap::default(),
|
||||||
|
_subscriptions,
|
||||||
|
};
|
||||||
|
|
||||||
|
let existing_worktrees: Vec<_> = worktree_store.read(cx).worktrees().collect();
|
||||||
|
|
||||||
|
for worktree in existing_worktrees {
|
||||||
|
store.scan_worktree_for_jj_repo(&worktree, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
store
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repository(&self) -> &Arc<dyn JujutsuRepository> {
|
fn on_worktree_store_event(
|
||||||
&self.repository
|
&mut self,
|
||||||
|
_worktree_store: Entity<WorktreeStore>,
|
||||||
|
event: &WorktreeStoreEvent,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
match event {
|
||||||
|
WorktreeStoreEvent::WorktreeAdded(worktree) => {
|
||||||
|
self.scan_worktree_for_jj_repo(worktree, cx);
|
||||||
|
}
|
||||||
|
WorktreeStoreEvent::WorktreeRemoved(_, worktree_id) => {
|
||||||
|
if self.repositories.remove(worktree_id).is_some() {
|
||||||
|
cx.emit(JujutsuStoreEvent::RepositoryRemoved(*worktree_id));
|
||||||
|
|
||||||
|
if self.active_repository == Some(*worktree_id) {
|
||||||
|
self.active_repository = None;
|
||||||
|
cx.emit(JujutsuStoreEvent::ActiveRepositoryChanged(None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scan_worktree_for_jj_repo(&mut self, worktree: &Entity<Worktree>, cx: &mut Context<Self>) {
|
||||||
|
let worktree = worktree.read(cx);
|
||||||
|
let worktree_id = worktree.id();
|
||||||
|
let root_path = worktree.abs_path();
|
||||||
|
|
||||||
|
match RealJujutsuRepository::new(&root_path) {
|
||||||
|
Ok(repository) => {
|
||||||
|
let repository = Arc::new(repository);
|
||||||
|
|
||||||
|
self.repositories.insert(worktree_id, repository);
|
||||||
|
cx.emit(JujutsuStoreEvent::RepositoryAdded(worktree_id));
|
||||||
|
|
||||||
|
if self.active_repository.is_none() {
|
||||||
|
self.active_repository = Some(worktree_id);
|
||||||
|
cx.emit(JujutsuStoreEvent::ActiveRepositoryChanged(Some(
|
||||||
|
worktree_id,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn repository_for_worktree(
|
||||||
|
&self,
|
||||||
|
worktree_id: WorktreeId,
|
||||||
|
) -> Option<&Arc<dyn JujutsuRepository>> {
|
||||||
|
self.repositories.get(&worktree_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active_repository(&self) -> Option<&Arc<dyn JujutsuRepository>> {
|
||||||
|
self.active_repository
|
||||||
|
.and_then(|id| self.repositories.get(&id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn repository(&self) -> Option<&Arc<dyn JujutsuRepository>> {
|
||||||
|
self.active_repository()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,11 @@ impl BookmarkPickerDelegate {
|
||||||
jj_store: Entity<JujutsuStore>,
|
jj_store: Entity<JujutsuStore>,
|
||||||
cx: &mut Context<BookmarkPicker>,
|
cx: &mut Context<BookmarkPicker>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let bookmarks = jj_store.read(cx).repository().list_bookmarks();
|
let bookmarks = jj_store
|
||||||
|
.read(cx)
|
||||||
|
.repository()
|
||||||
|
.map(|repo| repo.list_bookmarks())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
picker,
|
picker,
|
||||||
|
|
|
@ -7,9 +7,9 @@ use jj::JujutsuStore;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
pub fn init(cx: &mut App) {
|
pub fn init(cx: &mut App) {
|
||||||
JujutsuStore::init_global(cx);
|
cx.observe_new(|workspace: &mut Workspace, _window, cx| {
|
||||||
|
let worktree_store = workspace.project().read(cx).worktree_store();
|
||||||
cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
|
JujutsuStore::init_global(cx, worktree_store);
|
||||||
bookmark_picker::register(workspace);
|
bookmark_picker::register(workspace);
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue