1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use wsb::prelude::*;
use tokio::sync::{broadcast, RwLock};
use super::handlers::fleet::RepoDetailedStatus;
use super::handlers::worktree::WorktreeChangedEvent;
use super::ops::OpsRegistry;
use wsb::persist::global::models::PlaceFilter;
use wsb::persist::global::{DatabaseService, SessionRepo, WsbRepos};
/// Fired when a file in the worktree is created, modified, or deleted on disk.
/// The `path` is worktree-relative (e.g. `"capdag/src/main.rs"`).
/// `mtime_secs` is the Unix timestamp of the file's new mtime, or `None` if deleted.
#[derive(Clone, Debug, serde::Serialize)]
pub struct FileChangedEvent {
pub path: String,
pub mtime_secs: Option<u64>,
}
#[derive(Clone)]
pub struct WebState {
pub db: Arc<WsbRepos>,
pub db_service: Arc<DatabaseService>,
/// The machine's sessions — one store, shared by every worktree — and
/// which of them ran in this worktree: none outside `$PRJ`, where no
/// session is placed.
pub sessions: Arc<SessionRepo>,
pub place: Option<PlaceFilter>,
pub worktree_root: PathBuf,
/// What the workshop's database names this worktree by
/// ([`wsb::local_state::LocalState::key`]).
pub worktree_key: String,
/// The address the workbench is bound to. Reported by the settings page,
/// which must state where this daemon actually listens rather than a
/// remembered preference that may never have been applied.
pub listen: std::net::IpAddr,
pub port: u16,
pub git_status_tx: broadcast::Sender<RepoDetailedStatus>,
pub git_status_snapshot: Arc<RwLock<HashMap<String, RepoDetailedStatus>>>,
pub git_focus_tx: broadcast::Sender<String>,
pub git_nudge_tx: broadcast::Sender<Option<String>>,
pub ops: OpsRegistry,
/// Broadcast channel for worktree file change events.
pub file_changed_tx: broadcast::Sender<FileChangedEvent>,
/// Broadcast channel for worktree tree change events: which listings the
/// explorer must re-read, and which repository's subtree moved with them.
pub worktree_changed_tx: broadcast::Sender<WorktreeChangedEvent>,
/// The machine's GitHub mirror, shared by every worktree this daemon
/// serves, or why there is none. Its change broadcast is how a page learns
/// that what it shows is no longer what is held.
pub github: Result<Arc<super::github::GitHub>, String>,
/// The editor's code intelligence: omnicode's language servers, per analysis root.
pub code: Arc<crate::code::CodeIntel>,
}
impl WebState {
pub async fn new(
db: Arc<WsbRepos>,
db_service: Arc<DatabaseService>,
sessions: Arc<SessionRepo>,
place: Option<PlaceFilter>,
worktree_root: PathBuf,
worktree_key: String,
listen: std::net::IpAddr,
port: u16,
github: Result<Arc<super::github::GitHub>, String>,
) -> Result<Self> {
let (git_status_tx, _) = broadcast::channel(64);
let (git_focus_tx, _) = broadcast::channel(16);
let (git_nudge_tx, _) = broadcast::channel::<Option<String>>(64);
let (file_changed_tx, _) = broadcast::channel(256);
let (worktree_changed_tx, _) = broadcast::channel::<WorktreeChangedEvent>(64);
let logs_root = wsb::logs::root(&worktree_root)?;
let code = crate::code::CodeIntel::new(&worktree_root).map_err(|e| anyhow::anyhow!(e))?;
Ok(Self {
db,
db_service,
sessions,
place,
worktree_root,
worktree_key,
listen,
port,
git_status_tx,
git_status_snapshot: Arc::new(RwLock::new(HashMap::new())),
git_focus_tx,
git_nudge_tx,
// Command lines write their operation logs under the worktree's
// logs root, and the registry reads them from there, so a run's
// output outlives the ring buffer's capacity and this process.
ops: OpsRegistry::with_logs(logs_root),
file_changed_tx,
worktree_changed_tx,
github,
code,
})
}
}