1use crate::api::{create_router, AppState};
2use crate::watcher::FileWatcher;
3use gitent_core::{Session, Storage};
4use std::net::SocketAddr;
5use std::path::PathBuf;
6use std::sync::{Arc, Mutex};
7use tracing::info;
8
9pub struct GitentServer {
10 session: Session,
11 storage: Arc<Mutex<Storage>>,
12 _watcher: FileWatcher,
13}
14
15impl GitentServer {
16 pub fn new(root_path: PathBuf, db_path: PathBuf) -> anyhow::Result<Self> {
17 let session = Session::new(root_path);
18 let storage = Arc::new(Mutex::new(Storage::new(db_path)?));
19
20 {
21 let storage_guard = storage.lock().unwrap();
22 storage_guard.create_session(&session)?;
23 }
24
25 let watcher = FileWatcher::new(&session, Arc::clone(&storage))?;
26
27 Ok(Self {
28 session,
29 storage,
30 _watcher: watcher,
31 })
32 }
33
34 pub async fn serve(self, addr: SocketAddr) -> anyhow::Result<()> {
35 let state = AppState {
36 storage: self.storage,
37 };
38
39 let app = create_router(state);
40
41 info!("Server listening on {}", addr);
42 info!("Session ID: {}", self.session.id);
43 info!("Watching: {:?}", self.session.root_path);
44
45 let listener = tokio::net::TcpListener::bind(addr).await?;
46 axum::serve(listener, app).await?;
47
48 Ok(())
49 }
50
51 pub fn session_id(&self) -> uuid::Uuid {
52 self.session.id
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use tempfile::TempDir;
60
61 #[tokio::test]
62 async fn test_server_creation() {
63 let temp_dir = TempDir::new().unwrap();
64 let db_dir = TempDir::new().unwrap();
65
66 let db_path = db_dir.path().join("test.db");
67 let server = GitentServer::new(temp_dir.path().to_path_buf(), db_path);
68
69 assert!(server.is_ok());
70 }
71}